From patchwork Thu Jul 23 15:43:01 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: 27467 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 EBE82C3303 for ; Thu, 23 Jul 2026 15:43:58 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7873867F3C; Thu, 23 Jul 2026 17:43:58 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="kgoShcmT"; 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 E5FB467EE0 for ; Thu, 23 Jul 2026 17:43:34 +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 10AB41C37 for ; Thu, 23 Jul 2026 17:42:34 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1784821354; bh=2gBIBSGVZe6CFk459kjlDy3CLc4okzrbkmA9hkrsVDY=; h=From:To:Subject:Date:In-Reply-To:References:From; b=kgoShcmTyS5HuuxbuHzzyAZ6RVX4Fm/Mm0GgjPVTkKyFPIOB9+Nkol6dZCSiV0zEW rRoUkP2nlVf3vs/AKEvj52YMD/XW6wBsmaZZYH4O6XTVeTmu4ECUFE0KdGkT/adXpw KxFIXEmHHEyyeYHuEYZ2tnD2+FlGyoBVBNqQDRvU= From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= To: libcamera-devel@lists.libcamera.org Subject: [RFC PATCH v2 18/43] ipa: libipa: agc_mean_luminance: Remove persistent params Date: Thu, 23 Jul 2026 17:43:01 +0200 Message-ID: <20260723154327.1357866-19-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" Remove `set{Lux,ExposureCompensation}()` and pass them via `Params`. Signed-off-by: Barnabás Pőcze --- src/ipa/libipa/agc_mean_luminance.cpp | 62 +++++++++++---------------- src/ipa/libipa/agc_mean_luminance.h | 20 ++------- src/ipa/rkisp1/algorithms/agc.cpp | 7 ++- 3 files changed, 31 insertions(+), 58 deletions(-) diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp index d25b1e8322..38c9588e46 100644 --- a/src/ipa/libipa/agc_mean_luminance.cpp +++ b/src/ipa/libipa/agc_mean_luminance.cpp @@ -178,8 +178,7 @@ static constexpr unsigned int kDefaultLuxLevel = 500; */ AgcMeanLuminance::AgcMeanLuminance() - : filteredExposure_(0s), luxWarningEnabled_(true), - exposureCompensation_(1.0), frameCount_(0), lux_(0) + : filteredExposure_(0s), luxWarningEnabled_(true), frameCount_(0) { } @@ -441,25 +440,6 @@ int AgcMeanLuminance::parseTuningData(const ValueNode &tuningData) return parseExposureModes(tuningData); } -/** - * \fn AgcMeanLuminance::setExposureCompensation() - * \brief Set the exposure compensation value - * \param[in] gain The exposure compensation gain - * - * This function sets the exposure compensation value to be used in the - * AGC calculations. It is expressed as gain instead of EV. - */ - -/** - * \fn AgcMeanLuminance::setLux(int lux) - * \brief Set the lux level - * \param[in] lux The lux level - * - * This function sets the lux level to be used in the AGC calculations. A value - * of 0 means no measurement and a default value of \a kDefaultLuxLevel is used - * if necessary. - */ - /** * \brief Set the ExposureModeHelper limits for this class * \param[in] minExposureTime Minimum exposure time to allow @@ -530,26 +510,23 @@ double AgcMeanLuminance::estimateInitialGain(const Traits &traits, double yTarge /** * \brief Clamp gain within the bounds of a defined constraint - * \param[in] constraintModeIndex The index of the constraint to adhere to - * \param[in] hist A histogram over which to calculate inter-quantile means + * \param[in] params The set of parameters for the calculation * \param[in] gain The gain to clamp * * \return The gain clamped within the constraint bounds */ -double AgcMeanLuminance::constraintClampGain(uint32_t constraintModeIndex, - const Histogram &hist, - double gain) const +double AgcMeanLuminance::constraintClampGain(const Params ¶ms, double gain) const { - auto applyConstraint = [this, &gain, &hist](const AgcConstraint &constraint) { - double lux = lux_; + auto applyConstraint = [&](const AgcConstraint &constraint) { + double lux = params.lux; - if (relativeLuminanceTarget_.size() > 1 && lux_ == 0) + if (relativeLuminanceTarget_.size() > 1 && lux == 0) lux = kDefaultLuxLevel; double target = constraint.yTarget.eval( constraint.yTarget.domain().clamp(lux)); - double newGain = target * hist.bins() / - hist.interQuantileMean(constraint.qLo, constraint.qHi); + double newGain = target * params.yHist.bins() / + params.yHist.interQuantileMean(constraint.qLo, constraint.qHi); if (constraint.bound == AgcConstraint::Bound::Lower && newGain > gain) { @@ -568,7 +545,7 @@ double AgcMeanLuminance::constraintClampGain(uint32_t constraintModeIndex, } }; - const std::vector &constraints = constraintModes_.at(constraintModeIndex); + const std::vector &constraints = constraintModes_.at(params.constraintModeIndex); std::for_each(constraints.begin(), constraints.end(), applyConstraint); std::for_each(additionalConstraints_.begin(), additionalConstraints_.end(), applyConstraint); @@ -578,15 +555,16 @@ double AgcMeanLuminance::constraintClampGain(uint32_t constraintModeIndex, /** * \brief Get the currently effective y target + * \param[in] lux The effective lux value + * \param[in] exposureCompensation The exposure compensation value * * This function returns the current y target including exposure compensation. * * \return The y target value */ -double AgcMeanLuminance::effectiveYTarget() const +double AgcMeanLuminance::effectiveYTarget(double lux, double exposureCompensation) const { - double lux = lux_; - if (relativeLuminanceTarget_.size() > 1 && lux_ == 0) { + if (relativeLuminanceTarget_.size() > 1 && lux == 0) { /* * Warn after a few frames if there is still no lux measurement * available. The number of 10 is chosen a bit arbitrarily. It @@ -610,7 +588,7 @@ double AgcMeanLuminance::effectiveYTarget() const double luminanceTarget = relativeLuminanceTarget_.eval( relativeLuminanceTarget_.domain().clamp(lux)); - return std::min(luminanceTarget * exposureCompensation_, + return std::min(luminanceTarget * exposureCompensation, kMaxRelativeLuminanceTarget); } @@ -665,6 +643,14 @@ utils::Duration AgcMeanLuminance::filterExposure(utils::Duration exposureValue) * * \var AgcMeanLuminance::Params::exposureModeIndex * \brief The index of the exposure mode to use + * + * \var AgcMeanLuminance::Params::lux + * \brief The lux level to be used in the AGC calculations. A value of 0 means no + * measurement and a default value of \a kDefaultLuxLevel is used if necessary. + * + * \var AgcMeanLuminance::Params::exposureCompensation + * \brief The exposure compensation value to be used in the AGC calculations. + * It is expressed as gain instead of EV. */ /** @@ -696,7 +682,7 @@ AgcMeanLuminance::calculateNewEv(const Params ¶ms) */ ExposureModeHelper &exposureModeHelper = exposureModeHelpers_.at(params.exposureModeIndex); - double yTarget = effectiveYTarget(); + double yTarget = effectiveYTarget(params.lux, params.exposureCompensation); if (params.effectiveExposureValue == 0s) { LOG(AgcMeanLuminance, Error) @@ -711,7 +697,7 @@ AgcMeanLuminance::calculateNewEv(const Params ¶ms) } double gain = estimateInitialGain(params.traits, yTarget); - gain = constraintClampGain(params.constraintModeIndex, params.yHist, gain); + gain = constraintClampGain(params, gain); /* * We don't check whether we're already close to the target, because diff --git a/src/ipa/libipa/agc_mean_luminance.h b/src/ipa/libipa/agc_mean_luminance.h index 6418fe2e65..5e986be008 100644 --- a/src/ipa/libipa/agc_mean_luminance.h +++ b/src/ipa/libipa/agc_mean_luminance.h @@ -50,16 +50,6 @@ public: void configure(utils::Duration lineDuration, const CameraSensorHelper *sensorHelper); int parseTuningData(const ValueNode &tuningData); - void setExposureCompensation(double gain) - { - exposureCompensation_ = gain; - } - - void setLux(unsigned int lux) - { - lux_ = lux; - } - void setLimits(utils::Duration minExposureTime, utils::Duration maxExposureTime, double minGain, double maxGain, std::vector constraints); @@ -84,6 +74,8 @@ public: utils::Duration effectiveExposureValue; uint32_t constraintModeIndex; uint32_t exposureModeIndex; + double lux = 0; + double exposureCompensation = 1; }; struct Result : ExposureModeHelper::Result { @@ -92,7 +84,7 @@ public: [[nodiscard]] Result calculateNewEv(const Params ¶ms); - double effectiveYTarget() const; + double effectiveYTarget(double lux, double exposureCompensation) const; void resetFrameCount() { @@ -105,17 +97,13 @@ private: int parseConstraintModes(const ValueNode &tuningData); int parseExposureModes(const ValueNode &tuningData); double estimateInitialGain(const Traits &traits, double yTarget) const; - double constraintClampGain(uint32_t constraintModeIndex, - const Histogram &hist, - double gain) const; + double constraintClampGain(const Params ¶ms, double gain) const; utils::Duration filterExposure(utils::Duration exposureValue); utils::Duration filteredExposure_; mutable bool luxWarningEnabled_; - double exposureCompensation_; Pwl relativeLuminanceTarget_; uint64_t frameCount_; - unsigned int lux_; std::vector additionalConstraints_; std::map> constraintModes_; diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index 8ed9d7ea6d..fc228452c3 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -294,7 +294,7 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo) context.configuration.sensor.minAnalogueGain, context.configuration.sensor.maxAnalogueGain, {}); - context.activeState.agc.automatic.yTarget = agc_.effectiveYTarget(); + context.activeState.agc.automatic.yTarget = agc_.effectiveYTarget(0, 1); agc_.resetFrameCount(); @@ -717,9 +717,6 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, Histogram hist({ params->hist.hist_bins, context.hw.numHistogramBins }, [](uint32_t x) { return x >> 4; }); - agc_.setExposureCompensation(pow(2.0, frameContext.agc.exposureValue)); - agc_.setLux(frameContext.lux.lux); - const auto &newEv = agc_.calculateNewEv({ .traits = AgcTraits{ { params->ae.exp_mean, context.hw.numAeCells }, @@ -729,6 +726,8 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, .effectiveExposureValue = effectiveExposureValue, .constraintModeIndex = frameContext.agc.constraintMode, .exposureModeIndex = frameContext.agc.exposureMode, + .lux = frameContext.lux.lux, + .exposureCompensation = pow(2.0, frameContext.agc.exposureValue), }); LOG(RkISP1Agc, Debug)