[v1,04/11] libipa: awb: Add helper functions for AWB mode support
diff mbox series

Message ID 20250109115412.356768-5-stefan.klug@ideasonboard.com
State New
Headers show
Series
  • Add Bayesian AWB algorithm to libipa and rkisp1
Related show

Commit Message

Stefan Klug Jan. 9, 2025, 11:53 a.m. UTC
The AWB modes are specified in the libcamera core controls. It is
therefore quite likely that every AWB algorithm will implement them. Add
helper functions for parsing and storing the configured modes and the
currently selected mode to the AwbAlgorithm base class.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
---
 src/ipa/libipa/awb.cpp | 100 +++++++++++++++++++++++++++++++++++++++++
 src/ipa/libipa/awb.h   |  12 +++++
 2 files changed, 112 insertions(+)

Comments

Paul Elder Jan. 13, 2025, 10:40 p.m. UTC | #1
On Thu, Jan 09, 2025 at 12:53:55PM +0100, Stefan Klug wrote:
> The AWB modes are specified in the libcamera core controls. It is
> therefore quite likely that every AWB algorithm will implement them. Add
> helper functions for parsing and storing the configured modes and the
> currently selected mode to the AwbAlgorithm base class.
> 
> Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
> ---
>  src/ipa/libipa/awb.cpp | 100 +++++++++++++++++++++++++++++++++++++++++
>  src/ipa/libipa/awb.h   |  12 +++++
>  2 files changed, 112 insertions(+)
> 
> diff --git a/src/ipa/libipa/awb.cpp b/src/ipa/libipa/awb.cpp
> index 74e88d513b27..07502da66f73 100644
> --- a/src/ipa/libipa/awb.cpp
> +++ b/src/ipa/libipa/awb.cpp
> @@ -9,6 +9,8 @@
>  
>  #include <libcamera/base/log.h>
>  
> +#include <libcamera/control_ids.h>
> +
>  /**
>   * \file awb.h
>   * \brief Base classes for AWB algorithms
> @@ -132,6 +134,104 @@ namespace ipa {
>   * \brief Controls info map for the controls provided by the algorithm
>   */
>  
> +/**
> + * \var AwbAlgorithm::modes_
> + * \brief Map of all configured modes
> + * \sa AwbAlgorithm::parseModeConfigs
> + */
> +
> +/**
> + * \class AwbAlgorithm::ModeConfig
> + * \brief Holds the configuration of a single AWB mode
> + *
> + * Awb modes limit the regulation of the AWB algorithm to a specific range of
> + * colour temperatures.
> + */
> +
> +/**
> + * \var AwbAlgorithm::ModeConfig::ctLo
> + * \brief The lowest valid colour temperature of that mode
> + */
> +
> +/**
> + * \var AwbAlgorithm::ModeConfig::ctHi
> + * \brief The highest valid colour temperature of that mode
> + */
> +
> +/**
> + * \brief Parse the mode configurations from the tuning data
> + * \param[in] tuningData the YamlObject representing the tuning data
> + *
> + * Utility function to parse the tuning data for a AwbMode entry and read all
> + * provided modes. It populetes AwbAlgorithm::controls_, AwbAlgorithm::modes_

s/populetes/populates/

> + * and sets the current mode to AwbAuto.
> + *
> + * \return Zero on success, negative error code otherwise
> + */
> +int AwbAlgorithm::parseModeConfigs(const YamlObject &tuningData)
> +{
> +	std::vector<ControlValue> availableModes;
> +
> +	const YamlObject &yamlModes = tuningData[controls::AwbMode.name()];
> +	if (!yamlModes.isDictionary()) {
> +		LOG(Awb, Error)
> +			<< "AwbModes must be a dictionary.";
> +		return -EINVAL;
> +	}
> +
> +	for (const auto &[modeName, modeDict] : yamlModes.asDict()) {
> +		if (controls::AwbModeNameValueMap.find(modeName) ==
> +		    controls::AwbModeNameValueMap.end()) {
> +			LOG(Awb, Warning)
> +				<< "Skipping unknown awb mode '"
> +				<< modeName << "'";
> +			continue;
> +		}
> +
> +		if (!modeDict.isDictionary()) {
> +			LOG(Awb, Error)
> +				<< "Invalid awb mode '" << modeName << "'";
> +			return -EINVAL;
> +		}
> +
> +		const auto &modeValue = static_cast<controls::AwbModeEnum>(
> +			controls::AwbModeNameValueMap.at(modeName));
> +
> +		auto &config = modes_[modeValue];
> +		auto hi = modeDict["hi"].get<double>();

Would this be better non-auto...?


Either way,

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

> +		if (!hi) {
> +			LOG(Awb, Error) << "Failed to read hi param of mode "
> +					<< modeName;
> +			return -EINVAL;
> +		}
> +		config.ctHi = *hi;
> +
> +		auto lo = modeDict["lo"].get<double>();
> +		if (!lo) {
> +			LOG(Awb, Error) << "Failed to read low param of mode "
> +					<< modeName;
> +			return -EINVAL;
> +		}
> +		config.ctLo = *lo;
> +
> +		availableModes.push_back(modeValue);
> +	}
> +
> +	if (modes_.empty()) {
> +		LOG(Awb, Error) << "No AWB modes configured";
> +		return -EINVAL;
> +	}
> +
> +	if (modes_.find(controls::AwbAuto) == modes_.end()) {
> +		LOG(Awb, Error) << "AwbAuto mode is missing in the configuration.";
> +		return -EINVAL;
> +	}
> +
> +	controls_[&controls::AwbMode] = ControlInfo(availableModes);
> +
> +	return 0;
> +}
> +
>  } /* namespace ipa */
>  
>  } /* namespace libcamera */
> diff --git a/src/ipa/libipa/awb.h b/src/ipa/libipa/awb.h
> index 2dd471606ec4..426fdd6dae77 100644
> --- a/src/ipa/libipa/awb.h
> +++ b/src/ipa/libipa/awb.h
> @@ -7,7 +7,11 @@
>  
>  #pragma once
>  
> +#include <map>
> +
> +#include <libcamera/control_ids.h>
>  #include <libcamera/controls.h>
> +
>  #include "libcamera/internal/yaml_parser.h"
>  
>  #include "vector.h"
> @@ -43,7 +47,15 @@ public:
>  	virtual void handleControls([[maybe_unused]] const ControlList &controls) {}
>  
>  protected:
> +	int parseModeConfigs(const YamlObject &tuningData);
> +
> +	struct ModeConfig {
> +		double ctHi;
> +		double ctLo;
> +	};
> +
>  	ControlInfoMap::Map controls_;
> +	std::map<controls::AwbModeEnum, AwbAlgorithm::ModeConfig> modes_;
>  };
>  
>  } /* namespace ipa */
> -- 
> 2.43.0
>

