{"id":2367,"url":"https://patchwork.libcamera.org/api/1.1/patches/2367/?format=json","web_url":"https://patchwork.libcamera.org/patch/2367/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/1.1/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20191126233620.1695316-20-niklas.soderlund@ragnatech.se>","date":"2019-11-26T23:36:09","name":"[libcamera-devel,19/30] libcamera: v4l2_videodevice: Add new buffer interface","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"a489f43b6130b3df385c777069ad61a4526bacb0","submitter":{"id":5,"url":"https://patchwork.libcamera.org/api/1.1/people/5/?format=json","name":"Niklas Söderlund","email":"niklas.soderlund@ragnatech.se"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/2367/mbox/","series":[{"id":579,"url":"https://patchwork.libcamera.org/api/1.1/series/579/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=579","date":"2019-11-26T23:35:50","name":"libcamera: Rework buffer API","version":1,"mbox":"https://patchwork.libcamera.org/series/579/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/2367/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/2367/checks/","tags":{},"headers":{"Return-Path":"<niklas.soderlund@ragnatech.se>","Received":["from bin-mail-out-05.binero.net (bin-mail-out-05.binero.net\n\t[195.74.38.228])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 7ABB26136C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 27 Nov 2019 00:39:39 +0100 (CET)","from bismarck.berto.se (p54ac5865.dip0.t-ipconnect.de\n\t[84.172.88.101]) by bin-vsp-out-02.atm.binero.net (Halon) with ESMTPA\n\tid 022e8134-10a6-11ea-a0b9-005056917f90;\n\tWed, 27 Nov 2019 00:39:37 +0100 (CET)"],"X-Halon-ID":"022e8134-10a6-11ea-a0b9-005056917f90","Authorized-sender":"niklas@soderlund.pp.se","From":"=?utf-8?q?Niklas_S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>","To":"libcamera-devel@lists.libcamera.org","Date":"Wed, 27 Nov 2019 00:36:09 +0100","Message-Id":"<20191126233620.1695316-20-niklas.soderlund@ragnatech.se>","X-Mailer":"git-send-email 2.24.0","In-Reply-To":"<20191126233620.1695316-1-niklas.soderlund@ragnatech.se>","References":"<20191126233620.1695316-1-niklas.soderlund@ragnatech.se>","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Subject":"[libcamera-devel] [PATCH 19/30] libcamera: v4l2_videodevice: Add\n\tnew buffer interface","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>","X-List-Received-Date":"Tue, 26 Nov 2019 23:39:39 -0000"},"content":"Extend V4L2VideoDevice with two new functions, one to deal with\nallocating buffers from the video device and one to prepare the video\ndevice to use external buffers.\n\nThe two new functions intend to replace exportBuffers() and\nimportBuffers() once the transition to the FrameBuffer interface is\ncomplete.\n\nSigned-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n---\n src/libcamera/include/v4l2_videodevice.h |   4 +\n src/libcamera/v4l2_videodevice.cpp       | 126 ++++++++++++++++++++++-\n 2 files changed, 129 insertions(+), 1 deletion(-)","diff":"diff --git a/src/libcamera/include/v4l2_videodevice.h b/src/libcamera/include/v4l2_videodevice.h\nindex 254f8797af42dd8a..f4cbcfbd26ea540c 100644\n--- a/src/libcamera/include/v4l2_videodevice.h\n+++ b/src/libcamera/include/v4l2_videodevice.h\n@@ -162,6 +162,8 @@ public:\n \n \tint exportBuffers(BufferPool *pool);\n \tint importBuffers(BufferPool *pool);\n+\tint allocateBuffers(unsigned int count, std::vector<FrameBuffer *> *buffers);\n+\tint externalBuffers(unsigned int count);\n \tint releaseBuffers();\n \n \tint queueBuffer(Buffer *buffer);\n@@ -197,6 +199,7 @@ private:\n \tint requestBuffers(unsigned int count);\n \tint createPlane(BufferMemory *buffer, unsigned int index,\n \t\t\tunsigned int plane, unsigned int length);\n+\tFrameBuffer *createBuffer(struct v4l2_buffer buf);\n \tint exportDmaBuffer(unsigned int index, unsigned int plane);\n \n \tBuffer *dequeueBuffer();\n@@ -208,6 +211,7 @@ private:\n \tenum v4l2_memory memoryType_;\n \n \tBufferPool *bufferPool_;\n+\tV4L2BufferCache *cache_;\n \tstd::map<unsigned int, Buffer *> queuedBuffers_;\n \n \tEventNotifier *fdEvent_;\ndiff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp\nindex c82f2829601bd14c..9fe66018ec502626 100644\n--- a/src/libcamera/v4l2_videodevice.cpp\n+++ b/src/libcamera/v4l2_videodevice.cpp\n@@ -377,7 +377,8 @@ const std::string V4L2DeviceFormat::toString() const\n  * \\param[in] deviceNode The file-system path to the video device node\n  */\n V4L2VideoDevice::V4L2VideoDevice(const std::string &deviceNode)\n-\t: V4L2Device(deviceNode), bufferPool_(nullptr), fdEvent_(nullptr)\n+\t: V4L2Device(deviceNode), bufferPool_(nullptr), cache_(nullptr),\n+\t  fdEvent_(nullptr)\n {\n \t/*\n \t * We default to an MMAP based CAPTURE video device, however this will\n@@ -1042,6 +1043,100 @@ int V4L2VideoDevice::importBuffers(BufferPool *pool)\n \treturn 0;\n }\n \n+/**\n+ * \\brief Operate using buffers allocated from local video device\n+ * \\param[in] count Number of buffers to allocate\n+ * \\param[out] buffers Vector to store local buffers\n+ * \\return 0 on success or a negative error code otherwise\n+ */\n+int V4L2VideoDevice::allocateBuffers(unsigned int count, std::vector<FrameBuffer *> *buffers)\n+{\n+\tunsigned int i;\n+\tint ret;\n+\n+\tif (cache_) {\n+\t\tLOG(V4L2, Error) << \"Can't allocate buffers when cache exists\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tmemoryType_ = V4L2_MEMORY_MMAP;\n+\n+\tret = requestBuffers(count);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tfor (i = 0; i < count; ++i) {\n+\t\tstruct v4l2_buffer buf = {};\n+\t\tstruct v4l2_plane planes[VIDEO_MAX_PLANES] = {};\n+\n+\t\tbuf.index = i;\n+\t\tbuf.type = bufferType_;\n+\t\tbuf.memory = memoryType_;\n+\t\tbuf.length = VIDEO_MAX_PLANES;\n+\t\tbuf.m.planes = planes;\n+\n+\t\tret = ioctl(VIDIOC_QUERYBUF, &buf);\n+\t\tif (ret < 0) {\n+\t\t\tLOG(V4L2, Error)\n+\t\t\t\t<< \"Unable to query buffer \" << i << \": \"\n+\t\t\t\t<< strerror(-ret);\n+\t\t\tgoto err_buf;\n+\t\t}\n+\n+\t\tFrameBuffer *buffer = createBuffer(buf);\n+\t\tif (!buffer) {\n+\t\t\tLOG(V4L2, Error) << \"Unable to create buffer\";\n+\t\t\tret = -EINVAL;\n+\t\t\tgoto err_buf;\n+\t\t}\n+\n+\t\tbuffers->push_back(buffer);\n+\t}\n+\n+\tcache_ = new V4L2BufferCache(*buffers);\n+\n+\treturn count;\n+err_buf:\n+\trequestBuffers(0);\n+\n+\tfor (FrameBuffer *buffer : *buffers)\n+\t\tdelete buffer;\n+\n+\tbuffers->clear();\n+\n+\treturn ret;\n+}\n+\n+FrameBuffer *V4L2VideoDevice::createBuffer(struct v4l2_buffer buf)\n+{\n+\tconst unsigned int numPlanes = V4L2_TYPE_IS_MULTIPLANAR(buf.type) ? buf.length : 1;\n+\tstd::vector<FrameBuffer::Plane> planes;\n+\tFrameBuffer *frame = nullptr;\n+\n+\tfor (unsigned int nplane = 0; nplane < numPlanes; nplane++) {\n+\t\tint fd = exportDmaBuffer(buf.index, nplane);\n+\t\tif (fd < 0)\n+\t\t\tgoto out;\n+\n+\t\tFrameBuffer::Plane plane;\n+\t\tplane.fd = fd;\n+\t\tplane.length = V4L2_TYPE_IS_MULTIPLANAR(buf.type) ?\n+\t\t\tbuf.m.planes[nplane].length : buf.length;\n+\n+\t\tplanes.emplace_back(plane);\n+\t}\n+\n+\tif (!planes.empty())\n+\t\tframe = new FrameBuffer(planes);\n+\telse\n+\t\tLOG(V4L2, Error) << \"Failed to get planes\";\n+out:\n+\tfor (FrameBuffer::Plane &plane : planes)\n+\t\t::close(plane.fd);\n+\n+\treturn frame;\n+}\n+\n int V4L2VideoDevice::exportDmaBuffer(unsigned int index, unsigned int plane)\n {\n \tstruct v4l2_exportbuffer expbuf = {};\n@@ -1062,6 +1157,35 @@ int V4L2VideoDevice::exportDmaBuffer(unsigned int index, unsigned int plane)\n \treturn expbuf.fd;\n }\n \n+/**\n+ * \\brief Operate using buffers imported from external source\n+ * \\param[in] count Number of buffers to prepare for\n+ * \\return 0 on success or a negative error code otherwise\n+ */\n+int V4L2VideoDevice::externalBuffers(unsigned int count)\n+{\n+\t/*\n+\t* We can only prepare the device to use external buffers when no\n+\t* internal buffers have been allocated.\n+\t*/\n+\tif (cache_)\n+\t\treturn 0;\n+\n+\tint ret;\n+\n+\tmemoryType_ = V4L2_MEMORY_DMABUF;\n+\n+\tret = requestBuffers(count);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tcache_ = new V4L2BufferCache(count);\n+\n+\tLOG(V4L2, Debug) << \"provided for \" << count << \" external buffers\";\n+\n+\treturn 0;\n+}\n+\n /**\n  * \\brief Release all internally allocated buffers\n  */\n","prefixes":["libcamera-devel","19/30"]}