From patchwork Mon May 27 22:35:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 1322 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9427C618F8 for ; Tue, 28 May 2019 00:35:50 +0200 (CEST) Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D01E3D85; Tue, 28 May 2019 00:35:49 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1558996550; bh=7czLoM6h4CXiFdcVKIGsV6OgYRIV/mBVwKekKrgqENQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oHmMQOw3k0UT4HXoCUlPQoOWhbamLdcIGE7bS6/hL6H2c5rFtqbFe4U9rjIj82Cu+ ycbG0S4KFaJTVJxqn+eRzr57knB/9dhCfWjozqtG+BQm6eWhkBJzhDteGT4tc9ydjY H36IsSYOP/manM86hp9Rl7vunFcjmJkTMM8pvLMw= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Mon, 27 May 2019 18:35:36 -0400 Message-Id: <20190527223540.21855-5-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190527223540.21855-1-paul.elder@ideasonboard.com> References: <20190527223540.21855-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 4/8] libcamera: ipa_module: allow instantiation of IPAInterface 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: Mon, 27 May 2019 22:35:51 -0000 Add functions for loading the IPAInterface factory function from an IPA module shared object, and for creating an instance of an IPAInterface. These functions will be used by IPAManager, from which a PipelineHandler will request an IPAInterface. Also update meson to add the "-ldl" linker argument, to allow loading of the factory function from a shared object. Signed-off-by: Paul Elder --- src/libcamera/include/ipa_module.h | 15 +++++- src/libcamera/ipa_module.cpp | 80 ++++++++++++++++++++++++++++-- src/libcamera/meson.build | 3 +- 3 files changed, 92 insertions(+), 6 deletions(-) diff --git a/src/libcamera/include/ipa_module.h b/src/libcamera/include/ipa_module.h index a4c6dbd..bb03407 100644 --- a/src/libcamera/include/ipa_module.h +++ b/src/libcamera/include/ipa_module.h @@ -7,9 +7,10 @@ #ifndef __LIBCAMERA_IPA_MODULE_H__ #define __LIBCAMERA_IPA_MODULE_H__ -#include - +#include #include +#include +#include namespace libcamera { @@ -17,16 +18,26 @@ class IPAModule { public: explicit IPAModule(const std::string &libPath); + ~IPAModule(); bool isValid() const; const struct IPAModuleInfo &info() const; + bool load(); + + std::unique_ptr createInstance(); + private: struct IPAModuleInfo info_; std::string libPath_; bool valid_; + bool loaded_; + + void *dlhandle_; + typedef IPAInterface *(*ipaiFactory)(void); + ipaiFactory ipaCreate_; int loadIPAModuleInfo(); }; diff --git a/src/libcamera/ipa_module.cpp b/src/libcamera/ipa_module.cpp index 6e68934..9bb0594 100644 --- a/src/libcamera/ipa_module.cpp +++ b/src/libcamera/ipa_module.cpp @@ -7,6 +7,7 @@ #include "ipa_module.h" +#include #include #include #include @@ -242,13 +243,11 @@ int elfLoadSymbol(void *dst, size_t size, void *map, size_t soSize, * The IPA module shared object file must be of the same endianness and * bitness as libcamera. * - * \todo load funtions from the IPA to be used by pipelines - * * The caller shall call the isValid() method after constructing an * IPAModule instance to verify the validity of the IPAModule. */ IPAModule::IPAModule(const std::string &libPath) - : libPath_(libPath), valid_(false) + : libPath_(libPath), valid_(false), loaded_(false) { if (loadIPAModuleInfo() < 0) return; @@ -256,6 +255,12 @@ IPAModule::IPAModule(const std::string &libPath) valid_ = true; } +IPAModule::~IPAModule() +{ + if (dlhandle_) + dlclose(dlhandle_); +} + int IPAModule::loadIPAModuleInfo() { int fd = open(libPath_.c_str(), O_RDONLY); @@ -325,4 +330,73 @@ const struct IPAModuleInfo &IPAModule::info() const return info_; } +/** + * \brief Load the IPA implementation factory from the shared object + * + * The IPA module shared object implements an IPAInterface class to be used + * by pipeline handlers. This function loads the factory function from the + * shared object. Later, createInstance() can be called to instantiate the + * IPAInterface. + * + * This function only needs to be called successfully once, after which + * createInstance can be called as many times as IPAInterface instances are + * needed. + * + * Calling this function on an invalid module (as returned by isValid()) is + * an error. + * + * \return true if load was successful, or already loaded, and false otherwise + */ +bool IPAModule::load() +{ + if (!valid_) + return false; + + if (loaded_) + return true; + + dlhandle_ = dlopen(libPath_.c_str(), RTLD_LAZY); + if (!dlhandle_) { + LOG(IPAModule, Error) << "Failed to open IPA module shared object" + << dlerror(); + return false; + } + + void *symbol = dlsym(dlhandle_, "ipaCreate"); + if (!symbol) { + LOG(IPAModule, Error) << "Failed to load ipaCreate() from IPA module shared object" + << dlerror(); + dlclose(dlhandle_); + return false; + } + + ipaCreate_ = (ipaiFactory)symbol; + + loaded_ = true; + + return true; +} + +/** + * \brief Instantiate an IPAInterface + * + * After the IPAInterface implementation factory has been loaded (with load()), + * an instance can be created with this function. + * + * Calling this function on a module that has not yet been loaded, or an + * invalid module (as returned by load() and isValid(), respectively) is + * an error. + * + * \return the IPA implementation as a new IPAInterface instance + */ +std::unique_ptr IPAModule::createInstance() +{ + if (!valid_ || !loaded_) + return nullptr; + + std::unique_ptr ipai(ipaCreate_()); + + return ipai; +} + } /* namespace libcamera */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 07335e5..32f7da4 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -65,7 +65,8 @@ libcamera = shared_library('camera', libcamera_sources, install : true, include_directories : includes, - dependencies : libudev) + dependencies : libudev, + link_args : '-ldl') libcamera_dep = declare_dependency(sources : [libcamera_api, libcamera_h], include_directories : libcamera_includes,