v4l2bufferpool: add lock as atomic operation for seek

When seek flush, gst v4l2 buffer pool flush is not atomic which will
lead double enqueue buffer (qbuf) issue, and v4l2 buffer pool qbuf is
also not atomic which will lead no free buffer found in the pool.
1. add lock for calculate enqueue number in streamon function
2. add lock for v4l2 capture end streamoff in pool flush function
3. lock the whole funciton of v4l2 buffer pool qbuf, then the buffer
   pool index and qbuf operation are atomic

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4465>
This commit is contained in:
jeri.li 2023-04-21 09:58:36 +08:00 committed by GStreamer Marge Bot
parent 1c488626da
commit 2b63e30852

View file

@ -682,9 +682,11 @@ gst_v4l2_buffer_pool_streamon (GstV4l2BufferPool * pool)
guint num_queued; guint num_queued;
guint i, n = 0; guint i, n = 0;
GST_OBJECT_LOCK (pool);
num_queued = g_atomic_int_get (&pool->num_queued); num_queued = g_atomic_int_get (&pool->num_queued);
if (num_queued < pool->num_allocated) if (num_queued < pool->num_allocated)
n = pool->num_allocated - num_queued; n = pool->num_allocated - num_queued;
GST_OBJECT_UNLOCK (pool);
/* For captures, we need to enqueue buffers before we start streaming, /* For captures, we need to enqueue buffers before we start streaming,
* so the driver don't underflow immediately. As we have put then back * so the driver don't underflow immediately. As we have put then back
@ -1219,6 +1221,8 @@ gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool * pool, GstBuffer * buf,
gint old_buffer_state; gint old_buffer_state;
gint index; gint index;
GST_OBJECT_LOCK (pool);
index = group->buffer.index; index = group->buffer.index;
old_buffer_state = old_buffer_state =
@ -1254,8 +1258,6 @@ gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool * pool, GstBuffer * buf,
} }
} }
GST_OBJECT_LOCK (pool);
/* If the pool was orphaned, don't try to queue any returned buffers. /* If the pool was orphaned, don't try to queue any returned buffers.
* This is done with the objet lock in order to synchronize with * This is done with the objet lock in order to synchronize with
* orphaning. */ * orphaning. */
@ -1277,6 +1279,7 @@ gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool * pool, GstBuffer * buf,
already_queued: already_queued:
{ {
GST_ERROR_OBJECT (pool, "the buffer %i was already queued", index); GST_ERROR_OBJECT (pool, "the buffer %i was already queued", index);
GST_OBJECT_UNLOCK (pool);
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
} }
was_orphaned: was_orphaned:
@ -2310,7 +2313,9 @@ gst_v4l2_buffer_pool_flush (GstV4l2Object * v4l2object)
pool = GST_V4L2_BUFFER_POOL (bpool); pool = GST_V4L2_BUFFER_POOL (bpool);
GST_OBJECT_LOCK (pool);
gst_v4l2_buffer_pool_streamoff (pool); gst_v4l2_buffer_pool_streamoff (pool);
GST_OBJECT_UNLOCK (pool);
if (!V4L2_TYPE_IS_OUTPUT (pool->obj->type)) if (!V4L2_TYPE_IS_OUTPUT (pool->obj->type))
ret = gst_v4l2_buffer_pool_streamon (pool); ret = gst_v4l2_buffer_pool_streamon (pool);