Show a patch.

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

{
    "id": 20141,
    "url": "https://patchwork.libcamera.org/api/patches/20141/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/20141/",
    "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": "<20240529194251.863689-2-paul.elder@ideasonboard.com>",
    "date": "2024-05-29T19:42:48",
    "name": "[v3,1/4] utils: libtuning: modules: Add skeletal AGC module",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "576bfdb64bb11555f4c6891da62de6e03d6d8b15",
    "submitter": {
        "id": 17,
        "url": "https://patchwork.libcamera.org/api/people/17/?format=api",
        "name": "Paul Elder",
        "email": "paul.elder@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/20141/mbox/",
    "series": [
        {
            "id": 4339,
            "url": "https://patchwork.libcamera.org/api/series/4339/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4339",
            "date": "2024-05-29T19:42:47",
            "name": "utils: tuning: Add AGC and CCM",
            "version": 3,
            "mbox": "https://patchwork.libcamera.org/series/4339/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/20141/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/20141/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 0DA3BBDE6B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 29 May 2024 19:44:05 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id B2B84634BE;\n\tWed, 29 May 2024 21:44:04 +0200 (CEST)",
            "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id F10B06347E\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 29 May 2024 21:44:02 +0200 (CEST)",
            "from neptunite.hamster-moth.ts.net\n\t(h175-177-049-156.catv02.itscom.jp [175.177.49.156])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 22120149B;\n\tWed, 29 May 2024 21:43:57 +0200 (CEST)"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"I+up1b5Q\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1717011839;\n\tbh=4XC+W3tewX7dBN09vSB6sEGjsvw6KXo6ZoiOSnBP3ZI=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=I+up1b5Q9hlfO0cwd8ZyOXi0aANJdQTWE8UScmvl7QnwOrTSmYuXT83qzJcQdEsbG\n\tATbSwJ+a+zg1KH/HyWXTGmW66YWHMSwfQ3Y8i0b8YxBm90WjyQRoRsOVXdWUv9uBCX\n\t8loWVR35odiVj3kJ0K5I1p5t3PBe6zlJp5H24ohA=",
        "From": "Paul Elder <paul.elder@ideasonboard.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Cc": "Paul Elder <paul.elder@ideasonboard.com>,\n\tStefan Klug <stefan.klug@ideasonboard.com>",
        "Subject": "[PATCH v3 1/4] utils: libtuning: modules: Add skeletal AGC module",
        "Date": "Thu, 30 May 2024 04:42:48 +0900",
        "Message-Id": "<20240529194251.863689-2-paul.elder@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.39.2",
        "In-Reply-To": "<20240529194251.863689-1-paul.elder@ideasonboard.com>",
        "References": "<20240529194251.863689-1-paul.elder@ideasonboard.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "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": "Add a skeletal AGC module just so that we can have some AGC tuning\nvalues that we can use to test during development of AGC in the IPAs. As\nrkisp1 is the main target, we only add support for rkisp1 for now.\n\nThe parameters are mostly copied from the hardcoded values in ctt,\nexcept for the metering modes.\n\nSigned-off-by: Paul Elder <paul.elder@ideasonboard.com>\nReviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>\n\n---\nChanges in v3:\n- remove unused compatible string\n- make gain start from 2 in the exposure modes\n\nChanges in v2:\n- remove unneccessary imports\n- add support for both v10 and v12\n---\n .../tuning/libtuning/modules/agc/__init__.py  |   6 +\n utils/tuning/libtuning/modules/agc/agc.py     |  21 ++++\n utils/tuning/libtuning/modules/agc/rkisp1.py  | 110 ++++++++++++++++++\n 3 files changed, 137 insertions(+)\n create mode 100644 utils/tuning/libtuning/modules/agc/__init__.py\n create mode 100644 utils/tuning/libtuning/modules/agc/agc.py\n create mode 100644 utils/tuning/libtuning/modules/agc/rkisp1.py",
    "diff": "diff --git a/utils/tuning/libtuning/modules/agc/__init__.py b/utils/tuning/libtuning/modules/agc/__init__.py\nnew file mode 100644\nindex 000000000..4db9ca371\n--- /dev/null\n+++ b/utils/tuning/libtuning/modules/agc/__init__.py\n@@ -0,0 +1,6 @@\n+# SPDX-License-Identifier: GPL-2.0-or-later\n+#\n+# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n+\n+from libtuning.modules.agc.agc import AGC\n+from libtuning.modules.agc.rkisp1 import AGCRkISP1\ndiff --git a/utils/tuning/libtuning/modules/agc/agc.py b/utils/tuning/libtuning/modules/agc/agc.py\nnew file mode 100644\nindex 000000000..9c8899bad\n--- /dev/null\n+++ b/utils/tuning/libtuning/modules/agc/agc.py\n@@ -0,0 +1,21 @@\n+# SPDX-License-Identifier: BSD-2-Clause\n+#\n+# Copyright (C) 2019, Raspberry Pi Ltd\n+# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n+\n+from ..module import Module\n+\n+import libtuning as lt\n+\n+\n+class AGC(Module):\n+    type = 'agc'\n+    hr_name = 'AGC (Base)'\n+    out_name = 'GenericAGC'\n+\n+    # \\todo Add sector shapes and stuff just like lsc\n+    def __init__(self, *,\n+                 debug: list):\n+        super().__init__()\n+\n+        self.debug = debug\ndiff --git a/utils/tuning/libtuning/modules/agc/rkisp1.py b/utils/tuning/libtuning/modules/agc/rkisp1.py\nnew file mode 100644\nindex 000000000..02feb10e0\n--- /dev/null\n+++ b/utils/tuning/libtuning/modules/agc/rkisp1.py\n@@ -0,0 +1,110 @@\n+# SPDX-License-Identifier: BSD-2-Clause\n+#\n+# Copyright (C) 2019, Raspberry Pi Ltd\n+# Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>\n+#\n+# rkisp1.py - AGC module for tuning rkisp1\n+\n+from .agc import AGC\n+\n+import libtuning as lt\n+\n+\n+class AGCRkISP1(AGC):\n+    hr_name = 'AGC (RkISP1)'\n+    out_name = 'Agc'\n+\n+    def __init__(self, *, **kwargs):\n+        super().__init__(**kwargs)\n+\n+    # We don't actually need anything from the config file\n+    def validate_config(self, config: dict) -> bool:\n+        return True\n+\n+    def _generate_metering_modes(self) -> dict:\n+        centre_weighted = {\n+                'v10': [\n+                    0, 0,  0, 0, 0,\n+                    0, 6,  8, 6, 0,\n+                    0, 8, 16, 8, 0,\n+                    0, 6,  8, 6, 0,\n+                    0, 0,  0, 0, 0\n+                ],\n+\n+                'v12': [\n+                    0, 0, 0, 0,  0, 0, 0, 0, 0,\n+                    0, 0, 0, 0,  0, 0, 0, 0, 0,\n+                    0, 0, 0, 3,  4, 3, 0, 0, 0,\n+                    0, 0, 3, 6,  8, 6, 3, 0, 0,\n+                    0, 0, 4, 8, 16, 8, 4, 0, 0,\n+                    0, 0, 3, 6,  8, 6, 3, 0, 0,\n+                    0, 0, 0, 3,  4, 3, 0, 0, 0,\n+                    0, 0, 0, 0,  0, 0, 0, 0, 0,\n+                    0, 0, 0, 0,  0, 0, 0, 0, 0,\n+                ]\n+        }\n+\n+        spot = {\n+                'v10': [\n+                    0, 0,  0, 0, 0,\n+                    0, 2,  4, 2, 0,\n+                    0, 4, 16, 4, 0,\n+                    0, 2,  4, 2, 0,\n+                    0, 0,  0, 0, 0\n+                ],\n+\n+                'v12': [\n+                    0, 0, 0, 0,  0, 0, 0, 0, 0,\n+                    0, 0, 0, 0,  0, 0, 0, 0, 0,\n+                    0, 0, 0, 1,  2, 1, 0, 0, 0,\n+                    0, 0, 1, 2,  4, 2, 1, 0, 0,\n+                    0, 0, 2, 4, 16, 4, 2, 0, 0,\n+                    0, 0, 1, 2,  4, 2, 1, 0, 0,\n+                    0, 0, 0, 1,  2, 1, 0, 0, 0,\n+                    0, 0, 0, 0,  0, 0, 0, 0, 0,\n+                    0, 0, 0, 0,  0, 0, 0, 0, 0,\n+                ]\n+        }\n+\n+        matrix = {\n+                'v10': [1 for i in range(0, 25)],\n+                'v12': [1 for i in range(0, 81)]\n+        }\n+\n+        return {\n+            'MeteringCentreWeighted': centre_weighted,\n+            'MeteringSpot': spot,\n+            'MeteringMatrix': matrix\n+        }\n+\n+    def _generate_exposure_modes(self) -> dict:\n+        normal = { 'shutter': [100, 10000, 30000, 60000, 120000],\n+                   'gain': [2.0, 4.0, 6.0, 6.0, 6.0]}\n+        short = { 'shutter': [100, 5000, 10000, 20000, 120000],\n+                  'gain': [2.0, 4.0, 6.0, 6.0, 6.0]}\n+\n+        return { 'ExposureNormal': normal, 'ExposureShort': short }\n+\n+    def _generate_constraint_modes(self) -> dict:\n+        normal = { 'lower': { 'qLo': 0.98, 'qHi': 1.0, 'yTarget': [ 0, 0.5, 1000, 0.5 ] } }\n+        highlight = {\n+            'lower': { 'qLo': 0.98, 'qHi': 1.0, 'yTarget': [ 0, 0.5, 1000, 0.5 ] },\n+            'upper': { 'qLo': 0.98, 'qHi': 1.0, 'yTarget': [ 0, 0.8, 1000, 0.5 ] }\n+        }\n+\n+        return { 'ConstraintNormal': normal, 'ConstraintHighlight': highlight }\n+\n+    def _generate_y_target(self) -> list:\n+        return [0, 0.16, 1000, 0.165, 10000, 0.17]\n+\n+    def process(self, config: dict, images: list, outputs: dict) -> dict:\n+        output = {}\n+\n+        output['AeMeteringMode'] = self._generate_metering_modes()\n+        output['AeExposureMode'] = self._generate_exposure_modes()\n+        output['AeConstraintMode'] = self._generate_constraint_modes()\n+        output['relativeLuminanceTarget'] = self._generate_y_target()\n+\n+        # \\todo Debug functionality\n+\n+        return output\n",
    "prefixes": [
        "v3",
        "1/4"
    ]
}