From 2753a8f0c1cde305a359882ede6b592f8327e823 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Mon, 19 Jun 2023 11:09:22 +0200 Subject: [PATCH] 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: --- .../sys/v4l2codecs/gstv4l2codecallocator.c | 24 ++++++++------ .../sys/v4l2codecs/gstv4l2decoder.c | 33 +++++++++++++++++-- .../sys/v4l2codecs/gstv4l2decoder.h | 4 +++ 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecallocator.c b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecallocator.c index 40238bdafe..110f6867e9 100644 --- a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecallocator.c +++ b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecallocator.c @@ -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); } diff --git a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.c b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.c index 9b459e8d62..29352b0708 100644 --- a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.c +++ b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.c @@ -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 diff --git a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.h b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.h index c726c94b46..1ff06df4e8 100644 --- a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.h +++ b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.h @@ -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,