Show a patch.

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

{
    "id": 3749,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/3749/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/3749/",
    "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": "<20200511100150.5205-3-naush@raspberrypi.com>",
    "date": "2020-05-11T10:01:50",
    "name": "[libcamera-devel,2/2] libcamera: raspberrypi: Limit the maximum framerate to 30.0fps",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "feba076cf3b9c7f0ec29619b3852c6fc8cec2076",
    "submitter": {
        "id": 34,
        "url": "https://patchwork.libcamera.org/api/1.1/people/34/?format=api",
        "name": "Naushir Patuck",
        "email": "naush@raspberrypi.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/3749/mbox/",
    "series": [
        {
            "id": 892,
            "url": "https://patchwork.libcamera.org/api/1.1/series/892/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=892",
            "date": "2020-05-11T10:01:48",
            "name": "raspberrypi: FPS control",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/892/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/3749/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/3749/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "<naush@raspberrypi.com>",
        "Received": [
            "from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com\n\t[IPv6:2a00:1450:4864:20::42e])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 815EF603E2\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 11 May 2020 12:02:00 +0200 (CEST)",
            "by mail-wr1-x42e.google.com with SMTP id 50so9603210wrc.11\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 11 May 2020 03:02:00 -0700 (PDT)",
            "from naushir-VirtualBox.patuck.local ([88.97.76.4])\n\tby smtp.gmail.com with ESMTPSA id\n\tu74sm26391908wmu.13.2020.05.11.03.01.58\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tMon, 11 May 2020 03:01:58 -0700 (PDT)"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=raspberrypi.com\n\theader.i=@raspberrypi.com\n\theader.b=\"gSRRnrQ+\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references;\n\tbh=gSJF6QTfVRwWybx8gLeuO9JAxDrt1z6OOrCNObsnKRQ=;\n\tb=gSRRnrQ+DCJPiEMxXJziP8zOrgBho2vXZhWg+p1iQccmfYDDWRunMYa2MytSRKFCvK\n\t9+IQglcr29djsGbtvIaNyw6RJY2CTBNS6ligkXeneTVmcnWjomu4FMRTGTb0ZNlb+qk5\n\tLPX1SUKS1wNU3b7dawCGqW6fFwZeaoF+1DnmAWH6gwFxqmCbxbx2A7WoDq1vWXil2vCu\n\tVUcWNcGME/IxS1m6HokpyPhH02nuYawjYPcRz0W3sBHGia0JxkPqkl5sdy6dZD4XeJdt\n\taG0YDjRruOiASOSFx3YRF0RJSyYfIcy5vrWs8m69W77s8ydmMQNg6Yws3C+cKce2wKZd\n\tCeIg==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=gSJF6QTfVRwWybx8gLeuO9JAxDrt1z6OOrCNObsnKRQ=;\n\tb=IzubujwZSgvT1va9MlDnP2Dk6ge1pK09JGpzJj0EQ/bcE/T6Bsf1ZkEW+kTIZDH+mO\n\tAdT7KQV1GBtcqBynTZFsoPLaLnZ2njFDmlu/SHDt6RNot4OTZ4b6YNJl1JIDpf/tgBSC\n\tVmNm3M7/ccH7pkTe+biMeaZITQWDqEJnPbGGcsR2Lgw2uqS31ADqnyD/vjJm1QxdGwz3\n\t0HwlzgRQDfZnBLtgXxp5XSpmo7L0r7pWPQAg0RQ2ee7/bJbV6pdnMUNWi6gxRWO5B8ci\n\tmEx/ywMp+zxbv7i3RWEHUFphHpSUqquIbabfjsw3Rah3FcvHR6nsZQdLeVSXFIzsshSm\n\t7sPA==",
        "X-Gm-Message-State": "AGi0PuZNRFuSTTnbXDEQkv09n59ZVm57NI/PxL1y0R74mKgvmckJ8to7\n\tQqrj22Tfz7RtrINl4GOJ18bAkIJEmGFjEA==",
        "X-Google-Smtp-Source": "APiQypLIzPwn1ER9DQ0ASAjhzqkVR88uTyUP09wAQkxKbaC6PqmvGzFFawDr3KRWOqmo+xPTeMGb1w==",
        "X-Received": "by 2002:adf:e483:: with SMTP id i3mr17292506wrm.88.1589191319722;\n\tMon, 11 May 2020 03:01:59 -0700 (PDT)",
        "From": "Naushir Patuck <naush@raspberrypi.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Mon, 11 May 2020 11:01:50 +0100",
        "Message-Id": "<20200511100150.5205-3-naush@raspberrypi.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20200511100150.5205-1-naush@raspberrypi.com>",
        "References": "<20200511100150.5205-1-naush@raspberrypi.com>",
        "Subject": "[libcamera-devel] [PATCH 2/2] libcamera: raspberrypi: Limit the\n\tmaximum framerate to 30.0fps",
        "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>",
        "X-List-Received-Date": "Mon, 11 May 2020 10:02:00 -0000"
    },
    "content": "With the previous change to adapt framerate using VBLANK, the maximum\nframerate was limited by the sensor mode. This may not be entirely\nappropriate for what an application expects in the case where a mode\ncan produce > 30.0fps.\n\nProvide a mechanism to limit the maximum framerate. This is currently\na const set to 30.0fps. In future, this value could be passed in via\na Request or stream configuration.\n\nSigned-off-by: Naushir Patuck <naush@raspberrypi.com>\n---\n src/ipa/raspberrypi/cam_helper.hpp        |  2 +-\n src/ipa/raspberrypi/cam_helper_imx219.cpp | 18 ++++++++++++++----\n src/ipa/raspberrypi/cam_helper_imx477.cpp | 18 ++++++++++++++----\n src/ipa/raspberrypi/cam_helper_ov5647.cpp | 18 ++++++++++++++----\n src/ipa/raspberrypi/raspberrypi.cpp       |  8 +++++++-\n 5 files changed, 50 insertions(+), 14 deletions(-)",
    "diff": "diff --git a/src/ipa/raspberrypi/cam_helper.hpp b/src/ipa/raspberrypi/cam_helper.hpp\nindex 37281c78..4f7a3897 100644\n--- a/src/ipa/raspberrypi/cam_helper.hpp\n+++ b/src/ipa/raspberrypi/cam_helper.hpp\n@@ -74,7 +74,7 @@ public:\n \tMdParser &Parser() const { return *parser_; }\n \tuint32_t ExposureLines(double exposure_us) const;\n \tdouble Exposure(uint32_t exposure_lines) const; // in us\n-\tvirtual uint32_t GetVBlanking(double exposure_us) const = 0;\n+\tvirtual uint32_t GetVBlanking(double exposure_us, double maxFps) const = 0;\n \tvirtual uint32_t GainCode(double gain) const = 0;\n \tvirtual double Gain(uint32_t gain_code) const = 0;\n \tvirtual void GetDelays(int &exposure_delay, int &gain_delay) const;\ndiff --git a/src/ipa/raspberrypi/cam_helper_imx219.cpp b/src/ipa/raspberrypi/cam_helper_imx219.cpp\nindex d34a1f1f..51a18aca 100644\n--- a/src/ipa/raspberrypi/cam_helper_imx219.cpp\n+++ b/src/ipa/raspberrypi/cam_helper_imx219.cpp\n@@ -45,7 +45,7 @@ class CamHelperImx219 : public CamHelper\n {\n public:\n \tCamHelperImx219();\n-\tuint32_t GetVBlanking(double exposure) const override;\n+\tuint32_t GetVBlanking(double exposure, double maxFps) const override;\n \tuint32_t GainCode(double gain) const override;\n \tdouble Gain(uint32_t gain_code) const override;\n \tunsigned int MistrustFramesModeSwitch() const override;\n@@ -55,6 +55,8 @@ public:\n private:\n \t/* Smallest difference between the frame length and integration time. */\n \tstatic constexpr int frameIntegrationDiff = 4;\n+\t/* Largest possible frame length. */\n+\tstatic constexpr int maxFrameLength = 0xffff;\n };\n \n CamHelperImx219::CamHelperImx219()\n@@ -66,12 +68,20 @@ CamHelperImx219::CamHelperImx219()\n {\n }\n \n-uint32_t CamHelperImx219::GetVBlanking(double exposure) const\n+uint32_t CamHelperImx219::GetVBlanking(double exposure, double maxFps) const\n {\n+\tuint32_t frameLengthMin, vblank;\n \tuint32_t exposureLines = ExposureLines(exposure);\n \n-\treturn std::max<uint32_t>(mode_.height, exposureLines) -\n-\t       mode_.height + frameIntegrationDiff;\n+\tvblank = std::max<uint32_t>(mode_.height, exposureLines) -\n+\t\t mode_.height + frameIntegrationDiff;\n+\n+\t/* Limit the vblank to the maximum framerate requested. */\n+\tframeLengthMin = std::min<uint32_t>(1e9 / (mode_.line_length * maxFps),\n+\t\t\t\t\t    maxFrameLength);\n+\tvblank = std::max(vblank, frameLengthMin - mode_.height);\n+\n+\treturn vblank;\n }\n \n uint32_t CamHelperImx219::GainCode(double gain) const\ndiff --git a/src/ipa/raspberrypi/cam_helper_imx477.cpp b/src/ipa/raspberrypi/cam_helper_imx477.cpp\nindex 242d9689..ff815f9c 100644\n--- a/src/ipa/raspberrypi/cam_helper_imx477.cpp\n+++ b/src/ipa/raspberrypi/cam_helper_imx477.cpp\n@@ -35,7 +35,7 @@ class CamHelperImx477 : public CamHelper\n {\n public:\n \tCamHelperImx477();\n-\tuint32_t GetVBlanking(double exposure) const override;\n+\tuint32_t GetVBlanking(double exposure, double maxFps) const override;\n \tuint32_t GainCode(double gain) const override;\n \tdouble Gain(uint32_t gain_code) const override;\n \tbool SensorEmbeddedDataPresent() const override;\n@@ -44,6 +44,8 @@ public:\n private:\n \t/* Smallest difference between the frame length and integration time. */\n \tstatic constexpr int frameIntegrationDiff = 22;\n+\t/* Largest possible frame length. */\n+\tstatic constexpr int maxFrameLength = 0xffdc;\n };\n \n CamHelperImx477::CamHelperImx477()\n@@ -51,12 +53,20 @@ CamHelperImx477::CamHelperImx477()\n {\n }\n \n-uint32_t CamHelperImx477::GetVBlanking(double exposure) const\n+uint32_t CamHelperImx477::GetVBlanking(double exposure, double maxFps) const\n {\n+\tuint32_t frameLengthMin, vblank;\n \tuint32_t exposureLines = ExposureLines(exposure);\n \n-\treturn std::max<uint32_t>(mode_.height, exposureLines) -\n-\t       mode_.height + frameIntegrationDiff;\n+\tvblank = std::max<uint32_t>(mode_.height, exposureLines) -\n+\t\t mode_.height + frameIntegrationDiff;\n+\n+\t/* Limit the vblank to the maximum framerate requested. */\n+\tframeLengthMin = std::min<uint32_t>(1e9 / (mode_.line_length * maxFps),\n+\t\t\t\t\t    maxFrameLength);\n+\tvblank = std::max(vblank, frameLengthMin - mode_.height);\n+\n+\treturn vblank;\n }\n \n uint32_t CamHelperImx477::GainCode(double gain) const\ndiff --git a/src/ipa/raspberrypi/cam_helper_ov5647.cpp b/src/ipa/raspberrypi/cam_helper_ov5647.cpp\nindex ff37779c..53ac3c3b 100644\n--- a/src/ipa/raspberrypi/cam_helper_ov5647.cpp\n+++ b/src/ipa/raspberrypi/cam_helper_ov5647.cpp\n@@ -16,7 +16,7 @@ class CamHelperOv5647 : public CamHelper\n {\n public:\n \tCamHelperOv5647();\n-\tuint32_t GetVBlanking(double exposure) const override;\n+\tuint32_t GetVBlanking(double exposure, double maxFps) const override;\n \tuint32_t GainCode(double gain) const override;\n \tdouble Gain(uint32_t gain_code) const override;\n \tvoid GetDelays(int &exposure_delay, int &gain_delay) const override;\n@@ -27,6 +27,8 @@ public:\n private:\n \t/* Smallest difference between the frame length and integration time. */\n \tstatic constexpr int frameIntegrationDiff = 4;\n+\t/* Largest possible frame length. */\n+\tstatic constexpr int maxFrameLength = 0xffff;\n };\n \n /*\n@@ -39,12 +41,20 @@ CamHelperOv5647::CamHelperOv5647()\n {\n }\n \n-uint32_t CamHelperOv5647::GetVBlanking(double exposure) const\n+uint32_t CamHelperOv5647::GetVBlanking(double exposure, double maxFps) const\n {\n+\tuint32_t frameLengthMin, vblank;\n \tuint32_t exposureLines = ExposureLines(exposure);\n \n-\treturn std::max<uint32_t>(mode_.height, exposureLines) -\n-\t       mode_.height + frameIntegrationDiff;\n+\tvblank = std::max<uint32_t>(mode_.height, exposureLines) -\n+\t\t mode_.height + frameIntegrationDiff;\n+\n+\t/* Limit the vblank to the maximum framerate requested. */\n+\tframeLengthMin = std::min<uint32_t>(1e9 / (mode_.line_length * maxFps),\n+\t\t\t\t\t    maxFrameLength);\n+\tvblank = std::max(vblank, frameLengthMin - mode_.height);\n+\n+\treturn vblank;\n }\n \n uint32_t CamHelperOv5647::GainCode(double gain) const\ndiff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp\nindex 104727ea..3a2cc16e 100644\n--- a/src/ipa/raspberrypi/raspberrypi.cpp\n+++ b/src/ipa/raspberrypi/raspberrypi.cpp\n@@ -136,6 +136,12 @@ private:\n \t/* LS table allocation passed in from the pipeline handler. */\n \tuint32_t lsTableHandle_;\n \tvoid *lsTable_;\n+\n+\t/*\n+\t * Have some defaults here, but eventually it should come from the\n+\t * application via a Request, or perhaps stream configuration.\n+\t */\n+\tstatic constexpr double fpsMax = 30.0;\n };\n \n int IPARPi::init(const IPASettings &settings)\n@@ -795,7 +801,7 @@ void IPARPi::applyAGC(const struct AgcStatus *agcStatus)\n \n \tint32_t gain_code = helper_->GainCode(agcStatus->analogue_gain);\n \tint32_t exposure_lines = helper_->ExposureLines(agcStatus->shutter_time);\n-\tint32_t vblanking = helper_->GetVBlanking(agcStatus->shutter_time);\n+\tint32_t vblanking = helper_->GetVBlanking(agcStatus->shutter_time, fpsMax);\n \n \tif (unicam_ctrls_.find(V4L2_CID_ANALOGUE_GAIN) == unicam_ctrls_.end()) {\n \t\tLOG(IPARPI, Error) << \"Can't find analogue gain control\";\n",
    "prefixes": [
        "libcamera-devel",
        "2/2"
    ]
}