Show a patch.

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

{
    "id": 19318,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/19318/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/19318/",
    "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": "<20231214121350.206015-4-hdegoede@redhat.com>",
    "date": "2023-12-14T12:13:41",
    "name": "[libcamera-devel,03/11] libcamera: software_isp: Add SwStats base class",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "895ee011c8b5e21487771cb7ddd4902d2b1e18fa",
    "submitter": {
        "id": 102,
        "url": "https://patchwork.libcamera.org/api/1.1/people/102/?format=api",
        "name": "Hans de Goede",
        "email": "hdegoede@redhat.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/19318/mbox/",
    "series": [
        {
            "id": 4117,
            "url": "https://patchwork.libcamera.org/api/1.1/series/4117/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4117",
            "date": "2023-12-14T12:13:38",
            "name": "libcamera: introduce Software ISP and Software IPA",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/4117/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/19318/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/19318/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 786A3C3292\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 14 Dec 2023 12:14:04 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 1C92062B4A;\n\tThu, 14 Dec 2023 13:14:04 +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 15CB161D97\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 14 Dec 2023 13:14:02 +0100 (CET)",
            "from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com\n\t[66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS\n\t(version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n\tus-mta-637-rWsdU6djMhW3DP-oEIcReQ-1; Thu, 14 Dec 2023 07:13:57 -0500",
            "from smtp.corp.redhat.com\n\t(int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3])\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 mimecast-mx02.redhat.com (Postfix) with ESMTPS id BBA538630C5;\n\tThu, 14 Dec 2023 12:13:56 +0000 (UTC)",
            "from shalem.redhat.com (unknown [10.39.194.72])\n\tby smtp.corp.redhat.com (Postfix) with ESMTP id 481B31121306;\n\tThu, 14 Dec 2023 12:13:55 +0000 (UTC)"
        ],
        "DKIM-Signature": [
            "v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1702556044;\n\tbh=HGoZ/2miZ0DnzfXtEPZ5obtr5/e2y45lUGzw4o3mEBk=;\n\th=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=ctTbEcH9gBzCIx1tNsHEigeVS5r93uJBoNQN8Dakyv7+6fhwmfq6ad6/3wze6ECBY\n\tw8Uk870ODinN6hA/jIEIK5js5r+2WQY+sWwuipBSXe5kYemdPPkEhhx+C5OzlmY1Nm\n\tBc17u1f/O4sJhzhgyC/tTXYTPNZ+ctlRAitJ7vIEPruYTvdfOmJeqvu6C8QsmjQssI\n\t3zCCJhAkM5fgjuP+r98W1KXYw9uyhfORD7xxcR78msePnNc1Y56L9RzgBzAgVvbYHk\n\tKIxZtkgc6IYt5lWffIAog4a6G98E01d+1ZtLXw7sWf0v0cYNTpQZuzD/wyulrpbpZ7\n\tuEny4TsftO0vg==",
            "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1702556041;\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=jb1x2doyAt9CwBVHIyjwa9LcY/h0jg/Vb4MkHLGfX6I=;\n\tb=h8LRWqQ1Wbt20VBMgvT4oopmd6ZyRs9/sNfIlMKVQPa4Cuwtn0MG96Yb/IZnrldzM/SnNf\n\tR5M9pmgWU2zKlTwrJ9FUiMmpj5eVJLT13HcOwlb9BF15jWaGtqsbAyFLVG+c+ER6+pUimZ\n\tYCh8DiLdU8D0yjfvmdEziDnx1+kNOSQ="
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=redhat.com\n\theader.i=@redhat.com header.b=\"h8LRWqQ1\"; \n\tdkim-atps=neutral",
        "X-MC-Unique": "rWsdU6djMhW3DP-oEIcReQ-1",
        "To": "libcamera-devel@lists.libcamera.org,\n\tAndrey Konovalov <andrey.konovalov@linaro.org>",
        "Date": "Thu, 14 Dec 2023 13:13:41 +0100",
        "Message-ID": "<20231214121350.206015-4-hdegoede@redhat.com>",
        "In-Reply-To": "<20231214121350.206015-1-hdegoede@redhat.com>",
        "References": "<20231214121350.206015-1-hdegoede@redhat.com>",
        "MIME-Version": "1.0",
        "X-Scanned-By": "MIMEDefang 3.4.1 on 10.11.54.3",
        "X-Mimecast-Spam-Score": "0",
        "X-Mimecast-Originator": "redhat.com",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain; charset=\"US-ASCII\"; x-default=true",
        "Subject": "[libcamera-devel] [PATCH 03/11] libcamera: software_isp: Add\n\tSwStats base class",
        "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>",
        "From": "Hans de Goede via libcamera-devel <libcamera-devel@lists.libcamera.org>",
        "Reply-To": "Hans de Goede <hdegoede@redhat.com>",
        "Cc": "Maxime Ripard <mripard@redhat.com>, g.martti@gmail.com,\n\tt.langendam@gmail.com, srinivas.kandagatla@linaro.org,\n\tBryan O'Donoghue <bryan.odonoghue@linaro.org>, admin@dennisbonke.com",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "Add a virtual base class for CPU based software statistics gathering\nimplementations.\n\nThe idea is for the implementations to offer a configure function +\nfunctions to gather statistics on a line by line basis. This allows\nCPU based software debayering to call into interlace debayering and\nstatistics gathering on a line by line bases while the input data\nis still hot in the cache.\n\nThis base class also allows the user of an implementation to specify\na window over which to gather statistics instead of processing the\nwhole frame; and it allows the implementation to choose to only\nprocess 1/2, 1/4th, etc. of the lines instead of processing all\nlines (in the window) by setting y_skip_mask_ from configure().\nSkipping columns is left up the line-processing functions provided\nby the implementation.\n\nThe base class also provides a processFrame() convenience function\nwhich collects statistics for an entire frame at once for use cases\nwhere CPU based software debayering is not used.\n\nCo-authored-by: Andrey Konovalov <andrey.konovalov@linaro.org>\nSigned-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>\nSigned-off-by: Hans de Goede <hdegoede@redhat.com>\n---\n .../internal/software_isp/meson.build         |   6 +\n .../internal/software_isp/swisp_stats.h       |  21 +++\n .../libcamera/internal/software_isp/swstats.h | 150 ++++++++++++++++++\n src/libcamera/software_isp/meson.build        |   5 +\n src/libcamera/software_isp/swstats.cpp        |  65 ++++++++\n 5 files changed, 247 insertions(+)\n create mode 100644 include/libcamera/internal/software_isp/meson.build\n create mode 100644 include/libcamera/internal/software_isp/swisp_stats.h\n create mode 100644 include/libcamera/internal/software_isp/swstats.h\n create mode 100644 src/libcamera/software_isp/meson.build\n create mode 100644 src/libcamera/software_isp/swstats.cpp",
    "diff": "diff --git a/include/libcamera/internal/software_isp/meson.build b/include/libcamera/internal/software_isp/meson.build\nnew file mode 100644\nindex 00000000..1c43acc4\n--- /dev/null\n+++ b/include/libcamera/internal/software_isp/meson.build\n@@ -0,0 +1,6 @@\n+# SPDX-License-Identifier: CC0-1.0\n+\n+libcamera_internal_headers += files([\n+    'swisp_stats.h',\n+    'swstats.h',\n+])\ndiff --git a/include/libcamera/internal/software_isp/swisp_stats.h b/include/libcamera/internal/software_isp/swisp_stats.h\nnew file mode 100644\nindex 00000000..f7afbaa4\n--- /dev/null\n+++ b/include/libcamera/internal/software_isp/swisp_stats.h\n@@ -0,0 +1,21 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2023, Linaro Ltd\n+ *\n+ * swisp_stats.h - Statistics data format used by the software ISP and software IPA\n+ */\n+\n+#pragma once\n+\n+namespace libcamera {\n+\n+struct SwIspStats {\n+\tunsigned long sumR_;\n+\tunsigned long sumB_;\n+\tunsigned long sumG_;\n+\n+\tfloat bright_ratio;\n+\tfloat too_bright_ratio;\n+};\n+\n+} /* namespace libcamera */\ndiff --git a/include/libcamera/internal/software_isp/swstats.h b/include/libcamera/internal/software_isp/swstats.h\nnew file mode 100644\nindex 00000000..0e7407f6\n--- /dev/null\n+++ b/include/libcamera/internal/software_isp/swstats.h\n@@ -0,0 +1,150 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2023, Linaro Ltd\n+ * Copyright (C) 2023, Red Hat Inc.\n+ *\n+ * Authors:\n+ * Hans de Goede <hdegoede@redhat.com> \n+ *\n+ * swstats.h - software statistics base class\n+ */\n+\n+#pragma once\n+\n+#include <stdint.h>\n+\n+#include <libcamera/base/log.h>\n+#include <libcamera/base/signal.h>\n+\n+#include <libcamera/geometry.h>\n+\n+namespace libcamera {\n+\n+class PixelFormat;\n+struct SharedFD;\n+struct StreamConfiguration;\n+\n+LOG_DECLARE_CATEGORY(SwStats)\n+\n+class SwStats\n+{\n+public:\n+\tvirtual ~SwStats() = 0;\n+\n+\tvirtual bool isValid() const = 0;\n+\n+\t/*\n+\t * Setup the SwStats object for the passed in input format.\n+\t * Return 0 on success, a negative errno value on failure\n+\t * (unsupported format or failed to create the SharedMemObject).\n+\t */\n+\tvirtual int configure(const StreamConfiguration &inputCfg) = 0;\n+\n+\t/* Get the FD for the SharedMemObject for the stats. */\n+\tvirtual const SharedFD &getStatsFD() = 0;\n+\n+protected:\n+\ttypedef void (SwStats::*statsProcessFn)(const uint8_t *src, unsigned int stride);\n+\ttypedef void (SwStats::*statsVoidFn)();\n+\n+\t/* Variables set by configure(), used every line */\n+\tstatsProcessFn stats0_;\n+\tstatsProcessFn stats2_;\n+\n+\tunsigned int bpp_;         /* Memory used per pixel, not precision */\n+\tunsigned int y_skip_mask_; /* Skip lines where this bitmask is set in y */\n+\n+\t/* Statistics windows, set by setWindow(), used every line */\n+\tRectangle window_;\n+\n+\t/* Variables set by configure(), used once per frame */\n+\tstatsVoidFn startFrame_;\n+\tstatsVoidFn finishFrame_;\n+\tSize patternSize_;\n+\tunsigned int x_shift_; /* Offset of 0/1 applied to window_.x for bayer variants */\n+\n+public:\n+\t/*\n+\t * For some input-formats, e.g. Bayer data, processing is done multiple lines\n+\t * and/or columns at a time. Get width and height at which the (bayer) pattern\n+\t * repeats. Window values are rounded down to a multiple of this and the height\n+\t * also indicates if processLine2() should be called or not.\n+\t * This may only be called after a successful configure() call.\n+\t */\n+\tconst Size &patternSize() { return patternSize_; }\n+\n+\t/*\n+\t * Specify window coordinates over which to gather statistics.\n+\t */\n+\tvoid setWindow(Rectangle window)\n+\t{\n+\t\twindow_ = window;\n+\n+\t\twindow_.x &= ~(patternSize_.width - 1);\n+\t\twindow_.x += x_shift_;\n+\t\twindow_.y &= ~(patternSize_.height - 1);\n+\n+\t\t/* width_ - x_shift_ to make sure the window fits */\n+\t\twindow_.width -= x_shift_;\n+\t\twindow_.width &= ~(patternSize_.width - 1);\n+\t\twindow_.height &= ~(patternSize_.height - 1);\n+\t}\n+\n+\t/*\n+\t * Reset state to start statistic gathering for a new frame.\n+\t * This may only be called after a successful setWindow() call.\n+\t */\n+\tvoid startFrame()\n+\t{\n+\t\t(this->*startFrame_)();\n+\t}\n+\n+\t/*\n+\t * Process line 0 of input formats with patternSize height == 1.\n+\t * Process line 0 + 1 of input formats with patternSize height >= 2.\n+\t * This may only be called after a successful setWindow() call.\n+\t */\n+\tvoid processLine0(unsigned int y, const uint8_t *src, unsigned int stride)\n+\t{\n+\t\tif ((y & y_skip_mask_) || y < (unsigned int)window_.y ||\n+\t\t    y >= (window_.y + window_.height))\n+\t\t\treturn;\n+\n+\t\t(this->*stats0_)(src + window_.x * bpp_ / 8, stride);\n+\t}\n+\n+\t/*\n+\t * Process lines 2 + 3 of input formats with patternSize height == 4.\n+\t * This may only be called after a successful setWindow() call.\n+\t */\n+\tvoid processLine2(unsigned int y, const uint8_t *src, unsigned int stride)\n+\t{\n+\t\tif ((y & y_skip_mask_) || y < (unsigned int)window_.y ||\n+\t\t    y >= (window_.y + window_.height))\n+\t\t\treturn;\n+\n+\t\t(this->*stats2_)(src + window_.x * bpp_ / 8, stride);\n+\t}\n+\n+\t/*\n+\t * Finish statistics calculation for current frame and\n+\t * store the results in the SharedMemObject.\n+\t * This may only be called after a successful setWindow() call.\n+\t */\n+\tvoid finishFrame()\n+\t{\n+\t\t(this->*finishFrame_)();\n+\t}\n+\n+\t/*\n+\t * Process a whole frame at once, replacing manually calling\n+\t * startFrame() + processLine0() + finishFrame().\n+\t * This may only be called after a successful setWindow() call.\n+\t */\n+\tvoid processFrame(const uint8_t *src, unsigned int stride);\n+\n+\t/* The int parameter isn't actually used */\n+\tSignal<int> statsReady;\n+};\n+\n+} /* namespace libcamera */\ndiff --git a/src/libcamera/software_isp/meson.build b/src/libcamera/software_isp/meson.build\nnew file mode 100644\nindex 00000000..9359075d\n--- /dev/null\n+++ b/src/libcamera/software_isp/meson.build\n@@ -0,0 +1,5 @@\n+# SPDX-License-Identifier: CC0-1.0\n+\n+libcamera_sources += files([\n+\t'swstats.cpp',\n+])\ndiff --git a/src/libcamera/software_isp/swstats.cpp b/src/libcamera/software_isp/swstats.cpp\nnew file mode 100644\nindex 00000000..9a5e1a10\n--- /dev/null\n+++ b/src/libcamera/software_isp/swstats.cpp\n@@ -0,0 +1,65 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2023, Linaro Ltd\n+ * Copyright (C) 2023, Red Hat Inc.\n+ *\n+ * Authors:\n+ * Hans de Goede <hdegoede@redhat.com> \n+ *\n+ * swstats.cpp - software statistics base class\n+ */\n+\n+#include \"libcamera/internal/software_isp/swstats.h\"\n+\n+namespace libcamera {\n+\n+LOG_DEFINE_CATEGORY(SwStats)\n+\n+void SwStats::processFrame(const uint8_t *src, unsigned int stride)\n+{\n+\tunsigned int y_end = window_.y + window_.height;\n+\n+\tstartFrame();\n+\n+\t/* Adjust src to point to starting corner of the statistics window */\n+\tsrc += window_.y * stride;\n+\tsrc += window_.x * bpp_ / 8;\n+\n+\tswitch (patternSize_.height) {\n+\tcase 1:\n+\t\tfor (unsigned int y = window_.y ; y < y_end; y++) {\n+\t\t\tif (!(y & y_skip_mask_))\n+\t\t\t\t(this->*stats0_)(src, stride);\n+\t\t\tsrc += stride;\n+\t\t}\n+\t\tbreak;\n+\tcase 2:\n+\t\tfor (unsigned int y = window_.y ; y < y_end; y += 2) {\n+\t\t\tif (!(y & y_skip_mask_))\n+\t\t\t\t(this->*stats0_)(src, stride);\n+\t\t\tsrc += 2 * stride;\n+\t\t}\n+\t\tbreak;\n+\tcase 4:\n+\t\tfor (unsigned int y = window_.y ; y < y_end; y += 4) {\n+\t\t\tif (y & y_skip_mask_) {\n+\t\t\t\tsrc += 4 * stride;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\n+\t\t\t(this->*stats0_)(src, stride);\n+\t\t\tsrc += 2 * stride;\n+\t\t\t(this->*stats2_)(src, stride);\n+\t\t\tsrc += 2 * stride;\n+\t\t}\n+\t\tbreak;\n+\t}\n+\n+\tfinishFrame();\n+}\n+\n+SwStats::~SwStats()\n+{\n+}\n+\n+} /* namespace libcamera */\n",
    "prefixes": [
        "libcamera-devel",
        "03/11"
    ]
}