[{"id":39332,"web_url":"https://patchwork.libcamera.org/comment/39332/","msgid":"<44b5c65b-a5bd-4934-b97d-262728e115d3@collabora.com>","date":"2026-06-23T15:52:30","subject":"Re: [PATCH v2 03/11] ipa: simple: awb: Port to use libipa\n\tAwbAlgorithm","submitter":{"id":140,"url":"https://patchwork.libcamera.org/api/people/140/","name":"Robert Mader","email":"robert.mader@collabora.com"},"content":"Testing this on my FairPhone 5 with the following tuning file for both \nworking cameras (imx858, s5kjn1) - which works surprisingly well - this \nunfortunately shows some regressions.\n\n# SPDX-License-Identifier: CC0-1.0\n%YAML 1.1\n---\nversion: 1\nalgorithms:\n   - BlackLevel:\n       blackLevel: 4096\n   - Awb:\n   # Color correction matrices can be defined here. The CCM algorithm\n   # has a significant performance impact, and should only be enabled\n   # if tuned.\n   - Ccm:\n       ccms:\n         - ct: 2676\n           ccm: [ 2.02152, -0.41859, -0.60292,\n                 -0.59481,  2.21509, -0.62029,\n                 -0.44029, -1.16865,  2.60894 ]\n         - ct: 6890\n           ccm: [ 1.93867, -0.67486, -0.26381,\n                 -0.43049,  2.00702, -0.57652,\n                 -0.15696, -0.51345,  1.67041 ]\n   - Adjust:\n   - Agc:\n...\n\nMost of the time the results seem to match, but occasionally the image \ngets a strong either red or purple tint.\n\nIf this is expected and the tuning file just needs to get adjusted, then \nnever mind, but it does not look like that to me. My hunch would be that \nthe libipa impl does not clamp some values like the current/simple one does.\n\nOn 23.06.26 15:54, Jacopo Mondi wrote:\n> From: Kieran Bingham<kieran.bingham@ideasonboard.com>\n>\n> Port the SoftISP Awb algorithm to use the new libipa implementation\n> of AwbAlgorithm.\n>\n> The awbAlgo_ class member is initialized with the Q<4, 8> type even if\n> there is no physical register representation for SoftISP.\n>\n> The usage of libipa::awb::Context, which defines the gains vector as\n> RGB<double>, in the SimpleIPA ActiveState and FrameContext requires\n> changes to debayer_cpu.cpp and blc.cpp in order not to mix RGB<float>\n> and RGB<double>.\n>\n> Signed-off-by: Kieran Bingham<kieran.bingham@ideasonboard.com>\n> Signed-off-by: Jacopo Mondi<jacopo.mondi@ideasonboard.com>\n> Reviewed-by: Kieran Bingham<kieran.bingham@ideasonboard.com>\n> ---\n>   .../internal/software_isp/debayer_params.h         |   4 +-\n>   src/ipa/simple/algorithms/awb.cpp                  | 111 ++++++++++++++-------\n>   src/ipa/simple/algorithms/awb.h                    |  29 ++++++\n>   src/ipa/simple/algorithms/blc.cpp                  |   2 +-\n>   src/ipa/simple/algorithms/ccm.cpp                  |   2 +-\n>   src/ipa/simple/ipa_context.h                       |  12 +--\n>   src/libcamera/software_isp/debayer_cpu.cpp         |  12 +--\n>   7 files changed, 121 insertions(+), 51 deletions(-)\n>\n> diff --git a/include/libcamera/internal/software_isp/debayer_params.h b/include/libcamera/internal/software_isp/debayer_params.h\n> index 6772b43bced4..1074720d73c2 100644\n> --- a/include/libcamera/internal/software_isp/debayer_params.h\n> +++ b/include/libcamera/internal/software_isp/debayer_params.h\n> @@ -21,10 +21,10 @@ struct DebayerParams {\n>   \tMatrix<float, 3, 3> combinedMatrix = { { 1.0, 0.0, 0.0,\n>   \t\t\t\t\t\t 0.0, 1.0, 0.0,\n>   \t\t\t\t\t\t 0.0, 0.0, 1.0 } };\n> -\tRGB<float> blackLevel = RGB<float>({ 0.0, 0.0, 0.0 });\n> +\tRGB<double> blackLevel = RGB<double>({ 0.0, 0.0, 0.0 });\n>   \tfloat gamma = 1.0;\n>   \tfloat contrastExp = 1.0;\n> -\tRGB<float> gains = RGB<float>({ 1.0, 1.0, 1.0 });\n> +\tRGB<double> gains = RGB<double>({ 1.0, 1.0, 1.0 });\n>   };\n>   \n>   } /* namespace libcamera */\n> diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp\n> index 05155c83d172..77133b542d78 100644\n> --- a/src/ipa/simple/algorithms/awb.cpp\n> +++ b/src/ipa/simple/algorithms/awb.cpp\n> @@ -15,7 +15,6 @@\n>   #include <libcamera/control_ids.h>\n>   \n>   #include \"libipa/colours.h\"\n> -#include \"simple/ipa_context.h\"\n>   \n>   namespace libcamera {\n>   \n> @@ -23,41 +22,78 @@ LOG_DEFINE_CATEGORY(IPASoftAwb)\n>   \n>   namespace ipa::soft::algorithms {\n>   \n> +/*\n> + * \\todo Replace it with a proper Lux algorithm\n> + */\n> +static constexpr unsigned int kDefaultLux = 500;\n> +\n> +class SimpleAwbStats final : public AwbStats\n> +{\n> +public:\n> +\tSimpleAwbStats() {}\n> +\tSimpleAwbStats(const RGB<double> &rgbMeans)\n> +\t\t: AwbStats(rgbMeans)\n> +\t{\n> +\t}\n> +\n> +\t/* Minimum mean value below which AWB can't operate. */\n> +\tdouble minColourValue() const override\n> +\t{\n> +\t\treturn 0.2;\n> +\t}\n> +};\n> +\n> +/**\n> + * \\copydoc libcamera::ipa::Algorithm::init\n> + */\n> +int Awb::init(IPAContext &context, const ValueNode &tuningData)\n> +{\n> +\treturn awbAlgo_.init(tuningData, context.ctrlMap);\n> +}\n> +\n> +/**\n> + * \\copydoc libcamera::ipa::Algorithm::configure\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> +\treturn awbAlgo_.configure(context.activeState.awb);\n> +}\n>   \n> -\treturn 0;\n> +/**\n> + * \\copydoc libcamera::ipa::Algorithm::queueRequest\n> + */\n> +void Awb::queueRequest(IPAContext &context,\n> +\t\t       const uint32_t frame,\n> +\t\t       IPAFrameContext &frameContext,\n> +\t\t       const ControlList &controls)\n> +{\n> +\tawbAlgo_.queueRequest(context.activeState.awb, frame, frameContext.awb,\n> +\t\t\t      controls);\n>   }\n>   \n> +/**\n> + * \\copydoc libcamera::ipa::Algorithm::prepare\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> +\tawbAlgo_.prepare(context.activeState.awb, frameContext.awb);\n>   \n> -\tframeContext.gains = gains;\n> -\tparams->gains = gains;\n> +\tparams->gains = frameContext.awb.gains;\n>   }\n>   \n> -void Awb::process(IPAContext &context,\n> -\t\t  [[maybe_unused]] const uint32_t frame,\n> -\t\t  IPAFrameContext &frameContext,\n> -\t\t  const SwIspStats *stats,\n> -\t\t  ControlList &metadata)\n> +SimpleAwbStats Awb::calculateRgbMeans(IPAContext &context,\n> +\t\t\t\t      const SwIspStats *stats) const\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> -\tmetadata.set(controls::ColourGains, { frameContext.gains.r(),\n> -\t\t\t\t\t      frameContext.gains.b() });\n> -\n> -\tif (!stats->valid)\n> -\t\treturn;\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 +103,37 @@ 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> +\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>   \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 * \\todo Determine the minimum allowed thresholds from the mean\n> +\t * but we currently have the sum - not the mean value!\n> +\t *\n> +\t * Currently set to SimpleAwbStats::minColourValue() = 0.2.\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> -\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> -\n> -\tLOG(IPASoftAwb, Debug)\n> -\t\t<< \"gain R/B: \" << gains << \"; temperature: \"\n> -\t\t<< context.activeState.awb.temperatureK;\n> +\treturn SimpleAwbStats(rgbMeans);\n> +}\n> +\n> +/**\n> + * \\copydoc libcamera::ipa::Algorithm::process\n> + */\n> +void Awb::process(IPAContext &context, [[maybe_unused]] const uint32_t frame,\n> +\t\t  IPAFrameContext &frameContext, const SwIspStats *stats,\n> +\t\t  ControlList &metadata)\n> +{\n> +\tSimpleAwbStats awbStats = calculateRgbMeans(context, stats);\n> +\n> +\tawbAlgo_.process(context.activeState.awb, frameContext.awb, awbStats,\n> +\t\t\t kDefaultLux, metadata);\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 ad993f39c180..cb36cd092e51 100644\n> --- a/src/ipa/simple/algorithms/awb.h\n> +++ b/src/ipa/simple/algorithms/awb.h\n> @@ -7,19 +7,37 @@\n>   \n>   #pragma once\n>   \n> +#include <libcamera/controls.h>\n> +\n> +#include \"libcamera/internal/software_isp/debayer_params.h\"\n> +#include \"libcamera/internal/value_node.h\"\n> +\n> +#include \"libipa/awb.h\"\n> +#include \"libipa/fixedpoint.h\"\n> +#include \"simple/ipa_context.h\"\n> +\n>   #include \"algorithm.h\"\n>   \n>   namespace libcamera {\n>   \n>   namespace ipa::soft::algorithms {\n>   \n> +class SimpleAwbStats;\n> +\n>   class Awb : public Algorithm\n>   {\n>   public:\n>   \tAwb() = default;\n>   \t~Awb() = default;\n>   \n> +\tint init(IPAContext &context,\n> +\t\t const ValueNode &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 +47,17 @@ public:\n>   \t\t     IPAFrameContext &frameContext,\n>   \t\t     const SwIspStats *stats,\n>   \t\t     ControlList &metadata) override;\n> +\n> +private:\n> +\tSimpleAwbStats calculateRgbMeans(IPAContext &context,\n> +\t\t\t\t\t const SwIspStats *stats) const;\n> +\n> +\t/*\n> +\t * There actually is no Q register format for SoftISP, but allow the\n> +\t * colour gains to range in the [0.0f, 15.999f] interval, which seems\n> +\t * reasonable.\n> +\t */\n> +\tAwbAlgorithm<UQ<4, 8>> awbAlgo_;\n>   };\n>   \n>   } /* namespace ipa::soft::algorithms */\n> diff --git a/src/ipa/simple/algorithms/blc.cpp b/src/ipa/simple/algorithms/blc.cpp\n> index 677be56ed669..e45a913cd970 100644\n> --- a/src/ipa/simple/algorithms/blc.cpp\n> +++ b/src/ipa/simple/algorithms/blc.cpp\n> @@ -53,7 +53,7 @@ void BlackLevel::prepare(IPAContext &context,\n>   \t\t\t DebayerParams *params)\n>   {\n>   \t/* Latch the blacklevel gain so GPUISP can apply. */\n> -\tparams->blackLevel = RGB<float>(context.activeState.blc.level / 255.0f);\n> +\tparams->blackLevel = RGB<double>(context.activeState.blc.level / 255.0f);\n>   }\n>   \n>   void BlackLevel::process(IPAContext &context,\n> diff --git a/src/ipa/simple/algorithms/ccm.cpp b/src/ipa/simple/algorithms/ccm.cpp\n> index ace9c35dc462..ff37c718c6e4 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 ValueNode &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 8ccfacb46a59..29643a655ce1 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>   \n>   #include \"core_ipa_interface.h\"\n> @@ -36,6 +37,8 @@ struct IPASessionConfiguration {\n>   };\n>   \n>   struct IPAActiveState {\n> +\tipa::awb::ActiveState awb;\n> +\n>   \tstruct {\n>   \t\tint32_t exposure;\n>   \t\tdouble again;\n> @@ -48,11 +51,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> @@ -64,6 +62,8 @@ struct IPAActiveState {\n>   };\n>   \n>   struct IPAFrameContext : public FrameContext {\n> +\tipa::awb::FrameContext awb;\n> +\n>   \tMatrix<float, 3, 3> ccm;\n>   \n>   \tstruct {\n> @@ -71,8 +71,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;\n> diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp\n> index 49382b4c2719..ab22635fdfaf 100644\n> --- a/src/libcamera/software_isp/debayer_cpu.cpp\n> +++ b/src/libcamera/software_isp/debayer_cpu.cpp\n> @@ -1010,9 +1010,9 @@ void DebayerCpu::updateLookupTables(const DebayerParams &params)\n>   \t};\n>   \tconst unsigned int gammaTableSize = gammaTable_.size();\n>   \n> -\tconst RGB<float> blackIndex = params.blackLevel * kRGBLookupSize;\n> -\tconst RGB<float> gains = params.gains;\n> -\tconst RGB<float> div = (RGB<float>(kRGBLookupSize) - blackIndex).max(1.0);\n> +\tconst RGB<double> blackIndex = params.blackLevel * kRGBLookupSize;\n> +\tconst RGB<double> gains = params.gains;\n> +\tconst RGB<double> div = (RGB<double>(kRGBLookupSize) - blackIndex).max(1.0);\n>   \n>   \tif (ccmEnabled_) {\n>   \t\tif (gammaUpdateNeeded ||\n> @@ -1025,7 +1025,7 @@ void DebayerCpu::updateLookupTables(const DebayerParams &params)\n>   \t\t\tconst unsigned int greenIndex = 1;\n>   \t\t\tconst unsigned int blueIndex = swapRedBlueGains_ ? 0 : 2;\n>   \t\t\tfor (unsigned int i = 0; i < kRGBLookupSize; i++) {\n> -\t\t\t\tconst RGB<float> rgb = (gains * (RGB<float>(i) - blackIndex) * kRGBLookupSize / div)\n> +\t\t\t\tconst RGB<double> rgb = (gains * (RGB<double>(i) - blackIndex) * kRGBLookupSize / div)\n>   \t\t\t\t\t\t\t       .clamp(0.0, kRGBLookupSize - 1);\n>   \t\t\t\tred[i].r = std::round(rgb.r() * params.combinedMatrix[redIndex][0]);\n>   \t\t\t\tred[i].g = std::round(rgb.r() * params.combinedMatrix[greenIndex][0]);\n> @@ -1045,8 +1045,8 @@ void DebayerCpu::updateLookupTables(const DebayerParams &params)\n>   \t\t\tauto &green = green_;\n>   \t\t\tauto &blue = swapRedBlueGains_ ? red_ : blue_;\n>   \t\t\tfor (unsigned int i = 0; i < kRGBLookupSize; i++) {\n> -\t\t\t\tconst RGB<float> lutGains =\n> -\t\t\t\t\t(gains * (RGB<float>(i) - blackIndex) * gammaTableSize / div)\n> +\t\t\t\tconst RGB<double> lutGains =\n> +\t\t\t\t\t(gains * (RGB<double>(i) - blackIndex) * gammaTableSize / div)\n>   \t\t\t\t\t\t.clamp(0.0, gammaTableSize - 1);\n>   \t\t\t\tred[i] = gammaTable_[lutGains.r()];\n>   \t\t\t\tgreen[i] = gammaTable_[lutGains.g()];\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 AE07CC328C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 23 Jun 2026 15:52:43 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 95D9E65857;\n\tTue, 23 Jun 2026 17:52:42 +0200 (CEST)","from sender4-op-o12.zoho.com (sender4-op-o12.zoho.com\n\t[136.143.188.12])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 76CFD656E9\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 23 Jun 2026 17:52:40 +0200 (CEST)","by mx.zohomail.com with SMTPS id 1782229953413422.3839386422061;\n\tTue, 23 Jun 2026 08:52:33 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=collabora.com\n\theader.i=robert.mader@collabora.com header.b=\"QQwtIJlp\"; \n\tdkim-atps=neutral","ARC-Seal":"i=1; a=rsa-sha256; t=1782229956; cv=none; \n\td=zohomail.com; s=zohoarc; \n\tb=VrwQv4joIxa4j9Qi2wP2jyX5/iG6AWBDP+ENSWNdVURfsZEvpT08oxl4jIxHj0cjlaeDOmft5f6j45++zUflURtFkTLHdjBwZgTLYOeewVCfMcX1KN9cOHhOtGXegKfAhN1IA6w5MLZihC6jJHACFQIsrYuoi8YTxp1PnwJW8tc=","ARC-Message-Signature":"i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; \n\ts=zohoarc; t=1782229956;\n\th=Content-Type:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To:Cc;\n\tbh=9AjoVZz2W6XQF4TlkKNCwEsOiI4Y4RAVlLQIgSN6qS0=; \n\tb=SPoChlL5PUFNV3s15KE7JqWvwEyBX79G/tjUlXctanLSAckDa368IjIorslINV4lap0VP+gqQ9RIUcApxofWZI5Y9eq9DBIPTJV1stsG5Y1Fqqzh2LfgpKPo90hX+MBUpm/+dOGuBCEk5hL5UcERlBG0LWIEZG8WhgX4xUF77O4=","ARC-Authentication-Results":"i=1; mx.zohomail.com;\n\tdkim=pass  header.i=collabora.com;\n\tspf=pass  smtp.mailfrom=robert.mader@collabora.com;\n\tdmarc=pass header.from=<robert.mader@collabora.com>","DKIM-Signature":"v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1782229956;\n\ts=zohomail; d=collabora.com; i=robert.mader@collabora.com;\n\th=Content-Type:Message-ID:Date:Date:MIME-Version:Subject:Subject:To:To:References:From:From:In-Reply-To:Message-Id:Reply-To:Cc;\n\tbh=9AjoVZz2W6XQF4TlkKNCwEsOiI4Y4RAVlLQIgSN6qS0=;\n\tb=QQwtIJlphZfDA6bzDcG7EUGtWun5dD/yclC14y99qfZbGjhanPt69sXFHqhbjOX7\n\t0nq7yraOKDXH6DnB6/OuzHoOA2wDBNTHh7PM5QpFzQEn7AuUI1oGAVVnJ3EXpU+P4zN\n\tnd16f0UgT3Sqmm59CuJVp3AYM7mCJWhQSWoD4YEw=","Content-Type":"multipart/alternative;\n\tboundary=\"------------GzjtdVVXFl5gcv03KNmcMtmi\"","Message-ID":"<44b5c65b-a5bd-4934-b97d-262728e115d3@collabora.com>","Date":"Tue, 23 Jun 2026 17:52:30 +0200","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH v2 03/11] ipa: simple: awb: Port to use libipa\n\tAwbAlgorithm","To":"libcamera-devel@lists.libcamera.org","References":"<20260623-libipa-algorithms-v2-0-f97433f12e4e@ideasonboard.com>\n\t<20260623-libipa-algorithms-v2-3-f97433f12e4e@ideasonboard.com>","Content-Language":"en-US, de-DE, en-GB","From":"Robert Mader <robert.mader@collabora.com>","In-Reply-To":"<20260623-libipa-algorithms-v2-3-f97433f12e4e@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>"}}]