Show a patch.

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

{
    "id": 23726,
    "url": "https://patchwork.libcamera.org/api/patches/23726/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/23726/",
    "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": "<20250702131032.47654-11-mzamazal@redhat.com>",
    "date": "2025-07-02T13:10:29",
    "name": "[v12,10/12] libcamera: software_isp: Make measurement configurable",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "ef5839a44c56c5dc3c1f5638014149a70c7dce53",
    "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/23726/mbox/",
    "series": [
        {
            "id": 5265,
            "url": "https://patchwork.libcamera.org/api/series/5265/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5265",
            "date": "2025-07-02T13:10:19",
            "name": "Add global configuration file",
            "version": 12,
            "mbox": "https://patchwork.libcamera.org/series/5265/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/23726/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/23726/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 CDFDDC3237\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed,  2 Jul 2025 13:11:11 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 50BD268E5A;\n\tWed,  2 Jul 2025 15:11:11 +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 5C35568E4B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  2 Jul 2025 15:11:08 +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-111-JCtSowMePTqTBzDPUtBimA-1;\n\tWed, 02 Jul 2025 09:11:04 -0400",
            "from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com\n\t(mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com\n\t[10.30.177.40])\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 56BD118002E4; Wed,  2 Jul 2025 13:11:03 +0000 (UTC)",
            "from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.33.1])\n\tby mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix)\n\twith ESMTP id 88A7A19560AB; Wed,  2 Jul 2025 13:11:01 +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=\"VWBeIfbp\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1751461867;\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=M7Zyon08aXa4SGaMso9ofm17pC2HtXE+VNiamTdOlac=;\n\tb=VWBeIfbpIoL8yGv8WKnR7x4zVK/U6eA4aoHIYh+dapi/WZAjINt8YIJYP229vej7fHPQLt\n\tZKyyYU0iMKG06FQBWf+PSt7fSpNUsY02vSLEKbtaRw8AaNgzTT5b0XQjQFasKhSDTy60SA\n\tvP87xnkHYll1iRv1TjvHbnmOeJfDrW0=",
        "X-MC-Unique": "JCtSowMePTqTBzDPUtBimA-1",
        "X-Mimecast-MFC-AGG-ID": "JCtSowMePTqTBzDPUtBimA_1751461863",
        "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>, Laurent Pinchart\n\t<laurent.pinchart@ideasonboard.com>",
        "Subject": "[PATCH v12 10/12] libcamera: software_isp: Make measurement\n\tconfigurable",
        "Date": "Wed,  2 Jul 2025 15:10:29 +0200",
        "Message-ID": "<20250702131032.47654-11-mzamazal@redhat.com>",
        "In-Reply-To": "<20250702131032.47654-1-mzamazal@redhat.com>",
        "References": "<20250702131032.47654-1-mzamazal@redhat.com>",
        "MIME-Version": "1.0",
        "X-Scanned-By": "MIMEDefang 3.0 on 10.30.177.40",
        "X-Mimecast-Spam-Score": "0",
        "X-Mimecast-MFC-PROC-ID": "bUxLc333Ap85E68Xeb-soe6m0yzNlqcjnLR-75r9zlg_1751461863",
        "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": "Software ISP performs performance measurement on certain part of initial\nframes.  Let's make this range configurable.\n\nFor this purpose, this patch introduces new configuration options\npipelines.simple.measure.skip and pipelines.simple.measure.number.\nSetting the latter one to 0 disables the measurement.\n\nInstead of the last frame, the class member and its configuration\nspecify the number of frames to measure.  This is easier to use for\nusers and doesn't require to adjust two configuration parameters when\nthe number of the initially skipped frames is changed.\n\nThe patch also changes the names of the class members to make them more\naccurate.\n\nCompletes software ISP TODO #7.\n\nSigned-off-by: Milan Zamazal <mzamazal@redhat.com>\n---\n Documentation/runtime_configuration.rst    |  6 ++++++\n src/libcamera/software_isp/TODO            | 25 ----------------------\n src/libcamera/software_isp/debayer_cpu.cpp | 25 ++++++++++++++--------\n src/libcamera/software_isp/debayer_cpu.h   |  7 +++---\n 4 files changed, 25 insertions(+), 38 deletions(-)",
    "diff": "diff --git a/Documentation/runtime_configuration.rst b/Documentation/runtime_configuration.rst\nindex f4e86ae24..de74fa732 100644\n--- a/Documentation/runtime_configuration.rst\n+++ b/Documentation/runtime_configuration.rst\n@@ -52,6 +52,9 @@ file structure:\n           ...\n       simple:\n         copy_input_buffer: # true/false\n+        measure:\n+          skip: # non-negative integer, frames to skip initially\n+          number: # non-negative integer, frames to measure\n         supported_devices:\n         - driver: # driver name, e.g. `mxc-isi`\n           software_isp: # true/false\n@@ -87,6 +90,9 @@ Configuration file example\n             min_total_unicam_buffers: 2\n        simple:\n          copy_input_buffer: false\n+         measure:\n+           skip: 50\n+           number: 30\n          supported_devices:\n          - driver: mxc-isi\n            software_isp: true\ndiff --git a/src/libcamera/software_isp/TODO b/src/libcamera/software_isp/TODO\nindex 2c919f442..f19e15ae2 100644\n--- a/src/libcamera/software_isp/TODO\n+++ b/src/libcamera/software_isp/TODO\n@@ -71,31 +71,6 @@ per-frame buffers like we do for hardware ISPs.\n \n ---\n \n-7. Performance measurement configuration\n-\n-> void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams params)\n-> /* Measure before emitting signals */\n-> if (measuredFrames_ < DebayerCpu::kLastFrameToMeasure &&\n->     ++measuredFrames_ > DebayerCpu::kFramesToSkip) {\n-> \ttimespec frameEndTime = {};\n-> \tclock_gettime(CLOCK_MONOTONIC_RAW, &frameEndTime);\n-> \tframeProcessTime_ += timeDiff(frameEndTime, frameStartTime);\n-> \tif (measuredFrames_ == DebayerCpu::kLastFrameToMeasure) {\n-> \t\tconst unsigned int measuredFrames = DebayerCpu::kLastFrameToMeasure -\n-> \t\t\t\t\t\t    DebayerCpu::kFramesToSkip;\n-> \t\tLOG(Debayer, Info)\n-> \t\t\t<< \"Processed \" << measuredFrames\n-> \t\t\t<< \" frames in \" << frameProcessTime_ / 1000 << \"us, \"\n-> \t\t\t<< frameProcessTime_ / (1000 * measuredFrames)\n-> \t\t\t<< \" us/frame\";\n-> \t}\n-> }\n-\n-I wonder if there would be a way to control at runtime when/how to\n-perform those measurements. Maybe that's a bit overkill.\n-\n----\n-\n 8. DebayerCpu cleanups\n \n > >> class DebayerCpu : public Debayer, public Object\ndiff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp\nindex 704d4e487..d43687f75 100644\n--- a/src/libcamera/software_isp/debayer_cpu.cpp\n+++ b/src/libcamera/software_isp/debayer_cpu.cpp\n@@ -55,6 +55,13 @@ DebayerCpu::DebayerCpu(std::unique_ptr<SwStatsCpu> stats, const GlobalConfigurat\n \tenableInputMemcpy_ =\n \t\tconfiguration.option<bool>({ \"pipelines\", \"simple\", \"copy_input_buffer\" }).value_or(true);\n \n+\tskipBeforeMeasure_ = configuration.option<unsigned int>(\n+\t\t\t\t\t\t  { \"pipelines\", \"simple\", \"measure\", \"skip\" })\n+\t\t\t\t     .value_or(skipBeforeMeasure_);\n+\tframesToMeasure_ = configuration.option<unsigned int>(\n+\t\t\t\t\t\t{ \"pipelines\", \"simple\", \"measure\", \"number\" })\n+\t\t\t\t   .value_or(framesToMeasure_);\n+\n \t/* Initialize color lookup tables */\n \tfor (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) {\n \t\tred_[i] = green_[i] = blue_[i] = i;\n@@ -557,7 +564,7 @@ int DebayerCpu::configure(const StreamConfiguration &inputCfg,\n \t\t\tlineBuffers_[i].resize(lineBufferLength_);\n \t}\n \n-\tmeasuredFrames_ = 0;\n+\tencounteredFrames_ = 0;\n \tframeProcessTime_ = 0;\n \n \treturn 0;\n@@ -763,7 +770,10 @@ void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output\n {\n \ttimespec frameStartTime;\n \n-\tif (measuredFrames_ < DebayerCpu::kLastFrameToMeasure) {\n+\tbool measure = framesToMeasure_ > 0 &&\n+\t\t       encounteredFrames_ < skipBeforeMeasure_ + framesToMeasure_ &&\n+\t\t       ++encounteredFrames_ > skipBeforeMeasure_;\n+\tif (measure) {\n \t\tframeStartTime = {};\n \t\tclock_gettime(CLOCK_MONOTONIC_RAW, &frameStartTime);\n \t}\n@@ -820,18 +830,15 @@ void DebayerCpu::process(uint32_t frame, FrameBuffer *input, FrameBuffer *output\n \tdmaSyncers.clear();\n \n \t/* Measure before emitting signals */\n-\tif (measuredFrames_ < DebayerCpu::kLastFrameToMeasure &&\n-\t    ++measuredFrames_ > DebayerCpu::kFramesToSkip) {\n+\tif (measure) {\n \t\ttimespec frameEndTime = {};\n \t\tclock_gettime(CLOCK_MONOTONIC_RAW, &frameEndTime);\n \t\tframeProcessTime_ += timeDiff(frameEndTime, frameStartTime);\n-\t\tif (measuredFrames_ == DebayerCpu::kLastFrameToMeasure) {\n-\t\t\tconst unsigned int measuredFrames = DebayerCpu::kLastFrameToMeasure -\n-\t\t\t\t\t\t\t    DebayerCpu::kFramesToSkip;\n+\t\tif (encounteredFrames_ == skipBeforeMeasure_ + framesToMeasure_) {\n \t\t\tLOG(Debayer, Info)\n-\t\t\t\t<< \"Processed \" << measuredFrames\n+\t\t\t\t<< \"Processed \" << framesToMeasure_\n \t\t\t\t<< \" frames in \" << frameProcessTime_ / 1000 << \"us, \"\n-\t\t\t\t<< frameProcessTime_ / (1000 * measuredFrames)\n+\t\t\t\t<< frameProcessTime_ / (1000 * framesToMeasure_)\n \t\t\t\t<< \" us/frame\";\n \t\t}\n \t}\ndiff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h\nindex 2f35aa18b..9d343e464 100644\n--- a/src/libcamera/software_isp/debayer_cpu.h\n+++ b/src/libcamera/software_isp/debayer_cpu.h\n@@ -161,11 +161,10 @@ private:\n \tunsigned int xShift_; /* Offset of 0/1 applied to window_.x */\n \tbool enableInputMemcpy_;\n \tbool swapRedBlueGains_;\n-\tunsigned int measuredFrames_;\n+\tunsigned int encounteredFrames_;\n \tint64_t frameProcessTime_;\n-\t/* Skip 30 frames for things to stabilize then measure 30 frames */\n-\tstatic constexpr unsigned int kFramesToSkip = 30;\n-\tstatic constexpr unsigned int kLastFrameToMeasure = 60;\n+\tunsigned int skipBeforeMeasure_ = 30;\n+\tunsigned int framesToMeasure_ = 30;\n };\n \n } /* namespace libcamera */\n",
    "prefixes": [
        "v12",
        "10/12"
    ]
}