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/5695>
This commit is contained in:
jeri.li 2023-04-21 09:58:36 +08:00 committed by GStreamer Marge Bot
parent d809406dfc
commit 390d43dcde

View file

@ -682,9 +682,11 @@ gst_v4l2_buffer_pool_streamon (GstV4l2BufferPool * pool)
guint num_queued;
guint i, n = 0;
GST_OBJECT_LOCK (pool);
num_queued = g_atomic_int_get (&pool->num_queued);
if (num_queued < pool->num_allocated)
n = pool->num_allocated - num_queued;
GST_OBJECT_UNLOCK (pool);
/* For captures, we need to enqueue buffers before we start streaming,
* so the driver don't underflow immediately. As we have put then back
@ -1147,6 +1149,8 @@ gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool * pool, GstBuffer * buf,
gint old_buffer_state;
gint index;
GST_OBJECT_LOCK (pool);
index = group->buffer.index;
old_buffer_state =
@ -1182,8 +1186,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.
* This is done with the objet lock in order to synchronize with
* orphaning. */
@ -1205,6 +1207,7 @@ gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool * pool, GstBuffer * buf,
already_queued:
{
GST_ERROR_OBJECT (pool, "the buffer %i was already queued", index);
GST_OBJECT_UNLOCK (pool);
return GST_FLOW_ERROR;
}
was_orphaned:
@ -2281,7 +2284,9 @@ gst_v4l2_buffer_pool_flush (GstV4l2Object * v4l2object)
pool = GST_V4L2_BUFFER_POOL (bpool);
GST_OBJECT_LOCK (pool);
gst_v4l2_buffer_pool_streamoff (pool);
GST_OBJECT_UNLOCK (pool);
if (!V4L2_TYPE_IS_OUTPUT (pool->obj->type)) {
ret = gst_v4l2_buffer_pool_flush_events (v4l2object);