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:
parent
33d3c4e204
commit
9bb36ec274
5 changed files with 70 additions and 24 deletions
|
@ -139,6 +139,7 @@ public:
|
|||
int releaseBuffers();
|
||||
|
||||
int queueBuffer(Buffer *buffer);
|
||||
std::vector<std::unique_ptr<Buffer>> queueAllBuffers();
|
||||
Signal<Buffer *> bufferReady;
|
||||
|
||||
int streamOn();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue