From ce7ce2d86697cf8373b02fae8a93892c154bc227 Mon Sep 17 00:00:00 2001 From: Stefan Sauer Date: Wed, 16 Jul 2014 09:22:14 +0200 Subject: [PATCH] tracer: add more hooks and handle it in the plugins --- gst/gstelement.c | 17 +++- gst/gstpad.c | 36 ++++++--- gst/gsttracer.h | 80 +++++++++++++++++++ plugins/tracers/Makefile.am | 2 +- plugins/tracers/gstlog.c | 44 ++++++++++- plugins/tracers/gststats.c | 149 ++++++++++++++++++++++++++++++++++++ 6 files changed, 308 insertions(+), 20 deletions(-) diff --git a/gst/gstelement.c b/gst/gstelement.c index 2c44a39b45..ae43812946 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -90,6 +90,7 @@ #include "gstutils.h" #include "gstinfo.h" #include "gstquark.h" +#include "gsttracer.h" #include "gstvalue.h" #include "gst-i18n-lib.h" #include "glib-compat-private.h" @@ -1656,18 +1657,22 @@ gboolean gst_element_query (GstElement * element, GstQuery * query) { GstElementClass *klass; + gboolean res = FALSE; g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); g_return_val_if_fail (query != NULL, FALSE); + GST_TRACER_ELEMENT_QUERY_PRE (element, query); + klass = GST_ELEMENT_GET_CLASS (element); if (klass->query) { GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send query on element %s", GST_ELEMENT_NAME (element)); - return klass->query (element, query); + res = klass->query (element, query); } - return FALSE; + GST_TRACER_ELEMENT_QUERY_POST (element, res); + return res; } static gboolean @@ -1724,15 +1729,19 @@ gboolean gst_element_post_message (GstElement * element, GstMessage * message) { GstElementClass *klass; + gboolean res = FALSE; g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); g_return_val_if_fail (message != NULL, FALSE); + GST_TRACER_ELEMENT_POST_MESSAGE_PRE (element, message); + klass = GST_ELEMENT_GET_CLASS (element); if (klass->post_message) - return klass->post_message (element, message); + res = klass->post_message (element, message); - return FALSE; + GST_TRACER_ELEMENT_POST_MESSAGE_POST (element, res); + return res; } /** diff --git a/gst/gstpad.c b/gst/gstpad.c index 841a9bb04f..c31f4961b0 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -4760,6 +4760,8 @@ gst_pad_pull_range (GstPad * pad, guint64 offset, guint size, g_return_val_if_fail (*buffer == NULL || (GST_IS_BUFFER (*buffer) && gst_buffer_get_size (*buffer) >= size), GST_FLOW_ERROR); + GST_TRACER_PAD_PULL_RANGE_PRE (pad, offset, size); + GST_OBJECT_LOCK (pad); if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) goto flushing; @@ -4806,6 +4808,7 @@ probed_data: *buffer = res_buf; + GST_TRACER_PAD_PULL_RANGE_POST (pad, *buffer, ret); return ret; /* ERROR recovery here */ @@ -4815,7 +4818,8 @@ flushing: "pullrange, but pad was flushing"); pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING; GST_OBJECT_UNLOCK (pad); - return GST_FLOW_FLUSHING; + ret = GST_FLOW_FLUSHING; + goto done; } wrong_mode: { @@ -4823,7 +4827,8 @@ wrong_mode: GST_DEBUG_PAD_NAME (pad)); pad->ABI.abi.last_flowret = GST_FLOW_ERROR; GST_OBJECT_UNLOCK (pad); - return GST_FLOW_ERROR; + ret = GST_FLOW_ERROR; + goto done; } probe_stopped: { @@ -4844,7 +4849,7 @@ probe_stopped: } pad->ABI.abi.last_flowret = ret; GST_OBJECT_UNLOCK (pad); - return ret; + goto done; } not_linked: { @@ -4852,7 +4857,8 @@ not_linked: "pulling range, but it was not linked"); pad->ABI.abi.last_flowret = GST_FLOW_NOT_LINKED; GST_OBJECT_UNLOCK (pad); - return GST_FLOW_NOT_LINKED; + ret = GST_FLOW_NOT_LINKED; + goto done; } pull_range_failed: { @@ -4861,7 +4867,7 @@ pull_range_failed: GST_CAT_LEVEL_LOG (GST_CAT_SCHEDULING, (ret >= GST_FLOW_EOS) ? GST_LEVEL_INFO : GST_LEVEL_WARNING, pad, "pullrange failed, flow: %s", gst_flow_get_name (ret)); - return ret; + goto done; } probe_stopped_unref: { @@ -4877,8 +4883,11 @@ probe_stopped_unref: if (*buffer == NULL) gst_buffer_unref (res_buf); - return ret; + goto done; } +done: + GST_TRACER_PAD_PULL_RANGE_POST (pad, NULL, ret); + return ret; } /* must be called with pad object lock */ @@ -5227,6 +5236,8 @@ gst_pad_push_event (GstPad * pad, GstEvent * event) g_return_val_if_fail (GST_IS_PAD (pad), FALSE); g_return_val_if_fail (GST_IS_EVENT (event), FALSE); + GST_TRACER_PAD_PUSH_EVENT_PRE (pad, event); + if (GST_PAD_IS_SRC (pad)) { if (G_UNLIKELY (!GST_EVENT_IS_DOWNSTREAM (event))) goto wrong_direction; @@ -5281,6 +5292,7 @@ gst_pad_push_event (GstPad * pad, GstEvent * event) } GST_OBJECT_UNLOCK (pad); + GST_TRACER_PAD_PUSH_EVENT_POST (pad, res); return res; /* ERROR handling */ @@ -5289,28 +5301,30 @@ wrong_direction: g_warning ("pad %s:%s pushing %s event in wrong direction", GST_DEBUG_PAD_NAME (pad), GST_EVENT_TYPE_NAME (event)); gst_event_unref (event); - return FALSE; + goto done; } unknown_direction: { g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad)); gst_event_unref (event); - return FALSE; + goto done; } flushed: { GST_DEBUG_OBJECT (pad, "We're flushing"); GST_OBJECT_UNLOCK (pad); gst_event_unref (event); - return FALSE; + goto done; } eos: { GST_DEBUG_OBJECT (pad, "We're EOS"); GST_OBJECT_UNLOCK (pad); - gst_event_unref (event); - return FALSE; + goto done; } +done: + GST_TRACER_PAD_PUSH_EVENT_POST (pad, FALSE); + return FALSE; } /* Check if we can call the event function with the given event */ diff --git a/gst/gsttracer.h b/gst/gsttracer.h index 56570771f8..e8ea514919 100644 --- a/gst/gsttracer.h +++ b/gst/gsttracer.h @@ -66,6 +66,14 @@ typedef enum GST_TRACER_MESSAGE_ID_PAD_PUSH_POST, GST_TRACER_MESSAGE_ID_PAD_PUSH_LIST_PRE, GST_TRACER_MESSAGE_ID_PAD_PUSH_LIST_POST, + GST_TRACER_MESSAGE_ID_PAD_PULL_RANGE_PRE, + GST_TRACER_MESSAGE_ID_PAD_PULL_RANGE_POST, + GST_TRACER_MESSAGE_ID_PAD_PUSH_EVENT_PRE, + GST_TRACER_MESSAGE_ID_PAD_PUSH_EVENT_POST, + GST_TRACER_MESSAGE_ID_ELEMENT_POST_MESSAGE_PRE, + GST_TRACER_MESSAGE_ID_ELEMENT_POST_MESSAGE_POST, + GST_TRACER_MESSAGE_ID_ELEMENT_QUERY_PRE, + GST_TRACER_MESSAGE_ID_ELEMENT_QUERY_POST, GST_TRACER_MESSAGE_ID_LAST } GstTracerMessageId; @@ -153,12 +161,84 @@ extern GList *_priv_tracers[GST_TRACER_HOOK_ID_LAST]; } \ }G_STMT_END +#define GST_TRACER_PAD_PULL_RANGE_PRE(pad, offset, size) G_STMT_START{ \ + if (GST_TRACER_IS_ENABLED(GST_TRACER_HOOK_ID_BUFFERS)) { \ + gst_tracer_dispatch (GST_TRACER_HOOK_ID_BUFFERS, \ + GST_TRACER_MESSAGE_ID_PAD_PULL_RANGE_PRE, gst_util_get_timestamp (), \ + pad, offset, size); \ + } \ +}G_STMT_END + +#define GST_TRACER_PAD_PULL_RANGE_POST(pad, buffer, res) G_STMT_START{ \ + if (GST_TRACER_IS_ENABLED(GST_TRACER_HOOK_ID_BUFFERS)) { \ + gst_tracer_dispatch (GST_TRACER_HOOK_ID_BUFFERS, \ + GST_TRACER_MESSAGE_ID_PAD_PULL_RANGE_POST, gst_util_get_timestamp (), \ + pad, buffer, res); \ + } \ +}G_STMT_END + +#define GST_TRACER_PAD_PUSH_EVENT_PRE(pad, event) G_STMT_START{ \ + if (GST_TRACER_IS_ENABLED(GST_TRACER_HOOK_ID_EVENTS)) { \ + gst_tracer_dispatch (GST_TRACER_HOOK_ID_EVENTS, \ + GST_TRACER_MESSAGE_ID_PAD_PUSH_EVENT_PRE, gst_util_get_timestamp (), \ + pad, event); \ + } \ +}G_STMT_END + +#define GST_TRACER_PAD_PUSH_EVENT_POST(pad, res) G_STMT_START{ \ + if (GST_TRACER_IS_ENABLED(GST_TRACER_HOOK_ID_EVENTS)) { \ + gst_tracer_dispatch (GST_TRACER_HOOK_ID_EVENTS, \ + GST_TRACER_MESSAGE_ID_PAD_PUSH_EVENT_POST, gst_util_get_timestamp (), \ + pad, res); \ + } \ +}G_STMT_END + +#define GST_TRACER_ELEMENT_POST_MESSAGE_PRE(element, message) G_STMT_START{ \ + if (GST_TRACER_IS_ENABLED(GST_TRACER_HOOK_ID_MESSAGES)) { \ + gst_tracer_dispatch (GST_TRACER_HOOK_ID_MESSAGES, \ + GST_TRACER_MESSAGE_ID_ELEMENT_POST_MESSAGE_PRE, gst_util_get_timestamp (), \ + element, message); \ + } \ +}G_STMT_END + +#define GST_TRACER_ELEMENT_POST_MESSAGE_POST(element, res) G_STMT_START{ \ + if (GST_TRACER_IS_ENABLED(GST_TRACER_HOOK_ID_MESSAGES)) { \ + gst_tracer_dispatch (GST_TRACER_HOOK_ID_MESSAGES, \ + GST_TRACER_MESSAGE_ID_ELEMENT_POST_MESSAGE_POST, gst_util_get_timestamp (), \ + element, res); \ + } \ +}G_STMT_END + +#define GST_TRACER_ELEMENT_QUERY_PRE(element, query) G_STMT_START{ \ + if (GST_TRACER_IS_ENABLED(GST_TRACER_HOOK_ID_QUERIES)) { \ + gst_tracer_dispatch (GST_TRACER_HOOK_ID_QUERIES, \ + GST_TRACER_MESSAGE_ID_ELEMENT_QUERY_PRE, gst_util_get_timestamp (), \ + element, query); \ + } \ +}G_STMT_END + +#define GST_TRACER_ELEMENT_QUERY_POST(element, res) G_STMT_START{ \ + if (GST_TRACER_IS_ENABLED(GST_TRACER_HOOK_ID_QUERIES)) { \ + gst_tracer_dispatch (GST_TRACER_HOOK_ID_QUERIES, \ + GST_TRACER_MESSAGE_ID_ELEMENT_QUERY_POST, gst_util_get_timestamp (), \ + element, res); \ + } \ +}G_STMT_END + #else /* !GST_DISABLE_GST_DEBUG */ #define GST_TRACER_PAD_PUSH_PRE(pad, buffer) #define GST_TRACER_PAD_PUSH_POST(pad, res) #define GST_TRACER_PAD_PUSH_LIST_PRE(pad, list) #define GST_TRACER_PAD_PUSH_LIST_POST(pad, res) +#define GST_TRACER_PAD_PULL_RANGE_PRE(pad, offset, size) +#define GST_TRACER_PAD_PULL_RANGE_POST(pad, buffer, res) +#define GST_TRACER_PAD_PUSH_EVENT_PRE(pad, event) +#define GST_TRACER_PAD_PUSH_EVENT_POST(pad, res) +#define GST_TRACER_ELEMENT_POST_MESSAGE_PRE(element, message) +#define GST_TRACER_ELEMENT_POST_MESSAGE_POST(element, res) +#define GST_TRACER_ELEMENT_QUERY_PRE(element, query) +#define GST_TRACER_ELEMENT_QUERY_POST(element, res) #endif /* GST_DISABLE_GST_DEBUG */ diff --git a/plugins/tracers/Makefile.am b/plugins/tracers/Makefile.am index 498cb7b5dd..4809c191d1 100644 --- a/plugins/tracers/Makefile.am +++ b/plugins/tracers/Makefile.am @@ -9,7 +9,7 @@ libgstcoretracers_la_SOURCES = \ libgstcoretracers_la_CFLAGS = $(GST_OBJ_CFLAGS) libgstcoretracers_la_LIBADD = \ - $(top_builddir)/libs/gst/base/libgstbase-@GST_API_VERSION@.la \ + $(top_builddir)/gst/printf/libgstprintf.la \ $(GST_OBJ_LIBS) libgstcoretracers_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstcoretracers_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS) diff --git a/plugins/tracers/gstlog.c b/plugins/tracers/gstlog.c index 2897ef4b49..1754cebcc5 100644 --- a/plugins/tracers/gstlog.c +++ b/plugins/tracers/gstlog.c @@ -25,15 +25,21 @@ #include "gstlog.h" +#include + GST_DEBUG_CATEGORY_STATIC (gst_log_debug); #define GST_CAT_DEFAULT gst_log_debug GST_DEBUG_CATEGORY_STATIC (GST_CAT_BUFFER); GST_DEBUG_CATEGORY_STATIC (GST_CAT_BUFFER_LIST); +GST_DEBUG_CATEGORY_STATIC (GST_CAT_EVENT); +GST_DEBUG_CATEGORY_STATIC (GST_CAT_MESSAGE); #define _do_init \ GST_DEBUG_CATEGORY_INIT (gst_log_debug, "log", 0, "log tracer"); \ GST_DEBUG_CATEGORY_GET (GST_CAT_BUFFER, "GST_BUFFER"); \ - GST_DEBUG_CATEGORY_GET (GST_CAT_BUFFER_LIST, "GST_BUFFER_LIST"); + GST_DEBUG_CATEGORY_GET (GST_CAT_BUFFER_LIST, "GST_BUFFER_LIST"); \ + GST_DEBUG_CATEGORY_GET (GST_CAT_EVENT, "GST_EVENT"); \ + GST_DEBUG_CATEGORY_GET (GST_CAT_MESSAGE, "GST_MESSAGE"); #define gst_log_tracer_parent_class parent_class G_DEFINE_TYPE_WITH_CODE (GstLogTracer, gst_log_tracer, GST_TYPE_TRACER, _do_init); @@ -64,8 +70,6 @@ gst_log_tracer_invoke (GstTracer * self, GstTracerHookId hid, guint64 ts = va_arg (var_args, guint64); /* TODO(ensonic): log to different categories depending on 'mid' - * GST_TRACER_HOOK_ID_EVENTS -> GST_CAT_EVENT - * GST_TRACER_HOOK_ID_MESSAGES -> GST_CAT_MESSAGE * GST_TRACER_HOOK_ID_QUERIES -> (static category) * GST_TRACER_HOOK_ID_TOPLOGY -> ? */ @@ -86,11 +90,43 @@ gst_log_tracer_invoke (GstTracer * self, GstTracerHookId hid, cat = GST_CAT_BUFFER_LIST; fmt = "pad=%" GST_PTR_FORMAT ", res=%d"; break; + case GST_TRACER_MESSAGE_ID_PAD_PULL_RANGE_PRE: + cat = GST_CAT_BUFFER; + fmt = "pad=%" GST_PTR_FORMAT ", offset=%" G_GUINT64_FORMAT ", size=%u"; + break; + case GST_TRACER_MESSAGE_ID_PAD_PULL_RANGE_POST: + cat = GST_CAT_BUFFER; + fmt = "pad=%" GST_PTR_FORMAT ", buffer=%" GST_PTR_FORMAT ", res=%d"; + break; + case GST_TRACER_MESSAGE_ID_PAD_PUSH_EVENT_PRE: + cat = GST_CAT_EVENT; + fmt = "pad=%" GST_PTR_FORMAT ", event=%" GST_PTR_FORMAT; + break; + case GST_TRACER_MESSAGE_ID_PAD_PUSH_EVENT_POST: + cat = GST_CAT_EVENT; + fmt = "pad=%" GST_PTR_FORMAT ", res=%d"; + break; + case GST_TRACER_MESSAGE_ID_ELEMENT_POST_MESSAGE_PRE: + cat = GST_CAT_MESSAGE; + fmt = "element=%" GST_PTR_FORMAT ", message=%" GST_PTR_FORMAT; + break; + case GST_TRACER_MESSAGE_ID_ELEMENT_POST_MESSAGE_POST: + cat = GST_CAT_MESSAGE; + fmt = "element=%" GST_PTR_FORMAT ", res=%d"; + break; + case GST_TRACER_MESSAGE_ID_ELEMENT_QUERY_PRE: + fmt = "element=%" GST_PTR_FORMAT ", query=%" GST_PTR_FORMAT; + break; + case GST_TRACER_MESSAGE_ID_ELEMENT_QUERY_POST: + fmt = "element=%" GST_PTR_FORMAT ", res=%d"; + break; default: break; } if (fmt) { - gchar *str = g_strdup_vprintf (fmt, var_args); + gchar *str; + + __gst_vasprintf (&str, fmt, var_args); GST_CAT_TRACE (cat, "[%d,%d] %" GST_TIME_FORMAT ", %s", hid, mid, GST_TIME_ARGS (ts), str); g_free (str); diff --git a/plugins/tracers/gststats.c b/plugins/tracers/gststats.c index 93dccc52ef..7b8ab7e6e4 100644 --- a/plugins/tracers/gststats.c +++ b/plugins/tracers/gststats.c @@ -435,6 +435,36 @@ do_element_stats (GstStatsTracer * self, GstPad * pad, GstClockTime elapsed1, #endif } +/* FIXME: this looks a bit weired, check that we really want to do this + * + * in: a normal pad + * out: the element + * + * in: a proxy pad + * out: the element that contains the peer of the proxy + * + * in: a ghost pad + * out: the bin owning the ghostpad + */ +static GstObject * +get_real_pad_parent (GstPad * pad) +{ + GstObject *parent = GST_OBJECT_PARENT (pad); + + /* if parent of pad is a ghost-pad, then pad is a proxy_pad */ + if (parent && GST_IS_GHOST_PAD (parent)) { + pad = GST_PAD_CAST (parent); + parent = GST_OBJECT_PARENT (pad); + } + /* if pad is a ghost-pad, then parent is a bin and it is the parent of a + * proxy_pad */ + while (parent && GST_IS_GHOST_PAD (pad)) { + pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad)); + parent = pad ? GST_OBJECT_PARENT (pad) : NULL; + } + return parent; +} + /* tracer class */ static void gst_stats_tracer_finalize (GObject * obj); @@ -524,6 +554,101 @@ do_push_buffer_list_post (GstStatsTracer * self, va_list var_args) do_element_stats (self, pad, stats->last_ts, ts); } +static void +do_pull_range_list_pre (GstStatsTracer * self, va_list var_args) +{ + guint64 ts = va_arg (var_args, guint64); + GstPad *pad = va_arg (var_args, GstPad *); + GstPadStats *stats = get_pad_stats (self, pad); + stats->last_ts = ts; +} + +static void +do_pull_range_list_post (GstStatsTracer * self, va_list var_args) +{ + guint64 ts = va_arg (var_args, guint64); + GstPad *pad = va_arg (var_args, GstPad *); + GstBuffer *buffer = va_arg (var_args, GstBuffer *); + GstPadStats *stats = get_pad_stats (self, pad); + guint64 last_ts = stats->last_ts; + + if (buffer != NULL) { + do_pad_stats (self, pad, stats, buffer, ts); + do_transmission_stats (self, pad, buffer, ts); + } + do_element_stats (self, pad, last_ts, ts); +} + +static void +do_push_event_pre (GstStatsTracer * self, va_list var_args) +{ + guint64 ts = va_arg (var_args, guint64); + GstPad *pad = va_arg (var_args, GstPad *); + GstObject *parent; + GstElement *elem; + + parent = get_real_pad_parent (pad); + if ((elem = GST_ELEMENT (parent))) { + GstElementStats *stats = get_element_stats (self, elem); + get_pad_stats (self, pad); + + stats->last_ts = ts; + stats->num_events++; + self->num_events++; + } +} + +static void +do_push_event_post (GstStatsTracer * self, va_list var_args) +{ +#if 0 + guint64 ts = va_arg (var_args, guint64); + GstPad *pad = va_arg (var_args, GstPad *); +#endif +} + +static void +do_post_message_pre (GstStatsTracer * self, va_list var_args) +{ + guint64 ts = va_arg (var_args, guint64); + GstElement *elem = va_arg (var_args, GstElement *); + GstElementStats *stats = get_element_stats (self, elem); + + stats->last_ts = ts; + stats->num_messages++; + self->num_messages++; +} + +static void +do_post_message_post (GstStatsTracer * self, va_list var_args) +{ +#if 0 + guint64 ts = va_arg (var_args, guint64); + GstElement *elem = va_arg (var_args, GstElement *); +#endif +} + +static void +do_query_pre (GstStatsTracer * self, va_list var_args) +{ + guint64 ts = va_arg (var_args, guint64); + GstElement *elem = va_arg (var_args, GstElement *); + GstElementStats *stats = get_element_stats (self, elem); + + stats->last_ts = ts; + stats->num_queries++; + self->num_queries++; +} + +static void +do_query_post (GstStatsTracer * self, va_list var_args) +{ +#if 0 + guint64 ts = va_arg (var_args, guint64); + GstElement *elem = va_arg (var_args, GstElement *); +#endif +} + static void gst_stats_tracer_invoke (GstTracer * obj, GstTracerHookId hid, GstTracerMessageId mid, va_list var_args) @@ -543,6 +668,30 @@ gst_stats_tracer_invoke (GstTracer * obj, GstTracerHookId hid, case GST_TRACER_MESSAGE_ID_PAD_PUSH_LIST_POST: do_push_buffer_list_post (self, var_args); break; + case GST_TRACER_MESSAGE_ID_PAD_PULL_RANGE_PRE: + do_pull_range_list_pre (self, var_args); + break; + case GST_TRACER_MESSAGE_ID_PAD_PULL_RANGE_POST: + do_pull_range_list_post (self, var_args); + break; + case GST_TRACER_MESSAGE_ID_PAD_PUSH_EVENT_PRE: + do_push_event_pre (self, var_args); + break; + case GST_TRACER_MESSAGE_ID_PAD_PUSH_EVENT_POST: + do_push_event_post (self, var_args); + break; + case GST_TRACER_MESSAGE_ID_ELEMENT_POST_MESSAGE_PRE: + do_post_message_pre (self, var_args); + break; + case GST_TRACER_MESSAGE_ID_ELEMENT_POST_MESSAGE_POST: + do_post_message_post (self, var_args); + break; + case GST_TRACER_MESSAGE_ID_ELEMENT_QUERY_PRE: + do_query_pre (self, var_args); + break; + case GST_TRACER_MESSAGE_ID_ELEMENT_QUERY_POST: + do_query_post (self, var_args); + break; default: break; }