From patchwork Fri Nov 14 14:17:05 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 25062 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 88086C32DB for ; Fri, 14 Nov 2025 14:17:38 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id AC43A60AB7; Fri, 14 Nov 2025 15:17:34 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="p4o2mRgI"; 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 9620160A86 for ; Fri, 14 Nov 2025 15:17:21 +0100 (CET) Received: from [192.168.1.101] (93-61-96-190.ip145.fastwebnet.it [93.61.96.190]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 92FD61A8F; Fri, 14 Nov 2025 15:15:20 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1763129720; bh=Vnj6OMjyGCSUwrfWqA/064JQnBS2550S1SUFuChCM9g=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=p4o2mRgITWDJ8Ifui3RgJk2zYSWoT6XgLJK2UqKSEj68dsIlLqjlyRBAKXb0vJdMr UvQuoN91ISwJynS/IOQ3oWHkbbvYVhHklxGZdrvvN66IewxUmL3WIQfAupYDN5cAOD b92Z9ygPjNBEjgKCojukKGM/Hdcd6BaXGCWd18tE= From: Jacopo Mondi Date: Fri, 14 Nov 2025 15:17:05 +0100 Subject: [PATCH v3 10/19] ipa: libipa: agc: Make Agc::configure() set limits MIME-Version: 1.0 Message-Id: <20251114-exposure-limits-v3-10-b7c07feba026@ideasonboard.com> References: <20251114-exposure-limits-v3-0-b7c07feba026@ideasonboard.com> In-Reply-To: <20251114-exposure-limits-v3-0-b7c07feba026@ideasonboard.com> To: =?utf-8?q?Niklas_S=C3=B6derlund?= , Robert Mader , libcamera-devel@lists.libcamera.org Cc: Jacopo Mondi X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=12196; i=jacopo.mondi@ideasonboard.com; h=from:subject:message-id; bh=Vnj6OMjyGCSUwrfWqA/064JQnBS2550S1SUFuChCM9g=; b=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBpFznrmTYC2+3ozsxraW2Av74ljty4sX4G67t/4 NGUhrkYhdaJAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCaRc56wAKCRByNAaPFqFW PAfxEACVg7z73MD8vMTnTkWJNu+9kHapriY5LLI12IgBO1gWsJFB80qqriBNZ+6CjWXOupB3i7x Mpi/hxqOVsnTjV3rokZpibHje1NfnvPQjr9dy2HX6U0LNVyDVG1jAX8yaTlfYrn2zjnEPpxfkm1 2FFxdidtRMd7+CqO0HfcEZpBTpCAR276mK9QCy5b0j+QtTgpGgXUvfri3+/Q8HCwXIEjGCVhH5v dnV1sdPfzWQ06OTo63bt4i2Okatb5QzMUMLxIUipNHMsHIEy0PCe9PnJDu/Vg/duEfaz/S9Q+w6 5eZRSVcjUI4j/F4ki2G8930/way1Qfkxizi7u8O9dzSob1+faxxLn7Lo1IKIoiOLGlHbNPJiBqq K+wHy2GGgDPsZpLPeurKP/83twlCEiRvaXYHxqy0kvHEPsPRlrQGiT2C2LHR44ygTOZ0j19+0ck bmuSu+eo5Si6XR7F6S5G6H5khYelAZNnzq2YpcF65/vNHv0e6oltEo4O1mo4wmdxd/D/vc/7Dmb tWEAaK6880Xw2g+QixlBkcixQOv0uATK9VscgokvKW080IFi1PQFNhFQN3EbIbNi8r6wznS8t2B jwYjPH5sZDQ1l8ZurssJLECz6mfDnDPDdUKjpcadZ69G+sE5aOO7SViBjLwLjpc8UrDGbSGfk0J L0kM3fL0CEuStjQ== X-Developer-Key: i=jacopo.mondi@ideasonboard.com; a=openpgp; fpr=72392EDC88144A65C701EA9BA5826A2587AD026B 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 AgcMeanLuminance algorithm interface has a 'configure()' and 'setLimits()' API. configure() doesn't actually do much if not initialzing a few variables, and the Mali and IPU3 IPAs do not even call it. Configuring the AGC requires calling setLimits() at configure() time and at run time. In order to prepare to differentiate between configure-time settings of the Agc and run-time handling of dynamic parameters such as the frame duration limits, make the configure() operation initialize the Agc limits and provide an AgcMeanLuminance::SensorConfiguration type for IPAs to be populated with the sensor's default values. The new type mimics the ExposureModeHelper::SensorConfiguration on introduced in the previous patches and both will be removed once all the information there contained will be made available from the CameraSensorHelper. Update all IPAs Agc implementation deriving from AgcMeanLuminance to populate a AgcMeanLuminance::SensorConfiguration and use it in configure(). Signed-off-by: Jacopo Mondi --- src/ipa/ipu3/algorithms/agc.cpp | 14 +++++++-- src/ipa/libipa/agc_mean_luminance.cpp | 56 ++++++++++++++++++++++++++++++--- src/ipa/libipa/agc_mean_luminance.h | 11 ++++++- src/ipa/libipa/exposure_mode_helper.cpp | 20 +++++++----- src/ipa/libipa/exposure_mode_helper.h | 3 +- src/ipa/mali-c55/algorithms/agc.cpp | 16 ++++++---- src/ipa/rkisp1/algorithms/agc.cpp | 15 ++++----- 7 files changed, 105 insertions(+), 30 deletions(-) diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp index 4574f3a1a9cd3f40b1b1402238809ee1a777946d..5c72806dede5f55459bde69ab8cfaebc495c7560 100644 --- a/src/ipa/ipu3/algorithms/agc.cpp +++ b/src/ipa/ipu3/algorithms/agc.cpp @@ -115,9 +115,17 @@ int Agc::configure(IPAContext &context, context.activeState.agc.constraintMode = constraintModes().begin()->first; context.activeState.agc.exposureMode = exposureModeHelpers().begin()->first; - /* \todo Run this again when FrameDurationLimits is passed in */ - setLimits(minExposureTime_, maxExposureTime_, minAnalogueGain_, - maxAnalogueGain_, {}); + AgcMeanLuminance::SensorConfiguration sensorConfig; + sensorConfig.lineDuration = context.configuration.sensor.lineDuration; + sensorConfig.minExposureTime = minExposureTime_; + sensorConfig.maxExposureTime = maxExposureTime_; + sensorConfig.minAnalogueGain = minAnalogueGain_; + sensorConfig.maxAnalogueGain = maxAnalogueGain_; + + AgcMeanLuminance::configure(sensorConfig, context.camHelper.get()); + + /* \todo Update AGC limits when FrameDurationLimits is passed in */ + resetFrameCount(); return 0; diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp index 64f36bd75dd213671b5a2e6810245096ed001f21..512e153791f5b98da01efad6675192a5358e7698 100644 --- a/src/ipa/libipa/agc_mean_luminance.cpp +++ b/src/ipa/libipa/agc_mean_luminance.cpp @@ -95,6 +95,35 @@ static constexpr double kMaxRelativeLuminanceTarget = 0.95; * \brief The luminance target for the constraint */ +/** + * \struct AgcMeanLuminance::SensorConfiguration + * \brief The sensor configuration parameters + * + * This structure collects the sensor configuration parameters which need + * to be provided to the AGC algorithm at configure() time. + * + * Each time configure() is called the sensor configuration need to be updated + * with new parameters. + * + * \todo Remove it once all the information are available from the + * CameraSensorHelper. + * + * \var AgcMeanLuminance::SensorConfiguration::lineDuration + * \brief The line duration in microseconds + * + * \var AgcMeanLuminance::SensorConfiguration::minExposureTime + * \brief The sensor minimum exposure time in microseconds + * + * \var AgcMeanLuminance::SensorConfiguration::maxExposureTime + * \brief The sensor maximum exposure time in microseconds + * + * \var AgcMeanLuminance::SensorConfiguration::minAnalogueGain + * \brief The sensor minimum analogue gain absolute value + * + * \var AgcMeanLuminance::SensorConfiguration::maxAnalogueGain + * \brief The sensor maximum analogue gain absolute value + */ + /** * \class AgcMeanLuminance * \brief A mean-based auto-exposure algorithm @@ -314,17 +343,34 @@ int AgcMeanLuminance::parseExposureModes(const YamlObject &tuningData) /** * \brief Configure the exposure mode helpers - * \param[in] lineDuration The sensor line length + * \param[in] config The sensor configuration * \param[in] sensorHelper The sensor helper * - * This function configures the exposure mode helpers so they can correctly + * This function configures the exposure mode helpers by providing them the + * sensor configuration parameters and the sensor helper, so they can correctly * take quantization effects into account. */ -void AgcMeanLuminance::configure(utils::Duration lineDuration, +void AgcMeanLuminance::configure(const SensorConfiguration &config, const CameraSensorHelper *sensorHelper) { - for (auto &[id, helper] : exposureModeHelpers_) - helper->configure(lineDuration, sensorHelper); + for (auto &[id, helper] : exposureModeHelpers_) { + /* + * Translate from the SensorConfiguration to the + * ExposureModeHelper::SensorConfiguration. + * + * These are just place holders before all the information are + * available from the sensor helper. + */ + + ExposureModeHelper::SensorConfiguration sensorConfig; + sensorConfig.lineDuration_ = config.lineDuration; + sensorConfig.minExposureTime_ = config.minExposureTime; + sensorConfig.maxExposureTime_ = config.maxExposureTime; + sensorConfig.minGain_ = config.minAnalogueGain; + sensorConfig.maxGain_ = config.maxAnalogueGain; + + helper->configure(sensorConfig, sensorHelper); + } } /** diff --git a/src/ipa/libipa/agc_mean_luminance.h b/src/ipa/libipa/agc_mean_luminance.h index e5f164c3186b6b99cb0df5dd8dccf9026c22af20..42ead74b0cdc197bc2b27aee16918e2b42ea3d08 100644 --- a/src/ipa/libipa/agc_mean_luminance.h +++ b/src/ipa/libipa/agc_mean_luminance.h @@ -42,7 +42,16 @@ public: double yTarget; }; - void configure(utils::Duration lineDuration, const CameraSensorHelper *sensorHelper); + struct SensorConfiguration { + utils::Duration lineDuration; + utils::Duration minExposureTime; + utils::Duration maxExposureTime; + double minAnalogueGain; + double maxAnalogueGain; + }; + + void configure(const SensorConfiguration &config, + const CameraSensorHelper *sensorHelper); int parseTuningData(const YamlObject &tuningData); void setExposureCompensation(double gain) diff --git a/src/ipa/libipa/exposure_mode_helper.cpp b/src/ipa/libipa/exposure_mode_helper.cpp index c3ed1601939bd28435bbbc540d9b8c9d92b81912..f771b10a28eead2976c0000cf099ba5cfbe78e0f 100644 --- a/src/ipa/libipa/exposure_mode_helper.cpp +++ b/src/ipa/libipa/exposure_mode_helper.cpp @@ -111,24 +111,30 @@ ExposureModeHelper::ExposureModeHelper(const Span> stages); ~ExposureModeHelper() = default; - void configure(utils::Duration lineLength, const CameraSensorHelper *sensorHelper); + void configure(const SensorConfiguration &sensorConfig, + const CameraSensorHelper *sensorHelper); void setLimits(utils::Duration minExposureTime, utils::Duration maxExposureTime, double minGain, double maxGain); diff --git a/src/ipa/mali-c55/algorithms/agc.cpp b/src/ipa/mali-c55/algorithms/agc.cpp index 4fa00769d201d906be357809f5af02c71201a4f1..d6a1ff5aaca136c387feb8c948053fc83bb664ee 100644 --- a/src/ipa/mali-c55/algorithms/agc.cpp +++ b/src/ipa/mali-c55/algorithms/agc.cpp @@ -169,12 +169,16 @@ int Agc::configure(IPAContext &context, context.activeState.agc.constraintMode = constraintModes().begin()->first; context.activeState.agc.exposureMode = exposureModeHelpers().begin()->first; - /* \todo Run this again when FrameDurationLimits is passed in */ - setLimits(context.configuration.sensor.minShutterSpeed, - context.configuration.sensor.maxShutterSpeed, - context.configuration.sensor.minAnalogueGain, - context.configuration.sensor.maxAnalogueGain, - {}); + AgcMeanLuminance::SensorConfiguration sensorConfig; + sensorConfig.lineDuration = context.configuration.sensor.lineDuration; + sensorConfig.minExposureTime = context.configuration.sensor.minShutterSpeed; + sensorConfig.maxExposureTime = context.configuration.sensor.maxShutterSpeed; + sensorConfig.minAnalogueGain = context.configuration.sensor.minAnalogueGain; + sensorConfig.maxAnalogueGain = context.configuration.sensor.maxAnalogueGain; + + AgcMeanLuminance::configure(sensorConfig, context.camHelper.get()); + + /* \todo Update AGC limits when FrameDurationLimits is passed in */ resetFrameCount(); diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index aa1a90daf3ca7d0041c56000c12fc4d1ab5700eb..b0c8966eea63901640bbe16af2a5d8a303c63ece 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -200,13 +200,14 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo) context.configuration.agc.measureWindow.h_size = configInfo.outputSize.width; context.configuration.agc.measureWindow.v_size = configInfo.outputSize.height; - AgcMeanLuminance::configure(context.configuration.sensor.lineDuration, - context.camHelper.get()); - - setLimits(context.configuration.sensor.minExposureTime, - context.configuration.sensor.maxExposureTime, - context.configuration.sensor.minAnalogueGain, - context.configuration.sensor.maxAnalogueGain, {}); + AgcMeanLuminance::SensorConfiguration sensorConfig; + sensorConfig.lineDuration = context.configuration.sensor.lineDuration; + sensorConfig.minExposureTime = context.configuration.sensor.minExposureTime; + sensorConfig.maxExposureTime = context.configuration.sensor.maxExposureTime; + sensorConfig.minAnalogueGain = context.configuration.sensor.minAnalogueGain; + sensorConfig.maxAnalogueGain = context.configuration.sensor.maxAnalogueGain; + + AgcMeanLuminance::configure(sensorConfig, context.camHelper.get()); context.activeState.agc.automatic.yTarget = effectiveYTarget();