mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-28 11:10:37 +00:00
v4l2bufferpool: Wait before polling if queue is empty
In kernel before 3.17, polling during queue underrun would unblock right away and trigger POLLERR. As we are not handling POLLERR, we would endup blocking in DQBUF call, which won't be unblocked correctly when going to NULL state. A deadlock at start caused by locking error in libv4l2 was also seen before this patch. Instead, we wait until the queue is no longer empty before polling. https://bugzilla.gnome.org/show_bug.cgi?id=731015
This commit is contained in:
parent
db1d9444d6
commit
652ed3bceb
2 changed files with 25 additions and 1 deletions
|
@ -846,6 +846,11 @@ gst_v4l2_buffer_pool_flush_start (GstBufferPool * bpool)
|
|||
|
||||
gst_poll_set_flushing (pool->poll, TRUE);
|
||||
|
||||
GST_OBJECT_LOCK (pool);
|
||||
pool->empty = FALSE;
|
||||
g_cond_broadcast (&pool->empty_cond);
|
||||
GST_OBJECT_UNLOCK (pool);
|
||||
|
||||
if (pool->other_pool)
|
||||
gst_buffer_pool_set_flushing (pool->other_pool, TRUE);
|
||||
}
|
||||
|
@ -934,6 +939,11 @@ gst_v4l2_buffer_pool_poll (GstV4l2BufferPool * pool)
|
|||
{
|
||||
gint ret;
|
||||
|
||||
GST_OBJECT_LOCK (pool);
|
||||
while (pool->empty)
|
||||
g_cond_wait (&pool->empty_cond, GST_OBJECT_GET_LOCK (pool));
|
||||
GST_OBJECT_UNLOCK (pool);
|
||||
|
||||
if (!pool->can_poll_device)
|
||||
goto done;
|
||||
|
||||
|
@ -1001,6 +1011,11 @@ gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool * pool, GstBuffer * buf)
|
|||
if (!gst_v4l2_allocator_qbuf (pool->vallocator, group))
|
||||
goto queue_failed;
|
||||
|
||||
GST_OBJECT_LOCK (pool);
|
||||
pool->empty = FALSE;
|
||||
g_cond_signal (&pool->empty_cond);
|
||||
GST_OBJECT_UNLOCK (pool);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
||||
already_queued:
|
||||
|
@ -1047,7 +1062,11 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer)
|
|||
|
||||
/* mark the buffer outstanding */
|
||||
pool->buffers[group->buffer.index] = NULL;
|
||||
g_atomic_int_add (&pool->num_queued, -1);
|
||||
if (g_atomic_int_dec_and_test (&pool->num_queued)) {
|
||||
GST_OBJECT_LOCK (pool);
|
||||
pool->empty = TRUE;
|
||||
GST_OBJECT_UNLOCK (pool);
|
||||
}
|
||||
|
||||
timestamp = GST_TIMEVAL_TO_TIME (group->buffer.timestamp);
|
||||
|
||||
|
@ -1354,6 +1373,8 @@ gst_v4l2_buffer_pool_init (GstV4l2BufferPool * pool)
|
|||
{
|
||||
pool->poll = gst_poll_new (TRUE);
|
||||
pool->can_poll_device = TRUE;
|
||||
g_cond_init (&pool->empty_cond);
|
||||
pool->empty = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -53,6 +53,9 @@ struct _GstV4l2BufferPool
|
|||
GstPoll *poll; /* a poll for video_fd */
|
||||
gboolean can_poll_device;
|
||||
|
||||
gboolean empty;
|
||||
GCond empty_cond;
|
||||
|
||||
GstV4l2Allocator *vallocator;
|
||||
GstAllocator *allocator;
|
||||
GstAllocationParams params;
|
||||
|
|
Loading…
Reference in a new issue