Show a patch.

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

{
    "id": 11053,
    "url": "https://patchwork.libcamera.org/api/patches/11053/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/11053/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/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": "<20210129111616.1047483-4-naush@raspberrypi.com>",
    "date": "2021-01-29T11:16:14",
    "name": "[libcamera-devel,v4,3/5] ipa: raspberrypi: Limit the calculated vblank based on the sensor mode",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "4b05cfb624571a903be19bac5fa40993a9d79184",
    "submitter": {
        "id": 34,
        "url": "https://patchwork.libcamera.org/api/people/34/?format=api",
        "name": "Naushir Patuck",
        "email": "naush@raspberrypi.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/11053/mbox/",
    "series": [
        {
            "id": 1625,
            "url": "https://patchwork.libcamera.org/api/series/1625/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=1625",
            "date": "2021-01-29T11:16:11",
            "name": "Raspberry Pi: FrameDurations control refinements",
            "version": 4,
            "mbox": "https://patchwork.libcamera.org/series/1625/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/11053/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/11053/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 49E41BD808\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 29 Jan 2021 11:16:33 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 1769C683B2;\n\tFri, 29 Jan 2021 12:16:33 +0100 (CET)",
            "from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com\n\t[IPv6:2a00:1450:4864:20::42d])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id D4F7C683A2\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 29 Jan 2021 12:16:30 +0100 (CET)",
            "by mail-wr1-x42d.google.com with SMTP id a1so8464748wrq.6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 29 Jan 2021 03:16:30 -0800 (PST)",
            "from naushir-VirtualBox.patuck.local ([88.97.76.4])\n\tby smtp.gmail.com with ESMTPSA id\n\tf14sm11324007wre.69.2021.01.29.03.16.27\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tFri, 29 Jan 2021 03:16:28 -0800 (PST)"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=raspberrypi.com header.i=@raspberrypi.com\n\theader.b=\"qpHzXIAK\"; 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\t:mime-version:content-transfer-encoding;\n\tbh=JTTOH31m7p+bu3QZbZYeF2LaEMpxFjrTVsaqweEBDIo=;\n\tb=qpHzXIAKqHbxIEOukqmcnYJf96XztdOh2iYAeWN+Oh7pzDVSe8gmIBFMAzi9GrrZDh\n\tIfzrQHhsAcGF0ru0isgp4dLsAuyIl6xYDmh9JVOdrQTVaX36YfMYrmpmzG9B7ayBzA43\n\tUOZoNfWoPeVm2wmsncDj0SFkGfnUeihAMM46+sqfHFiqkMBcuyekd3dNk9Yi/PcpCzHk\n\t0gw9EIuaCwm0fWkgGQmJLpY4RQPUFCnImXIL4lToETPokXoRr7yzuoVk6fzV6CxKWXu7\n\t5k5mtV0XQqn5Q/D8vMyBaLnmTRQabNIoiM86aXu4rbciwYrKC6gxOcF1SnKe8JPZeQWK\n\tsY3g==",
        "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:mime-version:content-transfer-encoding;\n\tbh=JTTOH31m7p+bu3QZbZYeF2LaEMpxFjrTVsaqweEBDIo=;\n\tb=sV9xE2+BfzxIyynURpvDfSAAomID/PfiYTtrDLMzA/OB2K5zNQ1qzQyGN/YTUVCSOh\n\tciJfyBvuIc0Z2pbh2nlsIZ3R8juy1HjulNctaBBpKShtvmHY7cD1I8atozlr3Y5r/1ss\n\tS3WSaDitVGlgFPusSOEGwujzOWysPO/d5+vfkNqDvRjIe4R4fdrlS+rb/u/CVsFxPLsC\n\t4KD9JPLoAR0BqVHaSxf99lS7hvtcHzELedlBRlBasPNM/q1tzVQA0/OHCeOKY3dLs/Ao\n\t7Q8doHgpK412oZ/2hGjqs5p0S/LoMATvnT+BglCd0K/b99XzKGamWnIh118Ls8Q3GIlv\n\tjO2A==",
        "X-Gm-Message-State": "AOAM532wnq+xMOB7XEUsibY9NaAoApE9lS1Z7X9F7WbvdnciWfEmIayp\n\t2wp7/6bFhxA7rtU/WQNkQHMg67rdKyC0nRBt",
        "X-Google-Smtp-Source": "ABdhPJz1aDqKWFWXKqeGtv8+dJ4jlBJADZCpPsKDNbA+hyQED4EQFMVz1rmDpJjprZcLAtopoMLklg==",
        "X-Received": "by 2002:a5d:58c2:: with SMTP id o2mr3956475wrf.31.1611918990196; \n\tFri, 29 Jan 2021 03:16:30 -0800 (PST)",
        "From": "Naushir Patuck <naush@raspberrypi.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Fri, 29 Jan 2021 11:16:14 +0000",
        "Message-Id": "<20210129111616.1047483-4-naush@raspberrypi.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20210129111616.1047483-1-naush@raspberrypi.com>",
        "References": "<20210129111616.1047483-1-naush@raspberrypi.com>",
        "MIME-Version": "1.0",
        "Subject": "[libcamera-devel] [PATCH v4 3/5] ipa: raspberrypi: Limit the\n\tcalculated vblank based on the sensor mode",
        "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>",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "The existing framerate/vblank calculations did not account for the\nsensor mode limits. This commit extracts vblank limits from the sensor\nv4l2 controls, and stores it in the camera modes structure.\n\nExposure and vblank value calculations now use values clamped to the\nsensor mode limits. The libcamera::controls::FrameDurations metadata\nreturn values now reflect the minimum and maximum after clamping.\n\nSigned-off-by: Naushir Patuck <naush@raspberrypi.com>\nReviewed-by: David Plowman <david.plowman@raspberrypi.com>\nReviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n---\n src/ipa/raspberrypi/cam_helper.cpp           | 16 +++----\n src/ipa/raspberrypi/cam_helper.hpp           |  5 +-\n src/ipa/raspberrypi/cam_helper_imx219.cpp    |  6 +--\n src/ipa/raspberrypi/cam_helper_imx477.cpp    |  4 +-\n src/ipa/raspberrypi/cam_helper_ov5647.cpp    |  4 +-\n src/ipa/raspberrypi/controller/camera_mode.h |  2 +\n src/ipa/raspberrypi/raspberrypi.cpp          | 49 +++++++++++++-------\n 7 files changed, 47 insertions(+), 39 deletions(-)",
    "diff": "diff --git a/src/ipa/raspberrypi/cam_helper.cpp b/src/ipa/raspberrypi/cam_helper.cpp\nindex b7b8faf09c69..93d1b7b0296a 100644\n--- a/src/ipa/raspberrypi/cam_helper.cpp\n+++ b/src/ipa/raspberrypi/cam_helper.cpp\n@@ -34,9 +34,8 @@ CamHelper *CamHelper::Create(std::string const &cam_name)\n \treturn nullptr;\n }\n \n-CamHelper::CamHelper(MdParser *parser, unsigned int maxFrameLength,\n-\t\t     unsigned int frameIntegrationDiff)\n-\t: parser_(parser), initialized_(false), maxFrameLength_(maxFrameLength),\n+CamHelper::CamHelper(MdParser *parser, unsigned int frameIntegrationDiff)\n+\t: parser_(parser), initialized_(false),\n \t  frameIntegrationDiff_(frameIntegrationDiff)\n {\n }\n@@ -67,13 +66,12 @@ uint32_t CamHelper::GetVBlanking(double &exposure, double minFrameDuration,\n \tassert(initialized_);\n \n \t/*\n-\t * Clamp frame length by the frame duration range and the maximum allowable\n-\t * value in the sensor, given by maxFrameLength_.\n+\t * minFrameDuration and maxFrameDuration are clamped by the caller\n+\t * based on the limits for the active sensor mode.\n \t */\n-\tframeLengthMin = std::clamp<uint32_t>(1e3 * minFrameDuration / mode_.line_length,\n-\t\t\t\t\t      mode_.height, maxFrameLength_);\n-\tframeLengthMax = std::clamp<uint32_t>(1e3 * maxFrameDuration / mode_.line_length,\n-\t\t\t\t\t      mode_.height, maxFrameLength_);\n+\tframeLengthMin = 1e3 * minFrameDuration / mode_.line_length;\n+\tframeLengthMax = 1e3 * maxFrameDuration / mode_.line_length;\n+\n \t/*\n \t * Limit the exposure to the maximum frame duration requested, and\n \t * re-calculate if it has been clipped.\ndiff --git a/src/ipa/raspberrypi/cam_helper.hpp b/src/ipa/raspberrypi/cam_helper.hpp\nindex b1739a57e342..14d70112cb62 100644\n--- a/src/ipa/raspberrypi/cam_helper.hpp\n+++ b/src/ipa/raspberrypi/cam_helper.hpp\n@@ -62,8 +62,7 @@ class CamHelper\n {\n public:\n \tstatic CamHelper *Create(std::string const &cam_name);\n-\tCamHelper(MdParser *parser, unsigned int maxFrameLength,\n-\t\t  unsigned int frameIntegrationDiff);\n+\tCamHelper(MdParser *parser, unsigned int frameIntegrationDiff);\n \tvirtual ~CamHelper();\n \tvoid SetCameraMode(const CameraMode &mode);\n \tMdParser &Parser() const { return *parser_; }\n@@ -86,8 +85,6 @@ protected:\n \n private:\n \tbool initialized_;\n-\t/* Largest possible frame length, in units of lines. */\n-\tunsigned int maxFrameLength_;\n \t/*\n \t * Smallest difference between the frame length and integration time,\n \t * in units of lines.\ndiff --git a/src/ipa/raspberrypi/cam_helper_imx219.cpp b/src/ipa/raspberrypi/cam_helper_imx219.cpp\nindex 8688ec091c44..95b8e698fe3b 100644\n--- a/src/ipa/raspberrypi/cam_helper_imx219.cpp\n+++ b/src/ipa/raspberrypi/cam_helper_imx219.cpp\n@@ -56,15 +56,13 @@ private:\n \t * in units of lines.\n \t */\n \tstatic constexpr int frameIntegrationDiff = 4;\n-\t/* Largest possible frame length, in units of lines. */\n-\tstatic constexpr int maxFrameLength = 0xffff;\n };\n \n CamHelperImx219::CamHelperImx219()\n #if ENABLE_EMBEDDED_DATA\n-\t: CamHelper(new MdParserImx219(), maxFrameLength, frameIntegrationDiff)\n+\t: CamHelper(new MdParserImx219(), frameIntegrationDiff)\n #else\n-\t: CamHelper(new MdParserRPi(), maxFrameLength, frameIntegrationDiff)\n+\t: CamHelper(new MdParserRPi(), frameIntegrationDiff)\n #endif\n {\n }\ndiff --git a/src/ipa/raspberrypi/cam_helper_imx477.cpp b/src/ipa/raspberrypi/cam_helper_imx477.cpp\nindex 5396131003f1..eaa7be16d20e 100644\n--- a/src/ipa/raspberrypi/cam_helper_imx477.cpp\n+++ b/src/ipa/raspberrypi/cam_helper_imx477.cpp\n@@ -45,12 +45,10 @@ private:\n \t * in units of lines.\n \t */\n \tstatic constexpr int frameIntegrationDiff = 22;\n-\t/* Largest possible frame length, in units of lines. */\n-\tstatic constexpr int maxFrameLength = 0xffdc;\n };\n \n CamHelperImx477::CamHelperImx477()\n-\t: CamHelper(new MdParserImx477(), maxFrameLength, frameIntegrationDiff)\n+\t: CamHelper(new MdParserImx477(), frameIntegrationDiff)\n {\n }\n \ndiff --git a/src/ipa/raspberrypi/cam_helper_ov5647.cpp b/src/ipa/raspberrypi/cam_helper_ov5647.cpp\nindex 2bd8a754f133..a7f417324048 100644\n--- a/src/ipa/raspberrypi/cam_helper_ov5647.cpp\n+++ b/src/ipa/raspberrypi/cam_helper_ov5647.cpp\n@@ -30,8 +30,6 @@ private:\n \t * in units of lines.\n \t */\n \tstatic constexpr int frameIntegrationDiff = 4;\n-\t/* Largest possible frame length, in units of lines. */\n-\tstatic constexpr int maxFrameLength = 0xffff;\n };\n \n /*\n@@ -40,7 +38,7 @@ private:\n  */\n \n CamHelperOv5647::CamHelperOv5647()\n-\t: CamHelper(new MdParserRPi(), maxFrameLength, frameIntegrationDiff)\n+\t: CamHelper(new MdParserRPi(), frameIntegrationDiff)\n {\n }\n \ndiff --git a/src/ipa/raspberrypi/controller/camera_mode.h b/src/ipa/raspberrypi/controller/camera_mode.h\nindex 920f11beb0b0..256438c931d9 100644\n--- a/src/ipa/raspberrypi/controller/camera_mode.h\n+++ b/src/ipa/raspberrypi/controller/camera_mode.h\n@@ -37,6 +37,8 @@ struct CameraMode {\n \tdouble line_length;\n \t// any camera transform *not* reflected already in the camera tuning\n \tlibcamera::Transform transform;\n+\t// minimum and maximum fame lengths in units of lines\n+\tuint32_t min_frame_length, max_frame_length;\n };\n \n #ifdef __cplusplus\ndiff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp\nindex 5ccc7a6551f5..e4911b734e20 100644\n--- a/src/ipa/raspberrypi/raspberrypi.cpp\n+++ b/src/ipa/raspberrypi/raspberrypi.cpp\n@@ -102,6 +102,7 @@ private:\n \tvoid reportMetadata();\n \tbool parseEmbeddedData(unsigned int bufferId, struct DeviceStatus &deviceStatus);\n \tvoid processStats(unsigned int bufferId);\n+\tvoid applyFrameDurations(double minFrameDuration, double maxFrameDuration);\n \tvoid applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls);\n \tvoid applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls);\n \tvoid applyDG(const struct AgcStatus *dgStatus, ControlList &ctrls);\n@@ -279,6 +280,13 @@ void IPARPi::setMode(const CameraSensorInfo &sensorInfo)\n \t * the line length in pixels and the pixel rate.\n \t */\n \tmode_.line_length = 1e9 * sensorInfo.lineLength / sensorInfo.pixelRate;\n+\n+\t/*\n+\t * Set the frame length limits for the mode to ensure exposure and\n+\t * framerate calculations are clipped appropriately.\n+\t */\n+\tmode_.min_frame_length = sensorInfo.minFrameLength;\n+\tmode_.max_frame_length = sensorInfo.maxFrameLength;\n }\n \n void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n@@ -384,8 +392,8 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n \t\tcontroller_.Initialise();\n \t\tcontrollerInit_ = true;\n \n-\t\tminFrameDuration_ = defaultMinFrameDuration;\n-\t\tmaxFrameDuration_ = defaultMaxFrameDuration;\n+\t\t/* Supply initial values for frame durations. */\n+\t\tapplyFrameDurations(defaultMinFrameDuration, defaultMaxFrameDuration);\n \n \t\t/* Supply initial values for gain and exposure. */\n \t\tControlList ctrls(sensorCtrls_);\n@@ -819,20 +827,7 @@ void IPARPi::queueRequest(const ControlList &controls)\n \n \t\tcase controls::FRAME_DURATIONS: {\n \t\t\tauto frameDurations = ctrl.second.get<Span<const int64_t>>();\n-\n-\t\t\t/* This will be applied once AGC recalculations occur. */\n-\t\t\tminFrameDuration_ = frameDurations[0] ? frameDurations[0] : defaultMinFrameDuration;\n-\t\t\tmaxFrameDuration_ = frameDurations[1] ? frameDurations[1] : defaultMaxFrameDuration;\n-\t\t\tmaxFrameDuration_ = std::max(maxFrameDuration_, minFrameDuration_);\n-\n-\t\t\t/*\n-\t\t\t * \\todo The values returned in the metadata below must be\n-\t\t\t * correctly clipped by what the sensor mode supports and\n-\t\t\t * what the AGC exposure mode or manual shutter speed limits\n-\t\t\t */\n-\t\t\tlibcameraMetadata_.set(controls::FrameDurations,\n-\t\t\t\t\t       { static_cast<int64_t>(minFrameDuration_),\n-\t\t\t\t\t\t static_cast<int64_t>(maxFrameDuration_) });\n+\t\t\tapplyFrameDurations(frameDurations[0], frameDurations[1]);\n \t\t\tbreak;\n \t\t}\n \n@@ -991,6 +986,28 @@ void IPARPi::applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls)\n \t\t  static_cast<int32_t>(awbStatus->gain_b * 1000));\n }\n \n+void IPARPi::applyFrameDurations(double minFrameDuration, double maxFrameDuration)\n+{\n+\tconst double minSensorFrameDuration = 1e-3 * mode_.min_frame_length * mode_.line_length;\n+\tconst double maxSensorFrameDuration = 1e-3 * mode_.max_frame_length * mode_.line_length;\n+\n+\t/*\n+\t * This will only be applied once AGC recalculations occur.\n+\t * The values may be clamped based on the sensor mode capabilities as well.\n+\t */\n+\tminFrameDuration_ = minFrameDuration ? minFrameDuration : defaultMaxFrameDuration;\n+\tmaxFrameDuration_ = maxFrameDuration ? maxFrameDuration : defaultMinFrameDuration;\n+\tminFrameDuration_ = std::clamp(minFrameDuration_,\n+\t\t\t\t       minSensorFrameDuration, maxSensorFrameDuration);\n+\tmaxFrameDuration_ = std::clamp(maxFrameDuration_,\n+\t\t\t\t       minSensorFrameDuration, maxSensorFrameDuration);\n+\n+\t/* Return the validated limits out though metadata. */\n+\tlibcameraMetadata_.set(controls::FrameDurations,\n+\t\t\t       { static_cast<int64_t>(minFrameDuration_),\n+\t\t\t\t static_cast<int64_t>(maxFrameDuration_) });\n+}\n+\n void IPARPi::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls)\n {\n \tint32_t gainCode = helper_->GainCode(agcStatus->analogue_gain);\n",
    "prefixes": [
        "libcamera-devel",
        "v4",
        "3/5"
    ]
}