tracer: latency: Add parameter to select latency type
authorNicolas Dufresne <nicolas.dufresne@collabora.com>
Wed, 31 Oct 2018 20:50:48 +0000 (16:50 -0400)
committerJulian Bouzas <julian.bouzas@collabora.com>
Mon, 8 Apr 2019 16:28:07 +0000 (12:28 -0400)
This sets back the default to trace only pipeline latency, and add flags
to enabled element tracing. It is now possible to only trace element
latency, only trace pipeline latency, trace both or none.

plugins/tracers/gstlatency.c
plugins/tracers/gstlatency.h

index 8e30be3af5a070299144428e7c6f03f32541ee8f..bb6aedf054fbed9e088f989dee0e3dd52ddfe0e3 100644 (file)
  * @short_description: log processing latency stats
  *
  * A tracing module that determines src-to-sink latencies by injecting custom
- * events at sources and process them at sinks.
+ * events at sources and process them at sinks. This elements supports tracing
+ * the entire pipeline latency and per element latency. By default, only
+ * pipeline latency is traced. The 'flags' parameter can be used to enabled
+ * element tracing.
+ *
+ * ```
+ * GST_TRACERS="latency(flags=pipeline+element)" GST_DEBUG=GST_TRACER:7 ./...
+ * ```
  */
 /* TODO(ensonic): if there are two sources feeding into a mixer/muxer and later
  * we fan-out with tee and have two sinks, each sink would get all two events,
@@ -135,7 +142,8 @@ log_element_latency (const GstStructure * data, GstElement * element,
 }
 
 static void
-send_latency_probe (GstElement * parent, GstPad * pad, guint64 ts)
+send_latency_probe (GstLatencyTracer * self, GstElement * parent, GstPad * pad,
+    guint64 ts)
 {
   GstPad *peer_pad = GST_PAD_PEER (pad);
 
@@ -145,7 +153,8 @@ send_latency_probe (GstElement * parent, GstPad * pad, guint64 ts)
     gchar *pad_name;
     GstEvent *latency_probe;
 
-    if (GST_OBJECT_FLAG_IS_SET (parent, GST_ELEMENT_FLAG_SOURCE)) {
+    if (self->flags & GST_LATENCY_TRACER_FLAG_PIPELINE &&
+        GST_OBJECT_FLAG_IS_SET (parent, GST_ELEMENT_FLAG_SOURCE)) {
       pad_name = g_strdup_printf ("%s_%s", GST_DEBUG_PAD_NAME (pad));
 
       GST_DEBUG ("%s: Sending latency event", pad_name);
@@ -158,15 +167,17 @@ send_latency_probe (GstElement * parent, GstPad * pad, guint64 ts)
       gst_pad_push_event (pad, latency_probe);
     }
 
-    GST_DEBUG ("%s_%s: Sending sub-latency event", GST_DEBUG_PAD_NAME (pad));
+    if (self->flags & GST_LATENCY_TRACER_FLAG_ELEMENT) {
+      GST_DEBUG ("%s_%s: Sending sub-latency event", GST_DEBUG_PAD_NAME (pad));
 
-    pad_name = g_strdup_printf ("%s_%s", GST_DEBUG_PAD_NAME (peer_pad));
-    latency_probe = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
-        gst_structure_new_id (sub_latency_probe_id,
-            latency_probe_pad, G_TYPE_STRING, pad_name,
-            latency_probe_ts, G_TYPE_UINT64, ts, NULL));
-    gst_pad_push_event (pad, latency_probe);
-    g_free (pad_name);
+      pad_name = g_strdup_printf ("%s_%s", GST_DEBUG_PAD_NAME (peer_pad));
+      latency_probe = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
+          gst_structure_new_id (sub_latency_probe_id,
+              latency_probe_pad, G_TYPE_STRING, pad_name,
+              latency_probe_ts, G_TYPE_UINT64, ts, NULL));
+      gst_pad_push_event (pad, latency_probe);
+      g_free (pad_name);
+    }
   }
 }
 
@@ -202,21 +213,23 @@ calculate_latency (GstElement * parent, GstPad * pad, guint64 ts)
 }
 
 static void
-do_push_buffer_pre (GstTracer * self, guint64 ts, GstPad * pad)
+do_push_buffer_pre (GstTracer * tracer, guint64 ts, GstPad * pad)
 {
+  GstLatencyTracer *self = (GstLatencyTracer *) tracer;
   GstElement *parent = get_real_pad_parent (pad);
 
-  send_latency_probe (parent, pad, ts);
+  send_latency_probe (self, parent, pad, ts);
   calculate_latency (parent, pad, ts);
 }
 
 static void
-do_pull_range_pre (GstTracer * self, guint64 ts, GstPad * pad)
+do_pull_range_pre (GstTracer * tracer, guint64 ts, GstPad * pad)
 {
+  GstLatencyTracer *self = (GstLatencyTracer *) tracer;
   GstPad *peer_pad = GST_PAD_PEER (pad);
   GstElement *parent = get_real_pad_parent (peer_pad);
 
-  send_latency_probe (parent, peer_pad, ts);
+  send_latency_probe (self, parent, peer_pad, ts);
 }
 
 static void
@@ -312,9 +325,55 @@ do_push_event_pre (GstTracer * self, guint64 ts, GstPad * pad, GstEvent * ev)
 
 /* tracer class */
 
