From patchwork Thu Jan 23 11:40:54 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 22619 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 683A4BDE6B for ; Thu, 23 Jan 2025 11:42:25 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1D60F68568; Thu, 23 Jan 2025 12:42:25 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ib8TBA9b"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7C41861879 for ; Thu, 23 Jan 2025 12:42:22 +0100 (CET) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:c0a:33cd:b453:5d3f]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E92751189; Thu, 23 Jan 2025 12:41:18 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1737632479; bh=5V/ezk+n02YW9xGEUfyyfwQgB7o03lxD91pLbnvbnWw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ib8TBA9b0EAnzeDs96e1dnkjJqUsLiWIEyPIg62kTbwf/7bvZQV6HTiGMfhy6GfCD gGomUHmoJ8Uh0qIVpST7WNn817Wl4RdgN8+EG3JFXKhf3Yo6A4x9DyNCRtlESMU03N O8mOviRysJZ8zSvdPxmyuHLmLKfGOnIsWHevr27U= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug , Paul Elder , Daniel Scally Subject: [PATCH v2 04/17] libipa: awb: Add helper functions for AWB mode support Date: Thu, 23 Jan 2025 12:40:54 +0100 Message-ID: <20250123114204.79321-5-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250123114204.79321-1-stefan.klug@ideasonboard.com> References: <20250123114204.79321-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" 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 --- Changes in v2: - Collected tags - Improved documentation - Replaced AwbAuto handling with a user supplied default value --- 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 4db97f6a10fc..62b69dd96238 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 2dd471606ec4..1f7477c071ac 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/yaml_parser.h" #include "vector.h" @@ -43,7 +47,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 */