{"id":25070,"url":"https://patchwork.libcamera.org/api/patches/25070/?format=json","web_url":"https://patchwork.libcamera.org/patch/25070/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20251114-exposure-limits-v3-18-b7c07feba026@ideasonboard.com>","date":"2025-11-14T14:17:13","name":"[v3,18/19] ipa: libipa: agc: Initialize a sensible frame duration","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"ca08b5865c77b958c58847ce44e678dbdcf178a5","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/?format=json","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/25070/mbox/","series":[{"id":5590,"url":"https://patchwork.libcamera.org/api/series/5590/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=5590","date":"2025-11-14T14:16:55","name":"libipa: agc: Calculate exposure limits","version":3,"mbox":"https://patchwork.libcamera.org/series/5590/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/25070/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/25070/checks/","tags":{},"headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 63296C3337\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 14 Nov 2025 14:17:44 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id E7DC960ABA;\n\tFri, 14 Nov 2025 15:17:43 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id CB54560ABA\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 14 Nov 2025 15:17:24 +0100 (CET)","from [192.168.1.101] (93-61-96-190.ip145.fastwebnet.it\n\t[93.61.96.190])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id C86591F37;\n\tFri, 14 Nov 2025 15:15:23 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"wbyvHsUX\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1763129724;\n\tbh=h8FMFv/BsfC3u4TGP5N6VoUOd9JL4a85sWM8Gy+/rjs=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc:From;\n\tb=wbyvHsUXGRpC4by0p+TJItgaJNSBWadvRGvFjwS983PobJMRr8XZ1Vglu6gPczygo\n\te3vw6LZxIGDiT+0GTLxzb03GJ96y6gPZtmk1B/5BObpbtAnBS9SxXNOJLeSZ/mB2T6\n\tChUY8P7pJQ6S2UbA2hrNzdUrSAuhGiVZtoae38LU=","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","Date":"Fri, 14 Nov 2025 15:17:13 +0100","Subject":"[PATCH v3 18/19] ipa: libipa: agc: Initialize a sensible frame\n\tduration","MIME-Version":"1.0","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"7bit","Message-Id":"<20251114-exposure-limits-v3-18-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?= <niklas.soderlund@ragnatech.se>,\n\tRobert Mader <robert.mader@collabora.com>, \n\tlibcamera-devel@lists.libcamera.org","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","X-Mailer":"b4 0.14.2","X-Developer-Signature":"v=1; a=openpgp-sha256; l=5199;\n\ti=jacopo.mondi@ideasonboard.com; h=from:subject:message-id;\n\tbh=h8FMFv/BsfC3u4TGP5N6VoUOd9JL4a85sWM8Gy+/rjs=;\n\tb=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBpFznsEddLKFNFfl9vWvFoI6CAFOdWVGdzpegVy\n\tlRSLD1/pk6JAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCaRc57AAKCRByNAaPFqFW\n\tPDQ5D/4zVHEE1O/zQgHXy1zZdxs5e8011aT+U9w7aA1wPL26LdnwwWrUhEkjuLx5HIfvrJLegL/\n\t+RKsMCe2kQKSFQGqqGfdY8zucBo0q9K+FVb08MzMO0yx/ES/xpGoMsIiVLJwpjkY9GFEfLPOLZF\n\tlS/IP0DByUBNOy8XrgTUuyfDGMWUgXW3km+FfB0h+8yy1O8lRO213M7A/NksgMCNPLj++N3np73\n\tN9RjJZQ50rrJ7wMbxkrznAtPFUtZzw/kj+tbI2TBJMZQAp2XHVUHFhXLX8bo+wvsn/CwWniM3+b\n\tlrER80u9PaDctSzp3P9fJzC+/ms5aNok5ra+URAAiZw0xLbpw1EPTJfuMzEIJOdcxzSH8eJeOP0\n\tQxK27H+owccPJ7Wu5zFK/ZARERWcgNMfOjb50oXr7qREhyXvL/v0QnHGiqO9jO+gL1A4fFAuoI1\n\t4iBsV0Z2kZX0MdrzCdleRceVccwYTQwiFtE07/I8yyRmmGPbrAKm/Q7UgtH26npO5fefdhG3hx4\n\t8ofLGjvj50ks6oCEqxQW536tchm61wDySFHKEyx6eddJqEQAl5EWa1kvk7Bw3msggibnxizBvw3\n\to2lELUjWUYD9ZhPdzVV1PvaR3cL0ESPHXC4lpoe6jVf+KXDVoJabM9anEu8uoK3X7wx8UZgKpnk\n\tpjM4QDEIH1F33vg==","X-Developer-Key":"i=jacopo.mondi@ideasonboard.com; a=openpgp;\n\tfpr=72392EDC88144A65C701EA9BA5826A2587AD026B","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"},"content":"The AGC algorithm implemented by AgcMeanLuminance splits the desired\nexposure between shutter time, analogue and digital gains. It tries to\nmaximize the shutter time up to the specified limits and then increases\nthe gains.\n\nWhen initializing the algorithm at configure() time the IPA modules\nhave access to the Camera's absolute limits, which might include\na very long maximum frame duration. If such duration is used to clamp\nthe maximum exposure, the algorithm will maximize the shutter time,\nresulting in a very low frame rate.\n\nTry to pick a slighlty saner default of 30, 15 or 10 fps to limit the\nmaximum shutter time with to provide a reasonable out-of-the-box\nbehaviour for users. The new frame duration limit calculated by the AGC\nalgorithm is passed back to the IPA module that shall use it to compute\nthe right blankings to configure the camera with.\n\nAt the moment, only the RkISP1 IPA actually controls the frame duration,\nand so it is the only IPA that needs to use the frame duration as\ncomputed by the AGC algorithm.\n\nSigned-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n---\n src/ipa/libipa/agc_mean_luminance.cpp | 27 ++++++++++++++++++++++++---\n src/ipa/libipa/agc_mean_luminance.h   |  4 ++--\n src/ipa/rkisp1/algorithms/agc.cpp     |  3 ++-\n 3 files changed, 28 insertions(+), 6 deletions(-)","diff":"diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp\nindex b930e1f7240d4936aa8dc850657bbbf9c2f3a11f..f6768958c0d3d76108561b9455a15c715a89048e 100644\n--- a/src/ipa/libipa/agc_mean_luminance.cpp\n+++ b/src/ipa/libipa/agc_mean_luminance.cpp\n@@ -353,10 +353,29 @@ int AgcMeanLuminance::parseExposureModes(const YamlObject &tuningData)\n  * This function configures the exposure mode helpers by providing them the\n  * sensor configuration parameters and the sensor helper, so they can correctly\n  * take quantization effects into account.\n+ *\n+ * It computes a reasonable frame duration in the sensor's limits and returns it\n+ * to the IPA for configuring the sensor's blankings.\n+ *\n  */\n-void AgcMeanLuminance::configure(const SensorConfiguration &config,\n-\t\t\t\t const CameraSensorHelper *sensorHelper)\n+utils::Duration AgcMeanLuminance::configure(const SensorConfiguration &config,\n+\t\t\t\t\t    const CameraSensorHelper *sensorHelper)\n {\n+\n+\tutils::Duration minFrameDuration = config.minFrameDuration;\n+\tutils::Duration maxFrameDuration = config.maxFrameDuration;\n+\n+\tstatic constexpr utils::Duration duration30fps = 33333 * 1us;\n+\tstatic constexpr utils::Duration duration15fps = 66666 * 1us;\n+\tstatic constexpr utils::Duration duration10fps = 100000 * 1us;\n+\tutils::Duration frameDuration = minFrameDuration < duration30fps\n+\t\t\t\t      ? duration30fps\n+\t\t\t\t        : minFrameDuration < duration15fps\n+\t\t\t\t\t? duration15fps\n+\t\t\t\t\t  : minFrameDuration < duration10fps\n+\t\t\t\t\t  ? duration10fps : minFrameDuration;\n+\tframeDuration = std::min(frameDuration, maxFrameDuration);\n+\n \tfor (auto &[id, helper] : exposureModeHelpers_) {\n \t\t/*\n \t\t * Translate from the SensorConfiguration to the\n@@ -370,7 +389,7 @@ void AgcMeanLuminance::configure(const SensorConfiguration &config,\n \t\tsensorConfig.lineDuration_ = config.lineDuration;\n \t\tsensorConfig.minExposureTime_ = config.minExposureTime;\n \t\tsensorConfig.minFrameDuration_ = config.minFrameDuration;\n-\t\tsensorConfig.maxFrameDuration_ = config.maxFrameDuration;\n+\t\tsensorConfig.maxFrameDuration_ = frameDuration;\n \t\tsensorConfig.minGain_ = config.minAnalogueGain;\n \t\tsensorConfig.maxGain_ = config.maxAnalogueGain;\n \n@@ -378,6 +397,8 @@ void AgcMeanLuminance::configure(const SensorConfiguration &config,\n \t}\n \n \tresetFrameCount();\n+\n+\treturn frameDuration;\n }\n \n /**\ndiff --git a/src/ipa/libipa/agc_mean_luminance.h b/src/ipa/libipa/agc_mean_luminance.h\nindex 93a0959bbd9e0d6ec42248f2d3b19253ad389ae6..d66da7671c313e5acb959018b08a82335b7170b8 100644\n--- a/src/ipa/libipa/agc_mean_luminance.h\n+++ b/src/ipa/libipa/agc_mean_luminance.h\n@@ -51,8 +51,8 @@ public:\n \t\tdouble maxAnalogueGain;\n \t};\n \n-\tvoid configure(const SensorConfiguration &config,\n-\t\t       const CameraSensorHelper *sensorHelper);\n+\tutils::Duration configure(const SensorConfiguration &config,\n+\t\t\t\t  const CameraSensorHelper *sensorHelper);\n \tint parseTuningData(const YamlObject &tuningData);\n \n \tvoid setExposureCompensation(double gain)\ndiff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp\nindex 10498eb6357d8917e299ac24f6c8ba8c33af4eae..eac193b9aadfb17b7b6a02dcff2f3aa0b56dff84 100644\n--- a/src/ipa/rkisp1/algorithms/agc.cpp\n+++ b/src/ipa/rkisp1/algorithms/agc.cpp\n@@ -207,7 +207,8 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)\n \tsensorConfig.minAnalogueGain = context.configuration.sensor.minAnalogueGain;\n \tsensorConfig.maxAnalogueGain = context.configuration.sensor.maxAnalogueGain;\n \n-\tAgcMeanLuminance::configure(sensorConfig, context.camHelper.get());\n+\tcontext.activeState.agc.maxFrameDuration =\n+\t\tAgcMeanLuminance::configure(sensorConfig, context.camHelper.get());\n \n \tcontext.activeState.agc.automatic.yTarget = effectiveYTarget();\n \n","prefixes":["v3","18/19"]}