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
This commit is contained in:
Nicolas Dufresne 2014-05-14 17:18:35 -04:00
parent c1792de95e
commit a4b5811d22
4 changed files with 62 additions and 26 deletions

View file

@ -1690,29 +1690,38 @@ start_failed:
/** /**
* gst_v4l2_buffer_pool_flush: * gst_v4l2_buffer_pool_stop_streaming:
* @bpool: a #GstBufferPool * @bpool: a #GstBufferPool
* *
* First, set obj->poll to be flushing * First, set obj->poll to be flushing
* Call STREAMOFF to clear QUEUED flag on every driver buffers. * Call STREAMOFF to clear QUEUED flag on every driver buffers.
* Then release all buffers that are in pool->buffers array. * 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. * Returns: TRUE on success.
*/ */
gboolean 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;
/* 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");
/* 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)) if (!start_streaming (pool))
goto start_failed; goto start_failed;

View file

@ -84,7 +84,8 @@ GstBufferPool * gst_v4l2_buffer_pool_new (GstV4l2Object *obj, GstCaps *c
GstFlowReturn gst_v4l2_buffer_pool_process (GstV4l2BufferPool * bpool, GstBuffer ** buf); 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, void gst_v4l2_buffer_pool_set_other_pool (GstV4l2BufferPool * pool,
GstBufferPool * other_pool); GstBufferPool * other_pool);

View file

@ -530,6 +530,11 @@ static gboolean
gst_v4l2_transform_sink_event (GstBaseTransform * trans, GstEvent * event) gst_v4l2_transform_sink_event (GstBaseTransform * trans, GstEvent * event)
{ {
GstV4l2Transform *self = GST_V4L2_TRANSFORM (trans); 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)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_START: case GST_EVENT_FLUSH_START:
@ -539,19 +544,38 @@ gst_v4l2_transform_sink_event (GstBaseTransform * trans, GstEvent * event)
break; break;
case GST_EVENT_FLUSH_STOP: case GST_EVENT_FLUSH_STOP:
GST_DEBUG_OBJECT (self, "flush stop"); GST_DEBUG_OBJECT (self, "flush stop");
if (self->v4l2output->pool)
gst_v4l2_buffer_pool_flush (GST_V4L2_BUFFER_POOL (self->v4l2output-> if (self->v4l2output->pool) {
pool)); gst_v4l2_buffer_pool_stop_streaming (GST_V4L2_BUFFER_POOL
if (self->v4l2capture->pool) (self->v4l2output->pool));
gst_v4l2_buffer_pool_flush (GST_V4L2_BUFFER_POOL (self->v4l2capture-> gst_v4l2_buffer_pool_start_streaming (GST_V4L2_BUFFER_POOL
pool)); (self->v4l2capture->pool));
gst_v4l2_object_unlock_stop (self->v4l2output); gst_v4l2_object_unlock_stop (self->v4l2output);
gst_v4l2_object_unlock_stop (self->v4l2capture); }
if (self->v4l2capture->pool)
gst_v4l2_buffer_pool_stop_streaming (GST_V4L2_BUFFER_POOL
(self->v4l2capture->pool));
default: default:
break; 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 static GstStateChangeReturn

View file

@ -277,13 +277,12 @@ gst_v4l2_video_dec_flush (GstVideoDecoder * decoder)
self->output_flow = GST_FLOW_OK; self->output_flow = GST_FLOW_OK;
if (self->v4l2output->pool) 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) if (self->v4l2capture->pool)
gst_v4l2_buffer_pool_flush (GST_V4L2_BUFFER_POOL (self->v4l2capture->pool)); gst_v4l2_buffer_pool_stop_streaming (GST_V4L2_BUFFER_POOL
(self->v4l2capture->pool));
/* Output will remain flushing until new frame comes in */
gst_v4l2_object_unlock_stop (self->v4l2capture);
return TRUE; return TRUE;
} }
@ -525,7 +524,10 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
GST_DEBUG_OBJECT (self, "Starting decoding thread"); GST_DEBUG_OBJECT (self, "Starting decoding thread");
/* Enable processing input */ /* 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->v4l2output);
gst_v4l2_object_unlock_stop (self->v4l2capture);
/* Start the processing task, when it quits, the task will disable input /* Start the processing task, when it quits, the task will disable input
* processing to unlock input if draining, or prevent potential block */ * processing to unlock input if draining, or prevent potential block */