+static void
+gst_latency_tracer_constructed (GObject * object)
+{
+  GstLatencyTracer *self = GST_LATENCY_TRACER (object);
+  gchar *params, *tmp;
+  GstStructure *params_struct = NULL;
+
+  g_object_get (self, "params", &params, NULL);
+
+  if (!params)
+    return;
+
+  tmp = g_strdup_printf ("latency,%s", params);
+  params_struct = gst_structure_from_string (tmp, NULL);
+  g_free (tmp);
+
+  /* Read the flags if available */
+  if (params_struct) {
+    const gchar *flags = gst_structure_get_string (params_struct, "flags");
+
+    self->flags = 0;
+
+    if (flags) {
+      GStrv split = g_strsplit (flags, "+", -1);
+      gint i;
+
+      for (i = 0; split[i]; i++) {
+        if (g_str_equal (split[i], "pipeline"))
+          self->flags |= GST_LATENCY_TRACER_FLAG_PIPELINE;
+        else if (g_str_equal (split[i], "element"))
+          self->flags |= GST_LATENCY_TRACER_FLAG_ELEMENT;
+        else
+          GST_WARNING ("Invalid latency tracer flags %s", split[i]);
+      }
+
+      g_strfreev (split);
+    }
+  }
+
+  g_free (params);
+}
+
 static void
 gst_latency_tracer_class_init (GstLatencyTracerClass * klass)
 {
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->constructed = gst_latency_tracer_constructed;
+
   latency_probe_id = g_quark_from_static_string ("latency_probe.id");
   sub_latency_probe_id = g_quark_from_static_string ("sub_latency_probe.id");
   latency_probe_pad = g_quark_from_static_string ("latency_probe.pad");
@@ -375,6 +434,9 @@ gst_latency_tracer_init (GstLatencyTracer * self)
 {
   GstTracer *tracer = GST_TRACER (self);
 
+  /* only trace pipeline latency by default */
+  self->flags = GST_LATENCY_TRACER_FLAG_PIPELINE;
+
   /* in push mode, pre/post will be called before/after the peer chain
    * function has been called. For this reaosn, we only use -pre to avoid
    * accounting for the processing time of the peer element (the sink) */
index e2343033361e2a0b905f9880f64336880976f1e7..1c4cc45212bc365ddb620d10025132537ac0d5ae 100644 (file)
@@ -42,6 +42,12 @@ G_BEGIN_DECLS
 typedef struct _GstLatencyTracer GstLatencyTracer;
 typedef struct _GstLatencyTracerClass GstLatencyTracerClass;
 
+typedef enum
+{
+  GST_LATENCY_TRACER_FLAG_PIPELINE = 1 << 0,
+  GST_LATENCY_TRACER_FLAG_ELEMENT = 1 << 1,
+} GstLatencyTracerFlags;
+
 /**
  * GstLatencyTracer:
  *
@@ -51,6 +57,7 @@ struct _GstLatencyTracer {
   GstTracer     parent;
 
   /*< private >*/
+  GstLatencyTracerFlags flags;
 };
 
 struct _GstLatencyTracerClass {