v4l2codecs: Replace VIDIOC_REQBUFS calls by VIDIOC_CREATE_BUFS

Use VIDIOC_CREATE_BUFS ioctl to create buffers instead of VIDIOC_REQBUFS
because it allows to create buffers also while streaming.
To prepare the introduction of VIDIOC_REMOVE_BUFFERS create
the buffers one per one instead of a range of them. This way
it can, in the futur, fill the holes.
gst_v4l2_decoder_request_buffers() is stil used to remove all
the buffers of the queue.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7684>
This commit is contained in:
Benjamin Gaignard 2023-06-19 11:09:22 +02:00 committed by GStreamer Marge Bot
parent c25c4355b1
commit 2753a8f0c1
3 changed files with 49 additions and 12 deletions

View file

@ -173,21 +173,25 @@ gst_v4l2_codec_allocator_prepare (GstV4l2CodecAllocator * self)
{
GstV4l2Decoder *decoder = self->decoder;
GstPadDirection direction = self->direction;
gint ret;
guint i;
ret = gst_v4l2_decoder_request_buffers (decoder, direction, self->pool_size);
if (ret < self->pool_size) {
if (ret >= 0)
GST_DEBUG_OBJECT (self, "Try to create %d buffers", self->pool_size);
/* Allocate buffers one by one to avoid fragmentation issue and
* use the possible holes in v4l2 queue array */
for (i = 0; i < self->pool_size; i++) {
GstV4l2CodecBuffer *buf;
gint index = gst_v4l2_decoder_create_buffers (decoder, direction, 1);
if (index < 0) {
GST_ERROR_OBJECT (self,
"%i buffer was needed, but only %i could be allocated",
self->pool_size, ret);
goto failed;
}
self->pool_size, i);
goto failed;
}
for (i = 0; i < self->pool_size; i++) {
GstV4l2CodecBuffer *buf = gst_v4l2_codec_buffer_new (GST_ALLOCATOR (self),
decoder, direction, i);
buf =
gst_v4l2_codec_buffer_new (GST_ALLOCATOR (self), decoder, direction,
index);
g_queue_push_tail (&self->pool, buf);
}

View file

@ -659,14 +659,43 @@ gst_v4l2_decoder_request_buffers (GstV4l2Decoder * self,
return ret;
}
return reqbufs.count;
}
gint
gst_v4l2_decoder_create_buffers (GstV4l2Decoder * self,
GstPadDirection direction, guint num_buffers)
{
gint ret;
struct v4l2_create_buffers createbufs = {
.count = num_buffers,
.memory = V4L2_MEMORY_MMAP,
.format.type = direction_to_buffer_type (self, direction),
};
GST_DEBUG_OBJECT (self, "Creating %u buffers", num_buffers);
ret = ioctl (self->video_fd, VIDIOC_G_FMT, &createbufs.format);
if (ret < 0) {
GST_ERROR_OBJECT (self, "VIDIOC_G_FMT failed: %s", g_strerror (errno));
return ret;
}
ret = ioctl (self->video_fd, VIDIOC_CREATE_BUFS, &createbufs);
if (ret < 0) {
GST_ERROR_OBJECT (self, "VIDIOC_CREATE_BUFS failed: %s",
g_strerror (errno));
return ret;
}
if (direction == GST_PAD_SINK) {
if (reqbufs.capabilities & V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF)
if (createbufs.capabilities & V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF)
self->supports_holding_capture = TRUE;
else
self->supports_holding_capture = FALSE;
}
return reqbufs.count;
return createbufs.index;
}
gboolean

View file

@ -86,6 +86,10 @@ gint gst_v4l2_decoder_request_buffers (GstV4l2Decoder * self,
GstPadDirection direction,
guint num_buffers);
gint gst_v4l2_decoder_create_buffers (GstV4l2Decoder * self,
GstPadDirection direction,
guint num_buffers);
gboolean gst_v4l2_decoder_export_buffer (GstV4l2Decoder * self,
GstPadDirection directon,
gint index,