Patch Detail
Show a patch.
GET /api/patches/26839/?format=api
{ "id": 26839, "url": "https://patchwork.libcamera.org/api/patches/26839/?format=api", "web_url": "https://patchwork.libcamera.org/patch/26839/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/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": "<20260604095105.68798-19-mzamazal@redhat.com>", "date": "2026-06-04T09:51:00", "name": "[RFC,v3,14/17] libcamera: software_isp: Allocate statistics buffers", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "f6f66cc233dec77153219176133bbc9f9d60c0c6", "submitter": { "id": 177, "url": "https://patchwork.libcamera.org/api/people/177/?format=api", "name": "Milan Zamazal", "email": "mzamazal@redhat.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/26839/mbox/", "series": [ { "id": 5976, "url": "https://patchwork.libcamera.org/api/series/5976/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5976", "date": "2026-06-04T09:50:42", "name": "Software ISP: Share params and stats buffers", "version": 3, "mbox": "https://patchwork.libcamera.org/series/5976/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/26839/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/26839/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 08405C328C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 4 Jun 2026 09:52:04 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id B48946374A;\n\tThu, 4 Jun 2026 11:52:03 +0200 (CEST)", "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 9E0846373C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 4 Jun 2026 11:52:01 +0200 (CEST)", "from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com\n\t(ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63])\n\tby relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n\tcipher=TLS_AES_256_GCM_SHA384) id us-mta-475-vh6V6PanOwSPzOFGy25GTw-1;\n\tThu, 04 Jun 2026 05:51:57 -0400", "from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com\n\t(mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4])\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-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix)\n\twith ESMTPS id 739E5195608B; Thu, 4 Jun 2026 09:51:56 +0000 (UTC)", "from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.34.156])\n\tby mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix)\n\twith ESMTP id ABF4430001A1; Thu, 4 Jun 2026 09:51:54 +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=\"NwdleBNV\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1780566720;\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=mfsp11yEJ9c7syjjVm8HIxehAwxPUcdZ65gDFl06Xuk=;\n\tb=NwdleBNVWxXZeRmrAvIPXL5cTD7d1OeVhn9qDWjCI2hOs+ag74jtIRvIFRhPjfIiK/Ed30\n\txSlAkxaQrl9/J1LJC1cipsusnSk9Cn9nvAjrRwZ2xNKUqroV90uu9bxvXOix3Esz08fA4x\n\twkYkT8uX5GbUiGIWm66VO2a1RMOf/ME=", "X-MC-Unique": "vh6V6PanOwSPzOFGy25GTw-1", "X-Mimecast-MFC-AGG-ID": "vh6V6PanOwSPzOFGy25GTw_1780566716", "From": "Milan Zamazal <mzamazal@redhat.com>", "To": "libcamera-devel@lists.libcamera.org", "Cc": "Milan Zamazal <mzamazal@redhat.com>, =?utf-8?b?QmFybmFiw6FzIFDFkWN6?=\n\t=?utf-8?q?e?= <barnabas.pocze@ideasonboard.com>,\n\tjohannes.goede@oss.qualcomm.com", "Subject": "[RFC PATCH v3 14/17] libcamera: software_isp: Allocate statistics\n\tbuffers", "Date": "Thu, 4 Jun 2026 11:51:00 +0200", "Message-ID": "<20260604095105.68798-19-mzamazal@redhat.com>", "In-Reply-To": "<20260604095105.68798-1-mzamazal@redhat.com>", "References": "<20260604095105.68798-1-mzamazal@redhat.com>", "MIME-Version": "1.0", "X-Scanned-By": "MIMEDefang 3.4.1 on 10.30.177.4", "X-Mimecast-Spam-Score": "0", "X-Mimecast-MFC-PROC-ID": "eh7a3t8lalC9VIZIc-eXN83M3PuSUVDXlqBar3NjyKA_1780566716", "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": "In order to be able to use multiple shared statistics buffers, we must\nallocate them. They are allocated in SoftwareIsp and passed to\nSwIspStats. This changes the previous behavior when the (single) shared\nstatistics buffer was created in SwIspStats. Centralizing it to\nSoftwareIsp makes sharing multiple buffers with IPA easier.\n\nCurrently only one of the allocated buffers is used. This will be\nchanged once the buffers are shared with IPA in a followup patch.\n\nSigned-off-by: Milan Zamazal <mzamazal@redhat.com>\n---\n .../internal/software_isp/software_isp.h | 5 +++\n .../internal/software_isp/swstats_cpu.h | 11 ++---\n src/libcamera/software_isp/software_isp.cpp | 44 ++++++++++++++++---\n src/libcamera/software_isp/swstats_cpu.cpp | 26 ++++++-----\n 4 files changed, 62 insertions(+), 24 deletions(-)", "diff": "diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h\nindex 3e879c630..451596163 100644\n--- a/include/libcamera/internal/software_isp/software_isp.h\n+++ b/include/libcamera/internal/software_isp/software_isp.h\n@@ -33,6 +33,7 @@\n #include \"libcamera/internal/pipeline_handler.h\"\n #include \"libcamera/internal/shared_mem_object.h\"\n #include \"libcamera/internal/software_isp/debayer_params.h\"\n+#include \"libcamera/internal/software_isp/swstats_cpu.h\"\n \n namespace libcamera {\n \n@@ -91,6 +92,10 @@ public:\n private:\n \tvoid paramsBufferReady(const uint32_t paramsBufferId);\n \tbool allocateParamsBuffers(const unsigned int bufferCount);\n+\tstd::unique_ptr<SwStatsCpu> allocateStatsBuffers(\n+\t\tconst CameraManager &cm,\n+\t\tstd::map<uint32_t, SharedFD> &fdStats,\n+\t\tconst unsigned int bufferCount);\n \tvoid setSensorCtrls(const ControlList &sensorControls);\n \tvoid statsReady(uint32_t frame, const uint32_t statsBufferId);\n \tvoid statsProcessed(const uint32_t statsBufferId);\ndiff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h\nindex fd3f97cbb..cf2f88fcb 100644\n--- a/include/libcamera/internal/software_isp/swstats_cpu.h\n+++ b/include/libcamera/internal/software_isp/swstats_cpu.h\n@@ -1,7 +1,7 @@\n /* SPDX-License-Identifier: LGPL-2.1-or-later */\n /*\n * Copyright (C) 2023, Linaro Ltd\n- * Copyright (C) 2023, Red Hat Inc.\n+ * Copyright (C) 2023-2026 Red Hat Inc.\n *\n * Authors:\n * Hans de Goede <hdegoede@redhat.com>\n@@ -11,6 +11,7 @@\n \n #pragma once\n \n+#include <map>\n #include <stdint.h>\n #include <vector>\n \n@@ -35,7 +36,7 @@ struct StreamConfiguration;\n class SwStatsCpu\n {\n public:\n-\tSwStatsCpu(const CameraManager &cm);\n+\tSwStatsCpu(const CameraManager &cm, std::unique_ptr<std::map<uint32_t, SharedMemObject<SwIspStats>>> sharedStats);\n \t~SwStatsCpu() = default;\n \n \t/*\n@@ -46,9 +47,9 @@ public:\n \t */\n \tstatic constexpr uint32_t kStatPerNumFrames = 4;\n \n-\tbool isValid() const { return sharedStats_.fd().isValid(); }\n+\tbool isValid() const { return sharedStats_->begin()->second.fd().isValid(); }\n \n-\tconst SharedFD &getStatsFD() { return sharedStats_.fd(); }\n+\tconst SharedFD &getStatsFD() { return sharedStats_->begin()->second.fd(); }\n \n \tconst Size &patternSize() { return patternSize_; }\n \n@@ -119,7 +120,7 @@ private:\n \tunsigned int sumShift_;\n \n \tstd::vector<SwIspStats> stats_;\n-\tSharedMemObject<SwIspStats> sharedStats_;\n+\tstd::unique_ptr<std::map<uint32_t, SharedMemObject<SwIspStats>>> sharedStats_;\n \tBenchmark bench_;\n };\n \ndiff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp\nindex c44e035b8..c4da647e8 100644\n--- a/src/libcamera/software_isp/software_isp.cpp\n+++ b/src/libcamera/software_isp/software_isp.cpp\n@@ -14,6 +14,8 @@\n #include <sys/mman.h>\n #include <sys/types.h>\n #include <unistd.h>\n+#include <utility>\n+#include <vector>\n \n #include <libcamera/base/log.h>\n #include <libcamera/base/shared_fd.h>\n@@ -26,7 +28,10 @@\n \n #include \"libcamera/internal/bayer_format.h\"\n #include \"libcamera/internal/framebuffer.h\"\n+#include \"libcamera/internal/ipa_manager.h\"\n+#include \"libcamera/internal/shared_mem_object.h\"\n #include \"libcamera/internal/software_isp/debayer_params.h\"\n+#include \"libcamera/internal/software_isp/swisp_stats.h\"\n \n #include \"debayer_cpu.h\"\n #if HAVE_DEBAYER_EGL\n@@ -99,17 +104,15 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe,\n \n \tconst CameraManager &cm = *pipe->cameraManager();\n \n-\tauto stats = std::make_unique<SwStatsCpu>(cm);\n-\tif (!stats->isValid()) {\n-\t\tLOG(SoftwareIsp, Error) << \"Failed to create SwStatsCpu object\";\n-\t\treturn;\n-\t}\n-\tstats->statsReady.connect(this, &SoftwareIsp::statsReady);\n-\n \tstd::map<uint32_t, SharedFD> fdParams;\n \tfor (auto &[bufferId, item] : sharedParams_)\n \t\tfdParams[bufferId] = item.fd();\n \n+\tstd::map<uint32_t, SharedFD> fdStats;\n+\tauto stats = allocateStatsBuffers(cm, fdStats, bufferCount);\n+\tif (!stats)\n+\t\treturn;\n+\n #if HAVE_DEBAYER_EGL\n \tconst GlobalConfiguration &configuration = cm._d()->configuration();\n \tstd::optional<std::string> softISPMode = configuration.option<std::string>({ \"software_isp\", \"mode\" });\n@@ -203,6 +206,33 @@ bool SoftwareIsp::allocateParamsBuffers(const unsigned int bufferCount)\n \treturn true;\n }\n \n+std::unique_ptr<SwStatsCpu> SoftwareIsp::allocateStatsBuffers(\n+\tconst CameraManager &cm,\n+\tstd::map<uint32_t, SharedFD> &fdStats,\n+\tconst unsigned int bufferCount)\n+{\n+\tauto sharedStats = std::make_unique<std::map<uint32_t, SharedMemObject<SwIspStats>>>();\n+\tfor (unsigned int bufferId = 0; bufferId < bufferCount; bufferId++) {\n+\t\tauto shared = SharedMemObject<SwIspStats>(\"softIsp_stats\");\n+\t\tif (!shared) {\n+\t\t\tLOG(SoftwareIsp, Error) << \"Failed to create shared memory for statistics\";\n+\t\t\treturn nullptr;\n+\t\t}\n+\t\tif (!shared.fd().isValid()) {\n+\t\t\tLOG(SoftwareIsp, Error) << \"Invalid fd of shared statistics\";\n+\t\t\treturn nullptr;\n+\t\t}\n+\n+\t\tfdStats[bufferId] = shared.fd();\n+\t\tsharedStats->emplace(bufferId, std::move(shared));\n+\t}\n+\n+\tauto stats = std::make_unique<SwStatsCpu>(cm, std::move(sharedStats));\n+\tstats->statsReady.connect(this, &SoftwareIsp::statsReady);\n+\n+\treturn stats;\n+}\n+\n /**\n * \\fn int SoftwareIsp::loadConfiguration([[maybe_unused]] const std::string &filename)\n * \\brief Load a configuration from a file\ndiff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp\nindex 0e645f7e1..e6beb9692 100644\n--- a/src/libcamera/software_isp/swstats_cpu.cpp\n+++ b/src/libcamera/software_isp/swstats_cpu.cpp\n@@ -11,6 +11,8 @@\n \n #include \"libcamera/internal/software_isp/swstats_cpu.h\"\n \n+#include <memory>\n+\n #include <libcamera/base/log.h>\n \n #include <libcamera/stream.h>\n@@ -36,9 +38,11 @@ namespace libcamera {\n */\n \n /**\n- * \\fn SwStatsCpu::SwStatsCpu(const CameraManager &cm)\n+ * \\fn SwStatsCpu::SwStatsCpu(const CameraManager &cm, std::unique_ptr<std::map<uint32_t, SharedMemObject<SwIspStats>>> sharedStats)\n * \\brief Construct a SwStatsCpu object\n * \\param[in] cm The camera manager\n+ * \\param[in] sharedStats Mapping of statistics buffer ids to statistics\n+ * instances that are shared with the IPA\n *\n * Creates a SwStatsCpu object and initialises shared memory for statistics\n * exchange.\n@@ -159,12 +163,9 @@ namespace libcamera {\n \n LOG_DEFINE_CATEGORY(SwStatsCpu)\n \n-SwStatsCpu::SwStatsCpu(const CameraManager &cm)\n-\t: sharedStats_(\"softIsp_stats\"), bench_(cm, \"CPU stats\")\n+SwStatsCpu::SwStatsCpu(const CameraManager &cm, std::unique_ptr<std::map<uint32_t, SharedMemObject<SwIspStats>>> sharedStats)\n+\t: sharedStats_(std::move(sharedStats)), bench_(cm, \"CPU stats\")\n {\n-\tif (!sharedStats_)\n-\t\tLOG(SwStatsCpu, Error)\n-\t\t\t<< \"Failed to create shared memory for statistics\";\n }\n \n static constexpr unsigned int kRedYMul = 77; /* 0.299 * 256 */\n@@ -354,20 +355,21 @@ void SwStatsCpu::finishFrame(uint32_t frame,\n \t\t\t const uint32_t statsBufferId)\n {\n \tbool valid = frame % kStatPerNumFrames == 0;\n+\tSharedMemObject<SwIspStats> &stats = sharedStats_->at(statsBufferId);\n \n \tif (valid) {\n-\t\tsharedStats_->sum_ = RGB<uint64_t>({ 0, 0, 0 });\n-\t\tsharedStats_->yHistogram.fill(0);\n+\t\tstats->sum_ = RGB<uint64_t>({ 0, 0, 0 });\n+\t\tstats->yHistogram.fill(0);\n \t\tfor (const auto &s : stats_) {\n-\t\t\tsharedStats_->sum_ += s.sum_;\n+\t\t\tstats->sum_ += s.sum_;\n \t\t\tfor (unsigned int j = 0; j < SwIspStats::kYHistogramSize; j++)\n-\t\t\t\tsharedStats_->yHistogram[j] += s.yHistogram[j];\n+\t\t\t\tstats->yHistogram[j] += s.yHistogram[j];\n \t\t}\n \n-\t\tsharedStats_->sum_ >>= sumShift_;\n+\t\tstats->sum_ >>= sumShift_;\n \t}\n \n-\tsharedStats_->valid = valid;\n+\tstats->valid = valid;\n \tstatsReady.emit(frame, statsBufferId);\n }\n \n", "prefixes": [ "RFC", "v3", "14/17" ] }