From patchwork Mon Sep 14 14:02:53 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 28284 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 9B94FC336A for ; Mon, 14 Sep 2026 14:05:13 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id ECB9F68722; Mon, 14 Sep 2026 16:05:12 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="donrIXDu"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 373AD686FC for ; Mon, 14 Sep 2026 16:05:11 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:a279:75fa:1f6c:7f40]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 33599929; Mon, 14 Sep 2026 16:03:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1789394611; bh=raQ/c+eS4u2LKeTBRlo0CbtF8LZEQRdQt+IB7gIc3aw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=donrIXDu2aj/zpupFVHJQE24ffk/Moex5nMv++fYxYkckY+6FFGiTh6gS8k771HhE q0/Br7pApq/DcKAh5ZzKI1bDeA11IGhGUccINK1V8kzKQ+cJf/6K1VgA3pz+zHjOZT 6FBqLNBoKN4BkLfQSjqjjP0Qa7mCYIfKz784l6KA= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v3 40/41] libipa: agc: Make startup frames and regulations speed configurable Date: Mon, 14 Sep 2026 16:02:53 +0200 Message-ID: <20260914140309.3354666-41-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260914140309.3354666-1-stefan.klug@ideasonboard.com> References: <20260914140309.3354666-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 rkisp1 has now a good synchronization between sensor settings/isp params and stats. It can therefore benefit from a faster regulation. To do that without breaking other IPAs that use AgcMeanLuminance, move regulation speed and startup frames into configuration parameters that can be set at runtime. Signed-off-by: Stefan Klug --- src/ipa/libipa/agc.cpp | 14 ++++++++++++++ src/ipa/libipa/agc.h | 2 ++ src/ipa/libipa/agc_mean_luminance.cpp | 25 +++++++++++++++++++++---- src/ipa/libipa/agc_mean_luminance.h | 3 +++ 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/ipa/libipa/agc.cpp b/src/ipa/libipa/agc.cpp index a2438cb49d1b..5c06ca475926 100644 --- a/src/ipa/libipa/agc.cpp +++ b/src/ipa/libipa/agc.cpp @@ -262,6 +262,15 @@ namespace agc { * control only, without automatic adjustments. In this mode statistics * must not be provided to AgcAlgorithm::process(), and ExposureTimeMode * and AnalogueGainMode will only advertise manual control. + * + * \var AgcAlgorithm::ConfigurationParams::numStartupFrames + * \brief Number of startup frames + * + * During these frame the regulation speed is set to 1.0 to reach faster + * convergence. + * + * \var AgcAlgorithm::ConfigurationParams::regulationSpeed + * \brief The regulation speed */ /** @@ -513,6 +522,11 @@ int AgcAlgorithm::configure(agc::Session &session, agc::ActiveState &state, state.automatic.yTarget = impl.effectiveYTarget(0, 1); impl.configure(session.lineDuration, sensor_); + if (config.numStartupFrames) + impl.numStartupFrames_ = config.numStartupFrames.value(); + + if (config.regulationSpeed) + impl.regulationSpeed_ = config.regulationSpeed.value(); if (!session.autoAllowed) return; diff --git a/src/ipa/libipa/agc.h b/src/ipa/libipa/agc.h index 4914c9cee24b..a9140e7a3e61 100644 --- a/src/ipa/libipa/agc.h +++ b/src/ipa/libipa/agc.h @@ -126,6 +126,8 @@ public: const ControlInfoMap &sensorControls; ControlInfoMap::Map &ctrlMap; bool autoAllowed = true; + std::optional numStartupFrames = std::nullopt; + std::optional regulationSpeed = std::nullopt; }; struct ProcessParams { diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp index 72833247c5fd..3244e631517b 100644 --- a/src/ipa/libipa/agc_mean_luminance.cpp +++ b/src/ipa/libipa/agc_mean_luminance.cpp @@ -37,7 +37,7 @@ namespace ipa { * Number of frames for which to run the algorithm at full speed, before slowing * down to prevent large and jarring changes in exposure from frame to frame. */ -static constexpr uint32_t kNumStartupFrames = 10; +static constexpr uint32_t kDefaultNumStartupFrames = 10; /* * Default relative luminance target @@ -178,7 +178,8 @@ static constexpr unsigned int kDefaultLuxLevel = 500; */ AgcMeanLuminance::AgcMeanLuminance() - : filteredExposure_(0s), luxWarningEnabled_(true), frameCount_(0) + : numStartupFrames_(kDefaultNumStartupFrames), regulationSpeed_(0.2), + filteredExposure_(0s), luxWarningEnabled_(true), frameCount_(0) { } @@ -587,10 +588,10 @@ double AgcMeanLuminance::effectiveYTarget(double lux, double exposureCompensatio */ utils::Duration AgcMeanLuminance::filterExposure(utils::Duration exposureValue) { - double speed = 0.2; + double speed = regulationSpeed_; /* Adapt instantly if we are in startup phase. */ - if (frameCount_ < kNumStartupFrames) + if (frameCount_ < numStartupFrames_) speed = 1.0; /* @@ -701,6 +702,22 @@ AgcMeanLuminance::calculateNewEv(const Params ¶ms) return { exposureModeHelper.splitExposure(newExposureValue), yTarget }; } +/** + * \var AgcMeanLuminance::numStartupFrames_ + * \brief The number of startup frames + * + * During this number of frames after startup, the regulation is very aggressive + * to reach the target value within one or two cycles. + * + * \var AgcMeanLuminance::regulationSpeed_ + * The regulation speed. This controls the speed at which new target values are + * applied. The new target value is calculated as: + * + * \code{.unparsed} + * value = target * speed + oldValue * (1.0 - speed) + * \endcode + */ + } /* namespace ipa */ } /* namespace libcamera */ diff --git a/src/ipa/libipa/agc_mean_luminance.h b/src/ipa/libipa/agc_mean_luminance.h index f799618ffc2c..b7df7ea03702 100644 --- a/src/ipa/libipa/agc_mean_luminance.h +++ b/src/ipa/libipa/agc_mean_luminance.h @@ -79,6 +79,9 @@ public: double effectiveYTarget(double lux, double exposureCompensation) const; + uint32_t numStartupFrames_; + double regulationSpeed_; + private: int parseRelativeLuminanceTarget(const ValueNode &tuningData); int parseConstraint(const ValueNode &modeDict, int32_t id);