[libcamera-devel,v4,05/12] ipa: libipa: module: Add support for instantiation from YAML
diff mbox series

Message ID 20220620014305.26778-6-laurent.pinchart@ideasonboard.com
State Accepted
Headers show
Series
  • Add tuning file support for the RkISP1 IPA module
Related show

Commit Message

Laurent Pinchart June 20, 2022, 1:42 a.m. UTC
Add a Module::createAlgorithms() function to instantiate algorithms from
a YamlObject. The instantiated algorithms are stored in a private member
variable list, exposed through the Module::algorithms() function.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 src/ipa/libipa/module.cpp | 42 ++++++++++++++++------
 src/ipa/libipa/module.h   | 73 +++++++++++++++++++++++++++++++++++----
 2 files changed, 99 insertions(+), 16 deletions(-)

Comments

Nicolas Dufresne via libcamera-devel June 23, 2022, 12:29 p.m. UTC | #1
Hi Laurent,

On Mon, Jun 20, 2022 at 04:42:58AM +0300, Laurent Pinchart wrote:
> Add a Module::createAlgorithms() function to instantiate algorithms from
> a YamlObject. The instantiated algorithms are stored in a private member
> variable list, exposed through the Module::algorithms() function.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>

> ---
>  src/ipa/libipa/module.cpp | 42 ++++++++++++++++------
>  src/ipa/libipa/module.h   | 73 +++++++++++++++++++++++++++++++++++----
>  2 files changed, 99 insertions(+), 16 deletions(-)
> 
> diff --git a/src/ipa/libipa/module.cpp b/src/ipa/libipa/module.cpp
> index 451614fd04da..7735210444b6 100644
> --- a/src/ipa/libipa/module.cpp
> +++ b/src/ipa/libipa/module.cpp
> @@ -14,6 +14,8 @@
>  
>  namespace libcamera {
>  
> +LOG_DEFINE_CATEGORY(IPAModuleAlgo)
> +
>  /**
>   * \brief The IPA namespace
>   *
> @@ -76,7 +78,36 @@ namespace ipa {
>   */
>  
>  /**
> - * \fn Module::createAlgorithm()
> + * \fn Module::algorithms()
> + * \brief Retrieve the list of instantiated algorithms
> + * \return The list of instantiated algorithms
> + */
> +
> +/**
> + * \fn Module::createAlgorithms()
> + * \brief Create algorithms from YAML configuration data
> + * \param[in] context The IPA context
> + * \param[in] algorithms Algorithms configuration data as a parsed YamlObject
> + *
> + * This function iterates over the list of \a algorithms parsed from the YAML
> + * configuration file, and instantiates and initializes the corresponding
> + * algorithms. The configuration data is expected to be correct, any error
> + * causes the function to fail and return immediately.
> + *
> + * \return 0 on success, or a negative error code on failure
> + */
> +
> +/**
> + * \fn Module::registerAlgorithm()
> + * \brief Add an algorithm factory class to the list of available algorithms
> + * \param[in] factory Factory to use to construct the algorithm
> + *
> + * This function registers an algorithm factory. It is meant to be called by the
> + * AlgorithmFactory constructor only.
> + */
> +
> +/**
> + * \fn Module::createAlgorithm(const std::string &name)
>   * \brief Create an instance of an Algorithm by name
>   * \param[in] name The algorithm name
>   *
> @@ -90,15 +121,6 @@ namespace ipa {
>   * \return A new instance of the Algorithm subclass corresponding to the \a name
>   */
>  
> -/**
> - * \fn Module::registerAlgorithm()
> - * \brief Add an algorithm factory class to the list of available algorithms
> - * \param[in] factory Factory to use to construct the algorithm
> - *
> - * This function registers an algorithm factory. It is meant to be called by the
> - * AlgorithmFactory constructor only.
> - */
> -
>  } /* namespace ipa */
>  
>  } /* namespace libcamera */
> diff --git a/src/ipa/libipa/module.h b/src/ipa/libipa/module.h
> index f30fc33711bb..00d5785e1aa0 100644
> --- a/src/ipa/libipa/module.h
> +++ b/src/ipa/libipa/module.h
> @@ -7,14 +7,22 @@
>  
>  #pragma once
>  
> +#include <list>
>  #include <memory>
>  #include <string>
>  #include <vector>
>  
> +#include <libcamera/base/log.h>
> +#include <libcamera/base/utils.h>
> +
> +#include "libcamera/internal/yaml_parser.h"
> +
>  #include "algorithm.h"
>  
>  namespace libcamera {
>  
> +LOG_DECLARE_CATEGORY(IPAModuleAlgo)
> +
>  namespace ipa {
>  
>  template<typename _Context, typename _FrameContext, typename _Config,
> @@ -30,6 +38,63 @@ public:
>  
>  	virtual ~Module() {}
>  
> +	const std::list<std::unique_ptr<Algorithm<Module>>> &algorithms() const
> +	{
> +		return algorithms_;
> +	}
> +
> +	int createAlgorithms(Context &context, const YamlObject &algorithms)
> +	{
> +		const auto &list = algorithms.asList();
> +
> +		for (const auto &[i, algo] : utils::enumerate(list)) {
> +			if (!algo.isDictionary()) {
> +				LOG(IPAModuleAlgo, Error)
> +					<< "Invalid YAML syntax for algorithm " << i;
> +				algorithms_.clear();
> +				return -EINVAL;
> +			}
> +
> +			int ret = createAlgorithm(context, algo);
> +			if (ret) {
> +				algorithms_.clear();
> +				return ret;
> +			}
> +		}
> +
> +		return 0;
> +	}
> +
> +	static void registerAlgorithm(AlgorithmFactory<Module> *factory)
> +	{
> +		factories().push_back(factory);
> +	}
> +
> +private:
> +	int createAlgorithm(Context &context, const YamlObject &data)
> +	{
> +		const auto &[name, algoData] = *data.asDict().begin();
> +		std::unique_ptr<Algorithm<Module>> algo = createAlgorithm(name);
> +		if (!algo) {
> +			LOG(IPAModuleAlgo, Error)
> +				<< "Algorithm '" << name << "' not found";
> +			return -EINVAL;
> +		}
> +
> +		int ret = algo->init(context, algoData);
> +		if (ret) {
> +			LOG(IPAModuleAlgo, Error)
> +				<< "Algorithm '" << name << "' failed to initialize";
> +			return ret;
> +		}
> +
> +		LOG(IPAModuleAlgo, Debug)
> +			<< "Instantiated algorithm '" << name << "'";
> +
> +		algorithms_.push_back(std::move(algo));
> +		return 0;
> +	}
> +
>  	static std::unique_ptr<Algorithm<Module>> createAlgorithm(const std::string &name)
>  	{
>  		for (const AlgorithmFactory<Module> *factory : factories()) {
> @@ -40,12 +105,6 @@ public:
>  		return nullptr;
>  	}
>  
> -	static void registerAlgorithm(AlgorithmFactory<Module> *factory)
> -	{
> -		factories().push_back(factory);
> -	}
> -
> -private:
>  	static std::vector<AlgorithmFactory<Module> *> &factories()
>  	{
>  		/*
> @@ -56,6 +115,8 @@ private:
>  		static std::vector<AlgorithmFactory<Module> *> factories;
>  		return factories;
>  	}
> +
> +	std::list<std::unique_ptr<Algorithm<Module>>> algorithms_;
>  };
>  
>  } /* namespace ipa */

Patch
diff mbox series

diff --git a/src/ipa/libipa/module.cpp b/src/ipa/libipa/module.cpp
index 451614fd04da..7735210444b6 100644
--- a/src/ipa/libipa/module.cpp
+++ b/src/ipa/libipa/module.cpp
@@ -14,6 +14,8 @@ 
 
 namespace libcamera {
 
+LOG_DEFINE_CATEGORY(IPAModuleAlgo)
+
 /**
  * \brief The IPA namespace
  *
@@ -76,7 +78,36 @@  namespace ipa {
  */
 
 /**
- * \fn Module::createAlgorithm()
+ * \fn Module::algorithms()
+ * \brief Retrieve the list of instantiated algorithms
+ * \return The list of instantiated algorithms
+ */
+
+/**
+ * \fn Module::createAlgorithms()
+ * \brief Create algorithms from YAML configuration data
+ * \param[in] context The IPA context
+ * \param[in] algorithms Algorithms configuration data as a parsed YamlObject
+ *
+ * This function iterates over the list of \a algorithms parsed from the YAML
+ * configuration file, and instantiates and initializes the corresponding
+ * algorithms. The configuration data is expected to be correct, any error
+ * causes the function to fail and return immediately.
+ *
+ * \return 0 on success, or a negative error code on failure
+ */
+
+/**
+ * \fn Module::registerAlgorithm()
+ * \brief Add an algorithm factory class to the list of available algorithms
+ * \param[in] factory Factory to use to construct the algorithm
+ *
+ * This function registers an algorithm factory. It is meant to be called by the
+ * AlgorithmFactory constructor only.
+ */
+
+/**
+ * \fn Module::createAlgorithm(const std::string &name)
  * \brief Create an instance of an Algorithm by name
  * \param[in] name The algorithm name
  *
@@ -90,15 +121,6 @@  namespace ipa {
  * \return A new instance of the Algorithm subclass corresponding to the \a name
  */
 
-/**
- * \fn Module::registerAlgorithm()
- * \brief Add an algorithm factory class to the list of available algorithms
- * \param[in] factory Factory to use to construct the algorithm
- *
- * This function registers an algorithm factory. It is meant to be called by the
- * AlgorithmFactory constructor only.
- */
-
 } /* namespace ipa */
 
 } /* namespace libcamera */
diff --git a/src/ipa/libipa/module.h b/src/ipa/libipa/module.h
index f30fc33711bb..00d5785e1aa0 100644
--- a/src/ipa/libipa/module.h
+++ b/src/ipa/libipa/module.h
@@ -7,14 +7,22 @@ 
 
 #pragma once
 
+#include <list>
 #include <memory>
 #include <string>
 #include <vector>
 
+#include <libcamera/base/log.h>
+#include <libcamera/base/utils.h>
+
+#include "libcamera/internal/yaml_parser.h"
+
 #include "algorithm.h"
 
 namespace libcamera {
 
+LOG_DECLARE_CATEGORY(IPAModuleAlgo)
+
 namespace ipa {
 
 template<typename _Context, typename _FrameContext, typename _Config,
@@ -30,6 +38,63 @@  public:
 
 	virtual ~Module() {}
 
+	const std::list<std::unique_ptr<Algorithm<Module>>> &algorithms() const
+	{
+		return algorithms_;
+	}
+
+	int createAlgorithms(Context &context, const YamlObject &algorithms)
+	{
+		const auto &list = algorithms.asList();
+
+		for (const auto &[i, algo] : utils::enumerate(list)) {
+			if (!algo.isDictionary()) {
+				LOG(IPAModuleAlgo, Error)
+					<< "Invalid YAML syntax for algorithm " << i;
+				algorithms_.clear();
+				return -EINVAL;
+			}
+
+			int ret = createAlgorithm(context, algo);
+			if (ret) {
+				algorithms_.clear();
+				return ret;
+			}
+		}
+
+		return 0;
+	}
+
+	static void registerAlgorithm(AlgorithmFactory<Module> *factory)
+	{
+		factories().push_back(factory);
+	}
+
+private:
+	int createAlgorithm(Context &context, const YamlObject &data)
+	{
+		const auto &[name, algoData] = *data.asDict().begin();
+		std::unique_ptr<Algorithm<Module>> algo = createAlgorithm(name);
+		if (!algo) {
+			LOG(IPAModuleAlgo, Error)
+				<< "Algorithm '" << name << "' not found";
+			return -EINVAL;
+		}
+
+		int ret = algo->init(context, algoData);
+		if (ret) {
+			LOG(IPAModuleAlgo, Error)
+				<< "Algorithm '" << name << "' failed to initialize";
+			return ret;
+		}
+
+		LOG(IPAModuleAlgo, Debug)
+			<< "Instantiated algorithm '" << name << "'";
+
+		algorithms_.push_back(std::move(algo));
+		return 0;
+	}
+
 	static std::unique_ptr<Algorithm<Module>> createAlgorithm(const std::string &name)
 	{
 		for (const AlgorithmFactory<Module> *factory : factories()) {
@@ -40,12 +105,6 @@  public:
 		return nullptr;
 	}
 
-	static void registerAlgorithm(AlgorithmFactory<Module> *factory)
-	{
-		factories().push_back(factory);
-	}
-
-private:
 	static std::vector<AlgorithmFactory<Module> *> &factories()
 	{
 		/*
@@ -56,6 +115,8 @@  private:
 		static std::vector<AlgorithmFactory<Module> *> factories;
 		return factories;
 	}
+
+	std::list<std::unique_ptr<Algorithm<Module>>> algorithms_;
 };
 
 } /* namespace ipa */