libcamera: v4l2_videodevice: Add helper to queue all buffers

When starting the stream on a capture video device it is often needed to
queue all the allocated buffers. Add a helper method to do so, and
refactor the existing queueBuffer() method to make it clearer.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
This commit is contained in:
Laurent Pinchart 2019-07-09 13:56:55 +03:00
parent 33d3c4e204
commit 9bb36ec274
5 changed files with 70 additions and 24 deletions

View file

@ -139,6 +139,7 @@ public:
int releaseBuffers();
int queueBuffer(Buffer *buffer);
std::vector<std::unique_ptr<Buffer>> queueAllBuffers();
Signal<Buffer *> bufferReady;
int streamOn();

View file

@ -131,6 +131,7 @@ public:
CameraSensor *sensor_;
BufferPool pool_;
std::vector<std::unique_ptr<Buffer>> buffers_;
};
class IPU3Stream : public Stream
@ -1430,11 +1431,9 @@ int CIO2Device::start()
{
int ret;
for (Buffer &buffer : pool_.buffers()) {
ret = output_->queueBuffer(&buffer);
if (ret)
return ret;
}
buffers_ = output_->queueAllBuffers();
if (buffers_.empty())
return -EINVAL;
ret = output_->streamOn();
if (ret)
@ -1445,7 +1444,9 @@ int CIO2Device::start()
int CIO2Device::stop()
{
return output_->streamOff();
int ret = output_->streamOff();
buffers_.clear();
return ret;
}
int CIO2Device::mediaBusToFormat(unsigned int code)

View file

@ -894,8 +894,8 @@ int V4L2VideoDevice::releaseBuffers()
*/
int V4L2VideoDevice::queueBuffer(Buffer *buffer)
{
struct v4l2_plane v4l2Planes[VIDEO_MAX_PLANES] = {};
struct v4l2_buffer buf = {};
struct v4l2_plane planes[VIDEO_MAX_PLANES] = {};
int ret;
buf.index = buffer->index();
@ -904,21 +904,20 @@ int V4L2VideoDevice::queueBuffer(Buffer *buffer)
buf.field = V4L2_FIELD_NONE;
bool multiPlanar = V4L2_TYPE_IS_MULTIPLANAR(buf.type);
const std::vector<Plane> &planes = buffer->planes();
if (buf.memory == V4L2_MEMORY_DMABUF) {
if (multiPlanar) {
for (unsigned int p = 0;
p < buffer->planes().size();
p++)
planes[p].m.fd = buffer->planes()[p].dmabuf();
for (unsigned int p = 0; p < planes.size(); ++p)
v4l2Planes[p].m.fd = planes[p].dmabuf();
} else {
buf.m.fd = buffer->planes()[0].dmabuf();
buf.m.fd = planes[0].dmabuf();
}
}
if (multiPlanar) {
buf.length = buffer->planes().size();
buf.m.planes = planes;
buf.length = planes.size();
buf.m.planes = v4l2Planes;
}
if (V4L2_TYPE_IS_OUTPUT(bufferType_)) {
@ -944,6 +943,53 @@ int V4L2VideoDevice::queueBuffer(Buffer *buffer)
return 0;
}
/**
* \brief Queue all buffers into the video device
*
* When starting video capture users of the video device often need to queue
* all allocated buffers to the device. This helper method simplifies the
* implementation of the user by queuing all buffers and returning a vector of
* Buffer instances for each queued buffer.
*
* This method is meant to be used with video capture devices internal to a
* pipeline handler, such as ISP statistics capture devices, or raw CSI-2
* receivers. For video capture devices facing applications, buffers shall
* instead be queued when requests are received, and for video output devices,
* buffers shall be queued when frames are ready to be output.
*
* The caller shall ensure that the returned buffers vector remains valid until
* all the queued buffers are dequeued, either during capture, or by stopping
* the video device.
*
* Calling this method on an output device or on a device that has buffers
* already queued is an error and will return an empty vector.
*
* \return A vector of queued buffers, which will be empty if an error occurs
*/
std::vector<std::unique_ptr<Buffer>> V4L2VideoDevice::queueAllBuffers()
{
int ret;
if (queuedBuffersCount_)
return {};
if (V4L2_TYPE_IS_OUTPUT(bufferType_))
return {};
std::vector<std::unique_ptr<Buffer>> buffers;
for (unsigned int i = 0; i < bufferPool_->count(); ++i) {
Buffer *buffer = new Buffer();
buffer->index_ = i;
buffers.emplace_back(buffer);
ret = queueBuffer(buffer);
if (ret)
return {};
}
return buffers;
}
/**
* \brief Dequeue the next available buffer from the video device
*

View file

@ -117,11 +117,10 @@ protected:
capture_->bufferReady.connect(this, &BufferSharingTest::captureBufferReady);
output_->bufferReady.connect(this, &BufferSharingTest::outputBufferReady);
/* Queue all the buffers to the capture device. */
for (Buffer &buffer : pool_.buffers()) {
if (capture_->queueBuffer(&buffer))
return TestFail;
}
std::vector<std::unique_ptr<Buffer>> buffers;
buffers = capture_->queueAllBuffers();
if (buffers.empty())
return TestFail;
ret = capture_->streamOn();
if (ret) {

View file

@ -46,11 +46,10 @@ protected:
capture_->bufferReady.connect(this, &CaptureAsyncTest::receiveBuffer);
/* Queue all the buffers to the device. */
for (Buffer &b : pool_.buffers()) {
if (capture_->queueBuffer(&b))
return TestFail;
}
std::vector<std::unique_ptr<Buffer>> buffers;
buffers = capture_->queueAllBuffers();
if (buffers.empty())
return TestFail;
ret = capture_->streamOn();
if (ret)