[{"id":20829,"web_url":"https://patchwork.libcamera.org/comment/20829/","msgid":"<163658335669.2121661.10867876860392000584@Monstersaurus>","date":"2021-11-10T22:29:16","subject":"Re: [libcamera-devel] [PATCH v2 07/14] ipa: ipu3: agc: Improve gain\n\tcalculation","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Jean-Michel Hautbois (2021-11-10 19:58:54)\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> ---\n>  src/ipa/ipu3/algorithms/agc.cpp | 103 +++++++++++++++++++++++++++++++-\n>  src/ipa/ipu3/algorithms/agc.h   |   6 +-\n>  2 files changed, 105 insertions(+), 4 deletions(-)\n> \n> diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp\n> index 119a7938..ee37a9d5 100644\n> --- a/src/ipa/ipu3/algorithms/agc.cpp\n> +++ b/src/ipa/ipu3/algorithms/agc.cpp\n> @@ -67,6 +67,9 @@ 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>  Agc::Agc()\n>         : frameCount_(0), iqMean_(0.0), lineDuration_(0s), minExposureLines_(0),\n>           maxExposureLines_(0), filteredExposure_(0s), currentExposure_(0s),\n> @@ -186,10 +189,16 @@ void Agc::filterExposure()\n>   * \\brief Estimate the new exposure and gain values\n>   * \\param[inout] exposure The exposure value reference as a number of lines\n>   * \\param[inout] gain The gain reference to be updated\n> + * \\param[in] currentYGain The gain calculated on the current brightness level\n>   */\n> -void Agc::computeExposure(uint32_t &exposure, double &analogueGain)\n> +void Agc::computeExposure(uint32_t &exposure, double &analogueGain, double currentYGain)\n>  {\n> -       /* Estimate the gain needed to have the proportion wanted */\n> +       /*\n> +        * Estimate the gain needed to have the proportion of pixels in a given\n> +        * range wanted. iqMean_ returns the mean value of the top 2% of the\n> +        * cumulative histogram, and we want it to be as close as possible to a\n> +        * configured target.\n> +        */\n>         double evGain = kEvGainTarget * knumHistogramBins / iqMean_;\n>  \n>         if (std::abs(evGain - 1.0) < 0.01) {\n> @@ -199,6 +208,7 @@ void Agc::computeExposure(uint32_t &exposure, double &analogueGain)\n>         }\n>  \n>         /* extracted from Rpi::Agc::computeTargetExposure */\n> +\n>         /* Calculate the shutter time in seconds */\n>         utils::Duration currentShutter = exposure * lineDuration_;\n>         LOG(IPU3Agc, Debug) << \"Actual total exposure \" << currentShutter * analogueGain\n> @@ -206,6 +216,14 @@ void Agc::computeExposure(uint32_t &exposure, double &analogueGain)\n>                             << \" Gain \" << analogueGain\n>                             << \" Needed ev gain \" << evGain;\n>  \n> +       if (evGain < currentYGain)\n> +               evGain = currentYGain;\n> +\n> +       /* Consider within 1% of the target as correctly exposed */\n> +       if (std::abs(evGain - 1.0) < 0.01)\n> +               LOG(IPU3Agc, Debug) << \"We are well exposed (iqMean = \"\n> +                                   << iqMean_ << \")\";\n> +\n>         /*\n>          * Calculate the current exposure value for the scene as the latest\n>          * exposure value applied multiplied by the new estimated gain.\n> @@ -253,6 +271,57 @@ void Agc::computeExposure(uint32_t &exposure, double &analogueGain)\n>         prevExposureValue_ = shutterTime * analogueGain;\n>  }\n>  \n> +/**\n> + * \\brief Estimate the average brightness of the frame\n> + * \\param[in] context The shared IPA context\n\nframeContext?\n\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\nThank you - that all helps a lot in making it understandable (and being\nexplicit about where these conversions are from/represent).\n\n\n> + */\n> +double Agc::computeInitialY(IPAFrameContext &frameContext,\n> +                           const ipu3_uapi_grid_config &grid,\n> +                           const ipu3_uapi_stats_3a *stats,\n> +                           double currentYGain)\n> +{\n> +       double redSum = 0, greenSum = 0, blueSum = 0;\n> +\n> +       for (unsigned int cellY = 0; cellY < grid.height; cellY++) {\n> +               for (unsigned int cellX = 0; cellX < grid.width; cellX++) {\n> +                       uint32_t cellPosition = cellY * stride_ + cellX;\n> +\n> +                       const ipu3_uapi_awb_set_item *cell =\n> +                               reinterpret_cast<const ipu3_uapi_awb_set_item *>(\n> +                                       &stats->awb_raw_buffer.meta_data[cellPosition]\n> +                               );\n> +\n> +                       redSum += cell->R_avg * currentYGain;\n> +                       greenSum += (cell->Gr_avg + cell->Gb_avg) / 2 * currentYGain;\n> +                       blueSum += cell->B_avg * currentYGain;\n> +               }\n> +       }\n> +\n> +       /*\n> +        * Estimate the sum of the brightness values, weighted with the gains\n> +        * applied on the channels in AWB as the Rec. 601 luma.\n> +        */\n> +       double Y_sum = redSum * frameContext.awb.gains.red * .299 +\n> +                      greenSum * frameContext.awb.gains.green * .587 +\n> +                      blueSum * frameContext.awb.gains.blue * .114;\n> +\n> +       /* Return the normalized relative luminance. */\n> +       return Y_sum / (grid.height * grid.width) / kMaxLuminance;\n> +}\n> +\n> +\n>  /**\n>   * \\brief Process IPU3 statistics, and run AGC operations\n>   * \\param[in] context The shared IPA context\n> @@ -267,7 +336,35 @@ void Agc::process(IPAContext &context, const ipu3_uapi_stats_3a *stats)\n>         uint32_t &exposure = context.frameContext.agc.exposure;\n>         double &analogueGain = context.frameContext.agc.gain;\n>         measureBrightness(stats, context.configuration.grid.bdsGrid);\n> -       computeExposure(exposure, analogueGain);\n> +\n> +       double currentYGain = 1.0;\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\nI think I'd change s/considered right/considered correct/ - but it's not\ncritical.\n\n> +        */\n> +       double targetY = 0.16;\n\nWow - this is a big change from the 60 that it was before. Did something\nfundamental happen?\n\nWill this be required to come from some sensor tuning profile at a later\ndate?\n\nIf so - I'd add a \n\t\\todo targetY should be calibrated by sensor tuning\n\n(Same for any other constant that has been manually tuned at present).\n\nIs targetY ever changed in the code? If not - perhaps it should be a\nconstexpr to show that it isn't modified.\n\nBut aside from those which are all minor.\n\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n> +\n> +       /*\n> +        * Do this calculation a few times as brightness increase can be\n> +        * non-linear when there are saturated regions.\n> +        */\n> +       for (int i = 0; i < 8; i++) {\n> +               double initialY = computeInitialY(context.frameContext,\n> +                                                 context.configuration.grid.bdsGrid,\n> +                                                 stats, currentYGain);\n> +               double extra_gain = std::min(10.0, targetY / (initialY + .001));\n> +\n> +               currentYGain *= extra_gain;\n> +               LOG(IPU3Agc, Debug) << \"Initial Y \" << initialY\n> +                                   << \" target \" << targetY\n> +                                   << \" gives gain \" << currentYGain;\n> +               if (extra_gain < 1.01)\n> +                       break;\n> +       }\n> +\n> +       computeExposure(exposure, analogueGain, currentYGain);\n>         frameCount_++;\n>  }\n>  \n> diff --git a/src/ipa/ipu3/algorithms/agc.h b/src/ipa/ipu3/algorithms/agc.h\n> index 69e0b831..0a9152a9 100644\n> --- a/src/ipa/ipu3/algorithms/agc.h\n> +++ b/src/ipa/ipu3/algorithms/agc.h\n> @@ -34,7 +34,11 @@ private:\n>         void measureBrightness(const ipu3_uapi_stats_3a *stats,\n>                                const ipu3_uapi_grid_config &grid);\n>         void filterExposure();\n> -       void computeExposure(uint32_t &exposure, double &gain);\n> +       void computeExposure(uint32_t &exposure, double &gain, double currentYGain);\n> +       double computeInitialY(IPAFrameContext &frameContext,\n> +                              const ipu3_uapi_grid_config &grid,\n> +                              const ipu3_uapi_stats_3a *stats,\n> +                              double currentYGain);\n>  \n>         uint64_t frameCount_;\n>         uint64_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 24DCABF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 10 Nov 2021 22:29:22 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 95D326034E;\n\tWed, 10 Nov 2021 23:29:21 +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 C54FA6033C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 10 Nov 2021 23:29:19 +0100 (CET)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust3082.18-1.cable.virginm.net [86.31.172.11])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 57CA98B6;\n\tWed, 10 Nov 2021 23:29:19 +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=\"F2OHildY\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1636583359;\n\tbh=Y/AoydYU5QaynTbk5Vy4Ysg2vGtCL1gsSEbZhJVmV80=;\n\th=In-Reply-To:References:Subject:From:To:Date:From;\n\tb=F2OHildYZAR4eiGvmITwQ7v+nikD/YzlESO2abOY7NvDfloYmdckhwtcBetKRiVJD\n\tx2RcUZqXKt3EPBOWF7NMSxJME4WFx1CatAxXk/1HTvbcLBD7CANksK0lf0tAcy1eG1\n\tEzrROXlhhsdtLymvRF4AKBc/yliw0OfOru60tdBU=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20211110195901.85597-8-jeanmichel.hautbois@ideasonboard.com>","References":"<20211110195901.85597-1-jeanmichel.hautbois@ideasonboard.com>\n\t<20211110195901.85597-8-jeanmichel.hautbois@ideasonboard.com>","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","To":"Jean-Michel Hautbois <jeanmichel.hautbois@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Wed, 10 Nov 2021 22:29:16 +0000","Message-ID":"<163658335669.2121661.10867876860392000584@Monstersaurus>","User-Agent":"alot/0.10","Subject":"Re: [libcamera-devel] [PATCH v2 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>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":20839,"web_url":"https://patchwork.libcamera.org/comment/20839/","msgid":"<5c733b4e-f835-912f-a448-32a3876a1f1f@ideasonboard.com>","date":"2021-11-11T07:07:30","subject":"Re: [libcamera-devel] [PATCH v2 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 Kieran,\n\nOn 10/11/2021 23:29, Kieran Bingham wrote:\n> Quoting Jean-Michel Hautbois (2021-11-10 19:58:54)\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>> ---\n>>   src/ipa/ipu3/algorithms/agc.cpp | 103 +++++++++++++++++++++++++++++++-\n>>   src/ipa/ipu3/algorithms/agc.h   |   6 +-\n>>   2 files changed, 105 insertions(+), 4 deletions(-)\n>>\n>> diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp\n>> index 119a7938..ee37a9d5 100644\n>> --- a/src/ipa/ipu3/algorithms/agc.cpp\n>> +++ b/src/ipa/ipu3/algorithms/agc.cpp\n>> @@ -67,6 +67,9 @@ 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>>   Agc::Agc()\n>>          : frameCount_(0), iqMean_(0.0), lineDuration_(0s), minExposureLines_(0),\n>>            maxExposureLines_(0), filteredExposure_(0s), currentExposure_(0s),\n>> @@ -186,10 +189,16 @@ void Agc::filterExposure()\n>>    * \\brief Estimate the new exposure and gain values\n>>    * \\param[inout] exposure The exposure value reference as a number of lines\n>>    * \\param[inout] gain The gain reference to be updated\n>> + * \\param[in] currentYGain The gain calculated on the current brightness level\n>>    */\n>> -void Agc::computeExposure(uint32_t &exposure, double &analogueGain)\n>> +void Agc::computeExposure(uint32_t &exposure, double &analogueGain, double currentYGain)\n>>   {\n>> -       /* Estimate the gain needed to have the proportion wanted */\n>> +       /*\n>> +        * Estimate the gain needed to have the proportion of pixels in a given\n>> +        * range wanted. iqMean_ returns the mean value of the top 2% of the\n>> +        * cumulative histogram, and we want it to be as close as possible to a\n>> +        * configured target.\n>> +        */\n>>          double evGain = kEvGainTarget * knumHistogramBins / iqMean_;\n>>   \n>>          if (std::abs(evGain - 1.0) < 0.01) {\n>> @@ -199,6 +208,7 @@ void Agc::computeExposure(uint32_t &exposure, double &analogueGain)\n>>          }\n>>   \n>>          /* extracted from Rpi::Agc::computeTargetExposure */\n>> +\n>>          /* Calculate the shutter time in seconds */\n>>          utils::Duration currentShutter = exposure * lineDuration_;\n>>          LOG(IPU3Agc, Debug) << \"Actual total exposure \" << currentShutter * analogueGain\n>> @@ -206,6 +216,14 @@ void Agc::computeExposure(uint32_t &exposure, double &analogueGain)\n>>                              << \" Gain \" << analogueGain\n>>                              << \" Needed ev gain \" << evGain;\n>>   \n>> +       if (evGain < currentYGain)\n>> +               evGain = currentYGain;\n>> +\n>> +       /* Consider within 1% of the target as correctly exposed */\n>> +       if (std::abs(evGain - 1.0) < 0.01)\n>> +               LOG(IPU3Agc, Debug) << \"We are well exposed (iqMean = \"\n>> +                                   << iqMean_ << \")\";\n>> +\n>>          /*\n>>           * Calculate the current exposure value for the scene as the latest\n>>           * exposure value applied multiplied by the new estimated gain.\n>> @@ -253,6 +271,57 @@ void Agc::computeExposure(uint32_t &exposure, double &analogueGain)\n>>          prevExposureValue_ = shutterTime * analogueGain;\n>>   }\n>>   \n>> +/**\n>> + * \\brief Estimate the average brightness of the frame\n>> + * \\param[in] context The shared IPA context\n> \n> frameContext?\n> \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> Thank you - that all helps a lot in making it understandable (and being\n> explicit about where these conversions are from/represent).\n> \n> \n>> + */\n>> +double Agc::computeInitialY(IPAFrameContext &frameContext,\n>> +                           const ipu3_uapi_grid_config &grid,\n>> +                           const ipu3_uapi_stats_3a *stats,\n>> +                           double currentYGain)\n>> +{\n>> +       double redSum = 0, greenSum = 0, blueSum = 0;\n>> +\n>> +       for (unsigned int cellY = 0; cellY < grid.height; cellY++) {\n>> +               for (unsigned int cellX = 0; cellX < grid.width; cellX++) {\n>> +                       uint32_t cellPosition = cellY * stride_ + cellX;\n>> +\n>> +                       const ipu3_uapi_awb_set_item *cell =\n>> +                               reinterpret_cast<const ipu3_uapi_awb_set_item *>(\n>> +                                       &stats->awb_raw_buffer.meta_data[cellPosition]\n>> +                               );\n>> +\n>> +                       redSum += cell->R_avg * currentYGain;\n>> +                       greenSum += (cell->Gr_avg + cell->Gb_avg) / 2 * currentYGain;\n>> +                       blueSum += cell->B_avg * currentYGain;\n>> +               }\n>> +       }\n>> +\n>> +       /*\n>> +        * Estimate the sum of the brightness values, weighted with the gains\n>> +        * applied on the channels in AWB as the Rec. 601 luma.\n>> +        */\n>> +       double Y_sum = redSum * frameContext.awb.gains.red * .299 +\n>> +                      greenSum * frameContext.awb.gains.green * .587 +\n>> +                      blueSum * frameContext.awb.gains.blue * .114;\n>> +\n>> +       /* Return the normalized relative luminance. */\n>> +       return Y_sum / (grid.height * grid.width) / kMaxLuminance;\n>> +}\n>> +\n>> +\n>>   /**\n>>    * \\brief Process IPU3 statistics, and run AGC operations\n>>    * \\param[in] context The shared IPA context\n>> @@ -267,7 +336,35 @@ void Agc::process(IPAContext &context, const ipu3_uapi_stats_3a *stats)\n>>          uint32_t &exposure = context.frameContext.agc.exposure;\n>>          double &analogueGain = context.frameContext.agc.gain;\n>>          measureBrightness(stats, context.configuration.grid.bdsGrid);\n>> -       computeExposure(exposure, analogueGain);\n>> +\n>> +       double currentYGain = 1.0;\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> I think I'd change s/considered right/considered correct/ - but it's not\n> critical.\n> \n>> +        */\n>> +       double targetY = 0.16;\n> \n> Wow - this is a big change from the 60 that it was before. Did something\n> fundamental happen?\n\nI am now returning the normalized luma from computeInitialY() which is \nbasically dividing it by 255. This is the same as setting targetY = 41 \nwithout the division, and this is the value used in RPi too. I have seen \none or two cases where the targetY=60 (so, ~0.25) was a bit high.\n\n> \n> Will this be required to come from some sensor tuning profile at a later\n> date?\n> \n> If so - I'd add a\n> \t\\todo targetY should be calibrated by sensor tuning\n> \n> (Same for any other constant that has been manually tuned at present).\n> \n> Is targetY ever changed in the code? If not - perhaps it should be a\n> constexpr to show that it isn't modified.\n> \n> But aside from those which are all minor.\n\nIt could be configured, it can certainly be a constexpr :-).\nShould the maximum number of loops be a constexpr too ?\n\n> \n> \n> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> \n>> +\n>> +       /*\n>> +        * Do this calculation a few times as brightness increase can be\n>> +        * non-linear when there are saturated regions.\n>> +        */\n>> +       for (int i = 0; i < 8; i++) {\n>> +               double initialY = computeInitialY(context.frameContext,\n>> +                                                 context.configuration.grid.bdsGrid,\n>> +                                                 stats, currentYGain);\n>> +               double extra_gain = std::min(10.0, targetY / (initialY + .001));\n>> +\n>> +               currentYGain *= extra_gain;\n>> +               LOG(IPU3Agc, Debug) << \"Initial Y \" << initialY\n>> +                                   << \" target \" << targetY\n>> +                                   << \" gives gain \" << currentYGain;\n>> +               if (extra_gain < 1.01)\n>> +                       break;\n>> +       }\n>> +\n>> +       computeExposure(exposure, analogueGain, currentYGain);\n>>          frameCount_++;\n>>   }\n>>   \n>> diff --git a/src/ipa/ipu3/algorithms/agc.h b/src/ipa/ipu3/algorithms/agc.h\n>> index 69e0b831..0a9152a9 100644\n>> --- a/src/ipa/ipu3/algorithms/agc.h\n>> +++ b/src/ipa/ipu3/algorithms/agc.h\n>> @@ -34,7 +34,11 @@ private:\n>>          void measureBrightness(const ipu3_uapi_stats_3a *stats,\n>>                                 const ipu3_uapi_grid_config &grid);\n>>          void filterExposure();\n>> -       void computeExposure(uint32_t &exposure, double &gain);\n>> +       void computeExposure(uint32_t &exposure, double &gain, double currentYGain);\n>> +       double computeInitialY(IPAFrameContext &frameContext,\n>> +                              const ipu3_uapi_grid_config &grid,\n>> +                              const ipu3_uapi_stats_3a *stats,\n>> +                              double currentYGain);\n>>   \n>>          uint64_t frameCount_;\n>>          uint64_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 04A33BF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 11 Nov 2021 07:07:36 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id F29156035A;\n\tThu, 11 Nov 2021 08:07:34 +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 EEDDB600BF\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 11 Nov 2021 08:07:33 +0100 (CET)","from [IPV6:2a01:e0a:169:7140:e627:8337:a781:d98] (unknown\n\t[IPv6:2a01:e0a:169:7140:e627:8337:a781:d98])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 9D8E5E51;\n\tThu, 11 Nov 2021 08:07:33 +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=\"N+9wGt5Z\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1636614453;\n\tbh=H3K/CQIloITya2aW4vGD6WKVfm7e9SoPshYQO0kQBns=;\n\th=Date:Subject:To:References:From:In-Reply-To:From;\n\tb=N+9wGt5ZcBJ8m+jYIptDHAv3pUQAYk+gEq4XFOJ8KyQfyTEqsIOOpXJ8kGmcgrn+z\n\tq0XWToa6XxcWjIN9D+BVgagFEdu1wnY7E9OY3zD07tEUaN+ch64MX81q+RVQmY6yAx\n\tNYsGmRBdeZycqw1eui5PIYPOGkIIzGqqz784Nj2c=","Message-ID":"<5c733b4e-f835-912f-a448-32a3876a1f1f@ideasonboard.com>","Date":"Thu, 11 Nov 2021 08:07: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":"Kieran Bingham <kieran.bingham@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","References":"<20211110195901.85597-1-jeanmichel.hautbois@ideasonboard.com>\n\t<20211110195901.85597-8-jeanmichel.hautbois@ideasonboard.com>\n\t<163658335669.2121661.10867876860392000584@Monstersaurus>","From":"Jean-Michel Hautbois <jeanmichel.hautbois@ideasonboard.com>","In-Reply-To":"<163658335669.2121661.10867876860392000584@Monstersaurus>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","Subject":"Re: [libcamera-devel] [PATCH v2 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>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]