Patch Detail
Show a patch.
GET /api/1.1/patches/22736/?format=api
{ "id": 22736, "url": "https://patchwork.libcamera.org/api/1.1/patches/22736/?format=api", "web_url": "https://patchwork.libcamera.org/patch/22736/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/1.1/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20250205212725.138055-9-mzamazal@redhat.com>", "date": "2025-02-05T21:27:20", "name": "[v6,07/10] libcamera: software_isp: Add CCM algorithm", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "a909efdc678adca35556c890045015a115679e49", "submitter": { "id": 177, "url": "https://patchwork.libcamera.org/api/1.1/people/177/?format=api", "name": "Milan Zamazal", "email": "mzamazal@redhat.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/22736/mbox/", "series": [ { "id": 4989, "url": "https://patchwork.libcamera.org/api/1.1/series/4989/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4989", "date": "2025-02-05T21:27:12", "name": "Software ISP support for CCM", "version": 6, "mbox": "https://patchwork.libcamera.org/series/4989/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/22736/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/22736/checks/", "tags": {}, "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 CEF22C32F4\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 5 Feb 2025 21:28:00 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7E325685E5;\n\tWed, 5 Feb 2025 22:28:00 +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 C77F5685DD\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 5 Feb 2025 22:27:58 +0100 (CET)", "from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com\n\t(ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97])\n\tby relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n\tcipher=TLS_AES_256_GCM_SHA384) id us-mta-617-YhmlzwdCPYy7-weSSpMlfA-1;\n\tWed, 05 Feb 2025 16:27:56 -0500", "from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com\n\t(mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com\n\t[10.30.177.93])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\tkey-exchange X25519 server-signature RSA-PSS (2048 bits)\n\tserver-digest SHA256) (No client certificate requested)\n\tby mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix)\n\twith ESMTPS id 6AFD91800878; Wed, 5 Feb 2025 21:27:55 +0000 (UTC)", "from mzamazal-thinkpadp1gen3.tpbc.com (unknown [10.45.224.28])\n\tby mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix)\n\twith ESMTP id 412221800872; Wed, 5 Feb 2025 21:27:53 +0000 (UTC)" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=redhat.com header.i=@redhat.com\n\theader.b=\"FFQDFFPg\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1738790877;\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\tcontent-transfer-encoding:content-transfer-encoding:\n\tin-reply-to:in-reply-to:references:references;\n\tbh=gu9W2L/K/kPTCkTbmOYYJlWjwmYzDXzV5tME2ZuVYrw=;\n\tb=FFQDFFPgstetESL+sVmsDtdqwenX1D79IE3ARpHQI/uVYqQNcdnsetMf2+05jd8o2E3dO1\n\tbpfHeP+R5S3y7OaVj4eRkult8kUoQLEtjHhbPmJKKcG5grJjaIOrreA008lfwWe60cxvTL\n\tUPgEbAD626nc79SHJFQolRPKu3qY0MQ=", "X-MC-Unique": "YhmlzwdCPYy7-weSSpMlfA-1", "X-Mimecast-MFC-AGG-ID": "YhmlzwdCPYy7-weSSpMlfA", "From": "Milan Zamazal <mzamazal@redhat.com>", "To": "libcamera-devel@lists.libcamera.org", "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>,\n\tKieran Bingham <kieran.bingham@ideasonboard.com>", "Subject": "[PATCH v6 07/10] libcamera: software_isp: Add CCM algorithm", "Date": "Wed, 5 Feb 2025 22:27:20 +0100", "Message-ID": "<20250205212725.138055-9-mzamazal@redhat.com>", "In-Reply-To": "<20250205212725.138055-1-mzamazal@redhat.com>", "References": "<20250205212725.138055-1-mzamazal@redhat.com>", "MIME-Version": "1.0", "X-Scanned-By": "MIMEDefang 3.4.1 on 10.30.177.93", "X-Mimecast-Spam-Score": "0", "X-Mimecast-MFC-PROC-ID": "Q7sGjOiKb-3E-TiN5yuwCUXijBU0HuDf7OGLuQsaGZY_1738790875", "X-Mimecast-Originator": "redhat.com", "Content-Transfer-Encoding": "8bit", "content-type": "text/plain; charset=\"US-ASCII\"; x-default=true", "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>" }, "content": "This patch adds color correction matrix (CCM) algorithm to software ISP.\nIt is based on the corresponding algorithm in rkisp1.\n\nThe primary difference against hardware pipelines is that applying the\nCCM is optional. Applying CCM causes a significant slowdown, time\nneeded to process a frame raises by 40-90% on tested platforms. If CCM\nis really needed, it can be applied, if not, it's better to stick\nwithout it. This can be configured by presence or omission of Ccm\nalgorithm in the tuning file.\n\nCCM is changed only if the determined temperature changes by at least\n100 K (an arbitrarily selected value), to avoid recomputing the matrices\nand lookup tables all the time.\n\nSince the CCM is float, rather than double, to use the same type as in\nthe rkisp1 pipeline, the type of color gains is changed from double to\nfloat.\n\nThe outputs of the algorithm are not used yet, they will be enabled in\nfollowup patches.\n\nSigned-off-by: Milan Zamazal <mzamazal@redhat.com>\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n---\n src/ipa/simple/algorithms/awb.cpp | 4 +-\n src/ipa/simple/algorithms/ccm.cpp | 74 +++++++++++++++++++++++++++\n src/ipa/simple/algorithms/ccm.h | 43 ++++++++++++++++\n src/ipa/simple/algorithms/lut.cpp | 2 +-\n src/ipa/simple/algorithms/meson.build | 1 +\n src/ipa/simple/ipa_context.h | 14 ++++-\n 6 files changed, 134 insertions(+), 4 deletions(-)\n create mode 100644 src/ipa/simple/algorithms/ccm.cpp\n create mode 100644 src/ipa/simple/algorithms/ccm.h", "diff": "diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp\nindex 4e31e386..ec77c6e5 100644\n--- a/src/ipa/simple/algorithms/awb.cpp\n+++ b/src/ipa/simple/algorithms/awb.cpp\n@@ -59,9 +59,9 @@ void Awb::process(IPAContext &context,\n \t */\n \tauto &gains = context.activeState.awb.gains;\n \tgains = { {\n-\t\tsumR <= sumG / 4 ? 4.0 : static_cast<double>(sumG) / sumR,\n+\t\tsumR <= sumG / 4 ? 4.0f : static_cast<float>(sumG) / sumR,\n \t\t1.0,\n-\t\tsumB <= sumG / 4 ? 4.0 : static_cast<double>(sumG) / sumB,\n+\t\tsumB <= sumG / 4 ? 4.0f : static_cast<float>(sumG) / sumB,\n \t} };\n \n \tRGB<double> rgbGains{ { 1 / gains.r(), 1 / gains.g(), 1 / gains.b() } };\ndiff --git a/src/ipa/simple/algorithms/ccm.cpp b/src/ipa/simple/algorithms/ccm.cpp\nnew file mode 100644\nindex 00000000..86e0395c\n--- /dev/null\n+++ b/src/ipa/simple/algorithms/ccm.cpp\n@@ -0,0 +1,74 @@\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<float, 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+\tmetadata.set(controls::ColourCorrectionMatrix, frameContext.ccm.ccm.data());\n+}\n+\n+REGISTER_IPA_ALGORITHM(Ccm, \"Ccm\")\n+\n+} /* namespace ipa::soft::algorithms */\n+\n+} /* namespace libcamera */\ndiff --git a/src/ipa/simple/algorithms/ccm.h b/src/ipa/simple/algorithms/ccm.h\nnew file mode 100644\nindex 00000000..f4e2b85b\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<float, 3, 3>> ccm_;\n+};\n+\n+} /* namespace ipa::soft::algorithms */\n+\n+} /* namespace libcamera */\ndiff --git a/src/ipa/simple/algorithms/lut.cpp b/src/ipa/simple/algorithms/lut.cpp\nindex 60dd0624..352bbf57 100644\n--- a/src/ipa/simple/algorithms/lut.cpp\n+++ b/src/ipa/simple/algorithms/lut.cpp\n@@ -103,7 +103,7 @@ void Lut::prepare(IPAContext &context,\n \t\tconst double div = static_cast<double>(DebayerParams::kRGBLookupSize) /\n \t\t\t\t gammaTableSize;\n \t\t/* Apply gamma after gain! */\n-\t\tconst RGB<double> lutGains = (gains * i / div).min(gammaTableSize - 1);\n+\t\tconst RGB<float> lutGains = (gains * i / div).min(gammaTableSize - 1);\n \t\tparams->red[i] = gammaTable[static_cast<unsigned int>(lutGains.r())];\n \t\tparams->green[i] = gammaTable[static_cast<unsigned int>(lutGains.g())];\n \t\tparams->blue[i] = gammaTable[static_cast<unsigned int>(lutGains.b())];\ndiff --git a/src/ipa/simple/algorithms/meson.build b/src/ipa/simple/algorithms/meson.build\nindex 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 ])\ndiff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h\nindex df0552db..57883218 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@@ -37,7 +39,7 @@ struct IPAActiveState {\n \t} blc;\n \n \tstruct {\n-\t\tRGB<double> gains;\n+\t\tRGB<float> gains;\n \t\tunsigned int temperatureK;\n \t} awb;\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<float, 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<float, 3, 3> ccm;\n+\t} ccm;\n+\n \tstruct {\n \t\tint32_t exposure;\n \t\tdouble gain;\n", "prefixes": [ "v6", "07/10" ] }