{"id":16273,"url":"https://patchwork.libcamera.org/api/patches/16273/?format=json","web_url":"https://patchwork.libcamera.org/patch/16273/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20220620014305.26778-4-laurent.pinchart@ideasonboard.com>","date":"2022-06-20T01:42:56","name":"[libcamera-devel,v4,03/12] ipa: libipa: algorithm: Add an algorithm registration mechanism","commit_ref":null,"pull_url":null,"state":"accepted","archived":false,"hash":"6e6d2d021ad6eea8689daa8fe3a7b174bd37325c","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/?format=json","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/16273/mbox/","series":[{"id":3191,"url":"https://patchwork.libcamera.org/api/series/3191/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=3191","date":"2022-06-20T01:42:53","name":"Add tuning file support for the RkISP1 IPA module","version":4,"mbox":"https://patchwork.libcamera.org/series/3191/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/16273/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/16273/checks/","tags":{},"headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 20B5ABE173\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 20 Jun 2022 01:43:33 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6A3D365641;\n\tMon, 20 Jun 2022 03:43:30 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 48309601F1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 20 Jun 2022 03:43:26 +0200 (CEST)","from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id CE42425E;\n\tMon, 20 Jun 2022 03:43:25 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1655689410;\n\tbh=rIw0/l9qlrC1FD0Xq8PBMm5KK4qQtlgKRmBJ8tSg8Eg=;\n\th=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:\n\tFrom;\n\tb=SzdwS8VN0b28sexQlTKqkquVGBmPA5o8vbBYMGojINeKufDZdl3bnBKQ4e7vzHl5X\n\thjeg5z1/BTLnJj3a69GtJU/uubguD8C4g/5EvDbfl43ILxrnSqLJLrEH94rFQsHl0Q\n\tzHTxzwbo85BT11P4akV8ZcnIjID8rK4xnpHA9IQAEXYmH8nP8X/ypzIs7cAjQrL9xZ\n\tbs4DTxukLtuFfDK2mnqFDaI/wy/zU0v3aRSEgJZp7qeFjG/3vKeAhUGiCz09GMnmX0\n\tnHQgMy8XSUFLP3UiwXCj3UcfS3MWHzElc78YxyH1VG7aTfSNPmKAIFq4MANJTjKWUt\n\t6iyGVXi2hcKKg==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1655689406;\n\tbh=rIw0/l9qlrC1FD0Xq8PBMm5KK4qQtlgKRmBJ8tSg8Eg=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=q1hOo3VJzQWvpJ7PNKKGw1Kn5qw+CFPjfbHGRQGmES6cLBN0IkhbEjdz4h/JAxv1T\n\t3BNX9gwxjfOOL7ffX48I8GRIlOt1ezUWu8kYgCcbGhL8tI3wQMStf43zOB7iF7seSE\n\t0DxWnV9QsQiDo58NBU2GTgseyjmXZ4QF5hxSOs/U="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"q1hOo3VJ\"; dkim-atps=neutral","To":"libcamera-devel@lists.libcamera.org","Date":"Mon, 20 Jun 2022 04:42:56 +0300","Message-Id":"<20220620014305.26778-4-laurent.pinchart@ideasonboard.com>","X-Mailer":"git-send-email 2.35.1","In-Reply-To":"<20220620014305.26778-1-laurent.pinchart@ideasonboard.com>","References":"<20220620014305.26778-1-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","Subject":"[libcamera-devel] [PATCH v4 03/12] ipa: libipa: algorithm: Add an\n\talgorithm registration mechanism","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"},"content":"In order to allow dynamic instantiation of algorithms based on tuning\ndata files, add a mechanism to register algorithms with the IPA module.\nThe implementation relies on an AlgorithmFactory class and a\nregistration macro, similar to the pipeline handler registration\nmechanism. The main difference is that the algorithm registration and\ninstantiation are implemented in the Module class instead of the\nAlgorithmFactory class, making the factory an internal implementation\ndetail.\n\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n---\n src/ipa/libipa/algorithm.cpp | 54 ++++++++++++++++++++++++++++++++++++\n src/ipa/libipa/algorithm.h   | 41 ++++++++++++++++++++++++++-\n src/ipa/libipa/module.cpp    | 24 ++++++++++++++++\n src/ipa/libipa/module.h      | 33 ++++++++++++++++++++++\n 4 files changed, 151 insertions(+), 1 deletion(-)","diff":"diff --git a/src/ipa/libipa/algorithm.cpp b/src/ipa/libipa/algorithm.cpp\nindex 2df91e5d8fed..6e0bba56ecb2 100644\n--- a/src/ipa/libipa/algorithm.cpp\n+++ b/src/ipa/libipa/algorithm.cpp\n@@ -32,6 +32,11 @@ namespace ipa {\n  * argument.\n  */\n \n+/**\n+ * \\typedef Algorithm::Module\n+ * \\brief The IPA module type for this class of algorithms\n+ */\n+\n /**\n  * \\fn Algorithm::configure()\n  * \\brief Configure the Algorithm given an IPAConfigInfo\n@@ -94,6 +99,55 @@ namespace ipa {\n  * such that the algorithms use up to date state as required.\n  */\n \n+/**\n+ * \\class AlgorithmFactory\n+ * \\brief Registration of Algorithm classes and creation of instances\n+ *\n+ * To facilitate instantiation of Algorithm classes, the AlgorithmFactory class\n+ * implements auto-registration of algorithms with the IPA Module class. Each\n+ * Algorithm subclass shall register itself using the REGISTER_IPA_ALGORITHM()\n+ * macro, which will create a corresponding instance of an AlgorithmFactory\n+ * subclass and register it with the IPA Module.\n+ */\n+\n+/**\n+ * \\fn AlgorithmFactory::AlgorithmFactory()\n+ * \\brief Construct an algorithm factory\n+ * \\param[in] name Name of the algorithm class\n+ *\n+ * Creating an instance of the factory automatically registers is with the IPA\n+ * Module class, enabling creation of algorithm instances through\n+ * Module::createAlgorithm().\n+ *\n+ * The factory \\a name identifies the algorithm and shall be unique.\n+ */\n+\n+/**\n+ * \\fn AlgorithmFactory::name()\n+ * \\brief Retrieve the factory name\n+ * \\return The factory name\n+ */\n+\n+/**\n+ * \\fn AlgorithmFactory::create()\n+ * \\brief Create an instance of the Algorithm corresponding to the factory\n+ *\n+ * This virtual function is implemented by the REGISTER_IPA_ALGORITHM()\n+ * macro. It creates an algorithm instance.\n+ *\n+ * \\return A pointer to a newly constructed instance of the Algorithm subclass\n+ * corresponding to the factory\n+ */\n+\n+/**\n+ * \\def REGISTER_IPA_ALGORITHM\n+ * \\brief Register an algorithm with the IPA module\n+ * \\param[in] algorithm Class name of Algorithm derived class to register\n+ *\n+ * Register an Algorithm subclass with the IPA module to make it available for\n+ * instantiation through Module::createAlgorithm().\n+ */\n+\n } /* namespace ipa */\n \n } /* namespace libcamera */\ndiff --git a/src/ipa/libipa/algorithm.h b/src/ipa/libipa/algorithm.h\nindex fd2ffcfbc900..356c094976d4 100644\n--- a/src/ipa/libipa/algorithm.h\n+++ b/src/ipa/libipa/algorithm.h\n@@ -6,14 +6,19 @@\n  */\n #pragma once\n \n+#include <memory>\n+#include <string>\n+\n namespace libcamera {\n \n namespace ipa {\n \n-template<typename Module>\n+template<typename _Module>\n class Algorithm\n {\n public:\n+\tusing Module = _Module;\n+\n \tvirtual ~Algorithm() {}\n \n \tvirtual int configure([[maybe_unused]] typename Module::Context &context,\n@@ -34,6 +39,40 @@ public:\n \t}\n };\n \n+template<typename Module>\n+class AlgorithmFactory\n+{\n+public:\n+\tAlgorithmFactory(const char *name)\n+\t\t: name_(name)\n+\t{\n+\t\tModule::registerAlgorithm(this);\n+\t}\n+\n+\tvirtual ~AlgorithmFactory() = default;\n+\n+\tconst std::string &name() const { return name_; }\n+\n+\tvirtual std::unique_ptr<Algorithm<Module>> create() const = 0;\n+\n+private:\n+\tstd::string name_;\n+};\n+\n+#define REGISTER_IPA_ALGORITHM(algorithm)\t\t\t\t\t\\\n+class algorithm##Factory final : public AlgorithmFactory<algorithm::Module>\t\\\n+{\t\t\t\t\t\t\t\t\t\t\\\n+public:\t\t\t\t\t\t\t\t\t\t\\\n+\talgorithm##Factory() : AlgorithmFactory(#algorithm) {}\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\t\\\n+\tstd::unique_ptr<ipa::Algorithm<algorithm::Module>> create() const\t\\\n+\t{\t\t\t\t\t\t\t\t\t\\\n+\t\treturn std::make_unique<algorithm>();\t\t\t\t\\\n+\t}\t\t\t\t\t\t\t\t\t\\\n+};\t\t\t\t\t\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\t\\\n+static algorithm##Factory global_##algorithm##Factory;\n+\n } /* namespace ipa */\n \n } /* namespace libcamera */\ndiff --git a/src/ipa/libipa/module.cpp b/src/ipa/libipa/module.cpp\nindex d03cc8ef03ed..451614fd04da 100644\n--- a/src/ipa/libipa/module.cpp\n+++ b/src/ipa/libipa/module.cpp\n@@ -75,6 +75,30 @@ namespace ipa {\n  * \\brief The type of the IPA statistics and ISP results\n  */\n \n+/**\n+ * \\fn Module::createAlgorithm()\n+ * \\brief Create an instance of an Algorithm by name\n+ * \\param[in] name The algorithm name\n+ *\n+ * This function is the entry point to algorithm instantiation for the IPA\n+ * module. It creates and returns an instance of an algorithm identified by its\n+ * \\a name. If no such algorithm exists, the function returns nullptr.\n+ *\n+ * To make an algorithm available to the IPA module, it shall be registered with\n+ * the REGISTER_IPA_ALGORITHM() macro.\n+ *\n+ * \\return A new instance of the Algorithm subclass corresponding to the \\a name\n+ */\n+\n+/**\n+ * \\fn Module::registerAlgorithm()\n+ * \\brief Add an algorithm factory class to the list of available algorithms\n+ * \\param[in] factory Factory to use to construct the algorithm\n+ *\n+ * This function registers an algorithm factory. It is meant to be called by the\n+ * AlgorithmFactory constructor only.\n+ */\n+\n } /* namespace ipa */\n \n } /* namespace libcamera */\ndiff --git a/src/ipa/libipa/module.h b/src/ipa/libipa/module.h\nindex c4d778120408..f30fc33711bb 100644\n--- a/src/ipa/libipa/module.h\n+++ b/src/ipa/libipa/module.h\n@@ -7,6 +7,12 @@\n \n #pragma once\n \n+#include <memory>\n+#include <string>\n+#include <vector>\n+\n+#include \"algorithm.h\"\n+\n namespace libcamera {\n \n namespace ipa {\n@@ -23,6 +29,33 @@ public:\n \tusing Stats = _Stats;\n \n \tvirtual ~Module() {}\n+\n+\tstatic std::unique_ptr<Algorithm<Module>> createAlgorithm(const std::string &name)\n+\t{\n+\t\tfor (const AlgorithmFactory<Module> *factory : factories()) {\n+\t\t\tif (factory->name() == name)\n+\t\t\t\treturn factory->create();\n+\t\t}\n+\n+\t\treturn nullptr;\n+\t}\n+\n+\tstatic void registerAlgorithm(AlgorithmFactory<Module> *factory)\n+\t{\n+\t\tfactories().push_back(factory);\n+\t}\n+\n+private:\n+\tstatic std::vector<AlgorithmFactory<Module> *> &factories()\n+\t{\n+\t\t/*\n+\t\t * The static factories map is defined inside the function to ensure\n+\t\t * it gets initialized on first use, without any dependency on\n+\t\t * link order.\n+\t\t */\n+\t\tstatic std::vector<AlgorithmFactory<Module> *> factories;\n+\t\treturn factories;\n+\t}\n };\n \n } /* namespace ipa */\n","prefixes":["libcamera-devel","v4","03/12"]}