Patch Detail
Show a patch.
GET /api/1.1/patches/26859/?format=api
{ "id": 26859, "url": "https://patchwork.libcamera.org/api/1.1/patches/26859/?format=api", "web_url": "https://patchwork.libcamera.org/patch/26859/", "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": "<20260608150349.134371-17-mzamazal@redhat.com>", "date": "2026-06-08T15:03:45", "name": "[RFC,v4,16/17] libcamera: software_isp: Share statistics buffers with IPA", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "6c643af0e92b6842911cd4a25fde299b11f2ab9c", "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/26859/mbox/", "series": [ { "id": 5982, "url": "https://patchwork.libcamera.org/api/1.1/series/5982/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5982", "date": "2026-06-08T15:03:29", "name": "Software ISP: Share params and stats buffers", "version": 4, "mbox": "https://patchwork.libcamera.org/series/5982/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/26859/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/26859/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 482BAC328C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 8 Jun 2026 15:04:43 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id F2DF761F37;\n\tMon, 8 Jun 2026 17:04:42 +0200 (CEST)", "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 EE88561F0F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 8 Jun 2026 17:04:40 +0200 (CEST)", "from mx-prod-mc-08.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-492-Mk2iwlmsOQuiku_BvfqtYA-1;\n\tMon, 08 Jun 2026 11:04:37 -0400", "from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com\n\t(mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com\n\t[10.30.177.111])\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-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix)\n\twith ESMTPS id CCF93180075E; Mon, 8 Jun 2026 15:04:36 +0000 (UTC)", "from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.48.51])\n\tby mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix)\n\twith ESMTP id BB6DA1800351; Mon, 8 Jun 2026 15:04:34 +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=\"Tx5WEudA\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1780931079;\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=7SsbtO8egQymtUpgnE/ezOZ9vnLT1vLbyMEOW3CMceQ=;\n\tb=Tx5WEudAY6x+VnPQIT2W15uV03Kc3H6dVKBJUffnLTMDrSfqbKmmMg60Hxg6xpLFgz4Un7\n\ttJ7oFZp8UYXj3Hzwgv9WNtWSbQV1IjXTmGNfF9np7Lab1VDN3tMTNDqBXF7GdJveoIObgH\n\tImJ3Up4znJtwIyvcT7H1AG49Ywf0HiU=", "X-MC-Unique": "Mk2iwlmsOQuiku_BvfqtYA-1", "X-Mimecast-MFC-AGG-ID": "Mk2iwlmsOQuiku_BvfqtYA_1780931076", "From": "Milan Zamazal <mzamazal@redhat.com>", "To": "libcamera-devel@lists.libcamera.org", "Cc": "Milan Zamazal <mzamazal@redhat.com>, Kieran Bingham\n\t<kieran.bingham@ideasonboard.com>, =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?=\n\t<barnabas.pocze@ideasonboard.com>, johannes.goede@oss.qualcomm.com", "Subject": "[RFC PATCH v4 16/17] libcamera: software_isp: Share statistics\n\tbuffers with IPA", "Date": "Mon, 8 Jun 2026 17:03:45 +0200", "Message-ID": "<20260608150349.134371-17-mzamazal@redhat.com>", "In-Reply-To": "<20260608150349.134371-1-mzamazal@redhat.com>", "References": "<20260608150349.134371-1-mzamazal@redhat.com>", "MIME-Version": "1.0", "X-Scanned-By": "MIMEDefang 3.4.1 on 10.30.177.111", "X-Mimecast-Spam-Score": "0", "X-Mimecast-MFC-PROC-ID": "K716Wd0B4-gzt9tZ4t-d1A1ptZXVGYhfhaqSkph4z9s_1780931076", "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": "The last step to complete statistics buffer sharing is to pass all the\nallocated statistics buffers to the IPA and refer to them using their ids.\nThis allows to remove the buffer copying in SwStatsCpu::finishFrame.\n\nWe can also remove now the methods that served for handling the former\nsingle buffer shared between debayering and IPA.\n\nSigned-off-by: Milan Zamazal <mzamazal@redhat.com>\n---\n .../internal/software_isp/swstats_cpu.h | 5 +--\n include/libcamera/ipa/soft.mojom | 2 +-\n src/ipa/simple/soft_simple.cpp | 42 +++++++++----------\n src/libcamera/software_isp/debayer.cpp | 10 -----\n src/libcamera/software_isp/debayer.h | 2 -\n src/libcamera/software_isp/debayer_cpu.h | 1 -\n src/libcamera/software_isp/debayer_egl.h | 2 -\n src/libcamera/software_isp/software_isp.cpp | 2 +-\n src/libcamera/software_isp/swstats_cpu.cpp | 28 ++++---------\n 9 files changed, 31 insertions(+), 63 deletions(-)", "diff": "diff --git a/include/libcamera/internal/software_isp/swstats_cpu.h b/include/libcamera/internal/software_isp/swstats_cpu.h\nindex 7a66c9367..4ec13c4da 100644\n--- a/include/libcamera/internal/software_isp/swstats_cpu.h\n+++ b/include/libcamera/internal/software_isp/swstats_cpu.h\n@@ -12,6 +12,7 @@\n #pragma once\n \n #include <map>\n+#include <memory>\n #include <stdint.h>\n #include <vector>\n \n@@ -47,10 +48,6 @@ public:\n \t */\n \tstatic constexpr uint32_t kStatPerNumFrames = 4;\n \n-\tbool isValid() const { return sharedStats_->begin()->second.fd().isValid(); }\n-\n-\tconst SharedFD &getStatsFD() { return sharedStats_->begin()->second.fd(); }\n-\n \tconst Size &patternSize() { return patternSize_; }\n \n \tint configure(const StreamConfiguration &inputCfg, unsigned int statsBufferCount = 1);\ndiff --git a/include/libcamera/ipa/soft.mojom b/include/libcamera/ipa/soft.mojom\nindex c2c5fe382..a3739de00 100644\n--- a/include/libcamera/ipa/soft.mojom\n+++ b/include/libcamera/ipa/soft.mojom\n@@ -14,7 +14,7 @@ struct IPAConfigInfo {\n \n interface IPASoftInterface {\n \tinit(libcamera.IPASettings settings,\n-\t libcamera.SharedFD fdStats,\n+\t map<uint32, libcamera.SharedFD> fdStats,\n \t map<uint32, libcamera.SharedFD> fdParams,\n \t libcamera.IPACameraSensorInfo sensorInfo,\n \t libcamera.ControlInfoMap sensorControls)\ndiff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp\nindex ded75a970..ff585b75e 100644\n--- a/src/ipa/simple/soft_simple.cpp\n+++ b/src/ipa/simple/soft_simple.cpp\n@@ -52,7 +52,7 @@ public:\n \t~IPASoftSimple();\n \n \tint init(const IPASettings &settings,\n-\t\t const SharedFD &fdStats,\n+\t\t const std::map<uint32_t, SharedFD> &fdStats,\n \t\t const std::map<uint32_t, SharedFD> &fdParams,\n \t\t const IPACameraSensorInfo &sensorInfo,\n \t\t const ControlInfoMap &sensorControls,\n@@ -76,7 +76,7 @@ private:\n \tvoid updateExposure(double exposureMSV);\n \n \tstd::map<unsigned int, DebayerParams *> paramsBuffers_;\n-\tSwIspStats *stats_;\n+\tstd::map<unsigned int, SwIspStats *> statsBuffers_;\n \tstd::unique_ptr<CameraSensorHelper> camHelper_;\n \tControlInfoMap sensorInfoMap_;\n \n@@ -86,14 +86,14 @@ private:\n \n IPASoftSimple::~IPASoftSimple()\n {\n-\tif (stats_)\n-\t\tmunmap(stats_, sizeof(SwIspStats));\n+\tfor (auto &item : statsBuffers_)\n+\t\tmunmap(item.second, sizeof(SwIspStats));\n \tfor (auto &item : paramsBuffers_)\n \t\tmunmap(item.second, sizeof(DebayerParams));\n }\n \n int IPASoftSimple::init(const IPASettings &settings,\n-\t\t\tconst SharedFD &fdStats,\n+\t\t\tconst std::map<uint32_t, SharedFD> &fdStats,\n \t\t\tconst std::map<uint32_t, SharedFD> &fdParams,\n \t\t\tconst IPACameraSensorInfo &sensorInfo,\n \t\t\tconst ControlInfoMap &sensorControls,\n@@ -137,11 +137,20 @@ int IPASoftSimple::init(const IPASettings &settings,\n \t\treturn ret;\n \n \t*ccmEnabled = context_.ccmEnabled;\n-\tstats_ = nullptr;\n+\tfor (auto &[bufferId, sharedFd] : fdStats) {\n+\t\tif (!sharedFd.isValid()) {\n+\t\t\tLOG(IPASoft, Error) << \"Invalid Statistics handle\";\n+\t\t\treturn -ENODEV;\n+\t\t}\n+\n+\t\tvoid *mem = mmap(nullptr, sizeof(SwIspStats), PROT_READ,\n+\t\t\t\t MAP_SHARED, sharedFd.get(), 0);\n+\t\tif (mem == MAP_FAILED) {\n+\t\t\tLOG(IPASoft, Error) << \"Unable to map Statistics\";\n+\t\t\treturn -errno;\n+\t\t}\n \n-\tif (!fdStats.isValid()) {\n-\t\tLOG(IPASoft, Error) << \"Invalid Statistics handle\";\n-\t\treturn -ENODEV;\n+\t\tstatsBuffers_[bufferId] = static_cast<SwIspStats *>(mem);\n \t}\n \n \tfor (auto &[bufferId, sharedFd] : fdParams) {\n@@ -166,17 +175,6 @@ int IPASoftSimple::init(const IPASettings &settings,\n \t\tparamsBuffers_[bufferId] = params;\n \t}\n \n-\t{\n-\t\tvoid *mem = mmap(nullptr, sizeof(SwIspStats), PROT_READ,\n-\t\t\t\t MAP_SHARED, fdStats.get(), 0);\n-\t\tif (mem == MAP_FAILED) {\n-\t\t\tLOG(IPASoft, Error) << \"Unable to map Statistics\";\n-\t\t\treturn -errno;\n-\t\t}\n-\n-\t\tstats_ = static_cast<SwIspStats *>(mem);\n-\t}\n-\n \tControlInfoMap::Map ctrlMap = context_.ctrlMap;\n \t*ipaControls = ControlInfoMap(std::move(ctrlMap), controls::controls);\n \n@@ -303,6 +301,8 @@ void IPASoftSimple::processStats(const uint32_t frame,\n {\n \tIPAFrameContext &frameContext = context_.frameContexts.get(frame);\n \n+\tconst SwIspStats *stats = statsBuffers_.at(statsBufferId);\n+\n \tframeContext.sensor.exposure =\n \t\tsensorControls.get(V4L2_CID_EXPOSURE).get<int32_t>();\n \tint32_t again = sensorControls.get(V4L2_CID_ANALOGUE_GAIN).get<int32_t>();\n@@ -310,7 +310,7 @@ void IPASoftSimple::processStats(const uint32_t frame,\n \n \tControlList metadata(controls::controls);\n \tfor (const auto &algo : algorithms())\n-\t\talgo->process(context_, frame, frameContext, stats_, metadata);\n+\t\talgo->process(context_, frame, frameContext, stats, metadata);\n \tmetadataReady.emit(frame, metadata);\n \tstatsProcessed.emit(statsBufferId);\n \ndiff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp\nindex 341930e5b..533311200 100644\n--- a/src/libcamera/software_isp/debayer.cpp\n+++ b/src/libcamera/software_isp/debayer.cpp\n@@ -138,16 +138,6 @@ Debayer::~Debayer()\n * \\return The valid size ranges or an empty range if there are none\n */\n \n-/**\n- * \\fn const SharedFD &Debayer::getStatsFD()\n- * \\brief Get the file descriptor for the statistics\n- *\n- * This file descriptor provides access to the output statistics buffer\n- * associated with the current debayering process.\n- *\n- * \\return The file descriptor pointing to the statistics data\n- */\n-\n /**\n * \\fn unsigned int Debayer::frameSize()\n * \\brief Get the output frame size\ndiff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h\nindex 259261b1a..b0a1ed151 100644\n--- a/src/libcamera/software_isp/debayer.h\n+++ b/src/libcamera/software_isp/debayer.h\n@@ -57,8 +57,6 @@ public:\n \n \tvirtual SizeRange sizes(PixelFormat inputFormat, const Size &inputSize) = 0;\n \n-\tvirtual const SharedFD &getStatsFD() = 0;\n-\n \tunsigned int frameSize() { return outputConfig_.frameSize; }\n \n \tSignal<FrameBuffer *> inputBufferReady;\ndiff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h\nindex 8f8b2d6b1..e018567f4 100644\n--- a/src/libcamera/software_isp/debayer_cpu.h\n+++ b/src/libcamera/software_isp/debayer_cpu.h\n@@ -53,7 +53,6 @@ public:\n \tint start() override;\n \tvoid stop() override;\n \tSizeRange sizes(PixelFormat inputFormat, const Size &inputSize) override;\n-\tconst SharedFD &getStatsFD() override { return stats_->getStatsFD(); }\n \n private:\n \tfriend class DebayerCpuThread;\ndiff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h\nindex 36c856c10..d7d1bc618 100644\n--- a/src/libcamera/software_isp/debayer_egl.h\n+++ b/src/libcamera/software_isp/debayer_egl.h\n@@ -61,8 +61,6 @@ public:\n \tint start() override;\n \tvoid stop() override;\n \n-\tconst SharedFD &getStatsFD() override { return stats_->getStatsFD(); }\n-\n \tSizeRange sizes(PixelFormat inputFormat, const Size &inputSize) override;\n \n private:\ndiff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp\nindex 2a019e6bc..020226585 100644\n--- a/src/libcamera/software_isp/software_isp.cpp\n+++ b/src/libcamera/software_isp/software_isp.cpp\n@@ -162,7 +162,7 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe,\n \t}\n \n \tret = ipa_->init(IPASettings{ ipaTuningFile, sensor->model() },\n-\t\t\t debayer_->getStatsFD(),\n+\t\t\t fdStats,\n \t\t\t fdParams,\n \t\t\t sensorInfo,\n \t\t\t sensor->controls(),\ndiff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp\nindex 15eca4769..2f490af51 100644\n--- a/src/libcamera/software_isp/swstats_cpu.cpp\n+++ b/src/libcamera/software_isp/swstats_cpu.cpp\n@@ -48,20 +48,6 @@ namespace libcamera {\n * exchange.\n */\n \n-/**\n- * \\fn bool SwStatsCpu::isValid() const\n- * \\brief Gets whether the statistics object is valid\n- *\n- * \\return True if it's valid, false otherwise\n- */\n-\n-/**\n- * \\fn const SharedFD &SwStatsCpu::getStatsFD()\n- * \\brief Get the file descriptor for the statistics\n- *\n- * \\return The file descriptor\n- */\n-\n /**\n * \\fn const Size &SwStatsCpu::patternSize()\n * \\brief Get the pattern size\n@@ -407,21 +393,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+\tSharedMemObject<SwIspStats> &shared = sharedStats_->at(statsBufferId);\n \n \tif (valid) {\n-\t\tstats->sum_ = RGB<uint64_t>({ 0, 0, 0 });\n-\t\tstats->yHistogram.fill(0);\n+\t\tshared->sum_ = RGB<uint64_t>({ 0, 0, 0 });\n+\t\tshared->yHistogram.fill(0);\n \t\tfor (const auto &s : stats_) {\n-\t\t\tstats->sum_ += s.sum_;\n+\t\t\tshared->sum_ += s.sum_;\n \t\t\tfor (unsigned int j = 0; j < SwIspStats::kYHistogramSize; j++)\n-\t\t\t\tstats->yHistogram[j] += s.yHistogram[j];\n+\t\t\t\tshared->yHistogram[j] += s.yHistogram[j];\n \t\t}\n \n-\t\tstats->sum_ >>= sumShift_;\n+\t\tshared->sum_ >>= sumShift_;\n \t}\n \n-\tstats->valid = valid;\n+\tshared->valid = valid;\n \tstatsReady.emit(frame, statsBufferId);\n }\n \n", "prefixes": [ "RFC", "v4", "16/17" ] }