[{"id":36741,"web_url":"https://patchwork.libcamera.org/comment/36741/","msgid":"<176245148967.2421127.16212370290518051538@ping.linuxembedded.co.uk>","date":"2025-11-06T17:51:29","subject":"Re: [PATCH v2 3/3] ipa: libipa: agc_mean_luminance: Fix yTarget\n\thandling in constraints","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Stefan Klug (2025-11-06 16:42:27)\n> The yTarget loading code is broken and works neither for plain values\n> nor for arrays of values to form a PWL. Fix this by supporting both\n> cases. If a list is provided in the tuning file construct a PWL,\n> otherwise construct a single point PWL with the given value.\n> \n> Fixes: 24247a12c7d3 (\"ipa: libipa: Add AgcMeanLuminance base class\")\n> Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>\n> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>\n\nCan't find anything to say here so :\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n> ---\n> \n> Changes in v2:\n> - Collected tag\n> - Drop special logic to handle single values as that was added\n>   generically to the yaml Pwl loader\n> ---\n>  src/ipa/libipa/agc_mean_luminance.cpp | 41 +++++++++++++++++++--------\n>  src/ipa/libipa/agc_mean_luminance.h   |  5 ++--\n>  src/ipa/rkisp1/algorithms/wdr.cpp     |  3 +-\n>  3 files changed, 33 insertions(+), 16 deletions(-)\n> \n> diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp\n> index b80af92a2c0f..7fac8c760396 100644\n> --- a/src/ipa/libipa/agc_mean_luminance.cpp\n> +++ b/src/ipa/libipa/agc_mean_luminance.cpp\n> @@ -173,7 +173,7 @@ int AgcMeanLuminance::parseRelativeLuminanceTarget(const YamlObject &tuningData)\n>         return 0;\n>  }\n>  \n> -void AgcMeanLuminance::parseConstraint(const YamlObject &modeDict, int32_t id)\n> +int AgcMeanLuminance::parseConstraint(const YamlObject &modeDict, int32_t id)\n>  {\n>         for (const auto &[boundName, content] : modeDict.asDict()) {\n>                 if (boundName != \"upper\" && boundName != \"lower\") {\n> @@ -186,10 +186,14 @@ void AgcMeanLuminance::parseConstraint(const YamlObject &modeDict, int32_t id)\n>                 AgcConstraint::Bound bound = static_cast<AgcConstraint::Bound>(idx);\n>                 double qLo = content[\"qLo\"].get<double>().value_or(0.98);\n>                 double qHi = content[\"qHi\"].get<double>().value_or(1.0);\n> -               double yTarget =\n> -                       content[\"yTarget\"].getList<double>().value_or(std::vector<double>{ 0.5 }).at(0);\n> +               auto yTarget = content[\"yTarget\"].get<Pwl>();\n> +               if (!yTarget) {\n> +                       LOG(AgcMeanLuminance, Error)\n> +                               << \"Failed to parse yTarget\";\n> +                       return -EINVAL;\n> +               }\n>  \n> -               AgcConstraint constraint = { bound, qLo, qHi, yTarget };\n> +               AgcConstraint constraint = { bound, qLo, qHi, std::move(*yTarget) };\n>  \n>                 if (!constraintModes_.count(id))\n>                         constraintModes_[id] = {};\n> @@ -199,6 +203,8 @@ void AgcMeanLuminance::parseConstraint(const YamlObject &modeDict, int32_t id)\n>                 else\n>                         constraintModes_[id].insert(constraintModes_[id].begin(), constraint);\n>         }\n> +\n> +       return 0;\n>  }\n>  \n>  int AgcMeanLuminance::parseConstraintModes(const YamlObject &tuningData)\n> @@ -221,8 +227,11 @@ int AgcMeanLuminance::parseConstraintModes(const YamlObject &tuningData)\n>                                 return -EINVAL;\n>                         }\n>  \n> -                       parseConstraint(modeDict,\n> -                                       AeConstraintModeNameValueMap.at(modeName));\n> +                       int ret = parseConstraint(modeDict,\n> +                                                 AeConstraintModeNameValueMap.at(modeName));\n> +                       if (ret)\n> +                               return ret;\n> +\n>                         availableConstraintModes.push_back(\n>                                 AeConstraintModeNameValueMap.at(modeName));\n>                 }\n> @@ -239,7 +248,7 @@ int AgcMeanLuminance::parseConstraintModes(const YamlObject &tuningData)\n>                         AgcConstraint::Bound::Lower,\n>                         0.98,\n>                         1.0,\n> -                       0.5\n> +                       Pwl({ { { 0.0, 0.5 } } })\n>                 };\n>  \n>                 constraintModes_[controls::ConstraintNormal].insert(\n> @@ -352,8 +361,9 @@ void AgcMeanLuminance::configure(utils::Duration lineDuration,\n>   * the data in a specific format; the Agc algorithm's tuning data should contain\n>   * a dictionary called AeConstraintMode containing per-mode setting dictionaries\n>   * with the key being a value from \\ref controls::AeConstraintModeNameValueMap.\n> - * Each mode dict may contain either a \"lower\" or \"upper\" key or both, for\n> - * example:\n> + * The yTarget can either be provided as single value or as array in which case\n> + * it is interpreted as a PWL mapping lux levels to yTarget values. Each mode\n> + * dict may contain either a \"lower\" or \"upper\" key or both, for example:\n>   *\n>   * \\code{.unparsed}\n>   * algorithms:\n> @@ -372,7 +382,7 @@ void AgcMeanLuminance::configure(utils::Duration lineDuration,\n>   *           upper:\n>   *             qLo: 0.98\n>   *             qHi: 1.0\n> - *             yTarget: 0.8\n> + *             yTarget: [ 100, 0.8, 20000, 0.5 ]\n>   *\n>   * \\endcode\n>   *\n> @@ -528,8 +538,15 @@ double AgcMeanLuminance::constraintClampGain(uint32_t constraintModeIndex,\n>                                              const Histogram &hist,\n>                                              double gain)\n>  {\n> -       auto applyConstraint = [&gain, &hist](const AgcConstraint &constraint) {\n> -               double newGain = constraint.yTarget * hist.bins() /\n> +       auto applyConstraint = [this, &gain, &hist](const AgcConstraint &constraint) {\n> +               double lux = lux_;\n> +\n> +               if (relativeLuminanceTarget_.size() > 1 && lux_ == 0)\n> +                       lux = kDefaultLuxLevel;\n> +\n> +               double target = constraint.yTarget.eval(\n> +                       constraint.yTarget.domain().clamp(lux));\n> +               double newGain = target * hist.bins() /\n>                                  hist.interQuantileMean(constraint.qLo, constraint.qHi);\n>  \n>                 if (constraint.bound == AgcConstraint::Bound::Lower &&\n> diff --git a/src/ipa/libipa/agc_mean_luminance.h b/src/ipa/libipa/agc_mean_luminance.h\n> index 1fbff304a72b..d0d1fc139509 100644\n> --- a/src/ipa/libipa/agc_mean_luminance.h\n> +++ b/src/ipa/libipa/agc_mean_luminance.h\n> @@ -40,7 +40,7 @@ public:\n>                 Bound bound;\n>                 double qLo;\n>                 double qHi;\n> -               double yTarget;\n> +               Pwl yTarget;\n>         };\n>  \n>         void configure(utils::Duration lineDuration, const CameraSensorHelper *sensorHelper);\n> @@ -88,8 +88,7 @@ public:\n>  private:\n>         virtual double estimateLuminance(const double gain) const = 0;\n>         int parseRelativeLuminanceTarget(const YamlObject &tuningData);\n> -\n> -       void parseConstraint(const YamlObject &modeDict, int32_t id);\n> +       int parseConstraint(const YamlObject &modeDict, int32_t id);\n>         int parseConstraintModes(const YamlObject &tuningData);\n>         int parseExposureModes(const YamlObject &tuningData);\n>         double estimateInitialGain() const;\n> diff --git a/src/ipa/rkisp1/algorithms/wdr.cpp b/src/ipa/rkisp1/algorithms/wdr.cpp\n> index 45144913dcd8..ed81628c032c 100644\n> --- a/src/ipa/rkisp1/algorithms/wdr.cpp\n> +++ b/src/ipa/rkisp1/algorithms/wdr.cpp\n> @@ -175,7 +175,8 @@ int WideDynamicRange::configure(IPAContext &context,\n>         constraint.bound = AgcMeanLuminance::AgcConstraint::Bound::Upper;\n>         constraint.qHi = 1.0;\n>         constraint.qLo = 1.0 - exposureConstraintMaxBrightPixels_;\n> -       constraint.yTarget = exposureConstraintY_;\n> +       constraint.yTarget.clear();\n> +       constraint.yTarget.append(0, exposureConstraintY_);\n>         return 0;\n>  }\n>  \n> -- \n> 2.51.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 9F377C3241\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu,  6 Nov 2025 17:51:34 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A654D60A9E;\n\tThu,  6 Nov 2025 18:51:33 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 70707606E6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  6 Nov 2025 18:51:32 +0100 (CET)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 1E3796DF;\n\tThu,  6 Nov 2025 18:49: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=\"L/aQDeOw\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1762451377;\n\tbh=ZBdLSbijI5lk2vVxUJ3/BW7VKv2aFQtEXVON6NQ0lJo=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=L/aQDeOwLtsqMewn5mlu0qCsEFJcvDUeGJbGmhar6MXKOtkDhdGNY1jcqMdxudKU1\n\tlpFSMQK0PSiq37FbhA0qysT9pgaVmG8BgS1fM5ukCVzPMV6VDTis12NZhWP4bcMIsn\n\tDLjq9EerpbSSVvgGCZsxaEzNIc3PLGngsM0bgJD0=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20251106164239.460738-4-stefan.klug@ideasonboard.com>","References":"<20251106164239.460738-1-stefan.klug@ideasonboard.com>\n\t<20251106164239.460738-4-stefan.klug@ideasonboard.com>","Subject":"Re: [PATCH v2 3/3] ipa: libipa: agc_mean_luminance: Fix yTarget\n\thandling in constraints","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Stefan Klug <stefan.klug@ideasonboard.com>,\n\tDaniel Scally <dan.scally@ideasonboard.com>","To":"Stefan Klug <stefan.klug@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Thu, 06 Nov 2025 17:51:29 +0000","Message-ID":"<176245148967.2421127.16212370290518051538@ping.linuxembedded.co.uk>","User-Agent":"alot/0.9.1","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":36827,"web_url":"https://patchwork.libcamera.org/comment/36827/","msgid":"<optmx3smvm22dawzsdjfwrrkhmvqw5m2cm2bupyzt3g6vp6ype@6h6e4w3pzgp5>","date":"2025-11-14T17:22:04","subject":"Re: [PATCH v2 3/3] ipa: libipa: agc_mean_luminance: Fix yTarget\n\thandling in constraints","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Stefan\n\nOn Thu, Nov 06, 2025 at 05:42:27PM +0100, Stefan Klug wrote:\n> The yTarget loading code is broken and works neither for plain values\n> nor for arrays of values to form a PWL. Fix this by supporting both\n> cases. If a list is provided in the tuning file construct a PWL,\n> otherwise construct a single point PWL with the given value.\n>\n> Fixes: 24247a12c7d3 (\"ipa: libipa: Add AgcMeanLuminance base class\")\n> Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>\n> Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com>\n\nReviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n\nThanks\n  j\n\n>\n> ---\n>\n> Changes in v2:\n> - Collected tag\n> - Drop special logic to handle single values as that was added\n>   generically to the yaml Pwl loader\n> ---\n>  src/ipa/libipa/agc_mean_luminance.cpp | 41 +++++++++++++++++++--------\n>  src/ipa/libipa/agc_mean_luminance.h   |  5 ++--\n>  src/ipa/rkisp1/algorithms/wdr.cpp     |  3 +-\n>  3 files changed, 33 insertions(+), 16 deletions(-)\n>\n> diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp\n> index b80af92a2c0f..7fac8c760396 100644\n> --- a/src/ipa/libipa/agc_mean_luminance.cpp\n> +++ b/src/ipa/libipa/agc_mean_luminance.cpp\n> @@ -173,7 +173,7 @@ int AgcMeanLuminance::parseRelativeLuminanceTarget(const YamlObject &tuningData)\n>  \treturn 0;\n>  }\n>\n> -void AgcMeanLuminance::parseConstraint(const YamlObject &modeDict, int32_t id)\n> +int AgcMeanLuminance::parseConstraint(const YamlObject &modeDict, int32_t id)\n>  {\n>  \tfor (const auto &[boundName, content] : modeDict.asDict()) {\n>  \t\tif (boundName != \"upper\" && boundName != \"lower\") {\n> @@ -186,10 +186,14 @@ void AgcMeanLuminance::parseConstraint(const YamlObject &modeDict, int32_t id)\n>  \t\tAgcConstraint::Bound bound = static_cast<AgcConstraint::Bound>(idx);\n>  \t\tdouble qLo = content[\"qLo\"].get<double>().value_or(0.98);\n>  \t\tdouble qHi = content[\"qHi\"].get<double>().value_or(1.0);\n> -\t\tdouble yTarget =\n> -\t\t\tcontent[\"yTarget\"].getList<double>().value_or(std::vector<double>{ 0.5 }).at(0);\n> +\t\tauto yTarget = content[\"yTarget\"].get<Pwl>();\n> +\t\tif (!yTarget) {\n> +\t\t\tLOG(AgcMeanLuminance, Error)\n> +\t\t\t\t<< \"Failed to parse yTarget\";\n> +\t\t\treturn -EINVAL;\n> +\t\t}\n>\n> -\t\tAgcConstraint constraint = { bound, qLo, qHi, yTarget };\n> +\t\tAgcConstraint constraint = { bound, qLo, qHi, std::move(*yTarget) };\n>\n>  \t\tif (!constraintModes_.count(id))\n>  \t\t\tconstraintModes_[id] = {};\n> @@ -199,6 +203,8 @@ void AgcMeanLuminance::parseConstraint(const YamlObject &modeDict, int32_t id)\n>  \t\telse\n>  \t\t\tconstraintModes_[id].insert(constraintModes_[id].begin(), constraint);\n>  \t}\n> +\n> +\treturn 0;\n>  }\n>\n>  int AgcMeanLuminance::parseConstraintModes(const YamlObject &tuningData)\n> @@ -221,8 +227,11 @@ int AgcMeanLuminance::parseConstraintModes(const YamlObject &tuningData)\n>  \t\t\t\treturn -EINVAL;\n>  \t\t\t}\n>\n> -\t\t\tparseConstraint(modeDict,\n> -\t\t\t\t\tAeConstraintModeNameValueMap.at(modeName));\n> +\t\t\tint ret = parseConstraint(modeDict,\n> +\t\t\t\t\t\t  AeConstraintModeNameValueMap.at(modeName));\n> +\t\t\tif (ret)\n> +\t\t\t\treturn ret;\n> +\n>  \t\t\tavailableConstraintModes.push_back(\n>  \t\t\t\tAeConstraintModeNameValueMap.at(modeName));\n>  \t\t}\n> @@ -239,7 +248,7 @@ int AgcMeanLuminance::parseConstraintModes(const YamlObject &tuningData)\n>  \t\t\tAgcConstraint::Bound::Lower,\n>  \t\t\t0.98,\n>  \t\t\t1.0,\n> -\t\t\t0.5\n> +\t\t\tPwl({ { { 0.0, 0.5 } } })\n>  \t\t};\n>\n>  \t\tconstraintModes_[controls::ConstraintNormal].insert(\n> @@ -352,8 +361,9 @@ void AgcMeanLuminance::configure(utils::Duration lineDuration,\n>   * the data in a specific format; the Agc algorithm's tuning data should contain\n>   * a dictionary called AeConstraintMode containing per-mode setting dictionaries\n>   * with the key being a value from \\ref controls::AeConstraintModeNameValueMap.\n> - * Each mode dict may contain either a \"lower\" or \"upper\" key or both, for\n> - * example:\n> + * The yTarget can either be provided as single value or as array in which case\n> + * it is interpreted as a PWL mapping lux levels to yTarget values. Each mode\n> + * dict may contain either a \"lower\" or \"upper\" key or both, for example:\n>   *\n>   * \\code{.unparsed}\n>   * algorithms:\n> @@ -372,7 +382,7 @@ void AgcMeanLuminance::configure(utils::Duration lineDuration,\n>   *           upper:\n>   *             qLo: 0.98\n>   *             qHi: 1.0\n> - *             yTarget: 0.8\n> + *             yTarget: [ 100, 0.8, 20000, 0.5 ]\n>   *\n>   * \\endcode\n>   *\n> @@ -528,8 +538,15 @@ double AgcMeanLuminance::constraintClampGain(uint32_t constraintModeIndex,\n>  \t\t\t\t\t     const Histogram &hist,\n>  \t\t\t\t\t     double gain)\n>  {\n> -\tauto applyConstraint = [&gain, &hist](const AgcConstraint &constraint) {\n> -\t\tdouble newGain = constraint.yTarget * hist.bins() /\n> +\tauto applyConstraint = [this, &gain, &hist](const AgcConstraint &constraint) {\n> +\t\tdouble lux = lux_;\n> +\n> +\t\tif (relativeLuminanceTarget_.size() > 1 && lux_ == 0)\n> +\t\t\tlux = kDefaultLuxLevel;\n> +\n> +\t\tdouble target = constraint.yTarget.eval(\n> +\t\t\tconstraint.yTarget.domain().clamp(lux));\n> +\t\tdouble newGain = target * hist.bins() /\n>  \t\t\t\t hist.interQuantileMean(constraint.qLo, constraint.qHi);\n>\n>  \t\tif (constraint.bound == AgcConstraint::Bound::Lower &&\n> diff --git a/src/ipa/libipa/agc_mean_luminance.h b/src/ipa/libipa/agc_mean_luminance.h\n> index 1fbff304a72b..d0d1fc139509 100644\n> --- a/src/ipa/libipa/agc_mean_luminance.h\n> +++ b/src/ipa/libipa/agc_mean_luminance.h\n> @@ -40,7 +40,7 @@ public:\n>  \t\tBound bound;\n>  \t\tdouble qLo;\n>  \t\tdouble qHi;\n> -\t\tdouble yTarget;\n> +\t\tPwl yTarget;\n>  \t};\n>\n>  \tvoid configure(utils::Duration lineDuration, const CameraSensorHelper *sensorHelper);\n> @@ -88,8 +88,7 @@ public:\n>  private:\n>  \tvirtual double estimateLuminance(const double gain) const = 0;\n>  \tint parseRelativeLuminanceTarget(const YamlObject &tuningData);\n> -\n> -\tvoid parseConstraint(const YamlObject &modeDict, int32_t id);\n> +\tint parseConstraint(const YamlObject &modeDict, int32_t id);\n>  \tint parseConstraintModes(const YamlObject &tuningData);\n>  \tint parseExposureModes(const YamlObject &tuningData);\n>  \tdouble estimateInitialGain() const;\n> diff --git a/src/ipa/rkisp1/algorithms/wdr.cpp b/src/ipa/rkisp1/algorithms/wdr.cpp\n> index 45144913dcd8..ed81628c032c 100644\n> --- a/src/ipa/rkisp1/algorithms/wdr.cpp\n> +++ b/src/ipa/rkisp1/algorithms/wdr.cpp\n> @@ -175,7 +175,8 @@ int WideDynamicRange::configure(IPAContext &context,\n>  \tconstraint.bound = AgcMeanLuminance::AgcConstraint::Bound::Upper;\n>  \tconstraint.qHi = 1.0;\n>  \tconstraint.qLo = 1.0 - exposureConstraintMaxBrightPixels_;\n> -\tconstraint.yTarget = exposureConstraintY_;\n> +\tconstraint.yTarget.clear();\n> +\tconstraint.yTarget.append(0, exposureConstraintY_);\n>  \treturn 0;\n>  }\n>\n> --\n> 2.51.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 B1D0CC3241\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 14 Nov 2025 17:22:09 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id ED95B60A8B;\n\tFri, 14 Nov 2025 18:22:08 +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 66D92606E6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 14 Nov 2025 18:22:07 +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 2A1B0161;\n\tFri, 14 Nov 2025 18:20:06 +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=\"s2sp/Bdr\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1763140806;\n\tbh=EepwUbZYh2YKwmDtLVw8HDAVb4/gvjDczjPUVBb2yi4=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=s2sp/Bdr11MuwhYBs7luqlxMFsjYccn5dJirFrddNl91HVzA3HaphFrOGIhqtbgQV\n\tEv0N7k0mZIIQ5n/fx75u84nIsYwJnJu+baPIymgGEYH8eQzqcewHOBtyhdQ7Rn0sSY\n\tqFBviFx0Ew9kfo7h8hc+N45AkzuabXd/97RGOedg=","Date":"Fri, 14 Nov 2025 18:22:04 +0100","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","To":"Stefan Klug <stefan.klug@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org, \n\tDaniel Scally <dan.scally@ideasonboard.com>","Subject":"Re: [PATCH v2 3/3] ipa: libipa: agc_mean_luminance: Fix yTarget\n\thandling in constraints","Message-ID":"<optmx3smvm22dawzsdjfwrrkhmvqw5m2cm2bupyzt3g6vp6ype@6h6e4w3pzgp5>","References":"<20251106164239.460738-1-stefan.klug@ideasonboard.com>\n\t<20251106164239.460738-4-stefan.klug@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20251106164239.460738-4-stefan.klug@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>"}}]