Show a patch.

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

{
    "id": 21889,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/21889/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/21889/",
    "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": "<20241113131256.3170817-7-paul.elder@ideasonboard.com>",
    "date": "2024-11-13T13:12:54",
    "name": "[v3,6/8] ipa: rkisp1: Port to the new AEGC controls",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "cd889024e82736ca642fb04206c9beaf3bd67409",
    "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/21889/mbox/",
    "series": [
        {
            "id": 4790,
            "url": "https://patchwork.libcamera.org/api/1.1/series/4790/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4790",
            "date": "2024-11-13T13:12:48",
            "name": "AEGC controls",
            "version": 3,
            "mbox": "https://patchwork.libcamera.org/series/4790/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/21889/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/21889/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 E186BBE173\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 13 Nov 2024 13:13:37 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 8664F6582D;\n\tWed, 13 Nov 2024 14:13:37 +0100 (CET)",
            "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 7776165827\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 13 Nov 2024 14:13:34 +0100 (CET)",
            "from neptunite.flets-east.jp (unknown\n\t[IPv6:2404:7a81:160:2100:eb25:7aa0:7da7:eb24])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 638DB1054;\n\tWed, 13 Nov 2024 14:13:19 +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=\"EBMBwMWx\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1731503601;\n\tbh=FzpSv17XKN+UM3Mm/RpL4GL3Z1YKt7qCJSWRbfVnb58=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=EBMBwMWxprOznxLcXaePCrpEonOyA9mkzUfoHRvikstzXPMg7ASELmXhMIg1oYK9u\n\tfRciagjITK8lmlw0/7qgPsBw7p+Ep6/QsLiX7UXXsCDwdRDcKEl9dTpKe9H9l7OiSw\n\tdTFqsCDLet38nZvvduwhHFf4NYtxdgOsmFlH4BkY=",
        "From": "Paul Elder <paul.elder@ideasonboard.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Cc": "laurent.pinchart@ideasonboard.com, jacopo.mondi@ideasonboard.com,\n\tnaush@raspberrypi.com, david.plowman@raspberrypi.com,\n\tPaul Elder <paul.elder@ideasonboard.com>",
        "Subject": "[PATCH v3 6/8] ipa: rkisp1: Port to the new AEGC controls",
        "Date": "Wed, 13 Nov 2024 22:12:54 +0900",
        "Message-Id": "<20241113131256.3170817-7-paul.elder@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.39.2",
        "In-Reply-To": "<20241113131256.3170817-1-paul.elder@ideasonboard.com>",
        "References": "<20241113131256.3170817-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": "The newly introduced controls to drive the AEGC algorithm allow\ncontrolling the computation of the exposure time and analogue gain\nseparately.\n\nAugument the RkISP1 AEGC implementation to handle the exposure and gain\ncontrols separately using the new controls.\n\nSigned-off-by: Paul Elder <paul.elder@ideasonboard.com>\n\n---\nNew in v3\n\nBack 2 years ago in v2 RkISP1 didn't yet support AeEnable properly yet\nso the AeEnable control was simply removed.\n---\n src/ipa/rkisp1/algorithms/agc.cpp | 68 ++++++++++++++++++++++++-------\n src/ipa/rkisp1/ipa_context.cpp    | 14 +++++--\n src/ipa/rkisp1/ipa_context.h      |  6 ++-\n 3 files changed, 67 insertions(+), 21 deletions(-)",
    "diff": "diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp\nindex 301b7ec26508..0ad206621516 100644\n--- a/src/ipa/rkisp1/algorithms/agc.cpp\n+++ b/src/ipa/rkisp1/algorithms/agc.cpp\n@@ -148,7 +148,12 @@ int Agc::init(IPAContext &context, const YamlObject &tuningData)\n \tif (ret)\n \t\treturn ret;\n \n-\tcontext.ctrlMap[&controls::AeEnable] = ControlInfo(false, true);\n+\tcontext.ctrlMap[&controls::ExposureTimeMode] =\n+\t\tControlInfo(static_cast<int32_t>(controls::ExposureTimeModeAuto),\n+\t\t\t    static_cast<int32_t>(controls::ExposureTimeModeManual));\n+\tcontext.ctrlMap[&controls::AnalogueGainMode] =\n+\t\tControlInfo(static_cast<int32_t>(controls::AnalogueGainModeAuto),\n+\t\t\t    static_cast<int32_t>(controls::AnalogueGainModeManual));\n \tcontext.ctrlMap.merge(controls());\n \n \treturn 0;\n@@ -169,7 +174,8 @@ int Agc::configure(IPAContext &context, const IPACameraSensorInfo &configInfo)\n \t\t10ms / context.configuration.sensor.lineDuration;\n \tcontext.activeState.agc.manual.gain = context.activeState.agc.automatic.gain;\n \tcontext.activeState.agc.manual.exposure = context.activeState.agc.automatic.exposure;\n-\tcontext.activeState.agc.autoEnabled = !context.configuration.raw;\n+\tcontext.activeState.agc.autoExposureEnabled = !context.configuration.raw;\n+\tcontext.activeState.agc.autoGainEnabled = !context.configuration.raw;\n \n \tcontext.activeState.agc.constraintMode =\n \t\tstatic_cast<controls::AeConstraintModeEnum>(constraintModes().begin()->first);\n@@ -215,18 +221,42 @@ void Agc::queueRequest(IPAContext &context,\n \tauto &agc = context.activeState.agc;\n \n \tif (!context.configuration.raw) {\n-\t\tconst auto &agcEnable = controls.get(controls::AeEnable);\n-\t\tif (agcEnable && *agcEnable != agc.autoEnabled) {\n-\t\t\tagc.autoEnabled = *agcEnable;\n+\t\tconst auto &aeEnable = controls.get(controls::ExposureTimeMode);\n+\t\tif (aeEnable &&\n+\t\t    (*aeEnable == controls::ExposureTimeModeAuto) != agc.autoExposureEnabled) {\n+\t\t\tagc.autoExposureEnabled = (*aeEnable == controls::ExposureTimeModeAuto);\n \n \t\t\tLOG(RkISP1Agc, Debug)\n-\t\t\t\t<< (agc.autoEnabled ? \"Enabling\" : \"Disabling\")\n-\t\t\t\t<< \" AGC\";\n+\t\t\t\t<< (agc.autoExposureEnabled ? \"Enabling\" : \"Disabling\")\n+\t\t\t\t<< \" AGC (exposure)\";\n+\n+\t\t\t/*\n+\t\t\t * If we go from auto -> manual with no manual control\n+\t\t\t * set, use the last computed value\n+\t\t\t */\n+\t\t\tif (!agc.autoExposureEnabled && !controls.get(controls::ExposureTime))\n+\t\t\t\tframeContext.agc.exposure = agc.automatic.exposure;\n+\t\t}\n+\n+\t\tconst auto &agEnable = controls.get(controls::AnalogueGainMode);\n+\t\tif (agEnable &&\n+\t\t    (*agEnable == controls::AnalogueGainModeAuto) != agc.autoGainEnabled) {\n+\t\t\tagc.autoGainEnabled = (*agEnable == controls::AnalogueGainModeAuto);\n+\n+\t\t\tLOG(RkISP1Agc, Debug)\n+\t\t\t\t<< (agc.autoGainEnabled ? \"Enabling\" : \"Disabling\")\n+\t\t\t\t<< \" AGC (gain)\";\n+\t\t\t/*\n+\t\t\t * If we go from auto -> manual with no manual control\n+\t\t\t * set, use the last computed value\n+\t\t\t */\n+\t\t\tif (!agc.autoGainEnabled && !controls.get(controls::AnalogueGain))\n+\t\t\t\tframeContext.agc.gain = agc.automatic.gain;\n \t\t}\n \t}\n \n \tconst auto &exposure = controls.get(controls::ExposureTime);\n-\tif (exposure && !agc.autoEnabled) {\n+\tif (exposure && !agc.autoExposureEnabled) {\n \t\tagc.manual.exposure = *exposure * 1.0us\n \t\t\t\t    / context.configuration.sensor.lineDuration;\n \n@@ -235,18 +265,19 @@ void Agc::queueRequest(IPAContext &context,\n \t}\n \n \tconst auto &gain = controls.get(controls::AnalogueGain);\n-\tif (gain && !agc.autoEnabled) {\n+\tif (gain && !agc.autoGainEnabled) {\n \t\tagc.manual.gain = *gain;\n \n \t\tLOG(RkISP1Agc, Debug) << \"Set gain to \" << agc.manual.gain;\n \t}\n \n-\tframeContext.agc.autoEnabled = agc.autoEnabled;\n+\tframeContext.agc.autoExposureEnabled = agc.autoExposureEnabled;\n+\tframeContext.agc.autoGainEnabled = agc.autoGainEnabled;\n \n-\tif (!frameContext.agc.autoEnabled) {\n+\tif (!frameContext.agc.autoExposureEnabled)\n \t\tframeContext.agc.exposure = agc.manual.exposure;\n+\tif (!frameContext.agc.autoGainEnabled)\n \t\tframeContext.agc.gain = agc.manual.gain;\n-\t}\n \n \tconst auto &meteringMode = controls.get(controls::AeMeteringMode);\n \tif (meteringMode) {\n@@ -283,10 +314,10 @@ void Agc::queueRequest(IPAContext &context,\n void Agc::prepare(IPAContext &context, const uint32_t frame,\n \t\t  IPAFrameContext &frameContext, RkISP1Params *params)\n {\n-\tif (frameContext.agc.autoEnabled) {\n+\tif (frameContext.agc.autoExposureEnabled)\n \t\tframeContext.agc.exposure = context.activeState.agc.automatic.exposure;\n+\tif (frameContext.agc.autoGainEnabled)\n \t\tframeContext.agc.gain = context.activeState.agc.automatic.gain;\n-\t}\n \n \tif (frame > 0 && !frameContext.agc.updateMetering)\n \t\treturn;\n@@ -333,7 +364,14 @@ void Agc::fillMetadata(IPAContext &context, IPAFrameContext &frameContext,\n \t\t\t\t     * frameContext.sensor.exposure;\n \tmetadata.set(controls::AnalogueGain, frameContext.sensor.gain);\n \tmetadata.set(controls::ExposureTime, exposureTime.get<std::micro>());\n-\tmetadata.set(controls::AeEnable, frameContext.agc.autoEnabled);\n+\tmetadata.set(controls::ExposureTimeMode,\n+\t\t     frameContext.agc.autoExposureEnabled\n+\t\t     ? controls::ExposureTimeModeAuto\n+\t\t     : controls::ExposureTimeModeManual);\n+\tmetadata.set(controls::AnalogueGainMode,\n+\t\t     frameContext.agc.autoGainEnabled\n+\t\t     ? controls::AnalogueGainModeAuto\n+\t\t     : controls::AnalogueGainModeManual);\n \n \t/* \\todo Use VBlank value calculated from each frame exposure. */\n \tuint32_t vTotal = context.configuration.sensor.size.height\ndiff --git a/src/ipa/rkisp1/ipa_context.cpp b/src/ipa/rkisp1/ipa_context.cpp\nindex 14d0c02a2b32..a8e8e1c0d06e 100644\n--- a/src/ipa/rkisp1/ipa_context.cpp\n+++ b/src/ipa/rkisp1/ipa_context.cpp\n@@ -165,8 +165,11 @@ namespace libcamera::ipa::rkisp1 {\n  * \\var IPAActiveState::agc.automatic.gain\n  * \\brief Automatic analogue gain multiplier\n  *\n- * \\var IPAActiveState::agc.autoEnabled\n- * \\brief Manual/automatic AGC state as set by the AeEnable control\n+ * \\var IPAActiveState::agc.autoExposureEnabled\n+ * \\brief Manual/automatic AGC state (exposure) as set by the ExposureTimeMode control\n+ *\n+ * \\var IPAActiveState::agc.autoGainEnabled\n+ * \\brief Manual/automatic AGC state (gain) as set by the AnalogueGainMode control\n  *\n  * \\var IPAActiveState::agc.constraintMode\n  * \\brief Constraint mode as set by the AeConstraintMode control\n@@ -307,8 +310,11 @@ namespace libcamera::ipa::rkisp1 {\n  *\n  * The gain should be adapted to the sensor specific gain code before applying.\n  *\n- * \\var IPAFrameContext::agc.autoEnabled\n- * \\brief Manual/automatic AGC state as set by the AeEnable control\n+ * \\var IPAFrameContext::agc.autoExposureEnabled\n+ * \\brief Manual/automatic AGC state (exposure) as set by the ExposureTimeMode control\n+ *\n+ * \\var IPAFrameContext::agc.autoGainEnabled\n+ * \\brief Manual/automatic AGC state (gain) as set by the AnalogueGainMode control\n  *\n  * \\var IPAFrameContext::agc.constraintMode\n  * \\brief Constraint mode as set by the AeConstraintMode control\ndiff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h\nindex e274d9b01e1c..7f819d31015e 100644\n--- a/src/ipa/rkisp1/ipa_context.h\n+++ b/src/ipa/rkisp1/ipa_context.h\n@@ -75,7 +75,8 @@ struct IPAActiveState {\n \t\t\tdouble gain;\n \t\t} automatic;\n \n-\t\tbool autoEnabled;\n+\t\tbool autoExposureEnabled;\n+\t\tbool autoGainEnabled;\n \t\tcontrols::AeConstraintModeEnum constraintMode;\n \t\tcontrols::AeExposureModeEnum exposureMode;\n \t\tcontrols::AeMeteringModeEnum meteringMode;\n@@ -128,7 +129,8 @@ struct IPAFrameContext : public FrameContext {\n \tstruct {\n \t\tuint32_t exposure;\n \t\tdouble gain;\n-\t\tbool autoEnabled;\n+\t\tbool autoExposureEnabled;\n+\t\tbool autoGainEnabled;\n \t\tcontrols::AeConstraintModeEnum constraintMode;\n \t\tcontrols::AeExposureModeEnum exposureMode;\n \t\tcontrols::AeMeteringModeEnum meteringMode;\n",
    "prefixes": [
        "v3",
        "6/8"
    ]
}