Show a patch.

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

{
    "id": 19726,
    "url": "https://patchwork.libcamera.org/api/patches/19726/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/19726/",
    "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": "<20240315001613.2033-8-laurent.pinchart@ideasonboard.com>",
    "date": "2024-03-15T00:16:06",
    "name": "[v2,07/14] libcamera: v4l2_subdevice: Add stream support to get/set functions",
    "commit_ref": "0d2ad0cd8424e1b418cbb753bae100efc1b3d669",
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "3d43455bdcbf7aa68c3c257e58facb4542a21646",
    "submitter": {
        "id": 2,
        "url": "https://patchwork.libcamera.org/api/people/2/?format=api",
        "name": "Laurent Pinchart",
        "email": "laurent.pinchart@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/19726/mbox/",
    "series": [
        {
            "id": 4226,
            "url": "https://patchwork.libcamera.org/api/series/4226/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4226",
            "date": "2024-03-15T00:15:59",
            "name": "libcamera: Prepare for new camera sensor class",
            "version": 2,
            "mbox": "https://patchwork.libcamera.org/series/4226/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/19726/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/19726/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 20FEFC3273\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 15 Mar 2024 00:16:34 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id A0FA962CA8;\n\tFri, 15 Mar 2024 01:16:33 +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 3098562C8F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 15 Mar 2024 01:16:26 +0100 (CET)",
            "from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi\n\t[81.175.209.231])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 706F6A9A\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 15 Mar 2024 01:16:02 +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=\"ocGps1D8\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1710461762;\n\tbh=kxUI0S3ZMKw94ficFFWV0BmYIt3rsPshVpVXItN6sdU=;\n\th=From:To:Subject:Date:In-Reply-To:References:From;\n\tb=ocGps1D8a/OJjWoiOj6EcFLAgPNnRO9NuQsXHBZZUul0uk6OxNimbwoFSuw0AxBgD\n\tKGBi+OSSZ4MykbMnQy7t4q9x0sbfD47xMzEw9lSNC/IbKGLFmkzxMYgkU5+OoJ42cU\n\tS5hRw47eYAm5p0RDR0ZzuoY1Zeb7MqwV1dNL0YqY=",
        "From": "Laurent Pinchart <laurent.pinchart@ideasonboard.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Subject": "[PATCH v2 07/14] libcamera: v4l2_subdevice: Add stream support to\n\tget/set functions",
        "Date": "Fri, 15 Mar 2024 02:16:06 +0200",
        "Message-ID": "<20240315001613.2033-8-laurent.pinchart@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.43.2",
        "In-Reply-To": "<20240315001613.2033-1-laurent.pinchart@ideasonboard.com>",
        "References": "<20240315001613.2033-1-laurent.pinchart@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": "Extend the V4L2Subdevice API with stream support for the functions that\nget and set formats and selection rectangles. Add a Stream structure to\nidentify a subdev pad and stream, and use it to extend the V4L2Subdevice\nfunctions that get and set formats and selection rectangles with stream\nsupport.\n\nTo preserve the existing pad-based API, implement overloaded functions\nthat wrap the new stream-based API. This allows callers that are not\nstream-aware to use a simpler pad-based API, instead of having to\nexplicitly set the stream number to 0 in all API calls.\n\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\nReviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n---\nChanges since combined RFC:\n\n- Fix indentation in comments\n- Use operator<<(Stream) everywhere\n\nChanges since v1:\n\n- Drop incorrect comment change\n- Use operator<<(Stream)\n- Add comparison operators\n---\n include/libcamera/internal/v4l2_subdevice.h |  58 ++++-\n src/libcamera/v4l2_subdevice.cpp            | 248 +++++++++++++++-----\n 2 files changed, 238 insertions(+), 68 deletions(-)",
    "diff": "diff --git a/include/libcamera/internal/v4l2_subdevice.h b/include/libcamera/internal/v4l2_subdevice.h\nindex 1115cfa55594..6cd36730371a 100644\n--- a/include/libcamera/internal/v4l2_subdevice.h\n+++ b/include/libcamera/internal/v4l2_subdevice.h\n@@ -80,6 +80,21 @@ public:\n \t\tActiveFormat = V4L2_SUBDEV_FORMAT_ACTIVE,\n \t};\n \n+\tstruct Stream {\n+\t\tStream()\n+\t\t\t: pad(0), stream(0)\n+\t\t{\n+\t\t}\n+\n+\t\tStream(unsigned int p, unsigned int s)\n+\t\t\t: pad(p), stream(s)\n+\t\t{\n+\t\t}\n+\n+\t\tunsigned int pad;\n+\t\tunsigned int stream;\n+\t};\n+\n \tclass Routing : public std::vector<struct v4l2_subdev_route>\n \t{\n \tpublic:\n@@ -93,17 +108,39 @@ public:\n \n \tconst MediaEntity *entity() const { return entity_; }\n \n-\tint getSelection(unsigned int pad, unsigned int target,\n+\tint getSelection(const Stream &stream, unsigned int target,\n \t\t\t Rectangle *rect);\n-\tint setSelection(unsigned int pad, unsigned int target,\n+\tint getSelection(unsigned int pad, unsigned int target, Rectangle *rect)\n+\t{\n+\t\treturn getSelection({ pad, 0 }, target, rect);\n+\t}\n+\tint setSelection(const Stream &stream, unsigned int target,\n \t\t\t Rectangle *rect);\n+\tint setSelection(unsigned int pad, unsigned int target, Rectangle *rect)\n+\t{\n+\t\treturn setSelection({ pad, 0 }, target, rect);\n+\t}\n \n-\tFormats formats(unsigned int pad);\n+\tFormats formats(const Stream &stream);\n+\tFormats formats(unsigned int pad)\n+\t{\n+\t\treturn formats({ pad, 0 });\n+\t}\n \n+\tint getFormat(const Stream &stream, V4L2SubdeviceFormat *format,\n+\t\t      Whence whence = ActiveFormat);\n \tint getFormat(unsigned int pad, V4L2SubdeviceFormat *format,\n+\t\t      Whence whence = ActiveFormat)\n+\t{\n+\t\treturn getFormat({ pad, 0 }, format, whence);\n+\t}\n+\tint setFormat(const Stream &stream, V4L2SubdeviceFormat *format,\n \t\t      Whence whence = ActiveFormat);\n \tint setFormat(unsigned int pad, V4L2SubdeviceFormat *format,\n-\t\t      Whence whence = ActiveFormat);\n+\t\t      Whence whence = ActiveFormat)\n+\t{\n+\t\treturn setFormat({ pad, 0 }, format, whence);\n+\t}\n \n \tint getRouting(Routing *routing, Whence whence = ActiveFormat);\n \tint setRouting(Routing *routing, Whence whence = ActiveFormat);\n@@ -123,8 +160,8 @@ private:\n \tstd::optional<ColorSpace>\n \ttoColorSpace(const v4l2_mbus_framefmt &format) const;\n \n-\tstd::vector<unsigned int> enumPadCodes(unsigned int pad);\n-\tstd::vector<SizeRange> enumPadSizes(unsigned int pad,\n+\tstd::vector<unsigned int> enumPadCodes(const Stream &stream);\n+\tstd::vector<SizeRange> enumPadSizes(const Stream &stream,\n \t\t\t\t\t    unsigned int code);\n \n \tconst MediaEntity *entity_;\n@@ -133,4 +170,13 @@ private:\n \tstruct V4L2SubdeviceCapability caps_;\n };\n \n+bool operator==(const V4L2Subdevice::Stream &lhs, const V4L2Subdevice::Stream &rhs);\n+static inline bool operator!=(const V4L2Subdevice::Stream &lhs,\n+\t\t\t      const V4L2Subdevice::Stream &rhs)\n+{\n+\treturn !(lhs == rhs);\n+}\n+\n+std::ostream &operator<<(std::ostream &out, const V4L2Subdevice::Stream &stream);\n+\n } /* namespace libcamera */\ndiff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp\nindex 66da1edbf542..cc079425bb16 100644\n--- a/src/libcamera/v4l2_subdevice.cpp\n+++ b/src/libcamera/v4l2_subdevice.cpp\n@@ -842,6 +842,62 @@ std::ostream &operator<<(std::ostream &out, const V4L2SubdeviceFormat &f)\n  * \\brief The format operation applies to TRY formats\n  */\n \n+/**\n+ * \\class V4L2Subdevice::Stream\n+ * \\brief V4L2 subdevice stream\n+ *\n+ * This class identifies a subdev stream, by bundling the pad number with the\n+ * stream number. It is used in all stream-aware functions of the V4L2Subdevice\n+ * class to identify the stream the functions operate on.\n+ *\n+ * \\var V4L2Subdevice::Stream::pad\n+ * \\brief The 0-indexed pad number\n+ *\n+ * \\var V4L2Subdevice::Stream::stream\n+ * \\brief The stream number\n+ */\n+\n+/**\n+ * \\fn V4L2Subdevice::Stream::Stream()\n+ * \\brief Construct a Stream with pad and stream set to 0\n+ */\n+\n+/**\n+ * \\fn V4L2Subdevice::Stream::Stream(unsigned int pad, unsigned int stream)\n+ * \\brief Construct a Stream with a given \\a pad and \\a stream number\n+ * \\param[in] pad The indexed pad number\n+ * \\param[in] stream The stream number\n+ */\n+\n+/**\n+ * \\brief Compare streams for equality\n+ * \\return True if the two streams are equal, false otherwise\n+ */\n+bool operator==(const V4L2Subdevice::Stream &lhs, const V4L2Subdevice::Stream &rhs)\n+{\n+\treturn lhs.pad == rhs.pad && lhs.stream == rhs.stream;\n+}\n+\n+/**\n+ * \\fn bool operator!=(const V4L2Subdevice::Stream &lhs, const V4L2Subdevice::Stream &rhs)\n+ * \\brief Compare streams for inequality\n+ * \\return True if the two streams are not equal, false otherwise\n+ */\n+\n+/**\n+ * \\brief Insert a text representation of a V4L2Subdevice::Stream into an\n+ * output stream\n+ * \\param[in] out The output stream\n+ * \\param[in] stream The V4L2Subdevice::Stream\n+ * \\return The output stream \\a out\n+ */\n+std::ostream &operator<<(std::ostream &out, const V4L2Subdevice::Stream &stream)\n+{\n+\tout << stream.pad << \"/\" << stream.stream;\n+\n+\treturn out;\n+}\n+\n /**\n  * \\class V4L2Subdevice::Routing\n  * \\brief V4L2 subdevice routing table\n@@ -933,7 +989,7 @@ int V4L2Subdevice::open()\n \n /**\n  * \\brief Get selection rectangle \\a rect for \\a target\n- * \\param[in] pad The 0-indexed pad number the rectangle is retrieved from\n+ * \\param[in] stream The stream the rectangle is retrieved from\n  * \\param[in] target The selection target defined by the V4L2_SEL_TGT_* flags\n  * \\param[out] rect The retrieved selection rectangle\n  *\n@@ -941,13 +997,14 @@ int V4L2Subdevice::open()\n  *\n  * \\return 0 on success or a negative error code otherwise\n  */\n-int V4L2Subdevice::getSelection(unsigned int pad, unsigned int target,\n+int V4L2Subdevice::getSelection(const Stream &stream, unsigned int target,\n \t\t\t\tRectangle *rect)\n {\n \tstruct v4l2_subdev_selection sel = {};\n \n \tsel.which = V4L2_SUBDEV_FORMAT_ACTIVE;\n-\tsel.pad = pad;\n+\tsel.pad = stream.pad;\n+\tsel.stream = stream.stream;\n \tsel.target = target;\n \tsel.flags = 0;\n \n@@ -955,7 +1012,7 @@ int V4L2Subdevice::getSelection(unsigned int pad, unsigned int target,\n \tif (ret < 0) {\n \t\tLOG(V4L2, Error)\n \t\t\t<< \"Unable to get rectangle \" << target << \" on pad \"\n-\t\t\t<< pad << \": \" << strerror(-ret);\n+\t\t\t<< stream << \": \" << strerror(-ret);\n \t\treturn ret;\n \t}\n \n@@ -967,9 +1024,20 @@ int V4L2Subdevice::getSelection(unsigned int pad, unsigned int target,\n \treturn 0;\n }\n \n+/**\n+ * \\fn V4L2Subdevice::getSelection(unsigned int pad, unsigned int target,\n+ * Rectangle *rect)\n+ * \\brief Get selection rectangle \\a rect for \\a target\n+ * \\param[in] pad The 0-indexed pad number the rectangle is retrieved from\n+ * \\param[in] target The selection target defined by the V4L2_SEL_TGT_* flags\n+ * \\param[out] rect The retrieved selection rectangle\n+ *\n+ * \\return 0 on success or a negative error code otherwise\n+ */\n+\n /**\n  * \\brief Set selection rectangle \\a rect for \\a target\n- * \\param[in] pad The 0-indexed pad number the rectangle is to be applied to\n+ * \\param[in] stream The stream the rectangle is to be applied to\n  * \\param[in] target The selection target defined by the V4L2_SEL_TGT_* flags\n  * \\param[inout] rect The selection rectangle to be applied\n  *\n@@ -977,13 +1045,14 @@ int V4L2Subdevice::getSelection(unsigned int pad, unsigned int target,\n  *\n  * \\return 0 on success or a negative error code otherwise\n  */\n-int V4L2Subdevice::setSelection(unsigned int pad, unsigned int target,\n+int V4L2Subdevice::setSelection(const Stream &stream, unsigned int target,\n \t\t\t\tRectangle *rect)\n {\n \tstruct v4l2_subdev_selection sel = {};\n \n \tsel.which = V4L2_SUBDEV_FORMAT_ACTIVE;\n-\tsel.pad = pad;\n+\tsel.pad = stream.pad;\n+\tsel.stream = stream.stream;\n \tsel.target = target;\n \tsel.flags = 0;\n \n@@ -996,7 +1065,7 @@ int V4L2Subdevice::setSelection(unsigned int pad, unsigned int target,\n \tif (ret < 0) {\n \t\tLOG(V4L2, Error)\n \t\t\t<< \"Unable to set rectangle \" << target << \" on pad \"\n-\t\t\t<< pad << \": \" << strerror(-ret);\n+\t\t\t<< stream << \": \" << strerror(-ret);\n \t\treturn ret;\n \t}\n \n@@ -1007,26 +1076,40 @@ int V4L2Subdevice::setSelection(unsigned int pad, unsigned int target,\n \n \treturn 0;\n }\n+\n /**\n- * \\brief Enumerate all media bus codes and frame sizes on a \\a pad\n- * \\param[in] pad The 0-indexed pad number to enumerate formats on\n+ * \\fn V4L2Subdevice::setSelection(unsigned int pad, unsigned int target,\n+ * Rectangle *rect)\n+ * \\brief Set selection rectangle \\a rect for \\a target\n+ * \\param[in] pad The 0-indexed pad number the rectangle is to be applied to\n+ * \\param[in] target The selection target defined by the V4L2_SEL_TGT_* flags\n+ * \\param[inout] rect The selection rectangle to be applied\n+ *\n+ * \\todo Define a V4L2SelectionTarget enum for the selection target\n+ *\n+ * \\return 0 on success or a negative error code otherwise\n+ */\n+\n+/**\n+ * \\brief Enumerate all media bus codes and frame sizes on a \\a stream\n+ * \\param[in] stream The stream to enumerate formats for\n  *\n  * Enumerate all media bus codes and frame sizes supported by the subdevice on\n- * a \\a pad.\n+ * a \\a stream.\n  *\n  * \\return A list of the supported device formats\n  */\n-V4L2Subdevice::Formats V4L2Subdevice::formats(unsigned int pad)\n+V4L2Subdevice::Formats V4L2Subdevice::formats(const Stream &stream)\n {\n \tFormats formats;\n \n-\tif (pad >= entity_->pads().size()) {\n-\t\tLOG(V4L2, Error) << \"Invalid pad: \" << pad;\n+\tif (stream.pad >= entity_->pads().size()) {\n+\t\tLOG(V4L2, Error) << \"Invalid pad: \" << stream.pad;\n \t\treturn {};\n \t}\n \n-\tfor (unsigned int code : enumPadCodes(pad)) {\n-\t\tstd::vector<SizeRange> sizes = enumPadSizes(pad, code);\n+\tfor (unsigned int code : enumPadCodes(stream)) {\n+\t\tstd::vector<SizeRange> sizes = enumPadSizes(stream, code);\n \t\tif (sizes.empty())\n \t\t\treturn {};\n \n@@ -1034,7 +1117,7 @@ V4L2Subdevice::Formats V4L2Subdevice::formats(unsigned int pad)\n \t\tif (!inserted.second) {\n \t\t\tLOG(V4L2, Error)\n \t\t\t\t<< \"Could not add sizes for media bus code \"\n-\t\t\t\t<< code << \" on pad \" << pad;\n+\t\t\t\t<< code << \" on pad \" << stream.pad;\n \t\t\treturn {};\n \t\t}\n \t}\n@@ -1042,6 +1125,17 @@ V4L2Subdevice::Formats V4L2Subdevice::formats(unsigned int pad)\n \treturn formats;\n }\n \n+/**\n+ * \\fn V4L2Subdevice::formats(unsigned int pad)\n+ * \\brief Enumerate all media bus codes and frame sizes on a \\a pad\n+ * \\param[in] pad The 0-indexed pad number to enumerate formats on\n+ *\n+ * Enumerate all media bus codes and frame sizes supported by the subdevice on\n+ * a \\a pad\n+ *\n+ * \\return A list of the supported device formats\n+ */\n+\n std::optional<ColorSpace> V4L2Subdevice::toColorSpace(const v4l2_mbus_framefmt &format) const\n {\n \t/*\n@@ -1073,25 +1167,26 @@ std::optional<ColorSpace> V4L2Subdevice::toColorSpace(const v4l2_mbus_framefmt &\n }\n \n /**\n- * \\brief Retrieve the image format set on one of the V4L2 subdevice pads\n- * \\param[in] pad The 0-indexed pad number the format is to be retrieved from\n+ * \\brief Retrieve the image format set on one of the V4L2 subdevice streams\n+ * \\param[in] stream The stream the format is to be retrieved from\n  * \\param[out] format The image bus format\n  * \\param[in] whence The format to get, \\ref V4L2Subdevice::ActiveFormat\n  * \"ActiveFormat\" or \\ref V4L2Subdevice::TryFormat \"TryFormat\"\n  * \\return 0 on success or a negative error code otherwise\n  */\n-int V4L2Subdevice::getFormat(unsigned int pad, V4L2SubdeviceFormat *format,\n+int V4L2Subdevice::getFormat(const Stream &stream, V4L2SubdeviceFormat *format,\n \t\t\t     Whence whence)\n {\n \tstruct v4l2_subdev_format subdevFmt = {};\n \tsubdevFmt.which = whence;\n-\tsubdevFmt.pad = pad;\n+\tsubdevFmt.pad = stream.pad;\n+\tsubdevFmt.stream = stream.stream;\n \n \tint ret = ioctl(VIDIOC_SUBDEV_G_FMT, &subdevFmt);\n \tif (ret) {\n \t\tLOG(V4L2, Error)\n-\t\t\t<< \"Unable to get format on pad \" << pad\n-\t\t\t<< \": \" << strerror(-ret);\n+\t\t\t<< \"Unable to get format on pad \" << stream << \": \"\n+\t\t\t<< strerror(-ret);\n \t\treturn ret;\n \t}\n \n@@ -1104,6 +1199,66 @@ int V4L2Subdevice::getFormat(unsigned int pad, V4L2SubdeviceFormat *format,\n }\n \n /**\n+ * \\fn V4L2Subdevice::getFormat(unsigned int pad, V4L2SubdeviceFormat *format,\n+ * Whence whence)\n+ * \\brief Retrieve the image format set on one of the V4L2 subdevice pads\n+ * \\param[in] pad The 0-indexed pad number the format is to be retrieved from\n+ * \\param[out] format The image bus format\n+ * \\param[in] whence The format to get, \\ref V4L2Subdevice::ActiveFormat\n+ * \"ActiveFormat\" or \\ref V4L2Subdevice::TryFormat \"TryFormat\"\n+ * \\return 0 on success or a negative error code otherwise\n+ */\n+\n+/**\n+ * \\brief Set an image format on one of the V4L2 subdevice pads\n+ * \\param[in] stream The stream the format is to be applied to\n+ * \\param[inout] format The image bus format to apply to the stream\n+ * \\param[in] whence The format to set, \\ref V4L2Subdevice::ActiveFormat\n+ * \"ActiveFormat\" or \\ref V4L2Subdevice::TryFormat \"TryFormat\"\n+ *\n+ * Apply the requested image format to the desired stream and return the\n+ * actually applied format parameters, as getFormat() would do.\n+ *\n+ * \\return 0 on success or a negative error code otherwise\n+ */\n+int V4L2Subdevice::setFormat(const Stream &stream, V4L2SubdeviceFormat *format,\n+\t\t\t     Whence whence)\n+{\n+\tstruct v4l2_subdev_format subdevFmt = {};\n+\tsubdevFmt.which = whence;\n+\tsubdevFmt.pad = stream.pad;\n+\tsubdevFmt.stream = stream.stream;\n+\tsubdevFmt.format.width = format->size.width;\n+\tsubdevFmt.format.height = format->size.height;\n+\tsubdevFmt.format.code = format->code;\n+\tsubdevFmt.format.field = V4L2_FIELD_NONE;\n+\tif (format->colorSpace) {\n+\t\tfromColorSpace(format->colorSpace, subdevFmt.format);\n+\n+\t\t/* The CSC flag is only applicable to source pads. */\n+\t\tif (entity_->pads()[stream.pad]->flags() & MEDIA_PAD_FL_SOURCE)\n+\t\t\tsubdevFmt.format.flags |= V4L2_MBUS_FRAMEFMT_SET_CSC;\n+\t}\n+\n+\tint ret = ioctl(VIDIOC_SUBDEV_S_FMT, &subdevFmt);\n+\tif (ret) {\n+\t\tLOG(V4L2, Error)\n+\t\t\t<< \"Unable to set format on pad \" << stream << \": \"\n+\t\t\t<< strerror(-ret);\n+\t\treturn ret;\n+\t}\n+\n+\tformat->size.width = subdevFmt.format.width;\n+\tformat->size.height = subdevFmt.format.height;\n+\tformat->code = subdevFmt.format.code;\n+\tformat->colorSpace = toColorSpace(subdevFmt.format);\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * \\fn V4L2Subdevice::setFormat(unsigned int pad, V4L2SubdeviceFormat *format,\n+ * Whence whence)\n  * \\brief Set an image format on one of the V4L2 subdevice pads\n  * \\param[in] pad The 0-indexed pad number the format is to be applied to\n  * \\param[inout] format The image bus format to apply to the subdevice's pad\n@@ -1115,39 +1270,6 @@ int V4L2Subdevice::getFormat(unsigned int pad, V4L2SubdeviceFormat *format,\n  *\n  * \\return 0 on success or a negative error code otherwise\n  */\n-int V4L2Subdevice::setFormat(unsigned int pad, V4L2SubdeviceFormat *format,\n-\t\t\t     Whence whence)\n-{\n-\tstruct v4l2_subdev_format subdevFmt = {};\n-\tsubdevFmt.which = whence;\n-\tsubdevFmt.pad = pad;\n-\tsubdevFmt.format.width = format->size.width;\n-\tsubdevFmt.format.height = format->size.height;\n-\tsubdevFmt.format.code = format->code;\n-\tsubdevFmt.format.field = V4L2_FIELD_NONE;\n-\tif (format->colorSpace) {\n-\t\tfromColorSpace(format->colorSpace, subdevFmt.format);\n-\n-\t\t/* The CSC flag is only applicable to source pads. */\n-\t\tif (entity_->pads()[pad]->flags() & MEDIA_PAD_FL_SOURCE)\n-\t\t\tsubdevFmt.format.flags |= V4L2_MBUS_FRAMEFMT_SET_CSC;\n-\t}\n-\n-\tint ret = ioctl(VIDIOC_SUBDEV_S_FMT, &subdevFmt);\n-\tif (ret) {\n-\t\tLOG(V4L2, Error)\n-\t\t\t<< \"Unable to set format on pad \" << pad\n-\t\t\t<< \": \" << strerror(-ret);\n-\t\treturn ret;\n-\t}\n-\n-\tformat->size.width = subdevFmt.format.width;\n-\tformat->size.height = subdevFmt.format.height;\n-\tformat->code = subdevFmt.format.code;\n-\tformat->colorSpace = toColorSpace(subdevFmt.format);\n-\n-\treturn 0;\n-}\n \n /**\n  * \\brief Retrieve the subdevice's internal routing table\n@@ -1310,14 +1432,15 @@ std::string V4L2Subdevice::logPrefix() const\n \treturn \"'\" + entity_->name() + \"'\";\n }\n \n-std::vector<unsigned int> V4L2Subdevice::enumPadCodes(unsigned int pad)\n+std::vector<unsigned int> V4L2Subdevice::enumPadCodes(const Stream &stream)\n {\n \tstd::vector<unsigned int> codes;\n \tint ret;\n \n \tfor (unsigned int index = 0; ; index++) {\n \t\tstruct v4l2_subdev_mbus_code_enum mbusEnum = {};\n-\t\tmbusEnum.pad = pad;\n+\t\tmbusEnum.pad = stream.pad;\n+\t\tmbusEnum.stream = stream.stream;\n \t\tmbusEnum.index = index;\n \t\tmbusEnum.which = V4L2_SUBDEV_FORMAT_ACTIVE;\n \n@@ -1330,7 +1453,7 @@ std::vector<unsigned int> V4L2Subdevice::enumPadCodes(unsigned int pad)\n \n \tif (ret < 0 && ret != -EINVAL) {\n \t\tLOG(V4L2, Error)\n-\t\t\t<< \"Unable to enumerate formats on pad \" << pad\n+\t\t\t<< \"Unable to enumerate formats on pad \" << stream\n \t\t\t<< \": \" << strerror(-ret);\n \t\treturn {};\n \t}\n@@ -1338,7 +1461,7 @@ std::vector<unsigned int> V4L2Subdevice::enumPadCodes(unsigned int pad)\n \treturn codes;\n }\n \n-std::vector<SizeRange> V4L2Subdevice::enumPadSizes(unsigned int pad,\n+std::vector<SizeRange> V4L2Subdevice::enumPadSizes(const Stream &stream,\n \t\t\t\t\t\t   unsigned int code)\n {\n \tstd::vector<SizeRange> sizes;\n@@ -1347,7 +1470,8 @@ std::vector<SizeRange> V4L2Subdevice::enumPadSizes(unsigned int pad,\n \tfor (unsigned int index = 0;; index++) {\n \t\tstruct v4l2_subdev_frame_size_enum sizeEnum = {};\n \t\tsizeEnum.index = index;\n-\t\tsizeEnum.pad = pad;\n+\t\tsizeEnum.pad = stream.pad;\n+\t\tsizeEnum.stream = stream.stream;\n \t\tsizeEnum.code = code;\n \t\tsizeEnum.which = V4L2_SUBDEV_FORMAT_ACTIVE;\n \n@@ -1361,7 +1485,7 @@ std::vector<SizeRange> V4L2Subdevice::enumPadSizes(unsigned int pad,\n \n \tif (ret < 0 && ret != -EINVAL && ret != -ENOTTY) {\n \t\tLOG(V4L2, Error)\n-\t\t\t<< \"Unable to enumerate sizes on pad \" << pad\n+\t\t\t<< \"Unable to enumerate sizes on pad \" << stream\n \t\t\t<< \": \" << strerror(-ret);\n \t\treturn {};\n \t}\n",
    "prefixes": [
        "v2",
        "07/14"
    ]
}