mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
GstBufferPool *bpool = gst_v4l2_object_get_buffer_pool (v4l2object);
|
||||
GstV4l2BufferPool *pool;
|
||||
gboolean ret = TRUE;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
|
||||
if (!bpool)
|
||||
return FALSE;
|
||||
return GST_FLOW_ERROR;
|
||||
|
||||
pool = GST_V4L2_BUFFER_POOL (bpool);
|
||||
|
||||
|
@ -2234,8 +2275,14 @@ gst_v4l2_buffer_pool_flush (GstV4l2Object * v4l2object)
|
|||
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_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);
|
||||
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,
|
||||
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);
|
||||
|
||||
|
|
|
@ -348,8 +348,12 @@ gst_v4l2_video_dec_flush (GstVideoDecoder * decoder)
|
|||
|
||||
/* gst_v4l2_buffer_pool_flush() calls streamon the capture pool and must be
|
||||
* called after gst_v4l2_object_unlock_stop() stopped flushing the buffer
|
||||
* pool. */
|
||||
gst_v4l2_buffer_pool_flush (self->v4l2capture);
|
||||
* pool. If the resolution has changed before we stopped the driver we must
|
||||
* 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;
|
||||
}
|
||||
|
@ -888,6 +892,7 @@ beach:
|
|||
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
|
||||
return;
|
||||
}
|
||||
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue