From patchwork Thu Jul 23 15:42:59 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: 27465 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 60A1CBDE17 for ; Thu, 23 Jul 2026 15:43:56 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E804467F31; Thu, 23 Jul 2026 17:43:55 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="UG9UH4+A"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6BBA867EDE 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 8FF191C37 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=BUor4FFuTFvStj6cEasyaVz0CjfD/wopx30LsQF2m+M=; h=From:To:Subject:Date:In-Reply-To:References:From; b=UG9UH4+AUCKGHQ3I0xKbKaMAiEv7NOTmeKChmlOmmVCmJdeVcA8YXypKiIkp94ab4 OroH3F41aPDWLAMBMVYVHEkrIBZ1yUkP7jHRMu1q/HjuZ6edZGWEU4VHzkmWu0YyQy +0RFW7HyTLpOd7x+EkCve7qZVXYoPkdp+bkYZIcI= From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= To: libcamera-devel@lists.libcamera.org Subject: [RFC PATCH v2 16/43] ipa: libipa: agc_mean_luminance: calculateNewEv(): Collect results Date: Thu, 23 Jul 2026 17:42:59 +0200 Message-ID: <20260723154327.1357866-17-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 gives proper names to the returned quantities instead of just using an `std::tuple`. Signed-off-by: Barnabás Pőcze --- src/ipa/ipu3/algorithms/agc.cpp | 10 ++++------ src/ipa/libipa/agc_mean_luminance.cpp | 11 ++++++++--- src/ipa/libipa/agc_mean_luminance.h | 7 ++++--- src/ipa/libipa/exposure_mode_helper.cpp | 19 ++++++++++++++++++- src/ipa/libipa/exposure_mode_helper.h | 11 ++++++++--- src/ipa/mali-c55/algorithms/agc.cpp | 10 ++++------ src/ipa/rkisp1/algorithms/agc.cpp | 16 +++++++--------- 7 files changed, 53 insertions(+), 31 deletions(-) diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp index ac5b6e7513..e74db62960 100644 --- a/src/ipa/ipu3/algorithms/agc.cpp +++ b/src/ipa/ipu3/algorithms/agc.cpp @@ -237,9 +237,7 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, double analogueGain = frameContext.sensor.gain; utils::Duration effectiveExposureValue = exposureTime * analogueGain; - utils::Duration newExposureTime; - double aGain, qGain, dGain; - std::tie(newExposureTime, aGain, qGain, dGain) = agc_.calculateNewEv({ + const auto &newEv = agc_.calculateNewEv({ .traits = AgcTraits{ rgbTriples_, {{ @@ -257,12 +255,12 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, LOG(IPU3Agc, Debug) << "Divided up exposure time, analogue gain and digital gain are " - << newExposureTime << ", " << aGain << " and " << dGain; + << newEv.exposureTime << ", " << newEv.analogueGain << " and " << newEv.digitalGain; IPAActiveState &activeState = context.activeState; /* Update the estimated exposure time and gain. */ - activeState.agc.exposure = newExposureTime / context.configuration.sensor.lineDuration; - activeState.agc.gain = aGain; + activeState.agc.exposure = newEv.exposureTime / context.configuration.sensor.lineDuration; + activeState.agc.gain = newEv.analogueGain; metadata.set(controls::AnalogueGain, frameContext.sensor.gain); metadata.set(controls::ExposureTime, exposureTime.get()); diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp index e8679c66be..5e12c4b475 100644 --- a/src/ipa/libipa/agc_mean_luminance.cpp +++ b/src/ipa/libipa/agc_mean_luminance.cpp @@ -668,6 +668,11 @@ utils::Duration AgcMeanLuminance::filterExposure(utils::Duration exposureValue) * \brief The index of the exposure mode to use */ +/** + * \struct AgcMeanLuminance::Result + * \brief Collection of results of the mean luminance AGC algorithm + */ + /** * \brief Calculate the new exposure value and split it between exposure time * and gain @@ -680,7 +685,7 @@ utils::Duration AgcMeanLuminance::filterExposure(utils::Duration exposureValue) * \return Tuple of exposure time, analogue gain, quantization gain and digital * gain */ -std::tuple +AgcMeanLuminance::Result AgcMeanLuminance::calculateNewEv(const Params ¶ms) { /* @@ -699,7 +704,7 @@ AgcMeanLuminance::calculateNewEv(const Params ¶ms) * doesn't get stuck with 0 in case the sensor driver allows a * min exposure of 0. */ - return exposureModeHelper.splitExposure(10ms); + return { exposureModeHelper.splitExposure(10ms) }; } double gain = estimateInitialGain(params.traits); @@ -721,7 +726,7 @@ AgcMeanLuminance::calculateNewEv(const Params ¶ms) newExposureValue = filterExposure(newExposureValue); frameCount_++; - return exposureModeHelper.splitExposure(newExposureValue); + return { exposureModeHelper.splitExposure(newExposureValue) }; } /** diff --git a/src/ipa/libipa/agc_mean_luminance.h b/src/ipa/libipa/agc_mean_luminance.h index 9b82d97ab6..aa4c0369ac 100644 --- a/src/ipa/libipa/agc_mean_luminance.h +++ b/src/ipa/libipa/agc_mean_luminance.h @@ -9,7 +9,6 @@ #include #include -#include #include #include @@ -87,8 +86,10 @@ public: uint32_t exposureModeIndex; }; - std::tuple - calculateNewEv(const Params ¶ms); + struct Result : ExposureModeHelper::Result { + }; + + [[nodiscard]] Result calculateNewEv(const Params ¶ms); double effectiveYTarget() const; diff --git a/src/ipa/libipa/exposure_mode_helper.cpp b/src/ipa/libipa/exposure_mode_helper.cpp index 01c5cba8e2..762e27b4fd 100644 --- a/src/ipa/libipa/exposure_mode_helper.cpp +++ b/src/ipa/libipa/exposure_mode_helper.cpp @@ -153,6 +153,23 @@ double ExposureModeHelper::clampGain(double gain, double *quantizationGain) cons return clamped; } +/** + * \struct ExposureModeHelper::Result + * \brief Result of splitExposure() + * + * \var ExposureModeHelper::Result::exposureTime + * \brief The applicable exposure time + * + * \var ExposureModeHelper::Result::analogueGain + * \brief The applicable analogue gain + * + * \var ExposureModeHelper::Result::quantizationGain + * \brief The applicable quantization gain + * + * \var ExposureModeHelper::Result::digitalGain + * \brief The applicable digital gain + */ + /** * \brief Split exposure into exposure time and gain * \param[in] exposure Exposure value @@ -190,7 +207,7 @@ double ExposureModeHelper::clampGain(double gain, double *quantizationGain) cons * \return Tuple of exposure time, analogue gain, quantization gain and digital * gain */ -std::tuple +ExposureModeHelper::Result ExposureModeHelper::splitExposure(utils::Duration exposure) const { ASSERT(maxExposureTime_); diff --git a/src/ipa/libipa/exposure_mode_helper.h b/src/ipa/libipa/exposure_mode_helper.h index 968192ddc5..2bab20f974 100644 --- a/src/ipa/libipa/exposure_mode_helper.h +++ b/src/ipa/libipa/exposure_mode_helper.h @@ -7,7 +7,6 @@ #pragma once -#include #include #include @@ -30,8 +29,14 @@ public: void setLimits(utils::Duration minExposureTime, utils::Duration maxExposureTime, double minGain, double maxGain); - std::tuple - splitExposure(utils::Duration exposure) const; + struct Result { + utils::Duration exposureTime; + double analogueGain; + double quantizationGain; + double digitalGain; + }; + + [[nodiscard]] Result splitExposure(utils::Duration exposure) const; utils::Duration minExposureTime() const { return minExposureTime_; } utils::Duration maxExposureTime() const { return maxExposureTime_; } diff --git a/src/ipa/mali-c55/algorithms/agc.cpp b/src/ipa/mali-c55/algorithms/agc.cpp index fb97b87c6e..821f43e9fd 100644 --- a/src/ipa/mali-c55/algorithms/agc.cpp +++ b/src/ipa/mali-c55/algorithms/agc.cpp @@ -332,9 +332,7 @@ void Agc::process(IPAContext &context, utils::Duration currentShutter = exposure * configuration.sensor.lineDuration; utils::Duration effectiveExposureValue = currentShutter * analogueGain; - utils::Duration shutterTime; - double aGain, qGain, dGain; - std::tie(shutterTime, aGain, qGain, dGain) = agc_.calculateNewEv({ + const auto &newEv = agc_.calculateNewEv({ .traits = AgcTraits(statistics_), .yHist = statistics_.yHist, .effectiveExposureValue = effectiveExposureValue, @@ -344,10 +342,10 @@ void Agc::process(IPAContext &context, LOG(MaliC55Agc, Debug) << "Divided up shutter, analogue gain and digital gain are " - << shutterTime << ", " << aGain << " and " << dGain; + << newEv.exposureTime << ", " << newEv.analogueGain << " and " << newEv.digitalGain; - activeState.agc.automatic.exposure = shutterTime / configuration.sensor.lineDuration; - activeState.agc.automatic.sensorGain = aGain; + activeState.agc.automatic.exposure = newEv.exposureTime / configuration.sensor.lineDuration; + activeState.agc.automatic.sensorGain = newEv.analogueGain; metadata.set(controls::ExposureTime, currentShutter.get()); metadata.set(controls::AnalogueGain, frameContext.agc.sensorGain); diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index 8b4bcbd71b..a4567c8258 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -720,9 +720,7 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, 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({ + const auto &newEv = agc_.calculateNewEv({ .traits = AgcTraits{ { params->ae.exp_mean, context.hw.numAeCells }, meteringModes_.at(frameContext.agc.meteringMode), @@ -735,21 +733,21 @@ void Agc::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, LOG(RkISP1Agc, Debug) << "Divided up exposure time, analogue gain, quantization gain" - << " and digital gain are " << newExposureTime << ", " << aGain - << ", " << qGain << " and " << dGain; + << " and digital gain are " << newEv.exposureTime << ", " << newEv.analogueGain + << ", " << newEv.quantizationGain << " and " << newEv.digitalGain; IPAActiveState &activeState = context.activeState; /* Update the estimated exposure and gain. */ - activeState.agc.automatic.exposure = newExposureTime / lineDuration; - activeState.agc.automatic.gain = aGain; - activeState.agc.automatic.quantizationGain = qGain; + activeState.agc.automatic.exposure = newEv.exposureTime / lineDuration; + activeState.agc.automatic.gain = newEv.analogueGain; + activeState.agc.automatic.quantizationGain = newEv.quantizationGain; activeState.agc.automatic.yTarget = agc_.effectiveYTarget(); /* * Expand the target frame duration so that we do not run faster than * the minimum frame duration when we have short exposures. */ processFrameDuration(context, frameContext, - std::max(frameContext.agc.minFrameDuration, newExposureTime)); + std::max(frameContext.agc.minFrameDuration, newEv.exposureTime)); fillMetadata(context, frameContext, metadata); }