Show a patch.

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

{
    "id": 26053,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/26053/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/26053/",
    "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": "<20260130080935.2569621-5-paul.elder@ideasonboard.com>",
    "date": "2026-01-30T08:09:35",
    "name": "[v2,4/4] ipa: rkisp1: agc: Add support for sync",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "a00ebe32a50fbfbbca45169171b54b0d1766d90a",
    "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/26053/mbox/",
    "series": [
        {
            "id": 5759,
            "url": "https://patchwork.libcamera.org/api/1.1/series/5759/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5759",
            "date": "2026-01-30T08:09:31",
            "name": "Add Sync Layer",
            "version": 2,
            "mbox": "https://patchwork.libcamera.org/series/5759/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/26053/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/26053/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 14EF9C3226\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 30 Jan 2026 08:10:01 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id CE35D61FDC;\n\tFri, 30 Jan 2026 09:10:00 +0100 (CET)",
            "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 4EB0661FD1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 30 Jan 2026 09:09:59 +0100 (CET)",
            "from neptunite.hamster-moth.ts.net (unknown\n\t[IPv6:2404:7a81:160:2100:ec11:5e0c:deb8:1e2d])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 098FA1E23;\n\tFri, 30 Jan 2026 09:09:18 +0100 (CET)"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"HBn5eddS\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1769760561;\n\tbh=YkNHzAtu2r5UXKdVQG7lH8PyiJgdwYF3NoBj50v0SYU=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=HBn5eddSzx/xcQZmdW1Tcp0QKPqmq9dk/8bKJ6mMK1k5qJkZfLOQ5Wk6cYrLD2lAV\n\t2gucpoZd+teRl3/8eMC3CiuUdrHeJK+Q4C2pi1qLp0fUISgt4vWfRUvvg5/dKB/stT\n\t/b13dWhD/5BVnZWNsJ+IP7ZDLNRIizCee37bYUVo=",
        "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 v2 4/4] ipa: rkisp1: agc: Add support for sync",
        "Date": "Fri, 30 Jan 2026 17:09:35 +0900",
        "Message-ID": "<20260130080935.2569621-5-paul.elder@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.47.2",
        "In-Reply-To": "<20260130080935.2569621-1-paul.elder@ideasonboard.com>",
        "References": "<20260130080935.2569621-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---\nChanges in v2:\n- move SyncHelper from inherited to a member of Agc\n- cosmetic changes\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, 25 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp\nindex 55cadb1793a5..1496a118ae2b 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] = SyncHelper::controlInfo(120'000);\n+\t/* Insert the controls for agc */\n \tcontext.ctrlMap.merge(controls());\n \n \treturn 0;\n@@ -208,7 +217,11 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)\n \n \tcontext.activeState.agc.automatic.yTarget = effectiveYTarget();\n \n+\tcontext.ctrlMap[&controls::SyncAdjustment] =\n+\t\tSyncHelper::controlInfo(frameDurationLimits.max().get<int64_t>());\n+\n \tresetFrameCount();\n+\tsync_.resetSync();\n \n \treturn 0;\n }\n@@ -334,6 +347,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\tsync_.setSync(*sync, frameContext.agc.minFrameDuration);\n }\n \n /**\n@@ -453,6 +470,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@@ -511,7 +529,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 = 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..c6cc20679cf7 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@@ -58,6 +59,8 @@ private:\n \tSpan<const uint8_t> weights_;\n \n \tstd::map<int32_t, std::vector<uint8_t>> meteringModes_;\n+\n+\tSyncHelper sync_;\n };\n \n } /* namespace ipa::rkisp1::algorithms */\ndiff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h\nindex fa748811be74..3a5b499e088e 100644\n--- a/src/ipa/rkisp1/ipa_context.h\n+++ b/src/ipa/rkisp1/ipa_context.h\n@@ -164,6 +164,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": [
        "v2",
        "4/4"
    ]
}