[{"id":33248,"web_url":"https://patchwork.libcamera.org/comment/33248/","msgid":"<20250203004927.GL12673@pendragon.ideasonboard.com>","date":"2025-02-03T00:49:27","subject":"Re: [PATCH v5 07/10] libcamera: software_isp: Add CCM algorithm","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Milan,\n\nThank you for the patch.\n\nOn Thu, Jan 30, 2025 at 07:14:44PM +0100, Milan Zamazal wrote:\n> This patch adds color correction matrix (CCM) algorithm to software ISP.\n> It is based on the corresponding algorithm in rkisp1.\n> \n> The primary difference against hardware pipelines is that applying the\n> CCM is optional.  Applying CCM causes a significant slowdown, time\n> needed to process a frame raises by 40-90% on tested platforms.  If CCM\n> is really needed, it can be applied, if not, it's better to stick\n> without it.  This can be configured by presence or omission of Ccm\n> algorithm in the tuning file.\n> \n> CCM is changed only if the determined temperature changes by at least\n> 100 K (an arbitrarily selected value), to avoid recomputing the matrices\n> and lookup tables all the time.\n> \n> The outputs of the algorithm are not used yet, they will be enabled in\n> followup patches.\n> \n> Signed-off-by: Milan Zamazal <mzamazal@redhat.com>\n> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> ---\n>  src/ipa/simple/algorithms/ccm.cpp     | 79 +++++++++++++++++++++++++++\n>  src/ipa/simple/algorithms/ccm.h       | 43 +++++++++++++++\n>  src/ipa/simple/algorithms/meson.build |  1 +\n>  src/ipa/simple/ipa_context.h          | 12 ++++\n>  4 files changed, 135 insertions(+)\n>  create mode 100644 src/ipa/simple/algorithms/ccm.cpp\n>  create mode 100644 src/ipa/simple/algorithms/ccm.h\n> \n> diff --git a/src/ipa/simple/algorithms/ccm.cpp b/src/ipa/simple/algorithms/ccm.cpp\n> new file mode 100644\n> index 00000000..069a12f8\n> --- /dev/null\n> +++ b/src/ipa/simple/algorithms/ccm.cpp\n> @@ -0,0 +1,79 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2024, Ideas On Board\n> + * Copyright (C) 2024-2025, Red Hat Inc.\n> + *\n> + * Color correction matrix\n> + */\n> +\n> +#include \"ccm.h\"\n> +\n> +#include <libcamera/base/log.h>\n> +#include <libcamera/base/utils.h>\n> +\n> +#include <libcamera/control_ids.h>\n> +\n> +namespace {\n> +\n> +constexpr unsigned int kTemperatureThreshold = 100;\n> +\n> +}\n> +\n> +namespace libcamera {\n> +\n> +namespace ipa::soft::algorithms {\n> +\n> +LOG_DEFINE_CATEGORY(IPASoftCcm)\n> +\n> +int Ccm::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData)\n> +{\n> +\tint ret = ccm_.readYaml(tuningData[\"ccms\"], \"ct\", \"ccm\");\n> +\tif (ret < 0) {\n> +\t\tLOG(IPASoftCcm, Error)\n> +\t\t\t<< \"Failed to parse 'ccm' parameter from tuning file.\";\n> +\t\treturn ret;\n> +\t}\n> +\n> +\treturn 0;\n> +}\n> +\n> +void Ccm::prepare(IPAContext &context, const uint32_t frame,\n> +\t\t  IPAFrameContext &frameContext, [[maybe_unused]] DebayerParams *params)\n> +{\n> +\tconst unsigned int ct = context.activeState.awb.temperatureK;\n> +\n> +\t/* Change CCM only on bigger temperature changes. */\n> +\tif (frame > 0 &&\n> +\t    utils::abs_diff(ct, lastCt_) < kTemperatureThreshold) {\n> +\t\tframeContext.ccm.ccm = context.activeState.ccm.ccm;\n> +\t\tcontext.activeState.ccm.changed = false;\n> +\t\treturn;\n> +\t}\n> +\n> +\tlastCt_ = ct;\n> +\tMatrix<double, 3, 3> ccm = ccm_.getInterpolated(ct);\n> +\n> +\tcontext.activeState.ccm.ccm = ccm;\n> +\tframeContext.ccm.ccm = ccm;\n> +\tcontext.activeState.ccm.changed = true;\n> +}\n> +\n> +void Ccm::process([[maybe_unused]] IPAContext &context,\n> +\t\t  [[maybe_unused]] const uint32_t frame,\n> +\t\t  IPAFrameContext &frameContext,\n> +\t\t  [[maybe_unused]] const SwIspStats *stats,\n> +\t\t  ControlList &metadata)\n> +{\n> +\tfloat m[9];\n> +\tfor (unsigned int i = 0; i < 3; i++) {\n> +\t\tfor (unsigned int j = 0; j < 3; j++)\n> +\t\t\tm[i * 3 + j] = frameContext.ccm.ccm[i][j];\n> +\t}\n> +\tmetadata.set(controls::ColourCorrectionMatrix, m);\n> +}\n> +\n> +REGISTER_IPA_ALGORITHM(Ccm, \"Ccm\")\n> +\n> +} /* namespace ipa::soft::algorithms */\n> +\n> +} /* namespace libcamera */\n> diff --git a/src/ipa/simple/algorithms/ccm.h b/src/ipa/simple/algorithms/ccm.h\n> new file mode 100644\n> index 00000000..e5dc6506\n> --- /dev/null\n> +++ b/src/ipa/simple/algorithms/ccm.h\n> @@ -0,0 +1,43 @@\n> +/* SPDX-License-Identifier: LGPL-2.1-or-later */\n> +/*\n> + * Copyright (C) 2024-2025, Red Hat Inc.\n> + *\n> + * Color correction matrix\n> + */\n> +\n> +#pragma once\n> +\n> +#include \"libcamera/internal/matrix.h\"\n> +\n> +#include <libipa/interpolator.h>\n> +\n> +#include \"algorithm.h\"\n> +\n> +namespace libcamera {\n> +\n> +namespace ipa::soft::algorithms {\n> +\n> +class Ccm : public Algorithm\n> +{\n> +public:\n> +\tCcm() = default;\n> +\t~Ccm() = default;\n> +\n> +\tint init(IPAContext &context, const YamlObject &tuningData) override;\n> +\tvoid prepare(IPAContext &context,\n> +\t\t     const uint32_t frame,\n> +\t\t     IPAFrameContext &frameContext,\n> +\t\t     DebayerParams *params) override;\n> +\tvoid process(IPAContext &context, const uint32_t frame,\n> +\t\t     IPAFrameContext &frameContext,\n> +\t\t     const SwIspStats *stats,\n> +\t\t     ControlList &metadata) override;\n> +\n> +private:\n> +\tunsigned int lastCt_;\n> +\tInterpolator<Matrix<double, 3, 3>> ccm_;\n> +};\n> +\n> +} /* namespace ipa::soft::algorithms */\n> +\n> +} /* namespace libcamera */\n> diff --git a/src/ipa/simple/algorithms/meson.build b/src/ipa/simple/algorithms/meson.build\n> index 37a2eb53..2d0adb05 100644\n> --- a/src/ipa/simple/algorithms/meson.build\n> +++ b/src/ipa/simple/algorithms/meson.build\n> @@ -4,5 +4,6 @@ soft_simple_ipa_algorithms = files([\n>      'awb.cpp',\n>      'agc.cpp',\n>      'blc.cpp',\n> +    'ccm.cpp',\n>      'lut.cpp',\n>  ])\n> diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h\n> index df0552db..bd6c66d8 100644\n> --- a/src/ipa/simple/ipa_context.h\n> +++ b/src/ipa/simple/ipa_context.h\n> @@ -13,6 +13,8 @@\n>  \n>  #include <libcamera/controls.h>\n>  \n> +#include \"libcamera/internal/matrix.h\"\n> +\n>  #include <libipa/fc_queue.h>\n>  #include <libipa/vector.h>\n>  \n> @@ -47,6 +49,12 @@ struct IPAActiveState {\n>  \t\tuint8_t blackLevel;\n>  \t\tdouble contrast;\n>  \t} gamma;\n> +\n> +\tstruct {\n> +\t\tMatrix<double, 3, 3> ccm;\n> +\t\tbool changed;\n> +\t} ccm;\n> +\n>  \tstruct {\n>  \t\t/* 0..2 range, 1.0 = normal */\n>  \t\tstd::optional<double> contrast;\n> @@ -54,6 +62,10 @@ struct IPAActiveState {\n>  };\n>  \n>  struct IPAFrameContext : public FrameContext {\n> +\tstruct {\n> +\t\tMatrix<double, 3, 3> ccm;\n> +\t} ccm;\n> +\n>  \tstruct {\n>  \t\tint32_t exposure;\n>  \t\tdouble gain;","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 E3C1CC32DF\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon,  3 Feb 2025 00:49:33 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 0CD9E68579;\n\tMon,  3 Feb 2025 01:49:33 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 8BE8261876\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  3 Feb 2025 01:49:31 +0100 (CET)","from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi\n\t[81.175.209.231])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 36F48497;\n\tMon,  3 Feb 2025 01:48:20 +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=\"psrXpJCx\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1738543700;\n\tbh=hrkd/4fSZlob2h1MVPge5kKfeg/RZje5EufXbqsIC4I=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=psrXpJCxJ7oRcy0O4DjANgZbXBpgLgtN+a1GERkIsptT6FMHUZEvwPzjYjHBllMWv\n\tAJ3JGbYcY9XJX6Jq7gx0n8ovs3b31PBsaf4oqd+yG+EAU38LQxSQvCkuVojAHMjWmx\n\t7jAqDJXH99SWpX8HGBUxkvAH8MpYALG9muePKPyE=","Date":"Mon, 3 Feb 2025 02:49:27 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Milan Zamazal <mzamazal@redhat.com>","Cc":"libcamera-devel@lists.libcamera.org,\n\tRobert Mader <robert.mader@collabora.com>,\n\tHans de Goede <hdegoede@redhat.com>,\n\tKieran Bingham <kieran.bingham@ideasonboard.com>","Subject":"Re: [PATCH v5 07/10] libcamera: software_isp: Add CCM algorithm","Message-ID":"<20250203004927.GL12673@pendragon.ideasonboard.com>","References":"<20250130181449.130492-1-mzamazal@redhat.com>\n\t<20250130181449.130492-8-mzamazal@redhat.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20250130181449.130492-8-mzamazal@redhat.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>"}}]