[libcamera-devel] [PATCH v2 26/27] gst: libcamerasrc: Prevent src task deadlock on exhausted buffer pool

Nicolas Dufresne nicolas.dufresne at collabora.com
Thu Feb 27 21:04:06 CET 2020


From: Jakub Adam <jakub.adam at collabora.com>

Allow GstLibcameraPool to notify the source when a new buffer has become
available in a previously exhausted buffer pool. This can be used to
resume a src task that got paused because it couldn't acquire a buffer.

Without this change the src task will never resume from pause once the
pool gets exhausted.

To trigger the deadlock (it doesn't happen every time), run:

  gst-launch-1.0 libcamerasrc ! queue ! glimagesink

Signed-off-by: Jakub Adam <jakub.adam at collabora.com>
---
 src/gstreamer/gstlibcamerapool.cpp | 16 ++++++++++++++++
 src/gstreamer/gstlibcamerapool.h   |  6 ++++++
 src/gstreamer/gstlibcamerasrc.cpp  | 14 ++++++++++++--
 3 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/src/gstreamer/gstlibcamerapool.cpp b/src/gstreamer/gstlibcamerapool.cpp
index f85c3aa..5aa0eeb 100644
--- a/src/gstreamer/gstlibcamerapool.cpp
+++ b/src/gstreamer/gstlibcamerapool.cpp
@@ -18,6 +18,8 @@ struct _GstLibcameraPool {
 
 	GstAtomicQueue *queue;
 	GstLibcameraAllocator *allocator;
+	GstLibcameraBufferNotify buffer_notify;
+	gpointer buffer_notify_data;
 	Stream *stream;
 };
 
@@ -54,7 +56,12 @@ static void
 gst_libcamera_pool_release_buffer(GstBufferPool *pool, GstBuffer *buffer)
 {
 	GstLibcameraPool *self = GST_LIBCAMERA_POOL(pool);
+	bool do_notify = gst_atomic_queue_length(self->queue) == 0;
+
 	gst_atomic_queue_push(self->queue, buffer);
+
+	if (do_notify && self->buffer_notify)
+		self->buffer_notify(self->buffer_notify_data);
 }
 
 static void
@@ -108,6 +115,15 @@ gst_libcamera_pool_new(GstLibcameraAllocator *allocator, Stream *stream)
 	return pool;
 }
 
+void
+gst_libcamera_pool_set_buffer_notify(GstLibcameraPool *self,
+				     GstLibcameraBufferNotify notify,
+				     gpointer data)
+{
+	self->buffer_notify = notify;
+	self->buffer_notify_data = data;
+}
+
 Stream *
 gst_libcamera_pool_get_stream(GstLibcameraPool *self)
 {
diff --git a/src/gstreamer/gstlibcamerapool.h b/src/gstreamer/gstlibcamerapool.h
index 6fd2913..545be01 100644
--- a/src/gstreamer/gstlibcamerapool.h
+++ b/src/gstreamer/gstlibcamerapool.h
@@ -20,9 +20,15 @@
 #define GST_TYPE_LIBCAMERA_POOL gst_libcamera_pool_get_type()
 G_DECLARE_FINAL_TYPE(GstLibcameraPool, gst_libcamera_pool, GST_LIBCAMERA, POOL, GstBufferPool)
 
+typedef void (*GstLibcameraBufferNotify)(gpointer data);
+
 GstLibcameraPool *gst_libcamera_pool_new(GstLibcameraAllocator *allocator,
 					 libcamera::Stream *stream);
 
+void gst_libcamera_pool_set_buffer_notify(GstLibcameraPool *self,
+					  GstLibcameraBufferNotify notify,
+					  gpointer data);
+
 libcamera::Stream *gst_libcamera_pool_get_stream(GstLibcameraPool *self);
 
 libcamera::Stream *gst_libcamera_buffer_get_stream(GstBuffer *buffer);
diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
index fe60584..ecbfe37 100644
--- a/src/gstreamer/gstlibcamerasrc.cpp
+++ b/src/gstreamer/gstlibcamerasrc.cpp
@@ -434,6 +434,10 @@ gst_libcamera_src_task_enter(GstTask *task, GThread *thread, gpointer user_data)
 		const StreamConfiguration &stream_cfg = state->config->at(i);
 		GstLibcameraPool *pool = gst_libcamera_pool_new(self->allocator,
 								stream_cfg.stream());
+		gst_libcamera_pool_set_buffer_notify(pool,
+						     (GstLibcameraBufferNotify)gst_libcamera_resume_task,
+						     task);
+
 		gst_libcamera_pad_set_pool(srcpad, pool);
 		gst_flow_combiner_add_pad(self->flow_combiner, srcpad);
 	}
@@ -468,8 +472,14 @@ gst_libcamera_src_task_leave(GstTask *task, GThread *thread, gpointer user_data)
 
 	state->cam->stop();
 
-	for (GstPad *srcpad : state->srcpads)
-		gst_libcamera_pad_set_pool(srcpad, NULL);
+	for (GstPad *srcpad : state->srcpads) {
+		auto *pool = gst_libcamera_pad_get_pool(srcpad);
+
+		if (pool) {
+			gst_libcamera_pool_set_buffer_notify(pool, NULL, NULL);
+			gst_libcamera_pad_set_pool(srcpad, NULL);
+		}
+	}
 
 	g_clear_object(&self->allocator);
 	g_clear_pointer(&self->flow_combiner,
-- 
2.24.1



More information about the libcamera-devel mailing list