Patch
diff mbox series

diff --git a/src/ipa/libipa/awb.cpp b/src/ipa/libipa/awb.cpp
index 74e88d513b27..07502da66f73 100644
--- a/src/ipa/libipa/awb.cpp
+++ b/src/ipa/libipa/awb.cpp
@@ -9,6 +9,8 @@ 
 
 #include <libcamera/base/log.h>
 
+#include <libcamera/control_ids.h>
+
 /**
  * \file awb.h
  * \brief Base classes for AWB algorithms
@@ -132,6 +134,104 @@  namespace ipa {
  * \brief Controls info map for the controls provided by the algorithm
  */
 
+/**
+ * \var AwbAlgorithm::modes_
+ * \brief Map of all configured modes
+ * \sa AwbAlgorithm::parseModeConfigs
+ */
+
+/**
+ * \class AwbAlgorithm::ModeConfig
+ * \brief Holds the configuration of a single AWB mode
+ *
+ * Awb modes limit the regulation of the AWB algorithm to a specific range of
+ * colour temperatures.
+ */
+
+/**
+ * \var AwbAlgorithm::ModeConfig::ctLo
+ * \brief The lowest valid colour temperature of that mode
+ */
+
+/**
+ * \var AwbAlgorithm::ModeConfig::ctHi
+ * \brief The highest valid colour temperature of that mode
+ */
+
+/**
+ * \brief Parse the mode configurations from the tuning data
+ * \param[in] tuningData the YamlObject representing the tuning data
+ *
+ * Utility function to parse the tuning data for a AwbMode entry and read all
+ * provided modes. It populetes AwbAlgorithm::controls_, AwbAlgorithm::modes_
+ * and sets the current mode to AwbAuto.
+ *
+ * \return Zero on success, negative error code otherwise
+ */
+int AwbAlgorithm::parseModeConfigs(const YamlObject &tuningData)
+{
+	std::vector<ControlValue> availableModes;
+
+	const YamlObject &yamlModes = tuningData[controls::AwbMode.name()];
+	if (!yamlModes.isDictionary()) {
+		LOG(Awb, Error)
+			<< "AwbModes must be a dictionary.";
+		return -EINVAL;
+	}
+
+	for (const auto &[modeName, modeDict] : yamlModes.asDict()) {
+		if (controls::AwbModeNameValueMap.find(modeName) ==
+		    controls::AwbModeNameValueMap.end()) {
+			LOG(Awb, Warning)
+				<< "Skipping unknown awb mode '"
+				<< modeName << "'";
+			continue;
+		}
+
+		if (!modeDict.isDictionary()) {
+			LOG(Awb, Error)
+				<< "Invalid awb mode '" << modeName << "'";
+			return -EINVAL;
+		}
+
+		const auto &modeValue = static_cast<controls::AwbModeEnum>(
+			controls::AwbModeNameValueMap.at(modeName));
+
+		auto &config = modes_[modeValue];
+		auto hi = modeDict["hi"].get<double>();
+		if (!hi) {
+			LOG(Awb, Error) << "Failed to read hi param of mode "
+					<< modeName;
+			return -EINVAL;
+		}
+		config.ctHi = *hi;
+
+		auto lo = modeDict["lo"].get<double>();
+		if (!lo) {
+			LOG(Awb, Error) << "Failed to read low param of mode "
+					<< modeName;
+			return -EINVAL;
+		}
+		config.ctLo = *lo;
+
+		availableModes.push_back(modeValue);
+	}
+
+	if (modes_.empty()) {
+		LOG(Awb, Error) << "No AWB modes configured";
+		return -EINVAL;
+	}
+
+	if (modes_.find(controls::AwbAuto) == modes_.end()) {
+		LOG(Awb, Error) << "AwbAuto mode is missing in the configuration.";
+		return -EINVAL;
+	}
+
+	controls_[&controls::AwbMode] = ControlInfo(availableModes);
+
+	return 0;
+}
+
 } /* namespace ipa */
 
 } /* namespace libcamera */
diff --git a/src/ipa/libipa/awb.h b/src/ipa/libipa/awb.h
index 2dd471606ec4..426fdd6dae77 100644
--- a/src/ipa/libipa/awb.h
+++ b/src/ipa/libipa/awb.h
@@ -7,7 +7,11 @@ 
 
 #pragma once
 
+#include <map>
+
+#include <libcamera/control_ids.h>
 #include <libcamera/controls.h>
+
 #include "libcamera/internal/yaml_parser.h"
 
 #include "vector.h"
@@ -43,7 +47,15 @@  public:
 	virtual void handleControls([[maybe_unused]] const ControlList &controls) {}
 
 protected:
+	int parseModeConfigs(const YamlObject &tuningData);
+
+	struct ModeConfig {
+		double ctHi;
+		double ctLo;
+	};
+
 	ControlInfoMap::Map controls_;
+	std::map<controls::AwbModeEnum, AwbAlgorithm::ModeConfig> modes_;
 };
 
 } /* namespace ipa */