From patchwork Wed Jun 5 00:53:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 1355 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DCC226472A for ; Wed, 5 Jun 2019 02:53:32 +0200 (CEST) Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 36358321; Wed, 5 Jun 2019 02:53:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1559696012; bh=uKAEFI4mBSLI5wq4nHzo2wU6t3yS0PtFIQyUZY05y8Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fZkTHM0lrPF7jFb39ou39Hup9ioN2ptfCYOUWq7ZOMk6NM98DEbFXEvZY4bs4u8Tu msVRMiVevr4+1Rld2lJeJV0Mj22ahRSBE1v+3+wd+z7E30J+FBmqkoVc9NdJ+t3OlT gg6OUvXOLE1Jg9Yd41/YJjXzp2ba6OVWd/xdN1l4= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Tue, 4 Jun 2019 20:53:13 -0400 Message-Id: <20190605005316.4835-8-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190605005316.4835-1-paul.elder@ideasonboard.com> References: <20190605005316.4835-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 07/10] libcamera: ipa_manager: implement class for managing IPA modules X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 05 Jun 2019 00:53:33 -0000 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 Reviewed-by: Laurent Pinchart --- Changes in v3: - createIPA() now inputs an acceptable version range to find an IPAModule, as opposed to taking the version of the input pipeline handler - fix strtok (and C++ize it) - rename environment variable from IPA_MODULE_PATH to LIBCAMERA_IPA_MODULE_PATH Changes in v2: - make addDir private, and called from constructor - add hard-coded IPA modules path from meson - read environment variable for additional IPA module paths - move match to IPAModule - make addDir return value more sensible - add the build IPA directory to the IPA module path for all tests src/ipa/meson.build | 2 + src/libcamera/include/ipa_manager.h | 40 ++++++++ src/libcamera/ipa_manager.cpp | 149 ++++++++++++++++++++++++++++ src/libcamera/meson.build | 2 + src/meson.build | 1 + test/libtest/test.cpp | 6 ++ 6 files changed, 200 insertions(+) create mode 100644 src/ipa/meson.build create mode 100644 src/libcamera/include/ipa_manager.h create mode 100644 src/libcamera/ipa_manager.cpp diff --git a/src/ipa/meson.build b/src/ipa/meson.build new file mode 100644 index 0000000..be4f954 --- /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 0000000..310ce7c --- /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 + +#include +#include + +#include "ipa_module.h" +#include "pipeline_handler.h" + +namespace libcamera { + +class IPAManager +{ +public: + static IPAManager *instance(); + + std::unique_ptr createIPA(PipelineHandler *pipe, + uint32_t maxVersion, + uint32_t minVersion); + +private: + std::vector 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 0000000..f689aa6 --- /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 +#include +#include + +#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 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 32f7da4..0889b0d 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 4e41fd3..628e7a7 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 9d537ea..b119cf1 100644 --- a/test/libtest/test.cpp +++ b/test/libtest/test.cpp @@ -5,6 +5,8 @@ * test.cpp - libcamera test base class */ +#include + #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;