Commit 4e5d586c authored by Stefan Sauer's avatar Stefan Sauer

tracer: initial prototype for the tracing subsystem

parent 456ef2aa
......@@ -990,6 +990,7 @@ libs/gst/helpers/Makefile
libs/gst/net/Makefile
plugins/Makefile
plugins/elements/Makefile
plugins/tracers/Makefile
po/Makefile.in
tests/Makefile
tests/benchmarks/Makefile
......
......@@ -11,26 +11,57 @@ per process or none if tracing is off (not enabled via envvar or compiled out).
Certain GStreamer core function (such as gst_pad_push or gst_element_add_pad) will
call into the tracer. The tracer will dispatch into loaded tracing plugins.
Developers will be able to select a list of plugins by setting an environment
variable, such as GST_TRACE="meminfo,dbus". When then plugins are loaded, they will
add them to certain hooks. Another env var GST_TRACE_CHANNEL can be used to send
the tracing to a file or a socket (Do the same for GST_DEBUG_CHANNEL). The syntax
could be GST_XXX_CHANNEL=file:///path/to/file or GST_XXX_CHANNEL=tcp://<ip>:<port>.
variable, such as GST_TRACE="meminfo,dbus". One can also pass parameters to
plugins: GST_TRACE="log(events;buffers),stats(all)".
When then plugins are loaded, we'll add them to certain hooks according to that
they are interested in.
Another env var GST_TRACE_CHANNEL can be used to send the tracing to a file or
a socket (Do the same for GST_DEBUG_CHANNEL). The syntax could be
GST_XXX_CHANNEL=file:///path/to/file or GST_XXX_CHANNEL=tcp://<ip>:<port>.
If no channel is set, the tracing goes to stderr like the debug logging.
TODO(ensonic): we might want to have GST_{DEBUG|TRACE)_FORMAT envars as well. These
could be raw, ansi-color, binary, ...
TODO(ensonic): we might want to have GST_{DEBUG|TRACE)_FORMAT envars as well.
These could be raw, ansi-color, binary, suitable for babeltrace (see lttng), ...
Hooks
-----
e.g. gst_pad_push() will do add this line:
GST_TRACER_PUSH_BUFFER (pad, buffer)
With these we can deprecate GST_DEBUG_FILE and GST_DEBUG_NO_COLOR.
Hook api
--------
e.g. gst_pad_push() would become:
#ifndef GST_DISABLE_GST_DEBUG
static inline GstFlowReturn __gst_pad_push (GstPad * pad, GstBuffer * buffer);
#endif
GstFlowReturn
gst_pad_push (GstPad * pad, GstBuffer * buffer)
#ifndef GST_DISABLE_GST_DEBUG
{
if (__tracer_enabled && __tracer_hook_is_used)
gst_tracer_push_buffer_pre (pad, buffer);
GstFlowReturn res = __gst_pad_push (GstPad * pad, GstBuffer * buffer);
if (__tracer_enabled && __tracer_hook_is_used)
gst_tracer_push_buffer_post (pad, res);
return res;
}
static inline GstFlowReturn
__gst_pad_push (GstPad * pad, GstBuffer * buffer)
#endif
{
g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
If tracing is disable at compile time the macro will evaluate to nothing. Otherwise
it will become something along the lines of:
if (__tracer && __tracer_hook_is_used) {
gst_tracer_push_buffer (pad, buffer);
return gst_pad_push_data (pad,
GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_PUSH, buffer);
}
TODO(ensonic): gcc has some magic for wrapping functions
- http://gcc.gnu.org/onlinedocs/gcc/Constructing-Calls.html
- http://www.clifford.at/cfun/gccfeat/#gccfeat05.c
TODO(ensonic): we should eval if we can use something like jump_label in the kernel
- http://lwn.net/Articles/412072/ + http://lwn.net/Articles/435215/
- http://lxr.free-electrons.com/source/kernel/jump_label.c
......@@ -41,18 +72,49 @@ TODO(ensonic): liblttng-ust provides such a mechanism for user-space
- it is linux specific :/
In addition to api hooks we should also provide timer hooks. Interval timers are
useful to get e.g. resource usage snapshots. Also absolute timers might make sense.
Plugins can attach handlers to one or more hooks. When a hook such as
gst_tracer_push_buffer () is called it will take a timestamp and call all attached
handlers. Hooks will be called from misc threads. The trace plugins should only
consume (=read) the provided data. Most trace plugins will log data to a trace
channel.
useful to get e.g. resource usage snapshots. Also absolute timers might make
sense. All this could be implemented with a clock thread.
TODO(ensonic): use GSignal for the hooks?
Plugins
=======
Hooks
-----
gst_bin_add
gst_bin_remove
gst_element_add_pad
gst_element_post_message
gst_element_query
gst_element_remove_pad
gst_pad_link
gst_pad_pull_range
gst_pad_push
gst_pad_push_list
gst_pad_push_event
gst_pad_unlink
Plugin api
----------
TracerPlugins are plugin features. They have a simple api:
GstTracerHookMask init(gchar *params);
Plugins can attach handlers to one or more hooks. They use a HookMask to tell
which events they are interested in. The params are the extra detail from the
environment var.
void invoke(GstStructure *s);
Hooks marshall the parameters given to a trace hook into a GstStructure and also
add some extra into such as a timestamp. The hooks will receive this structure.
Hooks will be called from misc threads. The trace plugins should only consume
(=read) the provided data. Most trace plugins will log data to a trace channel.
void done(void);
Plugins can output results and release data. This would ideally be done at the
end of the applications, but gst_deinit() is not mandatory. gst_tracelib was
using a gcc_destructor
Plugins ideas
=============
We can have some under gstreamer/plugins/tracers/
meminfo
-------
......@@ -68,17 +130,19 @@ dbus
----
- provide a dbus iface to announce applications that are traced
- tracing UIs can use the dbus iface to find the channels where logging and tracing
is getting logged to, one would start the tracing UI first and when the
application is started with tracing activated, the dbus plugin will announce the
new application, upon which the tracing UI can start reading from the log channels
is getting logged to
- one would start the tracing UI first and when the application is started with
tracing activated, the dbus plugin will announce the new application,
upon which the tracing UI can start reading from the log channels, this avoid
missing some data
topology
--------
- register to pipeline topology hooks
- tracing UIs can show a live pipeline graph
communication
-------------
stats
-----
- register to buffer, event, message and query flow
- tracing apps can do e.g. statistics
......@@ -92,14 +156,21 @@ Alternatively it would show a dialog that shows all local apps (if the dbus plug
is loaded) and read the log streams from the sockets/files that are configured for
the app.
gst-trace-stats
---------------
Such a tool could read a trace and summarize the content like gst-tracelib did for
stats in 0.10.
gst-tracer
----------
Counterpart of gst-tracelib-ui
Problems / Open items
=====================
- when hooking into a timer, should we just have some predefined intervals?
- how to trigger the shutdown processing?
- when connecting to a running app, we cant easily get the 'current' state if logging
is using a socket, as past events are not stored
Try it
======
GST_DEBUG="GST_REG*:4,GST_TRACER:4,log:7" GST_TRACE=log gst-launch-1.0 fakesrc num-buffers=10 ! fakesink
- traces for buffer flow in TRACE level and default category
......@@ -115,6 +115,8 @@ libgstreamer_@GST_API_VERSION@_la_SOURCES = \
gsttoc.c \
gsttocsetter.c \
$(GST_TRACE_SRC) \
gsttracer.c \
gsttracerfactory.c \
gsttypefind.c \
gsttypefindfactory.c \
gsturi.c \
......@@ -218,6 +220,8 @@ gst_headers = \
gsttaskpool.h \
gsttoc.h \
gsttocsetter.h \
gsttracer.h \
gsttracerfactory.h \
gsttypefind.h \
gsttypefindfactory.h \
gsturi.h \
......
......@@ -587,6 +587,7 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
g_type_class_ref (gst_pad_get_type ());
g_type_class_ref (gst_element_factory_get_type ());
g_type_class_ref (gst_element_get_type ());
g_type_class_ref (gst_tracer_factory_get_type ());
g_type_class_ref (gst_type_find_factory_get_type ());
g_type_class_ref (gst_bin_get_type ());
g_type_class_ref (gst_bus_get_type ());
......@@ -718,6 +719,10 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
GST_INFO ("initialized GStreamer successfully");
#ifndef GST_DISABLE_GST_DEBUG
_priv_gst_tracer_init ();
#endif
return TRUE;
}
......@@ -951,6 +956,9 @@ gst_deinit (void)
GST_DEBUG ("already deinitialized");
return;
}
#ifndef GST_DISABLE_GST_DEBUG
_priv_gst_tracer_deinit ();
#endif
g_thread_pool_set_max_unused_threads (0);
bin_class = GST_BIN_CLASS (g_type_class_peek (gst_bin_get_type ()));
......@@ -984,6 +992,7 @@ gst_deinit (void)
g_type_class_unref (g_type_class_peek (gst_pad_get_type ()));
g_type_class_unref (g_type_class_peek (gst_element_factory_get_type ()));
g_type_class_unref (g_type_class_peek (gst_element_get_type ()));
g_type_class_unref (g_type_class_peek (gst_tracer_factory_get_type ()));
g_type_class_unref (g_type_class_peek (gst_type_find_factory_get_type ()));
g_type_class_unref (g_type_class_peek (gst_bin_get_type ()));
g_type_class_unref (g_type_class_peek (gst_bus_get_type ()));
......
......@@ -77,6 +77,8 @@
#include <gst/gsttaskpool.h>
#include <gst/gsttoc.h>
#include <gst/gsttocsetter.h>
#include <gst/gsttracer.h>
#include <gst/gsttracerfactory.h>
#include <gst/gsttypefind.h>
#include <gst/gsttypefindfactory.h>
#include <gst/gsturi.h>
......
......@@ -393,6 +393,27 @@ struct _GstTypeFindFactoryClass {
gpointer _gst_reserved[GST_PADDING];
};
struct _GstTracerFactory {
GstPluginFeature feature;
/* <private> */
GType type;
/*
gpointer user_data;
GDestroyNotify user_data_notify;
*/
gpointer _gst_reserved[GST_PADDING];
};
struct _GstTracerFactoryClass {
GstPluginFeatureClass parent;
/* <private> */
gpointer _gst_reserved[GST_PADDING];
};
struct _GstElementFactory {
GstPluginFeature parent;
......
......@@ -94,6 +94,7 @@
#include "gstutils.h"
#include "gstinfo.h"
#include "gsterror.h"
#include "gsttracer.h"
#include "gstvalue.h"
#include "glib-compat-private.h"
......@@ -4442,8 +4443,28 @@ not_linked:
*
* MT safe.
*/
#ifndef GST_DISABLE_GST_DEBUG
static inline GstFlowReturn __gst_pad_push (GstPad * pad, GstBuffer * buffer);
#endif
GstFlowReturn
gst_pad_push (GstPad * pad, GstBuffer * buffer)
#ifndef GST_DISABLE_GST_DEBUG
{
const gboolean trace = gst_tracer_is_enabled (GST_TRACER_HOOK_ID_BUFFERS);
GstFlowReturn res;
if (trace)
gst_tracer_push_buffer_pre (pad, buffer);
res = __gst_pad_push (pad, buffer);
if (trace)
gst_tracer_push_buffer_post (pad, res);
return res;
}
static inline GstFlowReturn
__gst_pad_push (GstPad * pad, GstBuffer * buffer)
#endif
{
g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
......
......@@ -55,7 +55,7 @@ G_BEGIN_DECLS
* This _must_ be updated whenever the registry format changes,
* we currently use the core version where this change happened.
*/
#define GST_MAGIC_BINARY_VERSION_STR "1.0.0"
#define GST_MAGIC_BINARY_VERSION_STR "1.3.0"
/*
* GST_MAGIC_BINARY_VERSION_LEN:
......
......@@ -31,6 +31,8 @@
#include <gst/gst_private.h>
#include <gst/gstconfig.h>
#include <gst/gstelement.h>
#include <gst/gsttracer.h>
#include <gst/gsttracerfactory.h>
#include <gst/gsttypefind.h>
#include <gst/gsttypefindfactory.h>
#include <gst/gstdeviceproviderfactory.h>
......@@ -350,6 +352,13 @@ gst_registry_chunks_save_feature (GList ** list, GstPluginFeature * feature)
/* pack element metadata strings */
gst_registry_chunks_save_string (list,
gst_structure_to_string (factory->metadata));
} else if (GST_IS_TRACER_FACTORY (feature)) {
/* Initialize with zeroes because of struct padding and
* valgrind complaining about copying unitialized memory
*/
pf = g_slice_new0 (GstRegistryChunkPluginFeature);
pf_size = sizeof (GstRegistryChunkPluginFeature);
chk = gst_registry_chunks_make_data (pf, pf_size);
} else {
GST_WARNING_OBJECT (feature, "unhandled feature type '%s'", type_name);
}
......@@ -677,6 +686,7 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
GST_DEBUG
("Reading/casting for GstRegistryChunkPluginFeature at address %p",
*in);
unpack_element (*in, dmf, GstRegistryChunkDeviceProviderFactory, end, fail);
pf = (GstRegistryChunkPluginFeature *) dmf;
......@@ -692,6 +702,12 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
goto fail;
}
}
} else if (GST_IS_TRACER_FACTORY (feature)) {
align (*in);
GST_DEBUG
("Reading/casting for GstRegistryChunkPluginFeature at address %p",
*in);
unpack_element (*in, pf, GstRegistryChunkPluginFeature, end, fail);
} else {
GST_WARNING ("unhandled factory type : %s", G_OBJECT_TYPE_NAME (feature));
goto fail;
......
/* GStreamer
* Copyright (C) 2013 Stefan Sauer <ensonic@users.sf.net>
*
* gsttracer.h: tracing subsystem
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "gst_private.h"
#include "gstenumtypes.h"
#include "gstregistry.h"
#include "gsttracer.h"
#include "gsttracerfactory.h"
#include "gstutils.h"
#ifndef GST_DISABLE_GST_DEBUG
GST_DEBUG_CATEGORY_EXTERN (tracer_debug);
#define GST_CAT_DEFAULT tracer_debug
/* tracing plugins base class */
enum
{
PROP_0,
PROP_PARAMS,
PROP_MASK,
PROP_LAST
};
static GParamSpec *properties[PROP_LAST];
static void gst_tracer_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_tracer_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
struct _GstTracerPrivate
{
const gchar *params;
GstTracerHook mask;
};
#define gst_tracer_parent_class parent_class
G_DEFINE_ABSTRACT_TYPE (GstTracer, gst_tracer, GST_TYPE_OBJECT);
static void
gst_tracer_class_init (GstTracerClass * klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = gst_tracer_set_property;
gobject_class->get_property = gst_tracer_get_property;
properties[PROP_PARAMS] =
g_param_spec_string ("params", "Params", "Extra configuration parameters",
NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
properties[PROP_MASK] =
g_param_spec_flags ("mask", "Mask", "Event mask", GST_TYPE_TRACER_HOOK,
GST_TRACER_HOOK_NONE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, PROP_LAST, properties);
g_type_class_add_private (klass, sizeof (GstTracerPrivate));
}
static void
gst_tracer_init (GstTracer * tracer)
{
tracer->priv = G_TYPE_INSTANCE_GET_PRIVATE (tracer, GST_TYPE_TRACER,
GstTracerPrivate);
}
static void
gst_tracer_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstTracer *self = GST_TRACER_CAST (object);
switch (prop_id) {
case PROP_PARAMS:
self->priv->params = g_value_get_string (value);
break;
case PROP_MASK:
self->priv->mask = g_value_get_flags (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_tracer_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstTracer *self = GST_TRACER_CAST (object);
switch (prop_id) {
case PROP_PARAMS:
g_value_set_string (value, self->priv->params);
break;
case PROP_MASK:
g_value_set_flags (value, self->priv->mask);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_tracer_invoke (GstTracer * self, GstStructure * s)
{
GstTracerClass *klass = GST_TRACER_GET_CLASS (self);
g_return_if_fail (klass->invoke);
klass->invoke (s);
}
/* tracing modules */
gboolean
gst_tracer_register (GstPlugin * plugin, const gchar * name, GType type)
{
GstPluginFeature *existing_feature;
GstRegistry *registry;
GstTracerFactory *factory;
g_return_val_if_fail (name != NULL, FALSE);
g_return_val_if_fail (g_type_is_a (type, GST_TYPE_TRACER), FALSE);
registry = gst_registry_get ();
/* check if feature already exists, if it exists there is no need to update it
* when the registry is getting updated, outdated plugins and all their
* features are removed and readded.
*/
existing_feature = gst_registry_lookup_feature (registry, name);
if (existing_feature) {
GST_DEBUG_OBJECT (registry, "update existing feature %p (%s)",
existing_feature, name);
factory = GST_TRACER_FACTORY_CAST (existing_feature);
factory->type = type;
existing_feature->loaded = TRUE;
//g_type_set_qdata (type, __gst_elementclass_factory, factory);
gst_object_unref (existing_feature);
return TRUE;
}
factory = g_object_newv (GST_TYPE_TRACER_FACTORY, 0, NULL);
GST_DEBUG_OBJECT (factory, "new tracer factory for %s", name);
gst_plugin_feature_set_name (GST_PLUGIN_FEATURE_CAST (factory), name);
gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE_CAST (factory),
GST_RANK_NONE);
factory->type = type;
GST_DEBUG_OBJECT (factory, "tracer factory for %u:%s",
(guint) type, g_type_name (type));
if (plugin && plugin->desc.name) {
GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = plugin->desc.name; /* interned string */
GST_PLUGIN_FEATURE_CAST (factory)->plugin = plugin;
g_object_add_weak_pointer ((GObject *) plugin,
(gpointer *) & GST_PLUGIN_FEATURE_CAST (factory)->plugin);
} else {
GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = "NULL";
GST_PLUGIN_FEATURE_CAST (factory)->plugin = NULL;
}
GST_PLUGIN_FEATURE_CAST (factory)->loaded = TRUE;
gst_registry_add_feature (gst_registry_get (),
GST_PLUGIN_FEATURE_CAST (factory));
return TRUE;
}
/* tracing helpers */
static gboolean tracer_enabled = FALSE;
static GList *tracers[GST_TRACER_HOOK_ID_LAST] = { NULL, };
/* Initialize the debugging system */
void
_priv_gst_tracer_init (void)
{
const gchar *env = g_getenv ("GST_TRACE");
if (env != NULL && *env != '\0') {
GstRegistry *registry = gst_registry_get ();
GstPluginFeature *feature;
GstTracerFactory *factory;
GstTracerHook mask;
GstTracer *tracer;
gchar **t = g_strsplit_set (env, ",", 0);
gint i = 0, j;
gchar *params;
GST_INFO ("enabling tracers: '%s'", env);
while (t[i]) {
// TODO(ensonic): check t[i] for params
params = NULL;
GST_INFO ("checking tracer: '%s'", t[i]);
if ((feature = gst_registry_lookup_feature (registry, t[i]))) {
factory = GST_TRACER_FACTORY (gst_plugin_feature_load (feature));
if (factory) {
GST_INFO_OBJECT (factory, "creating tracer: type-id=%u",
(guint) factory->type);
tracer = g_object_new (factory->type, "params", params, NULL);
g_object_get (tracer, "mask", &mask, NULL);
if (mask) {
/* add to lists according to mask */
j = 0;
while (mask && (j < GST_TRACER_HOOK_ID_LAST)) {
if (mask & 1) {
tracers[j] = g_list_prepend (tracers[j],
gst_object_ref (tracer));
GST_WARNING_OBJECT (tracer, "added tracer to hook %d", j);
}
mask >>= 1;
j++;
}
tracer_enabled = TRUE;
} else {
GST_WARNING_OBJECT (tracer,
"tracer with zero mask won't have any effect");
}
gst_object_unref (tracer);
} else {
GST_WARNING_OBJECT (feature,
"loading plugin containing feature %s failed!", t[i]);
}
} else {
GST_WARNING ("no tracer named '%s'", t[i]);
}
i++;
}
g_strfreev (t);
}
}
void
_priv_gst_tracer_deinit (void)
{
gint i;
GList *node;
/* shutdown tracers for final reports */
for (i = 0; i < GST_TRACER_HOOK_ID_LAST; i++) {
for (node = tracers[i]; node; node = g_list_next (node)) {
gst_object_unref (node->data);
}
g_list_free (tracers[i]);
tracers[i] = NULL;
}
}
gboolean
gst_tracer_is_enabled (GstTracerHookId id)
{
return tracer_enabled && (tracers[id] != NULL);
}
static void
dispatch (GstTracerHookId id, GstStructure * s)
{
GList *node;
for (node = tracers[id]; node; node = g_list_next (node)) {
gst_tracer_invoke (node->data, s);
}
}
/* tracing hooks */
void
gst_tracer_push_buffer_pre (GstPad * pad, GstBuffer * buffer)
{
// TODO(ensonic): gst_structure_new_id
dispatch (GST_TRACER_HOOK_ID_BUFFERS, gst_structure_new ("push_buffer::pre",
".ts", G_TYPE_UINT64, gst_util_get_timestamp (),
"pad", GST_TYPE_PAD, pad, "buffer", GST_TYPE_BUFFER, buffer, NULL));
}
void
gst_tracer_push_buffer_post (GstPad * pad, GstFlowReturn res)
{
// TODO(ensonic): gst_structure_new_id
dispatch (GST_TRACER_HOOK_ID_BUFFERS, gst_structure_new ("push_buffer::post",
".ts", G_TYPE_UINT64, gst_util_get_timestamp (),
"pad", GST_TYPE_PAD, pad, "return", G_TYPE_INT, res, NULL));
}
#endif /* GST_DISABLE_GST_DEBUG */
/* GStreamer
* Copyright (C) 2013 Stefan Sauer <ensonic@users.sf.net>
*
* gsttracer.h: tracing subsystem
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_TRACER_H__
#define __GST_TRACER_H__
#include <glib.h>
#include <glib-object.h>
#include <gst/gstconfig.h>
#include <gst/gstbin.h>
G_BEGIN_DECLS
#ifndef GST_DISABLE_GST_DEBUG
/* hook flags and ids */
typedef enum
{
GST_TRACER_HOOK_NONE = 0,
GST_TRACER_HOOK_BUFFERS = (1 << 0),
GST_TRACER_HOOK_EVENTS = (1 << 1),
GST_TRACER_HOOK_MESSAGES = (1 << 2),
GST_TRACER_HOOK_QUERIES = (1 << 3),
GST_TRACER_HOOK_TOPOLOGY = (1 << 4),
/*
GST_TRACER_HOOK_TIMER
*/
GST_TRACER_HOOK_ALL = (1 << 5) - 1
} GstTracerHook;
typedef enum
{
GST_TRACER_HOOK_ID_BUFFERS = 0,
GST_TRACER_HOOK_ID_EVENTS,
GST_TRACER_HOOK_ID_MESSAGES,
GST_TRACER_HOOK_ID_QUERIES,
GST_TRACER_HOOK_ID_TOPLOGY,
/*
GST_TRACER_HOOK_ID_TIMER
*/
GST_TRACER_HOOK_ID_LAST
} GstTracerHookId;
/* tracing plugins */
typedef struct _GstTracer GstTracer;
typedef struct _GstTracerPrivate GstTracerPrivate;
typedef struct _GstTracerClass GstTracerClass;
#define GST_TYPE_TRACER (gst_tracer_get_type())
#define GST_TRACER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TRACER,GstTracer))
#define GST_TRACER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TRACER,GstTracerClass))
#define GST_IS_TRACER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TRACER))
#define GST_IS_TRACER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TRACER))
#define GST_TRACER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_TRACER,GstTracerClass))