From patchwork Tue Nov 26 23:36:12 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 2370 Return-Path: Received: from bin-mail-out-06.binero.net (bin-mail-out-06.binero.net [195.74.38.229]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7B2F361C65 for ; Wed, 27 Nov 2019 00:39:43 +0100 (CET) X-Halon-ID: 03c6c4dd-10a6-11ea-a0b9-005056917f90 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (p54ac5865.dip0.t-ipconnect.de [84.172.88.101]) by bin-vsp-out-02.atm.binero.net (Halon) with ESMTPA id 03c6c4dd-10a6-11ea-a0b9-005056917f90; Wed, 27 Nov 2019 00:39:41 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Wed, 27 Nov 2019 00:36:12 +0100 Message-Id: <20191126233620.1695316-23-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 Subject: [libcamera-devel] [PATCH 22/30] libcamera: v4l2_videodevice: Add V4L2Stream to facilitate buffers X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 26 Nov 2019 23:39:43 -0000 In the FrameBuffer interface the streams and not the pipelines abstracts the knowledge about how and if buffers needs to be allocated or prepared before a capture session is started. The rational behind this model is the V4L2 API where if applications needs to allocate memory for buffers it do that using a video node and not using a external allocator. As the video node needs to be prepared in different ways depending on if it have been used for memory allocation or not each streams facing applications needs not only be available to be used to allocated buffers but track if they have been so in order to be started correctly. This change implements the interface for cameras backed by V4L2 video devices to function with the FrameBuffer interface. Signed-off-by: Niklas Söderlund --- src/libcamera/include/v4l2_videodevice.h | 24 +++++++ src/libcamera/v4l2_videodevice.cpp | 90 ++++++++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/src/libcamera/include/v4l2_videodevice.h b/src/libcamera/include/v4l2_videodevice.h index f4cbcfbd26ea540c..0e94c3f71d0b1208 100644 --- a/src/libcamera/include/v4l2_videodevice.h +++ b/src/libcamera/include/v4l2_videodevice.h @@ -16,6 +16,7 @@ #include #include #include +#include #include "formats.h" #include "log.h" @@ -236,6 +237,29 @@ private: V4L2VideoDevice *capture_; }; +class V4L2Stream : public Stream +{ +public: + V4L2Stream(V4L2VideoDevice *video); + +protected: + int allocateBuffers(const StreamConfiguration &config, + std::vector *buffers) override; + void releaseBuffers() override; + int start() override; + void stop() override; + +private: + enum BufferType { + NoBuffers, + AllocatedBuffers, + ExternalBuffers, + }; + + V4L2VideoDevice *video_; + BufferType bufferType_; +}; + } /* namespace libcamera */ #endif /* __LIBCAMERA_V4L2_VIDEODEVICE_H__ */ diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp index 9fe66018ec502626..f5810956b2040ce6 100644 --- a/src/libcamera/v4l2_videodevice.cpp +++ b/src/libcamera/v4l2_videodevice.cpp @@ -1711,4 +1711,94 @@ void V4L2M2MDevice::close() output_->close(); } +/** + * \class V4L2Stream + * \brief V4L2 Video stream for a camera + * + * The V4l2Stream implemets the interfaces mandated by Stream to allow buffers + * to be allocoated from a video device and presented to the user as if they + * where allocated externaly. + */ + +/** + * \brief Create a stream around a V4L2 video device + * \param[in] video V4L2 video device to serve + * + * Create a stream which will manage the application visible buffers for a V4L2 + * video device. + */ +V4L2Stream::V4L2Stream(V4L2VideoDevice *video) + : Stream(), video_(video), bufferType_(NoBuffers) +{ +} + +int V4L2Stream::allocateBuffers(const StreamConfiguration &config, + std::vector *buffers) +{ + if (bufferType_ != NoBuffers) + return -EINVAL; + + if (!buffers) + return -EINVAL; + + /* + * \todo: Extend V4L2VideoDevice to support VIDIOC_CREATE_BUFS which + * can take the whole configuration into account, until then use as + * much as possible (number of buffers) with VIDIOC_QUERYBUF. + * + * For this reason check that the format of the video device is the + * same as the one request or fail. This will allow for a applicaiton + * facing API that will work with VIDIOC_CREATE_BUFS. + */ + V4L2DeviceFormat format; + int ret = video_->getFormat(&format); + if (ret) + return ret; + + if (config.size != format.size || + config.pixelFormat != V4L2VideoDevice::toPixelFormat(format.fourcc)) + return -EINVAL; + + ret = video_->allocateBuffers(config.bufferCount, buffers); + if (ret) + return ret; + + bufferType_ = AllocatedBuffers; + + return ret; +} + +void V4L2Stream::releaseBuffers() +{ + if (bufferType_ == NoBuffers) + return; + + video_->releaseBuffers(); + bufferType_ = NoBuffers; +} + +int V4L2Stream::start() +{ + /* If internal buffers is already allocated nothing to do. */ + if (bufferType_ == AllocatedBuffers) + return 0; + + int ret = video_->externalBuffers(configuration_.bufferCount); + if (ret) + return ret; + + bufferType_ = ExternalBuffers; + + return ret; +} + +void V4L2Stream::stop() +{ + /* Only need to clean up if external buffers is used. */ + if (bufferType_ != ExternalBuffers) + return; + + releaseBuffers(); +} + } /* namespace libcamera */