From 897431800329628a756dbec4bd18a6a76237351b Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Thu, 3 Aug 2023 14:46:56 -0400 Subject: [PATCH] v4l2: bufferpool: Fix hang when splitting buffer Now that we can split GStreamer buffers over multiple v4l2 buffer, we may endup waiting for these buffers to be processed. Avoid waiting for any of the parts being processed. As a side effect, the pool will now try to grow if the number of buffers is not sufficient, and will fail otherwise. This fixes a hang if the very first frame did not fit. In this case, the driver will retrain that buffer until the capture is setup, but GStreamer won't setup the capture until process() function have returned. Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5100 Part-of: --- .../gst-plugins-good/sys/v4l2/gstv4l2bufferpool.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/subprojects/gst-plugins-good/sys/v4l2/gstv4l2bufferpool.c b/subprojects/gst-plugins-good/sys/v4l2/gstv4l2bufferpool.c index fd3499e267..01d55c3d63 100644 --- a/subprojects/gst-plugins-good/sys/v4l2/gstv4l2bufferpool.c +++ b/subprojects/gst-plugins-good/sys/v4l2/gstv4l2bufferpool.c @@ -2050,6 +2050,8 @@ gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer ** buf, gboolean outstanding; gsize queued_size = 0; gsize remaining_size = 0; + guint split_count = 1; + guint num_queued; if ((*buf)->pool != bpool) goto copying; @@ -2132,7 +2134,7 @@ gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer ** buf, /* Remove our ref, we will still hold this buffer in acquire as needed, * otherwise the pool will think it is outstanding and will refuse to stop. */ - gst_buffer_unref (to_queue); + gst_clear_buffer (&to_queue); /* release as many buffer as possible */ while (gst_v4l2_buffer_pool_dqbuf (pool, &buffer, &outstanding, @@ -2142,7 +2144,8 @@ gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer ** buf, FALSE); } - if (g_atomic_int_get (&pool->num_queued) >= pool->min_latency) { + num_queued = g_atomic_int_get (&pool->num_queued); + if (num_queued >= pool->min_latency && num_queued > split_count) { /* all buffers are queued, try to dequeue one and release it back * into the pool so that _acquire can get to it again. */ ret = @@ -2159,7 +2162,8 @@ gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer ** buf, if (remaining_size) { *buf = gst_buffer_make_writable (*buf); gst_buffer_resize (*buf, queued_size, -1); - return gst_v4l2_buffer_pool_process (pool, buf, frame_number); + split_count++; + goto copying; } break; }