Patch Detail
Show a patch.
GET /api/patches/1802/?format=api
{ "id": 1802, "url": "https://patchwork.libcamera.org/api/patches/1802/?format=api", "web_url": "https://patchwork.libcamera.org/patch/1802/", "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": "<20190813094020.10277-4-kieran.bingham@ideasonboard.com>", "date": "2019-08-13T09:40:17", "name": "[libcamera-devel,v3,3/6] libcamera: v4l2_videodevice: Support M2M devices", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "76647982b6d669b3d34ecc1f04d6ec60d900a2a0", "submitter": { "id": 4, "url": "https://patchwork.libcamera.org/api/people/4/?format=api", "name": "Kieran Bingham", "email": "kieran.bingham@ideasonboard.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/1802/mbox/", "series": [ { "id": 458, "url": "https://patchwork.libcamera.org/api/series/458/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=458", "date": "2019-08-13T09:40:14", "name": "V4L2 M2M Support (+RPi PoC)", "version": 3, "mbox": "https://patchwork.libcamera.org/series/458/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/1802/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/1802/checks/", "tags": {}, "headers": { "Return-Path": "<kieran.bingham@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 BFC3C61624\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 13 Aug 2019 11:40:25 +0200 (CEST)", "from localhost.localdomain\n\t(cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 4E3DAFA0;\n\tTue, 13 Aug 2019 11:40:25 +0200 (CEST)" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1565689225;\n\tbh=f/HUeRJSLJmSZu+rCLW2nAb7pY/qBSCbAOGt8l90Apk=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=vpU9opdQlpvjQ4dShsh1WU8iphDTItPDioUwCNAdFHXVKwsz6COQatEGq9b+4pu6w\n\toIhYHu6lYg8AKgOv/vxZR9HakYiadWbTimsbs7CRIKTMK2U2w+r+7l3NgE1l4AC0xX\n\tmu3B3z6RsHu2gW2JkM4ZL9BtvbmOn4VdeJfhpTgQ=", "From": "Kieran Bingham <kieran.bingham@ideasonboard.com>", "To": "LibCamera Devel <libcamera-devel@lists.libcamera.org>", "Date": "Tue, 13 Aug 2019 10:40:17 +0100", "Message-Id": "<20190813094020.10277-4-kieran.bingham@ideasonboard.com>", "X-Mailer": "git-send-email 2.20.1", "In-Reply-To": "<20190813094020.10277-1-kieran.bingham@ideasonboard.com>", "References": "<20190813094020.10277-1-kieran.bingham@ideasonboard.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Subject": "[libcamera-devel] [PATCH v3 3/6] libcamera: v4l2_videodevice:\n\tSupport M2M devices", "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": "Tue, 13 Aug 2019 09:40:25 -0000" }, "content": "V4L2 M2M devices represent a V4L2Device with two queues: One output, and\none capture on a single device node.\n\nRepresent this by instantiating a V4L2VideoDevice for each queue type,\nand preparing each device for its queue.\n\nSigned-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n---\n src/libcamera/include/v4l2_videodevice.h | 25 +++\n src/libcamera/v4l2_videodevice.cpp | 194 ++++++++++++++++++++++-\n 2 files changed, 218 insertions(+), 1 deletion(-)", "diff": "diff --git a/src/libcamera/include/v4l2_videodevice.h b/src/libcamera/include/v4l2_videodevice.h\nindex f5c8da93fcb5..0fc2dcd81d2b 100644\n--- a/src/libcamera/include/v4l2_videodevice.h\n+++ b/src/libcamera/include/v4l2_videodevice.h\n@@ -71,6 +71,11 @@ struct V4L2Capability final : v4l2_capability {\n \t\t\t\t\tV4L2_CAP_VIDEO_OUTPUT |\n \t\t\t\t\tV4L2_CAP_VIDEO_OUTPUT_MPLANE);\n \t}\n+\tbool isM2M() const\n+\t{\n+\t\treturn device_caps() & (V4L2_CAP_VIDEO_M2M |\n+\t\t\t\t\tV4L2_CAP_VIDEO_M2M_MPLANE);\n+\t}\n \tbool isMeta() const\n \t{\n \t\treturn device_caps() & (V4L2_CAP_META_CAPTURE |\n@@ -124,6 +129,7 @@ public:\n \tV4L2VideoDevice &operator=(const V4L2VideoDevice &) = delete;\n \n \tint open();\n+\tint open(int handle, enum v4l2_buf_type type);\n \tvoid close();\n \n \tconst char *driverName() const { return caps_.driver(); }\n@@ -182,6 +188,25 @@ private:\n \tEventNotifier *fdEvent_;\n };\n \n+class V4L2M2MDevice\n+{\n+public:\n+\tV4L2M2MDevice(const std::string &deviceNode);\n+\t~V4L2M2MDevice();\n+\n+\tint open();\n+\tvoid close();\n+\n+\tV4L2VideoDevice *output() { return output_; }\n+\tV4L2VideoDevice *capture() { return capture_; }\n+\n+private:\n+\tstd::string deviceNode_;\n+\n+\tV4L2VideoDevice *output_;\n+\tV4L2VideoDevice *capture_;\n+};\n+\n } /* namespace libcamera */\n \n #endif /* __LIBCAMERA_V4L2_VIDEODEVICE_H__ */\ndiff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp\nindex 81098dd70190..5e41f44eeb50 100644\n--- a/src/libcamera/v4l2_videodevice.cpp\n+++ b/src/libcamera/v4l2_videodevice.cpp\n@@ -89,6 +89,12 @@ LOG_DECLARE_CATEGORY(V4L2)\n * \\return True if the video device can capture or output images\n */\n \n+/**\n+ * \\fn V4L2Capability::isM2M()\n+ * \\brief Identify if the device is an M2M device\n+ * \\return True if the device can capture and output images using the M2M API\n+ */\n+\n /**\n * \\fn V4L2Capability::isMeta()\n * \\brief Identify if the video device captures or outputs image meta-data\n@@ -295,7 +301,8 @@ V4L2VideoDevice::~V4L2VideoDevice()\n }\n \n /**\n- * \\brief Open a V4L2 video device and query its capabilities\n+ * \\brief Open the V4L2 video device node and query its capabilities\n+ *\n * \\return 0 on success or a negative error code otherwise\n */\n int V4L2VideoDevice::open()\n@@ -355,6 +362,92 @@ int V4L2VideoDevice::open()\n \treturn 0;\n }\n \n+/**\n+ * \\brief Open a V4L2 video device from an opened file handle and query its\n+ * capabilities\n+ * \\param[in] handle The file descriptor to set\n+ * \\param[in] type The device type to operate on\n+ *\n+ * This methods opens a video device from the existing file descriptor \\a\n+ * handle. Like open(), this method queries the capabilities of the device, but\n+ * handles it according to the given device \\a type instead of determining its\n+ * type from the capabilities. This can be used to force a given device type for\n+ * M2M devices.\n+ *\n+ * The file descriptor \\a handle is duplicated, and the caller is responsible\n+ * for closing the \\a handle when it has no further use for it. The close()\n+ * method will close the duplicated file descriptor, leaving \\a handle\n+ * untouched.\n+ *\n+ * \\return 0 on success or a negative error code otherwise\n+ */\n+int V4L2VideoDevice::open(int handle, enum v4l2_buf_type type)\n+{\n+\tint ret;\n+\tint newFd;\n+\n+\tnewFd = dup(handle);\n+\tif (newFd < 0) {\n+\t\tret = -errno;\n+\t\tLOG(V4L2, Error) << \"Failed to duplicate file handle: \"\n+\t\t\t\t << strerror(-ret);\n+\t\treturn ret;\n+\t}\n+\n+\tret = V4L2Device::setFd(newFd);\n+\tif (ret < 0) {\n+\t\tLOG(V4L2, Error) << \"Failed to set file handle: \"\n+\t\t\t\t << strerror(-ret);\n+\t\t::close(newFd);\n+\t\treturn ret;\n+\t}\n+\n+\tret = ioctl(VIDIOC_QUERYCAP, &caps_);\n+\tif (ret < 0) {\n+\t\tLOG(V4L2, Error)\n+\t\t\t<< \"Failed to query device capabilities: \"\n+\t\t\t<< strerror(-ret);\n+\t\treturn ret;\n+\t}\n+\n+\tif (!caps_.hasStreaming()) {\n+\t\tLOG(V4L2, Error) << \"Device does not support streaming I/O\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/*\n+\t * Set buffer type and wait for read notifications on CAPTURE video\n+\t * devices (POLLIN), and write notifications for OUTPUT video devices\n+\t * (POLLOUT).\n+\t */\n+\tswitch (type) {\n+\tcase V4L2_BUF_TYPE_VIDEO_OUTPUT:\n+\t\tfdEvent_ = new EventNotifier(fd(), EventNotifier::Write);\n+\t\tbufferType_ = caps_.isMultiplanar()\n+\t\t\t ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE\n+\t\t\t : V4L2_BUF_TYPE_VIDEO_OUTPUT;\n+\t\tbreak;\n+\tcase V4L2_BUF_TYPE_VIDEO_CAPTURE:\n+\t\tfdEvent_ = new EventNotifier(fd(), EventNotifier::Read);\n+\t\tbufferType_ = caps_.isMultiplanar()\n+\t\t\t ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE\n+\t\t\t : V4L2_BUF_TYPE_VIDEO_CAPTURE;\n+\t\tbreak;\n+\tdefault:\n+\t\tLOG(V4L2, Error) << \"Unsupported buffer type\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tfdEvent_->activated.connect(this, &V4L2VideoDevice::bufferAvailable);\n+\tfdEvent_->setEnabled(false);\n+\n+\tLOG(V4L2, Debug)\n+\t\t<< \"Opened device \" << caps_.bus_info() << \": \"\n+\t\t<< caps_.driver() << \": \" << caps_.card();\n+\n+\treturn 0;\n+}\n+\n /**\n * \\brief Close the video device, releasing any resources acquired by open()\n */\n@@ -1143,4 +1236,103 @@ V4L2VideoDevice *V4L2VideoDevice::fromEntityName(const MediaDevice *media,\n \treturn new V4L2VideoDevice(mediaEntity);\n }\n \n+/**\n+ * \\class V4L2M2MDevice\n+ * \\brief Memory2Memory video device\n+ *\n+ * The V4L2M2MDevice manages two V4L2VideoDevice instances on the same\n+ * deviceNode which operate together using two queues to implement the V4L2\n+ * Memory to Memory API.\n+ *\n+ * The two devices should be opened by calling open() on the V4L2M2MDevice, and\n+ * can be closed by calling close on the V4L2M2MDevice.\n+ *\n+ * Calling V4L2VideoDevice::open() and V4L2VideoDevice::close() on the capture\n+ * or output V4L2VideoDevice is not permitted.\n+ */\n+\n+/**\n+ * \\fn V4L2M2MDevice::output\n+ * \\brief Retrieve the output V4L2VideoDevice instance\n+ * \\return The output V4L2Device instance\n+ */\n+\n+/**\n+ * \\fn V4L2M2MDevice::capture\n+ * \\brief Retrieve the capture V4L2VideoDevice instance\n+ * \\return The capture V4L2Device instance\n+ */\n+\n+/**\n+ * \\brief Create a new V4L2M2MDevice from the \\a deviceNode\n+ */\n+V4L2M2MDevice::V4L2M2MDevice(const std::string &deviceNode)\n+\t: deviceNode_(deviceNode)\n+{\n+\toutput_ = new V4L2VideoDevice(deviceNode);\n+\tcapture_ = new V4L2VideoDevice(deviceNode);\n+}\n+\n+V4L2M2MDevice::~V4L2M2MDevice()\n+{\n+\tdelete capture_;\n+\tdelete output_;\n+}\n+\n+/**\n+ * \\brief Open a V4L2 Memory to Memory device\n+ *\n+ * Open the device node and prepare the two V4L2VideoDevice instances to handle\n+ * their respective buffer queues.\n+ *\n+ * \\return 0 on success or a negative error code otherwise\n+ */\n+int V4L2M2MDevice::open()\n+{\n+\tint fd;\n+\tint ret;\n+\n+\t/*\n+\t * The output and capture V4L2VideoDevice instances use the same file\n+\t * handle for the same device node. The local file handle can be closed\n+\t * as the V4L2VideoDevice::open() retains a handle by duplicating the\n+\t * fd passed in.\n+\t */\n+\tfd = ::open(deviceNode_.c_str(), O_RDWR | O_NONBLOCK);\n+\tif (fd < 0) {\n+\t\tret = -errno;\n+\t\tLOG(V4L2, Error)\n+\t\t\t<< \"Failed to open V4L2 M2M device: \" << strerror(-ret);\n+\t\treturn ret;\n+\t}\n+\n+\tret = output_->open(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT);\n+\tif (ret)\n+\t\tgoto err;\n+\n+\tret = capture_->open(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE);\n+\tif (ret)\n+\t\tgoto err;\n+\n+\t::close(fd);\n+\n+\treturn 0;\n+\n+err:\n+\tclose();\n+\t::close(fd);\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * \\brief Close the memory-to-memory device, releasing any resources acquired by\n+ * open()\n+ */\n+void V4L2M2MDevice::close()\n+{\n+\tcapture_->close();\n+\toutput_->close();\n+}\n+\n } /* namespace libcamera */\n", "prefixes": [ "libcamera-devel", "v3", "3/6" ] }