v4l2videodec: Don't lock the decoder when stopping task
[platform/upstream/gst-plugins-good.git] / sys / v4l2 / gstv4l2videodec.c
index 2fc2763..9de0b54 100644 (file)
@@ -74,8 +74,8 @@ gst_v4l2_video_dec_set_property (GObject * object,
           pspec);
       break;
     case PROP_CAPTURE_IO_MODE:
-      gst_v4l2_object_set_property_helper (self->v4l2capture, prop_id, value,
-          pspec);
+      gst_v4l2_object_set_property_helper (self->v4l2capture, PROP_IO_MODE,
+          value, pspec);
       break;
 
     case PROP_DEVICE:
@@ -213,9 +213,10 @@ gst_v4l2_video_dec_stop (GstVideoDecoder * decoder)
   gst_v4l2_object_unlock (self->v4l2output);
   gst_v4l2_object_unlock (self->v4l2capture);
 
-  GST_VIDEO_DECODER_STREAM_LOCK (decoder);
   /* Wait for capture thread to stop */
   gst_pad_stop_task (decoder->srcpad);
+
+  GST_VIDEO_DECODER_STREAM_LOCK (decoder);
   self->output_flow = GST_FLOW_OK;
   GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
 
@@ -251,6 +252,7 @@ gst_v4l2_video_dec_set_format (GstVideoDecoder * decoder,
       goto done;
     }
     gst_video_codec_state_unref (self->input_state);
+    self->input_state = NULL;
 
     /* FIXME we probably need to do more work if pools are active */
   }
@@ -272,14 +274,18 @@ gst_v4l2_video_dec_flush (GstVideoDecoder * decoder)
   GST_DEBUG_OBJECT (self, "Flushing");
 
   /* Wait for capture thread to stop */
+  GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
   gst_pad_stop_task (decoder->srcpad);
+  GST_VIDEO_DECODER_STREAM_LOCK (decoder);
   self->output_flow = GST_FLOW_OK;
 
-  gst_v4l2_buffer_pool_flush (GST_V4L2_BUFFER_POOL (self->v4l2output->pool));
-  gst_v4l2_buffer_pool_flush (GST_V4L2_BUFFER_POOL (self->v4l2capture->pool));
+  if (self->v4l2output->pool)
+    gst_v4l2_buffer_pool_stop_streaming (GST_V4L2_BUFFER_POOL
+        (self->v4l2output->pool));
 
-  /* Output will remain flushing until new frame comes in */
-  gst_v4l2_object_unlock_stop (self->v4l2capture);
+  if (self->v4l2capture->pool)
+    gst_v4l2_buffer_pool_stop_streaming (GST_V4L2_BUFFER_POOL
+        (self->v4l2capture->pool));
 
   return TRUE;
 }
@@ -309,7 +315,7 @@ gst_v4l2_video_dec_finish (GstVideoDecoder * decoder)
     buffer = gst_buffer_new ();
     ret =
         gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->
-            v4l2output->pool), buffer);
+            v4l2output->pool), &buffer);
     gst_buffer_unref (buffer);
   }
   GST_VIDEO_DECODER_STREAM_LOCK (decoder);
@@ -376,20 +382,23 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
    * comes in and holding this lock would prevent that.
    */
   pool = gst_video_decoder_get_buffer_pool (decoder);
+
+  /* Pool may be NULL if we started going to READY state */
+  if (pool == NULL) {
+    ret = GST_FLOW_FLUSHING;
+    goto beach;
+  }
+
   ret = gst_buffer_pool_acquire_buffer (pool, &buffer, NULL);
   g_object_unref (pool);
 
   if (ret != GST_FLOW_OK)
     goto beach;
 
-  /* Check if buffer isn't the last one */
-  if (gst_buffer_get_size (buffer) == 0)
-    goto beach;
-
   GST_LOG_OBJECT (decoder, "Process output buffer");
   ret =
       gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->
-          v4l2capture->pool), buffer);
+          v4l2capture->pool), &buffer);
 
   if (ret != GST_FLOW_OK)
     goto beach;
@@ -433,11 +442,14 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
     goto flushing;
 
   if (G_UNLIKELY (!GST_V4L2_IS_ACTIVE (self->v4l2output))) {
+    if (!self->input_state)
+      goto not_negotiated;
     if (!gst_v4l2_object_set_format (self->v4l2output, self->input_state->caps))
       goto not_negotiated;
   }
 
   if (G_UNLIKELY (!GST_V4L2_IS_ACTIVE (self->v4l2capture))) {
+    GstBufferPool *pool = GST_BUFFER_POOL (self->v4l2output->pool);
     GstVideoInfo info;
     GstVideoCodecState *output_state;
     GstBuffer *codec_data;
@@ -457,17 +469,31 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
       frame->input_buffer = NULL;
     }
 
+    /* Ensure input internal pool is active */
+    if (!gst_buffer_pool_is_active (pool)) {
+      GstStructure *config = gst_buffer_pool_get_config (pool);
+      gst_buffer_pool_config_set_params (config, self->input_state->caps,
+          self->v4l2output->info.size, 2, 2);
+
+      /* There is no reason to refuse this config */
+      if (!gst_buffer_pool_set_config (pool, config))
+        goto activate_failed;
+
+      if (!gst_buffer_pool_set_active (pool, TRUE))
+        goto activate_failed;
+    }
+
     GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
     gst_v4l2_object_unlock_stop (self->v4l2output);
     ret =
         gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->
-            v4l2output->pool), codec_data);
+            v4l2output->pool), &codec_data);
     gst_v4l2_object_unlock (self->v4l2output);
     GST_VIDEO_DECODER_STREAM_LOCK (decoder);
 
     gst_buffer_unref (codec_data);
 
-    if (!gst_v4l2_object_setup_format (self->v4l2capture, &info, &self->align))
+    if (!gst_v4l2_object_acquire_format (self->v4l2capture, &info))
       goto not_negotiated;
 
     output_state = gst_video_decoder_set_output_state (decoder,
@@ -483,6 +509,11 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
       else
         goto not_negotiated;
     }
+
+    /* Ensure our internal pool is activated */
+    if (!gst_buffer_pool_set_active (GST_BUFFER_POOL (self->v4l2capture->pool),
+            TRUE))
+      goto activate_failed;
   }
 
   if (g_atomic_int_get (&self->processing) == FALSE) {
@@ -496,7 +527,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 */
@@ -509,7 +543,7 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
     GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
     ret =
         gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->v4l2output->
-            pool), frame->input_buffer);
+            pool), &frame->input_buffer);
     GST_VIDEO_DECODER_STREAM_LOCK (decoder);
 
     if (ret == GST_FLOW_FLUSHING) {
@@ -531,6 +565,13 @@ not_negotiated:
     ret = GST_FLOW_NOT_NEGOTIATED;
     goto drop;
   }
+activate_failed:
+  {
+    GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
+        (_("Failed to allocate required memory.")),
+        ("Buffer pool activation failed"));
+    return GST_FLOW_ERROR;
+  }
 flushing:
   {
     ret = GST_FLOW_FLUSHING;
@@ -786,7 +827,7 @@ gst_v4l2_video_dec_class_init (GstV4l2VideoDecClass * klass)
    *
    * Capture IO Mode
    */
-  g_object_class_install_property (gobject_class, PROP_IO_MODE,
+  g_object_class_install_property (gobject_class, PROP_CAPTURE_IO_MODE,
       g_param_spec_enum ("capture-io-mode", "Capture IO mode",
           "Capture I/O mode",
           GST_TYPE_V4L2_IO_MODE, GST_V4L2_IO_AUTO,