Show a patch.

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

{
    "id": 22073,
    "url": "https://patchwork.libcamera.org/api/patches/22073/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/22073/",
    "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": "<20241125151430.2437285-7-stefan.klug@ideasonboard.com>",
    "date": "2024-11-25T15:14:15",
    "name": "[v2,6/8] libcamera: converter_v4l2_m2m: Improve crop bounds support",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "9e793d8e058839fb22ef4b1006a063be5534e480",
    "submitter": {
        "id": 184,
        "url": "https://patchwork.libcamera.org/api/people/184/?format=api",
        "name": "Stefan Klug",
        "email": "stefan.klug@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/22073/mbox/",
    "series": [
        {
            "id": 4818,
            "url": "https://patchwork.libcamera.org/api/series/4818/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4818",
            "date": "2024-11-25T15:14:09",
            "name": "rkisp1: Fix aspect ratio and ScalerCrop",
            "version": 2,
            "mbox": "https://patchwork.libcamera.org/series/4818/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/22073/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/22073/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 26AC2C32A3\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 25 Nov 2024 15:14:54 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id B1F0966034;\n\tMon, 25 Nov 2024 16:14:53 +0100 (CET)",
            "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 59A0E65FE3\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 25 Nov 2024 16:14:51 +0100 (CET)",
            "from ideasonboard.com (unknown\n\t[IPv6:2a00:6020:448c:6c00:4cf:a935:de6f:a329])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id A3A7EE1F;\n\tMon, 25 Nov 2024 16:14:29 +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=\"qTFXaew5\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1732547669;\n\tbh=knniJ0aUE/TXqU61yO0r18bhGE24rQ3H6mBXI0cxkRk=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=qTFXaew5HHak5GN4nshvt7rhOyghHUTjN3I5245cHn4v30MEeav7jwbqEaqjGBsH6\n\tQq93JML6jv4LbxKy7jHoK0AfwEj/XfVU4SJ0ofVLvLvTMcDkjLnsZtJs4JkmbugYgc\n\tYrinfK838lSs+OT4nGdoDnLn0TkgEggE+bvv4heA=",
        "From": "Stefan Klug <stefan.klug@ideasonboard.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Cc": "Stefan Klug <stefan.klug@ideasonboard.com>",
        "Subject": "[PATCH v2 6/8] libcamera: converter_v4l2_m2m: Improve crop bounds\n\tsupport",
        "Date": "Mon, 25 Nov 2024 16:14:15 +0100",
        "Message-ID": "<20241125151430.2437285-7-stefan.klug@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.43.0",
        "In-Reply-To": "<20241125151430.2437285-1-stefan.klug@ideasonboard.com>",
        "References": "<20241125151430.2437285-1-stefan.klug@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": "When a converter (dw100 on imx8mp in this case) is used in a pipeline,\nthe ScalerCrop control get's created at createCamera() time. As this is\nbefore configure(), no streams were configured on the converter and the\nstream specific crop bounds are not known. Extend the converter class to\nreport the default crop bounds in case the provided stream is not found.\n\nSigned-off-by: Stefan Klug <stefan.klug@ideasonboard.com>\n---\nChanges in v2:\n- Added this patch\n---\n .../internal/converter/converter_v4l2_m2m.h   |   1 +\n src/libcamera/converter.cpp                   |   3 +\n .../converter/converter_v4l2_m2m.cpp          | 113 +++++++++---------\n 3 files changed, 59 insertions(+), 58 deletions(-)",
    "diff": "diff --git a/include/libcamera/internal/converter/converter_v4l2_m2m.h b/include/libcamera/internal/converter/converter_v4l2_m2m.h\nindex 0bc0d053e2c4..a5286166f574 100644\n--- a/include/libcamera/internal/converter/converter_v4l2_m2m.h\n+++ b/include/libcamera/internal/converter/converter_v4l2_m2m.h\n@@ -105,6 +105,7 @@ private:\n \n \tstd::map<const Stream *, std::unique_ptr<V4L2M2MStream>> streams_;\n \tstd::map<FrameBuffer *, unsigned int> queue_;\n+\tstd::pair<Rectangle, Rectangle> inputCropBounds_;\n };\n \n } /* namespace libcamera */\ndiff --git a/src/libcamera/converter.cpp b/src/libcamera/converter.cpp\nindex 945f2527b96a..d4b5e5260e02 100644\n--- a/src/libcamera/converter.cpp\n+++ b/src/libcamera/converter.cpp\n@@ -195,6 +195,9 @@ Converter::~Converter()\n  * this function should be called after the \\a stream has been configured using\n  * configure().\n  *\n+ * When called with an invalid \\a stream, the function returns the default crop\n+ * bounds of the converter.\n+ *\n  * \\return A pair containing the minimum and maximum crop bound in that order\n  */\n \ndiff --git a/src/libcamera/converter/converter_v4l2_m2m.cpp b/src/libcamera/converter/converter_v4l2_m2m.cpp\nindex d63ef2f8028f..bd7e5cce600d 100644\n--- a/src/libcamera/converter/converter_v4l2_m2m.cpp\n+++ b/src/libcamera/converter/converter_v4l2_m2m.cpp\n@@ -30,6 +30,52 @@ namespace libcamera {\n \n LOG_DECLARE_CATEGORY(Converter)\n \n+namespace {\n+\n+int getCropBounds(V4L2VideoDevice *device, Rectangle &minCrop,\n+\t\t  Rectangle &maxCrop)\n+{\n+\tRectangle minC;\n+\tRectangle maxC;\n+\n+\t/* Find crop bounds */\n+\tminC.width = 1;\n+\tminC.height = 1;\n+\tmaxC.width = UINT_MAX;\n+\tmaxC.height = UINT_MAX;\n+\n+\tint ret = device->setSelection(V4L2_SEL_TGT_CROP, &minC);\n+\tif (ret) {\n+\t\tLOG(Converter, Error)\n+\t\t\t<< \"Could not query minimum selection crop: \"\n+\t\t\t<< strerror(-ret);\n+\t\treturn ret;\n+\t}\n+\n+\tret = device->getSelection(V4L2_SEL_TGT_CROP_BOUNDS, &maxC);\n+\tif (ret) {\n+\t\tLOG(Converter, Error)\n+\t\t\t<< \"Could not query maximum selection crop: \"\n+\t\t\t<< strerror(-ret);\n+\t\treturn ret;\n+\t}\n+\n+\t/* Reset the crop to its maximum */\n+\tret = device->setSelection(V4L2_SEL_TGT_CROP, &maxC);\n+\tif (ret) {\n+\t\tLOG(Converter, Error)\n+\t\t\t<< \"Could not reset selection crop: \"\n+\t\t\t<< strerror(-ret);\n+\t\treturn ret;\n+\t}\n+\n+\tminCrop = minC;\n+\tmaxCrop = maxC;\n+\treturn 0;\n+}\n+\n+} /* namespace */\n+\n /* -----------------------------------------------------------------------------\n  * V4L2M2MConverter::V4L2M2MStream\n  */\n@@ -98,41 +144,10 @@ int V4L2M2MConverter::V4L2M2MStream::configure(const StreamConfiguration &inputC\n \toutputBufferCount_ = outputCfg.bufferCount;\n \n \tif (converter_->features() & Feature::InputCrop) {\n-\t\tRectangle minCrop;\n-\t\tRectangle maxCrop;\n-\n-\t\t/* Find crop bounds */\n-\t\tminCrop.width = 1;\n-\t\tminCrop.height = 1;\n-\t\tmaxCrop.width = UINT_MAX;\n-\t\tmaxCrop.height = UINT_MAX;\n-\n-\t\tret = setInputSelection(V4L2_SEL_TGT_CROP, &minCrop);\n-\t\tif (ret) {\n-\t\t\tLOG(Converter, Error)\n-\t\t\t\t<< \"Could not query minimum selection crop: \"\n-\t\t\t\t<< strerror(-ret);\n-\t\t\treturn ret;\n-\t\t}\n-\n-\t\tret = getInputSelection(V4L2_SEL_TGT_CROP_BOUNDS, &maxCrop);\n-\t\tif (ret) {\n-\t\t\tLOG(Converter, Error)\n-\t\t\t\t<< \"Could not query maximum selection crop: \"\n-\t\t\t\t<< strerror(-ret);\n-\t\t\treturn ret;\n-\t\t}\n-\n-\t\t/* Reset the crop to its maximum */\n-\t\tret = setInputSelection(V4L2_SEL_TGT_CROP, &maxCrop);\n-\t\tif (ret) {\n-\t\t\tLOG(Converter, Error)\n-\t\t\t\t<< \"Could not reset selection crop: \"\n-\t\t\t\t<< strerror(-ret);\n+\t\tret = getCropBounds(m2m_->output(), inputCropBounds_.first,\n+\t\t\t\t    inputCropBounds_.second);\n+\t\tif (ret)\n \t\t\treturn ret;\n-\t\t}\n-\n-\t\tinputCropBounds_ = { minCrop, maxCrop };\n \t}\n \n \treturn 0;\n@@ -258,27 +273,9 @@ V4L2M2MConverter::V4L2M2MConverter(MediaDevice *media)\n \t\treturn;\n \t}\n \n-\t/* Discover Feature::InputCrop */\n-\tRectangle maxCrop;\n-\tmaxCrop.width = UINT_MAX;\n-\tmaxCrop.height = UINT_MAX;\n-\n-\tret = m2m_->output()->setSelection(V4L2_SEL_TGT_CROP, &maxCrop);\n-\tif (ret)\n-\t\treturn;\n-\n-\t/*\n-\t * Rectangles for cropping targets are defined even if the device\n-\t * does not support cropping. Their sizes and positions will be\n-\t * fixed in such cases.\n-\t *\n-\t * Set and inspect a crop equivalent to half of the maximum crop\n-\t * returned earlier. Use this to determine whether the crop on\n-\t * input is really supported.\n-\t */\n-\tRectangle halfCrop(maxCrop.size() / 2);\n-\tret = m2m_->output()->setSelection(V4L2_SEL_TGT_CROP, &halfCrop);\n-\tif (!ret && halfCrop != maxCrop) {\n+\tret = getCropBounds(m2m_->output(), inputCropBounds_.first,\n+\t\t\t    inputCropBounds_.second);\n+\tif (!ret && inputCropBounds_.first != inputCropBounds_.second) {\n \t\tfeatures_ |= Feature::InputCrop;\n \n \t\tLOG(Converter, Info)\n@@ -477,10 +474,10 @@ std::pair<Rectangle, Rectangle>\n V4L2M2MConverter::inputCropBounds(const Stream *stream)\n {\n \tauto iter = streams_.find(stream);\n-\tif (iter == streams_.end())\n-\t\treturn {};\n+\tif (iter != streams_.end())\n+\t\treturn iter->second->inputCropBounds();\n \n-\treturn iter->second->inputCropBounds();\n+\treturn inputCropBounds_;\n }\n \n /**\n",
    "prefixes": [
        "v2",
        "6/8"
    ]
}