mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-19 06:46:38 +00:00
tracer: latency: Add parameter to select latency type
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.
This commit is contained in:
parent
6a35153e4e
commit
bdb75a1450
2 changed files with 84 additions and 15 deletions
|
@ -23,7 +23,14 @@
|
||||||
* @short_description: log processing latency stats
|
* @short_description: log processing latency stats
|
||||||
*
|
*
|
||||||
* A tracing module that determines src-to-sink latencies by injecting custom
|
* 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
|
/* 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,
|
* 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
|
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);
|
GstPad *peer_pad = GST_PAD_PEER (pad);
|
||||||
|
|
||||||
|
@ -145,7 +153,8 @@ send_latency_probe (GstElement * parent, GstPad * pad, guint64 ts)
|
||||||
gchar *pad_name;
|
gchar *pad_name;
|
||||||
GstEvent *latency_probe;
|
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));
|
pad_name = g_strdup_printf ("%s_%s", GST_DEBUG_PAD_NAME (pad));
|
||||||
|
|
||||||
GST_DEBUG ("%s: Sending latency event", pad_name);
|
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_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));
|
pad_name = g_strdup_printf ("%s_%s", GST_DEBUG_PAD_NAME (peer_pad));
|
||||||
latency_probe = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
|
latency_probe = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
|
||||||
gst_structure_new_id (sub_latency_probe_id,
|
gst_structure_new_id (sub_latency_probe_id,
|
||||||
latency_probe_pad, G_TYPE_STRING, pad_name,
|
latency_probe_pad, G_TYPE_STRING, pad_name,
|
||||||
latency_probe_ts, G_TYPE_UINT64, ts, NULL));
|
latency_probe_ts, G_TYPE_UINT64, ts, NULL));
|
||||||
gst_pad_push_event (pad, latency_probe);
|
gst_pad_push_event (pad, latency_probe);
|
||||||
g_free (pad_name);
|
g_free (pad_name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,21 +213,23 @@ calculate_latency (GstElement * parent, GstPad * pad, guint64 ts)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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);
|
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);
|
calculate_latency (parent, pad, ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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);
|
GstPad *peer_pad = GST_PAD_PEER (pad);
|
||||||
GstElement *parent = get_real_pad_parent (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
|
static void
|
||||||
|
@ -312,9 +325,55 @@ do_push_event_pre (GstTracer * self, guint64 ts, GstPad * pad, GstEvent * ev)
|
||||||
|
|
||||||
/* tracer class */
|
/* 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", ¶ms, 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
|
static void
|
||||||
gst_latency_tracer_class_init (GstLatencyTracerClass * klass)
|
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");
|
latency_probe_id = g_quark_from_static_string ("latency_probe.id");
|
||||||
sub_latency_probe_id = g_quark_from_static_string ("sub_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");
|
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);
|
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
|
/* 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
|
* function has been called. For this reaosn, we only use -pre to avoid
|
||||||
* accounting for the processing time of the peer element (the sink) */
|
* accounting for the processing time of the peer element (the sink) */
|
||||||
|
|
|
@ -42,6 +42,12 @@ G_BEGIN_DECLS
|
||||||
typedef struct _GstLatencyTracer GstLatencyTracer;
|
typedef struct _GstLatencyTracer GstLatencyTracer;
|
||||||
typedef struct _GstLatencyTracerClass GstLatencyTracerClass;
|
typedef struct _GstLatencyTracerClass GstLatencyTracerClass;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GST_LATENCY_TRACER_FLAG_PIPELINE = 1 << 0,
|
||||||
|
GST_LATENCY_TRACER_FLAG_ELEMENT = 1 << 1,
|
||||||
|
} GstLatencyTracerFlags;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstLatencyTracer:
|
* GstLatencyTracer:
|
||||||
*
|
*
|
||||||
|
@ -51,6 +57,7 @@ struct _GstLatencyTracer {
|
||||||
GstTracer parent;
|
GstTracer parent;
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
|
GstLatencyTracerFlags flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstLatencyTracerClass {
|
struct _GstLatencyTracerClass {
|
||||||
|
|
Loading…
Reference in a new issue