Patch Detail
Show a patch.
GET /api/1.1/patches/527/?format=api
{ "id": 527, "url": "https://patchwork.libcamera.org/api/1.1/patches/527/?format=api", "web_url": "https://patchwork.libcamera.org/patch/527/", "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": "<20190206060818.13907-13-laurent.pinchart@ideasonboard.com>", "date": "2019-02-06T06:08:03", "name": "[libcamera-devel,12/27] libcamera: Add V4L2Subdevice", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "3ef8d9df968b278e66ac7f08ddfa9b21f1d35da3", "submitter": { "id": 2, "url": "https://patchwork.libcamera.org/api/1.1/people/2/?format=api", "name": "Laurent Pinchart", "email": "laurent.pinchart@ideasonboard.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/527/mbox/", "series": [ { "id": 170, "url": "https://patchwork.libcamera.org/api/1.1/series/170/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=170", "date": "2019-02-06T06:07:51", "name": "Capture frames throught requests", "version": 1, "mbox": "https://patchwork.libcamera.org/series/170/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/527/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/527/checks/", "tags": {}, "headers": { "Return-Path": "<laurent.pinchart@ideasonboard.com>", "Received": [ "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 380F761026\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 6 Feb 2019 07:08:26 +0100 (CET)", "from pendragon.ideasonboard.com (d51A4137F.access.telenet.be\n\t[81.164.19.127])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id D278E2D8\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 6 Feb 2019 07:08:25 +0100 (CET)" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1549433305;\n\tbh=O3mcBuKcrm1QhL6KMm2kJOMjJjiCP6DKOSN+AZnzdIs=;\n\th=From:To:Subject:Date:In-Reply-To:References:From;\n\tb=c4mBXQoVCjcVM1UynQzI+UhqlSo41zuj45Dx/WMtqADAeJmrBUP1qzlwl9TfnaEVi\n\t5rz/N1HLbO0B/YI8tSaTnZnnnOkpFSqQuAi309APUBQp+mskKMEu+mfQDWixbYlJDb\n\tPcsRCvBLJFoJ91Tjm1U0Sd0EP331byM6Ysz3f5ng=", "From": "Laurent Pinchart <laurent.pinchart@ideasonboard.com>", "To": "libcamera-devel@lists.libcamera.org", "Date": "Wed, 6 Feb 2019 08:08:03 +0200", "Message-Id": "<20190206060818.13907-13-laurent.pinchart@ideasonboard.com>", "X-Mailer": "git-send-email 2.19.2", "In-Reply-To": "<20190206060818.13907-1-laurent.pinchart@ideasonboard.com>", "References": "<20190206060818.13907-1-laurent.pinchart@ideasonboard.com>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=UTF-8", "Content-Transfer-Encoding": "8bit", "Subject": "[libcamera-devel] [PATCH 12/27] libcamera: Add V4L2Subdevice", "X-BeenThere": "libcamera-devel@lists.libcamera.org", "X-Mailman-Version": "2.1.23", "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": "Wed, 06 Feb 2019 06:08:28 -0000" }, "content": "From: Jacopo Mondi <jacopo@jmondi.org>\n\nAdd V4L2Subdevice class that provides an interface to interact with\nV4L2 defined sub-devices.\n\nSigned-off-by: Jacopo Mondi <jacopo@jmondi.org>\nReviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n---\n src/libcamera/include/v4l2_subdevice.h | 51 +++++\n src/libcamera/meson.build | 1 +\n src/libcamera/v4l2_subdevice.cpp | 265 +++++++++++++++++++++++++\n 3 files changed, 317 insertions(+)\n create mode 100644 src/libcamera/include/v4l2_subdevice.h\n create mode 100644 src/libcamera/v4l2_subdevice.cpp", "diff": "diff --git a/src/libcamera/include/v4l2_subdevice.h b/src/libcamera/include/v4l2_subdevice.h\nnew file mode 100644\nindex 000000000000..8fd666078985\n--- /dev/null\n+++ b/src/libcamera/include/v4l2_subdevice.h\n@@ -0,0 +1,51 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2019, Google Inc.\n+ *\n+ * v4l2_subdevice.h - V4L2 Subdevice\n+ */\n+#ifndef __LIBCAMERA_V4L2_SUBDEVICE_H__\n+#define __LIBCAMERA_V4L2_SUBDEVICE_H__\n+\n+#include <string>\n+\n+namespace libcamera {\n+\n+struct Rectangle;\n+\n+struct V4L2SubdeviceFormat {\n+\tuint32_t mbus_code;\n+\tuint32_t width;\n+\tuint32_t height;\n+};\n+\n+class V4L2Subdevice\n+{\n+public:\n+\texplicit V4L2Subdevice(const MediaEntity *entity);\n+\tV4L2Subdevice(const V4L2Subdevice &) = delete;\n+\tV4L2Subdevice &operator=(const V4L2Subdevice &) = delete;\n+\n+\tint open();\n+\tbool isOpen() const;\n+\tvoid close();\n+\n+\tstd::string deviceNode() const { return deviceNode_; }\n+\n+\tint setCrop(unsigned int pad, Rectangle *rect);\n+\tint setCompose(unsigned int pad, Rectangle *rect);\n+\n+\tint getFormat(unsigned int pad, V4L2SubdeviceFormat *format);\n+\tint setFormat(unsigned int pad, V4L2SubdeviceFormat *format);\n+\n+private:\n+\tint setSelection(unsigned int pad, unsigned int target,\n+\t\t\t Rectangle *rect);\n+\n+\tstd::string deviceNode_;\n+\tint fd_;\n+};\n+\n+} /* namespace libcamera */\n+\n+#endif /* __LIBCAMERA_V4L2_SUBDEVICE_H__ */\ndiff --git a/src/libcamera/meson.build b/src/libcamera/meson.build\nindex 8b33c4b25c30..ac991dc59d18 100644\n--- a/src/libcamera/meson.build\n+++ b/src/libcamera/meson.build\n@@ -15,6 +15,7 @@ libcamera_sources = files([\n 'stream.cpp',\n 'timer.cpp',\n 'v4l2_device.cpp',\n+ 'v4l2_subdevice.cpp',\n ])\n \n libcamera_headers = files([\ndiff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp\nnew file mode 100644\nindex 000000000000..1d5b11115dbb\n--- /dev/null\n+++ b/src/libcamera/v4l2_subdevice.cpp\n@@ -0,0 +1,265 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2019, Google Inc.\n+ *\n+ * v4l2_subdevice.cpp - V4L2 Subdevice\n+ */\n+\n+#include <fcntl.h>\n+#include <string.h>\n+#include <sys/ioctl.h>\n+#include <unistd.h>\n+\n+#include <linux/v4l2-subdev.h>\n+\n+#include \"geometry.h\"\n+#include \"log.h\"\n+#include \"media_object.h\"\n+#include \"v4l2_subdevice.h\"\n+\n+/**\n+ * \\file v4l2_subdevice.h\n+ * \\brief V4L2 Subdevice API\n+ */\n+\n+namespace libcamera {\n+\n+LOG_DEFINE_CATEGORY(V4L2Subdev)\n+\n+/**\n+ * \\struct V4L2SubdeviceFormat\n+ * \\brief The V4L2 sub-device image format and sizes\n+ *\n+ * This structure describes the format of images when transported between\n+ * separate components connected through a physical bus, such as image sensor\n+ * and image receiver or between components part of the same System-on-Chip that\n+ * realize an image transformation pipeline.\n+ *\n+ * The format of images when transported on physical interconnections is known\n+ * as the \"media bus format\", and it is identified by a resolution and a pixel\n+ * format identification code, known as the \"media bus code\", not to be confused\n+ * with the fourcc code that identify the format of images when stored in memory\n+ * (see V4L2Device::V4L2DeviceFormat).\n+ *\n+ * Media Bus formats supported by the V4L2 APIs are described in Section\n+ * 4.15.3.4.1 of the \"Part I - Video for Linux API\" chapter of the \"Linux Media\n+ * Infrastructure userspace API\", part of the Linux kernel documentation.\n+ *\n+ * Image media bus formats are properties of the subdev pads. When images are\n+ * transported between two media pads identified by a 0-indexed number, the\n+ * image bus format configured on the two pads should match (according to the\n+ * underlying driver format matching criteria) in order to prepare for a\n+ * successful streaming operation. For a more detailed description of the image\n+ * format negotiation process when performed between V4L2 subdevices, refer to\n+ * Section 4.15.3.1 of the above mentioned Linux kernel documentation section.\n+ */\n+\n+/**\n+ * \\var V4L2SubdeviceFormat::width\n+ * \\brief The image width in pixels\n+ */\n+\n+/**\n+ * \\var V4L2SubdeviceFormat::height\n+ * \\brief The image height in pixels\n+ */\n+\n+/**\n+ * \\var V4L2SubdeviceFormat::mbus_code\n+ * \\brief The image format bus code\n+ */\n+\n+/**\n+ * \\class V4L2Subdevice\n+ * \\brief A V4L2 subdevice as exposed by the Linux kernel\n+ *\n+ * The V4L2Subdevice class provides an API to the \"Sub-device interface\" as\n+ * described in section 4.15 of the \"Linux Media Infrastructure userspace API\"\n+ * chapter of the Linux Kernel documentation.\n+ *\n+ * A V4L2Subdevice is constructed from a MediaEntity instance, using the system\n+ * path of the entity's device node. No API call other than open(), isOpen()\n+ * and close() shall be called on an unopened device instance. Upon destruction\n+ * any device left open will be closed, and any resources released.\n+ */\n+\n+/**\n+ * \\brief Create a V4L2 subdevice from a MediaEntity using its device node\n+ * path\n+ */\n+V4L2Subdevice::V4L2Subdevice(const MediaEntity *entity)\n+\t: deviceNode_(entity->deviceNode()), fd_(-1)\n+{\n+}\n+\n+/**\n+ * \\brief Open a V4L2 subdevice\n+ *\n+ * \\return 0 on success, a negative error code otherwise\n+ */\n+int V4L2Subdevice::open()\n+{\n+\tint ret;\n+\n+\tif (isOpen()) {\n+\t\tLOG(V4L2Subdev, Error) << \"Device already open\";\n+\t\treturn -EBUSY;\n+\t}\n+\n+\tret = ::open(deviceNode_.c_str(), O_RDWR);\n+\tif (ret < 0) {\n+\t\tret = -errno;\n+\t\tLOG(V4L2Subdev, Error)\n+\t\t\t<< \"Failed to open V4L2 subdevice '\" << deviceNode_\n+\t\t\t<< \"': \" << strerror(-ret);\n+\t\treturn ret;\n+\t}\n+\tfd_ = ret;\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * \\brief Check if the subdevice is open\n+ * \\return True if the subdevice is open, false otherwise\n+ */\n+bool V4L2Subdevice::isOpen() const\n+{\n+\treturn fd_ != -1;\n+}\n+\n+/**\n+ * \\brief Close the subdevice, releasing any resources acquired by open()\n+ */\n+void V4L2Subdevice::close()\n+{\n+\tif (!isOpen())\n+\t\treturn;\n+\n+\t::close(fd_);\n+\tfd_ = -1;\n+}\n+\n+/**\n+ * \\fn V4L2Subdevice::deviceNode()\n+ * \\brief Retrieve the path of the device node associated with the subdevice\n+ *\n+ * \\return The subdevice's device node system path\n+ */\n+\n+/**\n+ * \\brief Set a crop rectangle on one of the V4L2 subdevice pads\n+ * \\param[in] pad The 0-indexed pad number the rectangle is to be applied to\n+ * \\param[inout] rect The rectangle describing crop target area\n+ *\n+ * \\return 0 on success, or a negative error code otherwise\n+ */\n+int V4L2Subdevice::setCrop(unsigned int pad, Rectangle *rect)\n+{\n+\treturn setSelection(pad, V4L2_SEL_TGT_CROP, rect);\n+}\n+\n+/**\n+ * \\brief Set a compose rectangle on one of the V4L2 subdevice pads\n+ * \\param[in] pad The 0-indexed pad number the rectangle is to be applied to\n+ * \\param[inout] rect The rectangle describing the compose target area\n+ *\n+ * \\return 0 on success, or a negative error code otherwise\n+ */\n+int V4L2Subdevice::setCompose(unsigned int pad, Rectangle *rect)\n+{\n+\treturn setSelection(pad, V4L2_SEL_TGT_COMPOSE, rect);\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+ * \\param[out] format The image bus format\n+ *\n+ * \\return 0 for success, a negative error code otherwise\n+ */\n+int V4L2Subdevice::getFormat(unsigned int pad, V4L2SubdeviceFormat *format)\n+{\n+\tstruct v4l2_subdev_format subdevFmt = {};\n+\tsubdevFmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;\n+\tsubdevFmt.pad = pad;\n+\n+\tint ret = ioctl(fd_, VIDIOC_SUBDEV_G_FMT, &subdevFmt);\n+\tif (ret) {\n+\t\tret = -errno;\n+\t\tLOG(V4L2Subdev, Error)\n+\t\t\t<< \"Unable to get format on pad \" << pad\n+\t\t\t<< \" of \" << deviceNode_ << \": \" << strerror(-ret);\n+\t\treturn ret;\n+\t}\n+\n+\tformat->width = subdevFmt.format.width;\n+\tformat->height = subdevFmt.format.height;\n+\tformat->mbus_code = subdevFmt.format.code;\n+\n+\treturn 0;\n+}\n+\n+/**\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+ *\n+ * Apply the requested image format to the desired media pad and return the\n+ * actually applied format parameters, as \\ref V4L2Subdevice::getFormat would\n+ * do.\n+ *\n+ * \\return 0 for success, a negative error code otherwise\n+ */\n+int V4L2Subdevice::setFormat(unsigned int pad, V4L2SubdeviceFormat *format)\n+{\n+\tstruct v4l2_subdev_format subdevFmt = {};\n+\tsubdevFmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;\n+\tsubdevFmt.pad = pad;\n+\tsubdevFmt.format.width = format->width;\n+\tsubdevFmt.format.height = format->height;\n+\tsubdevFmt.format.code = format->mbus_code;\n+\n+\tint ret = ioctl(fd_, VIDIOC_SUBDEV_S_FMT, &subdevFmt);\n+\tif (ret) {\n+\t\tret = -errno;\n+\t\tLOG(Error) << \"Unable to set format: \" << strerror(-ret);\n+\t\treturn ret;\n+\t}\n+\n+\tformat->width = subdevFmt.format.width;\n+\tformat->height = subdevFmt.format.height;\n+\tformat->mbus_code = subdevFmt.format.code;\n+\n+\treturn 0;\n+}\n+\n+int V4L2Subdevice::setSelection(unsigned int pad, 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.target = target;\n+\tsel.flags = 0;\n+\n+\tsel.r.left = rect->y;\n+\tsel.r.top = rect->x;\n+\tsel.r.width = rect->w;\n+\tsel.r.height = rect->h;\n+\n+\tint ret = ioctl(fd_, VIDIOC_SUBDEV_S_SELECTION, sel);\n+\tif (ret < 0) {\n+\t\tret = -errno;\n+\t\tLOG(V4L2Subdev, Error)\n+\t\t\t<< \"Unable to set rectangle \" << target << \" on pad \"\n+\t\t\t<< pad << \" of \" << deviceNode_ << \": \"\n+\t\t\t<< strerror(-ret);\n+\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+} /* namespace libcamera */\n", "prefixes": [ "libcamera-devel", "12/27" ] }