[{"id":32268,"web_url":"https://patchwork.libcamera.org/comment/32268/","msgid":"<87v7wjfql8.fsf@redhat.com>","date":"2024-11-19T10:46:59","subject":"Re: [PATCH v3 13/17] ipa: libipa: colour: Use the RGB class to\n\tmodel RGB values","submitter":{"id":177,"url":"https://patchwork.libcamera.org/api/people/177/","name":"Milan Zamazal","email":"mzamazal@redhat.com"},"content":"Laurent Pinchart <laurent.pinchart@ideasonboard.com> writes:\n\n> The rec601LuminanceFromRGB() and estimateCCT() functions take RGB\n> triplets as three variables. Replace them with instances of the RGB\n> class and adapt the users accordingly. Only variables passed directly to\n> these functions are converted to RGB instances, further conversion of\n> IPA moduels to the RGB class will be performed separately.\n\n... modules ...\n\n> While at it, fix a typo in the documentation of the estimateCCT()\n> function.\n>\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\nReviewed-by: Milan Zamazal <mzamazal@redhat.com>\n\n> ---\n>  src/ipa/ipu3/algorithms/agc.cpp            | 14 +++----\n>  src/ipa/ipu3/algorithms/awb.cpp            |  2 +-\n>  src/ipa/libipa/colours.cpp                 | 22 +++++-----\n>  src/ipa/libipa/colours.h                   |  6 ++-\n>  src/ipa/rkisp1/algorithms/awb.cpp          | 47 ++++++++++++----------\n>  src/ipa/rpi/controller/rpi/agc_channel.cpp | 21 +++++-----\n>  6 files changed, 55 insertions(+), 57 deletions(-)\n>\n> diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp\n> index 466b3fb31a6c..fda4daa6306c 100644\n> --- a/src/ipa/ipu3/algorithms/agc.cpp\n> +++ b/src/ipa/ipu3/algorithms/agc.cpp\n> @@ -178,18 +178,16 @@ Histogram Agc::parseStatistics(const ipu3_uapi_stats_3a *stats,\n>   */\n>  double Agc::estimateLuminance(double gain) const\n>  {\n> -\tdouble redSum = 0, greenSum = 0, blueSum = 0;\n> +\tRGB<double> sum{ 0.0 };\n>  \n>  \tfor (unsigned int i = 0; i < rgbTriples_.size(); i++) {\n> -\t\tredSum += std::min(std::get<0>(rgbTriples_[i]) * gain, 255.0);\n> -\t\tgreenSum += std::min(std::get<1>(rgbTriples_[i]) * gain, 255.0);\n> -\t\tblueSum += std::min(std::get<2>(rgbTriples_[i]) * gain, 255.0);\n> +\t\tsum.r() += std::min(std::get<0>(rgbTriples_[i]) * gain, 255.0);\n> +\t\tsum.g() += std::min(std::get<1>(rgbTriples_[i]) * gain, 255.0);\n> +\t\tsum.b() += std::min(std::get<2>(rgbTriples_[i]) * gain, 255.0);\n>  \t}\n>  \n> -\tdouble ySum = rec601LuminanceFromRGB(redSum * rGain_,\n> -\t\t\t\t\t     greenSum * gGain_,\n> -\t\t\t\t\t     blueSum * bGain_);\n> -\n> +\tRGB<double> gains{{ rGain_, gGain_, bGain_ }};\n> +\tdouble ySum = rec601LuminanceFromRGB(sum * gains);\n>  \treturn ySum / (bdsGrid_.height * bdsGrid_.width) / 255;\n>  }\n>  \n> diff --git a/src/ipa/ipu3/algorithms/awb.cpp b/src/ipa/ipu3/algorithms/awb.cpp\n> index 7c6bff09147c..55de05d9e39f 100644\n> --- a/src/ipa/ipu3/algorithms/awb.cpp\n> +++ b/src/ipa/ipu3/algorithms/awb.cpp\n> @@ -412,7 +412,7 @@ void Awb::awbGreyWorld()\n>  \t       blueGain = sumBlue.g() / (sumBlue.b() + 1);\n>  \n>  \t/* Color temperature is not relevant in Grey world but still useful to estimate it :-) */\n> -\tasyncResults_.temperatureK = estimateCCT(sumRed.r(), sumRed.g(), sumBlue.b());\n> +\tasyncResults_.temperatureK = estimateCCT({{ sumRed.r(), sumRed.g(), sumBlue.b() }});\n>  \n>  \t/*\n>  \t * Gain values are unsigned integer value ranging [0, 8) with 13 bit\n> diff --git a/src/ipa/libipa/colours.cpp b/src/ipa/libipa/colours.cpp\n> index 9fcb53b08ffb..6c597093ddf8 100644\n> --- a/src/ipa/libipa/colours.cpp\n> +++ b/src/ipa/libipa/colours.cpp\n> @@ -21,9 +21,7 @@ namespace ipa {\n>  \n>  /**\n>   * \\brief Estimate luminance from RGB values following ITU-R BT.601\n> - * \\param[in] r The red value\n> - * \\param[in] g The green value\n> - * \\param[in] b The blue value\n> + * \\param[in] rgb The RGB value\n>   *\n>   * This function estimates a luminance value from a triplet of Red, Green and\n>   * Blue values, following the formula defined by ITU-R Recommendation BT.601-7\n> @@ -31,21 +29,19 @@ namespace ipa {\n>   *\n>   * \\return The estimated luminance value\n>   */\n> -double rec601LuminanceFromRGB(double r, double g, double b)\n> +double rec601LuminanceFromRGB(const RGB<double> &rgb)\n>  {\n> -\treturn (r * .299) + (g * .587) + (b * .114);\n> +\treturn (rgb.r() * .299) + (rgb.g() * .587) + (rgb.b() * .114);\n>  }\n>  \n>  /**\n>   * \\brief Estimate correlated colour temperature from RGB color space input\n> - * \\param[in] red The input red value\n> - * \\param[in] green The input green value\n> - * \\param[in] blue The input blue value\n> + * \\param[in] rgb The RGB value\n>   *\n>   * This function estimates the correlated color temperature RGB color space\n>   * input. In physics and color science, the Planckian locus or black body locus\n>   * is the path or locus that the color of an incandescent black body would take\n> - * in a particular chromaticity space as the blackbody temperature changes.\n> + * in a particular chromaticity space as the black body temperature changes.\n>   *\n>   * If a narrow range of color temperatures is considered (those encapsulating\n>   * daylight being the most practical case) one can approximate the Planckian\n> @@ -56,12 +52,12 @@ double rec601LuminanceFromRGB(double r, double g, double b)\n>   *\n>   * \\return The estimated color temperature\n>   */\n> -uint32_t estimateCCT(double red, double green, double blue)\n> +uint32_t estimateCCT(const RGB<double> &rgb)\n>  {\n>  \t/* Convert the RGB values to CIE tristimulus values (XYZ) */\n> -\tdouble X = (-0.14282) * (red) + (1.54924) * (green) + (-0.95641) * (blue);\n> -\tdouble Y = (-0.32466) * (red) + (1.57837) * (green) + (-0.73191) * (blue);\n> -\tdouble Z = (-0.68202) * (red) + (0.77073) * (green) + (0.56332) * (blue);\n> +\tdouble X = (-0.14282) * rgb.r() + (1.54924) * rgb.g() + (-0.95641) * rgb.b();\n> +\tdouble Y = (-0.32466) * rgb.r() + (1.57837) * rgb.g() + (-0.73191) * rgb.b();\n> +\tdouble Z = (-0.68202) * rgb.r() + (0.77073) * rgb.g() + (0.56332) * rgb.b();\n>  \n>  \t/* Calculate the normalized chromaticity values */\n>  \tdouble x = X / (X + Y + Z);\n> diff --git a/src/ipa/libipa/colours.h b/src/ipa/libipa/colours.h\n> index b42ed0ac1612..fa6a8b575cc7 100644\n> --- a/src/ipa/libipa/colours.h\n> +++ b/src/ipa/libipa/colours.h\n> @@ -9,12 +9,14 @@\n>  \n>  #include <stdint.h>\n>  \n> +#include \"vector.h\"\n> +\n>  namespace libcamera {\n>  \n>  namespace ipa {\n>  \n> -double rec601LuminanceFromRGB(double r, double g, double b);\n> -uint32_t estimateCCT(double red, double green, double blue);\n> +double rec601LuminanceFromRGB(const RGB<double> &rgb);\n> +uint32_t estimateCCT(const RGB<double> &rgb);\n>  \n>  } /* namespace ipa */\n>  \n> diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp\n> index 5c1d9511ce8b..dbeaf81565ff 100644\n> --- a/src/ipa/rkisp1/algorithms/awb.cpp\n> +++ b/src/ipa/rkisp1/algorithms/awb.cpp\n> @@ -192,9 +192,7 @@ void Awb::process(IPAContext &context,\n>  \tconst rkisp1_cif_isp_stat *params = &stats->params;\n>  \tconst rkisp1_cif_isp_awb_stat *awb = &params->awb;\n>  \tIPAActiveState &activeState = context.activeState;\n> -\tdouble greenMean;\n> -\tdouble redMean;\n> -\tdouble blueMean;\n> +\tRGB<double> rgbMeans;\n>  \n>  \tmetadata.set(controls::AwbEnable, frameContext.awb.autoEnabled);\n>  \tmetadata.set(controls::ColourGains, {\n> @@ -209,9 +207,11 @@ void Awb::process(IPAContext &context,\n>  \t}\n>  \n>  \tif (rgbMode_) {\n> -\t\tgreenMean = awb->awb_mean[0].mean_y_or_g;\n> -\t\tredMean = awb->awb_mean[0].mean_cr_or_r;\n> -\t\tblueMean = awb->awb_mean[0].mean_cb_or_b;\n> +\t\trgbMeans = {{\n> +\t\t\tstatic_cast<double>(awb->awb_mean[0].mean_y_or_g),\n> +\t\t\tstatic_cast<double>(awb->awb_mean[0].mean_cr_or_r),\n> +\t\t\tstatic_cast<double>(awb->awb_mean[0].mean_cb_or_b)\n> +\t\t}};\n>  \t} else {\n>  \t\t/* Get the YCbCr mean values */\n>  \t\tdouble yMean = awb->awb_mean[0].mean_y_or_g;\n> @@ -233,9 +233,11 @@ void Awb::process(IPAContext &context,\n>  \t\tyMean -= 16;\n>  \t\tcbMean -= 128;\n>  \t\tcrMean -= 128;\n> -\t\tredMean = 1.1636 * yMean - 0.0623 * cbMean + 1.6008 * crMean;\n> -\t\tgreenMean = 1.1636 * yMean - 0.4045 * cbMean - 0.7949 * crMean;\n> -\t\tblueMean = 1.1636 * yMean + 1.9912 * cbMean - 0.0250 * crMean;\n> +\t\trgbMeans = {{\n> +\t\t\t1.1636 * yMean - 0.0623 * cbMean + 1.6008 * crMean,\n> +\t\t\t1.1636 * yMean - 0.4045 * cbMean - 0.7949 * crMean,\n> +\t\t\t1.1636 * yMean + 1.9912 * cbMean - 0.0250 * crMean\n> +\t\t}};\n>  \n>  \t\t/*\n>  \t\t * Due to hardware rounding errors in the YCbCr means, the\n> @@ -243,9 +245,7 @@ void Awb::process(IPAContext &context,\n>  \t\t * negative gains, messing up calculation. Prevent this by\n>  \t\t * clamping the means to positive values.\n>  \t\t */\n> -\t\tredMean = std::max(redMean, 0.0);\n> -\t\tgreenMean = std::max(greenMean, 0.0);\n> -\t\tblueMean = std::max(blueMean, 0.0);\n> +\t\trgbMeans = rgbMeans.max(0.0);\n>  \t}\n>  \n>  \t/*\n> @@ -253,19 +253,22 @@ void Awb::process(IPAContext &context,\n>  \t * divide by the gains that were used to get the raw means from the\n>  \t * sensor.\n>  \t */\n> -\tredMean /= frameContext.awb.gains.red;\n> -\tgreenMean /= frameContext.awb.gains.green;\n> -\tblueMean /= frameContext.awb.gains.blue;\n> +\tRGB<double> gains{{\n> +\t\tframeContext.awb.gains.red,\n> +\t\tframeContext.awb.gains.green,\n> +\t\tframeContext.awb.gains.blue\n> +\t}};\n> +\trgbMeans /= gains;\n>  \n>  \t/*\n>  \t * If the means are too small we don't have enough information to\n>  \t * meaningfully calculate gains. Freeze the algorithm in that case.\n>  \t */\n> -\tif (redMean < kMeanMinThreshold && greenMean < kMeanMinThreshold &&\n> -\t    blueMean < kMeanMinThreshold)\n> +\tif (rgbMeans.r() < kMeanMinThreshold && rgbMeans.g() < kMeanMinThreshold &&\n> +\t    rgbMeans.b() < kMeanMinThreshold)\n>  \t\treturn;\n>  \n> -\tactiveState.awb.temperatureK = estimateCCT(redMean, greenMean, blueMean);\n> +\tactiveState.awb.temperatureK = estimateCCT(rgbMeans);\n>  \n>  \t/* Metadata shall contain the up to date measurement */\n>  \tmetadata.set(controls::ColourTemperature, activeState.awb.temperatureK);\n> @@ -275,8 +278,8 @@ void Awb::process(IPAContext &context,\n>  \t * gain is hardcoded to 1.0. Avoid divisions by zero by clamping the\n>  \t * divisor to a minimum value of 1.0.\n>  \t */\n> -\tdouble redGain = greenMean / std::max(redMean, 1.0);\n> -\tdouble blueGain = greenMean / std::max(blueMean, 1.0);\n> +\tdouble redGain = rgbMeans.g() / std::max(rgbMeans.r(), 1.0);\n> +\tdouble blueGain = rgbMeans.g() / std::max(rgbMeans.b(), 1.0);\n>  \n>  \t/*\n>  \t * Clamp the gain values to the hardware, which expresses gains as Q2.8\n> @@ -298,8 +301,8 @@ void Awb::process(IPAContext &context,\n>  \n>  \tLOG(RkISP1Awb, Debug)\n>  \t\t<< std::showpoint\n> -\t\t<< \"Means [\" << redMean << \", \" << greenMean << \", \" << blueMean\n> -\t\t<< \"], gains [\" << activeState.awb.gains.automatic.red << \", \"\n> +\t\t<< \"Means \" << rgbMeans\n> +\t\t<< \", gains [\" << activeState.awb.gains.automatic.red << \", \"\n>  \t\t<< activeState.awb.gains.automatic.green << \", \"\n>  \t\t<< activeState.awb.gains.automatic.blue << \"], temp \"\n>  \t\t<< activeState.awb.temperatureK << \"K\";\n> diff --git a/src/ipa/rpi/controller/rpi/agc_channel.cpp b/src/ipa/rpi/controller/rpi/agc_channel.cpp\n> index 8583f4f31907..a99beb70b89a 100644\n> --- a/src/ipa/rpi/controller/rpi/agc_channel.cpp\n> +++ b/src/ipa/rpi/controller/rpi/agc_channel.cpp\n> @@ -13,6 +13,7 @@\n>  #include <libcamera/base/log.h>\n>  \n>  #include \"libipa/colours.h\"\n> +#include \"libipa/vector.h\"\n>  \n>  #include \"../awb_status.h\"\n>  #include \"../device_status.h\"\n> @@ -680,12 +681,13 @@ static double computeInitialY(StatisticsPtr &stats, AwbStatus const &awb,\n>  \t * Note that the weights are applied by the IPA to the statistics directly,\n>  \t * before they are given to us here.\n>  \t */\n> -\tdouble rSum = 0, gSum = 0, bSum = 0, pixelSum = 0;\n> +\tipa::RGB<double> sum{ 0.0 };\n> +\tdouble pixelSum = 0;\n>  \tfor (unsigned int i = 0; i < stats->agcRegions.numRegions(); i++) {\n>  \t\tauto &region = stats->agcRegions.get(i);\n> -\t\trSum += std::min<double>(region.val.rSum * gain, (maxVal - 1) * region.counted);\n> -\t\tgSum += std::min<double>(region.val.gSum * gain, (maxVal - 1) * region.counted);\n> -\t\tbSum += std::min<double>(region.val.bSum * gain, (maxVal - 1) * region.counted);\n> +\t\tsum.r() += std::min<double>(region.val.rSum * gain, (maxVal - 1) * region.counted);\n> +\t\tsum.g() += std::min<double>(region.val.gSum * gain, (maxVal - 1) * region.counted);\n> +\t\tsum.b() += std::min<double>(region.val.bSum * gain, (maxVal - 1) * region.counted);\n>  \t\tpixelSum += region.counted;\n>  \t}\n>  \tif (pixelSum == 0.0) {\n> @@ -693,14 +695,11 @@ static double computeInitialY(StatisticsPtr &stats, AwbStatus const &awb,\n>  \t\treturn 0;\n>  \t}\n>  \n> -\tdouble ySum;\n>  \t/* Factor in the AWB correction if needed. */\n> -\tif (stats->agcStatsPos == Statistics::AgcStatsPos::PreWb) {\n> -\t\tySum = ipa::rec601LuminanceFromRGB(rSum * awb.gainR,\n> -\t\t\t\t\t\t   gSum * awb.gainG,\n> -\t\t\t\t\t\t   bSum * awb.gainB);\n> -\t} else\n> -\t\tySum = ipa::rec601LuminanceFromRGB(rSum, gSum, bSum);\n> +\tif (stats->agcStatsPos == Statistics::AgcStatsPos::PreWb)\n> +\t\tsum *= ipa::RGB<double>{{ awb.gainR, awb.gainR, awb.gainB }};\n> +\n> +\tdouble ySum = ipa::rec601LuminanceFromRGB(sum);\n>  \n>  \treturn ySum / pixelSum / (1 << 16);\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 2FCFCC32F1\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 19 Nov 2024 10:47:09 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id D8A2665EF4;\n\tTue, 19 Nov 2024 11:47:07 +0100 (CET)","from us-smtp-delivery-124.mimecast.com\n\t(us-smtp-delivery-124.mimecast.com [170.10.133.124])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 6C7606589D\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 19 Nov 2024 11:47:05 +0100 (CET)","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-688-KMwOKifgN9SR6AAT4a27cg-1; Tue, 19 Nov 2024 05:47:02 -0500","by mail-wr1-f71.google.com with SMTP id\n\tffacd0b85a97d-3824395a677so366958f8f.0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 19 Nov 2024 02:47:02 -0800 (PST)","from nuthatch ([2a00:102a:400a:489a:34bf:5bf1:e776:7185])\n\tby smtp.gmail.com with ESMTPSA id\n\tffacd0b85a97d-38244064616sm7066246f8f.79.2024.11.19.02.46.59\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tTue, 19 Nov 2024 02:47:00 -0800 (PST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=redhat.com header.i=@redhat.com\n\theader.b=\"GHz6WeRJ\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1732013224;\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=zk6uVYhQ72BzuUEKL+QLNSS/DXsxZsb9WnoKusJWsaY=;\n\tb=GHz6WeRJH/Z9p/H2gLXFiqvOHXWZSWliSMzr90ZFCLhGCmfUXUcF4ceq9DgW1RgzWCA485\n\t2LUuB5uTmr1WUThYKw7cnZKLc6FWO1Qcdy0u3Rxpgv3k4eMTarTk7qm++Pw1sDdIo0eVQg\n\tuCdw2LB8UTE4/bdJ7096oJb2inG1VWM=","X-MC-Unique":"KMwOKifgN9SR6AAT4a27cg-1","X-Mimecast-MFC-AGG-ID":"KMwOKifgN9SR6AAT4a27cg","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1732013221; x=1732618021;\n\th=mime-version:user-agent:message-id:date:references:in-reply-to\n\t:subject:cc:to:from:x-gm-message-state:from:to:cc:subject:date\n\t:message-id:reply-to;\n\tbh=zk6uVYhQ72BzuUEKL+QLNSS/DXsxZsb9WnoKusJWsaY=;\n\tb=pSxR5JNxNeO3WNdcukM3zDTAJBJj0JZRJWMca7sNVBQVlSSgbP9ikmTqotMd1HONmZ\n\tXs+KjOpjI5nN5HyUYuQuCEsVeH/T+H7N7JEHVoJJOOIsw321vYA1MP6/s7KU5G9eygEU\n\tZEkf4yFmUeQX+v/Ib8p2b8n0hkGHrqvvSfKkjoIyPzgh3AxRZINJV1ZGSPLHyHUJ/XH6\n\t9QFVEzHxecseu/3G/oBaCOAXiDcV/kX14BjiKxTqbm1mzWPa7Gw393shgCJQuD90mxor\n\t13EXdxEdhQUQlNDw92vnttdmWWkBD67vF/HAJzirbGbaR2Kd+o12tyJdU8oe+P6HASq+\n\tocLA==","X-Gm-Message-State":"AOJu0YzspZcw0BIkTAG1Q2HzxTt7oIiJuxsOgO1eJnLlx4j+gxRjGDkE\n\t+j0u2UJzCeFaTyREK4fxN0i2efKGgDR7VfKQ8EVmqCxidgJk2GCyCvHmiXLWLGmBppr6jsIQhKp\n\tDUnLVWZy7Vj9/YIBE6FIr3ngB8qKRtISjmxYVhwS6TSKq/WbaIRPpjl/GZoV0fQolq98hfnMSLw\n\tSoHKNo5AvwHUDAm6sWmTkvdks0m8/oXxjiiNHILczI4WfxCPtT8R0yMoA=","X-Received":["by 2002:a5d:64c9:0:b0:382:424:94fe with SMTP id\n\tffacd0b85a97d-38225aa7ed7mr13935081f8f.36.1732013221206; \n\tTue, 19 Nov 2024 02:47:01 -0800 (PST)","by 2002:a5d:64c9:0:b0:382:424:94fe with SMTP id\n\tffacd0b85a97d-38225aa7ed7mr13935050f8f.36.1732013220587; \n\tTue, 19 Nov 2024 02:47:00 -0800 (PST)"],"X-Google-Smtp-Source":"AGHT+IFy0Q5gWxHkw/vZ/4xgZ1fzVXufzyvaphVKz7b0NNavYDdRaNGI5g7lpIVsSFPewoeZOV2SSw==","From":"Milan Zamazal <mzamazal@redhat.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH v3 13/17] ipa: libipa: colour: Use the RGB class to\n\tmodel RGB values","In-Reply-To":"<20241118221618.13953-14-laurent.pinchart@ideasonboard.com>\n\t(Laurent Pinchart's message of \"Tue, 19 Nov 2024 00:16:14 +0200\")","References":"<20241118221618.13953-1-laurent.pinchart@ideasonboard.com>\n\t<20241118221618.13953-14-laurent.pinchart@ideasonboard.com>","Date":"Tue, 19 Nov 2024 11:46:59 +0100","Message-ID":"<87v7wjfql8.fsf@redhat.com>","User-Agent":"Gnus/5.13 (Gnus v5.13)","MIME-Version":"1.0","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"UUa8ZLsUsRYpByhaAgxZZKdJOZ0yMk-I9aDWz7i5gCQ_1732013222","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>"}}]