Show a patch.

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

{
    "id": 17850,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/17850/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/17850/",
    "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": "<20221123134346.129807-5-jacopo@jmondi.org>",
    "date": "2022-11-23T13:43:46",
    "name": "[libcamera-devel,v2,4/4] ipa: rkisp1: add FrameDurationLimits control",
    "commit_ref": "1d8fb317593680a539435dc2cfbb67676894d4c9",
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "167aa78a7e7f342caad21f0c9b2101187cb30151",
    "submitter": {
        "id": 3,
        "url": "https://patchwork.libcamera.org/api/1.1/people/3/?format=api",
        "name": "Jacopo Mondi",
        "email": "jacopo@jmondi.org"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/17850/mbox/",
    "series": [
        {
            "id": 3633,
            "url": "https://patchwork.libcamera.org/api/1.1/series/3633/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=3633",
            "date": "2022-11-23T13:43:42",
            "name": "ipa: Validate controls in CameraSensor",
            "version": 2,
            "mbox": "https://patchwork.libcamera.org/series/3633/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/17850/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/17850/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 72682BE08B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 23 Nov 2022 13:44:03 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 1FFA663313;\n\tWed, 23 Nov 2022 14:44:03 +0100 (CET)",
            "from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net\n\t[IPv6:2001:4b98:dc4:8::224])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 38C0E63313\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 23 Nov 2022 14:44:01 +0100 (CET)",
            "(Authenticated sender: jacopo@jmondi.org)\n\tby mail.gandi.net (Postfix) with ESMTPSA id 7A980E000F;\n\tWed, 23 Nov 2022 13:44:00 +0000 (UTC)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1669211043;\n\tbh=Nu8fAcglarQ1J/JjWXeW4NbEtZjXEed4s6EarGgVuVk=;\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=03O2iNd97up/508Md91oNrXKAB8OBK8D9RxGyPU4gk/qStZrP88AGsP8oJk9jYE78\n\tMsbEXq3RE/488GfBgPZqOnxODj6C4LWsLtti3AZhtuUaV2AuEI15aUIh5VVPoy55hm\n\tSsPmkNHCU9oFor+eGz05iIBGhYzZzjR0SgyiGupD5k3HYBkjxH1YyqBABjEea68cAL\n\tIu30a5HrkppiaVWW+sYBDxABqTn26Y2jQvAZmfvFljDcUitvepnScBb0YWkDJ0rGv3\n\tAHzGtrjnWxQH8JZJiCPcqfzUOvRXyoYJcHTAKAPSUgfRAppjBMvbCQ1cS/YfbkNAEJ\n\t2mF1yJrDxUAbQ==",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Wed, 23 Nov 2022 14:43:46 +0100",
        "Message-Id": "<20221123134346.129807-5-jacopo@jmondi.org>",
        "X-Mailer": "git-send-email 2.38.1",
        "In-Reply-To": "<20221123134346.129807-1-jacopo@jmondi.org>",
        "References": "<20221123134346.129807-1-jacopo@jmondi.org>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [PATCH v2 4/4] ipa: rkisp1: add\n\tFrameDurationLimits control",
        "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": "Jacopo Mondi via libcamera-devel <libcamera-devel@lists.libcamera.org>",
        "Reply-To": "Jacopo Mondi <jacopo@jmondi.org>",
        "Cc": "Nicholas Roth <nicholas@rothemail.net>",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "From: Nicholas Roth <nicholas@rothemail.net>\n\nCurrently, the Android HAL does not work on rkisp1-based devices because\nrequired FrameDurationLimits metadata is missing from the IPA\nimplementation.\n\nThis change sets FrameDurationLimits for rkisp1 based on the existing\nipu3 implementation, using the sensor's reported range of vertical\nblanking intervals with the minimum reported horizontal blanking\ninterval.\n\nSigned-off-by: Nicholas Roth <nicholas@rothemail.net>\nSigned-off-by: Jacopo Mondi <jacopo@jmondi.org>\n---\n include/libcamera/ipa/rkisp1.mojom       |  6 ++-\n src/ipa/rkisp1/rkisp1.cpp                | 57 +++++++++++++++++++++---\n src/libcamera/pipeline/rkisp1/rkisp1.cpp | 17 ++++---\n 3 files changed, 67 insertions(+), 13 deletions(-)",
    "diff": "diff --git a/include/libcamera/ipa/rkisp1.mojom b/include/libcamera/ipa/rkisp1.mojom\nindex 36bf291e8a51..1009e970a1b5 100644\n--- a/include/libcamera/ipa/rkisp1.mojom\n+++ b/include/libcamera/ipa/rkisp1.mojom\n@@ -15,14 +15,16 @@ struct IPAConfigInfo {\n \n interface IPARkISP1Interface {\n \tinit(libcamera.IPASettings settings,\n-\t     uint32 hwRevision)\n+\t     uint32 hwRevision,\n+\t     libcamera.IPACameraSensorInfo sensorInfo,\n+\t     libcamera.ControlInfoMap sensorControls)\n \t\t=> (int32 ret, libcamera.ControlInfoMap ipaControls);\n \tstart() => (int32 ret);\n \tstop();\n \n \tconfigure(IPAConfigInfo configInfo,\n \t\t  map<uint32, libcamera.IPAStream> streamConfig)\n-\t\t=> (int32 ret);\n+\t\t=> (int32 ret, libcamera.ControlInfoMap ipaControls);\n \n \tmapBuffers(array<libcamera.IPABuffer> buffers);\n \tunmapBuffers(array<uint32> ids);\ndiff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp\nindex a9e144303072..9265d3c9f53c 100644\n--- a/src/ipa/rkisp1/rkisp1.cpp\n+++ b/src/ipa/rkisp1/rkisp1.cpp\n@@ -49,12 +49,15 @@ public:\n \tIPARkISP1();\n \n \tint init(const IPASettings &settings, unsigned int hwRevision,\n+\t\t const IPACameraSensorInfo &sensorInfo,\n+\t\t const ControlInfoMap &sensorControls,\n \t\t ControlInfoMap *ipaControls) override;\n \tint start() override;\n \tvoid stop() override;\n \n \tint configure(const IPAConfigInfo &ipaConfig,\n-\t\t      const std::map<uint32_t, IPAStream> &streamConfig) override;\n+\t\t      const std::map<uint32_t, IPAStream> &streamConfig,\n+\t\t      ControlInfoMap *ipaControls) override;\n \tvoid mapBuffers(const std::vector<IPABuffer> &buffers) override;\n \tvoid unmapBuffers(const std::vector<unsigned int> &ids) override;\n \n@@ -67,6 +70,9 @@ protected:\n \tstd::string logPrefix() const override;\n \n private:\n+\tvoid updateControls(const IPACameraSensorInfo &sensorInfo,\n+\t\t\t    const ControlInfoMap &sensorControls,\n+\t\t\t    ControlInfoMap *ipaControls);\n \tvoid setControls(unsigned int frame);\n \n \tstd::map<unsigned int, FrameBuffer> buffers_;\n@@ -114,6 +120,8 @@ std::string IPARkISP1::logPrefix() const\n }\n \n int IPARkISP1::init(const IPASettings &settings, unsigned int hwRevision,\n+\t\t    const IPACameraSensorInfo &sensorInfo,\n+\t\t    const ControlInfoMap &sensorControls,\n \t\t    ControlInfoMap *ipaControls)\n {\n \t/* \\todo Add support for other revisions */\n@@ -180,9 +188,8 @@ int IPARkISP1::init(const IPASettings &settings, unsigned int hwRevision,\n \tif (ret)\n \t\treturn ret;\n \n-\t/* Return the controls handled by the IPA. */\n-\tControlInfoMap::Map ctrlMap = rkisp1Controls;\n-\t*ipaControls = ControlInfoMap(std::move(ctrlMap), controls::controls);\n+\t/* Initialize controls. */\n+\tupdateControls(sensorInfo, sensorControls, ipaControls);\n \n \treturn 0;\n }\n@@ -200,7 +207,8 @@ void IPARkISP1::stop()\n }\n \n int IPARkISP1::configure(const IPAConfigInfo &ipaConfig,\n-\t\t\t [[maybe_unused]] const std::map<uint32_t, IPAStream> &streamConfig)\n+\t\t\t [[maybe_unused]] const std::map<uint32_t, IPAStream> &streamConfig,\n+\t\t\t ControlInfoMap *ipaControls)\n {\n \tsensorControls_ = ipaConfig.sensorControls;\n \n@@ -230,6 +238,9 @@ int IPARkISP1::configure(const IPAConfigInfo &ipaConfig,\n \tcontext_.configuration.sensor.size = info.outputSize;\n \tcontext_.configuration.sensor.lineDuration = info.minLineLength * 1.0s / info.pixelRate;\n \n+\t/* Update the camera controls using the new sensor settings. */\n+\tupdateControls(info, sensorControls_, ipaControls);\n+\n \t/*\n \t * When the AGC computes the new exposure values for a frame, it needs\n \t * to know the limits for shutter speed and analogue gain.\n@@ -332,6 +343,42 @@ void IPARkISP1::processStatsBuffer(const uint32_t frame, const uint32_t bufferId\n \tmetadataReady.emit(frame, metadata);\n }\n \n+void IPARkISP1::updateControls(const IPACameraSensorInfo &sensorInfo,\n+\t\t\t       const ControlInfoMap &sensorControls,\n+\t\t\t       ControlInfoMap *ipaControls)\n+{\n+\tControlInfoMap::Map ctrlMap = rkisp1Controls;\n+\n+\t/*\n+\t * Compute the frame duration limits.\n+\t *\n+\t * The frame length is computed assuming a fixed line length combined\n+\t * with the vertical frame sizes.\n+\t */\n+\tconst ControlInfo &v4l2HBlank = sensorControls.find(V4L2_CID_HBLANK)->second;\n+\tuint32_t hblank = v4l2HBlank.def().get<int32_t>();\n+\tuint32_t lineLength = sensorInfo.outputSize.width + hblank;\n+\n+\tconst ControlInfo &v4l2VBlank = sensorControls.find(V4L2_CID_VBLANK)->second;\n+\tstd::array<uint32_t, 3> frameHeights{\n+\t\tv4l2VBlank.min().get<int32_t>() + sensorInfo.outputSize.height,\n+\t\tv4l2VBlank.max().get<int32_t>() + sensorInfo.outputSize.height,\n+\t\tv4l2VBlank.def().get<int32_t>() + sensorInfo.outputSize.height,\n+\t};\n+\n+\tstd::array<int64_t, 3> frameDurations;\n+\tfor (unsigned int i = 0; i < frameHeights.size(); ++i) {\n+\t\tuint64_t frameSize = lineLength * frameHeights[i];\n+\t\tframeDurations[i] = frameSize / (sensorInfo.pixelRate / 1000000U);\n+\t}\n+\n+\tctrlMap[&controls::FrameDurationLimits] = ControlInfo(frameDurations[0],\n+\t\t\t\t\t\t\t      frameDurations[1],\n+\t\t\t\t\t\t\t      frameDurations[2]);\n+\n+\t*ipaControls = ControlInfoMap(std::move(ctrlMap), controls::controls);\n+}\n+\n void IPARkISP1::setControls(unsigned int frame)\n {\n \t/*\ndiff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp\nindex e946ccc4c930..231b16eca110 100644\n--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp\n+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp\n@@ -347,8 +347,15 @@ int RkISP1CameraData::loadIPA(unsigned int hwRevision)\n \t\tipaTuningFile = std::string(configFromEnv);\n \t}\n \n-\tint ret = ipa_->init({ ipaTuningFile, sensor_->model() }, hwRevision,\n-\t\t\t     &controlInfo_);\n+\tIPACameraSensorInfo sensorInfo{};\n+\tint ret = sensor_->sensorInfo(&sensorInfo);\n+\tif (ret) {\n+\t\tLOG(RkISP1, Error) << \"Camera sensor information not available\";\n+\t\treturn ret;\n+\t}\n+\n+\tret = ipa_->init({ ipaTuningFile, sensor_->model() }, hwRevision,\n+\t\t\t sensorInfo, sensor_->controls(), &controlInfo_);\n \tif (ret < 0) {\n \t\tLOG(RkISP1, Error) << \"IPA initialization failure\";\n \t\treturn ret;\n@@ -718,14 +725,12 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c)\n \tipa::rkisp1::IPAConfigInfo ipaConfig{};\n \n \tret = data->sensor_->sensorInfo(&ipaConfig.sensorInfo);\n-\tif (ret) {\n-\t\tLOG(RkISP1, Error) << \"Camera sensor information not available\";\n+\tif (ret)\n \t\treturn ret;\n-\t}\n \n \tipaConfig.sensorControls = data->sensor_->controls();\n \n-\tret = data->ipa_->configure(ipaConfig, streamConfig);\n+\tret = data->ipa_->configure(ipaConfig, streamConfig, &data->controlInfo_);\n \tif (ret) {\n \t\tLOG(RkISP1, Error) << \"failed configuring IPA (\" << ret << \")\";\n \t\treturn ret;\n",
    "prefixes": [
        "libcamera-devel",
        "v2",
        "4/4"
    ]
}