#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"
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
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;
}
/**
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;
*buffer = res_buf;
+ GST_TRACER_PAD_PULL_RANGE_POST (pad, *buffer, ret);
return ret;
/* ERROR recovery here */
"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:
{
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:
{
}
pad->ABI.abi.last_flowret = ret;
GST_OBJECT_UNLOCK (pad);
- return ret;
+ goto done;
}
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:
{
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:
{
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 */
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;
}
GST_OBJECT_UNLOCK (pad);
+ GST_TRACER_PAD_PUSH_EVENT_POST (pad, res);
return res;
/* ERROR handling */
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 */
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;
} \
}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 */
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)
#include "gstlog.h"
+#include <gst/printf/printf.h>
+
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);
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 -> ?
*/
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);
#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);
}
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)
{
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;
}