v4l2: Split flush in start/stop_streaming
authorNicolas Dufresne <nicolas.dufresne@collabora.com>
Wed, 14 May 2014 21:18:35 +0000 (17:18 -0400)
committerNicolas Dufresne <nicolas.dufresne@collabora.com>
Thu, 15 May 2014 16:21:44 +0000 (12:21 -0400)
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
sys/v4l2/gstv4l2bufferpool.h
sys/v4l2/gstv4l2transform.c
sys/v4l2/gstv4l2videodec.c

index 3a067f6..0e90650 100644 (file)
@@ -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;
 
index 3a0aeda..3459637 100644 (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);
 
-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);
index aecd530..d0c9139 100644 (file)
@@ -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
index 2b3aa9d..71481d2 100644 (file)
@@ -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 */