summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Elder <paul.elder@ideasonboard.com>2019-06-03 13:19:44 -0400
committerPaul Elder <paul.elder@ideasonboard.com>2019-06-05 10:44:52 -0400
commit7fa98a4cdd296c86fe053ab17486c1e0e2a72e90 (patch)
treed038f64587b41f02f9ec928a6181ec72589b5b97
parent42c9b4bad40b462ef267b477e136202f02071137 (diff)
libcamera: ipa_manager: implement class for managing IPA modules
IPAManager is a class that will search in given directories for IPA modules, and will load them into a list. It also provides an interface for pipeline handlers to acquire an IPA. A meson build file for the IPAs is added, which also specifies a hard-coded path for where to load the IPAs from in the installation directory. More paths can be specified with the environment variable LIBCAMERA_IPA_MODULE_PATH, with the same syntax as the regular PATH environment variable. Make the test framework set this environment variable. Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--src/ipa/meson.build2
-rw-r--r--src/libcamera/include/ipa_manager.h40
-rw-r--r--src/libcamera/ipa_manager.cpp149
-rw-r--r--src/libcamera/meson.build2
-rw-r--r--src/meson.build1
-rw-r--r--test/libtest/test.cpp6
6 files changed, 200 insertions, 0 deletions
diff --git a/src/ipa/meson.build b/src/ipa/meson.build
new file mode 100644
index 00000000..be4f9547
--- /dev/null
+++ b/src/ipa/meson.build
@@ -0,0 +1,2 @@
+config_h.set('IPA_MODULE_DIR',
+ '"' + join_paths(get_option('prefix'), get_option('libdir'), 'libcamera') + '"')
diff --git a/src/libcamera/include/ipa_manager.h b/src/libcamera/include/ipa_manager.h
new file mode 100644
index 00000000..310ce7c8
--- /dev/null
+++ b/src/libcamera/include/ipa_manager.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * ipa_manager.h - Image Processing Algorithm module manager
+ */
+#ifndef __LIBCAMERA_IPA_MANAGER_H__
+#define __LIBCAMERA_IPA_MANAGER_H__
+
+#include <vector>
+
+#include <libcamera/ipa/ipa_interface.h>
+#include <libcamera/ipa/ipa_module_info.h>
+
+#include "ipa_module.h"
+#include "pipeline_handler.h"
+
+namespace libcamera {
+
+class IPAManager
+{
+public:
+ static IPAManager *instance();
+
+ std::unique_ptr<IPAInterface> createIPA(PipelineHandler *pipe,
+ uint32_t maxVersion,
+ uint32_t minVersion);
+
+private:
+ std::vector<IPAModule *> modules_;
+
+ IPAManager();
+ ~IPAManager();
+
+ int addDir(const char *libDir);
+};
+
+} /* namespace libcamera */
+
+#endif /* __LIBCAMERA_IPA_MANAGER_H__ */
diff --git a/src/libcamera/ipa_manager.cpp b/src/libcamera/ipa_manager.cpp
new file mode 100644
index 00000000..f689aa69
--- /dev/null
+++ b/src/libcamera/ipa_manager.cpp
@@ -0,0 +1,149 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * ipa_manager.cpp - Image Processing Algorithm module manager
+ */
+
+#include "ipa_manager.h"
+
+#include <dirent.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "ipa_module.h"
+#include "log.h"
+#include "pipeline_handler.h"
+#include "utils.h"
+
+/**
+ * \file ipa_manager.h
+ * \brief Image Processing Algorithm module manager
+ */
+
+namespace libcamera {
+
+LOG_DEFINE_CATEGORY(IPAManager)
+
+/**
+ * \class IPAManager
+ * \brief Manager for IPA modules
+ */
+
+IPAManager::IPAManager()
+{
+ addDir(IPA_MODULE_DIR);
+
+ std::string modulePaths = utils::secure_getenv("LIBCAMERA_IPA_MODULE_PATH");
+ if (modulePaths.empty())
+ return;
+
+ for (size_t pos = 0, delim = 0; delim != std::string::npos;
+ pos = delim + 1) {
+ delim = modulePaths.find(':', pos);
+ size_t count = delim == std::string::npos ? delim : delim - pos;
+ std::string path = modulePaths.substr(pos, count);
+ if (path.empty())
+ continue;
+
+ addDir(path.c_str());
+ }
+}
+
+IPAManager::~IPAManager()
+{
+ for (IPAModule *module : modules_)
+ delete module;
+}
+
+/**
+ * \brief Retrieve the IPA manager instance
+ *
+ * The IPAManager is a singleton and can't be constructed manually. This
+ * function shall instead be used to retrieve the single global instance of the
+ * manager.
+ *
+ * \return The IPA manager instance
+ */
+IPAManager *IPAManager::instance()
+{
+ static IPAManager ipaManager;
+ return &ipaManager;
+}
+
+/**
+ * \brief Load IPA modules from a directory
+ * \param[in] libDir directory to search for IPA modules
+ *
+ * This method tries to create an IPAModule instance for every shared object
+ * found in \a libDir, and skips invalid IPA modules.
+ *
+ * \return Number of modules loaded by this call, or a negative error code
+ * otherwise
+ */
+int IPAManager::addDir(const char *libDir)
+{
+ struct dirent *ent;
+ DIR *dir;
+
+ dir = opendir(libDir);
+ if (!dir) {
+ int ret = -errno;
+ LOG(IPAManager, Error)
+ << "Invalid path " << libDir << " for IPA modules: "
+ << strerror(-ret);
+ return ret;
+ }
+
+ unsigned int count = 0;
+ while ((ent = readdir(dir)) != nullptr) {
+ int offset = strlen(ent->d_name) - 3;
+ if (offset < 0)
+ continue;
+ if (strcmp(&ent->d_name[offset], ".so"))
+ continue;
+
+ IPAModule *ipaModule = new IPAModule(std::string(libDir) +
+ "/" + ent->d_name);
+ if (!ipaModule->isValid()) {
+ delete ipaModule;
+ continue;
+ }
+
+ modules_.push_back(ipaModule);
+ count++;
+ }
+
+ closedir(dir);
+ return count;
+}
+
+/**
+ * \brief Create an IPA interface that matches a given pipeline handler
+ * \param[in] pipe The pipeline handler that wants a matching IPA interface
+ * \param[in] minVersion Minimum acceptable version of IPA module
+ * \param[in] maxVersion Maximum acceptable version of IPA module
+ *
+ * \return A newly created IPA interface, or nullptr if no matching
+ * IPA module is found
+ */
+std::unique_ptr<IPAInterface> IPAManager::createIPA(PipelineHandler *pipe,
+ uint32_t maxVersion,
+ uint32_t minVersion)
+{
+ IPAModule *m = nullptr;
+
+ for (IPAModule *module : modules_) {
+ if (module->match(pipe, minVersion, maxVersion)) {
+ m = module;
+ break;
+ }
+ }
+
+ if (!m || !m->load())
+ return nullptr;
+
+ return m->createInstance();
+}
+
+} /* namespace libcamera */
diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
index 32f7da4d..0889b0d3 100644
--- a/src/libcamera/meson.build
+++ b/src/libcamera/meson.build
@@ -11,6 +11,7 @@ libcamera_sources = files([
'formats.cpp',
'geometry.cpp',
'ipa_interface.cpp',
+ 'ipa_manager.cpp',
'ipa_module.cpp',
'log.cpp',
'media_device.cpp',
@@ -33,6 +34,7 @@ libcamera_headers = files([
'include/device_enumerator_udev.h',
'include/event_dispatcher_poll.h',
'include/formats.h',
+ 'include/ipa_manager.h',
'include/ipa_module.h',
'include/log.h',
'include/media_device.h',
diff --git a/src/meson.build b/src/meson.build
index 4e41fd3e..628e7a7f 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,3 +1,4 @@
subdir('libcamera')
+subdir('ipa')
subdir('cam')
subdir('qcam')
diff --git a/test/libtest/test.cpp b/test/libtest/test.cpp
index 9d537ea0..b119cf19 100644
--- a/test/libtest/test.cpp
+++ b/test/libtest/test.cpp
@@ -5,6 +5,8 @@
* test.cpp - libcamera test base class
*/
+#include <stdlib.h>
+
#include "test.h"
Test::Test()
@@ -19,6 +21,10 @@ int Test::execute()
{
int ret;
+ ret = setenv("LIBCAMERA_IPA_MODULE_PATH", "src/ipa", 1);
+ if (ret)
+ return errno;
+
ret = init();
if (ret)
return ret;