From patchwork Thu Feb 27 20:04:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolas Dufresne X-Patchwork-Id: 2908 Return-Path: Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [IPv6:2a00:1098:0:82:1000:25:2eeb:e3e3]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6F4EE62755 for ; Thu, 27 Feb 2020 21:04:30 +0100 (CET) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: nicolas) with ESMTPSA id D9C662949DF From: Nicolas Dufresne To: libcamera-devel@lists.libcamera.org Cc: Jakub Adam Date: Thu, 27 Feb 2020 15:04:06 -0500 Message-Id: <20200227200407.490616-27-nicolas.dufresne@collabora.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200227200407.490616-1-nicolas.dufresne@collabora.com> References: <20200227200407.490616-1-nicolas.dufresne@collabora.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 26/27] gst: libcamerasrc: Prevent src task deadlock on exhausted buffer pool X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 27 Feb 2020 20:04:31 -0000 From: Jakub Adam 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 --- 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,