From d19ae2a228f3ad9ba792f905de09d5f4a71a9c20 Mon Sep 17 00:00:00 2001 From: Stefan Klug Date: Thu, 23 Jan 2025 12:40:54 +0100 Subject: libipa: awb: Add helper functions for AWB mode support 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 in the AwbAlgorithm base class. Signed-off-by: Stefan Klug Reviewed-by: Paul Elder Reviewed-by: Daniel Scally --- src/ipa/libipa/awb.cpp | 127 +++++++++++++++++++++++++++++++++++++++++++++++++ src/ipa/libipa/awb.h | 13 +++++ 2 files changed, 140 insertions(+) diff --git a/src/ipa/libipa/awb.cpp b/src/ipa/libipa/awb.cpp index 4db97f6a..62b69dd9 100644 --- a/src/ipa/libipa/awb.cpp +++ b/src/ipa/libipa/awb.cpp @@ -9,6 +9,8 @@ #include +#include + /** * \file awb.h * \brief Base classes for AWB algorithms @@ -132,6 +134,131 @@ 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 + * \param[in] def The default value for the AwbMode control + * + * Utility function to parse the tuning data for an AwbMode entry and read all + * provided modes. It adds controls::AwbMode to AwbAlgorithm::controls_ and + * populates AwbAlgorithm::modes_. For a list of possible modes see \ref + * controls::AwbModeEnum. + * + * Each mode entry must contain a "lo" and "hi" key to specify the lower and + * upper colour temperature of that mode. For example: + * + * \code{.unparsed} + * algorithms: + * - Awb: + * AwbMode: + * AwbAuto: + * lo: 2500 + * hi: 8000 + * AwbIncandescent: + * lo: 2500 + * hi: 3000 + * ... + * \endcode + * + * If \a def is supplied but not contained in the the \a tuningData, -EINVAL is + * returned. + * + * \sa controls::AwbModeEnum + * \return Zero on success, negative error code otherwise + */ +int AwbAlgorithm::parseModeConfigs(const YamlObject &tuningData, + const ControlValue &def) +{ + std::vector 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::AwbModeNameValueMap.at(modeName)); + + ModeConfig &config = modes_[modeValue]; + + auto hi = modeDict["hi"].get(); + if (!hi) { + LOG(Awb, Error) << "Failed to read hi param of mode " + << modeName; + return -EINVAL; + } + config.ctHi = *hi; + + auto lo = modeDict["lo"].get(); + 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 (!def.isNone() && + modes_.find(def.get()) == modes_.end()) { + const auto &names = controls::AwbMode.enumerators(); + LOG(Awb, Error) << names.at(def.get()) + << " mode is missing in the configuration."; + return -EINVAL; + } + + controls_[&controls::AwbMode] = ControlInfo(availableModes, def); + + return 0; +} + } /* namespace ipa */ } /* namespace libcamera */ diff --git a/src/ipa/libipa/awb.h b/src/ipa/libipa/awb.h index 95be01b0..4a1b012a 100644 --- a/src/ipa/libipa/awb.h +++ b/src/ipa/libipa/awb.h @@ -7,7 +7,11 @@ #pragma once +#include + +#include #include + #include "libcamera/internal/vector.h" #include "libcamera/internal/yaml_parser.h" @@ -42,7 +46,16 @@ public: virtual void handleControls([[maybe_unused]] const ControlList &controls) {} protected: + int parseModeConfigs(const YamlObject &tuningData, + const ControlValue &def = {}); + + struct ModeConfig { + double ctHi; + double ctLo; + }; + ControlInfoMap::Map controls_; + std::map modes_; }; } /* namespace ipa */ -- cgit v1.2.1