[{"id":20935,"web_url":"https://patchwork.libcamera.org/comment/20935/","msgid":"<20211112231254.GE8453@jade.amanokami.net>","date":"2021-11-12T23:12:54","subject":"Re: [libcamera-devel] [PATCH v4 07/14] ipa: ipu3: agc: Improve gain\n\tcalculation","submitter":{"id":17,"url":"https://patchwork.libcamera.org/api/people/17/","name":"Paul Elder","email":"paul.elder@ideasonboard.com"},"content":"Hi Jean-Michel,\n\nOn Thu, Nov 11, 2021 at 03:09:21PM +0100, Jean-Michel Hautbois wrote:\n> When an image is partially saturated, its brightness is not increasing\n> linearly when the shutter time or gain increases. It is a big issue with\n> a backlight as the algorithm is fading to darkness right now.\n> \n> Introduce a function to estimate the brightness of the frame, based on\n> the current exposure/gain and loop on it several times to estimate it\n> again and approach the non linear function.\n> \n> Inspired-by: 7de5506c30b3 (\"libcamera: src: ipa: raspberrypi: agc: Improve gain update calculation for partly saturated images\")\n> Signed-off-by: Jean-Michel Hautbois <jeanmichel.hautbois@ideasonboard.com>\n> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> ---\n>  src/ipa/ipu3/algorithms/agc.cpp | 104 +++++++++++++++++++++++++++++++-\n>  src/ipa/ipu3/algorithms/agc.h   |   6 +-\n>  2 files changed, 106 insertions(+), 4 deletions(-)\n> \n> diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp\n> index 61ca8b3f..a34f070e 100644\n> --- a/src/ipa/ipu3/algorithms/agc.cpp\n> +++ b/src/ipa/ipu3/algorithms/agc.cpp\n> @@ -67,6 +67,17 @@ static constexpr uint32_t kMinCellsPerZoneRatio = 255 * 20 / 100;\n>  /* Number of frames to wait before calculating stats on minimum exposure */\n>  static constexpr uint32_t kNumStartupFrames = 10;\n>  \n> +/* Maximum luminance used for brightness normalization */\n> +static constexpr uint32_t kMaxLuminance = 255;\n> +\n> +/*\n> + * Normalized luma value target.\n> + *\n> + * It's a number that's chosen so that, when the camera points at a grey\n> + * target, the resulting image brightness is considered right.\n> + */\n> +static constexpr double kNormalizedLumaTarget = 0.16;\n> +\n>  Agc::Agc()\n>  \t: frameCount_(0), iqMean_(0.0), lineDuration_(0s), minExposureLines_(0),\n>  \t  maxExposureLines_(0), filteredExposure_(0s), currentExposure_(0s),\n> @@ -185,14 +196,20 @@ void Agc::filterExposure()\n>  /**\n>   * \\brief Estimate the new exposure and gain values\n>   * \\param[inout] frameContext The shared IPA frame Context\n> + * \\param[in] currentYGain The gain calculated on the current brightness level\n>   */\n> -void Agc::computeExposure(IPAFrameContext &frameContext)\n> +void Agc::computeExposure(IPAFrameContext &frameContext, double currentYGain)\n>  {\n>  \t/* Get the effective exposure and gain applied on the sensor. */\n>  \tuint32_t exposure = frameContext.sensor.exposure;\n>  \tdouble analogueGain = frameContext.sensor.gain;\n>  \n> -\t/* Estimate the gain needed to have the proportion wanted */\n> +\t/*\n> +\t * Estimate the gain needed to have the proportion of pixels in a given\n> +\t * range wanted. iqMean_ returns the mean value of the top 2% of the\n> +\t * cumulative histogram, and we want it to be as close as possible to a\n> +\t * configured target.\n> +\t */\n>  \tdouble evGain = kEvGainTarget * knumHistogramBins / iqMean_;\n>  \n>  \tif (std::abs(evGain - 1.0) < 0.01) {\n> @@ -202,6 +219,7 @@ void Agc::computeExposure(IPAFrameContext &frameContext)\n>  \t}\n>  \n>  \t/* extracted from Rpi::Agc::computeTargetExposure */\n> +\n>  \t/* Calculate the shutter time in seconds */\n>  \tutils::Duration currentShutter = exposure * lineDuration_;\n>  \tLOG(IPU3Agc, Debug) << \"Actual total exposure \" << currentShutter * analogueGain\n> @@ -209,6 +227,14 @@ void Agc::computeExposure(IPAFrameContext &frameContext)\n>  \t\t\t    << \" Gain \" << analogueGain\n>  \t\t\t    << \" Needed ev gain \" << evGain;\n>  \n> +\tif (evGain < currentYGain)\n> +\t\tevGain = currentYGain;\n> +\n> +\t/* Consider within 1% of the target as correctly exposed */\n> +\tif (std::abs(evGain - 1.0) < 0.01)\n> +\t\tLOG(IPU3Agc, Debug) << \"We are well exposed (iqMean = \"\n> +\t\t\t\t    << iqMean_ << \")\";\n\nI thought we saw this stanza in the last patch, right before this hunk?\n\n> +\n>  \t/*\n>  \t * Calculate the current exposure value for the scene as the latest\n>  \t * exposure value applied multiplied by the new estimated gain.\n> @@ -257,6 +283,56 @@ void Agc::computeExposure(IPAFrameContext &frameContext)\n>  \tprevExposureValue_ = shutterTime * analogueGain;\n>  }\n>  \n> +/**\n> + * \\brief Estimate the average brightness of the frame\n> + * \\param[in] frameContext The shared IPA frame context\n> + * \\param[in] grid The grid used to store the statistics in the IPU3\n> + * \\param[in] stats The IPU3 statistics and ISP results\n> + * \\param[in] currentYGain The gain calculated on the current brightness level\n> + * \\return The normalized luma\n> + *\n> + * Luma is the weighted sum of gamma-compressed R′G′B′ components of a color\n> + * video. The luma values are normalized as 0.0 to 1.0, with 1.0 being a\n> + * theoretical perfect reflector of 100% reference white. We use the Rec. 601\n> + * luma here.\n> + *\n> + * More detailed information can be found in:\n> + * https://en.wikipedia.org/wiki/Luma_(video)\n> + */\n> +double Agc::computeInitialY(IPAFrameContext &frameContext,\n> +\t\t\t    const ipu3_uapi_grid_config &grid,\n> +\t\t\t    const ipu3_uapi_stats_3a *stats,\n> +\t\t\t    double currentYGain)\n> +{\n> +\tdouble redSum = 0, greenSum = 0, blueSum = 0;\n> +\n> +\tfor (unsigned int cellY = 0; cellY < grid.height; cellY++) {\n> +\t\tfor (unsigned int cellX = 0; cellX < grid.width; cellX++) {\n> +\t\t\tuint32_t cellPosition = cellY * stride_ + cellX;\n> +\n> +\t\t\tconst ipu3_uapi_awb_set_item *cell =\n> +\t\t\t\treinterpret_cast<const ipu3_uapi_awb_set_item *>(\n> +\t\t\t\t\t&stats->awb_raw_buffer.meta_data[cellPosition]\n> +\t\t\t\t);\n> +\n> +\t\t\tredSum += cell->R_avg * currentYGain;\n> +\t\t\tgreenSum += (cell->Gr_avg + cell->Gb_avg) / 2 * currentYGain;\n> +\t\t\tblueSum += cell->B_avg * currentYGain;\n> +\t\t}\n> +\t}\n> +\n> +\t/*\n> +\t * Estimate the sum of the brightness values, weighted with the gains\n> +\t * applied on the channels in AWB as the Rec. 601 luma.\n> +\t */\n> +\tdouble Y_sum = redSum * frameContext.awb.gains.red * .299 +\n> +\t\t       greenSum * frameContext.awb.gains.green * .587 +\n> +\t\t       blueSum * frameContext.awb.gains.blue * .114;\n> +\n> +\t/* Return the normalized relative luminance. */\n> +\treturn Y_sum / (grid.height * grid.width) / kMaxLuminance;\n> +}\n> +\n>  /**\n>   * \\brief Process IPU3 statistics, and run AGC operations\n>   * \\param[in] context The shared IPA context\n> @@ -268,7 +344,29 @@ void Agc::computeExposure(IPAFrameContext &frameContext)\n>  void Agc::process(IPAContext &context, const ipu3_uapi_stats_3a *stats)\n>  {\n>  \tmeasureBrightness(stats, context.configuration.grid.bdsGrid);\n> -\tcomputeExposure(context.frameContext);\n> +\n> +\tdouble currentYGain = 1.0;\n> +\tdouble targetY = kNormalizedLumaTarget;\n> +\n> +\t/*\n> +\t * Do this calculation a few times as brightness increase can be\n> +\t * non-linear when there are saturated regions.\n> +\t */\n> +\tfor (int i = 0; i < 8; i++) {\n> +\t\tdouble initialY = computeInitialY(context.frameContext,\n> +\t\t\t\t\t\t  context.configuration.grid.bdsGrid,\n> +\t\t\t\t\t\t  stats, currentYGain);\n> +\t\tdouble extra_gain = std::min(10.0, targetY / (initialY + .001));\n> +\n> +\t\tcurrentYGain *= extra_gain;\n> +\t\tLOG(IPU3Agc, Debug) << \"Initial Y \" << initialY\n> +\t\t\t\t    << \" target \" << targetY\n> +\t\t\t\t    << \" gives gain \" << currentYGain;\n> +\t\tif (extra_gain < 1.01)\n> +\t\t\tbreak;\n> +\t}\n> +\n> +\tcomputeExposure(context.frameContext, currentYGain);\n>  \tframeCount_++;\n>  }\n>  \n> diff --git a/src/ipa/ipu3/algorithms/agc.h b/src/ipa/ipu3/algorithms/agc.h\n> index f0db25ee..79736283 100644\n> --- a/src/ipa/ipu3/algorithms/agc.h\n> +++ b/src/ipa/ipu3/algorithms/agc.h\n> @@ -34,7 +34,11 @@ private:\n>  \tvoid measureBrightness(const ipu3_uapi_stats_3a *stats,\n>  \t\t\t       const ipu3_uapi_grid_config &grid);\n>  \tvoid filterExposure();\n> -\tvoid computeExposure(IPAFrameContext &frameContext);\n> +\tvoid computeExposure(IPAFrameContext &frameContext, double currentYGain);\n> +\tdouble computeInitialY(IPAFrameContext &frameContext,\n> +\t\t\t       const ipu3_uapi_grid_config &grid,\n> +\t\t\t       const ipu3_uapi_stats_3a *stats,\n> +\t\t\t       double currentYGain);\n\nThe rest looks good.\n\nReviewed-by: Paul Elder <paul.elder@ideasonboard.com>\n\n>  \n>  \tuint64_t frameCount_;\n>  \tuint64_t lastFrame_;\n> -- \n> 2.32.0\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 62C43BDB1C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 12 Nov 2021 23:13:07 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id BC4596036E;\n\tSat, 13 Nov 2021 00:13:06 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 6A882600B5\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 13 Nov 2021 00:13:05 +0100 (CET)","from jade.amanokami.net (KD027085206038.au-net.ne.jp\n\t[27.85.206.38])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 0BA509CA;\n\tSat, 13 Nov 2021 00:13:02 +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=\"uICiP3Xc\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1636758785;\n\tbh=n3CaAT+mMyBG+nOqZLOUfF8grD3xPm9ibHQ2R3KegDw=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=uICiP3Xc5DuK6rYtVBmijn8FIRbqjDJoBoVUOveccgwbAMQgUrW4Rdogq20XBvfI3\n\tdEEXozi52JBTrgB5p/4M5lyzetHhd+zz3cp4H00zKLIRxbv9Yno3Y8kS5ai1RRvYTd\n\t1fwn/pN+p4wHoem7abehatvzi5K6hdQKX0C1KAuE=","Date":"Sat, 13 Nov 2021 08:12:54 +0900","From":"Paul Elder <paul.elder@ideasonboard.com>","To":"Jean-Michel Hautbois <jeanmichel.hautbois@ideasonboard.com>","Message-ID":"<20211112231254.GE8453@jade.amanokami.net>","References":"<20211111140928.136111-1-jeanmichel.hautbois@ideasonboard.com>\n\t<20211111140928.136111-8-jeanmichel.hautbois@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20211111140928.136111-8-jeanmichel.hautbois@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v4 07/14] ipa: ipu3: agc: Improve gain\n\tcalculation","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>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":20943,"web_url":"https://patchwork.libcamera.org/comment/20943/","msgid":"<a88e0c9d-2398-c6d8-09cc-c4721ce65bcb@ideasonboard.com>","date":"2021-11-13T08:19:30","subject":"Re: [libcamera-devel] [PATCH v4 07/14] ipa: ipu3: agc: Improve gain\n\tcalculation","submitter":{"id":75,"url":"https://patchwork.libcamera.org/api/people/75/","name":"Jean-Michel Hautbois","email":"jeanmichel.hautbois@ideasonboard.com"},"content":"Hi Paul,\n\nOn 13/11/2021 00:12, Paul Elder wrote:\n> Hi Jean-Michel,\n> \n> On Thu, Nov 11, 2021 at 03:09:21PM +0100, Jean-Michel Hautbois wrote:\n>> When an image is partially saturated, its brightness is not increasing\n>> linearly when the shutter time or gain increases. It is a big issue with\n>> a backlight as the algorithm is fading to darkness right now.\n>>\n>> Introduce a function to estimate the brightness of the frame, based on\n>> the current exposure/gain and loop on it several times to estimate it\n>> again and approach the non linear function.\n>>\n>> Inspired-by: 7de5506c30b3 (\"libcamera: src: ipa: raspberrypi: agc: Improve gain update calculation for partly saturated images\")\n>> Signed-off-by: Jean-Michel Hautbois <jeanmichel.hautbois@ideasonboard.com>\n>> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n>> ---\n>>   src/ipa/ipu3/algorithms/agc.cpp | 104 +++++++++++++++++++++++++++++++-\n>>   src/ipa/ipu3/algorithms/agc.h   |   6 +-\n>>   2 files changed, 106 insertions(+), 4 deletions(-)\n>>\n>> diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp\n>> index 61ca8b3f..a34f070e 100644\n>> --- a/src/ipa/ipu3/algorithms/agc.cpp\n>> +++ b/src/ipa/ipu3/algorithms/agc.cpp\n>> @@ -67,6 +67,17 @@ static constexpr uint32_t kMinCellsPerZoneRatio = 255 * 20 / 100;\n>>   /* Number of frames to wait before calculating stats on minimum exposure */\n>>   static constexpr uint32_t kNumStartupFrames = 10;\n>>   \n>> +/* Maximum luminance used for brightness normalization */\n>> +static constexpr uint32_t kMaxLuminance = 255;\n>> +\n>> +/*\n>> + * Normalized luma value target.\n>> + *\n>> + * It's a number that's chosen so that, when the camera points at a grey\n>> + * target, the resulting image brightness is considered right.\n>> + */\n>> +static constexpr double kNormalizedLumaTarget = 0.16;\n>> +\n>>   Agc::Agc()\n>>   \t: frameCount_(0), iqMean_(0.0), lineDuration_(0s), minExposureLines_(0),\n>>   \t  maxExposureLines_(0), filteredExposure_(0s), currentExposure_(0s),\n>> @@ -185,14 +196,20 @@ void Agc::filterExposure()\n>>   /**\n>>    * \\brief Estimate the new exposure and gain values\n>>    * \\param[inout] frameContext The shared IPA frame Context\n>> + * \\param[in] currentYGain The gain calculated on the current brightness level\n>>    */\n>> -void Agc::computeExposure(IPAFrameContext &frameContext)\n>> +void Agc::computeExposure(IPAFrameContext &frameContext, double currentYGain)\n>>   {\n>>   \t/* Get the effective exposure and gain applied on the sensor. */\n>>   \tuint32_t exposure = frameContext.sensor.exposure;\n>>   \tdouble analogueGain = frameContext.sensor.gain;\n>>   \n>> -\t/* Estimate the gain needed to have the proportion wanted */\n>> +\t/*\n>> +\t * Estimate the gain needed to have the proportion of pixels in a given\n>> +\t * range wanted. iqMean_ returns the mean value of the top 2% of the\n>> +\t * cumulative histogram, and we want it to be as close as possible to a\n>> +\t * configured target.\n>> +\t */\n>>   \tdouble evGain = kEvGainTarget * knumHistogramBins / iqMean_;\n>>   \n>>   \tif (std::abs(evGain - 1.0) < 0.01) {\n>> @@ -202,6 +219,7 @@ void Agc::computeExposure(IPAFrameContext &frameContext)\n>>   \t}\n>>   \n>>   \t/* extracted from Rpi::Agc::computeTargetExposure */\n>> +\n>>   \t/* Calculate the shutter time in seconds */\n>>   \tutils::Duration currentShutter = exposure * lineDuration_;\n>>   \tLOG(IPU3Agc, Debug) << \"Actual total exposure \" << currentShutter * analogueGain\n>> @@ -209,6 +227,14 @@ void Agc::computeExposure(IPAFrameContext &frameContext)\n>>   \t\t\t    << \" Gain \" << analogueGain\n>>   \t\t\t    << \" Needed ev gain \" << evGain;\n>>   \n>> +\tif (evGain < currentYGain)\n>> +\t\tevGain = currentYGain;\n>> +\n>> +\t/* Consider within 1% of the target as correctly exposed */\n>> +\tif (std::abs(evGain - 1.0) < 0.01)\n>> +\t\tLOG(IPU3Agc, Debug) << \"We are well exposed (iqMean = \"\n>> +\t\t\t\t    << iqMean_ << \")\";\n> \n> I thought we saw this stanza in the last patch, right before this hunk?\n\nGood catch ! This is indeed a bug :-).\nI will send v5, with all the reviewed-by and commit messages changed, \nwith this bug fixed.\n\n> \n>> +\n>>   \t/*\n>>   \t * Calculate the current exposure value for the scene as the latest\n>>   \t * exposure value applied multiplied by the new estimated gain.\n>> @@ -257,6 +283,56 @@ void Agc::computeExposure(IPAFrameContext &frameContext)\n>>   \tprevExposureValue_ = shutterTime * analogueGain;\n>>   }\n>>   \n>> +/**\n>> + * \\brief Estimate the average brightness of the frame\n>> + * \\param[in] frameContext The shared IPA frame context\n>> + * \\param[in] grid The grid used to store the statistics in the IPU3\n>> + * \\param[in] stats The IPU3 statistics and ISP results\n>> + * \\param[in] currentYGain The gain calculated on the current brightness level\n>> + * \\return The normalized luma\n>> + *\n>> + * Luma is the weighted sum of gamma-compressed R′G′B′ components of a color\n>> + * video. The luma values are normalized as 0.0 to 1.0, with 1.0 being a\n>> + * theoretical perfect reflector of 100% reference white. We use the Rec. 601\n>> + * luma here.\n>> + *\n>> + * More detailed information can be found in:\n>> + * https://en.wikipedia.org/wiki/Luma_(video)\n>> + */\n>> +double Agc::computeInitialY(IPAFrameContext &frameContext,\n>> +\t\t\t    const ipu3_uapi_grid_config &grid,\n>> +\t\t\t    const ipu3_uapi_stats_3a *stats,\n>> +\t\t\t    double currentYGain)\n>> +{\n>> +\tdouble redSum = 0, greenSum = 0, blueSum = 0;\n>> +\n>> +\tfor (unsigned int cellY = 0; cellY < grid.height; cellY++) {\n>> +\t\tfor (unsigned int cellX = 0; cellX < grid.width; cellX++) {\n>> +\t\t\tuint32_t cellPosition = cellY * stride_ + cellX;\n>> +\n>> +\t\t\tconst ipu3_uapi_awb_set_item *cell =\n>> +\t\t\t\treinterpret_cast<const ipu3_uapi_awb_set_item *>(\n>> +\t\t\t\t\t&stats->awb_raw_buffer.meta_data[cellPosition]\n>> +\t\t\t\t);\n>> +\n>> +\t\t\tredSum += cell->R_avg * currentYGain;\n>> +\t\t\tgreenSum += (cell->Gr_avg + cell->Gb_avg) / 2 * currentYGain;\n>> +\t\t\tblueSum += cell->B_avg * currentYGain;\n>> +\t\t}\n>> +\t}\n>> +\n>> +\t/*\n>> +\t * Estimate the sum of the brightness values, weighted with the gains\n>> +\t * applied on the channels in AWB as the Rec. 601 luma.\n>> +\t */\n>> +\tdouble Y_sum = redSum * frameContext.awb.gains.red * .299 +\n>> +\t\t       greenSum * frameContext.awb.gains.green * .587 +\n>> +\t\t       blueSum * frameContext.awb.gains.blue * .114;\n>> +\n>> +\t/* Return the normalized relative luminance. */\n>> +\treturn Y_sum / (grid.height * grid.width) / kMaxLuminance;\n>> +}\n>> +\n>>   /**\n>>    * \\brief Process IPU3 statistics, and run AGC operations\n>>    * \\param[in] context The shared IPA context\n>> @@ -268,7 +344,29 @@ void Agc::computeExposure(IPAFrameContext &frameContext)\n>>   void Agc::process(IPAContext &context, const ipu3_uapi_stats_3a *stats)\n>>   {\n>>   \tmeasureBrightness(stats, context.configuration.grid.bdsGrid);\n>> -\tcomputeExposure(context.frameContext);\n>> +\n>> +\tdouble currentYGain = 1.0;\n>> +\tdouble targetY = kNormalizedLumaTarget;\n>> +\n>> +\t/*\n>> +\t * Do this calculation a few times as brightness increase can be\n>> +\t * non-linear when there are saturated regions.\n>> +\t */\n>> +\tfor (int i = 0; i < 8; i++) {\n>> +\t\tdouble initialY = computeInitialY(context.frameContext,\n>> +\t\t\t\t\t\t  context.configuration.grid.bdsGrid,\n>> +\t\t\t\t\t\t  stats, currentYGain);\n>> +\t\tdouble extra_gain = std::min(10.0, targetY / (initialY + .001));\n>> +\n>> +\t\tcurrentYGain *= extra_gain;\n>> +\t\tLOG(IPU3Agc, Debug) << \"Initial Y \" << initialY\n>> +\t\t\t\t    << \" target \" << targetY\n>> +\t\t\t\t    << \" gives gain \" << currentYGain;\n>> +\t\tif (extra_gain < 1.01)\n>> +\t\t\tbreak;\n>> +\t}\n>> +\n>> +\tcomputeExposure(context.frameContext, currentYGain);\n>>   \tframeCount_++;\n>>   }\n>>   \n>> diff --git a/src/ipa/ipu3/algorithms/agc.h b/src/ipa/ipu3/algorithms/agc.h\n>> index f0db25ee..79736283 100644\n>> --- a/src/ipa/ipu3/algorithms/agc.h\n>> +++ b/src/ipa/ipu3/algorithms/agc.h\n>> @@ -34,7 +34,11 @@ private:\n>>   \tvoid measureBrightness(const ipu3_uapi_stats_3a *stats,\n>>   \t\t\t       const ipu3_uapi_grid_config &grid);\n>>   \tvoid filterExposure();\n>> -\tvoid computeExposure(IPAFrameContext &frameContext);\n>> +\tvoid computeExposure(IPAFrameContext &frameContext, double currentYGain);\n>> +\tdouble computeInitialY(IPAFrameContext &frameContext,\n>> +\t\t\t       const ipu3_uapi_grid_config &grid,\n>> +\t\t\t       const ipu3_uapi_stats_3a *stats,\n>> +\t\t\t       double currentYGain);\n> \n> The rest looks good.\n> \n> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>\n> \n>>   \n>>   \tuint64_t frameCount_;\n>>   \tuint64_t lastFrame_;\n>> -- \n>> 2.32.0\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 0A486BDB1C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSat, 13 Nov 2021 08:19:37 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 2960960368;\n\tSat, 13 Nov 2021 09:19:36 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id ADB3B60121\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 13 Nov 2021 09:19:34 +0100 (CET)","from [IPV6:2a01:e0a:169:7140:4d35:9445:6881:4ffd] (unknown\n\t[IPv6:2a01:e0a:169:7140:4d35:9445:6881:4ffd])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 4057255C;\n\tSat, 13 Nov 2021 09:19:34 +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=\"dxbJ/x8H\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1636791574;\n\tbh=LPdRmUUS1hx3Sq+FgTTR83wsfsgWgFhRy7YqaAaeRzg=;\n\th=Date:Subject:To:Cc:References:From:In-Reply-To:From;\n\tb=dxbJ/x8HRsAYP6kUa8NbrojxPYX+pQywe8vVPBSozf3wXSDVFRsBOBI8USD9/kGD+\n\t9DetYtud4sHZj3lTIpUzKYjRXFWiVAowYyau1JSnMEXmARvhWgzJ8klh368VdYwVd9\n\tJ8HCs3ugZ5L2WrkVgoXpOV7rCT9cVLneUCaV/R70=","Message-ID":"<a88e0c9d-2398-c6d8-09cc-c4721ce65bcb@ideasonboard.com>","Date":"Sat, 13 Nov 2021 09:19:30 +0100","MIME-Version":"1.0","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101\n\tThunderbird/91.2.1","Content-Language":"en-US","To":"Paul Elder <paul.elder@ideasonboard.com>","References":"<20211111140928.136111-1-jeanmichel.hautbois@ideasonboard.com>\n\t<20211111140928.136111-8-jeanmichel.hautbois@ideasonboard.com>\n\t<20211112231254.GE8453@jade.amanokami.net>","From":"Jean-Michel Hautbois <jeanmichel.hautbois@ideasonboard.com>","In-Reply-To":"<20211112231254.GE8453@jade.amanokami.net>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","Subject":"Re: [libcamera-devel] [PATCH v4 07/14] ipa: ipu3: agc: Improve gain\n\tcalculation","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>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]