From patchwork Thu Jul 23 15:42:57 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 27464 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 8F16FC3301 for ; Thu, 23 Jul 2026 15:43:54 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 16F2267F20; Thu, 23 Jul 2026 17:43:54 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="JgtLzCLC"; 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 012FA67EC7 for ; Thu, 23 Jul 2026 17:43:33 +0200 (CEST) Received: from pb-laptop.local (185.182.215.156.nat.pool.zt.hu [185.182.215.156]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 221CA1C37 for ; Thu, 23 Jul 2026 17:42:33 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1784821353; bh=0guaNOTTnXwSaZhS+tOKH3iYPgTi94jBtetlKj0Ptcw=; h=From:To:Subject:Date:In-Reply-To:References:From; b=JgtLzCLCt8geo4TIbtBYLFQFumZcSjFCjinIzP9SDdxuY1ZFWYn0dm/30tw3MvABS LbN28ei/gaNdrYdyKjxge7RViT+CBdlNBjYMoxisaFwjKBTD6tgAGxAsbn+7RqnmzC MSbB483K6AED4TDIf+hGPSZumW0RKZMM5MuTCCg0= From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= To: libcamera-devel@lists.libcamera.org Subject: [RFC PATCH v2 14/43] ipa: libipa: agc_mean_luminance: calculateNewEv(): Collect params Date: Thu, 23 Jul 2026 17:42:57 +0200 Message-ID: <20260723154327.1357866-15-barnabas.pocze@ideasonboard.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260723154327.1357866-1-barnabas.pocze@ideasonboard.com> References: <20260723154327.1357866-1-barnabas.pocze@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 a new type that contains all parameters for the `calculateNewEv()` function. Signed-off-by: Barnabás Pőcze --- src/ipa/ipu3/algorithms/agc.cpp | 28 +++++++++-------- src/ipa/libipa/agc_mean_luminance.cpp | 44 ++++++++++++++++----------- src/ipa/libipa/agc_mean_luminance.h | 12 ++++++-- src/ipa/mali-c55/algorithms/agc.cpp | 12 +++++--- src/ipa/rkisp1/algorithms/agc.cpp | 18 ++++++----- 5 files changed, 68 insertions(+), 46 deletions(-) diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp index a919418d69..ac5b6e7513 100644 --- a/src/ipa/ipu3/algorithms/agc.cpp +++ b/src/ipa/ipu3/algorithms/agc.cpp @@ -236,22 +236,24 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, * frameContext.sensor.exposure; double analogueGain = frameContext.sensor.gain; utils::Duration effectiveExposureValue = exposureTime * analogueGain; - AgcTraits agcTraits{ - rgbTriples_, - {{ - context.activeState.awb.gains.red, - context.activeState.awb.gains.blue, - context.activeState.awb.gains.green, - }}, - bdsGrid_, - }; utils::Duration newExposureTime; double aGain, qGain, dGain; - std::tie(newExposureTime, aGain, qGain, dGain) = - agc_.calculateNewEv(context.activeState.agc.constraintMode, - context.activeState.agc.exposureMode, hist, - effectiveExposureValue, agcTraits); + std::tie(newExposureTime, aGain, qGain, dGain) = agc_.calculateNewEv({ + .traits = AgcTraits{ + rgbTriples_, + {{ + context.activeState.awb.gains.red, + context.activeState.awb.gains.blue, + context.activeState.awb.gains.green, + }}, + bdsGrid_, + }, + .yHist = hist, + .effectiveExposureValue = effectiveExposureValue, + .constraintModeIndex = context.activeState.agc.constraintMode, + .exposureModeIndex = context.activeState.agc.exposureMode, + }); LOG(IPU3Agc, Debug) << "Divided up exposure time, analogue gain and digital gain are " diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp index 31636159a2..083d67eb70 100644 --- a/src/ipa/libipa/agc_mean_luminance.cpp +++ b/src/ipa/libipa/agc_mean_luminance.cpp @@ -648,16 +648,30 @@ utils::Duration AgcMeanLuminance::filterExposure(utils::Duration exposureValue) return filteredExposure_; } +/** + * \struct AgcMeanLuminance::Params + * \brief Collection of parameters for the mean luminance AGC algorithm + * + * \var AgcMeanLuminance::Params::traits + * \brief The traits object implementing the necessary functions + * + * \var AgcMeanLuminance::Params::yHist + * \brief A histogram from the ISP statistics to use in constraining the calculated gain + * + * \var AgcMeanLuminance::Params::effectiveExposureValue + * \brief The EV applied to the frame from which the statistics in use derive + * + * \var AgcMeanLuminance::Params::constraintModeIndex + * \brief The index of the constraint mode to use + * + * \var AgcMeanLuminance::Params::exposureModeIndex + * \brief The index of the exposure mode to use + */ + /** * \brief Calculate the new exposure value and split it between exposure time * and gain - * \param[in] constraintModeIndex The index of the current constraint mode - * \param[in] exposureModeIndex The index of the current exposure mode - * \param[in] yHist A Histogram from the ISP statistics to use in constraining - * the calculated gain - * \param[in] effectiveExposureValue The EV applied to the frame from which the - * statistics in use derive - * \param[in] traits The traits object implementing the necessary functions + * \param[in] params The set of parameters for the calculation * * Calculate a new exposure value to try to obtain the target. The calculated * exposure value is filtered to prevent rapid changes from frame to frame, and @@ -667,20 +681,16 @@ utils::Duration AgcMeanLuminance::filterExposure(utils::Duration exposureValue) * gain */ std::tuple -AgcMeanLuminance::calculateNewEv(uint32_t constraintModeIndex, - uint32_t exposureModeIndex, - const Histogram &yHist, - utils::Duration effectiveExposureValue, - const Traits &traits) +AgcMeanLuminance::calculateNewEv(const Params ¶ms) { /* * The pipeline handler should validate that we have received an allowed * value for AeExposureMode. */ ExposureModeHelper &exposureModeHelper = - exposureModeHelpers_.at(exposureModeIndex); + exposureModeHelpers_.at(params.exposureModeIndex); - if (effectiveExposureValue == 0s) { + if (params.effectiveExposureValue == 0s) { LOG(AgcMeanLuminance, Error) << "Effective exposure value is 0. This is a bug in AGC " "and must be fixed for proper operation."; @@ -692,8 +702,8 @@ AgcMeanLuminance::calculateNewEv(uint32_t constraintModeIndex, return exposureModeHelper.splitExposure(10ms); } - double gain = estimateInitialGain(traits); - gain = constraintClampGain(constraintModeIndex, yHist, gain); + double gain = estimateInitialGain(params.traits); + gain = constraintClampGain(params.constraintModeIndex, params.yHist, gain); /* * We don't check whether we're already close to the target, because @@ -702,7 +712,7 @@ AgcMeanLuminance::calculateNewEv(uint32_t constraintModeIndex, * pass through the splitExposure() function. */ - utils::Duration newExposureValue = effectiveExposureValue * gain; + utils::Duration newExposureValue = params.effectiveExposureValue * gain; /* * We filter the exposure value to make sure changes are not too jarring diff --git a/src/ipa/libipa/agc_mean_luminance.h b/src/ipa/libipa/agc_mean_luminance.h index d5425cd20b..eb9d6fec2b 100644 --- a/src/ipa/libipa/agc_mean_luminance.h +++ b/src/ipa/libipa/agc_mean_luminance.h @@ -79,10 +79,16 @@ public: return controls_; } + struct Params { + const Traits &traits; + const Histogram &yHist; + utils::Duration effectiveExposureValue; + uint32_t constraintModeIndex; + uint32_t exposureModeIndex; + }; + std::tuple - calculateNewEv(uint32_t constraintModeIndex, uint32_t exposureModeIndex, - const Histogram &yHist, utils::Duration effectiveExposureValue, - const Traits &traits); + calculateNewEv(const Params ¶ms); double effectiveYTarget() const; diff --git a/src/ipa/mali-c55/algorithms/agc.cpp b/src/ipa/mali-c55/algorithms/agc.cpp index 29b7c66159..fb97b87c6e 100644 --- a/src/ipa/mali-c55/algorithms/agc.cpp +++ b/src/ipa/mali-c55/algorithms/agc.cpp @@ -331,14 +331,16 @@ void Agc::process(IPAContext &context, double analogueGain = frameContext.agc.sensorGain; utils::Duration currentShutter = exposure * configuration.sensor.lineDuration; utils::Duration effectiveExposureValue = currentShutter * analogueGain; - AgcTraits agcTraits(statistics_); utils::Duration shutterTime; double aGain, qGain, dGain; - std::tie(shutterTime, aGain, qGain, dGain) = - agc_.calculateNewEv(activeState.agc.constraintMode, - activeState.agc.exposureMode, statistics_.yHist, - effectiveExposureValue, agcTraits); + std::tie(shutterTime, aGain, qGain, dGain) = agc_.calculateNewEv({ + .traits = AgcTraits(statistics_), + .yHist = statistics_.yHist, + .effectiveExposureValue = effectiveExposureValue, + .constraintModeIndex = activeState.agc.constraintMode, + .exposureModeIndex = activeState.agc.exposureMode, + }); LOG(MaliC55Agc, Debug) << "Divided up shutter, analogue gain and digital gain are " diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index 129f5be2a5..8b4bcbd71b 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -716,20 +716,22 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, /* The lower 4 bits are fractional and meant to be discarded. */ Histogram hist({ params->hist.hist_bins, context.hw.numHistogramBins }, [](uint32_t x) { return x >> 4; }); - AgcTraits agcTraits{ - { params->ae.exp_mean, context.hw.numAeCells }, - meteringModes_.at(frameContext.agc.meteringMode), - }; agc_.setExposureCompensation(pow(2.0, frameContext.agc.exposureValue)); agc_.setLux(frameContext.lux.lux); utils::Duration newExposureTime; double aGain, qGain, dGain; - std::tie(newExposureTime, aGain, qGain, dGain) = - agc_.calculateNewEv(frameContext.agc.constraintMode, - frameContext.agc.exposureMode, - hist, effectiveExposureValue, agcTraits); + std::tie(newExposureTime, aGain, qGain, dGain) = agc_.calculateNewEv({ + .traits = AgcTraits{ + { params->ae.exp_mean, context.hw.numAeCells }, + meteringModes_.at(frameContext.agc.meteringMode), + }, + .yHist = hist, + .effectiveExposureValue = effectiveExposureValue, + .constraintModeIndex = frameContext.agc.constraintMode, + .exposureModeIndex = frameContext.agc.exposureMode, + }); LOG(RkISP1Agc, Debug) << "Divided up exposure time, analogue gain, quantization gain"