gst: libcamerasrc: Prevent src task deadlock on exhausted buffer pool
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@collabora.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
9dab15bed6
commit
170def84c6
2 changed files with 20 additions and 0 deletions
|
@ -14,6 +14,13 @@
|
||||||
|
|
||||||
using namespace libcamera;
|
using namespace libcamera;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SIGNAL_BUFFER_NOTIFY,
|
||||||
|
N_SIGNALS
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals[N_SIGNALS];
|
||||||
|
|
||||||
struct _GstLibcameraPool {
|
struct _GstLibcameraPool {
|
||||||
GstBufferPool parent;
|
GstBufferPool parent;
|
||||||
|
|
||||||
|
@ -55,7 +62,12 @@ static void
|
||||||
gst_libcamera_pool_release_buffer(GstBufferPool *pool, GstBuffer *buffer)
|
gst_libcamera_pool_release_buffer(GstBufferPool *pool, GstBuffer *buffer)
|
||||||
{
|
{
|
||||||
GstLibcameraPool *self = GST_LIBCAMERA_POOL(pool);
|
GstLibcameraPool *self = GST_LIBCAMERA_POOL(pool);
|
||||||
|
bool do_notify = gst_atomic_queue_length(self->queue) == 0;
|
||||||
|
|
||||||
gst_atomic_queue_push(self->queue, buffer);
|
gst_atomic_queue_push(self->queue, buffer);
|
||||||
|
|
||||||
|
if (do_notify)
|
||||||
|
g_signal_emit(self, signals[SIGNAL_BUFFER_NOTIFY], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -90,6 +102,11 @@ gst_libcamera_pool_class_init(GstLibcameraPoolClass *klass)
|
||||||
pool_class->acquire_buffer = gst_libcamera_pool_acquire_buffer;
|
pool_class->acquire_buffer = gst_libcamera_pool_acquire_buffer;
|
||||||
pool_class->reset_buffer = gst_libcamera_pool_reset_buffer;
|
pool_class->reset_buffer = gst_libcamera_pool_reset_buffer;
|
||||||
pool_class->release_buffer = gst_libcamera_pool_release_buffer;
|
pool_class->release_buffer = gst_libcamera_pool_release_buffer;
|
||||||
|
|
||||||
|
signals[SIGNAL_BUFFER_NOTIFY] = g_signal_new("buffer-notify",
|
||||||
|
G_OBJECT_CLASS_TYPE(klass), G_SIGNAL_RUN_LAST,
|
||||||
|
0, nullptr, nullptr, nullptr,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GstLibcameraPool *
|
GstLibcameraPool *
|
||||||
|
|
|
@ -439,6 +439,9 @@ gst_libcamera_src_task_enter(GstTask *task, GThread *thread, gpointer user_data)
|
||||||
const StreamConfiguration &stream_cfg = state->config_->at(i);
|
const StreamConfiguration &stream_cfg = state->config_->at(i);
|
||||||
GstLibcameraPool *pool = gst_libcamera_pool_new(self->allocator,
|
GstLibcameraPool *pool = gst_libcamera_pool_new(self->allocator,
|
||||||
stream_cfg.stream());
|
stream_cfg.stream());
|
||||||
|
g_signal_connect_swapped(pool, "buffer-notify",
|
||||||
|
G_CALLBACK(gst_libcamera_resume_task), task);
|
||||||
|
|
||||||
gst_libcamera_pad_set_pool(srcpad, pool);
|
gst_libcamera_pad_set_pool(srcpad, pool);
|
||||||
gst_flow_combiner_add_pad(self->flow_combiner, srcpad);
|
gst_flow_combiner_add_pad(self->flow_combiner, srcpad);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue