Show a patch.

GET /api/patches/26828/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 26828,
    "url": "https://patchwork.libcamera.org/api/patches/26828/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/26828/",
    "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-8-mzamazal@redhat.com>",
    "date": "2026-06-04T09:50:49",
    "name": "[RFC,v3,05/17] libcamera: software_isp: Introduce arguments for parameters buffers",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "1b8f6c755d5180b45e65c4a18ae5ce63c856746b",
    "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/26828/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/26828/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/26828/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 47A1BC328C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu,  4 Jun 2026 09:51:36 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id F1A3363403;\n\tThu,  4 Jun 2026 11:51:35 +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 62C5563400\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  4 Jun 2026 11:51:34 +0200 (CEST)",
            "from mx-prod-mc-01.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-550-_Bb0TlE2O06WCqjVr1xvoA-1;\n\tThu, 04 Jun 2026 05:51:31 -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-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix)\n\twith ESMTPS id 40FB3195609F; Thu,  4 Jun 2026 09:51:30 +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 460DE30001A1; Thu,  4 Jun 2026 09:51:27 +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=\"G+mS1vZR\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1780566693;\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=b5bFoNg+hoimeYs6xplOIwMunOFAxEdn+UAcs2um9uM=;\n\tb=G+mS1vZReSwcd9B4APeAEFZ5nWbxBzzidH316pw8nIGv2pxN8XPb6c2Mlg88jk9Ugo4VPY\n\te/0GwvmCUCg8OIfwUoDu6lnCJYim9/4tCfaSRSrD18Wsr1poJPrE1Mk1/UbgYK64zbQsE0\n\tNMSoc0ZI+I97k+DMbd+DyhSXvrO/Kdk=",
        "X-MC-Unique": "_Bb0TlE2O06WCqjVr1xvoA-1",
        "X-Mimecast-MFC-AGG-ID": "_Bb0TlE2O06WCqjVr1xvoA_1780566690",
        "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 05/17] libcamera: software_isp: Introduce arguments\n\tfor parameters buffers",
        "Date": "Thu,  4 Jun 2026 11:50:49 +0200",
        "Message-ID": "<20260604095105.68798-8-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": "sy2U9bcqv-i2Zv9525rqOxnHsKOc-tO69mKaM3GorUQ_1780566690",
        "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": "Processing parameters in software ISP are currently passed by value.\nThis is unlike hardware pipelines, which use a ring of buffers for the\npurpose and pass references to the buffers currently selected from the\nring rather than passing the whole parameters buffers.\n\nThis is a preparatory patch to introduce a similar mechanism in software\nISP, in order to resolve TODO #5.  It adds a new argument paramsBufferId\nfor the future parameters buffer ids passed to the calls.  The buffer\nids must be passed to the following groups of methods:\n\n- IPASoftSimple::prepare, in order to create the parameters in the given\n  buffer for the corresponding frame processing.\n\n- SoftwareIsp::saveIspParams, in order to signal that the parameters are\n  set by the IPA.\n\n- Debayer::process, in order to get the buffer with the processing\n  parameters.\n\n- SoftwareIsp::paramsBufferReady, in order to signal that the selected\n  parameters buffer from the ring is no longer needed for the given\n  frame and can be reused.  This is a newly introduced signal.\n\nThe type of the buffer id parameter is set to uint32_t because:\n\n- It can be used in mojom.\n- It is consistent with the similar types in the hardware pipelines.\n- It covers file descriptor number range, which will be used as buffer\n  ids (more on this in followup patches).\n\nThis patch doesn't do more than adding the arguments, to keep the patch\nsimple.  The buffer handling will be implemented in the followup\npatches.\n\nSigned-off-by: Milan Zamazal <mzamazal@redhat.com>\n---\n .../libcamera/internal/software_isp/software_isp.h |  3 ++-\n include/libcamera/ipa/soft.mojom                   |  4 ++--\n src/ipa/simple/soft_simple.cpp                     |  8 +++++---\n src/libcamera/software_isp/debayer.cpp             |  8 +++++++-\n src/libcamera/software_isp/debayer.h               |  6 +++++-\n src/libcamera/software_isp/debayer_cpu.cpp         |  6 +++++-\n src/libcamera/software_isp/debayer_cpu.h           |  4 +++-\n src/libcamera/software_isp/debayer_egl.cpp         |  6 +++++-\n src/libcamera/software_isp/debayer_egl.h           |  4 +++-\n src/libcamera/software_isp/software_isp.cpp        | 14 +++++++++++---\n 10 files changed, 48 insertions(+), 15 deletions(-)",
    "diff": "diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h\nindex 86cb8f8de..85c9059e2 100644\n--- a/include/libcamera/internal/software_isp/software_isp.h\n+++ b/include/libcamera/internal/software_isp/software_isp.h\n@@ -88,7 +88,8 @@ public:\n \tSignal<const ControlList &> setSensorControls;\n \n private:\n-\tvoid saveIspParams();\n+\tvoid saveIspParams(const uint32_t paramsBufferId);\n+\tvoid paramsBufferReady(const uint32_t paramsBufferId);\n \tvoid setSensorCtrls(const ControlList &sensorControls);\n \tvoid statsReady(uint32_t frame, uint32_t bufferId);\n \tvoid inputReady(FrameBuffer *input);\ndiff --git a/include/libcamera/ipa/soft.mojom b/include/libcamera/ipa/soft.mojom\nindex e75b03a3d..18789d5de 100644\n--- a/include/libcamera/ipa/soft.mojom\n+++ b/include/libcamera/ipa/soft.mojom\n@@ -25,7 +25,7 @@ interface IPASoftInterface {\n \t\t=> (int32 ret);\n \n \t[async] queueRequest(uint32 frame, libcamera.ControlList sensorControls);\n-\t[async] computeParams(uint32 frame);\n+\t[async] computeParams(uint32 frame, uint32 paramsBufferId);\n \t[async] processStats(uint32 frame,\n \t\t\t     uint32 bufferId,\n \t\t\t     libcamera.ControlList sensorControls);\n@@ -33,6 +33,6 @@ interface IPASoftInterface {\n \n interface IPASoftEventInterface {\n \tsetSensorControls(libcamera.ControlList sensorControls);\n-\tparamsComputed();\n+\tparamsComputed(uint32 paramsBufferId);\n \tmetadataReady(uint32 frame, libcamera.ControlList metadata);\n };\ndiff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp\nindex cfc1389e4..69bfef302 100644\n--- a/src/ipa/simple/soft_simple.cpp\n+++ b/src/ipa/simple/soft_simple.cpp\n@@ -64,7 +64,8 @@ public:\n \tvoid stop() override;\n \n \tvoid queueRequest(const uint32_t frame, const ControlList &controls) override;\n-\tvoid computeParams(const uint32_t frame) override;\n+\tvoid computeParams(const uint32_t frame,\n+\t\t\t   const uint32_t paramsBufferId) override;\n \tvoid processStats(const uint32_t frame, const uint32_t bufferId,\n \t\t\t  const ControlList &sensorControls) override;\n \n@@ -283,7 +284,8 @@ void IPASoftSimple::queueRequest(const uint32_t frame, const ControlList &contro\n \t\talgo->queueRequest(context_, frame, frameContext, controls);\n }\n \n-void IPASoftSimple::computeParams(const uint32_t frame)\n+void IPASoftSimple::computeParams(const uint32_t frame,\n+\t\t\t\t  const uint32_t paramsBufferId)\n {\n \tcontext_.activeState.combinedMatrix = Matrix<float, 3, 3>::identity();\n \n@@ -292,7 +294,7 @@ void IPASoftSimple::computeParams(const uint32_t frame)\n \t\talgo->prepare(context_, frame, frameContext, params_);\n \tparams_->combinedMatrix = context_.activeState.combinedMatrix;\n \n-\tparamsComputed.emit();\n+\tparamsComputed.emit(paramsBufferId);\n }\n \n void IPASoftSimple::processStats(const uint32_t frame,\ndiff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp\nindex 2d7abfb83..7b1be52b2 100644\n--- a/src/libcamera/software_isp/debayer.cpp\n+++ b/src/libcamera/software_isp/debayer.cpp\n@@ -104,9 +104,10 @@ Debayer::~Debayer()\n  */\n \n /**\n- * \\fn void Debayer::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, DebayerParams params)\n+ * \\fn void Debayer::process(uint32_t frame, const uint32_t paramsBufferId, FrameBuffer *input, FrameBuffer *output, DebayerParams params)\n  * \\brief Process the bayer data into the requested format\n  * \\param[in] frame The frame number\n+ * \\param[in] paramsBufferId The id of the params buffer in use\n  * \\param[in] input The input buffer\n  * \\param[in] output The output buffer\n  * \\param[in] params The parameters to be used in debayering\n@@ -142,6 +143,11 @@ Debayer::~Debayer()\n  * current stream.\n  */\n \n+/**\n+ * \\var Debayer::paramsBufferReady\n+ * \\brief Signals when the processing params are no longer needed\n+ */\n+\n /**\n  * \\var Signal<FrameBuffer *> Debayer::inputBufferReady\n  * \\brief Signals when the input buffer is ready\ndiff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h\nindex a2a17ec18..9a97851b7 100644\n--- a/src/libcamera/software_isp/debayer.h\n+++ b/src/libcamera/software_isp/debayer.h\n@@ -47,7 +47,10 @@ public:\n \tvirtual std::tuple<unsigned int, unsigned int>\n \tstrideAndFrameSize(const PixelFormat &outputFormat, const Size &size) = 0;\n \n-\tvirtual void process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams &params) = 0;\n+\tvirtual void process(uint32_t frame,\n+\t\t\t     const uint32_t paramsBufferId,\n+\t\t\t     FrameBuffer *input, FrameBuffer *output,\n+\t\t\t     const DebayerParams &params) = 0;\n \tvirtual int start() { return 0; }\n \tvirtual void stop() {}\n \n@@ -59,6 +62,7 @@ public:\n \n \tSignal<FrameBuffer *> inputBufferReady;\n \tSignal<FrameBuffer *> outputBufferReady;\n+\tSignal<uint32_t> paramsBufferReady;\n \n \tstruct DebayerInputConfig {\n \t\tSize patternSize;\ndiff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp\nindex 1f9b24da0..51b58fce5 100644\n--- a/src/libcamera/software_isp/debayer_cpu.cpp\n+++ b/src/libcamera/software_isp/debayer_cpu.cpp\n@@ -971,7 +971,9 @@ void DebayerCpu::updateLookupTables(const DebayerParams &params)\n \tparams_ = params;\n }\n \n-void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams &params)\n+void DebayerCpu::process(uint32_t frame, const uint32_t paramsBufferId,\n+\t\t\t FrameBuffer *input, FrameBuffer *output,\n+\t\t\t const DebayerParams &params)\n {\n \tbench_.startFrame();\n \n@@ -981,6 +983,8 @@ void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output\n \n \tupdateLookupTables(params);\n \n+\tparamsBufferReady.emit(paramsBufferId);\n+\n \t/* Copy metadata from the input buffer */\n \tFrameMetadata &metadata = output->_d()->metadata();\n \tmetadata.status = input->metadata().status;\ndiff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h\nindex 68da95083..1b4e8548a 100644\n--- a/src/libcamera/software_isp/debayer_cpu.h\n+++ b/src/libcamera/software_isp/debayer_cpu.h\n@@ -42,7 +42,9 @@ public:\n \tstd::vector<PixelFormat> formats(PixelFormat input) override;\n \tstd::tuple<unsigned int, unsigned int>\n \tstrideAndFrameSize(const PixelFormat &outputFormat, const Size &size) override;\n-\tvoid process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams &params) override;\n+\tvoid process(uint32_t frame, const uint32_t paramsBufferId,\n+\t\t     FrameBuffer *input, FrameBuffer *output,\n+\t\t     const DebayerParams &params) override;\n \tint start() override;\n \tvoid stop() override;\n \tSizeRange sizes(PixelFormat inputFormat, const Size &inputSize) override;\ndiff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp\nindex 99825d49e..60fd5463f 100644\n--- a/src/libcamera/software_isp/debayer_egl.cpp\n+++ b/src/libcamera/software_isp/debayer_egl.cpp\n@@ -546,7 +546,9 @@ int DebayerEGL::debayerGPU(FrameBuffer *input, FrameBuffer *output, const Debaye\n \treturn 0;\n }\n \n-void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams &params)\n+void DebayerEGL::process(uint32_t frame, const uint32_t paramsBufferId,\n+\t\t\t FrameBuffer *input, FrameBuffer *output,\n+\t\t\t const DebayerParams &params)\n {\n \tbench_.startFrame();\n \n@@ -563,6 +565,7 @@ void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output\n \t\tLOG(Debayer, Error) << \"debayerGPU failed\";\n \t\tgoto error;\n \t}\n+\tparamsBufferReady.emit(paramsBufferId);\n \n \tmetadata.planes()[0].bytesused = output->planes()[0].length;\n \n@@ -593,6 +596,7 @@ void DebayerEGL::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output\n \treturn;\n \n error:\n+\tparamsBufferReady.emit(paramsBufferId);\n \tbench_.finishFrame();\n \tmetadata.status = FrameMetadata::FrameError;\n \treturn;\ndiff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h\nindex 875e7cfc5..a3a4448e7 100644\n--- a/src/libcamera/software_isp/debayer_egl.h\n+++ b/src/libcamera/software_isp/debayer_egl.h\n@@ -51,7 +51,9 @@ public:\n \tstd::vector<PixelFormat> formats(PixelFormat input) override;\n \tstd::tuple<unsigned int, unsigned int> strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) override;\n \n-\tvoid process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams &params) override;\n+\tvoid process(uint32_t frame, const uint32_t paramsBufferId,\n+\t\t     FrameBuffer *input, FrameBuffer *output,\n+\t\t     const DebayerParams &params) override;\n \tint start() override;\n \tvoid stop() override;\n \ndiff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp\nindex f17f1ca1f..a1200e924 100644\n--- a/src/libcamera/software_isp/software_isp.cpp\n+++ b/src/libcamera/software_isp/software_isp.cpp\n@@ -128,6 +128,7 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor,\n \n \tdebayer_->inputBufferReady.connect(this, &SoftwareIsp::inputReady);\n \tdebayer_->outputBufferReady.connect(this, &SoftwareIsp::outputReady);\n+\tdebayer_->paramsBufferReady.connect(this, &SoftwareIsp::paramsBufferReady);\n \n \tipa_ = pipe->createIPA<ipa::soft::IPAProxySoft>(0, 0);\n \tif (!ipa_) {\n@@ -408,16 +409,23 @@ void SoftwareIsp::stop()\n  */\n void SoftwareIsp::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output)\n {\n-\tipa_->computeParams(frame);\n+\t/* \\todo Provide a real value */\n+\tconstexpr uint32_t paramsBufferId = 0;\n+\tipa_->computeParams(frame, paramsBufferId);\n \tdebayer_->invokeMethod(&Debayer::process,\n-\t\t\t       ConnectionTypeQueued, frame, input, output, debayerParams_);\n+\t\t\t       ConnectionTypeQueued, frame, paramsBufferId,\n+\t\t\t       input, output, debayerParams_);\n }\n \n-void SoftwareIsp::saveIspParams()\n+void SoftwareIsp::saveIspParams([[maybe_unused]] const uint32_t paramsBufferId)\n {\n \tdebayerParams_ = *sharedParams_;\n }\n \n+void SoftwareIsp::paramsBufferReady([[maybe_unused]] const uint32_t paramsBufferId)\n+{\n+}\n+\n void SoftwareIsp::setSensorCtrls(const ControlList &sensorControls)\n {\n \tsetSensorControls.emit(sensorControls);\n",
    "prefixes": [
        "RFC",
        "v3",
        "05/17"
    ]
}