From patchwork Fri Sep 19 09:40:31 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 24425 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 957D4C3331 for ; Fri, 19 Sep 2025 09:41:45 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 675586B5C8; Fri, 19 Sep 2025 11:41:44 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="vRx0c5d0"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2561262C38 for ; Fri, 19 Sep 2025 11:41:41 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:4d54:eab8:98ca:163b]) by perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id E3B87C67; Fri, 19 Sep 2025 11:40:20 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1758274821; bh=8QESrQ2P6bkZ2N/UKPNrA4RaLN0gtxHRQyM5r/MAJM4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vRx0c5d06lrgaRXrSpBcOqfbUhCELlB54/wyQnd/SbFStDjr/pZH1nMPk+JOwYfnC YdecA9pstMq+zdDasiLoaMznuaA5Kb+upj3SSwLk1hNKX5jH2N8O++bR//2Ced34d8 Y2LIdwaMCNEWnbp50Nd3pc9JQnEsthZ1C0DQ7cM8= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug , Paul Elder , Kieran Bingham Subject: [PATCH v5 16/19] libipa: agc_mean_luminance: Add support for additional constraints Date: Fri, 19 Sep 2025 11:40:31 +0200 Message-ID: <20250919094041.183031-17-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250919094041.183031-1-stefan.klug@ideasonboard.com> References: <20250919094041.183031-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" Add support for additional constraints added at runtime. This is for example useful for WDR use cases where you want to add an upper constraint to limit the amount of saturated pixels. Signed-off-by: Stefan Klug Reviewed-by: Paul Elder Reviewed-by: Kieran Bingham --- Changes in v5: - Collected tag Changes in v4: - Added missing docs for the constraints parameter - Collected tag Changes in v3: - Added this patch --- src/ipa/ipu3/algorithms/agc.cpp | 2 +- src/ipa/libipa/agc_mean_luminance.cpp | 17 +++++++++++++---- src/ipa/libipa/agc_mean_luminance.h | 3 ++- src/ipa/mali-c55/algorithms/agc.cpp | 3 ++- src/ipa/rkisp1/algorithms/agc.cpp | 4 ++-- 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp index da045640d569..b0d89541da85 100644 --- a/src/ipa/ipu3/algorithms/agc.cpp +++ b/src/ipa/ipu3/algorithms/agc.cpp @@ -117,7 +117,7 @@ int Agc::configure(IPAContext &context, /* \todo Run this again when FrameDurationLimits is passed in */ setLimits(minExposureTime_, maxExposureTime_, minAnalogueGain_, - maxAnalogueGain_); + maxAnalogueGain_, {}); resetFrameCount(); return 0; diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp index 45eba97516f3..64f36bd75dd2 100644 --- a/src/ipa/libipa/agc_mean_luminance.cpp +++ b/src/ipa/libipa/agc_mean_luminance.cpp @@ -7,6 +7,7 @@ #include "agc_mean_luminance.h" +#include #include #include @@ -408,16 +409,20 @@ int AgcMeanLuminance::parseTuningData(const YamlObject &tuningData) * \param[in] maxExposureTime Maximum ewposure time to allow * \param[in] minGain Minimum gain to allow * \param[in] maxGain Maximum gain to allow + * \param[in] constraints Additional constraints to apply * * This function calls \ref ExposureModeHelper::setLimits() for each * ExposureModeHelper that has been created for this class. */ void AgcMeanLuminance::setLimits(utils::Duration minExposureTime, utils::Duration maxExposureTime, - double minGain, double maxGain) + double minGain, double maxGain, + std::vector constraints) { for (auto &[id, helper] : exposureModeHelpers_) helper->setLimits(minExposureTime, maxExposureTime, minGain, maxGain); + + additionalConstraints_ = std::move(constraints); } /** @@ -495,8 +500,7 @@ double AgcMeanLuminance::constraintClampGain(uint32_t constraintModeIndex, const Histogram &hist, double gain) { - std::vector &constraints = constraintModes_[constraintModeIndex]; - for (const AgcConstraint &constraint : constraints) { + auto applyConstraint = [&gain, &hist](const AgcConstraint &constraint) { double newGain = constraint.yTarget * hist.bins() / hist.interQuantileMean(constraint.qLo, constraint.qHi); @@ -515,7 +519,12 @@ double AgcMeanLuminance::constraintClampGain(uint32_t constraintModeIndex, << newGain; gain = newGain; } - } + }; + + std::vector &constraints = constraintModes_[constraintModeIndex]; + std::for_each(constraints.begin(), constraints.end(), applyConstraint); + + std::for_each(additionalConstraints_.begin(), additionalConstraints_.end(), applyConstraint); return gain; } diff --git a/src/ipa/libipa/agc_mean_luminance.h b/src/ipa/libipa/agc_mean_luminance.h index 950b7b893754..d7ec548e3e58 100644 --- a/src/ipa/libipa/agc_mean_luminance.h +++ b/src/ipa/libipa/agc_mean_luminance.h @@ -51,7 +51,7 @@ public: } void setLimits(utils::Duration minExposureTime, utils::Duration maxExposureTime, - double minGain, double maxGain); + double minGain, double maxGain, std::vector constraints); std::map> constraintModes() { @@ -97,6 +97,7 @@ private: utils::Duration filteredExposure_; double relativeLuminanceTarget_; + std::vector additionalConstraints_; std::map> constraintModes_; std::map> exposureModeHelpers_; ControlInfoMap::Map controls_; diff --git a/src/ipa/mali-c55/algorithms/agc.cpp b/src/ipa/mali-c55/algorithms/agc.cpp index 88f8664c9823..f60fddac3f04 100644 --- a/src/ipa/mali-c55/algorithms/agc.cpp +++ b/src/ipa/mali-c55/algorithms/agc.cpp @@ -173,7 +173,8 @@ int Agc::configure(IPAContext &context, setLimits(context.configuration.agc.minShutterSpeed, context.configuration.agc.maxShutterSpeed, context.configuration.agc.minAnalogueGain, - context.configuration.agc.maxAnalogueGain); + context.configuration.agc.maxAnalogueGain, + {}); resetFrameCount(); diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index d0337fd0027f..d1b6bb7196f4 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -206,7 +206,7 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo) setLimits(context.configuration.sensor.minExposureTime, context.configuration.sensor.maxExposureTime, context.configuration.sensor.minAnalogueGain, - context.configuration.sensor.maxAnalogueGain); + context.configuration.sensor.maxAnalogueGain, {}); resetFrameCount(); @@ -590,7 +590,7 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, maxAnalogueGain = frameContext.agc.gain; } - setLimits(minExposureTime, maxExposureTime, minAnalogueGain, maxAnalogueGain); + setLimits(minExposureTime, maxExposureTime, minAnalogueGain, maxAnalogueGain, {}); /* * The Agc algorithm needs to know the effective exposure value that was