From patchwork Sun Feb 3 11:00:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 488 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2D68660DB8 for ; Sun, 3 Feb 2019 12:01:07 +0100 (CET) Received: from localhost.localdomain (218.182-78-194.adsl-static.isp.belgacom.be [194.78.182.218]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A97835AA; Sun, 3 Feb 2019 12:01:06 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1549191666; bh=6IEmseyYCDF7xAtlbgbit0IeGxn/U4GY5MhKc462adI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZEUEy6Bumu2yw9oSf5sGD6SudSHxeN+f3nIkolNzvqmGc+Rgky+8ev5AwYRG7r7gz GPvNmDcGiW92HhjL2psGl9sF3S/8H1uN0js3Nneoj0IKziWKmVlJ5u1A+KO5ZCScBC 1jNwls9GMYQPcAAcf5ELOXNHOXL+je7NdqOVtRLs= From: Kieran Bingham To: LibCamera Devel Date: Sun, 3 Feb 2019 12:00:52 +0100 Message-Id: <20190203110102.5663-2-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> References: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 01/11] test: v4l2_device: Use DeviceEnumerator to find a UVCVideo X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 03 Feb 2019 11:01:07 -0000 Utilise the existing DeviceEnumerator system to identify a suitable V4L2Device for testing. Specifically target these tests at a uvcvideo driver based device as a known supported target. Signed-off-by: Kieran Bingham --- test/v4l2_device/v4l2_device_test.cpp | 28 +++++++++++++++++++++------ test/v4l2_device/v4l2_device_test.h | 7 +++++++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/test/v4l2_device/v4l2_device_test.cpp b/test/v4l2_device/v4l2_device_test.cpp index 362553712caa..e71a93cf2453 100644 --- a/test/v4l2_device/v4l2_device_test.cpp +++ b/test/v4l2_device/v4l2_device_test.cpp @@ -10,6 +10,10 @@ #include "v4l2_device_test.h" +#include "device_enumerator.h" +#include "media_device.h" + +using namespace std; using namespace libcamera; bool exists(const std::string &path) @@ -24,20 +28,32 @@ bool exists(const std::string &path) int V4L2DeviceTest::init() { - const std::string device("/dev/video0"); + enumerator_ = DeviceEnumerator::create(); + if (!enumerator_) { + cerr << "Failed to create device enumerator" << endl; + return TestFail; + } - /* Validate the device node exists. */ - if (!exists(device)) { - std::cout << "No video device available" << std::endl; - return TestSkip; + if (enumerator_->enumerate()) { + cerr << "Failed to enumerate media devices" << endl; + return TestFail; } - dev_ = new V4L2Device(device); + DeviceMatch dm("uvcvideo"); + media_ = std::move(enumerator_->search(dm)); + if (!media_) + return TestSkip; + + media_->acquire(); + + dev_ = new V4L2Device(*media_->entities()[0]); return dev_->open(); } void V4L2DeviceTest::cleanup() { + media_->release(); + delete dev_; }; diff --git a/test/v4l2_device/v4l2_device_test.h b/test/v4l2_device/v4l2_device_test.h index 405cb7d6f404..d8652a5c9e15 100644 --- a/test/v4l2_device/v4l2_device_test.h +++ b/test/v4l2_device/v4l2_device_test.h @@ -7,7 +7,12 @@ #ifndef __LIBCAMERA_V4L2_DEVICE_TEST_H_ #define __LIBCAMERA_V4L2_DEVICE_TEST_H_ +#include + #include "test.h" + +#include "device_enumerator.h" +#include "media_device.h" #include "v4l2_device.h" using namespace libcamera; @@ -21,6 +26,8 @@ protected: int init(); void cleanup(); + std::unique_ptr enumerator_; + std::shared_ptr media_; V4L2Device *dev_; }; From patchwork Sun Feb 3 11:00:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 489 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4594260B1B for ; Sun, 3 Feb 2019 12:01:07 +0100 (CET) Received: from localhost.localdomain (218.182-78-194.adsl-static.isp.belgacom.be [194.78.182.218]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id DFEBBD4A; Sun, 3 Feb 2019 12:01:06 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1549191667; bh=nne7oU1/bxd+Fc8K/U1tQc528Ql3yyAVTq5vnd9egA0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Hs3gWRHjUo7ahm4JEEs50o/Q6NG7Lm2Jbrv9vDHQSVI65JXxNAnCpnKMoxq50Htdf Q8tSUGmkmdBidAyBmhSEl9HhGopMztuzoQSECJU38tiqbf8FLkBpb2DSeR+KfW70NZ 50qznOM39EqHqYwLKtHUXrWrO3wBXYn8R8fhQNQ4= From: Kieran Bingham To: LibCamera Devel Date: Sun, 3 Feb 2019 12:00:53 +0100 Message-Id: <20190203110102.5663-3-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> References: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 02/11] libcamera: buffer: Support v4l2_buffer construction X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 03 Feb 2019 11:01:07 -0000 Provide a constructor to create a Buffer object directly from a v4l2_buffer as a V4L2Buffer type. This allows the Buffers to be created directly following a v4l2_reqbufs operation. Signed-off-by: Kieran Bingham --- include/libcamera/buffer.h | 2 +- src/libcamera/buffer.cpp | 27 +++++++++++++++++++++++++++ src/libcamera/include/v4l2_device.h | 8 ++++++++ src/libcamera/v4l2_device.cpp | 27 +++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 1 deletion(-) diff --git a/include/libcamera/buffer.h b/include/libcamera/buffer.h index afe99d5c4ab0..e730fc0f84fd 100644 --- a/include/libcamera/buffer.h +++ b/include/libcamera/buffer.h @@ -46,7 +46,7 @@ public: unsigned int index() const { return index_; }; const std::vector &planes() { return planes_; }; -private: +protected: unsigned int index_; unsigned int format_; diff --git a/src/libcamera/buffer.cpp b/src/libcamera/buffer.cpp index 887863b2af2e..c21994d7c035 100644 --- a/src/libcamera/buffer.cpp +++ b/src/libcamera/buffer.cpp @@ -10,6 +10,8 @@ #include #include +#include + #include #include "log.h" @@ -241,6 +243,31 @@ int Buffer::munmap() * \brief Return a reference to the vector holding all Planes within the buffer */ +/** + * \enum Buffer::BufferType + * \brief Identify the type of buffer for derived types + * + * Buffers may be derived to support specific buffer type features on top of the + * generic interface. The BufferType is used internally to assert compatibility + * in the event of any generic Buffer object being upcast to a specific type. + */ + +/** + * \var Buffer::BufferTypeGeneric + * \brief The Buffer can only be supported through the public Buffer API + */ + +/** + * \var Buffer::BufferTypeV4L2 + * \brief The Buffer can supported through both the public Buffer API and the + * internal V4L2 API. + */ + +/** + * \var Buffer::type_ + * \brief An internal BufferType to describe the construction of the Buffer. + */ + /** * \class BufferPool * \brief A pool of buffers diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h index f68b2b1df525..9e9eada94130 100644 --- a/src/libcamera/include/v4l2_device.h +++ b/src/libcamera/include/v4l2_device.h @@ -11,6 +11,8 @@ #include +#include + namespace libcamera { struct V4L2Capability final : v4l2_capability { @@ -53,6 +55,12 @@ struct V4L2Capability final : v4l2_capability { } }; +class V4L2Buffer : public Buffer +{ +public: + V4L2Buffer(struct v4l2_buffer &vb); +}; + class V4L2DeviceFormat { public: diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 5c415d0bddbc..d507ea9700b3 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -80,6 +80,33 @@ LOG_DEFINE_CATEGORY(V4L2) * \return True if the device provides Streaming I/O IOCTLs */ +/** + * \brief Construct a Buffer object from a v4l2_buffer description + * + * Buffers are abstracted in the same format regardless of using the single + * planar API or multi-planar API. The buffer object contains a Plane for each + * memory plane required to represent the buffer. + */ +V4L2Buffer::V4L2Buffer(struct v4l2_buffer &vb) + : Buffer() +{ + index_ = vb.index; + + if (V4L2_TYPE_IS_MULTIPLANAR(vb.type)) { + unsigned int i; + for (i = 0; i < vb.length; ++i) { + /* TODO: dmaBuf should retrieve FD here */ + Plane *plane = new Plane(vb.m.planes[i].length, + vb.m.planes[i].m.mem_offset); + planes_.push_back(plane); + } + } else { + /* TODO: dmaBuf should retrieve FD here */ + Plane *plane = new Plane(vb.length, vb.m.offset); + planes_.push_back(plane); + } +} + /** * \class V4L2DeviceFormat * \brief The V4L2 device image format and sizes From patchwork Sun Feb 3 11:00:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 490 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 776EF60DB8 for ; Sun, 3 Feb 2019 12:01:07 +0100 (CET) Received: from localhost.localdomain (218.182-78-194.adsl-static.isp.belgacom.be [194.78.182.218]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 24DF741; Sun, 3 Feb 2019 12:01:07 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1549191667; bh=vADjpcRolxRvmqMSCf9mbfAOlHvYZfvFHgaf20N6v7U=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ecayt8CmuFd1N784orcPDUEoiUrVO2P/mGtVwe6ywks4ErONXmbAkTkTZAb3JlzD8 htgd3fusIxV5u91/l3lWBzX24PXnlKXAmMVhHUZndnIrgPhIizsmvBxIjgd5wGGFzM VER563935bZFZozVAAqdakRMIaID9y51jzky7E9Q= From: Kieran Bingham To: LibCamera Devel Date: Sun, 3 Feb 2019 12:00:54 +0100 Message-Id: <20190203110102.5663-4-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> References: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 03/11] libcamera: v4l2_device: Request buffers from the device X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 03 Feb 2019 11:01:07 -0000 Provide a requestBuffers() interface to allocate buffers from the V4L2Device and keep a vector of the buffers in the V4L2Device object for later queue and dequeue operations. Signed-off-by: Kieran Bingham --- include/libcamera/buffer.h | 4 +- src/libcamera/include/v4l2_device.h | 10 +++ src/libcamera/v4l2_device.cpp | 111 +++++++++++++++++++++++++++- 3 files changed, 122 insertions(+), 3 deletions(-) diff --git a/include/libcamera/buffer.h b/include/libcamera/buffer.h index e730fc0f84fd..97fab5c65cce 100644 --- a/include/libcamera/buffer.h +++ b/include/libcamera/buffer.h @@ -71,10 +71,10 @@ public: void free(); unsigned int count() const { return buffers_.size(); }; - const std::vector &buffers() { return buffers_; }; + std::vector &buffers() { return buffers_; }; private: - virtual int allocateMemory() = 0; + virtual int allocateMemory() { return 0; }; BufferPool::Memory memory_; std::vector buffers_; diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h index 9e9eada94130..6599ce2d761c 100644 --- a/src/libcamera/include/v4l2_device.h +++ b/src/libcamera/include/v4l2_device.h @@ -8,6 +8,7 @@ #define __LIBCAMERA_V4L2_DEVICE_H__ #include +#include #include @@ -76,6 +77,7 @@ public: }; class MediaEntity; + class V4L2Device { public: @@ -97,6 +99,8 @@ public: int format(V4L2DeviceFormat *fmt); int setFormat(V4L2DeviceFormat *fmt); + BufferPool *requestBuffers(unsigned int qty = 8); + private: int getFormatSingleplane(V4L2DeviceFormat *fmt); int setFormatSingleplane(V4L2DeviceFormat *fmt); @@ -104,10 +108,16 @@ private: int getFormatMultiplane(V4L2DeviceFormat *fmt); int setFormatMultiplane(V4L2DeviceFormat *fmt); + int requestBuffers(unsigned int qty, std::vector &buffers); + std::string deviceNode_; int fd_; V4L2Capability caps_; + enum v4l2_buf_type bufferType_; + enum v4l2_memory memoryType_; + + BufferPool *bufferPool_; }; } /* namespace libcamera */ diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index d507ea9700b3..8bcd8bbc34f6 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -10,6 +10,9 @@ #include #include #include +#include + +#include #include "log.h" #include "media_object.h" @@ -187,8 +190,14 @@ V4L2Buffer::V4L2Buffer(struct v4l2_buffer &vb) * \param deviceNode The file-system path to the video device node */ V4L2Device::V4L2Device(const std::string &deviceNode) - : deviceNode_(deviceNode), fd_(-1) + : deviceNode_(deviceNode), fd_(-1), bufferPool_(nullptr) { + /* + * We default to an MMAP based CAPTURE device, however this will be + * updated based upon the device capabilities. + */ + bufferType_ = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + memoryType_ = V4L2_MEMORY_MMAP; } /** @@ -205,6 +214,8 @@ V4L2Device::V4L2Device(const MediaEntity &entity) V4L2Device::~V4L2Device() { close(); + + delete bufferPool_; } /** @@ -305,6 +316,104 @@ void V4L2Device::close() * \return The string containing the device location */ +/** + * \brief Request \a qty buffers to be allocated from the device and returned + * as a BufferPool + * \return A BufferPool containing the device buffers, or nullptr if the + * allocation fails + */ +BufferPool *V4L2Device::requestBuffers(unsigned int qty) +{ + int ret; + + if (bufferPool_) { + LOG(V4L2, Warning) << "Pre-existing buffer pool will be lost"; + delete bufferPool_; + } + + bufferPool_ = new BufferPool(BufferPool::Internal); + + ret = requestBuffers(qty, bufferPool_->buffers()); + if (ret) { + delete bufferPool_; + bufferPool_ = nullptr; + return nullptr; + } + + return bufferPool_; +} + +/** + * \brief Request \a qty buffers from the V4L2Device and track Buffer + * representations within the specified \a buffers target. + */ +int V4L2Device::requestBuffers(unsigned int qty, std::vector &buffers) +{ + struct v4l2_requestbuffers rb = {}; + unsigned int i; + int ret; + + rb.count = qty; + rb.type = bufferType_; + rb.memory = memoryType_; /** \todo Support dmaBuf memoryTypes */ + + ret = ioctl(fd_, VIDIOC_REQBUFS, &rb); + if (ret < 0) { + ret = -errno; + LOG(V4L2, Error) + << "Unable to request " << qty << " buffers: " + << strerror(-ret); + return ret; + } + + LOG(V4L2, Debug) + << deviceNode_ << ":" << rb.count << " buffers requested."; + + if (memoryType_ != V4L2_MEMORY_MMAP) { + LOG(V4L2, Error) + << "Non-mmap allocations are not yet supported."; + return -EINVAL; + } + + /* Map the buffers. */ + for (i = 0; i < rb.count; ++i) { + struct v4l2_plane planes[VIDEO_MAX_PLANES] = {}; + struct v4l2_buffer buf = {}; + struct Buffer *buffer; + + buf.index = i; + buf.type = bufferType_; + buf.memory = memoryType_; + buf.length = VIDEO_MAX_PLANES; + buf.m.planes = planes; + + ret = ioctl(fd_, VIDIOC_QUERYBUF, &buf); + if (ret < 0) { + LOG(V4L2, Error) + << "Unable to query buffer " << i << ": " + << strerror(errno); + return ret; + } + + if (V4L2_TYPE_IS_MULTIPLANAR(buf.type)) { + for (unsigned int p = 0; p < buf.length; ++p) + LOG(V4L2, Debug) + << "plane: " << p + << " length: " << buf.m.planes[p].length + << " offset: " + << buf.m.planes[p].data_offset; + } else { + LOG(V4L2, Debug) << "length: " << buf.length + << " offset: " << buf.m.offset; + } + + buffer = new V4L2Buffer(buf); + buffers.push_back(buffer); + } + + return 0; +} + /** * \brief Retrieve the image format set on the V4L2 device * \return 0 for success, a negative error code otherwise From patchwork Sun Feb 3 11:00:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 491 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AEF0260B1B for ; Sun, 3 Feb 2019 12:01:07 +0100 (CET) Received: from localhost.localdomain (218.182-78-194.adsl-static.isp.belgacom.be [194.78.182.218]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 5B4BFD4B; Sun, 3 Feb 2019 12:01:07 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1549191667; bh=ApbnUKVZtAMnEj3TtinpMY7Bpb+TnV7zi2Y0DX8u63s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=D39BaXHSADMjrhNtQt/oaCJAsLYGcVq9GQ4Fgty9zCUnBoHonPlrn8bQB9ELWjOk9 A30v9jq4RugIEA36XvRiKELVlykuWcp5jzYSuGJaaYgkLPIml9aiLtkw/Nvo1E11Xy JbcVYtGaKvCK44EOA5ISDRF465VBfav0XtTpVdNE= From: Kieran Bingham To: LibCamera Devel Date: Sun, 3 Feb 2019 12:00:55 +0100 Message-Id: <20190203110102.5663-5-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> References: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 04/11] libcamera: v4l2_device: Support exporting buffers X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 03 Feb 2019 11:01:07 -0000 Implement the VIDIOC_EXPBUF functionality allowing our buffers to be exported to other V4L2Device objects. Export buffers when they are allocated during a call to requestBuffers() Signed-off-by: Kieran Bingham --- src/libcamera/include/v4l2_device.h | 2 + src/libcamera/v4l2_device.cpp | 59 +++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h index 6599ce2d761c..f445f98f97a4 100644 --- a/src/libcamera/include/v4l2_device.h +++ b/src/libcamera/include/v4l2_device.h @@ -109,6 +109,8 @@ private: int setFormatMultiplane(V4L2DeviceFormat *fmt); int requestBuffers(unsigned int qty, std::vector &buffers); + int exportBuffer(Buffer *buffer); + int exportBuffers(BufferPool *pool); std::string deviceNode_; int fd_; diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 8bcd8bbc34f6..728478a1ae8f 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -340,6 +340,13 @@ BufferPool *V4L2Device::requestBuffers(unsigned int qty) return nullptr; } + ret = exportBuffers(bufferPool_); + if (ret) { + delete bufferPool_; + bufferPool_ = nullptr; + return nullptr; + } + return bufferPool_; } @@ -414,6 +421,58 @@ int V4L2Device::requestBuffers(unsigned int qty, std::vector &buffers) return 0; } +int V4L2Device::exportBuffer(Buffer *buffer) +{ + unsigned int i = 0; + for (Plane *plane : buffer->planes()) { + struct v4l2_exportbuffer expbuf = {}; + int ret; + + expbuf.type = bufferType_; + expbuf.index = buffer->index(); + expbuf.plane = i++; + + ret = ioctl(fd_, VIDIOC_EXPBUF, &expbuf); + if (ret < 0) { + ret = -errno; + LOG(V4L2, Error) + << "Failed to export buffer: " << strerror(-ret); + return ret; + } + + plane->setDmabuf(expbuf.fd); + } + + return 0; +} + +int V4L2Device::exportBuffers(BufferPool *pool) +{ + for (Buffer *buffer : pool->buffers()) { + int ret = exportBuffer(buffer); + if (ret) + return ret; + + /** + * \todo: Remove this mmap + * It is a temporary work around to have all internal buffers + * mapped for early development. + * + * Applications will be expected to map buffers if necessary. + */ + ret = buffer->mmap(); + if (ret) { + ret = -errno; + LOG(V4L2, Error) + << "Failed to mmap a buffer instance: " + << strerror(-ret); + return ret; + } + } + + return 0; +} + /** * \brief Retrieve the image format set on the V4L2 device * \return 0 for success, a negative error code otherwise From patchwork Sun Feb 3 11:00:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 492 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E7DD460B1B for ; Sun, 3 Feb 2019 12:01:07 +0100 (CET) Received: from localhost.localdomain (218.182-78-194.adsl-static.isp.belgacom.be [194.78.182.218]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 936F85AA; Sun, 3 Feb 2019 12:01:07 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1549191667; bh=2lZdF4EKlfd+Qs7P7uWQt6FhfoMHH8BdFkjfYeFpk1Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qjc3/GC66Vx8ksESPpYYmH3wtCqygQmOaW1aodtmktSFuE0/9XmwesFFY9CXZbTyw y8s6Ht0B3gumKqzAumwlxw7bF9MiXT1tx6Fy9tdB1Ezybi3mpMA4KjXB4pztLimQp9 S7gOh7hQkl2QfuCcEECXfCpP3YHb2eJtFtLLib/Q= From: Kieran Bingham To: LibCamera Devel Date: Sun, 3 Feb 2019 12:00:56 +0100 Message-Id: <20190203110102.5663-6-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> References: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 05/11] test: v4l2_device: Add request_buffers test X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 03 Feb 2019 11:01:08 -0000 Add a utility to the test suite to request and allocate buffers from a V4L2Device to ensure it functions successfully. Signed-off-by: Kieran Bingham --- test/v4l2_device/meson.build | 1 + test/v4l2_device/request_buffers.cpp | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 test/v4l2_device/request_buffers.cpp diff --git a/test/v4l2_device/meson.build b/test/v4l2_device/meson.build index 41675a303498..b6b672611d60 100644 --- a/test/v4l2_device/meson.build +++ b/test/v4l2_device/meson.build @@ -2,6 +2,7 @@ # They are not alphabetically sorted. v4l2_device_tests = [ [ 'double_open', 'double_open.cpp' ], + [ 'request_buffers', 'request_buffers.cpp' ], ] foreach t : v4l2_device_tests diff --git a/test/v4l2_device/request_buffers.cpp b/test/v4l2_device/request_buffers.cpp new file mode 100644 index 000000000000..8ab0f560516f --- /dev/null +++ b/test/v4l2_device/request_buffers.cpp @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * libcamera V4L2 API tests + */ + +#include "v4l2_device_test.h" + +class RequestBuffers : public V4L2DeviceTest +{ +protected: + int run() + { + /* TODO: + * Test invalid requests + * Test different buffer allocations + */ + BufferPool *pool = dev_->requestBuffers(8); + + if (!pool) + return TestFail; + + return TestPass; + } +}; + +TEST_REGISTER(RequestBuffers); From patchwork Sun Feb 3 11:00:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 493 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2D24C60B1B for ; Sun, 3 Feb 2019 12:01:08 +0100 (CET) Received: from localhost.localdomain (218.182-78-194.adsl-static.isp.belgacom.be [194.78.182.218]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id CADFB41; Sun, 3 Feb 2019 12:01:07 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1549191667; bh=0fw5UjSZFZh+JNXV5ehFKNSCl3dpJv03wlB0ejGnFxw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=d4JlOo9nWB+zXVff09eLt7wMSA3D7HqN2nwHd4WcCPLNXCd5OsnQF7KxuxgCgQMa8 bOGOUUKKOWkaaKJ5hQTdfeAAH4GpL+y8wi4qJnrDvcfItzQETKc4+JTotUdbuihAgi r0Ul37tvl+m+MBPwAHp8ZcppX9PEsnlUEqEvtafM= From: Kieran Bingham To: LibCamera Devel Date: Sun, 3 Feb 2019 12:00:57 +0100 Message-Id: <20190203110102.5663-7-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> References: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 06/11] libcamera: v4l2_device: Implement stream{On, Off} X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 03 Feb 2019 11:01:08 -0000 Support starting and stopping a stream on a V4L2 device. This requires having buffers queued, thus both queueBuffer() and dequeueBuffer() are also added. Signed-off-by: Kieran Bingham --- src/libcamera/include/v4l2_device.h | 6 ++ src/libcamera/v4l2_device.cpp | 134 ++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h index f445f98f97a4..d3dad355be58 100644 --- a/src/libcamera/include/v4l2_device.h +++ b/src/libcamera/include/v4l2_device.h @@ -101,6 +101,12 @@ public: BufferPool *requestBuffers(unsigned int qty = 8); + int queueBuffer(Buffer *frame); + Buffer *dequeueBuffer(); + + int streamOn(); + int streamOff(); + private: int getFormatSingleplane(V4L2DeviceFormat *fmt); int setFormatSingleplane(V4L2DeviceFormat *fmt); diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 728478a1ae8f..1fd289137b36 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -592,4 +592,138 @@ int V4L2Device::setFormatMultiplane(V4L2DeviceFormat *fmt) return 0; } +/** + * \brief Queue a buffer into the device. + * + * For Capture devices the buffer will be operated on and can be dequeued later + * with active data. + * + * For Output devices the buffer should contain valid data and will be processed + * by the receiving device. The buffer will be available to dequeue when it is + * no longer in use by the Output device. + * + * \return 0 if the operation completes or a negative error number otherwise + */ +int V4L2Device::queueBuffer(Buffer *frame) +{ + struct v4l2_buffer buf = {}; + struct v4l2_plane planes[VIDEO_MAX_PLANES] = {}; + int ret; + + buf.index = frame->index(); + buf.type = bufferType_; + buf.memory = memoryType_; + + if (V4L2_TYPE_IS_MULTIPLANAR(buf.type)) { + buf.length = frame->planes().size(); + buf.m.planes = planes; + } + + LOG(V4L2, Debug) << "Queueing buffer idx: " << buf.index; + + ret = ioctl(fd_, VIDIOC_QBUF, &buf); + if (ret < 0) { + ret = -errno; + LOG(V4L2, Error) + << "Failed to queue buffer: " << strerror(-ret); + return ret; + } + + return 0; +} + +/** + * \brief dequeue a buffer from the device + * + * For Capture devices the buffer will be contain valid data and can be used for + * further processing. The buffer should be re-queued when it is no longer in + * use. + * + * For Output devices the buffer has been processed by the hardware and can now + * be freely re-used. + * + * \return A Buffer pointer if the operation completes or a nullptr otherwise + */ +Buffer *V4L2Device::dequeueBuffer() +{ + struct v4l2_buffer buf = {}; + struct v4l2_plane planes[VIDEO_MAX_PLANES] = {}; + int ret; + + buf.type = bufferType_; + buf.memory = memoryType_; + + if (V4L2_TYPE_IS_MULTIPLANAR(buf.type)) { + buf.length = VIDEO_MAX_PLANES; + buf.m.planes = planes; + } + + ret = ioctl(fd_, VIDIOC_DQBUF, &buf); + if (ret < 0) { + ret = -errno; + LOG(V4L2, Error) + << "Failed to dequeue buffer: " << strerror(-ret); + return nullptr; + } + + if (buf.index >= bufferPool_->buffers().size()) { + LOG(V4L2, Error) << "Invalid buffer index dequeued"; + return nullptr; + } + + return bufferPool_->buffers()[buf.index]; +} + +/** + * \brief Request that the V4L2Device commences streaming + * + * Prepares the device to start processing Buffers, and connects the completion + * handler to the bufferAvailable Slot. + * + * \return 0 if the operation completes or a negative error number otherwise + */ +int V4L2Device::streamOn() +{ + int ret; + + if (caps_.isCapture()) { + for (Buffer *b : bufferPool_->buffers()) { + ret = queueBuffer(b); + if (ret) + return ret; + } + } + + ret = ioctl(fd_, VIDIOC_STREAMON, &bufferType_); + if (ret < 0) { + ret = -errno; + LOG(V4L2, Error) + << "Failed to start streaming: " << strerror(-ret); + return ret; + } + + return 0; +} + +/** + * \brief Request that the V4L2Device stops streaming + * + * Asks the device to halt any current streaming operations. + * + * \return 0 if the operation completes or a negative error number otherwise + */ +int V4L2Device::streamOff() +{ + int ret; + + ret = ioctl(fd_, VIDIOC_STREAMOFF, &bufferType_); + if (ret < 0) { + LOG(V4L2, Error) + << "Failed to stop streaming: " << strerror(errno); + return ret; + } + + return 0; +} + } /* namespace libcamera */ From patchwork Sun Feb 3 11:00:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 494 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 64C4260DBE for ; Sun, 3 Feb 2019 12:01:08 +0100 (CET) Received: from localhost.localdomain (218.182-78-194.adsl-static.isp.belgacom.be [194.78.182.218]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 10112D4A; Sun, 3 Feb 2019 12:01:08 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1549191668; bh=h61nRg17APg4PX1uEULMKb1XlohppBJguIjPC9z7EbM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YCvMKPKcqZnm9ztPcX3fjNUJOLU8PRk8l5KKLqatRx/RlK2u0eMvqz1mUIS2iFWH2 kkmUIACsPNDIObo6z9dkKDDHli+S+AhlJ/f0W/mvonZ90uYWRngjiSj7D7GqlE8aDx MF27y120wZ/ehFkxLXyQ/fXMJvxJHHULBGQxT5GE= From: Kieran Bingham To: LibCamera Devel Date: Sun, 3 Feb 2019 12:00:58 +0100 Message-Id: <20190203110102.5663-8-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> References: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 07/11] test: v4l2_device: Add StreamOn/StreamOff test X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 03 Feb 2019 11:01:10 -0000 Provide a small test to exercise the streamOn() and streamOff() calls. 8 buffers are requested locally. Signed-off-by: Kieran Bingham --- test/v4l2_device/meson.build | 1 + test/v4l2_device/stream_on_off.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 test/v4l2_device/stream_on_off.cpp diff --git a/test/v4l2_device/meson.build b/test/v4l2_device/meson.build index b6b672611d60..cbaa79da9b81 100644 --- a/test/v4l2_device/meson.build +++ b/test/v4l2_device/meson.build @@ -3,6 +3,7 @@ v4l2_device_tests = [ [ 'double_open', 'double_open.cpp' ], [ 'request_buffers', 'request_buffers.cpp' ], + [ 'stream_on_off', 'stream_on_off.cpp' ], ] foreach t : v4l2_device_tests diff --git a/test/v4l2_device/stream_on_off.cpp b/test/v4l2_device/stream_on_off.cpp new file mode 100644 index 000000000000..9f1937b66aae --- /dev/null +++ b/test/v4l2_device/stream_on_off.cpp @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * libcamera V4L2 API tests + */ + +#include "v4l2_device_test.h" + +class StreamOnStreamOff : public V4L2DeviceTest +{ +protected: + int run() + { + int ret; + + BufferPool *pool = dev_->requestBuffers(8); + if (!pool) + return TestFail; + + ret = dev_->streamOn(); + if (ret) + return ret; + + return dev_->streamOff(); + } +}; + +TEST_REGISTER(StreamOnStreamOff); From patchwork Sun Feb 3 11:00:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 495 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 98FB760DD1 for ; Sun, 3 Feb 2019 12:01:08 +0100 (CET) Received: from localhost.localdomain (218.182-78-194.adsl-static.isp.belgacom.be [194.78.182.218]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 460815AA; Sun, 3 Feb 2019 12:01:08 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1549191668; bh=n2JjINr+mWY49vb4kt1nljqEvmVsceUWHcYrY14V15k=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HuINa73w0toz9UoZDJu6gbuOd4ECfunrgTTN6H1d/TT6wtmzP9utmSeCMnPLC/0+6 CNKtyoEqawTpiQE0APOYQEFnAQn4Pxu67Ym6xr0FWVxYja82TtxS/zhWHOyqXAT54/ 3kJUhHHvUQA392nSBV/E3vHY7KxdG8fgHxuWnM/k= From: Kieran Bingham To: LibCamera Devel Date: Sun, 3 Feb 2019 12:00:59 +0100 Message-Id: <20190203110102.5663-9-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> References: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 08/11] test: v4l2_device: Add a functional capture test X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 03 Feb 2019 11:01:10 -0000 We now have enough infrastructure to be able to capture frames from a basic UVC device. Provide a test loop which captures frames, and returns them back to the kernel. Signed-off-by: Kieran Bingham --- test/v4l2_device/capture_frames.cpp | 51 +++++++++++++++++++++++++++++ test/v4l2_device/meson.build | 1 + 2 files changed, 52 insertions(+) create mode 100644 test/v4l2_device/capture_frames.cpp diff --git a/test/v4l2_device/capture_frames.cpp b/test/v4l2_device/capture_frames.cpp new file mode 100644 index 000000000000..276be91a9a82 --- /dev/null +++ b/test/v4l2_device/capture_frames.cpp @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * libcamera V4L2 API tests + */ + +#include "v4l2_device_test.h" + +class CaptureFrames : public V4L2DeviceTest +{ +protected: + int run() + { + int ret; + + BufferPool *pool = dev_->requestBuffers(8); + if (!pool) + return TestFail; + + ret = dev_->streamOn(); + if (ret) + return ret; + + /* + * With no dispatcher loop, the internal asynchronous buffer + * retrieval will not operate. + * + * We can manually validate the dequeueBuffer() and + * queueBuffer() calls directly here. + * + * The application should not use these calls directly if it + * makes any calls to: + * dispatcher->processEvents(); + */ + for (unsigned int i; i < 30; ++i) { + auto buffer = dev_->dequeueBuffer(); + + /* Check buffer */ + if (!buffer) + return TestFail; + + if (dev_->queueBuffer(buffer)) + return TestFail; + } + + return dev_->streamOff(); + } +}; + +TEST_REGISTER(CaptureFrames); diff --git a/test/v4l2_device/meson.build b/test/v4l2_device/meson.build index cbaa79da9b81..f04c7ded009c 100644 --- a/test/v4l2_device/meson.build +++ b/test/v4l2_device/meson.build @@ -4,6 +4,7 @@ v4l2_device_tests = [ [ 'double_open', 'double_open.cpp' ], [ 'request_buffers', 'request_buffers.cpp' ], [ 'stream_on_off', 'stream_on_off.cpp' ], + [ 'capture_frames', 'capture_frames.cpp' ], ] foreach t : v4l2_device_tests From patchwork Sun Feb 3 11:01:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 496 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id CD40F60DB8 for ; Sun, 3 Feb 2019 12:01:08 +0100 (CET) Received: from localhost.localdomain (218.182-78-194.adsl-static.isp.belgacom.be [194.78.182.218]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7B524D4B; Sun, 3 Feb 2019 12:01:08 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1549191668; bh=Cmht+l0P+IHzGRpfCwRuAbBlWTJUaMyLBGZrKGZuKPs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LKxXvCbw/OgrFSvbVATRlSaLoTe87uf1BcBn3V90D09g/gexrDM06bdUzR2D7Fjv2 acO48N9nth93uSFqNiStcLft/Z8hV7zwGq4J0ycEhdL9Fn0gcZBF18q5pugsL4qNrf /Rno+u7p0Ndb/0KHuTWryYoFAVM0sjsTsvPKdsAQ= From: Kieran Bingham To: LibCamera Devel Date: Sun, 3 Feb 2019 12:01:00 +0100 Message-Id: <20190203110102.5663-10-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> References: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 09/11] libcamera: v4l2_device: Add event driven buffer passing X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 03 Feb 2019 11:01:10 -0000 Register an EventNotifier on our device file descriptor to be notified of EventNotifier::Read events. These signal that a buffer is ready for dequeing on the V4L2Device. A Buffer is dequeued, and passed through the bufferReady Signal. Signed-off-by: Kieran Bingham --- src/libcamera/include/v4l2_device.h | 7 ++++++ src/libcamera/v4l2_device.cpp | 39 +++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h index d3dad355be58..fbbddad68082 100644 --- a/src/libcamera/include/v4l2_device.h +++ b/src/libcamera/include/v4l2_device.h @@ -13,6 +13,7 @@ #include #include +#include namespace libcamera { @@ -107,6 +108,8 @@ public: int streamOn(); int streamOff(); + Signal bufferReady; + private: int getFormatSingleplane(V4L2DeviceFormat *fmt); int setFormatSingleplane(V4L2DeviceFormat *fmt); @@ -118,6 +121,8 @@ private: int exportBuffer(Buffer *buffer); int exportBuffers(BufferPool *pool); + void bufferAvailable(EventNotifier *notifier); + std::string deviceNode_; int fd_; V4L2Capability caps_; @@ -126,6 +131,8 @@ private: enum v4l2_memory memoryType_; BufferPool *bufferPool_; + + EventNotifier *fdEvent_; }; } /* namespace libcamera */ diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 1fd289137b36..630b43532c3e 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -13,6 +13,7 @@ #include #include +#include #include "log.h" #include "media_object.h" @@ -190,7 +191,8 @@ V4L2Buffer::V4L2Buffer(struct v4l2_buffer &vb) * \param deviceNode The file-system path to the video device node */ V4L2Device::V4L2Device(const std::string &deviceNode) - : deviceNode_(deviceNode), fd_(-1), bufferPool_(nullptr) + : deviceNode_(deviceNode), fd_(-1), bufferPool_(nullptr), + fdEvent_(nullptr) { /* * We default to an MMAP based CAPTURE device, however this will be @@ -674,6 +676,28 @@ Buffer *V4L2Device::dequeueBuffer() return bufferPool_->buffers()[buf.index]; } +/** + * \brief Slot to handle completed buffer events from the V4L2 device + * + * When this Slot is called, a Buffer has become available from the device, and + * will be emitted through the bufferReady Signal. + * + * For Capture devices the Buffer will be contain valid data. + * For Output devices the Buffer can be considered empty. + */ +void V4L2Device::bufferAvailable(EventNotifier *notifier) +{ + Buffer *buffer; + + LOG(V4L2, Debug) << "A buffer is available"; + + buffer = dequeueBuffer(); + + bufferReady.emit(buffer); + + queueBuffer(buffer); +} + /** * \brief Request that the V4L2Device commences streaming * @@ -702,13 +726,17 @@ int V4L2Device::streamOn() return ret; } + fdEvent_ = new EventNotifier(fd_, EventNotifier::Read); + fdEvent_->activated.connect(this, &V4L2Device::bufferAvailable); + return 0; } /** * \brief Request that the V4L2Device stops streaming * - * Asks the device to halt any current streaming operations. + * Asks the device to halt any current streaming operations and remove the event + * notifier registered against the device file descriptor. * * \return 0 if the operation completes or a negative error number otherwise */ @@ -723,7 +751,14 @@ int V4L2Device::streamOff() return ret; } + delete fdEvent_; + return 0; } +/** + * \var V4L2Device::bufferReady + * \brief A Signal handler which emits completed buffers. + */ + } /* namespace libcamera */ From patchwork Sun Feb 3 11:01:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 497 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0FFF760DD6 for ; Sun, 3 Feb 2019 12:01:09 +0100 (CET) Received: from localhost.localdomain (218.182-78-194.adsl-static.isp.belgacom.be [194.78.182.218]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id B1B0C41; Sun, 3 Feb 2019 12:01:08 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1549191668; bh=oDxTNucYy3vOWg1TqMKzYuhw/t7U6/nsw1sEYLipvrg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qd43pd34Hdx/YSHHDaVFFbtHILlpv3XzdFwb6DN5SvXPX6CAFbwnzmGg2orfo02hk AyTuw0j+ZdzAerOZeO4aQKX1bwf26MQFeqyYnLcqPu++weFXgSPK1plXAe7EzXsxc3 yk1TJBYcg1YDUA43b8fIdqJ+JC68F1ANEjtZSNXY= From: Kieran Bingham To: LibCamera Devel Date: Sun, 3 Feb 2019 12:01:01 +0100 Message-Id: <20190203110102.5663-11-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> References: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 10/11] test: v4l2_device: Provide asynchronous capture test X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 03 Feb 2019 11:01:10 -0000 Utilise the event_dispatcher to create a default event loop, and process asynchronous buffer receive events. If no frames are captured in 5 seconds, the test will fail. It will also fail if less than 30 frames have been captured int the same timeout period. Signed-off-by: Kieran Bingham --- test/v4l2_device/capture_async.cpp | 69 ++++++++++++++++++++++++++++++ test/v4l2_device/meson.build | 1 + 2 files changed, 70 insertions(+) create mode 100644 test/v4l2_device/capture_async.cpp diff --git a/test/v4l2_device/capture_async.cpp b/test/v4l2_device/capture_async.cpp new file mode 100644 index 000000000000..70f340dba3f1 --- /dev/null +++ b/test/v4l2_device/capture_async.cpp @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * libcamera V4L2 API tests + */ + +#include +#include +#include +#include + +#include + +#include "v4l2_device_test.h" + +class CaptureAsync : public V4L2DeviceTest +{ +public: + CaptureAsync() + : frames(0){}; + + void ReceiveBuffer(Buffer *buffer) + { + std::cout << "Received a Buffer" << std::endl; + frames++; + } + +protected: + int run() + { + EventDispatcher *dispatcher = CameraManager::instance()->eventDispatcher(); + Timer timeout; + int ret; + + BufferPool *pool = dev_->requestBuffers(8); + if (!pool) + return TestFail; + + dev_->bufferReady.connect(this, &CaptureAsync::ReceiveBuffer); + + ret = dev_->streamOn(); + if (ret) + return ret; + + timeout.start(5000); + while (timeout.isRunning()) + dispatcher->processEvents(); + + if (frames < 1) { + std::cout << "Failed to capture any frames within timeout." << std::endl; + return TestFail; + } + + if (frames < 30) { + std::cout << "Failed to capture 30 frames within timeout." << std::endl; + return TestFail; + } + + std::cout << "Processed " << frames << " frames" << std::endl; + + return dev_->streamOff(); + } + +private: + unsigned int frames; +}; + +TEST_REGISTER(CaptureAsync); diff --git a/test/v4l2_device/meson.build b/test/v4l2_device/meson.build index f04c7ded009c..2a37b7b06134 100644 --- a/test/v4l2_device/meson.build +++ b/test/v4l2_device/meson.build @@ -5,6 +5,7 @@ v4l2_device_tests = [ [ 'request_buffers', 'request_buffers.cpp' ], [ 'stream_on_off', 'stream_on_off.cpp' ], [ 'capture_frames', 'capture_frames.cpp' ], + [ 'capture_async', 'capture_async.cpp' ], ] foreach t : v4l2_device_tests From patchwork Sun Feb 3 11:01:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 498 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 48A5D60DBF for ; Sun, 3 Feb 2019 12:01:09 +0100 (CET) Received: from localhost.localdomain (218.182-78-194.adsl-static.isp.belgacom.be [194.78.182.218]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E777A5AA; Sun, 3 Feb 2019 12:01:08 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1549191669; bh=xd95viNIHdkTi2L4JZPRetCmmmWxPGMMERwPWaUI7gk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BeN9QsPUInoU6CeR4Jj1ILeCMSN2EUFwuDsJzwNEXvEO2WFWnCZfvL53+LkBEiAD5 JsPaVgyvQybD6IZGZCHd7a8cZjo0K7143+I7VN85tUASER3hOgg0ONP1YsAGoMlEIU K7dPf+Kd2Ws5gbh+5h1VZ7IvdgBv5n0PeuOzHhQE= From: Kieran Bingham To: LibCamera Devel Date: Sun, 3 Feb 2019 12:01:02 +0100 Message-Id: <20190203110102.5663-12-kieran.bingham@ideasonboard.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> References: <20190203110102.5663-1-kieran.bingham@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 11/11] libcamera: v4l2device: update Buffer with information from v4l2_buffer when dequeueing X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 03 Feb 2019 11:01:10 -0000 From: Niklas Söderlund Copy the information from the struct v4l2_buffer when dequeueing the buffer as applications need this information to make sens of the captured data. Signed-off-by: Niklas Söderlund [Kieran: Re-adapt to use the V4L2Buffer class casting] --- include/libcamera/buffer.h | 12 ++++++++++++ src/libcamera/include/v4l2_device.h | 2 ++ src/libcamera/v4l2_device.cpp | 17 ++++++++++++++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/include/libcamera/buffer.h b/include/libcamera/buffer.h index 97fab5c65cce..b4dd0851bc7f 100644 --- a/include/libcamera/buffer.h +++ b/include/libcamera/buffer.h @@ -7,6 +7,7 @@ #ifndef __LIBCAMERA_BUFFER_H__ #define __LIBCAMERA_BUFFER_H__ +#include #include namespace libcamera { @@ -46,8 +47,19 @@ public: unsigned int index() const { return index_; }; const std::vector &planes() { return planes_; }; + unsigned int bytesused() const { return bytesused_; }; + unsigned int flags() const { return flags_; }; + unsigned int field() const { return field_; }; + struct timeval timestamp() const { return timestamp_; }; + unsigned int sequence() const { return sequence_; }; + protected: unsigned int index_; + unsigned int bytesused_; + unsigned int flags_; + unsigned int field_; + struct timeval timestamp_; + unsigned int sequence_; unsigned int format_; unsigned int width_; diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h index fbbddad68082..641362ff594c 100644 --- a/src/libcamera/include/v4l2_device.h +++ b/src/libcamera/include/v4l2_device.h @@ -61,6 +61,8 @@ class V4L2Buffer : public Buffer { public: V4L2Buffer(struct v4l2_buffer &vb); + + void update(struct v4l2_buffer &vb); }; class V4L2DeviceFormat diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 630b43532c3e..7fafe2af393d 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -111,6 +112,16 @@ V4L2Buffer::V4L2Buffer(struct v4l2_buffer &vb) } } +void V4L2Buffer::update(struct v4l2_buffer &vb) +{ + /* Update buffer information */ + bytesused_ = vb.bytesused; + flags_ = vb.flags; + field_ = vb.field; + timestamp_ = vb.timestamp; + sequence_ = vb.sequence; +} + /** * \class V4L2DeviceFormat * \brief The V4L2 device image format and sizes @@ -673,7 +684,11 @@ Buffer *V4L2Device::dequeueBuffer() return nullptr; } - return bufferPool_->buffers()[buf.index]; + V4L2Buffer *b; + b = reinterpret_cast(bufferPool_->buffers()[buf.index]); + b->update(buf); + + return b; } /**