gst-validate-scenario: Make waits optional in appsrc-push
authorAlicia Boya García <ntrrgc@gmail.com>
Sun, 17 Feb 2019 14:38:53 +0000 (15:38 +0100)
committerAlicia Boya García <ntrrgc@gmail.com>
Sun, 24 Feb 2019 00:23:58 +0000 (01:23 +0100)
While in many cases it's desirable to wait for a buffer to be pushed
downstream when using appsrc-push, in some cases this is not possible as
such pushing action is dependent on following actions that would not be
executed if we wait.

An example for this is prerolling:

    appsrc ! qtdemux ! video/x-h264 ! decodebin name=dec ! %(videosink)s

    description, seek=false, handles-states=true
    appsrc-push, target-element-name=appsrc0, file-name="raw_h264.0.mp4"
    set-state, state=playing
    appsrc-eos, target-element-name=appsrc0

In order for the preroll to occur, both the appsrc needs to push the
buffer and the state needs to reach PLAYING. But `set-state` cannot
finish if the buffer has not been pushed (the state transition does not
finish) and conversely pushing the buffer will not finish until the
state has reached.

Making appsrc-push not wait for the buffer solves this problem. This
patch makes appsrc-push aware of this issue by only waiting for the
buffer to be pushed if the pipeline is in a state that allows buffers to
flow.

validate/gst/validate/gst-validate-scenario.c
validate/gst/validate/gst-validate-scenario.h

index ec8a144..2c59220 100644 (file)
@@ -346,6 +346,12 @@ gst_validate_action_init (GstValidateAction * action)
 }
 
 void
+gst_validate_action_ref (GstValidateAction * action)
+{
+  gst_mini_object_ref (GST_MINI_OBJECT (action));
+}
+
+void
 gst_validate_action_unref (GstValidateAction * action)
 {
   gst_mini_object_unref (GST_MINI_OBJECT (action));
@@ -2659,6 +2665,7 @@ appsrc_push_chain_wrapper (GstPad * pad, GstObject * parent, GstBuffer * buffer,
   GST_VALIDATE_SCENARIO_EOS_HANDLING_LOCK (scenario);
   ret = pad->chainfunc (pad, parent, buffer);
   gst_validate_action_set_done (action);
+  gst_validate_action_unref (action);
   *remove_wrapper = TRUE;
   GST_VALIDATE_SCENARIO_EOS_HANDLING_UNLOCK (scenario);
   g_object_unref (scenario);
@@ -2698,6 +2705,12 @@ _execute_appsrc_push (GstValidateScenario * scenario,
   guint64 offset = 0;
   guint64 size = -1;
   gint push_buffer_ret;
+  gboolean wait;
+
+  /* We will only wait for the the buffer to be pushed if we are in a state
+   * that allows flow of buffers (>=PAUSED). Otherwise the buffer will just
+   * be enqueued. */
+  wait = scenario->priv->target_state >= GST_STATE_PAUSED;
 
   target = _get_target_element (scenario, action);
   if (target == NULL) {
@@ -2759,6 +2772,9 @@ _execute_appsrc_push (GstValidateScenario * scenario,
     gst_object_unref (peer_pad);
   }
 
+  /* Keep the action alive until set done is called. */
+  gst_validate_action_ref (action);
+
   g_signal_emit_by_name (target, "push-buffer", buffer, &push_buffer_ret);
   if (push_buffer_ret != GST_FLOW_OK) {
     gchar *structure_string = gst_structure_to_string (action->structure);
@@ -2770,7 +2786,14 @@ _execute_appsrc_push (GstValidateScenario * scenario,
 
   g_free (file_name);
   gst_object_unref (target);
-  return GST_VALIDATE_EXECUTE_ACTION_ASYNC;
+
+  if (wait) {
+    return GST_VALIDATE_EXECUTE_ACTION_ASYNC;
+  } else {
+    gst_validate_printf (NULL,
+        "Pipeline is not ready to push buffers, interlacing appsrc-push action...");
+    return GST_VALIDATE_EXECUTE_ACTION_INTERLACED;
+  }
 }
 
 static gint
@@ -3357,6 +3380,9 @@ _load_scenario_file (GstValidateScenario * scenario,
       gst_structure_get_boolean (structure, "handles-states",
           &priv->handles_state);
 
+      if (!priv->handles_state)
+        priv->target_state = GST_STATE_PLAYING;
+
       pipeline_name = gst_structure_get_string (structure, "pipeline-name");
       if (pipeline_name) {
         g_free (priv->pipeline_name);
@@ -5072,7 +5098,7 @@ init_scenarios (void)
         },
         {NULL}
       }),
-      "Queues a buffer from an appsrc and waits for it to be handled by downstream elements in the same streaming thread.",
+      "Queues a buffer in an appsrc. If the pipeline state allows flow of buffers, the next action is not run until the buffer has been pushed.",
       GST_VALIDATE_ACTION_TYPE_NONE);
 
   REGISTER_ACTION_TYPE ("appsrc-eos", _execute_appsrc_eos,
index 39ac488..963c517 100644 (file)
@@ -126,6 +126,8 @@ GstValidateAction   * gst_validate_action_new          (GstValidateScenario * sc
                                                         GstStructure *structure,
                                                         gboolean add_to_lists);
 GST_VALIDATE_API
+void gst_validate_action_ref               (GstValidateAction * action);
+GST_VALIDATE_API
 void gst_validate_action_unref             (GstValidateAction * action);
 
 #define GST_TYPE_VALIDATE_ACTION            (gst_validate_action_get_type ())