[{"id":32987,"web_url":"https://patchwork.libcamera.org/comment/32987/","msgid":"<173644395512.3771432.17163385300401870311@ping.linuxembedded.co.uk>","date":"2025-01-09T17:32:35","subject":"Re: [PATCH v3 8/9] libcamera: software_isp: Track whether CCM is\n\tenabled","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Milan Zamazal (2024-12-10 15:34:38)\n> Applying color correction matrix (CCM) in software ISP is optional due\n> to performance reasons.  CCM is applied if and only if `Ccm' algorithm\n> is present in the tuning file and it defines some CCM.\n> Software ISP debayering is a performance critical piece of code and we\n> do not want to use dynamic conditionals there.  Therefore we pass\n> information about CCM application to debayering configuration and let it\n> select the right versions of debayering functions using templates.  This\n> is a similar trick as the previously used one for adding or not adding\n> an alpha channel to the output.\n> \n> Debayering gets this information but it ignores it in this patch.\n> Actual processing with CCM is added in the followup patch.\n> \n> Signed-off-by: Milan Zamazal <mzamazal@redhat.com>\n> ---\n>  include/libcamera/ipa/soft.mojom            |  2 +-\n>  src/ipa/simple/algorithms/ccm.cpp           | 18 +++++------\n>  src/ipa/simple/algorithms/ccm.h             |  1 +\n>  src/ipa/simple/soft_simple.cpp              |  8 +++--\n>  src/libcamera/software_isp/debayer.cpp      |  3 +-\n>  src/libcamera/software_isp/debayer.h        |  3 +-\n>  src/libcamera/software_isp/debayer_cpu.cpp  | 35 ++++++++++++---------\n>  src/libcamera/software_isp/debayer_cpu.h    | 24 +++++++-------\n>  src/libcamera/software_isp/software_isp.cpp |  5 +--\n>  9 files changed, 56 insertions(+), 43 deletions(-)\n> \n> diff --git a/include/libcamera/ipa/soft.mojom b/include/libcamera/ipa/soft.mojom\n> index d52e6f1a..b5ed3905 100644\n> --- a/include/libcamera/ipa/soft.mojom\n> +++ b/include/libcamera/ipa/soft.mojom\n> @@ -21,7 +21,7 @@ interface IPASoftInterface {\n>         start() => (int32 ret);\n>         stop();\n>         configure(IPAConfigInfo configInfo)\n> -               => (int32 ret);\n> +               => (int32 ret, bool ccmEnabled);\n>  \n>         [async] queueRequest(uint32 frame, libcamera.ControlList sensorControls);\n>         [async] computeParams(uint32 frame);\n> diff --git a/src/ipa/simple/algorithms/ccm.cpp b/src/ipa/simple/algorithms/ccm.cpp\n> index 40fe12c8..26bf8ff1 100644\n> --- a/src/ipa/simple/algorithms/ccm.cpp\n> +++ b/src/ipa/simple/algorithms/ccm.cpp\n> @@ -25,26 +25,24 @@ unsigned int Ccm::kTemperatureThreshold = 100;\n>  int Ccm::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData)\n>  {\n>         int ret = ccm_.readYaml(tuningData[\"ccms\"], \"ct\", \"ccm\");\n> -       if (ret < 0) {\n> +       if (ret < 0)\n>                 LOG(IPASoftCcm, Warning)\n>                         << \"Failed to parse 'ccm' \"\n>                         << \"parameter from tuning file; falling back to unit matrix\";\n> -               ccmEnabled_ = false;\n> -       } else {\n> -               ccmEnabled_ = true;\n> -       }\n\nI'm not seeing why we're not tracking this...\n\n>  \n>         return 0;\n>  }\n>  \n> +int Ccm::configure(IPAContext &context,\n> +                  [[maybe_unused]] const IPAConfigInfo &configInfo)\n> +{\n> +       context.activeState.ccm.enabled = true;\n> +       return 0;\n> +}\n> +\n>  void Ccm::prepare(IPAContext &context, const uint32_t frame,\n>                   IPAFrameContext &frameContext, [[maybe_unused]] DebayerParams *params)\n>  {\n> -       context.activeState.ccm.enabled = ccmEnabled_;\n> -\n> -       if (!ccmEnabled_)\n> -               return;\n> -\n\nI'm not sure I understand why we're not returning and doing nothing if !ccmEnabled_\n\n>         unsigned int ct = context.activeState.awb.temperatureK;\n>  \n>         /* Change CCM only on bigger temperature changes. */\n> diff --git a/src/ipa/simple/algorithms/ccm.h b/src/ipa/simple/algorithms/ccm.h\n> index 23481a08..fe81ebd5 100644\n> --- a/src/ipa/simple/algorithms/ccm.h\n> +++ b/src/ipa/simple/algorithms/ccm.h\n> @@ -24,6 +24,7 @@ public:\n>         ~Ccm() = default;\n>  \n>         int init(IPAContext &context, const YamlObject &tuningData) override;\n> +       int configure(IPAContext &context, const IPAConfigInfo &configInfo) override;\n>         void prepare(IPAContext &context,\n>                      const uint32_t frame,\n>                      IPAFrameContext &frameContext,\n> diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp\n> index b26e4e15..545773fa 100644\n> --- a/src/ipa/simple/soft_simple.cpp\n> +++ b/src/ipa/simple/soft_simple.cpp\n> @@ -52,7 +52,7 @@ public:\n>                  const SharedFD &fdParams,\n>                  const ControlInfoMap &sensorInfoMap,\n>                  ControlInfoMap *ipaControls) override;\n> -       int configure(const IPAConfigInfo &configInfo) override;\n> +       int configure(const IPAConfigInfo &configInfo, bool *ccmEnabled) override;\n>  \n>         int start() override;\n>         void stop() override;\n> @@ -182,7 +182,7 @@ int IPASoftSimple::init(const IPASettings &settings,\n>         return 0;\n>  }\n>  \n> -int IPASoftSimple::configure(const IPAConfigInfo &configInfo)\n> +int IPASoftSimple::configure(const IPAConfigInfo &configInfo, bool *ccmEnabled)\n>  {\n>         sensorInfoMap_ = configInfo.sensorControls;\n>  \n> @@ -242,12 +242,16 @@ int IPASoftSimple::configure(const IPAConfigInfo &configInfo)\n>                 context_.configuration.agc.againMinStep = 1.0;\n>         }\n>  \n> +       context_.activeState.ccm.enabled = false;\n\nI would hope/expect this to be initialised to false already.\n\n> +\n>         for (auto const &algo : algorithms()) {\n>                 int ret = algo->configure(context_, configInfo);\n>                 if (ret)\n>                         return ret;\n>         }\n>  \n> +       *ccmEnabled = context_.activeState.ccm.enabled;\n\nAnd if there's no ccm enabled in the tuning file - it should never\nupdate it so it would still be possible to use this line, without\nchanging the current state tracking in the ccm module itself.\n\n> +\n>         LOG(IPASoft, Info)\n>                 << \"Exposure \" << context_.configuration.agc.exposureMin << \"-\"\n>                 << context_.configuration.agc.exposureMax\n> diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp\n> index f0b83261..595f73f6 100644\n> --- a/src/libcamera/software_isp/debayer.cpp\n> +++ b/src/libcamera/software_isp/debayer.cpp\n> @@ -57,10 +57,11 @@ Debayer::~Debayer()\n>  }\n>  \n>  /**\n> - * \\fn int Debayer::configure(const StreamConfiguration &inputCfg, const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs)\n> + * \\fn int Debayer::configure(const StreamConfiguration &inputCfg, const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs, ccmEnabled)\n>   * \\brief Configure the debayer object according to the passed in parameters\n>   * \\param[in] inputCfg The input configuration\n>   * \\param[in] outputCfgs The output configurations\n> + * \\param[in] ccmEnabled Whether a color correction matrix is applied\n>   *\n>   * \\return 0 on success, a negative errno on failure\n>   */\n> diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h\n> index d7ca060d..ba033d44 100644\n> --- a/src/libcamera/software_isp/debayer.h\n> +++ b/src/libcamera/software_isp/debayer.h\n> @@ -33,7 +33,8 @@ public:\n>         virtual ~Debayer() = 0;\n>  \n>         virtual int configure(const StreamConfiguration &inputCfg,\n> -                             const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs) = 0;\n> +                             const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs,\n> +                             bool ccmEnabled) = 0;\n>  \n>         virtual std::vector<PixelFormat> formats(PixelFormat inputFormat) = 0;\n>  \n> diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp\n> index 01cfb36b..3c6597f9 100644\n> --- a/src/libcamera/software_isp/debayer_cpu.cpp\n> +++ b/src/libcamera/software_isp/debayer_cpu.cpp\n> @@ -114,7 +114,7 @@ DebayerCpu::~DebayerCpu() = default;\n>                 (prev[x] + curr[x - p] + curr[x + n] + next[x]) / (4 * (div)),         \\\n>                 curr[x] / (div))\n>  \n> -template<bool addAlphaByte>\n> +template<bool addAlphaByte, bool ccmEnabled>\n>  void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n>  {\n>         DECLARE_SRC_POINTERS(uint8_t)\n> @@ -125,7 +125,7 @@ void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n>         }\n>  }\n>  \n> -template<bool addAlphaByte>\n> +template<bool addAlphaByte, bool ccmEnabled>\n>  void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n>  {\n>         DECLARE_SRC_POINTERS(uint8_t)\n> @@ -136,7 +136,7 @@ void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n>         }\n>  }\n>  \n> -template<bool addAlphaByte>\n> +template<bool addAlphaByte, bool ccmEnabled>\n>  void DebayerCpu::debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n>  {\n>         DECLARE_SRC_POINTERS(uint16_t)\n> @@ -148,7 +148,7 @@ void DebayerCpu::debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n>         }\n>  }\n>  \n> -template<bool addAlphaByte>\n> +template<bool addAlphaByte, bool ccmEnabled>\n>  void DebayerCpu::debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n>  {\n>         DECLARE_SRC_POINTERS(uint16_t)\n> @@ -160,7 +160,7 @@ void DebayerCpu::debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n>         }\n>  }\n>  \n> -template<bool addAlphaByte>\n> +template<bool addAlphaByte, bool ccmEnabled>\n>  void DebayerCpu::debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n>  {\n>         DECLARE_SRC_POINTERS(uint16_t)\n> @@ -172,7 +172,7 @@ void DebayerCpu::debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n>         }\n>  }\n>  \n> -template<bool addAlphaByte>\n> +template<bool addAlphaByte, bool ccmEnabled>\n>  void DebayerCpu::debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n>  {\n>         DECLARE_SRC_POINTERS(uint16_t)\n> @@ -184,7 +184,7 @@ void DebayerCpu::debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n>         }\n>  }\n>  \n> -template<bool addAlphaByte>\n> +template<bool addAlphaByte, bool ccmEnabled>\n>  void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n>  {\n>         const int widthInBytes = window_.width * 5 / 4;\n> @@ -210,7 +210,7 @@ void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n>         }\n>  }\n>  \n> -template<bool addAlphaByte>\n> +template<bool addAlphaByte, bool ccmEnabled>\n>  void DebayerCpu::debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n>  {\n>         const int widthInBytes = window_.width * 5 / 4;\n> @@ -231,7 +231,7 @@ void DebayerCpu::debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n>         }\n>  }\n>  \n> -template<bool addAlphaByte>\n> +template<bool addAlphaByte, bool ccmEnabled>\n>  void DebayerCpu::debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[])\n>  {\n>         const int widthInBytes = window_.width * 5 / 4;\n> @@ -252,7 +252,7 @@ void DebayerCpu::debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[])\n>         }\n>  }\n>  \n> -template<bool addAlphaByte>\n> +template<bool addAlphaByte, bool ccmEnabled>\n>  void DebayerCpu::debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[])\n>  {\n>         const int widthInBytes = window_.width * 5 / 4;\n> @@ -368,10 +368,11 @@ int DebayerCpu::setupStandardBayerOrder(BayerFormat::Order order)\n>         return 0;\n>  }\n>  \n> -#define SET_DEBAYER_METHODS(method0, method1)                                                \\\n> -       debayer0_ = addAlphaByte ? &DebayerCpu::method0<true> : &DebayerCpu::method0<false>; \\\n> -       debayer1_ = addAlphaByte ? &DebayerCpu::method1<true> : &DebayerCpu::method1<false>;\n> +#define SET_DEBAYER_METHODS(method0, method1)                                                                        \\\n> +       debayer0_ = addAlphaByte ? &DebayerCpu::method0<true, ccmEnabled> : &DebayerCpu::method0<false, ccmEnabled>; \\\n> +       debayer1_ = addAlphaByte ? &DebayerCpu::method1<true, ccmEnabled> : &DebayerCpu::method1<false, ccmEnabled>;\n>  \n> +template<bool ccmEnabled>\n>  int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat)\n>  {\n>         BayerFormat bayerFormat =\n> @@ -464,7 +465,8 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputF\n>  }\n>  \n>  int DebayerCpu::configure(const StreamConfiguration &inputCfg,\n> -                         const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs)\n> +                         const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs,\n> +                         bool ccmEnabled)\n>  {\n>         if (getInputConfig(inputCfg.pixelFormat, inputConfig_) != 0)\n>                 return -EINVAL;\n> @@ -503,7 +505,10 @@ int DebayerCpu::configure(const StreamConfiguration &inputCfg,\n>                 return -EINVAL;\n>         }\n>  \n> -       if (setDebayerFunctions(inputCfg.pixelFormat, outputCfg.pixelFormat) != 0)\n> +       int ret = ccmEnabled\n> +                         ? setDebayerFunctions<true>(inputCfg.pixelFormat, outputCfg.pixelFormat)\n> +                         : setDebayerFunctions<false>(inputCfg.pixelFormat, outputCfg.pixelFormat);\n> +       if (ret != 0)\n>                 return -EINVAL;\n>  \n>         window_.x = ((inputCfg.size.width - outputCfg.size.width) / 2) &\n> diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h\n> index 2c47e7c6..b2ec8f1b 100644\n> --- a/src/libcamera/software_isp/debayer_cpu.h\n> +++ b/src/libcamera/software_isp/debayer_cpu.h\n> @@ -31,7 +31,8 @@ public:\n>         ~DebayerCpu();\n>  \n>         int configure(const StreamConfiguration &inputCfg,\n> -                     const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs);\n> +                     const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs,\n> +                     bool ccmEnabled);\n>         Size patternSize(PixelFormat inputFormat);\n>         std::vector<PixelFormat> formats(PixelFormat input);\n>         std::tuple<unsigned int, unsigned int>\n> @@ -85,28 +86,28 @@ private:\n>         using debayerFn = void (DebayerCpu::*)(uint8_t *dst, const uint8_t *src[]);\n>  \n>         /* 8-bit raw bayer format */\n> -       template<bool addAlphaByte>\n> +       template<bool addAlphaByte, bool ccmEnabled>\n>         void debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);\n> -       template<bool addAlphaByte>\n> +       template<bool addAlphaByte, bool ccmEnabled>\n>         void debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);\n>         /* unpacked 10-bit raw bayer format */\n> -       template<bool addAlphaByte>\n> +       template<bool addAlphaByte, bool ccmEnabled>\n>         void debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);\n> -       template<bool addAlphaByte>\n> +       template<bool addAlphaByte, bool ccmEnabled>\n>         void debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);\n>         /* unpacked 12-bit raw bayer format */\n> -       template<bool addAlphaByte>\n> +       template<bool addAlphaByte, bool ccmEnabled>\n>         void debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);\n> -       template<bool addAlphaByte>\n> +       template<bool addAlphaByte, bool ccmEnabled>\n>         void debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);\n>         /* CSI-2 packed 10-bit raw bayer format (all the 4 orders) */\n> -       template<bool addAlphaByte>\n> +       template<bool addAlphaByte, bool ccmEnabled>\n>         void debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);\n> -       template<bool addAlphaByte>\n> +       template<bool addAlphaByte, bool ccmEnabled>\n>         void debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);\n> -       template<bool addAlphaByte>\n> +       template<bool addAlphaByte, bool ccmEnabled>\n>         void debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[]);\n> -       template<bool addAlphaByte>\n> +       template<bool addAlphaByte, bool ccmEnabled>\n>         void debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]);\n>  \n>         struct DebayerInputConfig {\n> @@ -125,6 +126,7 @@ private:\n>         int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config);\n>         int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config);\n>         int setupStandardBayerOrder(BayerFormat::Order order);\n> +       template<bool ccmEnabled>\n>         int setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat);\n>         void setupInputMemcpy(const uint8_t *linePointers[]);\n>         void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src);\n> diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp\n> index 2bea64d9..6a07de85 100644\n> --- a/src/libcamera/software_isp/software_isp.cpp\n> +++ b/src/libcamera/software_isp/software_isp.cpp\n> @@ -236,11 +236,12 @@ int SoftwareIsp::configure(const StreamConfiguration &inputCfg,\n>  {\n>         ASSERT(ipa_ && debayer_);\n>  \n> -       int ret = ipa_->configure(configInfo);\n> +       bool ccmEnabled;\n> +       int ret = ipa_->configure(configInfo, &ccmEnabled);\n>         if (ret < 0)\n>                 return ret;\n>  \n> -       return debayer_->configure(inputCfg, outputCfgs);\n> +       return debayer_->configure(inputCfg, outputCfgs, ccmEnabled);\n>  }\n>  \n>  /**\n> -- \n> 2.44.2\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 25569C32EA\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu,  9 Jan 2025 17:32:40 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 3F45C684F3;\n\tThu,  9 Jan 2025 18:32:39 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 80F2F61884\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  9 Jan 2025 18:32:38 +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 AA4D19FC;\n\tThu,  9 Jan 2025 18:31:44 +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=\"GrmEtxPK\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1736443904;\n\tbh=vMH8tlhOUAM1HVJwQOL86IZqpB8wvh48bK8HwT1Q5LA=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=GrmEtxPKAL+d5S07hqRuo9d/LxZvAghZvdP77bDKFhUweHZo/5efVI2SUwTVDG03J\n\twJvV9qSRAkfciMiOESeoB5RDmJwM+pW1kl5KqtYg32LyJmEV17/Zn10mQnsJsiv2AP\n\tVk+An8sZrq1p+egrBu+YRvvPrgnO1FVmGJWcVcVM=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20241210153440.1007470-9-mzamazal@redhat.com>","References":"<20241210153440.1007470-1-mzamazal@redhat.com>\n\t<20241210153440.1007470-9-mzamazal@redhat.com>","Subject":"Re: [PATCH v3 8/9] libcamera: software_isp: Track whether CCM is\n\tenabled","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Milan Zamazal <mzamazal@redhat.com>,\n\tRobert Mader <robert.mader@collabora.com>,\n\tHans de Goede <hdegoede@redhat.com>, \n\tLaurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Milan Zamazal <mzamazal@redhat.com>, libcamera-devel@lists.libcamera.org","Date":"Thu, 09 Jan 2025 17:32:35 +0000","Message-ID":"<173644395512.3771432.17163385300401870311@ping.linuxembedded.co.uk>","User-Agent":"alot/0.10","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":33025,"web_url":"https://patchwork.libcamera.org/comment/33025/","msgid":"<85r05amo5u.fsf@mzamazal-thinkpadp1gen3.tpbc.csb>","date":"2025-01-10T20:03:57","subject":"Re: [PATCH v3 8/9] libcamera: software_isp: Track whether CCM is\n\tenabled","submitter":{"id":177,"url":"https://patchwork.libcamera.org/api/people/177/","name":"Milan Zamazal","email":"mzamazal@redhat.com"},"content":"Hi Kieran,\n\nthank you for review.\n\nKieran Bingham <kieran.bingham@ideasonboard.com> writes:\n\n> Quoting Milan Zamazal (2024-12-10 15:34:38)\n>> Applying color correction matrix (CCM) in software ISP is optional due\n>> to performance reasons.  CCM is applied if and only if `Ccm' algorithm\n>\n>> is present in the tuning file and it defines some CCM.\n>> Software ISP debayering is a performance critical piece of code and we\n>> do not want to use dynamic conditionals there.  Therefore we pass\n>> information about CCM application to debayering configuration and let it\n>> select the right versions of debayering functions using templates.  This\n>> is a similar trick as the previously used one for adding or not adding\n>> an alpha channel to the output.\n>> \n>> Debayering gets this information but it ignores it in this patch.\n>> Actual processing with CCM is added in the followup patch.\n>> \n>> Signed-off-by: Milan Zamazal <mzamazal@redhat.com>\n>> ---\n>>  include/libcamera/ipa/soft.mojom            |  2 +-\n>>  src/ipa/simple/algorithms/ccm.cpp           | 18 +++++------\n>>  src/ipa/simple/algorithms/ccm.h             |  1 +\n>>  src/ipa/simple/soft_simple.cpp              |  8 +++--\n>>  src/libcamera/software_isp/debayer.cpp      |  3 +-\n>>  src/libcamera/software_isp/debayer.h        |  3 +-\n>>  src/libcamera/software_isp/debayer_cpu.cpp  | 35 ++++++++++++---------\n>>  src/libcamera/software_isp/debayer_cpu.h    | 24 +++++++-------\n>>  src/libcamera/software_isp/software_isp.cpp |  5 +--\n>>  9 files changed, 56 insertions(+), 43 deletions(-)\n>> \n>> diff --git a/include/libcamera/ipa/soft.mojom b/include/libcamera/ipa/soft.mojom\n>> index d52e6f1a..b5ed3905 100644\n>> --- a/include/libcamera/ipa/soft.mojom\n>> +++ b/include/libcamera/ipa/soft.mojom\n>> @@ -21,7 +21,7 @@ interface IPASoftInterface {\n>>         start() => (int32 ret);\n>>         stop();\n>>         configure(IPAConfigInfo configInfo)\n>> -               => (int32 ret);\n>> +               => (int32 ret, bool ccmEnabled);\n>>  \n>>         [async] queueRequest(uint32 frame, libcamera.ControlList sensorControls);\n>>         [async] computeParams(uint32 frame);\n>> diff --git a/src/ipa/simple/algorithms/ccm.cpp b/src/ipa/simple/algorithms/ccm.cpp\n>> index 40fe12c8..26bf8ff1 100644\n>> --- a/src/ipa/simple/algorithms/ccm.cpp\n>> +++ b/src/ipa/simple/algorithms/ccm.cpp\n>> @@ -25,26 +25,24 @@ unsigned int Ccm::kTemperatureThreshold = 100;\n>>  int Ccm::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData)\n>>  {\n>>         int ret = ccm_.readYaml(tuningData[\"ccms\"], \"ct\", \"ccm\");\n>> -       if (ret < 0) {\n>> +       if (ret < 0)\n>>                 LOG(IPASoftCcm, Warning)\n>>                         << \"Failed to parse 'ccm' \"\n>>                         << \"parameter from tuning file; falling back to unit matrix\";\n>> -               ccmEnabled_ = false;\n>> -       } else {\n>> -               ccmEnabled_ = true;\n>> -       }\n>\n> I'm not seeing why we're not tracking this...\n\nIndeed, it looks confused, I'll revert this change.\n\n>>         return 0;\n>>  }\n>>  \n>> +int Ccm::configure(IPAContext &context,\n>> +                  [[maybe_unused]] const IPAConfigInfo &configInfo)\n>> +{\n>> +       context.activeState.ccm.enabled = true;\n\nThis should be changed to:\n\n  context.activeState.ccm.enabled = ccmEnabled_;\n\n>> +       return 0;\n>> +}\n>> +\n>>  void Ccm::prepare(IPAContext &context, const uint32_t frame,\n>>                   IPAFrameContext &frameContext, [[maybe_unused]] DebayerParams *params)\n>>  {\n>> -       context.activeState.ccm.enabled = ccmEnabled_;\n>> -\n>> -       if (!ccmEnabled_)\n>> -               return;\n>> -\n>\n> I'm not sure I understand why we're not returning and doing nothing if !ccmEnabled_\n\nYes, the removed lines should be replaced by\n\n  if (!context.activeState.ccm.enabled)\n          return;\n\n>>         unsigned int ct = context.activeState.awb.temperatureK;\n>>  \n>>         /* Change CCM only on bigger temperature changes. */\n>> diff --git a/src/ipa/simple/algorithms/ccm.h b/src/ipa/simple/algorithms/ccm.h\n>> index 23481a08..fe81ebd5 100644\n>> --- a/src/ipa/simple/algorithms/ccm.h\n>> +++ b/src/ipa/simple/algorithms/ccm.h\n>> @@ -24,6 +24,7 @@ public:\n>>         ~Ccm() = default;\n>>  \n>>         int init(IPAContext &context, const YamlObject &tuningData) override;\n>> +       int configure(IPAContext &context, const IPAConfigInfo &configInfo) override;\n>>         void prepare(IPAContext &context,\n>>                      const uint32_t frame,\n>>                      IPAFrameContext &frameContext,\n>> diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp\n>> index b26e4e15..545773fa 100644\n>> --- a/src/ipa/simple/soft_simple.cpp\n>> +++ b/src/ipa/simple/soft_simple.cpp\n>> @@ -52,7 +52,7 @@ public:\n>>                  const SharedFD &fdParams,\n>>                  const ControlInfoMap &sensorInfoMap,\n>>                  ControlInfoMap *ipaControls) override;\n>> -       int configure(const IPAConfigInfo &configInfo) override;\n>> +       int configure(const IPAConfigInfo &configInfo, bool *ccmEnabled) override;\n>>  \n>>         int start() override;\n>>         void stop() override;\n>> @@ -182,7 +182,7 @@ int IPASoftSimple::init(const IPASettings &settings,\n>>         return 0;\n>>  }\n>>  \n>> -int IPASoftSimple::configure(const IPAConfigInfo &configInfo)\n>> +int IPASoftSimple::configure(const IPAConfigInfo &configInfo, bool *ccmEnabled)\n>>  {\n>>         sensorInfoMap_ = configInfo.sensorControls;\n>>  \n>> @@ -242,12 +242,16 @@ int IPASoftSimple::configure(const IPAConfigInfo &configInfo)\n>>                 context_.configuration.agc.againMinStep = 1.0;\n>>         }\n>>  \n>> +       context_.activeState.ccm.enabled = false;\n>\n> I would hope/expect this to be initialised to false already.\n\nAFAIK yes, `false' is already the default value.\n\n>> +\n>>         for (auto const &algo : algorithms()) {\n>>                 int ret = algo->configure(context_, configInfo);\n>>                 if (ret)\n>>                         return ret;\n>>         }\n>>  \n>> +       *ccmEnabled = context_.activeState.ccm.enabled;\n>\n> And if there's no ccm enabled in the tuning file - it should never\n> update it so it would still be possible to use this line, without\n> changing the current state tracking in the ccm module itself.\n\nYes.\n\n>> +\n>>         LOG(IPASoft, Info)\n>>                 << \"Exposure \" << context_.configuration.agc.exposureMin << \"-\"\n>>                 << context_.configuration.agc.exposureMax\n>> diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp\n>> index f0b83261..595f73f6 100644\n>> --- a/src/libcamera/software_isp/debayer.cpp\n>> +++ b/src/libcamera/software_isp/debayer.cpp\n>> @@ -57,10 +57,11 @@ Debayer::~Debayer()\n>>  }\n>>  \n>>  /**\n>> - * \\fn int Debayer::configure(const StreamConfiguration &inputCfg, const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs)\n>> + * \\fn int Debayer::configure(const StreamConfiguration &inputCfg, const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs, ccmEnabled)\n             ^^^^^^^^^^\n\n`bool' missing here.\n\n>>   * \\brief Configure the debayer object according to the passed in parameters\n>>   * \\param[in] inputCfg The input configuration\n>>   * \\param[in] outputCfgs The output configurations\n>> + * \\param[in] ccmEnabled Whether a color correction matrix is applied\n>>   *\n>>   * \\return 0 on success, a negative errno on failure\n>>   */\n>> diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h\n>> index d7ca060d..ba033d44 100644\n>> --- a/src/libcamera/software_isp/debayer.h\n>> +++ b/src/libcamera/software_isp/debayer.h\n>> @@ -33,7 +33,8 @@ public:\n>>         virtual ~Debayer() = 0;\n>>  \n>>         virtual int configure(const StreamConfiguration &inputCfg,\n>> -                             const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs) = 0;\n>> +                             const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs,\n>> +                             bool ccmEnabled) = 0;\n>>  \n>>         virtual std::vector<PixelFormat> formats(PixelFormat inputFormat) = 0;\n>>  \n>> diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp\n>> index 01cfb36b..3c6597f9 100644\n>> --- a/src/libcamera/software_isp/debayer_cpu.cpp\n>> +++ b/src/libcamera/software_isp/debayer_cpu.cpp\n>> @@ -114,7 +114,7 @@ DebayerCpu::~DebayerCpu() = default;\n>>                 (prev[x] + curr[x - p] + curr[x + n] + next[x]) / (4 * (div)),         \\\n>>                 curr[x] / (div))\n>>  \n>> -template<bool addAlphaByte>\n>> +template<bool addAlphaByte, bool ccmEnabled>\n>>  void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n>>  {\n>>         DECLARE_SRC_POINTERS(uint8_t)\n>> @@ -125,7 +125,7 @@ void DebayerCpu::debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n>>         }\n>>  }\n>>  \n>> -template<bool addAlphaByte>\n>> +template<bool addAlphaByte, bool ccmEnabled>\n>>  void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n>>  {\n>>         DECLARE_SRC_POINTERS(uint8_t)\n>> @@ -136,7 +136,7 @@ void DebayerCpu::debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n>>         }\n>>  }\n>>  \n>> -template<bool addAlphaByte>\n>> +template<bool addAlphaByte, bool ccmEnabled>\n>>  void DebayerCpu::debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n>>  {\n>>         DECLARE_SRC_POINTERS(uint16_t)\n>> @@ -148,7 +148,7 @@ void DebayerCpu::debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n>>         }\n>>  }\n>>  \n>> -template<bool addAlphaByte>\n>> +template<bool addAlphaByte, bool ccmEnabled>\n>>  void DebayerCpu::debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n>>  {\n>>         DECLARE_SRC_POINTERS(uint16_t)\n>> @@ -160,7 +160,7 @@ void DebayerCpu::debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n>>         }\n>>  }\n>>  \n>> -template<bool addAlphaByte>\n>> +template<bool addAlphaByte, bool ccmEnabled>\n>>  void DebayerCpu::debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n>>  {\n>>         DECLARE_SRC_POINTERS(uint16_t)\n>> @@ -172,7 +172,7 @@ void DebayerCpu::debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n>>         }\n>>  }\n>>  \n>> -template<bool addAlphaByte>\n>> +template<bool addAlphaByte, bool ccmEnabled>\n>>  void DebayerCpu::debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n>>  {\n>>         DECLARE_SRC_POINTERS(uint16_t)\n>> @@ -184,7 +184,7 @@ void DebayerCpu::debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n>>         }\n>>  }\n>>  \n>> -template<bool addAlphaByte>\n>> +template<bool addAlphaByte, bool ccmEnabled>\n>>  void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n>>  {\n>>         const int widthInBytes = window_.width * 5 / 4;\n>> @@ -210,7 +210,7 @@ void DebayerCpu::debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[])\n>>         }\n>>  }\n>>  \n>> -template<bool addAlphaByte>\n>> +template<bool addAlphaByte, bool ccmEnabled>\n>>  void DebayerCpu::debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n>>  {\n>>         const int widthInBytes = window_.width * 5 / 4;\n>> @@ -231,7 +231,7 @@ void DebayerCpu::debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[])\n>>         }\n>>  }\n>>  \n>> -template<bool addAlphaByte>\n>> +template<bool addAlphaByte, bool ccmEnabled>\n>>  void DebayerCpu::debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[])\n>>  {\n>>         const int widthInBytes = window_.width * 5 / 4;\n>> @@ -252,7 +252,7 @@ void DebayerCpu::debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[])\n>>         }\n>>  }\n>>  \n>> -template<bool addAlphaByte>\n>> +template<bool addAlphaByte, bool ccmEnabled>\n>>  void DebayerCpu::debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[])\n>>  {\n>>         const int widthInBytes = window_.width * 5 / 4;\n>> @@ -368,10 +368,11 @@ int DebayerCpu::setupStandardBayerOrder(BayerFormat::Order order)\n>>         return 0;\n>>  }\n>>  \n>> -#define SET_DEBAYER_METHODS(method0, method1)                                                \\\n>> -       debayer0_ = addAlphaByte ? &DebayerCpu::method0<true> : &DebayerCpu::method0<false>; \\\n>> -       debayer1_ = addAlphaByte ? &DebayerCpu::method1<true> : &DebayerCpu::method1<false>;\n>> +#define SET_DEBAYER_METHODS(method0, method1)                                                                        \\\n>> +       debayer0_ = addAlphaByte ? &DebayerCpu::method0<true, ccmEnabled> : &DebayerCpu::method0<false, ccmEnabled>; \\\n>> +       debayer1_ = addAlphaByte ? &DebayerCpu::method1<true, ccmEnabled> : &DebayerCpu::method1<false, ccmEnabled>;\n>>  \n>> +template<bool ccmEnabled>\n>>  int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat)\n>>  {\n>>         BayerFormat bayerFormat =\n>> @@ -464,7 +465,8 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputF\n>>  }\n>>  \n>>  int DebayerCpu::configure(const StreamConfiguration &inputCfg,\n>> -                         const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs)\n>> +                         const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs,\n>> +                         bool ccmEnabled)\n>>  {\n>>         if (getInputConfig(inputCfg.pixelFormat, inputConfig_) != 0)\n>>                 return -EINVAL;\n>> @@ -503,7 +505,10 @@ int DebayerCpu::configure(const StreamConfiguration &inputCfg,\n>>                 return -EINVAL;\n>>         }\n>>  \n>> -       if (setDebayerFunctions(inputCfg.pixelFormat, outputCfg.pixelFormat) != 0)\n>> +       int ret = ccmEnabled\n>> +                         ? setDebayerFunctions<true>(inputCfg.pixelFormat, outputCfg.pixelFormat)\n>> +                         : setDebayerFunctions<false>(inputCfg.pixelFormat, outputCfg.pixelFormat);\n>> +       if (ret != 0)\n>>                 return -EINVAL;\n>>  \n>>         window_.x = ((inputCfg.size.width - outputCfg.size.width) / 2) &\n>> diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h\n>> index 2c47e7c6..b2ec8f1b 100644\n>> --- a/src/libcamera/software_isp/debayer_cpu.h\n>> +++ b/src/libcamera/software_isp/debayer_cpu.h\n>> @@ -31,7 +31,8 @@ public:\n>>         ~DebayerCpu();\n>>  \n>>         int configure(const StreamConfiguration &inputCfg,\n>> -                     const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs);\n>> +                     const std::vector<std::reference_wrapper<StreamConfiguration>> &outputCfgs,\n>> +                     bool ccmEnabled);\n>>         Size patternSize(PixelFormat inputFormat);\n>>         std::vector<PixelFormat> formats(PixelFormat input);\n>>         std::tuple<unsigned int, unsigned int>\n>> @@ -85,28 +86,28 @@ private:\n>>         using debayerFn = void (DebayerCpu::*)(uint8_t *dst, const uint8_t *src[]);\n>>  \n>>         /* 8-bit raw bayer format */\n>> -       template<bool addAlphaByte>\n>> +       template<bool addAlphaByte, bool ccmEnabled>\n>>         void debayer8_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);\n>> -       template<bool addAlphaByte>\n>> +       template<bool addAlphaByte, bool ccmEnabled>\n>>         void debayer8_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);\n>>         /* unpacked 10-bit raw bayer format */\n>> -       template<bool addAlphaByte>\n>> +       template<bool addAlphaByte, bool ccmEnabled>\n>>         void debayer10_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);\n>> -       template<bool addAlphaByte>\n>> +       template<bool addAlphaByte, bool ccmEnabled>\n>>         void debayer10_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);\n>>         /* unpacked 12-bit raw bayer format */\n>> -       template<bool addAlphaByte>\n>> +       template<bool addAlphaByte, bool ccmEnabled>\n>>         void debayer12_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);\n>> -       template<bool addAlphaByte>\n>> +       template<bool addAlphaByte, bool ccmEnabled>\n>>         void debayer12_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);\n>>         /* CSI-2 packed 10-bit raw bayer format (all the 4 orders) */\n>> -       template<bool addAlphaByte>\n>> +       template<bool addAlphaByte, bool ccmEnabled>\n>>         void debayer10P_BGBG_BGR888(uint8_t *dst, const uint8_t *src[]);\n>> -       template<bool addAlphaByte>\n>> +       template<bool addAlphaByte, bool ccmEnabled>\n>>         void debayer10P_GRGR_BGR888(uint8_t *dst, const uint8_t *src[]);\n>> -       template<bool addAlphaByte>\n>> +       template<bool addAlphaByte, bool ccmEnabled>\n>>         void debayer10P_GBGB_BGR888(uint8_t *dst, const uint8_t *src[]);\n>> -       template<bool addAlphaByte>\n>> +       template<bool addAlphaByte, bool ccmEnabled>\n>>         void debayer10P_RGRG_BGR888(uint8_t *dst, const uint8_t *src[]);\n>>  \n>>         struct DebayerInputConfig {\n>> @@ -125,6 +126,7 @@ private:\n>>         int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config);\n>>         int getOutputConfig(PixelFormat outputFormat, DebayerOutputConfig &config);\n>>         int setupStandardBayerOrder(BayerFormat::Order order);\n>> +       template<bool ccmEnabled>\n>>         int setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputFormat);\n>>         void setupInputMemcpy(const uint8_t *linePointers[]);\n>>         void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src);\n>> diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp\n>> index 2bea64d9..6a07de85 100644\n>> --- a/src/libcamera/software_isp/software_isp.cpp\n>> +++ b/src/libcamera/software_isp/software_isp.cpp\n>> @@ -236,11 +236,12 @@ int SoftwareIsp::configure(const StreamConfiguration &inputCfg,\n>>  {\n>>         ASSERT(ipa_ && debayer_);\n>>  \n>> -       int ret = ipa_->configure(configInfo);\n>> +       bool ccmEnabled;\n>> +       int ret = ipa_->configure(configInfo, &ccmEnabled);\n>>         if (ret < 0)\n>>                 return ret;\n>>  \n>> -       return debayer_->configure(inputCfg, outputCfgs);\n>> +       return debayer_->configure(inputCfg, outputCfgs, ccmEnabled);\n>>  }\n>>  \n>>  /**\n>> -- \n>> 2.44.2\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 44473C32F9\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 10 Jan 2025 20:04:07 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 5589461891;\n\tFri, 10 Jan 2025 21:04:06 +0100 (CET)","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 5904F608AA\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 10 Jan 2025 21:04:04 +0100 (CET)","from mail-wr1-f70.google.com (mail-wr1-f70.google.com\n\t[209.85.221.70]) by relay.mimecast.com with ESMTP with STARTTLS\n\t(version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n\tus-mta-185-kRcT2lhPPk-PJNGskij6pg-1; Fri, 10 Jan 2025 15:04:02 -0500","by mail-wr1-f70.google.com with SMTP id\n\tffacd0b85a97d-385dcadffebso1230134f8f.0\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 10 Jan 2025 12:04:01 -0800 (PST)","from mzamazal-thinkpadp1gen3.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-38a8e37d0bdsm5309418f8f.3.2025.01.10.12.03.58\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tFri, 10 Jan 2025 12:03:58 -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=\"avP62LsP\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1736539443;\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=RXydk7TBKShATN3N8W9xxjyH4VHDKLxNbb81qHrZY0I=;\n\tb=avP62LsPqwSOtQxl2Fpu0f/xAINwoIm0CdanqIHC+H7SJ3YzC+I8x7RfJ+9TdISKN1H8SG\n\taQ9DktwbnhQpCI4S0ig3eMjFOMc6KHoqlaZzA59jsyul/vs/qXD8iNlc+RMsia0GWrUNbV\n\t1SbqdyrQWDkmPPjgeJ+r4Wa633fZQxs=","X-MC-Unique":"kRcT2lhPPk-PJNGskij6pg-1","X-Mimecast-MFC-AGG-ID":"kRcT2lhPPk-PJNGskij6pg","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1736539440; x=1737144240;\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=RXydk7TBKShATN3N8W9xxjyH4VHDKLxNbb81qHrZY0I=;\n\tb=Ohf/g/6PfcJHALZK9irzGbm2E5203N8Xuh/sZDEddCdzDKV8DMB5eCSVURkg47mUmH\n\tbBKjPPJQQoIqF/57K24YzeRcBS6HNTdDiZPwLzGq+QZToM70GawRblxg34MidBsaUA0+\n\t8BN7WDmuVdCxbi/qL6x7CDr1PcajMuMayckTx6PxZWgA5OlrZEXAbq4TB3HY6NGhuRzP\n\tmBP+2FDQp52gr+z9sAuM8IemEuIcDGIvbj0H5OTuPvtW6GzcyaxLzb34ZjWsh753/fPc\n\t8HMk6cEa1POkouQiTQtGDWfTK2paI0CwNyKr+qxnV92DRR4s50KyrrFcJ0ntM5ranGVN\n\tZb0g==","X-Gm-Message-State":"AOJu0YzLtd8gVQRx5dykWWCw31QqUNLAZe4kQ60bPPafHckS0l4rGOa3\n\ty0BXVJHGncWdt08kqjaBhHcClPy0MIKq/hO4bJmrFNn8eBWjUaDUPgGDCnRUbCzZdnnFxVA8emp\n\tE4dMKcHiy/vxjVKjhgl5W3JM7H3vAvobWdXv4yMOTGBpXGG6VM464q0RqGcrP4Udxh7R8I/JNsu\n\tA3KkM=","X-Gm-Gg":"ASbGncsiwFSh7U2PkWCIXc9fwkVPwRWmKsYYAWfGYpg91k2hy9Ega32YicKnjdLhRCi\n\tIBZ4b9fQQWYQZHjoMEQedf5KySwKFitxKQBo+0UFjIdmOXkPwz2Jc3NCmgae7bRHA8XzeK2Uql+\n\td8TJ2HPHAa8rlmXADtsyQG7SmIc6eLUhv/OIhGfITVemf7UtGzdBNTVopTu+vVvkuDiZqQjLZgQ\n\tQIhvzgdjiHDtVotBCEEt+IJPmxa2VNjdYB0tAk9Um4Npk+GdcnDutR6thl117Oh2kyVhpAm682X\n\t5BHUrJp8b2wrihpEFrsQWLqDxOOflWHQCw==","X-Received":["by 2002:a5d:648b:0:b0:386:3e3c:ef1 with SMTP id\n\tffacd0b85a97d-38a87312f36mr12257347f8f.35.1736539440471; \n\tFri, 10 Jan 2025 12:04:00 -0800 (PST)","by 2002:a5d:648b:0:b0:386:3e3c:ef1 with SMTP id\n\tffacd0b85a97d-38a87312f36mr12257293f8f.35.1736539439781; \n\tFri, 10 Jan 2025 12:03:59 -0800 (PST)"],"X-Google-Smtp-Source":"AGHT+IFnSzZDSrFnbRnLWkvITn/UCVv/y5TdAp5rN2g91p7mTTIWZhFeiKdZQo6jLGtFW7n9ev1G1A==","From":"Milan Zamazal <mzamazal@redhat.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org,  Robert Mader\n\t<robert.mader@collabora.com>,  Hans de Goede <hdegoede@redhat.com>,\n\tLaurent Pinchart <laurent.pinchart@ideasonboard.com>","Subject":"Re: [PATCH v3 8/9] libcamera: software_isp: Track whether CCM is\n\tenabled","In-Reply-To":"<173644395512.3771432.17163385300401870311@ping.linuxembedded.co.uk>\n\t(Kieran Bingham's message of \"Thu, 09 Jan 2025 17:32:35 +0000\")","References":"<20241210153440.1007470-1-mzamazal@redhat.com>\n\t<20241210153440.1007470-9-mzamazal@redhat.com>\n\t<173644395512.3771432.17163385300401870311@ping.linuxembedded.co.uk>","Date":"Fri, 10 Jan 2025 21:03:57 +0100","Message-ID":"<85r05amo5u.fsf@mzamazal-thinkpadp1gen3.tpbc.csb>","User-Agent":"Gnus/5.13 (Gnus v5.13)","MIME-Version":"1.0","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"kT2LguZOjn1b-nO86SMybmXpmp-TL4fG904WnsTPGsw_1736539441","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>"}}]