From patchwork Mon Jun 3 23:16:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 1338 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F3EB5618F7 for ; Tue, 4 Jun 2019 01:16:47 +0200 (CEST) Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id C7E4E530; Tue, 4 Jun 2019 01:16:46 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1559603807; bh=7IrbRSZZHfyJ2kt6IZiUrLbvK2ZkrHJbfZYAqsiuvrQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=awr3rsGR/uDMC2PByUrZuh8eg1FhDArxPcV38gs3BL/yeHoufxbP/TZxfizr580o6 DRmcYyjY/5DGdEv81/Xu9sDdzJYGX+jF9rcuBiP1Sf7xyoZehiFpeBfRRlNi/heCSd PfqahMG1c6WKVCo6Tw/2tE83BUyAj/DAUuB7s2yY= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Mon, 3 Jun 2019 19:16:28 -0400 Message-Id: <20190603231637.28554-2-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190603231637.28554-1-paul.elder@ideasonboard.com> References: <20190603231637.28554-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 01/10] libcamera: ipa_interface: add header 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, 03 Jun 2019 23:16:48 -0000 Define an IPAInterface class which will contain an IPA implementation. The methods that the IPAInterface exposes form the interface to the IPA implementation, hence the name. IPA module shared objects will implement this class. This also means that IPA module shared objects must be implemented in C++, so remove the C test IPA module. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- No change in v2 include/libcamera/ipa/ipa_interface.h | 22 ++++++++++++++++++++++ include/libcamera/meson.build | 1 + src/libcamera/ipa_interface.cpp | 27 +++++++++++++++++++++++++++ src/libcamera/meson.build | 1 + test/ipa/ipa_test.cpp | 2 -- test/ipa/meson.build | 1 - test/ipa/shared_test.c | 6 ------ 7 files changed, 51 insertions(+), 9 deletions(-) create mode 100644 include/libcamera/ipa/ipa_interface.h create mode 100644 src/libcamera/ipa_interface.cpp delete mode 100644 test/ipa/shared_test.c diff --git a/include/libcamera/ipa/ipa_interface.h b/include/libcamera/ipa/ipa_interface.h new file mode 100644 index 0000000..2c5eb1f --- /dev/null +++ b/include/libcamera/ipa/ipa_interface.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * ipa_interface.h - Image Processing Algorithm interface + */ +#ifndef __LIBCAMERA_IPA_INTERFACE_H__ +#define __LIBCAMERA_IPA_INTERFACE_H__ + +namespace libcamera { + +class IPAInterface +{ +public: + virtual ~IPAInterface() {} + + virtual int init() = 0; +}; + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_IPA_INTERFACE_H__ */ diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index 1fcf6b5..1b86fdc 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -5,6 +5,7 @@ libcamera_api = files([ 'event_dispatcher.h', 'event_notifier.h', 'geometry.h', + 'ipa/ipa_interface.h', 'ipa/ipa_module_info.h', 'object.h', 'request.h', diff --git a/src/libcamera/ipa_interface.cpp b/src/libcamera/ipa_interface.cpp new file mode 100644 index 0000000..9d30da2 --- /dev/null +++ b/src/libcamera/ipa_interface.cpp @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * ipa_interface.cpp - Image Processing Algorithm interface + */ + +#include + +/** + * \file ipa_interface.h + * \brief Image Processing Algorithm interface + */ + +namespace libcamera { + +/** + * \class IPAInterface + * \brief Interface for IPA implementation + */ + +/** + * \fn IPAInterface::init() + * \brief Initialise the IPAInterface + */ + +} /* namespace libcamera */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 6a73580..07335e5 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_interface.cpp', 'ipa_module.cpp', 'log.cpp', 'media_device.cpp', diff --git a/test/ipa/ipa_test.cpp b/test/ipa/ipa_test.cpp index 9861ee2..2dbc702 100644 --- a/test/ipa/ipa_test.cpp +++ b/test/ipa/ipa_test.cpp @@ -60,8 +60,6 @@ protected: 9001, }; - count += runTest("test/ipa/ipa-dummy-c.so", testInfo); - count += runTest("test/ipa/ipa-dummy-cpp.so", testInfo); if (count < 0) diff --git a/test/ipa/meson.build b/test/ipa/meson.build index ecde313..08ee95c 100644 --- a/test/ipa/meson.build +++ b/test/ipa/meson.build @@ -1,5 +1,4 @@ ipa_modules_sources = [ - ['ipa-dummy-c', 'shared_test.c'], ['ipa-dummy-cpp', 'shared_test.cpp'], ] diff --git a/test/ipa/shared_test.c b/test/ipa/shared_test.c deleted file mode 100644 index 87d182b..0000000 --- a/test/ipa/shared_test.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -const struct IPAModuleInfo ipaModuleInfo = { - .name = "It's over nine thousand!", - .version = 9001, -}; From patchwork Mon Jun 3 23:16:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 1339 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A8FAD618F8 for ; Tue, 4 Jun 2019 01:16:48 +0200 (CEST) Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id DCBC284; Tue, 4 Jun 2019 01:16:47 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1559603808; bh=QknrrpprZbcdknTfh2Oz/A3xoU4OyOrt6v+HLMq1JWM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hVyMkaX8GbG0sFddE4CPj1UWgAt6gkyc5SivJ8iXrevCkT4McAWE1MLZlnnk05JFT UYZhijepCxMjuXx5j9yvxUOO6gWoQc1z+0F/OYbkdApBeBzQaZRGbXVV9OlICgNeRO pUED9il3OA1C2Uc62DbS8jTGPmhp1T48r27kE76Q= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Mon, 3 Jun 2019 19:16:29 -0400 Message-Id: <20190603231637.28554-3-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190603231637.28554-1-paul.elder@ideasonboard.com> References: <20190603231637.28554-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 02/10] libcamera: pipeline: add name, major version, and minor version 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, 03 Jun 2019 23:16:49 -0000 In order to match an IPA module with a pipeline handler, the pipeline handler must have a name and a version. Add these to PipelineHandler as getters and attributes so that they can be automatically defined by REGISTER_PIPELINE_HANDLER. Also add a macro PIPELINE_HANDLER to create a single version number given a major and minor version pair. It is put in ipa_module_info.h because IPA modules will also need this macro. Signed-off-by: Paul Elder --- Changes in v2: - make the name and version getters into methods of the base PipelineHandler class, so that the specialized pipeline handlers no longer have to specify overriding - add PIPELINE_VERSION macro to create one version number from major and minor pair include/libcamera/ipa/ipa_module_info.h | 2 ++ src/libcamera/include/pipeline_handler.h | 14 ++++++++--- src/libcamera/ipa_module.cpp | 17 +++++++++++++ src/libcamera/pipeline/ipu3/ipu3.cpp | 13 +++++++--- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 14 +++++++---- src/libcamera/pipeline/uvcvideo.cpp | 11 +++++--- src/libcamera/pipeline/vimc.cpp | 12 ++++++--- src/libcamera/pipeline_handler.cpp | 32 ++++++++++++++++++++++-- 8 files changed, 93 insertions(+), 22 deletions(-) diff --git a/include/libcamera/ipa/ipa_module_info.h b/include/libcamera/ipa/ipa_module_info.h index 4e0d668..e5f2a7e 100644 --- a/include/libcamera/ipa/ipa_module_info.h +++ b/include/libcamera/ipa/ipa_module_info.h @@ -7,6 +7,8 @@ #ifndef __LIBCAMERA_IPA_MODULE_INFO_H__ #define __LIBCAMERA_IPA_MODULE_INFO_H__ +#define PIPELINE_VERSION(majorV, minorV) (majorV * 1000 + minorV) + #ifdef __cplusplus namespace libcamera { #endif diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h index 7da6df1..67971b3 100644 --- a/src/libcamera/include/pipeline_handler.h +++ b/src/libcamera/include/pipeline_handler.h @@ -50,7 +50,8 @@ private: class PipelineHandler : public std::enable_shared_from_this { public: - PipelineHandler(CameraManager *manager); + PipelineHandler(CameraManager *manager, const char *name, + uint32_t version); virtual ~PipelineHandler(); virtual bool match(DeviceEnumerator *enumerator) = 0; @@ -77,6 +78,9 @@ public: bool completeBuffer(Camera *camera, Request *request, Buffer *buffer); void completeRequest(Camera *camera, Request *request); + const char *name() const { return name_; } + uint32_t version() const { return version_; } + protected: void registerCamera(std::shared_ptr camera, std::unique_ptr data); @@ -86,6 +90,9 @@ protected: CameraManager *manager_; + const char *name_; + uint32_t version_; + private: void mediaDeviceDisconnected(MediaDevice *media); virtual void disconnect(); @@ -112,14 +119,15 @@ private: std::string name_; }; -#define REGISTER_PIPELINE_HANDLER(handler) \ +#define REGISTER_PIPELINE_HANDLER(handler, pipelineVersion) \ class handler##Factory final : public PipelineHandlerFactory \ { \ public: \ handler##Factory() : PipelineHandlerFactory(#handler) {} \ std::shared_ptr create(CameraManager *manager) \ { \ - return std::make_shared(manager); \ + return std::make_shared(manager, #handler, \ + pipelineVersion); \ } \ }; \ static handler##Factory global_##handler##Factory; diff --git a/src/libcamera/ipa_module.cpp b/src/libcamera/ipa_module.cpp index 86cbe71..db56415 100644 --- a/src/libcamera/ipa_module.cpp +++ b/src/libcamera/ipa_module.cpp @@ -169,6 +169,23 @@ int elfLoadSymbol(void *dst, size_t size, void *map, size_t soSize, } /* namespace */ +/** + * \def PIPELINE_VERSION + * \brief Convert a major and minor version pair to a single version number + * \param[in] majorV Major version + * \param[in] minorV Minor version + * + * This macro should be used by the pipeline handler and by the IPA module + * to declare the version of the pipeline handler, for matching purposes. + * + * The major version of the pipeline handler should be updated whenever a + * change is made that causes currently compatible IPA modules to no longer + * be compatible, or if there is an API change between the pipeline handler + * and IPA modules. The minor version should be updated whenever a change is + * made that causes currently compatible IPA modules to no longer be compatible, + * but future IPA versions will still be compatible. + */ + /** * \struct IPAModuleInfo * \brief Information of an IPA module diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 05005c4..cfbf86a 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -194,7 +195,8 @@ private: class PipelineHandlerIPU3 : public PipelineHandler { public: - PipelineHandlerIPU3(CameraManager *manager); + PipelineHandlerIPU3(CameraManager *manager, const char *name, + uint32_t version); CameraConfiguration *generateConfiguration(Camera *camera, const StreamRoles &roles) override; @@ -372,8 +374,11 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate() return status; } -PipelineHandlerIPU3::PipelineHandlerIPU3(CameraManager *manager) - : PipelineHandler(manager), cio2MediaDev_(nullptr), imguMediaDev_(nullptr) +PipelineHandlerIPU3::PipelineHandlerIPU3(CameraManager *manager, + const char *name, + uint32_t version) + : PipelineHandler(manager, name, version), + cio2MediaDev_(nullptr), imguMediaDev_(nullptr) { } @@ -1452,6 +1457,6 @@ int CIO2Device::mediaBusToFormat(unsigned int code) } } -REGISTER_PIPELINE_HANDLER(PipelineHandlerIPU3); +REGISTER_PIPELINE_HANDLER(PipelineHandlerIPU3, PIPELINE_VERSION(0, 1)); } /* namespace libcamera */ diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 9b3eea2..077d84e 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -73,7 +74,8 @@ private: class PipelineHandlerRkISP1 : public PipelineHandler { public: - PipelineHandlerRkISP1(CameraManager *manager); + PipelineHandlerRkISP1(CameraManager *manager, const char *name, + uint32_t version); ~PipelineHandlerRkISP1(); CameraConfiguration *generateConfiguration(Camera *camera, @@ -200,9 +202,11 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate() return status; } -PipelineHandlerRkISP1::PipelineHandlerRkISP1(CameraManager *manager) - : PipelineHandler(manager), dphy_(nullptr), isp_(nullptr), - video_(nullptr) +PipelineHandlerRkISP1::PipelineHandlerRkISP1(CameraManager *manager, + const char *name, + uint32_t version) + : PipelineHandler(manager, name, version), dphy_(nullptr), + isp_(nullptr), video_(nullptr) { } @@ -499,6 +503,6 @@ void PipelineHandlerRkISP1::bufferReady(Buffer *buffer) completeRequest(activeCamera_, request); } -REGISTER_PIPELINE_HANDLER(PipelineHandlerRkISP1); +REGISTER_PIPELINE_HANDLER(PipelineHandlerRkISP1, PIPELINE_VERSION(0, 1)); } /* namespace libcamera */ diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp index 45260f3..430f467 100644 --- a/src/libcamera/pipeline/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo.cpp @@ -6,6 +6,7 @@ */ #include +#include #include #include @@ -50,7 +51,8 @@ public: class PipelineHandlerUVC : public PipelineHandler { public: - PipelineHandlerUVC(CameraManager *manager); + PipelineHandlerUVC(CameraManager *manager, const char *name, + uint32_t version); CameraConfiguration *generateConfiguration(Camera *camera, const StreamRoles &roles) override; @@ -115,8 +117,9 @@ CameraConfiguration::Status UVCCameraConfiguration::validate() return status; } -PipelineHandlerUVC::PipelineHandlerUVC(CameraManager *manager) - : PipelineHandler(manager) +PipelineHandlerUVC::PipelineHandlerUVC(CameraManager *manager, const char *name, + uint32_t version) + : PipelineHandler(manager, name, version) { } @@ -263,6 +266,6 @@ void UVCCameraData::bufferReady(Buffer *buffer) pipe_->completeRequest(camera_, request); } -REGISTER_PIPELINE_HANDLER(PipelineHandlerUVC); +REGISTER_PIPELINE_HANDLER(PipelineHandlerUVC, PIPELINE_VERSION(0, 1)); } /* namespace libcamera */ diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp index 0e4eede..78feeb8 100644 --- a/src/libcamera/pipeline/vimc.cpp +++ b/src/libcamera/pipeline/vimc.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -53,7 +54,8 @@ public: class PipelineHandlerVimc : public PipelineHandler { public: - PipelineHandlerVimc(CameraManager *manager); + PipelineHandlerVimc(CameraManager *manager, const char *name, + uint32_t version); CameraConfiguration *generateConfiguration(Camera *camera, const StreamRoles &roles) override; @@ -130,8 +132,10 @@ CameraConfiguration::Status VimcCameraConfiguration::validate() return status; } -PipelineHandlerVimc::PipelineHandlerVimc(CameraManager *manager) - : PipelineHandler(manager) +PipelineHandlerVimc::PipelineHandlerVimc(CameraManager *manager, + const char *name, + uint32_t version) + : PipelineHandler(manager, name, version) { } @@ -274,6 +278,6 @@ void VimcCameraData::bufferReady(Buffer *buffer) pipe_->completeRequest(camera_, request); } -REGISTER_PIPELINE_HANDLER(PipelineHandlerVimc); +REGISTER_PIPELINE_HANDLER(PipelineHandlerVimc, PIPELINE_VERSION(0, 1)); } /* namespace libcamera */ diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index dd56907..b18f14d 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -104,14 +104,17 @@ LOG_DEFINE_CATEGORY(Pipeline) /** * \brief Construct a PipelineHandler instance * \param[in] manager The camera manager + * \param[in] name The name of the pipeline handler + * \param[in] version The version of the pipeline handler * * In order to honour the std::enable_shared_from_this<> contract, * PipelineHandler instances shall never be constructed manually, but always * through the PipelineHandlerFactory::create() method implemented by the * respective factories. */ -PipelineHandler::PipelineHandler(CameraManager *manager) - : manager_(manager) +PipelineHandler::PipelineHandler(CameraManager *manager, const char *name, + uint32_t version) + : manager_(manager), name_(name), version_(version) { } @@ -505,6 +508,28 @@ CameraData *PipelineHandler::cameraData(const Camera *camera) * constant for the whole lifetime of the pipeline handler. */ +/** + * \fn PipelineHandler::name() + * \brief Retrieve the pipeline handler name + * \return The pipeline handler name + */ + +/** + * \fn PipelineHandler::version() + * \brief Retrieve the pipeline handler version + * \return The pipeline handler version + */ + +/** + * \var PipelineHandler::name_ + * \brief Pipeline handler name + */ + +/** + * \var PipelineHandler::version_ + * \brief Pipeline handler version + */ + /** * \class PipelineHandlerFactory * \brief Registration of PipelineHandler classes and creation of instances @@ -586,9 +611,12 @@ std::vector &PipelineHandlerFactory::factories() * \def REGISTER_PIPELINE_HANDLER * \brief Register a pipeline handler with the pipeline handler factory * \param[in] handler Class name of PipelineHandler derived class to register + * \param[in] pipelineVersion Version of the PipelineHandler * * Register a PipelineHandler subclass with the factory and make it available to * try and match devices. + * + * \sa PIPELINE_VERSION */ } /* namespace libcamera */ From patchwork Mon Jun 3 23:16:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 1340 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5E9BA618F8 for ; Tue, 4 Jun 2019 01:16:49 +0200 (CEST) Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id B451B51C; Tue, 4 Jun 2019 01:16:48 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1559603809; bh=+7EFQc5nylQ8AqqoqXxe8roQ6ZZaRUTvTOEeocenYqI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VB3vgpPaxJfC36tpqyMXLHx38OK080V1AIDbVogHRRk2YWmiBdefwlOpDH8CnmX/C 6SsOq+RXgRoiF0ZStIRFUY4ryLaGQCYTeMfBQKkd1XuvIqVGXZQnR9sHQPGkAeM6RT urGxZ4NOVH1BPWmXUke1CNw0J4qWyUj/t2UHTMXE= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Mon, 3 Jun 2019 19:16:30 -0400 Message-Id: <20190603231637.28554-4-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190603231637.28554-1-paul.elder@ideasonboard.com> References: <20190603231637.28554-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 03/10] libcamera: ipa_module_info: update struct to allow IPA matching 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, 03 Jun 2019 23:16:49 -0000 We need a way to match pipelines with IPA modules, so add fields in IPAModuleInfo to hold the IPA API version number, the pipeline name, and the pipeline version. Also update IPA module tests and Doxygen accordingly. Doxygen needs to be updated to accomodate __attribute__((packed)). Signed-off-by: Paul Elder --- - combine pipeline major and minor versions into one using the PIPELINE_VERSION macro, and update tests accordingly Documentation/Doxyfile.in | 7 ++-- include/libcamera/ipa/ipa_module_info.h | 10 ++++-- src/libcamera/ipa_module.cpp | 46 +++++++++++++++++++++---- test/ipa/ipa_test.cpp | 30 +++++++++------- test/ipa/shared_test.cpp | 4 ++- 5 files changed, 72 insertions(+), 25 deletions(-) diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in index 67eaded..ac70efb 100644 --- a/Documentation/Doxyfile.in +++ b/Documentation/Doxyfile.in @@ -2016,7 +2016,7 @@ ENABLE_PREPROCESSING = YES # The default value is: NO. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -MACRO_EXPANSION = NO +MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then # the macro expansion is limited to the macros specified with the PREDEFINED and @@ -2024,7 +2024,7 @@ MACRO_EXPANSION = NO # The default value is: NO. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -EXPAND_ONLY_PREDEF = NO +EXPAND_ONLY_PREDEF = YES # If the SEARCH_INCLUDES tag is set to YES, the include files in the # INCLUDE_PATH will be searched if a #include is found. @@ -2057,7 +2057,8 @@ INCLUDE_FILE_PATTERNS = *.h # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. PREDEFINED = __DOXYGEN__ \ - __cplusplus + __cplusplus \ + __attribute__(x)= # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The diff --git a/include/libcamera/ipa/ipa_module_info.h b/include/libcamera/ipa/ipa_module_info.h index e5f2a7e..df9b47e 100644 --- a/include/libcamera/ipa/ipa_module_info.h +++ b/include/libcamera/ipa/ipa_module_info.h @@ -7,6 +7,10 @@ #ifndef __LIBCAMERA_IPA_MODULE_INFO_H__ #define __LIBCAMERA_IPA_MODULE_INFO_H__ +#include + +#define IPA_MODULE_API_VERSION 1 + #define PIPELINE_VERSION(majorV, minorV) (majorV * 1000 + minorV) #ifdef __cplusplus @@ -14,9 +18,11 @@ namespace libcamera { #endif struct IPAModuleInfo { + int moduleAPIVersion; + uint32_t pipelineVersion; + char pipelineName[256]; char name[256]; - unsigned int version; -}; +} __attribute__((packed)); #ifdef __cplusplus extern "C" { diff --git a/src/libcamera/ipa_module.cpp b/src/libcamera/ipa_module.cpp index db56415..067f868 100644 --- a/src/libcamera/ipa_module.cpp +++ b/src/libcamera/ipa_module.cpp @@ -169,6 +169,17 @@ int elfLoadSymbol(void *dst, size_t size, void *map, size_t soSize, } /* namespace */ +/** + * \def IPA_MODULE_API_VERSION + * \brief The IPA API version + * + * This version number specifies the version for the layout of + * struct IPAModuleInfo. + * The IPA module shall use this macro to set its moduleAPIVersion field. + * + * \sa libcamera::IPAModuleInfo::moduleAPIVersion + */ + /** * \def PIPELINE_VERSION * \brief Convert a major and minor version pair to a single version number @@ -193,14 +204,37 @@ int elfLoadSymbol(void *dst, size_t size, void *map, size_t soSize, * This structure contains the information of an IPA module. It is loaded, * read, and validated before anything else is loaded from the shared object. * - * \var IPAModuleInfo::name - * \brief The name of the IPA module + * \var IPAModuleInfo::moduleAPIVersion + * \brief The IPA API version that the IPA module implements + * + * This version number specifies the version for the layout of + * struct IPAModuleInfo. + * The IPA module shall report here the version that it was built for, + * using the macro IPA_MODULE_API_VERSION. * - * \var IPAModuleInfo::version - * \brief The version of the IPA module + * \sa IPA_MODULE_API_VERSION * - * \todo abi compatability version - * \todo pipeline compatability matcher + * \var IPAModuleInfo::pipelineVersion + * \brief The pipeline handler version that the IPA module is for + * + * This field shall be constructed from a major and minor version using the + * macro PIPELINE_VERSION. + * + * The major version of the module and pipeline handler must be equal in + * order for the pipeline handler and the module to be matched. + *, and the API between pipeline handlers and the IPA + * + * The minor version of the module must be equal to or greater than + * the pipeline handler minor version in order for the pipeline handler + * and the module to be matched. + * + * \var IPAModuleInfo::pipelineName + * \brief The name of the pipeline handler that the IPA module is for + * + * This name is used to match a pipeline handler with the module. + * + * \var IPAModuleInfo::name + * \brief The name of the IPA module */ /** diff --git a/test/ipa/ipa_test.cpp b/test/ipa/ipa_test.cpp index 2dbc702..d7b18c7 100644 --- a/test/ipa/ipa_test.cpp +++ b/test/ipa/ipa_test.cpp @@ -33,18 +33,20 @@ protected: const struct IPAModuleInfo &info = ll->info(); - if (strcmp(info.name, testInfo.name)) { - cerr << "test IPA module has incorrect name" << endl; - cerr << "expected \"" << testInfo.name << "\", got \"" - << info.name << "\"" << endl; - ret = -1; - } - - if (info.version != testInfo.version) { - cerr << "test IPA module has incorrect version" << endl; - cerr << "expected \"" << testInfo.version << "\", got \"" - << info.version << "\"" << endl; - ret = -1; + if (info.moduleAPIVersion != testInfo.moduleAPIVersion || + info.pipelineVersion != testInfo.pipelineVersion || + strcmp(info.pipelineName, testInfo.pipelineName) || + strcmp(info.name, testInfo.name)) { + cerr << "IPA module information mismatch: expected:" << endl + << "moduleAPIVersion = " << testInfo.moduleAPIVersion << endl + << "pipelineVersion = " << testInfo.pipelineVersion << endl + << "pipelineName = " << testInfo.pipelineName << endl + << "name = " << testInfo.name + << "got: " << endl + << "moduleAPIVersion = " << info.moduleAPIVersion << endl + << "pipelineVersion = " << info.pipelineVersion << endl + << "pipelineName = " << info.pipelineName << endl + << "name = " << info.name << endl; } delete ll; @@ -56,8 +58,10 @@ protected: int count = 0; const struct IPAModuleInfo testInfo = { + IPA_MODULE_API_VERSION, + PIPELINE_VERSION(0, 9001), + "bleep", "It's over nine thousand!", - 9001, }; count += runTest("test/ipa/ipa-dummy-cpp.so", testInfo); diff --git a/test/ipa/shared_test.cpp b/test/ipa/shared_test.cpp index 4e5c976..5afc135 100644 --- a/test/ipa/shared_test.cpp +++ b/test/ipa/shared_test.cpp @@ -4,8 +4,10 @@ namespace libcamera { extern "C" { const struct libcamera::IPAModuleInfo ipaModuleInfo = { + IPA_MODULE_API_VERSION, + PIPELINE_VERSION(0, 9001), + "bleep", "It's over nine thousand!", - 9001, }; }; From patchwork Mon Jun 3 23:16:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 1341 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 07EAD618FD for ; Tue, 4 Jun 2019 01:16:50 +0200 (CEST) Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 61A4C530; Tue, 4 Jun 2019 01:16:49 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1559603809; bh=UOsv0TgC+jo2hmcdz8tvv/XPHbWwu29iW6WxYLw/Mgg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LjBS3FVAd/yjxKBQA5ct57WnN404ehtrSxu/cLcZGQjSOXsQfD9oYLIg0IdXf+LdL L5pSYeBmG/fvk+aD7/pDtyvnP6t1PMx8temRUhpssRS0TGipX2I3mVRYPquklnvXGa NSUF4OGldUURKJHgblu9e9gsg4rsZsJJxJ9L8kpQ= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Mon, 3 Jun 2019 19:16:31 -0400 Message-Id: <20190603231637.28554-5-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190603231637.28554-1-paul.elder@ideasonboard.com> References: <20190603231637.28554-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 04/10] 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, 03 Jun 2019 23:16:50 -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 Reviewed-by: Laurent Pinchart --- Changes in v2: - mostly just documentation src/libcamera/include/ipa_module.h | 12 +++++ src/libcamera/ipa_module.cpp | 83 ++++++++++++++++++++++++++++-- src/libcamera/meson.build | 3 +- 3 files changed, 94 insertions(+), 4 deletions(-) diff --git a/src/libcamera/include/ipa_module.h b/src/libcamera/include/ipa_module.h index a4c6dbd..557435c 100644 --- a/src/libcamera/include/ipa_module.h +++ b/src/libcamera/include/ipa_module.h @@ -7,8 +7,10 @@ #ifndef __LIBCAMERA_IPA_MODULE_H__ #define __LIBCAMERA_IPA_MODULE_H__ +#include #include +#include #include namespace libcamera { @@ -17,16 +19,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 *(*ipaIntfFactory)(void); + ipaIntfFactory ipaCreate_; int loadIPAModuleInfo(); }; diff --git a/src/libcamera/ipa_module.cpp b/src/libcamera/ipa_module.cpp index 067f868..91d97ae 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 @@ -257,13 +258,12 @@ 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), + dlHandle_(nullptr), ipaCreate_(nullptr) { if (loadIPAModuleInfo() < 0) return; @@ -271,6 +271,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); @@ -340,4 +346,75 @@ 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 method 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_); + dlHandle_ = nullptr; + return false; + } + + ipaCreate_ = (ipaIntfFactory)symbol; + + loaded_ = true; + + return true; +} + +/** + * \brief Instantiate an IPAInterface + * + * After loading the IPA module with load(), this method creates an + * instance of the IPA module interface. + * + * 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 on success, + * or nullptr on error + */ +std::unique_ptr IPAModule::createInstance() +{ + if (!valid_ || !loaded_) + return nullptr; + + return std::unique_ptr(ipaCreate_()); +} + } /* 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, From patchwork Mon Jun 3 23:16:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 1342 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AB2E1618F7 for ; Tue, 4 Jun 2019 01:16:50 +0200 (CEST) Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 1038A84; Tue, 4 Jun 2019 01:16:49 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1559603810; bh=53Y8BE362kE9OW52XW2x8AqdWydCsOCRYMJe0Xtihvo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vPt1Wj0M0/IQ2bvtbQwib4ZXjYVilcRZMWD4hFn3Dkk4N3qWmwLyMpo0NdzQC1kA6 1EMSc5XtOML9LySew0hJVzRMeNj/w55jM5KO+xAoLn5xMR8AFKNIKMQ9lstJrPb7nW xF+WnCX0VvpwYpMFxiszMPvi8xQB2Ce4sqMZmmmM= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Mon, 3 Jun 2019 19:16:32 -0400 Message-Id: <20190603231637.28554-6-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190603231637.28554-1-paul.elder@ideasonboard.com> References: <20190603231637.28554-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 05/10] libcamera: ipa_module: match IPA module with pipeline handler 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, 03 Jun 2019 23:16:51 -0000 Add a method to IPAModule to check if it matches with a given pipeline handler. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- New patch, but this IPAModule::match method used to be IPAManager::match src/libcamera/include/ipa_module.h | 4 ++++ src/libcamera/ipa_module.cpp | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/libcamera/include/ipa_module.h b/src/libcamera/include/ipa_module.h index 557435c..48ff2b6 100644 --- a/src/libcamera/include/ipa_module.h +++ b/src/libcamera/include/ipa_module.h @@ -13,6 +13,8 @@ #include #include +#include "pipeline_handler.h" + namespace libcamera { class IPAModule @@ -29,6 +31,8 @@ public: std::unique_ptr createInstance(); + bool match(PipelineHandler *pipe) const; + private: struct IPAModuleInfo info_; diff --git a/src/libcamera/ipa_module.cpp b/src/libcamera/ipa_module.cpp index 91d97ae..c1b04fe 100644 --- a/src/libcamera/ipa_module.cpp +++ b/src/libcamera/ipa_module.cpp @@ -18,6 +18,7 @@ #include #include "log.h" +#include "pipeline_handler.h" /** * \file ipa_module.h @@ -417,4 +418,22 @@ std::unique_ptr IPAModule::createInstance() return std::unique_ptr(ipaCreate_()); } +/** + * \brief Match this IPAModule with a PipelineHandler + * \param[in] pipe Pipeline handler to match with + * + * Checks if this IPA module matches the \a pipe pipeline handler. + * Matching is based on the fields of the IPA module info, and the + * corresponding attributes of the pipeline handler, such as pipeline version + * and name. + * + * \return true if the pipeline handler matches the IPA module, false otherwise + */ +bool IPAModule::match(PipelineHandler *pipe) const +{ + return info_.moduleAPIVersion == IPA_MODULE_API_VERSION && + info_.pipelineVersion == pipe->version() && + !strcmp(info_.pipelineName, pipe->name()); +} + } /* namespace libcamera */ From patchwork Mon Jun 3 23:16:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 1343 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 59CF460BD7 for ; Tue, 4 Jun 2019 01:16:51 +0200 (CEST) Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id B129F51C; Tue, 4 Jun 2019 01:16:50 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1559603811; bh=gXMLYxF7voHAjC0JxKIFD6nWjuPImrEQSEJMSG3acvA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QiKCoyiOKdcTPtlizypVN83VcZnz/WkhwJW0N6Gmoa51pX3N+zNezJIspJIrlY8Z8 DT2xNHwQ5cFN3UJ5rUul7zbRHFvAAwpmqwho2mpYfQ8YoMlIzNQYWV8mKhExs0Lpoq uja6kHl4uQbVn7nHHVD0HaF6q2Eys/zMm79hMkig= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Mon, 3 Jun 2019 19:16:33 -0400 Message-Id: <20190603231637.28554-7-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190603231637.28554-1-paul.elder@ideasonboard.com> References: <20190603231637.28554-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 06/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: Mon, 03 Jun 2019 23:16:51 -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 aquire 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 IPA_MODULE_PATH, with the same syntax as the regular PATH environment variable. Make the test framework populate this environment variable. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- 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 | 39 ++++++++ src/libcamera/ipa_manager.cpp | 141 ++++++++++++++++++++++++++++ src/libcamera/meson.build | 2 + src/meson.build | 1 + test/libtest/test.cpp | 6 ++ 6 files changed, 191 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..694df64 --- /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 +#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); + +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..6a946a2 --- /dev/null +++ b/src/libcamera/ipa_manager.cpp @@ -0,0 +1,141 @@ +/* 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 + +#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); + + char *modulePaths = utils::secure_getenv("IPA_MODULE_PATH"); + if (!modulePaths) + return; + + char *saveptr; + char *dir; + if ((dir = strtok_r(modulePaths, ":", &saveptr))) + addDir(dir); + while ((dir = strtok_r(nullptr, ":", &saveptr))) + addDir(dir); +} + +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 found + * shared object 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; + } + + int count = 0; + while ((ent = readdir(dir)) != nullptr) { + if (strlen(ent->d_name) < 3) + continue; + int offset = strlen(ent->d_name) - 3; + 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 + * + * \return IPA interface, or nullptr if no matching IPA module is found + */ +std::unique_ptr IPAManager::createIPA(PipelineHandler *pipe) +{ + IPAModule *m = nullptr; + + for (IPAModule *module : modules_) { + if (module->match(pipe)) { + 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..451c111 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("IPA_MODULE_PATH", "test/ipa", 1); + if (ret) + return errno; + ret = init(); if (ret) return ret; From patchwork Mon Jun 3 23:16:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 1344 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 05542618F7 for ; Tue, 4 Jun 2019 01:16:52 +0200 (CEST) Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 5EEC8587; Tue, 4 Jun 2019 01:16:51 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1559603811; bh=O8JTsoc2Ne6jQjTOe/n2U9Bn1rv2GhthU6bs8Jp9E4g=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pqkfeR3zltfEway2AdhL0DBaN+5rwPNdM9P8TK7fJ/74CtwJryOXfIUqavHrnruz2 hvp2DCPNRmE+hbBfCD4SCt4Ji2MX4ABiszgfr85mx0IcP+vMlWhPGY3fZK2LBz3hcz ESXdWYFy3PhCOr1W0sJRBGf+eEixh/6lmZ5GItoM= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Mon, 3 Jun 2019 19:16:34 -0400 Message-Id: <20190603231637.28554-8-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190603231637.28554-1-paul.elder@ideasonboard.com> References: <20190603231637.28554-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 07/10] libcamera: ipa: add dummy IPA implementation 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, 03 Jun 2019 23:16:52 -0000 Add a dummy IPA module. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- Changes in v2: - use macros for defining the version fields in ipaModuleInfo src/ipa/ipa_dummy.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++ src/ipa/meson.build | 11 +++++++++++ 2 files changed, 56 insertions(+) create mode 100644 src/ipa/ipa_dummy.cpp diff --git a/src/ipa/ipa_dummy.cpp b/src/ipa/ipa_dummy.cpp new file mode 100644 index 0000000..99a74ff --- /dev/null +++ b/src/ipa/ipa_dummy.cpp @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * ipa_dummy.cpp - Dummy Image Processing Algorithm module + */ + +#include + +#include +#include + +namespace libcamera { + +class IPADummy : public IPAInterface +{ +public: + int init(); +}; + +int IPADummy::init() +{ + std::cout << "initializing dummy IPA!" << std::endl; + return 0; +} + +/* + * External IPA module interface + */ + +extern "C" { +const struct libcamera::IPAModuleInfo ipaModuleInfo = { + IPA_MODULE_API_VERSION, + PIPELINE_VERSION(0, 1), + "PipelineHandlerVimc", + "Dummy IPA for Vimc", +}; + +IPAInterface *ipaCreate() +{ + return new IPADummy(); +} +}; + +}; /* namespace libcamera */ diff --git a/src/ipa/meson.build b/src/ipa/meson.build index be4f954..33d734d 100644 --- a/src/ipa/meson.build +++ b/src/ipa/meson.build @@ -1,2 +1,13 @@ +ipa_dummy_sources = files([ + 'ipa_dummy.cpp', +]) + +ipa_dummy = shared_library('ipa_dummy', + ipa_dummy_sources, + name_prefix : '', + include_directories : libcamera_includes, + install : true, + install_dir : join_paths(get_option('libdir'), 'libcamera')) + config_h.set('IPA_MODULE_DIR', '"' + join_paths(get_option('prefix'), get_option('libdir'), 'libcamera') + '"') From patchwork Mon Jun 3 23:16:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 1345 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C169D618F9 for ; Tue, 4 Jun 2019 01:16:52 +0200 (CEST) Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 0E76284; Tue, 4 Jun 2019 01:16:51 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1559603812; bh=sHLLuBNWxFbYSA4h91sOZVYyUfLGEs8Xoe6s7WHXwkE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FgnbvTpRNPFlCN9q1qxsgW9VpcAHO/P7gbRMxHl9JNjTu0hijOdC5fghgFIjkzrH4 U3P5rhtfBcE0FO9zCjMwE6Kmz1HrRLCN7hoUvAW4piyZ0+c/uNEOmyiw2KuWWnDJQx Mj+PbyihSFErAdtDZaQeSrwg7XkPleD5ktiqKf0g= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Mon, 3 Jun 2019 19:16:35 -0400 Message-Id: <20190603231637.28554-9-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190603231637.28554-1-paul.elder@ideasonboard.com> References: <20190603231637.28554-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 08/10] libcamera: test: remove test IPA and use dummy IPA instead 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, 03 Jun 2019 23:16:53 -0000 Use the dummy IPA for testing/sample IPA instead of the earlier test IPA. Remove the test IPA, and update tests and meson accordingly. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- Changes in v2: - use macros for defining the fields in the expected IPA module info test/ipa/ipa_test.cpp | 8 ++++---- test/ipa/meson.build | 10 ---------- test/libtest/test.cpp | 2 +- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/test/ipa/ipa_test.cpp b/test/ipa/ipa_test.cpp index d7b18c7..f401e29 100644 --- a/test/ipa/ipa_test.cpp +++ b/test/ipa/ipa_test.cpp @@ -59,12 +59,12 @@ protected: const struct IPAModuleInfo testInfo = { IPA_MODULE_API_VERSION, - PIPELINE_VERSION(0, 9001), - "bleep", - "It's over nine thousand!", + PIPELINE_VERSION(0, 1), + "PipelineHandlerVimc", + "Dummy IPA for Vimc", }; - count += runTest("test/ipa/ipa-dummy-cpp.so", testInfo); + count += runTest("src/ipa/ipa_dummy.so", testInfo); if (count < 0) return TestFail; diff --git a/test/ipa/meson.build b/test/ipa/meson.build index 08ee95c..bca39fa 100644 --- a/test/ipa/meson.build +++ b/test/ipa/meson.build @@ -1,13 +1,3 @@ -ipa_modules_sources = [ - ['ipa-dummy-cpp', 'shared_test.cpp'], -] - -foreach m : ipa_modules_sources - shared_library(m, name_prefix : '', - dependencies : libcamera_dep, - include_directories : test_includes_public) -endforeach - ipa_test = [ ['ipa_test', 'ipa_test.cpp'], ] diff --git a/test/libtest/test.cpp b/test/libtest/test.cpp index 451c111..a0c5102 100644 --- a/test/libtest/test.cpp +++ b/test/libtest/test.cpp @@ -21,7 +21,7 @@ int Test::execute() { int ret; - ret = setenv("IPA_MODULE_PATH", "test/ipa", 1); + ret = setenv("IPA_MODULE_PATH", "src/ipa", 1); if (ret) return errno; From patchwork Mon Jun 3 23:16: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: 1346 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 76409618FB for ; Tue, 4 Jun 2019 01:16:53 +0200 (CEST) Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D0034587; Tue, 4 Jun 2019 01:16:52 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1559603813; bh=uwq8QHYM17uy7O0OTiCqblzmomjoyJW7xhYEZ5F3ezs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QD4DDAzAS/4C5EPGKp1W6YJeEbxdY/1AVNgdKpv/2oei5ZQmH800c3WJCaGz4+BTb 6p99nX2dKG+y+nUQWUM+fY6CCzrNxagZD3igh0lsrGHLvLrYD+zVnGRrhKQ5XSbsM8 CGJsWDSE40AQUb6Of1GTWpdYmQWj54UQHzxzwnik= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Mon, 3 Jun 2019 19:16:36 -0400 Message-Id: <20190603231637.28554-10-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190603231637.28554-1-paul.elder@ideasonboard.com> References: <20190603231637.28554-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 09/10] libcamera: pipeline: store IPA in pipeline data 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, 03 Jun 2019 23:16:53 -0000 After the pipeline handler acquires an IPA, it should save it for future use. Store it in the pipeline data. Signed-off-by: Paul Elder --- New patch src/libcamera/include/pipeline_handler.h | 3 +++ src/libcamera/pipeline_handler.cpp | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h index 67971b3..a2d9624 100644 --- a/src/libcamera/include/pipeline_handler.h +++ b/src/libcamera/include/pipeline_handler.h @@ -14,6 +14,7 @@ #include #include +#include #include namespace libcamera { @@ -93,6 +94,8 @@ protected: const char *name_; uint32_t version_; + std::unique_ptr ipa_; + private: void mediaDeviceDisconnected(MediaDevice *media); virtual void disconnect(); diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index b18f14d..d6e68b0 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -530,6 +530,14 @@ CameraData *PipelineHandler::cameraData(const Camera *camera) * \brief Pipeline handler version */ +/** + * \var PipelineHandler::ipa_ + * \brief The IPA that the pipeline handler will use + * + * The pipeline handler can acquire an IPA from the IPAManager. Once it is + * acquired, it will be stored here. + */ + /** * \class PipelineHandlerFactory * \brief Registration of PipelineHandler classes and creation of instances From patchwork Mon Jun 3 23:16:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 1347 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2459D618F7 for ; Tue, 4 Jun 2019 01:16:54 +0200 (CEST) Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7E0B151C; Tue, 4 Jun 2019 01:16:53 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1559603813; bh=K2tLOK1usFqbAdnG9qt0ZB+0ooznf3NDvsqvkNsOp54=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lvSLTNiYrzRcajUeHUAeBeiDUGQc4tckHPgtM1vy2h+Rgh/ggC2tNtOt/M/CB2akW FH/tdSKAR0ryXtP81nq5a7FiHlJC627iEM9wLmKIGu1rj94wDIBAx3Cy85U/ZZaAq9 7Z4zBpgKtWGOGhdKxTFxls0SZlzIcw1AlhSu0Gkg= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Mon, 3 Jun 2019 19:16:37 -0400 Message-Id: <20190603231637.28554-11-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190603231637.28554-1-paul.elder@ideasonboard.com> References: <20190603231637.28554-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 10/10] libcamera: pipeline: vimc: add dummy IPA 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, 03 Jun 2019 23:16:54 -0000 Make the vimc pipeline handler get the dummy IPA, to show how an IPA can be acquired by a pipeline handler. Signed-off-by: Paul Elder --- Changes in v2: - save IPA to pipeline data - no IPA is fatal error src/libcamera/pipeline/vimc.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp index 78feeb8..f000c21 100644 --- a/src/libcamera/pipeline/vimc.cpp +++ b/src/libcamera/pipeline/vimc.cpp @@ -10,10 +10,12 @@ #include #include +#include #include #include #include "device_enumerator.h" +#include "ipa_manager.h" #include "log.h" #include "media_device.h" #include "pipeline_handler.h" @@ -252,6 +254,15 @@ bool PipelineHandlerVimc::match(DeviceEnumerator *enumerator) if (!media) return false; + IPAManager *ipaManager = IPAManager::instance(); + ipa_ = ipaManager->createIPA(this); + if (ipa_ == nullptr) { + LOG(VIMC, Error) << "no matching IPA found"; + return false; + } else { + ipa_->init(); + } + std::unique_ptr data = utils::make_unique(this); /* Locate and open the capture video node. */