[{"id":38540,"web_url":"https://patchwork.libcamera.org/comment/38540/","msgid":"<85o6jta21c.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","date":"2026-04-08T15:45:51","subject":"Re: [PATCH 10/13] ipa: simple: Convert awb to libipa implementation","submitter":{"id":177,"url":"https://patchwork.libcamera.org/api/people/177/","name":"Milan Zamazal","email":"mzamazal@redhat.com"},"content":"Hi Kieran,\n\nKieran Bingham <kieran.bingham@ideasonboard.com> writes:\n\n> This brings in both Greyworld and Bayes from libipa assuming the tuning\n> file provides the Bayesian priors from calibration.\n>\n> Manual controls become available and enabled as well, and the storage in\n> the Context is moved to the new common types.\n>\n> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> ---\n>  src/ipa/simple/algorithms/awb.cpp | 215 +++++++++++++++++++++++++++++++++-----\n>  src/ipa/simple/algorithms/awb.h   |  12 +++\n>  src/ipa/simple/algorithms/ccm.cpp |   2 +-\n>  src/ipa/simple/ipa_context.h      |  12 +--\n>  4 files changed, 209 insertions(+), 32 deletions(-)\n>\n> diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp\n> index 05155c83d172d64609053ba940a4c12a2248bb04..90c05e86bae6eefe4874feeb1263af07acd5fcfc 100644\n> --- a/src/ipa/simple/algorithms/awb.cpp\n> +++ b/src/ipa/simple/algorithms/awb.cpp\n> @@ -14,6 +14,8 @@\n>  \n>  #include <libcamera/control_ids.h>\n>  \n> +#include \"libipa/awb_bayes.h\"\n> +#include \"libipa/awb_grey.h\"\n>  #include \"libipa/colours.h\"\n>  #include \"simple/ipa_context.h\"\n>  \n> @@ -23,24 +25,173 @@ LOG_DEFINE_CATEGORY(IPASoftAwb)\n>  \n>  namespace ipa::soft::algorithms {\n>  \n> +constexpr int32_t kMinColourTemperature = 2500;\n> +constexpr int32_t kMaxColourTemperature = 10000;\n> +constexpr int32_t kDefaultColourTemperature = 5000;\n> +\n> +/* Identical to RKISP1AwbStats ... why ? */\n\nWhy not to deduplicate rkisp1 and libipa first and only then to\nintroduce a patch to use libipa in simple?\n\n> +class SimpleAwbStats final : public AwbStats\n> +{\n> +public:\n> +\tSimpleAwbStats(const RGB<double> &rgbMeans)\n> +\t\t: rgbMeans_(rgbMeans)\n> +\t{\n> +\t\trg_ = rgbMeans_.r() / rgbMeans_.g();\n> +\t\tbg_ = rgbMeans_.b() / rgbMeans_.g();\n> +\t}\n> +\n> +\tdouble computeColourError(const RGB<double> &gains) const override\n> +\t{\n> +\t\t/*\n> +\t\t * Compute the sum of the squared colour error (non-greyness) as\n> +\t\t * it appears in the log likelihood equation.\n> +\t\t */\n> +\t\tdouble deltaR = gains.r() * rg_ - 1.0;\n> +\t\tdouble deltaB = gains.b() * bg_ - 1.0;\n> +\t\tdouble delta2 = deltaR * deltaR + deltaB * deltaB;\n> +\n> +\t\treturn delta2;\n> +\t}\n> +\n> +\tRGB<double> rgbMeans() const override\n> +\t{\n> +\t\treturn rgbMeans_;\n> +\t}\n> +\n> +private:\n> +\tRGB<double> rgbMeans_;\n> +\tdouble rg_;\n> +\tdouble bg_;\n> +};\n> +\n> +int Awb::init(IPAContext &context, const YamlObject &tuningData)\n> +{\n> +\tauto &cmap = context.ctrlMap;\n> +\n> +\tcmap[&controls::ColourTemperature] = ControlInfo(kMinColourTemperature,\n> +\t\t\t\t\t\t\t kMaxColourTemperature,\n> +\t\t\t\t\t\t\t kDefaultColourTemperature);\n> +\n> +\tcmap[&controls::AwbEnable] = ControlInfo(false, true);\n> +\tcmap[&controls::ColourGains] = ControlInfo(0.0f, 3.996f,\n> +\t\t\t\t\t\t   Span<const float, 2>{ { 1.0f, 1.0f } });\n> +\n> +\tif (!tuningData.contains(\"algorithm\"))\n> +\t\tLOG(IPASoftAwb, Info) << \"No AWB algorithm specified.\"\n> +\t\t\t\t      << \" Default to grey world\";\n> +\n> +\tauto mode = tuningData[\"algorithm\"].get<std::string>(\"grey\");\n> +\tif (mode == \"grey\") {\n> +\t\tawbAlgo_ = std::make_unique<AwbGrey>();\n> +\t} else if (mode == \"bayes\") {\n> +\t\tawbAlgo_ = std::make_unique<AwbBayes>();\n> +\t} else {\n> +\t\tLOG(IPASoftAwb, Error) << \"Unknown AWB algorithm: \" << mode;\n> +\t\treturn -EINVAL;\n> +\t}\n> +\tLOG(IPASoftAwb, Debug) << \"Using AWB algorithm: \" << mode;\n> +\n> +\tint ret = awbAlgo_->init(tuningData);\n> +\tif (ret) {\n> +\t\tLOG(IPASoftAwb, Error) << \"Failed to init AWB algorithm\";\n> +\t\treturn ret;\n> +\t}\n> +\n> +\tconst auto &src = awbAlgo_->controls();\n> +\tcmap.insert(src.begin(), src.end());\n> +\n> +\treturn 0;\n> +}\n> +\n>  int Awb::configure(IPAContext &context,\n>  \t\t   [[maybe_unused]] const IPAConfigInfo &configInfo)\n>  {\n> -\tauto &gains = context.activeState.awb.gains;\n> -\tgains = { { 1.0, 1.0, 1.0 } };\n> +\tcontext.activeState.awb.manual.gains = RGB<double>{ 1.0 };\n> +\tauto gains = awbAlgo_->gainsFromColourTemperature(kDefaultColourTemperature);\n> +\tif (gains)\n> +\t\tcontext.activeState.awb.automatic.gains = *gains;\n> +\telse\n> +\t\tcontext.activeState.awb.automatic.gains = RGB<double>{ 1.0 };\n> +\n> +\tcontext.activeState.awb.autoEnabled = true;\n> +\tcontext.activeState.awb.manual.temperatureK = kDefaultColourTemperature;\n> +\tcontext.activeState.awb.automatic.temperatureK = kDefaultColourTemperature;\n> +\n> +\tcontext.configuration.awb.enabled = true;\n>  \n>  \treturn 0;\n>  }\n>  \n> +/**\n> + * \\copydoc libcamera::ipa::Algorithm::queueRequest\n> + */\n> +void Awb::queueRequest(IPAContext &context,\n> +\t\t       [[maybe_unused]] const uint32_t frame,\n> +\t\t       [[maybe_unused]] IPAFrameContext &frameContext,\n> +\t\t       const ControlList &controls)\n> +{\n> +\tauto &awb = context.activeState.awb;\n> +\n> +\tconst auto &awbEnable = controls.get(controls::AwbEnable);\n> +\tif (awbEnable && *awbEnable != awb.autoEnabled) {\n> +\t\tawb.autoEnabled = *awbEnable;\n> +\n> +\t\tLOG(IPASoftAwb, Debug)\n> +\t\t\t<< (*awbEnable ? \"Enabling\" : \"Disabling\") << \" AWB\";\n> +\t}\n> +\n> +\tawbAlgo_->handleControls(controls);\n> +\n> +\tframeContext.awb.autoEnabled = awb.autoEnabled;\n> +\n> +\tif (awb.autoEnabled)\n> +\t\treturn;\n> +\n> +\tconst auto &colourGains = controls.get(controls::ColourGains);\n> +\tconst auto &colourTemperature = controls.get(controls::ColourTemperature);\n> +\tbool update = false;\n> +\tif (colourGains) {\n> +\t\tawb.manual.gains.r() = (*colourGains)[0];\n> +\t\tawb.manual.gains.b() = (*colourGains)[1];\n> +\t\t/*\n> +\t\t * \\todo Colour temperature reported in metadata is now\n> +\t\t * incorrect, as we can't deduce the temperature from the gains.\n> +\t\t * This will be fixed with the bayes AWB algorithm.\n> +\t\t */\n> +\t\tupdate = true;\n> +\t} else if (colourTemperature) {\n> +\t\tawb.manual.temperatureK = *colourTemperature;\n> +\t\tconst auto &gains = awbAlgo_->gainsFromColourTemperature(*colourTemperature);\n> +\t\tif (gains) {\n> +\t\t\tawb.manual.gains.r() = gains->r();\n> +\t\t\tawb.manual.gains.b() = gains->b();\n> +\t\t\tupdate = true;\n> +\t\t}\n> +\t}\n> +\n> +\tif (update)\n> +\t\tLOG(IPASoftAwb, Debug)\n> +\t\t\t<< \"Set colour gains to \" << awb.manual.gains;\n> +\n> +\tframeContext.awb.gains = awb.manual.gains;\n> +\tframeContext.awb.temperatureK = awb.manual.temperatureK;\n> +}\n> +\n>  void Awb::prepare(IPAContext &context,\n>  \t\t  [[maybe_unused]] const uint32_t frame,\n>  \t\t  IPAFrameContext &frameContext,\n>  \t\t  DebayerParams *params)\n>  {\n> -\tauto &gains = context.activeState.awb.gains;\n> +\t/*\n> +\t * When AutoAWB is enabled, this is the latest opportunity to take\n> +\t * the most recent and up to date desired AWB gains.\n> +\t */\n> +\tif (frameContext.awb.autoEnabled) {\n> +\t\tframeContext.awb.gains = context.activeState.awb.automatic.gains;\n> +\t\tframeContext.awb.temperatureK = context.activeState.awb.automatic.temperatureK;\n> +\t}\n>  \n> -\tframeContext.gains = gains;\n> -\tparams->gains = gains;\n> +\tparams->gains = frameContext.awb.gains;\n>  }\n>  \n>  void Awb::process(IPAContext &context,\n> @@ -49,15 +200,19 @@ void Awb::process(IPAContext &context,\n>  \t\t  const SwIspStats *stats,\n>  \t\t  ControlList &metadata)\n>  {\n> -\tconst SwIspStats::Histogram &histogram = stats->yHistogram;\n> -\tconst uint8_t blackLevel = context.activeState.blc.level;\n> +\tIPAActiveState &activeState = context.activeState;\n> +\tRGB<float> gains = frameContext.awb.gains;\n>  \n> -\tmetadata.set(controls::ColourGains, { frameContext.gains.r(),\n> -\t\t\t\t\t      frameContext.gains.b() });\n> +\tmetadata.set(controls::AwbEnable, frameContext.awb.autoEnabled);\n> +\tmetadata.set(controls::ColourGains, { gains.r(), gains.b() });\n> +\tmetadata.set(controls::ColourTemperature, frameContext.awb.temperatureK);\n>  \n>  \tif (!stats->valid)\n>  \t\treturn;\n>  \n> +\tconst SwIspStats::Histogram &histogram = stats->yHistogram;\n> +\tconst uint8_t blackLevel = context.activeState.blc.level;\n> +\n>  \t/*\n>  \t * Black level must be subtracted to get the correct AWB ratios, they\n>  \t * would be off if they were computed from the whole brightness range\n> @@ -67,30 +222,42 @@ void Awb::process(IPAContext &context,\n>  \t\thistogram.begin(), histogram.end(), uint64_t(0));\n>  \tconst uint64_t offset = blackLevel * nPixels;\n>  \tconst uint64_t minValid = 1;\n> +\n>  \t/*\n>  \t * Make sure the sums are at least minValid, while preventing unsigned\n>  \t * integer underflow.\n>  \t */\n>  \tconst RGB<uint64_t> sum = stats->sum_.max(offset + minValid) - offset;\n>  \n> -\t/*\n> -\t * Calculate red and blue gains for AWB.\n> -\t * Clamp max gain at 4.0, this also avoids 0 division.\n> -\t */\n> -\tauto &gains = context.activeState.awb.gains;\n> -\tgains = { {\n> -\t\tsum.r() <= sum.g() / 4 ? 4.0f : static_cast<float>(sum.g()) / sum.r(),\n> -\t\t1.0,\n> -\t\tsum.b() <= sum.g() / 4 ? 4.0f : static_cast<float>(sum.g()) / sum.b(),\n> -\t} };\n> +\tRGB<double> rgbMeans = { { static_cast<double>(sum.r() / nPixels),\n> +\t\t\t\t   static_cast<double>(sum.g() / nPixels),\n> +\t\t\t\t   static_cast<double>(sum.b() / nPixels) } };\n>  \n> -\tRGB<double> rgbGains{ { 1 / gains.r(), 1 / gains.g(), 1 / gains.b() } };\n> -\tcontext.activeState.awb.temperatureK = estimateCCT(rgbGains);\n> -\tmetadata.set(controls::ColourTemperature, context.activeState.awb.temperatureK);\n> +\t/*\n> +\t * Todo: Determine the minimum allowed thresholds from the mean\n> +\t * but we currently have the sum - not the mean value!\n> +\t */\n> +\tSimpleAwbStats awbStats{ rgbMeans };\n> +\n> +\tAwbResult awbResult = awbAlgo_->calculateAwb(awbStats, frameContext.lux.lux);\n> +\n> +\t/* Todo: Check if clamping required */\n> +\n> +\t/* Filter the values to avoid oscillations. */\n> +\tdouble speed = 0.2;\n> +\tdouble ct = awbResult.colourTemperature;\n> +\tct = ct * speed + activeState.awb.automatic.temperatureK * (1 - speed);\n> +\tawbResult.gains = awbResult.gains * speed +\n> +\t\t\t  activeState.awb.automatic.gains * (1 - speed);\n> +\n> +\tactiveState.awb.automatic.temperatureK = static_cast<unsigned int>(ct);\n> +\tactiveState.awb.automatic.gains = awbResult.gains;\n>  \n>  \tLOG(IPASoftAwb, Debug)\n> -\t\t<< \"gain R/B: \" << gains << \"; temperature: \"\n> -\t\t<< context.activeState.awb.temperatureK;\n> +\t\t<< std::showpoint\n> +\t\t<< \"Means \" << rgbMeans << \", gains \"\n> +\t\t<< activeState.awb.automatic.gains << \", temp \"\n> +\t\t<< activeState.awb.automatic.temperatureK << \"K\";\n>  }\n>  \n>  REGISTER_IPA_ALGORITHM(Awb, \"Awb\")\n> diff --git a/src/ipa/simple/algorithms/awb.h b/src/ipa/simple/algorithms/awb.h\n> index ad993f39c18002547301b0588dfde143382854a9..fa8f38f65d6e9fdd18418361711e683916b9a9ba 100644\n> --- a/src/ipa/simple/algorithms/awb.h\n> +++ b/src/ipa/simple/algorithms/awb.h\n> @@ -7,6 +7,8 @@\n>  \n>  #pragma once\n>  \n> +#include \"libipa/awb.h\"\n> +\n>  #include \"algorithm.h\"\n>  \n>  namespace libcamera {\n> @@ -19,7 +21,14 @@ public:\n>  \tAwb() = default;\n>  \t~Awb() = default;\n>  \n> +\tint init(IPAContext &context,\n> +\t\t const YamlObject &tuningData) override;\n>  \tint configure(IPAContext &context, const IPAConfigInfo &configInfo) override;\n> +\n> +\tvoid queueRequest(IPAContext &context,\n> +\t\t\t  [[maybe_unused]] const uint32_t frame,\n> +\t\t\t  IPAFrameContext &frameContext,\n> +\t\t\t  const ControlList &controls) override;\n>  \tvoid prepare(IPAContext &context,\n>  \t\t     const uint32_t frame,\n>  \t\t     IPAFrameContext &frameContext,\n> @@ -29,6 +38,9 @@ public:\n>  \t\t     IPAFrameContext &frameContext,\n>  \t\t     const SwIspStats *stats,\n>  \t\t     ControlList &metadata) override;\n> +\n> +private:\n> +\tstd::unique_ptr<AwbAlgorithm> awbAlgo_;\n>  };\n>  \n>  } /* namespace ipa::soft::algorithms */\n> diff --git a/src/ipa/simple/algorithms/ccm.cpp b/src/ipa/simple/algorithms/ccm.cpp\n> index 911a5af2c90b55187f0d98519f3c29b8e0804567..6dace73202a800b2c6375c30083e1ed50ef425b1 100644\n> --- a/src/ipa/simple/algorithms/ccm.cpp\n> +++ b/src/ipa/simple/algorithms/ccm.cpp\n> @@ -44,7 +44,7 @@ int Ccm::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData\n>  void Ccm::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,\n>  \t\t  IPAFrameContext &frameContext, [[maybe_unused]] DebayerParams *params)\n>  {\n> -\tconst unsigned int ct = context.activeState.awb.temperatureK;\n> +\tconst unsigned int ct = frameContext.awb.temperatureK;\n>  \n>  \t/* Change CCM only on bigger temperature changes. */\n>  \tif (!currentCcm_ ||\n> diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h\n> index 2bd7c4642b118d7bb94b1b16cdf4ede5fb2554b5..67b03b5b835f59cf2e339d21377e06d1bbe79b6f 100644\n> --- a/src/ipa/simple/ipa_context.h\n> +++ b/src/ipa/simple/ipa_context.h\n> @@ -16,6 +16,7 @@\n>  #include \"libcamera/internal/matrix.h\"\n>  #include \"libcamera/internal/vector.h\"\n>  \n> +#include <libipa/awb.h>\n>  #include <libipa/fc_queue.h>\n>  #include <libipa/lux.h>\n>  \n> @@ -26,6 +27,8 @@ namespace libcamera {\n>  namespace ipa::soft {\n>  \n>  struct IPASessionConfiguration {\n> +\tipa::awb::Session awb;\n> +\n>  \tstruct {\n>  \t\tint32_t exposureMin, exposureMax;\n>  \t\tdouble againMin, againMax, again10, againMinStep;\n> @@ -38,6 +41,7 @@ struct IPASessionConfiguration {\n>  \n>  struct IPAActiveState {\n>  \tipa::lux::ActiveState lux;\n> +\tipa::awb::ActiveState awb;\n>  \n>  \tstruct {\n>  \t\tint32_t exposure;\n> @@ -51,11 +55,6 @@ struct IPAActiveState {\n>  \t\tdouble lastGain;\n>  \t} blc;\n>  \n> -\tstruct {\n> -\t\tRGB<float> gains;\n> -\t\tunsigned int temperatureK;\n> -\t} awb;\n> -\n>  \tMatrix<float, 3, 3> combinedMatrix;\n>  \n>  \tstruct {\n> @@ -68,6 +67,7 @@ struct IPAActiveState {\n>  \n>  struct IPAFrameContext : public FrameContext {\n>  \tipa::lux::FrameContext lux;\n> +\tipa::awb::FrameContext awb;\n>  \n>  \tMatrix<float, 3, 3> ccm;\n>  \n> @@ -76,8 +76,6 @@ struct IPAFrameContext : public FrameContext {\n>  \t\tdouble gain;\n>  \t} sensor;\n>  \n> -\tRGB<float> gains;\n> -\n>  \tfloat gamma;\n>  \tstd::optional<float> contrast;\n>  \tstd::optional<float> saturation;","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 4E8DBBEFBE\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed,  8 Apr 2026 15:46:01 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 75B7462DEF;\n\tWed,  8 Apr 2026 17:46:00 +0200 (CEST)","from us-smtp-delivery-124.mimecast.com\n\t(us-smtp-delivery-124.mimecast.com [170.10.129.124])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id CEBFD62CE6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  8 Apr 2026 17:45:58 +0200 (CEST)","from mail-wr1-f71.google.com (mail-wr1-f71.google.com\n\t[209.85.221.71]) by relay.mimecast.com with ESMTP with STARTTLS\n\t(version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n\tus-mta-407-dc9TuBSUMkea1MF6ceJx8w-1; Wed, 08 Apr 2026 11:45:55 -0400","by mail-wr1-f71.google.com with SMTP id\n\tffacd0b85a97d-43d03065782so4376909f8f.0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 08 Apr 2026 08:45:55 -0700 (PDT)","from mzamazal-thinkpadp1gen7.tpbc.csb\n\t(ip-77-48-47-2.net.vodafone.cz. [77.48.47.2])\n\tby smtp.gmail.com with ESMTPSA id\n\tffacd0b85a97d-43d1e2c54bdsm60085857f8f.16.2026.04.08.08.45.51\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tWed, 08 Apr 2026 08:45:52 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=redhat.com header.i=@redhat.com\n\theader.b=\"ahC80WCM\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1775663157;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\tto:to:cc:cc:mime-version:mime-version:content-type:content-type:\n\tin-reply-to:in-reply-to:references:references;\n\tbh=8YhdmV6njFCEEzf+LD7cJDCq/3/wHZKEIMBIsW614Ek=;\n\tb=ahC80WCM5ZBXtD2DJfiujZPM3x8DkDID//j6BPKhsyFwa8ePquxsys8JujqRoS99McxZWV\n\tK/Y8RiR8O5CrbFyXrX1vStH1tn56ngoqE8t45ZFS+KfCcpvDFgZQPqdtHf3gw4UxDEJsKM\n\toiCzWYDvhLXscWQUGhWwafNwKm+1RgE=","X-MC-Unique":"dc9TuBSUMkea1MF6ceJx8w-1","X-Mimecast-MFC-AGG-ID":"dc9TuBSUMkea1MF6ceJx8w_1775663155","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20251104; t=1775663154; x=1776267954;\n\th=mime-version:user-agent:message-id:date:references:in-reply-to\n\t:subject:cc:to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject\n\t:date:message-id:reply-to;\n\tbh=8YhdmV6njFCEEzf+LD7cJDCq/3/wHZKEIMBIsW614Ek=;\n\tb=m9KH8j6LIlFRDr1wEne9Hdbexq21WyRZ318sR+46EanSzkFAO4PihsBDN35mWFeoSI\n\twawxHxya44EY7v/WDze0iP/2B1whNu9xr/jyJdZK5jVJM47Cu8L7CocEQXuN4jiy4y6X\n\tplsebIW0Tx0Z+0f67O4iFTtrsVHeO4+zDuI7TGXGDlsXMmF7xRWEGbGqnHg6/AQM9xHJ\n\tvt8oyN++dthu8PIwJB+m/LQqT3Krep55NMFjiOL3aAnS5IYlmzaHfMy2qZG1UgbKxE+N\n\tbD/Vi/iQWCjjbfB+Zrzukudf2wtkcci5tN5TFozAsUmF4F/EntopwaxopZyJlel1Xu47\n\tQVIQ==","X-Gm-Message-State":"AOJu0Ywz+7j8CmJSYhXkbiaZv/qHTTOXrbjGNx3NZxQniBVWEzPE90xj\n\tPALvWPveXIgyDbqiuHxLC0b7J9VDlXJsAv/WpcM3EMhHapyf3doVSuoFGiipXL8XK6W8+SHZx+Z\n\ttF2UyECSX+YT8uDfsJ3v7N0z8qmlOhLS2AcL6kc5nIE61z+InN4Y7u3D2Qacqc03/NyHzZpBj2K\n\tik+h8jOEu4Le4ghVMOmlOBEoQ9fGh5vikGpWlU97R2OOnqeZ9j4iN2/n8b/Ic=","X-Gm-Gg":"AeBDiesbAeSz1jLlZX6IloXEQjfgEfD+OD9s4qqgkNLb5ZUcOBjvuAvCNrWnpSxPNet\n\tU3z/qI0e16ZPjdYOHAcc2O34KL1WP2H/fKAJKUvSO/a7ZMnZ1gNW45zOekBZP9RyUAoGewa5Sm5\n\tB3At7OpieArZLgbA3EzvhcYCiQdU+PrzVRG5trxk4dyL5xOJVvX7wNWSN8dmNpkiAxhdoiavAwR\n\tNpNDuGMy25rPCRPgSeBG2GG8woFJx5kBdLsFUddJta2I3ePJPtPihaIPAnYrRz+TcZbfZFGgjm/\n\tU9iPfx5c2A7aDD5+sEMR6LmIhuMTWf5QoiMr6b0gcc14AvbgXmo6p4749tc4bqHYMetRfI2KWE3\n\t/6vnHkMf9Ph4xEoEGAYwxR8CY5l82aCph/W0Vhp9v6PW98UZITj3gl+6A/kRM/hbE8DWfmQc7M8\n\tM=","X-Received":["by 2002:a05:6000:230c:b0:43b:48d3:2a46 with SMTP id\n\tffacd0b85a97d-43d292fc2bbmr31904458f8f.33.1775663154001; \n\tWed, 08 Apr 2026 08:45:54 -0700 (PDT)","by 2002:a05:6000:230c:b0:43b:48d3:2a46 with SMTP id\n\tffacd0b85a97d-43d292fc2bbmr31904382f8f.33.1775663153275; \n\tWed, 08 Apr 2026 08:45:53 -0700 (PDT)"],"From":"Milan Zamazal <mzamazal@redhat.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH 10/13] ipa: simple: Convert awb to libipa implementation","In-Reply-To":"<20260407-kbingham-awb-split-v1-10-a39af3f4dc20@ideasonboard.com>\n\t(Kieran Bingham's message of \"Tue, 07 Apr 2026 23:01:13 +0100\")","References":"<20260407-kbingham-awb-split-v1-0-a39af3f4dc20@ideasonboard.com>\n\t<20260407-kbingham-awb-split-v1-10-a39af3f4dc20@ideasonboard.com>","Date":"Wed, 08 Apr 2026 17:45:51 +0200","Message-ID":"<85o6jta21c.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","User-Agent":"Gnus/5.13 (Gnus v5.13)","MIME-Version":"1.0","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"XfMEhT71587IdL5HkGvmZzbvExZVJC-gq0s7vSQw4OI_1775663155","X-Mimecast-Originator":"redhat.com","Content-Type":"text/plain","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":38557,"web_url":"https://patchwork.libcamera.org/comment/38557/","msgid":"<20260408212250.GK1965119@killaraus.ideasonboard.com>","date":"2026-04-08T21:22:50","subject":"Re: [PATCH 10/13] ipa: simple: Convert awb to libipa implementation","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Wed, Apr 08, 2026 at 05:45:51PM +0200, Milan Zamazal wrote:\n> Kieran Bingham <kieran.bingham@ideasonboard.com> writes:\n> \n> > This brings in both Greyworld and Bayes from libipa assuming the tuning\n> > file provides the Bayesian priors from calibration.\n> >\n> > Manual controls become available and enabled as well, and the storage in\n> > the Context is moved to the new common types.\n> >\n> > Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> > ---\n> >  src/ipa/simple/algorithms/awb.cpp | 215 +++++++++++++++++++++++++++++++++-----\n> >  src/ipa/simple/algorithms/awb.h   |  12 +++\n> >  src/ipa/simple/algorithms/ccm.cpp |   2 +-\n> >  src/ipa/simple/ipa_context.h      |  12 +--\n> >  4 files changed, 209 insertions(+), 32 deletions(-)\n> >\n> > diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp\n> > index 05155c83d172d64609053ba940a4c12a2248bb04..90c05e86bae6eefe4874feeb1263af07acd5fcfc 100644\n> > --- a/src/ipa/simple/algorithms/awb.cpp\n> > +++ b/src/ipa/simple/algorithms/awb.cpp\n> > @@ -14,6 +14,8 @@\n> >  \n> >  #include <libcamera/control_ids.h>\n> >  \n> > +#include \"libipa/awb_bayes.h\"\n> > +#include \"libipa/awb_grey.h\"\n> >  #include \"libipa/colours.h\"\n> >  #include \"simple/ipa_context.h\"\n> >  \n> > @@ -23,24 +25,173 @@ LOG_DEFINE_CATEGORY(IPASoftAwb)\n> >  \n> >  namespace ipa::soft::algorithms {\n> >  \n> > +constexpr int32_t kMinColourTemperature = 2500;\n> > +constexpr int32_t kMaxColourTemperature = 10000;\n> > +constexpr int32_t kDefaultColourTemperature = 5000;\n> > +\n> > +/* Identical to RKISP1AwbStats ... why ? */\n> \n> Why not to deduplicate rkisp1 and libipa first and only then to\n> introduce a patch to use libipa in simple?\n\nThat would make it easier to review indeed.\n\n[snip]","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 094FEBDCBD\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed,  8 Apr 2026 21:22:53 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id BF24062E42;\n\tWed,  8 Apr 2026 23:22:52 +0200 (CEST)","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 D888862E2C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  8 Apr 2026 23:22:51 +0200 (CEST)","from killaraus.ideasonboard.com\n\t(2001-14ba-703d-e500--2a1.rev.dnainternet.fi\n\t[IPv6:2001:14ba:703d:e500::2a1])\n\tby perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 5F3A0241;\n\tWed,  8 Apr 2026 23:21:23 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"c8uwnxml\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1775683283;\n\tbh=af5NqqacYU9pKSmWhxFvKNEV55sPTa/M5859HNDD09s=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=c8uwnxml4KVj2xXRBz3e8j+UiMuoPiF6y8QyWnM4X3DihHhX/7HzU2nQrLNP/fqEJ\n\tzBcRMNH3kQo2GsS+t0G74Thn3mI+GEw43DrjieWJ7tlphoPgXYY6ywnuhrsfVZ91iE\n\tLQ1dvSYM+yaiSlMEd5XDPGUeCcz6GcfkZyzi7FTw=","Date":"Thu, 9 Apr 2026 00:22:50 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Milan Zamazal <mzamazal@redhat.com>","Cc":"Kieran Bingham <kieran.bingham@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH 10/13] ipa: simple: Convert awb to libipa implementation","Message-ID":"<20260408212250.GK1965119@killaraus.ideasonboard.com>","References":"<20260407-kbingham-awb-split-v1-0-a39af3f4dc20@ideasonboard.com>\n\t<20260407-kbingham-awb-split-v1-10-a39af3f4dc20@ideasonboard.com>\n\t<85o6jta21c.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<85o6jta21c.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","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>"}}]