[RFC,1/7] libcamera: ipa_manager: Factor out .so file searching
diff mbox series

Message ID 20250626095944.1746345-2-paul.elder@ideasonboard.com
State New
Headers show
Series
  • Add Layers support
Related show

Commit Message

Paul Elder June 26, 2025, 9:59 a.m. UTC
In the near future we will add support for layers/shoes on top of
libcamera, which will need to search for shared object files similar to
how IPAManager does. To avoid code duplication, move this code out of
IPAManager into internal utils.

Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
---
 include/libcamera/internal/ipa_manager.h |   4 -
 include/libcamera/internal/meson.build   |   1 +
 include/libcamera/internal/utils.h       |  26 ++++++
 src/libcamera/ipa_manager.cpp            | 108 ++++-------------------
 src/libcamera/meson.build                |   1 +
 src/libcamera/utils.cpp                  | 107 ++++++++++++++++++++++
 6 files changed, 154 insertions(+), 93 deletions(-)
 create mode 100644 include/libcamera/internal/utils.h
 create mode 100644 src/libcamera/utils.cpp

Patch
diff mbox series

diff --git a/include/libcamera/internal/ipa_manager.h b/include/libcamera/internal/ipa_manager.h
index a0d448cf9862..6b0ba4b5477f 100644
--- a/include/libcamera/internal/ipa_manager.h
+++ b/include/libcamera/internal/ipa_manager.h
@@ -59,10 +59,6 @@  public:
 #endif
 
 private:
-	void parseDir(const char *libDir, unsigned int maxDepth,
-		      std::vector<std::string> &files);
-	unsigned int addDir(const char *libDir, unsigned int maxDepth = 0);
-
 	IPAModule *module(PipelineHandler *pipe, uint32_t minVersion,
 			  uint32_t maxVersion);
 
diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build
index 5c80a28c4cbe..690f5c5ec9f6 100644
--- a/include/libcamera/internal/meson.build
+++ b/include/libcamera/internal/meson.build
@@ -41,6 +41,7 @@  libcamera_internal_headers = files([
     'shared_mem_object.h',
     'source_paths.h',
     'sysfs.h',
+    'utils.h',
     'v4l2_device.h',
     'v4l2_pixelformat.h',
     'v4l2_subdevice.h',
diff --git a/include/libcamera/internal/utils.h b/include/libcamera/internal/utils.h
new file mode 100644
index 000000000000..742657bebb28
--- /dev/null
+++ b/include/libcamera/internal/utils.h
@@ -0,0 +1,26 @@ 
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2018, Google Inc.
+ *
+ * Miscellaneous utility functions
+ */
+
+#pragma once
+
+#include <functional>
+#include <string>
+#include <vector>
+
+namespace libcamera {
+
+namespace utils {
+
+void parseDir(const char *libDir, unsigned int maxDepth,
+	      std::vector<std::string> &files);
+
+unsigned int addDir(const char *libDir, unsigned int maxDepth,
+		    std::function<int(const std::string &)> func);
+
+} /* namespace utils */
+
+} /* namespace libcamera */
diff --git a/src/libcamera/ipa_manager.cpp b/src/libcamera/ipa_manager.cpp
index 830750dcc0fb..ecad4845a077 100644
--- a/src/libcamera/ipa_manager.cpp
+++ b/src/libcamera/ipa_manager.cpp
@@ -8,9 +8,8 @@ 
 #include "libcamera/internal/ipa_manager.h"
 
 #include <algorithm>
-#include <dirent.h>
+#include <functional>
 #include <string.h>
-#include <sys/types.h>
 
 #include <libcamera/base/file.h>
 #include <libcamera/base/log.h>
@@ -19,6 +18,7 @@ 
 #include "libcamera/internal/ipa_module.h"
 #include "libcamera/internal/ipa_proxy.h"
 #include "libcamera/internal/pipeline_handler.h"
+#include "libcamera/internal/utils.h"
 
 /**
  * \file ipa_manager.h
@@ -110,6 +110,20 @@  IPAManager::IPAManager()
 
 	unsigned int ipaCount = 0;
 
+	auto &modules = modules_;
+	std::function<int(const std::string &)> addDirHandler =
+	[&modules](const std::string &file) {
+		auto ipaModule = std::make_unique<IPAModule>(file);
+		if (!ipaModule->isValid())
+			return 0;
+
+		LOG(IPAManager, Debug) << "Loaded IPA module '" << file << "'";
+
+		modules.push_back(std::move(ipaModule));
+
+		return 1;
+	};
+
 	/* User-specified paths take precedence. */
 	const char *modulePaths = utils::secure_getenv("LIBCAMERA_IPA_MODULE_PATH");
 	if (modulePaths) {
@@ -117,7 +131,7 @@  IPAManager::IPAManager()
 			if (dir.empty())
 				continue;
 
-			ipaCount += addDir(dir.c_str());
+			ipaCount += utils::addDir(dir.c_str(), 0, addDirHandler);
 		}
 
 		if (!ipaCount)
@@ -138,11 +152,11 @@  IPAManager::IPAManager()
 			<< "libcamera is not installed. Adding '"
 			<< ipaBuildPath << "' to the IPA search path";
 
-		ipaCount += addDir(ipaBuildPath.c_str(), maxDepth);
+		ipaCount += utils::addDir(ipaBuildPath.c_str(), maxDepth, addDirHandler);
 	}
 
 	/* Finally try to load IPAs from the installed system path. */
-	ipaCount += addDir(IPA_MODULE_DIR);
+	ipaCount += utils::addDir(IPA_MODULE_DIR, 0, addDirHandler);
 
 	if (!ipaCount)
 		LOG(IPAManager, Warning)
@@ -151,90 +165,6 @@  IPAManager::IPAManager()
 
 IPAManager::~IPAManager() = default;
 
-/**
- * \brief Identify shared library objects within a directory
- * \param[in] libDir The directory to search for shared objects
- * \param[in] maxDepth The maximum depth of sub-directories to parse
- * \param[out] files A vector of paths to shared object library files
- *
- * Search a directory for .so files, allowing recursion down to sub-directories
- * no further than the depth specified by \a maxDepth.
- *
- * Discovered shared objects are added to the \a files vector.
- */
-void IPAManager::parseDir(const char *libDir, unsigned int maxDepth,
-			  std::vector<std::string> &files)
-{
-	struct dirent *ent;
-	DIR *dir;
-
-	dir = opendir(libDir);
-	if (!dir)
-		return;
-
-	while ((ent = readdir(dir)) != nullptr) {
-		if (ent->d_type == DT_DIR && maxDepth) {
-			if (strcmp(ent->d_name, ".") == 0 ||
-			    strcmp(ent->d_name, "..") == 0)
-				continue;
-
-			std::string subdir = std::string(libDir) + "/" + ent->d_name;
-
-			/* Recursion is limited to maxDepth. */
-			parseDir(subdir.c_str(), maxDepth - 1, files);
-
-			continue;
-		}
-
-		int offset = strlen(ent->d_name) - 3;
-		if (offset < 0)
-			continue;
-		if (strcmp(&ent->d_name[offset], ".so"))
-			continue;
-
-		files.push_back(std::string(libDir) + "/" + ent->d_name);
-	}
-
-	closedir(dir);
-}
-
-/**
- * \brief Load IPA modules from a directory
- * \param[in] libDir The directory to search for IPA modules
- * \param[in] maxDepth The maximum depth of sub-directories to search
- *
- * This function tries to create an IPAModule instance for every shared object
- * found in \a libDir, and skips invalid IPA modules.
- *
- * Sub-directories are searched up to a depth of \a maxDepth. A \a maxDepth
- * value of 0 only searches the directory specified in \a libDir.
- *
- * \return Number of modules loaded by this call
- */
-unsigned int IPAManager::addDir(const char *libDir, unsigned int maxDepth)
-{
-	std::vector<std::string> files;
-
-	parseDir(libDir, maxDepth, files);
-
-	/* Ensure a stable ordering of modules. */
-	std::sort(files.begin(), files.end());
-
-	unsigned int count = 0;
-	for (const std::string &file : files) {
-		auto ipaModule = std::make_unique<IPAModule>(file);
-		if (!ipaModule->isValid())
-			continue;
-
-		LOG(IPAManager, Debug) << "Loaded IPA module '" << file << "'";
-
-		modules_.push_back(std::move(ipaModule));
-		count++;
-	}
-
-	return count;
-}
-
 /**
  * \brief Retrieve an IPA module that matches a given pipeline handler
  * \param[in] pipe The pipeline handler
diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
index 28a3b0f36d53..8e2aa921a620 100644
--- a/src/libcamera/meson.build
+++ b/src/libcamera/meson.build
@@ -51,6 +51,7 @@  libcamera_internal_sources = files([
     'shared_mem_object.cpp',
     'source_paths.cpp',
     'sysfs.cpp',
+    'utils.cpp',
     'v4l2_device.cpp',
     'v4l2_pixelformat.cpp',
     'v4l2_subdevice.cpp',
diff --git a/src/libcamera/utils.cpp b/src/libcamera/utils.cpp
new file mode 100644
index 000000000000..ef046ac3134e
--- /dev/null
+++ b/src/libcamera/utils.cpp
@@ -0,0 +1,107 @@ 
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2019, Google Inc.
+ *
+ * Miscellaneous utility functions (internal)
+ */
+
+#include "libcamera/internal/utils.h"
+
+#include <algorithm>
+#include <dirent.h>
+#include <functional>
+#include <string.h>
+#include <string>
+#include <sys/types.h>
+#include <vector>
+
+/**
+ * \file internal/utils.h
+ * \brief Miscellaneous utility functions (internal)
+ */
+
+namespace libcamera {
+
+namespace utils {
+
+/**
+ * \brief Identify shared library objects within a directory
+ * \param[in] libDir The directory to search for shared objects
+ * \param[in] maxDepth The maximum depth of sub-directories to parse
+ * \param[out] files A vector of paths to shared object library files
+ *
+ * Search a directory for .so files, allowing recursion down to sub-directories
+ * no further than the depth specified by \a maxDepth.
+ *
+ * Discovered shared objects are added to the \a files vector.
+ */
+void parseDir(const char *libDir, unsigned int maxDepth,
+	      std::vector<std::string> &files)
+{
+	struct dirent *ent;
+	DIR *dir;
+
+	dir = opendir(libDir);
+	if (!dir)
+		return;
+
+	while ((ent = readdir(dir)) != nullptr) {
+		if (ent->d_type == DT_DIR && maxDepth) {
+			if (strcmp(ent->d_name, ".") == 0 ||
+			    strcmp(ent->d_name, "..") == 0)
+				continue;
+
+			std::string subdir = std::string(libDir) + "/" + ent->d_name;
+
+			/* Recursion is limited to maxDepth. */
+			parseDir(subdir.c_str(), maxDepth - 1, files);
+
+			continue;
+		}
+
+		int offset = strlen(ent->d_name) - 3;
+		if (offset < 0)
+			continue;
+		if (strcmp(&ent->d_name[offset], ".so"))
+			continue;
+
+		files.push_back(std::string(libDir) + "/" + ent->d_name);
+	}
+
+	closedir(dir);
+}
+
+/**
+ * \brief Execute some function on shared object files from a directory
+ * \param[in] libDir The directory to search for shared objects
+ * \param[in] maxDepth The maximum depth of sub-directories to search
+ * \param[in] func The function to execute on every shared object
+ *
+ * This function tries to execute the given function \a func for every shared
+ * object found in \a libDir.
+ *
+ * Sub-directories are searched up to a depth of \a maxDepth. A \a maxDepth
+ * value of 0 only searches the directory specified in \a libDir.
+ *
+ * \return Number of shared objects loaded by this call
+ */
+unsigned int addDir(const char *libDir, unsigned int maxDepth,
+		    std::function<int(const std::string &)> func)
+{
+	std::vector<std::string> files;
+
+	parseDir(libDir, maxDepth, files);
+
+	/* Ensure a stable ordering of modules. */
+	std::sort(files.begin(), files.end());
+
+	unsigned int count = 0;
+	for (const std::string &file : files)
+		count += func(file);
+
+	return count;
+}
+
+} /* namespace utils */
+
+} /* namespace libcamera */