From a4b5811d22ba401fbcfc4d264034a9ca1d9aca67 Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Wed, 14 May 2014 17:18:35 -0400 Subject: [PATCH] v4l2: Split flush in start/stop_streaming This allow calling start streaming later for capture device. Currently it breaks in dmabuf-import because downstream is holding a buffer that will only be released after stream-start. https://bugzilla.gnome.org/show_bug.cgi?id=730207 --- sys/v4l2/gstv4l2bufferpool.c | 33 ++++++++++++++++++----------- sys/v4l2/gstv4l2bufferpool.h | 3 ++- sys/v4l2/gstv4l2transform.c | 40 ++++++++++++++++++++++++++++-------- sys/v4l2/gstv4l2videodec.c | 12 ++++++----- 4 files changed, 62 insertions(+), 26 deletions(-) diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c index 3a067f6ad4..0e90650818 100644 --- a/sys/v4l2/gstv4l2bufferpool.c +++ b/sys/v4l2/gstv4l2bufferpool.c @@ -1690,31 +1690,40 @@ start_failed: /** - * gst_v4l2_buffer_pool_flush: + * gst_v4l2_buffer_pool_stop_streaming: * @bpool: a #GstBufferPool * * First, set obj->poll to be flushing * Call STREAMOFF to clear QUEUED flag on every driver buffers. * Then release all buffers that are in pool->buffers array. - * Finally call STREAMON if CAPTURE type - * The caller is responsible to unset flushing on obj->pool * * Returns: TRUE on success. */ gboolean -gst_v4l2_buffer_pool_flush (GstV4l2BufferPool * pool) +gst_v4l2_buffer_pool_stop_streaming (GstV4l2BufferPool * pool) { - GstV4l2Object *obj = pool->obj; + GST_DEBUG_OBJECT (pool, "stop streaming"); - GST_DEBUG_OBJECT (pool, "flush"); + if (!stop_streaming (pool)) + goto stop_failed; - stop_streaming (pool); + return TRUE; - /* we can start capturing now, we wait for the playback - * case until we queued the first buffer */ - if (!V4L2_TYPE_IS_OUTPUT (obj->type)) - if (!start_streaming (pool)) - goto start_failed; + /* ERRORS */ +stop_failed: + { + GST_ERROR_OBJECT (pool, "failed to stop streaming"); + return FALSE; + } +} + +gboolean +gst_v4l2_buffer_pool_start_streaming (GstV4l2BufferPool * pool) +{ + GST_DEBUG_OBJECT (pool, "start straming"); + + if (!start_streaming (pool)) + goto start_failed; return TRUE; diff --git a/sys/v4l2/gstv4l2bufferpool.h b/sys/v4l2/gstv4l2bufferpool.h index 3a0aeda25a..3459637d51 100644 --- a/sys/v4l2/gstv4l2bufferpool.h +++ b/sys/v4l2/gstv4l2bufferpool.h @@ -84,7 +84,8 @@ GstBufferPool * gst_v4l2_buffer_pool_new (GstV4l2Object *obj, GstCaps *c GstFlowReturn gst_v4l2_buffer_pool_process (GstV4l2BufferPool * bpool, GstBuffer ** buf); -gboolean gst_v4l2_buffer_pool_flush (GstV4l2BufferPool * pool); +gboolean gst_v4l2_buffer_pool_stop_streaming (GstV4l2BufferPool * pool); +gboolean gst_v4l2_buffer_pool_start_streaming (GstV4l2BufferPool * pool); void gst_v4l2_buffer_pool_set_other_pool (GstV4l2BufferPool * pool, GstBufferPool * other_pool); diff --git a/sys/v4l2/gstv4l2transform.c b/sys/v4l2/gstv4l2transform.c index aecd530e98..d0c9139863 100644 --- a/sys/v4l2/gstv4l2transform.c +++ b/sys/v4l2/gstv4l2transform.c @@ -530,6 +530,11 @@ static gboolean gst_v4l2_transform_sink_event (GstBaseTransform * trans, GstEvent * event) { GstV4l2Transform *self = GST_V4L2_TRANSFORM (trans); + gboolean ret; + + /* Nothing to flush in passthrough */ + if (gst_base_transform_is_passthrough (trans)) + return GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_START: @@ -539,19 +544,38 @@ gst_v4l2_transform_sink_event (GstBaseTransform * trans, GstEvent * event) break; case GST_EVENT_FLUSH_STOP: GST_DEBUG_OBJECT (self, "flush stop"); - if (self->v4l2output->pool) - gst_v4l2_buffer_pool_flush (GST_V4L2_BUFFER_POOL (self->v4l2output-> - pool)); + + if (self->v4l2output->pool) { + gst_v4l2_buffer_pool_stop_streaming (GST_V4L2_BUFFER_POOL + (self->v4l2output->pool)); + gst_v4l2_buffer_pool_start_streaming (GST_V4L2_BUFFER_POOL + (self->v4l2capture->pool)); + gst_v4l2_object_unlock_stop (self->v4l2output); + } if (self->v4l2capture->pool) - gst_v4l2_buffer_pool_flush (GST_V4L2_BUFFER_POOL (self->v4l2capture-> - pool)); - gst_v4l2_object_unlock_stop (self->v4l2output); - gst_v4l2_object_unlock_stop (self->v4l2capture); + gst_v4l2_buffer_pool_stop_streaming (GST_V4L2_BUFFER_POOL + (self->v4l2capture->pool)); default: break; } - return GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event); + ret = GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + /* Buffer should be back now */ + if (self->v4l2capture->pool) { + gst_v4l2_buffer_pool_start_streaming (GST_V4L2_BUFFER_POOL + (self->v4l2capture->pool)); + gst_v4l2_object_unlock_stop (self->v4l2capture); + } + GST_DEBUG_OBJECT (self, "flush stop done"); + break; + default: + break; + } + + return ret; } static GstStateChangeReturn diff --git a/sys/v4l2/gstv4l2videodec.c b/sys/v4l2/gstv4l2videodec.c index 2b3aa9d83a..71481d22af 100644 --- a/sys/v4l2/gstv4l2videodec.c +++ b/sys/v4l2/gstv4l2videodec.c @@ -277,13 +277,12 @@ gst_v4l2_video_dec_flush (GstVideoDecoder * decoder) self->output_flow = GST_FLOW_OK; if (self->v4l2output->pool) - gst_v4l2_buffer_pool_flush (GST_V4L2_BUFFER_POOL (self->v4l2output->pool)); + gst_v4l2_buffer_pool_stop_streaming (GST_V4L2_BUFFER_POOL + (self->v4l2output->pool)); if (self->v4l2capture->pool) - gst_v4l2_buffer_pool_flush (GST_V4L2_BUFFER_POOL (self->v4l2capture->pool)); - - /* Output will remain flushing until new frame comes in */ - gst_v4l2_object_unlock_stop (self->v4l2capture); + gst_v4l2_buffer_pool_stop_streaming (GST_V4L2_BUFFER_POOL + (self->v4l2capture->pool)); return TRUE; } @@ -525,7 +524,10 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder, GST_DEBUG_OBJECT (self, "Starting decoding thread"); /* Enable processing input */ + gst_v4l2_buffer_pool_start_streaming (GST_V4L2_BUFFER_POOL + (self->v4l2capture->pool)); gst_v4l2_object_unlock_stop (self->v4l2output); + gst_v4l2_object_unlock_stop (self->v4l2capture); /* Start the processing task, when it quits, the task will disable input * processing to unlock input if draining, or prevent potential block */