summaryrefslogtreecommitdiff
path: root/src/ipa/libipa
diff options
context:
space:
mode:
authorStefan Klug <stefan.klug@ideasonboard.com>2025-01-23 12:40:54 +0100
committerStefan Klug <stefan.klug@ideasonboard.com>2025-02-21 17:35:03 +0100
commitd19ae2a228f3ad9ba792f905de09d5f4a71a9c20 (patch)
tree8a5791f23a12a2fedfe99bfa265b9d2804e55e6a /src/ipa/libipa
parent6f663990a0f73f6b1e058470bc3129a21b252f17 (diff)
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 <stefan.klug@ideasonboard.com> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>
Diffstat (limited to 'src/ipa/libipa')
-rw-r--r--src/ipa/libipa/awb.cpp127
-rw-r--r--src/ipa/libipa/awb.h13
2 files changed, 140 insertions, 0 deletions
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 <libcamera/base/log.h>
+#include <libcamera/control_ids.h>
+
/**
* \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<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));
+
+ ModeConfig &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 (!def.isNone() &&
+ modes_.find(def.get<controls::AwbModeEnum>()) == modes_.end()) {
+ const auto &names = controls::AwbMode.enumerators();
+ LOG(Awb, Error) << names.at(def.get<controls::AwbModeEnum>())
+ << " 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 <map>
+
+#include <libcamera/control_ids.h>
#include <libcamera/controls.h>
+
#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<controls::AwbModeEnum, AwbAlgorithm::ModeConfig> modes_;
};
} /* namespace ipa */