validate: allow scenarios to define max pipeline latency
authorGuillaume Desmottes <guillaume.desmottes@collabora.com>
Mon, 4 Feb 2019 16:03:01 +0000 (17:03 +0100)
committerGuillaume Desmottes <guillaume.desmottes@collabora.com>
Wed, 6 Feb 2019 15:07:02 +0000 (16:07 +0100)
The 'max-latency' description field can now be used to specify the max
latency allowed for the running pipeline.

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

index 955e7ab..960d7d1 100644 (file)
@@ -396,6 +396,10 @@ gst_validate_report_load_issues (void)
       _("The execution of an action did not properly happen"), NULL);
   REGISTER_VALIDATE_ISSUE (ISSUE, SCENARIO_ACTION_EXECUTION_ISSUE,
       _("An issue happened during the execution of a scenario"), NULL);
+  REGISTER_VALIDATE_ISSUE (CRITICAL, SCENARIO_ACTION_LATENCY_TOO_HIGH,
+      _
+      ("The pipeline latency is higher than the maximum allowed by the scenario"),
+      NULL);
   REGISTER_VALIDATE_ISSUE (WARNING, G_LOG_WARNING, _("We got a g_log warning"),
       NULL);
   REGISTER_VALIDATE_ISSUE (CRITICAL, G_LOG_CRITICAL,
index 4c43aae..83be159 100644 (file)
@@ -120,6 +120,7 @@ typedef enum {
 #define SCENARIO_ACTION_EXECUTION_ERROR          _QUARK("scenario::execution-error")
 #define SCENARIO_ACTION_TIMEOUT                  _QUARK("scenario::action-timeout")
 #define SCENARIO_ACTION_EXECUTION_ISSUE          _QUARK("scenario::execution-issue")
+#define SCENARIO_ACTION_LATENCY_TOO_HIGH         _QUARK("scenario::latency-too-high")
 
 #define G_LOG_ISSUE                              _QUARK("g-log::issue")
 #define G_LOG_WARNING                            _QUARK("g-log::warning")
index 9a1203b..a331045 100644 (file)
@@ -157,6 +157,7 @@ struct _GstValidateScenarioPrivate
   GList *overrides;
 
   gchar *pipeline_name;
+  GstClockTime max_latency;
 
   /* 'switch-track action' currently waiting for
    * GST_MESSAGE_STREAMS_SELECTED to be completed. */
@@ -2634,6 +2635,36 @@ streams_list_contain (GList * streams, const gchar * stream_id)
   return FALSE;
 }
 
+static void
+gst_validate_scenario_check_latency (GstValidateScenario * scenario,
+    GstElement * pipeline)
+{
+  GstValidateScenarioPrivate *priv = scenario->priv;
+  GstQuery *query;
+  GstClockTime min_latency;
+
+  query = gst_query_new_latency ();
+  if (!gst_element_query (GST_ELEMENT_CAST (pipeline), query)) {
+    GST_VALIDATE_REPORT (scenario, SCENARIO_ACTION_EXECUTION_ERROR,
+        "Failed to perfom LATENCY query");
+    gst_query_unref (query);
+    return;
+  }
+
+  gst_query_parse_latency (query, NULL, &min_latency, NULL);
+  GST_DEBUG_OBJECT (scenario, "Pipeline latency: %" GST_TIME_FORMAT
+      " max allowed: %" GST_TIME_FORMAT,
+      GST_TIME_ARGS (min_latency), GST_TIME_ARGS (priv->max_latency));
+
+  if (priv->max_latency != GST_CLOCK_TIME_NONE &&
+      min_latency > priv->max_latency) {
+    GST_VALIDATE_REPORT (scenario, SCENARIO_ACTION_LATENCY_TOO_HIGH,
+        "Pipeline latency is too high: %" GST_TIME_FORMAT " (max allowed %"
+        GST_TIME_FORMAT ")", GST_TIME_ARGS (min_latency),
+        GST_TIME_ARGS (priv->max_latency));
+  }
+}
+
 static gboolean
 message_cb (GstBus * bus, GstMessage * message, GstValidateScenario * scenario)
 {
@@ -2702,6 +2733,11 @@ message_cb (GstBus * bus, GstMessage * message, GstValidateScenario * scenario)
 
         if (pstate == GST_STATE_READY && nstate == GST_STATE_PAUSED)
           _add_execute_actions_gsource (scenario);
+
+        /* GstBin only send a new latency message when reaching PLAYING if
+         * async-handling=true so check the latency manually. */
+        if (nstate == GST_STATE_PLAYING)
+          gst_validate_scenario_check_latency (scenario, pipeline);
       }
       break;
     }
@@ -2858,6 +2894,9 @@ message_cb (GstBus * bus, GstMessage * message, GstValidateScenario * scenario)
       g_list_free_full (streams_selected, gst_object_unref);
       break;
     }
+    case GST_MESSAGE_LATENCY:
+      gst_validate_scenario_check_latency (scenario, pipeline);
+      break;
 
     default:
       break;
@@ -2895,6 +2934,7 @@ _load_scenario_file (GstValidateScenario * scenario,
   gboolean ret = TRUE;
   GList *structures, *tmp;
   GstValidateScenarioPrivate *priv = scenario->priv;
+  GList *config;
 
   *is_config = FALSE;
 
@@ -2922,6 +2962,9 @@ _load_scenario_file (GstValidateScenario * scenario,
         priv->pipeline_name = g_strdup (pipeline_name);
       }
 
+      gst_validate_utils_get_clocktime (structure, "max-latency",
+          &priv->max_latency);
+
       continue;
     } else if (!g_strcmp0 (type, "include")) {
       const gchar *location = gst_structure_get_string (structure, "location");
@@ -2973,6 +3016,14 @@ _load_scenario_file (GstValidateScenario * scenario,
     action->action_number = priv->num_actions++;
   }
 
+  /* max latency can be overriden using config */
+  for (config = gst_validate_plugin_get_config (NULL); config;
+      config = g_list_next (config)) {
+    if (gst_validate_utils_get_clocktime (config->data, "max-latency",
+            &priv->max_latency))
+      break;
+  }
+
 done:
   g_list_free_full (structures, (GDestroyNotify) gst_structure_free);
 
@@ -3216,6 +3267,7 @@ gst_validate_scenario_init (GstValidateScenario * scenario)
   priv->action_execution_interval = 10;
   priv->vars = gst_structure_new_empty ("vars");
   g_weak_ref_init (&scenario->priv->ref_pipeline, NULL);
+  priv->max_latency = GST_CLOCK_TIME_NONE;
 
   g_mutex_init (&priv->lock);
 }
@@ -4244,6 +4296,16 @@ init_scenarios (void)
         .possible_variables = NULL,
         .def = "NULL"
       },
+      {
+        .name = "max-latency",
+        .description = "The maximum latency in nanoseconds allowed for this pipeline.\n"
+          "It can be overriden using core configuration, like for example by defining the "
+          "env variable GST_VALIDATE_CONFIG=core,max-latency=33000000",
+        .mandatory = FALSE,
+        .types = "double, int",
+        .possible_variables = NULL,
+        .def = "infinite (GST_CLOCK_TIME_NONE)"
+      },
       {NULL}
       }),
       "Allows to describe the scenario in various ways",