mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
v4l2: pool: Flush events on capture queue
Unfortunately streamoff does not flush the events, and this can cause all sort of issues. Flush events on capture queue. We also return GST_V4L2_FLOW_RESOLUTION_CHANGE in case a resolution change was seen. This allow skipping streamon(capture) on flush, which could lead to a configuration miss-match, or failure if the buffers aren't of the right size. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4437>
This commit is contained in:
parent
00492234bd
commit
51fa6a2656
3 changed files with 60 additions and 8 deletions
|
@ -2218,15 +2218,56 @@ gst_v4l2_buffer_pool_copy_at_threshold (GstV4l2BufferPool * pool, gboolean copy)
|
||||||
GST_OBJECT_UNLOCK (pool);
|
GST_OBJECT_UNLOCK (pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
static GstFlowReturn
|
||||||
|
gst_v4l2_buffer_pool_flush_events (GstV4l2Object * v4l2object)
|
||||||
|
{
|
||||||
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
gboolean event_found;
|
||||||
|
|
||||||
|
/* FIXME simplify this when we drop legacy support for driver without poll()
|
||||||
|
* support. When we do, we can switch the video_fd to non blocking, and just
|
||||||
|
* pop the events directly. */
|
||||||
|
|
||||||
|
do {
|
||||||
|
struct v4l2_event event = { 0, };
|
||||||
|
gint poll_ret;
|
||||||
|
|
||||||
|
event_found = FALSE;
|
||||||
|
|
||||||
|
gst_poll_set_flushing (v4l2object->poll, FALSE);
|
||||||
|
|
||||||
|
do {
|
||||||
|
/* GstPoll don't have 0ns timeout, but 1 will do */
|
||||||
|
poll_ret = gst_poll_wait (v4l2object->poll, 1);
|
||||||
|
} while (poll_ret == EAGAIN || poll_ret == EINTR);
|
||||||
|
|
||||||
|
if (gst_poll_fd_has_pri (v4l2object->poll, &v4l2object->pollfd)) {
|
||||||
|
if (!gst_v4l2_dequeue_event (v4l2object, &event))
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
|
||||||
|
event_found = TRUE;
|
||||||
|
|
||||||
|
if (event.type == V4L2_EVENT_SOURCE_CHANGE &&
|
||||||
|
(event.u.src_change.changes & V4L2_EVENT_SRC_CH_RESOLUTION)) {
|
||||||
|
GST_DEBUG_OBJECT (v4l2object->dbg_obj,
|
||||||
|
"Can't streamon capture as the resolution have changed.");
|
||||||
|
ret = GST_V4L2_FLOW_RESOLUTION_CHANGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (event_found);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
GstFlowReturn
|
||||||
gst_v4l2_buffer_pool_flush (GstV4l2Object * v4l2object)
|
gst_v4l2_buffer_pool_flush (GstV4l2Object * v4l2object)
|
||||||
{
|
{
|
||||||
GstBufferPool *bpool = gst_v4l2_object_get_buffer_pool (v4l2object);
|
GstBufferPool *bpool = gst_v4l2_object_get_buffer_pool (v4l2object);
|
||||||
GstV4l2BufferPool *pool;
|
GstV4l2BufferPool *pool;
|
||||||
gboolean ret = TRUE;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
|
||||||
if (!bpool)
|
if (!bpool)
|
||||||
return FALSE;
|
return GST_FLOW_ERROR;
|
||||||
|
|
||||||
pool = GST_V4L2_BUFFER_POOL (bpool);
|
pool = GST_V4L2_BUFFER_POOL (bpool);
|
||||||
|
|
||||||
|
@ -2234,8 +2275,14 @@ gst_v4l2_buffer_pool_flush (GstV4l2Object * v4l2object)
|
||||||
gst_v4l2_buffer_pool_streamoff (pool);
|
gst_v4l2_buffer_pool_streamoff (pool);
|
||||||
GST_OBJECT_UNLOCK (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_flush_events (v4l2object);
|
||||||
|
|
||||||
|
/* If the format haven't change, avoid reallocation to go back to
|
||||||
|
* streaming */
|
||||||
|
if (ret == GST_FLOW_OK)
|
||||||
|
ret = gst_v4l2_buffer_pool_streamon (pool);
|
||||||
|
}
|
||||||
|
|
||||||
gst_object_unref (bpool);
|
gst_object_unref (bpool);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -115,7 +115,7 @@ void gst_v4l2_buffer_pool_set_other_pool (GstV4l2BufferPool * poo
|
||||||
void gst_v4l2_buffer_pool_copy_at_threshold (GstV4l2BufferPool * pool,
|
void gst_v4l2_buffer_pool_copy_at_threshold (GstV4l2BufferPool * pool,
|
||||||
gboolean copy);
|
gboolean copy);
|
||||||
|
|
||||||
gboolean gst_v4l2_buffer_pool_flush (GstV4l2Object * v4l2object);
|
GstFlowReturn gst_v4l2_buffer_pool_flush (GstV4l2Object * v4l2object);
|
||||||
|
|
||||||
gboolean gst_v4l2_buffer_pool_orphan (GstV4l2Object * v4l2object);
|
gboolean gst_v4l2_buffer_pool_orphan (GstV4l2Object * v4l2object);
|
||||||
|
|
||||||
|
|
|
@ -348,8 +348,12 @@ gst_v4l2_video_dec_flush (GstVideoDecoder * decoder)
|
||||||
|
|
||||||
/* gst_v4l2_buffer_pool_flush() calls streamon the capture pool and must be
|
/* gst_v4l2_buffer_pool_flush() calls streamon the capture pool and must be
|
||||||
* called after gst_v4l2_object_unlock_stop() stopped flushing the buffer
|
* called after gst_v4l2_object_unlock_stop() stopped flushing the buffer
|
||||||
* pool. */
|
* pool. If the resolution has changed before we stopped the driver we must
|
||||||
gst_v4l2_buffer_pool_flush (self->v4l2capture);
|
* reallocate the capture pool. We simply discard the pool, and let the
|
||||||
|
* capture thread handle re-allocation.*/
|
||||||
|
if (gst_v4l2_buffer_pool_flush (self->v4l2capture) ==
|
||||||
|
GST_V4L2_FLOW_RESOLUTION_CHANGE || self->draining)
|
||||||
|
gst_v4l2_object_stop (self->v4l2capture);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -888,6 +892,7 @@ beach:
|
||||||
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
|
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
|
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue