From patchwork Fri Nov 14 14:17:06 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 25063 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 603B5C3332 for ; Fri, 14 Nov 2025 14:17:39 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 0E7EA60B2C; Fri, 14 Nov 2025 15:17:36 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="oI+6knlW"; 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 0657560A8A for ; Fri, 14 Nov 2025 15:17:22 +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 037481AED; 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=1763129721; bh=Un6DimgZnEXwkGeYxO0GXkQ1C5J3iMRmDxlXCIsp1N0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=oI+6knlWsDduoZzse89BE4tBNYlp6MraZJMfl4QgD/rOFwmCq+CtNfwoXU4wNRMBP WXltMyLQbyOkRGKot7yssQra8g6qJ4BcpDltCFL8JZ5ZxCcbdN8iF3JAbiLw5KZ2Kc E3gKDvVOr5wXRJ8nhEPQcAUYeeUpeJ+O6Pfj2vxk= From: Jacopo Mondi Date: Fri, 14 Nov 2025 15:17:06 +0100 Subject: [PATCH v3 11/19] ipa: libipa: agc: Pass the frame duration to configure() MIME-Version: 1.0 Message-Id: <20251114-exposure-limits-v3-11-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=12478; i=jacopo.mondi@ideasonboard.com; h=from:subject:message-id; bh=Un6DimgZnEXwkGeYxO0GXkQ1C5J3iMRmDxlXCIsp1N0=; b=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBpFznrDM0hmmIBWJFe9NzTMVwtdgmzgH09yZwgt 6tVvNuBbq+JAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCaRc56wAKCRByNAaPFqFW PIG3EADFAXPcp0pcNFs9jJK0E+vLYv904IJ6AhGVtHkJZHQhm7GU7knuovGLakulk23NXtdQbrJ C+t72oQ+vosfS61EeaF54GytaXkL7UnvMrbDC/t635fjNuFSXO4V/wechWGFjsw5IrP1CAdmjjS NlRRXAk19KsrR1FbG+zCdIORpNgboflpg43m3Vh3MaXDr10EFDjpiEUrvLtBxngiLJldJ4vNjKh u7+9cV0hWS/wpdWHl1dWbVIQRKTPbLlgDJZxUPv6yKwhygeibu1a2UHSVxMYsEnUq1jv/qAGH27 rJnlq+1yoJ1zpWsbi3yG7AgT3td67kXp3kIsq8YTqJRvGVsErckZTFbr2raSp7pmU41+sSF9z2T m8HvgzgBV8SXdA75+roukDeOJPOCx7+rw9WgxohO9FdpSLHvh46vgZ1BzBYCN1HInKlkA/Gqx/U s2F2pKMvW3LdCxu+llxfJeX8+b97xX01yhPWl0KyGhF9dc6ygHORrSylaRU077I/X9Nvx2x1+7u YYuUtern67qWtS7+mQQ5D7PMsHRvANVOK9X4P5Mp4dqtpINs7Zj8KGWGoO5sOqA6bMlBJaAaeA1 oVkY+EgnV5B+6oTbvJV5qYNhe6maxx63zk92MOdwiUzjZweX0MpNpJiAG2b3O9fQVvw5S4JZQpl bcD9tGYz6/9qPKA== 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" Pass the min/max sensor frame duration to the AGC configure() operation. This prepares for limiting the exposure time to the frame duration. In order to be able to provide to the AGC the frame duration in the IPU3 and Mali-C55 IPAs it is necessary to store the FrameDurationLimits in the context sensor configuration, like it was already done for the RkISP1 IPA. Signed-off-by: Jacopo Mondi --- src/ipa/ipu3/algorithms/agc.cpp | 2 ++ src/ipa/ipu3/ipa_context.h | 4 ++++ src/ipa/ipu3/ipu3.cpp | 18 +++++++++++++++--- src/ipa/libipa/agc_mean_luminance.cpp | 8 ++++++++ src/ipa/libipa/agc_mean_luminance.h | 2 ++ src/ipa/mali-c55/algorithms/agc.cpp | 6 ++++++ src/ipa/mali-c55/ipa_context.h | 4 ++++ src/ipa/mali-c55/mali-c55.cpp | 17 ++++++++++++----- src/ipa/rkisp1/algorithms/agc.cpp | 2 ++ 9 files changed, 55 insertions(+), 8 deletions(-) diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp index 5c72806dede5f55459bde69ab8cfaebc495c7560..002ee574c02b79c25834a9d87a5881a9de52e39e 100644 --- a/src/ipa/ipu3/algorithms/agc.cpp +++ b/src/ipa/ipu3/algorithms/agc.cpp @@ -118,6 +118,8 @@ int Agc::configure(IPAContext &context, AgcMeanLuminance::SensorConfiguration sensorConfig; sensorConfig.lineDuration = context.configuration.sensor.lineDuration; sensorConfig.minExposureTime = minExposureTime_; + sensorConfig.minFrameDuration = context.configuration.sensor.minFrameDuration; + sensorConfig.maxFrameDuration = context.configuration.sensor.maxFrameDuration; sensorConfig.maxExposureTime = maxExposureTime_; sensorConfig.minAnalogueGain = minAnalogueGain_; sensorConfig.maxAnalogueGain = maxAnalogueGain_; diff --git a/src/ipa/ipu3/ipa_context.h b/src/ipa/ipu3/ipa_context.h index baf84b8cbc9a1ff9411c0a994e35317b613580dd..33f3fe3ae1b503d47887873046def0835cd53894 100644 --- a/src/ipa/ipu3/ipa_context.h +++ b/src/ipa/ipu3/ipa_context.h @@ -39,6 +39,8 @@ struct IPASessionConfiguration { Size size; utils::Duration minExposureTime; utils::Duration maxExposureTime; + utils::Duration minFrameDuration; + utils::Duration maxFrameDuration; double minAnalogueGain; double maxAnalogueGain; } sensor; @@ -56,6 +58,8 @@ struct IPAActiveState { double gain; uint32_t constraintMode; uint32_t exposureMode; + utils::Duration minFrameDuration; + utils::Duration maxFrameDuration; } agc; struct { diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp index 60f22727a0f75e374b53fb6d3185946b70c25582..0c8651c5235f9e4e9944eb88595aeef41f016310 100644 --- a/src/ipa/ipu3/ipu3.cpp +++ b/src/ipa/ipu3/ipu3.cpp @@ -167,7 +167,8 @@ private: void updateControls(const IPACameraSensorInfo &sensorInfo, const ControlInfoMap &sensorControls, ControlInfoMap *ipaControls); - void updateSessionConfiguration(const ControlInfoMap &sensorControls); + void updateSessionConfiguration(const IPACameraSensorInfo &sensorInfo, + const ControlInfoMap &sensorControls); void setControls(unsigned int frame); void calculateBdsGrid(const Size &bdsOutputSize); @@ -197,7 +198,8 @@ std::string IPAIPU3::logPrefix() const * \brief Compute IPASessionConfiguration using the sensor information and the * sensor V4L2 controls */ -void IPAIPU3::updateSessionConfiguration(const ControlInfoMap &sensorControls) +void IPAIPU3::updateSessionConfiguration(const IPACameraSensorInfo &sensorInfo, + const ControlInfoMap &sensorControls) { const ControlInfo vBlank = sensorControls.find(V4L2_CID_VBLANK)->second; context_.configuration.sensor.defVBlank = vBlank.def().get(); @@ -210,6 +212,12 @@ void IPAIPU3::updateSessionConfiguration(const ControlInfoMap &sensorControls) int32_t minGain = v4l2Gain.min().get(); int32_t maxGain = v4l2Gain.max().get(); + const ControlInfo &v4l2VBlank = sensorControls.find(V4L2_CID_VBLANK)->second; + std::array frameHeights{ + v4l2VBlank.min().get() + sensorInfo.outputSize.height, + v4l2VBlank.max().get() + sensorInfo.outputSize.height, + }; + /* * When the AGC computes the new exposure values for a frame, it needs * to know the limits for exposure time and analogue gain. @@ -219,6 +227,10 @@ void IPAIPU3::updateSessionConfiguration(const ControlInfoMap &sensorControls) */ context_.configuration.sensor.minExposureTime = minExposure * context_.configuration.sensor.lineDuration; context_.configuration.sensor.maxExposureTime = maxExposure * context_.configuration.sensor.lineDuration; + context_.configuration.sensor.minFrameDuration = frameHeights[0] * + context_.configuration.sensor.lineDuration; + context_.configuration.sensor.maxFrameDuration = frameHeights[1] * + context_.configuration.sensor.lineDuration; context_.configuration.sensor.minAnalogueGain = context_.camHelper->gain(minGain); context_.configuration.sensor.maxAnalogueGain = context_.camHelper->gain(maxGain); } @@ -488,7 +500,7 @@ int IPAIPU3::configure(const IPAConfigInfo &configInfo, updateControls(sensorInfo_, sensorCtrls_, ipaControls); /* Update the IPASessionConfiguration using the sensor settings. */ - updateSessionConfiguration(sensorCtrls_); + updateSessionConfiguration(sensorInfo_, sensorCtrls_); for (auto const &algo : algorithms()) { int ret = algo->configure(context_, configInfo); diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp index 512e153791f5b98da01efad6675192a5358e7698..602050729fd08649e2db8d07623a8a39e7a53a77 100644 --- a/src/ipa/libipa/agc_mean_luminance.cpp +++ b/src/ipa/libipa/agc_mean_luminance.cpp @@ -117,6 +117,12 @@ static constexpr double kMaxRelativeLuminanceTarget = 0.95; * \var AgcMeanLuminance::SensorConfiguration::maxExposureTime * \brief The sensor maximum exposure time in microseconds * + * \var AgcMeanLuminance::SensorConfiguration::minFrameDuration + * \brief The sensor minimum frame duration in microseconds + * + * \var AgcMeanLuminance::SensorConfiguration::maxFrameDuration + * \brief The sensor maximum frame duration in microseconds + * * \var AgcMeanLuminance::SensorConfiguration::minAnalogueGain * \brief The sensor minimum analogue gain absolute value * @@ -366,6 +372,8 @@ void AgcMeanLuminance::configure(const SensorConfiguration &config, sensorConfig.lineDuration_ = config.lineDuration; sensorConfig.minExposureTime_ = config.minExposureTime; sensorConfig.maxExposureTime_ = config.maxExposureTime; + sensorConfig.minFrameDuration_ = config.minFrameDuration; + sensorConfig.maxFrameDuration_ = config.maxFrameDuration; sensorConfig.minGain_ = config.minAnalogueGain; sensorConfig.maxGain_ = config.maxAnalogueGain; diff --git a/src/ipa/libipa/agc_mean_luminance.h b/src/ipa/libipa/agc_mean_luminance.h index 42ead74b0cdc197bc2b27aee16918e2b42ea3d08..c3c8ce1cdda9229eca400b730f2ee896e9a0af93 100644 --- a/src/ipa/libipa/agc_mean_luminance.h +++ b/src/ipa/libipa/agc_mean_luminance.h @@ -46,6 +46,8 @@ public: utils::Duration lineDuration; utils::Duration minExposureTime; utils::Duration maxExposureTime; + utils::Duration minFrameDuration; + utils::Duration maxFrameDuration; double minAnalogueGain; double maxAnalogueGain; }; diff --git a/src/ipa/mali-c55/algorithms/agc.cpp b/src/ipa/mali-c55/algorithms/agc.cpp index d6a1ff5aaca136c387feb8c948053fc83bb664ee..731b29ced1030ecb3f44b83ad28a0691dd5d2f0d 100644 --- a/src/ipa/mali-c55/algorithms/agc.cpp +++ b/src/ipa/mali-c55/algorithms/agc.cpp @@ -168,11 +168,17 @@ int Agc::configure(IPAContext &context, context.activeState.agc.manual.ispGain = kMinDigitalGain; context.activeState.agc.constraintMode = constraintModes().begin()->first; context.activeState.agc.exposureMode = exposureModeHelpers().begin()->first; + context.activeState.agc.minFrameDuration = + context.configuration.sensor.minFrameDuration; + context.activeState.agc.maxFrameDuration = + context.configuration.sensor.maxFrameDuration; AgcMeanLuminance::SensorConfiguration sensorConfig; sensorConfig.lineDuration = context.configuration.sensor.lineDuration; sensorConfig.minExposureTime = context.configuration.sensor.minShutterSpeed; sensorConfig.maxExposureTime = context.configuration.sensor.maxShutterSpeed; + sensorConfig.minFrameDuration = context.configuration.sensor.minFrameDuration; + sensorConfig.maxFrameDuration = context.configuration.sensor.maxFrameDuration; sensorConfig.minAnalogueGain = context.configuration.sensor.minAnalogueGain; sensorConfig.maxAnalogueGain = context.configuration.sensor.maxAnalogueGain; diff --git a/src/ipa/mali-c55/ipa_context.h b/src/ipa/mali-c55/ipa_context.h index fe75590ec93302e61a31e4832f5c497aab80cf4d..3b64cb7571729d4af162def5b2316331b3561af1 100644 --- a/src/ipa/mali-c55/ipa_context.h +++ b/src/ipa/mali-c55/ipa_context.h @@ -30,6 +30,8 @@ struct IPASessionConfiguration { uint32_t blackLevel; utils::Duration minShutterSpeed; utils::Duration maxShutterSpeed; + utils::Duration minFrameDuration; + utils::Duration maxFrameDuration; double minAnalogueGain; double maxAnalogueGain; } sensor; @@ -51,6 +53,8 @@ struct IPAActiveState { uint32_t constraintMode; uint32_t exposureMode; uint32_t temperatureK; + utils::Duration minFrameDuration; + utils::Duration maxFrameDuration; } agc; struct { diff --git a/src/ipa/mali-c55/mali-c55.cpp b/src/ipa/mali-c55/mali-c55.cpp index 9375facf7ab559853986f66634d4e36b896361c8..491ae71a06dbede967bfbe1bcdcab25d177ad691 100644 --- a/src/ipa/mali-c55/mali-c55.cpp +++ b/src/ipa/mali-c55/mali-c55.cpp @@ -177,16 +177,23 @@ void IPAMaliC55::updateSessionConfiguration(const IPACameraSensorInfo &info, int32_t minGain = v4l2Gain.min().get(); int32_t maxGain = v4l2Gain.max().get(); + const ControlInfo &v4l2VBlank = sensorControls.find(V4L2_CID_VBLANK)->second; + std::array frameHeights{ + v4l2VBlank.min().get() + info.outputSize.height, + v4l2VBlank.max().get() + info.outputSize.height, + }; + /* * When the AGC computes the new exposure values for a frame, it needs * to know the limits for shutter speed and analogue gain. * As it depends on the sensor, update it with the controls. - * - * \todo take VBLANK into account for maximum shutter speed */ - context_.configuration.sensor.lineDuration = info.minLineLength * 1.0s / info.pixelRate; - context_.configuration.sensor.minShutterSpeed = minExposure * context_.configuration.sensor.lineDuration; - context_.configuration.sensor.maxShutterSpeed = maxExposure * context_.configuration.sensor.lineDuration; + utils::Duration lineDuration = info.minLineLength * 1.0s / info.pixelRate; + context_.configuration.sensor.lineDuration = lineDuration; + context_.configuration.sensor.minShutterSpeed = minExposure * lineDuration; + context_.configuration.sensor.maxShutterSpeed = maxExposure * lineDuration; + context_.configuration.sensor.minFrameDuration = frameHeights[0] * lineDuration; + context_.configuration.sensor.maxFrameDuration = frameHeights[1] * lineDuration; context_.configuration.sensor.minAnalogueGain = context_.camHelper->gain(minGain); context_.configuration.sensor.maxAnalogueGain = context_.camHelper->gain(maxGain); diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp index b0c8966eea63901640bbe16af2a5d8a303c63ece..de2980485f2d3a8973f065981f8cdd520e3dfc47 100644 --- a/src/ipa/rkisp1/algorithms/agc.cpp +++ b/src/ipa/rkisp1/algorithms/agc.cpp @@ -204,6 +204,8 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo) sensorConfig.lineDuration = context.configuration.sensor.lineDuration; sensorConfig.minExposureTime = context.configuration.sensor.minExposureTime; sensorConfig.maxExposureTime = context.configuration.sensor.maxExposureTime; + sensorConfig.minFrameDuration = context.configuration.sensor.minFrameDuration; + sensorConfig.maxFrameDuration = context.configuration.sensor.maxFrameDuration; sensorConfig.minAnalogueGain = context.configuration.sensor.minAnalogueGain; sensorConfig.maxAnalogueGain = context.configuration.sensor.maxAnalogueGain;