[{"id":36631,"web_url":"https://patchwork.libcamera.org/comment/36631/","msgid":"<20251102203416.GK27255@pendragon.ideasonboard.com>","date":"2025-11-02T20:34:16","subject":"Re: [PATCH v2 06/10] ipa: libipa: agc: Initialize exposure with\n\tframe duration","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Tue, Oct 28, 2025 at 10:31:52AM +0100, Jacopo Mondi wrote:\n> The maximum exposure time the AGC algorithm can achieve is, by\n> definition, limited by the maximum programmed frame duration.\n> \n> When initializing the AGC algorithm, use the frame duration and the\n> sensor's exposure margin to calculate the maximum exposure, unless\n> the IPA has asked for a fixed exposure by setting min == max.\n> \n> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> ---\n>  src/ipa/libipa/exposure_mode_helper.cpp | 25 +++++++++++++++++++++++--\n>  1 file changed, 23 insertions(+), 2 deletions(-)\n> \n> diff --git a/src/ipa/libipa/exposure_mode_helper.cpp b/src/ipa/libipa/exposure_mode_helper.cpp\n> index edb8f04b245f01119d0d0b0917d10f98c7172dc0..8f40290959e24294ead008c7228e2f67ffc5adf8 100644\n> --- a/src/ipa/libipa/exposure_mode_helper.cpp\n> +++ b/src/ipa/libipa/exposure_mode_helper.cpp\n> @@ -106,12 +106,33 @@ void ExposureModeHelper::configure(utils::Duration lineDuration,\n>  \t\t\t\t   const CameraSensorHelper *sensorHelper)\n>  {\n>  \tlineDuration_ = lineDuration;\n> -\tminExposureTime_ = minExposureTime;\n> -\tmaxExposureTime_ = maxExposureTime;\n>  \tmaxFrameDuration_ = maxFrameDuration;\n>  \tminGain_ = minGain;\n>  \tmaxGain_ = maxGain;\n>  \tsensorHelper_ = sensorHelper;\n> +\n> +\tminExposureTime_ = minExposureTime;\n> +\n> +\t/*\n> +\t * Compute the maximum exposure time.\n> +\t *\n> +\t * If maxExposureTime is equal to minExposureTime then we use them\n> +\t * to fix the exposure time.\n> +\t *\n> +\t * Otherwise, if the exposure can range between a min and max, use the\n> +\t * maxFrameDuration minus the margin as upper limit for exposure\n> +\t * (capped to the provided max exposure).\n> +\t */\n> +\tauto margin = sensorHelper_->exposureMargin();\n> +\tif (!margin.has_value()) {\n> +\t\tLOG(ExposureModeHelper, Warning)\n> +\t\t\t<< \"Exposure margin not known. Default to 4\";\n> +\t\tmargin = { 4 };\n> +\t}\n> +\n> +\tmaxExposureTime_ = minExposureTime != maxExposureTime\n> +\t\t\t ? maxFrameDuration - margin.value() * lineDuration\n> +\t\t\t : minExposureTime;\n\nI'd reorganize this to call exposureMargin() only when minExposureTime\n!= maxExposureTime.\n\nWhat happens if maxFrameDuration is smaller than the margin ? Or if\nsubtracting the margin makes max < min ? And even more importantly,\nshouldn't the maxFrameDuration - margin only *clamp* maxExposureTime,\nnot replace it ?\n\n>  }\n>  \n>  /**","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 1665DC3241\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSun,  2 Nov 2025 20:34:33 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 3EF7B60A80;\n\tSun,  2 Nov 2025 21:34:32 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 9AFEE606E6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSun,  2 Nov 2025 21:34:30 +0100 (CET)","from pendragon.ideasonboard.com (82-203-160-149.bb.dnainternet.fi\n\t[82.203.160.149])\n\tby perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id C29BB99F;\n\tSun,  2 Nov 2025 21:32:37 +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=\"vB4nidEX\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1762115557;\n\tbh=QIODaVE0pgHj76Pr0hjF1ga/W3g0tEotRMZbFPlCUJY=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=vB4nidEX8J01F+2eANiMPLvxg8Ve9ygHRmYBh6q/qAO/U77CMl2sH13AiTY/i6k+B\n\tWX0bD4D0O8uw+WNCBi/m/7wdeYCzEyb3vUBaWaLOQSTQScVl3aDW5HxF/NtmGlk3ZG\n\tnnf8UKoZfi6dmGXj88awu4owAkm8d/R0yPr1X1Kw=","Date":"Sun, 2 Nov 2025 22:34:16 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","Cc":"Niklas =?utf-8?q?S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>,\n\tRobert Mader <robert.mader@collabora.com>, \n\tlibcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH v2 06/10] ipa: libipa: agc: Initialize exposure with\n\tframe duration","Message-ID":"<20251102203416.GK27255@pendragon.ideasonboard.com>","References":"<20251028-exposure-limits-v2-0-a8b5a318323e@ideasonboard.com>\n\t<20251028-exposure-limits-v2-6-a8b5a318323e@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20251028-exposure-limits-v2-6-a8b5a318323e@ideasonboard.com>","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>"}},{"id":36683,"web_url":"https://patchwork.libcamera.org/comment/36683/","msgid":"<mosfc5ig2agabn5bt3pckginjysahbzmhffllj265pz7dylzld@fzakmm4h2bi3>","date":"2025-11-04T16:09:52","subject":"Re: [PATCH v2 06/10] ipa: libipa: agc: Initialize exposure with\n\tframe duration","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Laurent\n\nOn Sun, Nov 02, 2025 at 10:34:16PM +0200, Laurent Pinchart wrote:\n> On Tue, Oct 28, 2025 at 10:31:52AM +0100, Jacopo Mondi wrote:\n> > The maximum exposure time the AGC algorithm can achieve is, by\n> > definition, limited by the maximum programmed frame duration.\n> >\n> > When initializing the AGC algorithm, use the frame duration and the\n> > sensor's exposure margin to calculate the maximum exposure, unless\n> > the IPA has asked for a fixed exposure by setting min == max.\n> >\n> > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> > ---\n> >  src/ipa/libipa/exposure_mode_helper.cpp | 25 +++++++++++++++++++++++--\n> >  1 file changed, 23 insertions(+), 2 deletions(-)\n> >\n> > diff --git a/src/ipa/libipa/exposure_mode_helper.cpp b/src/ipa/libipa/exposure_mode_helper.cpp\n> > index edb8f04b245f01119d0d0b0917d10f98c7172dc0..8f40290959e24294ead008c7228e2f67ffc5adf8 100644\n> > --- a/src/ipa/libipa/exposure_mode_helper.cpp\n> > +++ b/src/ipa/libipa/exposure_mode_helper.cpp\n> > @@ -106,12 +106,33 @@ void ExposureModeHelper::configure(utils::Duration lineDuration,\n> >  \t\t\t\t   const CameraSensorHelper *sensorHelper)\n> >  {\n> >  \tlineDuration_ = lineDuration;\n> > -\tminExposureTime_ = minExposureTime;\n> > -\tmaxExposureTime_ = maxExposureTime;\n> >  \tmaxFrameDuration_ = maxFrameDuration;\n> >  \tminGain_ = minGain;\n> >  \tmaxGain_ = maxGain;\n> >  \tsensorHelper_ = sensorHelper;\n> > +\n> > +\tminExposureTime_ = minExposureTime;\n> > +\n> > +\t/*\n> > +\t * Compute the maximum exposure time.\n> > +\t *\n> > +\t * If maxExposureTime is equal to minExposureTime then we use them\n> > +\t * to fix the exposure time.\n> > +\t *\n> > +\t * Otherwise, if the exposure can range between a min and max, use the\n> > +\t * maxFrameDuration minus the margin as upper limit for exposure\n> > +\t * (capped to the provided max exposure).\n> > +\t */\n> > +\tauto margin = sensorHelper_->exposureMargin();\n> > +\tif (!margin.has_value()) {\n> > +\t\tLOG(ExposureModeHelper, Warning)\n> > +\t\t\t<< \"Exposure margin not known. Default to 4\";\n> > +\t\tmargin = { 4 };\n> > +\t}\n> > +\n> > +\tmaxExposureTime_ = minExposureTime != maxExposureTime\n> > +\t\t\t ? maxFrameDuration - margin.value() * lineDuration\n> > +\t\t\t : minExposureTime;\n>\n> I'd reorganize this to call exposureMargin() only when minExposureTime\n> != maxExposureTime.\n\nSure. I'll re-work this function anyway, I'll keep this in mind.\n\n>\n> What happens if maxFrameDuration is smaller than the margin ? Or if\n\nHow can this happen ? The frame duration is at least the visible frame\nheight, isn't it ? And the max frame duration is (height + max\nvblank). Can this be smaller than the margin ?\n\n> subtracting the margin makes max < min ? And even more importantly,\n\nare you talking about max and min exposure right ?\n\nAgain, this seems very unlikely, the min exposure is usually in same\norder of magnitude of the margin (from 4 to 75 lines in the sensors we\ncurrently support). To have maxExposure < minExposure we should have\nthat the min_exposure + margin > (height + min_vblank). This seems\nquite unlikely.\n\nI can however make sure that\n        maxExposure = max(maxExposure, minExposure)\n\n> shouldn't the maxFrameDuration - margin only *clamp* maxExposureTime,\n> not replace it ?\n\nmmm, I'm not sure why...\n\nThe maximum achievable exposure follows the max frame duration,\ndoesn't it ?\n\nApplications can't set an exposure range but a single ExposureTime, so\nit's not like we're overwriting a user setting. Have I missed\nsomething ?\n\n>\n> >  }\n> >\n> >  /**\n>\n> --\n> Regards,\n>\n> Laurent Pinchart","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 7A2BAC3241\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue,  4 Nov 2025 16:09:58 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A83B460A8B;\n\tTue,  4 Nov 2025 17:09:57 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id D8EFD6069A\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  4 Nov 2025 17:09:55 +0100 (CET)","from ideasonboard.com (93-61-96-190.ip145.fastwebnet.it\n\t[93.61.96.190])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id C65C31771;\n\tTue,  4 Nov 2025 17:08:01 +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=\"kA/SlPOC\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1762272481;\n\tbh=B85/RX73L5d7yWH614xPwmdAbmodBnazCh86E0Z7KjQ=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=kA/SlPOCnyhPepFGr1pWGtOvqMcrJtzgXp0dC7wobXT2YJ/y6CtUYw2V6KL4moFcI\n\tzjVJzxdNRQqZsgR70VoNnxdsOIe5Mx4RHDvhV/B3BFQc9CZt3BfBCQMa/r1nzCBuM+\n\t5uYm0nUraM0Rd/S8o4IDllnf1hXdMaIx60wXPcyk=","Date":"Tue, 4 Nov 2025 17:09:52 +0100","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>,  Niklas =?utf-8?b?U8O2?=\n\t=?utf-8?q?derlund?= <niklas.soderlund@ragnatech.se>, Robert Mader\n\t<robert.mader@collabora.com>,  libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH v2 06/10] ipa: libipa: agc: Initialize exposure with\n\tframe duration","Message-ID":"<mosfc5ig2agabn5bt3pckginjysahbzmhffllj265pz7dylzld@fzakmm4h2bi3>","References":"<20251028-exposure-limits-v2-0-a8b5a318323e@ideasonboard.com>\n\t<20251028-exposure-limits-v2-6-a8b5a318323e@ideasonboard.com>\n\t<20251102203416.GK27255@pendragon.ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20251102203416.GK27255@pendragon.ideasonboard.com>","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>"}}]