Show a patch.

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

{
    "id": 24263,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/24263/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/24263/",
    "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": "<20250829091011.2628954-5-paul.elder@ideasonboard.com>",
    "date": "2025-08-29T09:10:10",
    "name": "[4/4] ipa: rkisp1: agc: Add support for sync",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "916480db88b2860dd36401a2ce7d2d0af40b132f",
    "submitter": {
        "id": 17,
        "url": "https://patchwork.libcamera.org/api/1.1/people/17/?format=api",
        "name": "Paul Elder",
        "email": "paul.elder@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/24263/mbox/",
    "series": [
        {
            "id": 5412,
            "url": "https://patchwork.libcamera.org/api/1.1/series/5412/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5412",
            "date": "2025-08-29T09:10:06",
            "name": "Add Sync Layer",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/5412/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/24263/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/24263/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 0E9C9C32BB\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 29 Aug 2025 09:10:42 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 8ACB36931B;\n\tFri, 29 Aug 2025 11:10:41 +0200 (CEST)",
            "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 7DA46692DF\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 29 Aug 2025 11:10:38 +0200 (CEST)",
            "from neptunite.hamster-moth.ts.net (unknown\n\t[IPv6:2404:7a81:160:2100:af44:1f54:23d7:1088])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 1F0164B74;\n\tFri, 29 Aug 2025 11:09:30 +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=\"c9cdqFFo\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1756458573;\n\tbh=z+MBMMjBikMkn+xybDV065KU8O/9NSa+XKkT7EUEYok=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=c9cdqFFoZMZ/lxz2/wRcNPp/ZzaR6hzivTbM57NXxlAZg+n9zfqM924S0wBa22Lf1\n\tlwKY9+yYXnGXG5wAzLF9NTXAA5e6ZY5aKlh0/kPJ189cf6OgFXnFKNhYIeQt+MI2ln\n\tXA+rkeK2I3Yihhbq2q7hWbz28EP4oDkvOw3pUklQ=",
        "From": "Paul Elder <paul.elder@ideasonboard.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Cc": "Paul Elder <paul.elder@ideasonboard.com>, david.plowman@raspberrypi.com, \n\tnaush@raspberrypi.com, kieran.bingham@ideasonboard.com,\n\tstefan.klug@ideasonboard.com",
        "Subject": "[PATCH 4/4] ipa: rkisp1: agc: Add support for sync",
        "Date": "Fri, 29 Aug 2025 18:10:10 +0900",
        "Message-ID": "<20250829091011.2628954-5-paul.elder@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.47.2",
        "In-Reply-To": "<20250829091011.2628954-1-paul.elder@ideasonboard.com>",
        "References": "<20250829091011.2628954-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 sync support to the RkISP1 IPA using the SyncHelper from libipa. The\nsyncAdjustment is saved in the frameContext (as opposed to getting it\nfrom the SyncHelper) to avoid potential races and ensure that the same\nvalue that was set into vblank will be returned in metadata.\n\nSigned-off-by: Paul Elder <paul.elder@ideasonboard.com>\n---\n src/ipa/rkisp1/algorithms/agc.cpp | 22 +++++++++++++++++++++-\n src/ipa/rkisp1/algorithms/agc.h   |  3 ++-\n src/ipa/rkisp1/ipa_context.h      |  1 +\n 3 files changed, 24 insertions(+), 2 deletions(-)",
    "diff": "diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp\nindex bb1558df5422..9a27696ff868 100644\n--- a/src/ipa/rkisp1/algorithms/agc.cpp\n+++ b/src/ipa/rkisp1/algorithms/agc.cpp\n@@ -156,6 +156,15 @@ int Agc::init(IPAContext &context, const YamlObject &tuningData)\n \t\t\t\tControlValue(controls::AnalogueGainModeManual) } },\n \t\t\t    ControlValue(controls::AnalogueGainModeAuto));\n \tcontext.ctrlMap[&controls::ExposureValue] = ControlInfo(-8.0f, 8.0f, 0.0f);\n+\t/*\n+\t * Insert the controlInfo for sync. Since FrameDurationLimits is only\n+\t * set *after* the algorithms are initialized, we have no information\n+\t * on it here. Use a sensible default here and update it later in\n+\t * configure().\n+\t * \\todo Move FrameDurationLimits from the base IPA to AGC\n+\t */\n+\tcontext.ctrlMap[&controls::SyncAdjustment] = controlInfo(120000);\n+\t/* Insert the controls for agc */\n \tcontext.ctrlMap.merge(controls());\n \n \treturn 0;\n@@ -202,7 +211,11 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)\n \t\t  context.configuration.sensor.minAnalogueGain,\n \t\t  context.configuration.sensor.maxAnalogueGain);\n \n+\tcontext.ctrlMap[&controls::SyncAdjustment] =\n+\t\tcontrolInfo(frameDurationLimits.max().get<int64_t>());\n+\n \tresetFrameCount();\n+\tresetSync();\n \n \treturn 0;\n }\n@@ -324,6 +337,10 @@ void Agc::queueRequest(IPAContext &context,\n \t}\n \tframeContext.agc.minFrameDuration = agc.minFrameDuration;\n \tframeContext.agc.maxFrameDuration = agc.maxFrameDuration;\n+\n+\tconst auto &sync = controls.get(controls::SyncAdjustment);\n+\tif (sync)\n+\t\tsetSync(*sync, frameContext.agc.minFrameDuration);\n }\n \n /**\n@@ -413,6 +430,7 @@ void Agc::fillMetadata(IPAContext &context, IPAFrameContext &frameContext,\n \tmetadata.set(controls::AeExposureMode, frameContext.agc.exposureMode);\n \tmetadata.set(controls::AeConstraintMode, frameContext.agc.constraintMode);\n \tmetadata.set(controls::ExposureValue, frameContext.agc.exposureValue);\n+\tmetadata.set(controls::SyncAdjustment, frameContext.agc.syncAdjustment.count());\n }\n \n /**\n@@ -471,7 +489,9 @@ void Agc::processFrameDuration(IPAContext &context,\n \tIPACameraSensorInfo &sensorInfo = context.sensorInfo;\n \tutils::Duration lineDuration = context.configuration.sensor.lineDuration;\n \n-\tframeContext.agc.vblank = (frameDuration / lineDuration) - sensorInfo.outputSize.height;\n+\tutils::Duration sync = getSync();\n+\tframeContext.agc.vblank = ((frameDuration + sync) / lineDuration) - sensorInfo.outputSize.height;\n+\tframeContext.agc.syncAdjustment = sync;\n \n \t/* Update frame duration accounting for line length quantization. */\n \tframeContext.agc.frameDuration = (sensorInfo.outputSize.height + frameContext.agc.vblank) * lineDuration;\ndiff --git a/src/ipa/rkisp1/algorithms/agc.h b/src/ipa/rkisp1/algorithms/agc.h\nindex 7867eed9c4e3..4441a519e857 100644\n--- a/src/ipa/rkisp1/algorithms/agc.h\n+++ b/src/ipa/rkisp1/algorithms/agc.h\n@@ -15,6 +15,7 @@\n #include <libcamera/geometry.h>\n \n #include \"libipa/agc_mean_luminance.h\"\n+#include \"libipa/sync_helper.h\"\n \n #include \"algorithm.h\"\n \n@@ -22,7 +23,7 @@ namespace libcamera {\n \n namespace ipa::rkisp1::algorithms {\n \n-class Agc : public Algorithm, public AgcMeanLuminance\n+class Agc : public Algorithm, public AgcMeanLuminance, public SyncHelper\n {\n public:\n \tAgc();\ndiff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h\nindex 7ccc7b501aff..c21ab77b2ba5 100644\n--- a/src/ipa/rkisp1/ipa_context.h\n+++ b/src/ipa/rkisp1/ipa_context.h\n@@ -143,6 +143,7 @@ struct IPAFrameContext : public FrameContext {\n \t\tbool updateMetering;\n \t\tbool autoExposureModeChange;\n \t\tbool autoGainModeChange;\n+\t\tutils::Duration syncAdjustment;\n \t} agc;\n \n \tstruct {\n",
    "prefixes": [
        "4/4"
    ]
}