[libcamera-devel,RFC,v2,3/5] libcamera: ipa_manager: implement class for managing IPA modules

Message ID 20190523164210.2105-4-paul.elder@ideasonboard.com
State Accepted
Headers show
Series
  • Add IPAManager
Related show

Commit Message

Paul Elder May 23, 2019, 4:42 p.m. UTC
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 pipelines to aquire an IPA.

Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
---
Changes in v2:
- made IPAManager into a real singleton (as opposed to my misunderstood
  version)
- return non-const IPAModule from IPAManager::acquireIPA()
- made return value of addDir return the total number of modules loaded
  - that way the caller can know if any modules were loaded at all
    (since zero modules loaded doesn't really constitute as an error)

 src/libcamera/include/ipa_manager.h |  39 +++++++++
 src/libcamera/ipa_manager.cpp       | 122 ++++++++++++++++++++++++++++
 src/libcamera/meson.build           |   2 +
 3 files changed, 163 insertions(+)
 create mode 100644 src/libcamera/include/ipa_manager.h
 create mode 100644 src/libcamera/ipa_manager.cpp

Patch

diff --git a/src/libcamera/include/ipa_manager.h b/src/libcamera/include/ipa_manager.h
new file mode 100644
index 0000000..333fec0
--- /dev/null
+++ b/src/libcamera/include/ipa_manager.h
@@ -0,0 +1,39 @@ 
+/* 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 <libcamera/ipa/ipa_module_info.h>
+#include <list>
+#include <string>
+
+#include "ipa_module.h"
+#include "pipeline_handler.h"
+
+namespace libcamera {
+
+class IPAManager
+{
+public:
+	static IPAManager *instance();
+
+	int addDir(const std::string &libDir);
+
+	IPAModule *acquireIPA(const struct IPAModuleInfo &info) const;
+
+private:
+	std::list<IPAModule *> modules_;
+
+	IPAManager();
+	~IPAManager();
+
+	bool match(const IPAModule *ipa, const struct IPAModuleInfo &info) const;
+};
+
+} /* 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 0000000..3d65786
--- /dev/null
+++ b/src/libcamera/ipa_manager.cpp
@@ -0,0 +1,122 @@ 
+/* 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 "ipa_module.h"
+#include "pipeline_handler.h"
+#include "utils.h"
+
+#include <dirent.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "log.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()
+{
+}
+
+IPAManager::~IPAManager()
+{
+}
+
+/**
+ * \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
+ *
+ * Goes through \a libDir and tries to create an IPAModule instance for every
+ * found shared object. Skips invalid IPA modules.
+ *
+ * \return total number of modules loaded (including modules loaded in
+ * previous calls of this function), or negative error code
+ */
+int IPAManager::addDir(const std::string &libDir)
+{
+	struct dirent *ent;
+	DIR *dir;
+
+	dir = opendir(libDir.c_str());
+	if (!dir) {
+		int ret = -errno;
+		LOG(IPAManager, Error) << "Invalid path for IPA modules: "
+				       << strerror(ret);
+		return ret;
+	}
+
+	while ((ent = readdir(dir)) != nullptr) {
+		int offset = strlen(ent->d_name) - 3;
+		if (strncmp(&ent->d_name[offset], ".so", 3))
+			continue;
+
+		IPAModule *ipaModule = new IPAModule(libDir + "/" + ent->d_name);
+		if (ipaModule->isValid())
+			modules_.push_back(ipaModule);
+	}
+
+	closedir(dir);
+	return modules_.size();
+}
+
+/**
+ * \brief Retrieve an IPA module that matches a desired IPA module info
+ *
+ * \return IPA module
+ */
+IPAModule *IPAManager::acquireIPA(const struct IPAModuleInfo &info) const
+{
+	IPAModule *m = nullptr;
+
+	for (IPAModule *module : modules_) {
+		if (module->isAcquired())
+			continue;
+
+		if (match(module, info) && module->acquire()) {
+			m = module;
+			break;
+		}
+	}
+
+	return m;
+}
+
+bool IPAManager::match(const IPAModule *ipa, const struct IPAModuleInfo &info) const
+{
+	return ipa->info().ipaAPIVersion == info.ipaAPIVersion &&
+	       ipa->info().pipelineVersion >= info.pipelineVersion &&
+	       !strcmp(ipa->info().pipelineName, info.pipelineName);
+}
+
+} /* namespace libcamera */
diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
index e5b48f2..ee1b658 100644
--- a/src/libcamera/meson.build
+++ b/src/libcamera/meson.build
@@ -10,6 +10,7 @@  libcamera_sources = files([
     'event_notifier.cpp',
     'formats.cpp',
     'geometry.cpp',
+    'ipa_manager.cpp',
     'ipa_module.cpp',
     'log.cpp',
     'media_device.cpp',
@@ -32,6 +33,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',