mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 06:58:56 +00:00
tracerrecord: add a log record class
We use this class to register tracer log entry metadata and build a log template. With the log template we can serialize log data very efficiently. This also simplifies the logging code, since that is now a simple varargs function that is not exposing the implementation details. Add docs for the new class and basic tests. Remove the previous log handler. Fixes #760267
This commit is contained in:
parent
7b49459f1a
commit
10b78d872b
17 changed files with 742 additions and 150 deletions
|
@ -135,6 +135,7 @@ Windows. It is released under the GNU Library General Public License
|
|||
<xi:include href="xml/gstinfo.xml" />
|
||||
<xi:include href="xml/gsttracer.xml" />
|
||||
<xi:include href="xml/gsttracerfactory.xml" />
|
||||
<xi:include href="xml/gsttracerrecord.xml" />
|
||||
|
||||
</chapter>
|
||||
|
||||
|
|
|
@ -3047,7 +3047,6 @@ gst_toc_scope_get_type
|
|||
GstTracer
|
||||
gst_tracer_register
|
||||
gst_tracing_register_hook
|
||||
gst_tracer_log_trace
|
||||
|
||||
GstTracerHookBinAddPost
|
||||
GstTracerHookBinAddPre
|
||||
|
@ -3143,6 +3142,26 @@ gst_tracer_factory_get_type
|
|||
</SECTION>
|
||||
|
||||
|
||||
<SECTION>
|
||||
<FILE>gsttracerrecord</FILE>
|
||||
<TITLE>GstTracerRecord</TITLE>
|
||||
GstTracerRecord
|
||||
gst_tracer_record_new
|
||||
gst_tracer_record_log
|
||||
<SUBSECTION Standard>
|
||||
GstTracerRecordClass
|
||||
GST_TRACER_RECORD
|
||||
GST_IS_TRACER_RECORD
|
||||
GST_TRACER_RECORD_CLASS
|
||||
GST_IS_TRACER_RECORD_CLASS
|
||||
GST_TRACER_RECORD_GET_CLASS
|
||||
GST_TRACER_RECORD_CAST
|
||||
GST_TYPE_TRACER_RECORD
|
||||
<SUBSECTION Private>
|
||||
gst_tracer_record_get_type
|
||||
</SECTION>
|
||||
|
||||
|
||||
<SECTION>
|
||||
<FILE>gsttocsetter</FILE>
|
||||
<TITLE>GstTocSetter</TITLE>
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/gsttracer.h>
|
||||
#include <gst/gsttracerrecord.h>
|
||||
|
||||
gst_bin_get_type
|
||||
gst_buffer_pool_get_type
|
||||
|
@ -31,6 +32,7 @@ gst_tag_setter_get_type
|
|||
gst_task_get_type
|
||||
gst_tracer_get_type
|
||||
gst_tracer_factory_get_type
|
||||
gst_tracer_record_get_type
|
||||
gst_type_find_factory_get_type
|
||||
gst_uri_handler_get_type
|
||||
|
||||
|
|
|
@ -117,6 +117,7 @@ libgstreamer_@GST_API_VERSION@_la_SOURCES = \
|
|||
$(GST_TRACE_SRC) \
|
||||
gsttracer.c \
|
||||
gsttracerfactory.c \
|
||||
gsttracerrecord.c \
|
||||
gsttracerutils.c \
|
||||
gsttypefind.c \
|
||||
gsttypefindfactory.c \
|
||||
|
@ -223,6 +224,7 @@ gst_headers = \
|
|||
gsttocsetter.h \
|
||||
gsttracer.h \
|
||||
gsttracerfactory.h \
|
||||
gsttracerrecord.h \
|
||||
gsttypefind.h \
|
||||
gsttypefindfactory.h \
|
||||
gsturi.h \
|
||||
|
|
|
@ -151,6 +151,11 @@ G_GNUC_INTERNAL
|
|||
gboolean priv_gst_structure_append_to_gstring (const GstStructure * structure,
|
||||
GString * s);
|
||||
G_GNUC_INTERNAL
|
||||
gboolean priv__gst_structure_append_template_to_gstring (GQuark field_id,
|
||||
const GValue *value,
|
||||
gpointer user_data);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void priv_gst_caps_features_append_to_gstring (const GstCapsFeatures * features, GString *s);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
|
|
|
@ -1877,7 +1877,7 @@ gst_structure_to_abbr (GType type)
|
|||
}
|
||||
|
||||
static GType
|
||||
gst_structure_value_get_generic_type (GValue * val)
|
||||
gst_structure_value_get_generic_type (const GValue * val)
|
||||
{
|
||||
if (G_VALUE_TYPE (val) == GST_TYPE_LIST
|
||||
|| G_VALUE_TYPE (val) == GST_TYPE_ARRAY) {
|
||||
|
@ -1941,6 +1941,50 @@ priv_gst_structure_append_to_gstring (const GstStructure * structure,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
priv__gst_structure_append_template_to_gstring (GQuark field_id,
|
||||
const GValue * value, gpointer user_data)
|
||||
{
|
||||
GType type = gst_structure_value_get_generic_type (value);
|
||||
GString *s = (GString *) user_data;
|
||||
|
||||
g_string_append_len (s, ", ", 2);
|
||||
/* FIXME: do we need to escape fieldnames? */
|
||||
g_string_append (s, g_quark_to_string (field_id));
|
||||
g_string_append_len (s, "=(", 2);
|
||||
g_string_append (s, gst_structure_to_abbr (type));
|
||||
g_string_append_c (s, ')');
|
||||
|
||||
//TODO(ensonic): table like GstStructureAbbreviation (or extend it)
|
||||
if (type == G_TYPE_INT) {
|
||||
g_string_append_len (s, "%i", 2);
|
||||
} else if (type == G_TYPE_UINT) {
|
||||
g_string_append_len (s, "%u", 2);
|
||||
} else if (type == G_TYPE_FLOAT) {
|
||||
g_string_append_len (s, "%f", 2);
|
||||
} else if (type == G_TYPE_DOUBLE) {
|
||||
g_string_append_len (s, "%lf", 3);
|
||||
} else if (type == G_TYPE_STRING) {
|
||||
g_string_append_len (s, "%s", 2);
|
||||
} else if (type == G_TYPE_BOOLEAN) {
|
||||
/* we normally store this as a string, but can parse it also from an int */
|
||||
g_string_append_len (s, "%i", 2);
|
||||
} else if (type == G_TYPE_INT64) {
|
||||
g_string_append (s, "%" G_GINT64_FORMAT);
|
||||
} else if (type == G_TYPE_UINT64) {
|
||||
g_string_append (s, "%" G_GUINT64_FORMAT);
|
||||
} else if (type == GST_TYPE_STRUCTURE) {
|
||||
g_string_append (s, "%" GST_PTR_FORMAT);
|
||||
} else if (g_type_is_a (type, G_TYPE_ENUM)) {
|
||||
g_string_append (s, "%i");
|
||||
} else {
|
||||
GST_WARNING ("unhandled type: %s", g_type_name (type));
|
||||
g_string_append (s, "%" GST_PTR_FORMAT);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_structure_to_string:
|
||||
* @structure: a #GstStructure
|
||||
|
|
|
@ -194,38 +194,3 @@ gst_tracer_register (GstPlugin * plugin, const gchar * name, GType type)
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* tracing module helpers */
|
||||
|
||||
/**
|
||||
* gst_tracer_log_trace:
|
||||
*
|
||||
* Default log hander for traces. Serialzed the trace event into the log.
|
||||
*
|
||||
* Right now this is using the gstreamer debug log with the level TRACE (7) and
|
||||
* the category "GST_TRACER".
|
||||
* <note><para>
|
||||
* Please note that this is still under discussion and subject to change.
|
||||
* </para></note>
|
||||
*/
|
||||
void
|
||||
gst_tracer_log_trace (GstStructure * s)
|
||||
{
|
||||
GST_TRACE ("%" GST_PTR_FORMAT, s);
|
||||
/* expands to:
|
||||
gst_debug_log_valist (
|
||||
GST_CAT_DEFAULT, GST_LEVEL_TRACE,
|
||||
file, func, line, object
|
||||
"%" GST_PTR_FORMAT, s);
|
||||
// does it make sense to use the {file, line, func} from the tracer hook?
|
||||
// a)
|
||||
// - we'd need to pass them in the macros to gst_tracer_dispatch()
|
||||
// - and each tracer needs to grab them from the va_list and pass them here
|
||||
// b)
|
||||
// - we create a content in dispatch, pass that to the tracer
|
||||
// - and the tracer will pass that here
|
||||
// ideally we also use *our* ts instead of the one that
|
||||
// gst_debug_log_default() will pick
|
||||
*/
|
||||
gst_structure_free (s);
|
||||
}
|
||||
|
|
|
@ -68,9 +68,6 @@ void gst_tracing_register_hook (GstTracer *tracer, const gchar *detail,
|
|||
/* tracing modules */
|
||||
gboolean gst_tracer_register (GstPlugin * plugin, const gchar * name, GType type);
|
||||
|
||||
/* tracing module helpers */
|
||||
void gst_tracer_log_trace (GstStructure * s);
|
||||
|
||||
#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTracer, gst_object_unref)
|
||||
#endif
|
||||
|
|
251
gst/gsttracerrecord.c
Normal file
251
gst/gsttracerrecord.c
Normal file
|
@ -0,0 +1,251 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2016 Stefan Sauer <ensonic@users.sf.net>
|
||||
*
|
||||
* gsttracerrecord.c: tracer log record class
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:gsttracerrecord
|
||||
* @short_description: Trace log entry class
|
||||
*
|
||||
* Tracing modules will create instances of this class to announce the data they
|
||||
* will log and create a log formatter.
|
||||
*
|
||||
* Since: 1.8
|
||||
*/
|
||||
|
||||
#define GST_USE_UNSTABLE_API
|
||||
|
||||
#include "gst_private.h"
|
||||
#include "gstinfo.h"
|
||||
#include "gststructure.h"
|
||||
#include "gsttracerrecord.h"
|
||||
#include "gstvalue.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_EXTERN (tracer_debug);
|
||||
#define GST_CAT_DEFAULT tracer_debug
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_SPEC,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *properties[PROP_LAST];
|
||||
|
||||
struct _GstTracerRecord
|
||||
{
|
||||
GstObject parent;
|
||||
|
||||
GstStructure *spec;
|
||||
gchar *format;
|
||||
};
|
||||
|
||||
struct _GstTracerRecordClass
|
||||
{
|
||||
GstObjectClass parent_class;
|
||||
};
|
||||
|
||||
#define gst_tracer_record_parent_class parent_class
|
||||
G_DEFINE_TYPE (GstTracerRecord, gst_tracer_record, GST_TYPE_OBJECT);
|
||||
|
||||
static gboolean
|
||||
build_field_template (GQuark field_id, const GValue * value, gpointer user_data)
|
||||
{
|
||||
GString *s = (GString *) user_data;
|
||||
const GstStructure *sub;
|
||||
GValue template_value = { 0, };
|
||||
GType type;
|
||||
gboolean res;
|
||||
|
||||
g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_STRUCTURE, FALSE);
|
||||
|
||||
sub = gst_value_get_structure (value);
|
||||
type = g_value_get_gtype (gst_structure_get_value (sub, "type"));
|
||||
g_value_init (&template_value, type);
|
||||
|
||||
res = priv__gst_structure_append_template_to_gstring (field_id,
|
||||
&template_value, s);
|
||||
g_value_unset (&template_value);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tracer_record_build_format (GstTracerRecord * self)
|
||||
{
|
||||
GstStructure *structure = self->spec;
|
||||
GString *s;
|
||||
gchar *name = (gchar *) g_quark_to_string (structure->name);
|
||||
gchar *p;
|
||||
|
||||
g_return_if_fail (g_str_has_suffix (name, ".class"));
|
||||
|
||||
GST_TRACE ("%" GST_PTR_FORMAT, structure);
|
||||
|
||||
/* cut off '.class' suffix */
|
||||
name = g_strdup (name);
|
||||
p = strrchr (name, '.');
|
||||
*p = '\0';
|
||||
|
||||
s = g_string_sized_new (STRUCTURE_ESTIMATED_STRING_LEN (structure));
|
||||
g_string_append (s, name);
|
||||
gst_structure_foreach (structure, build_field_template, s);
|
||||
g_string_append_c (s, ';');
|
||||
|
||||
self->format = g_string_free (s, FALSE);
|
||||
GST_INFO ("new format string: %s", self->format);
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tracer_record_dispose (GObject * object)
|
||||
{
|
||||
GstTracerRecord *self = GST_TRACER_RECORD (object);
|
||||
|
||||
gst_structure_free (self->spec);
|
||||
g_free (self->format);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tracer_record_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstTracerRecord *self = GST_TRACER_RECORD_CAST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_SPEC:
|
||||
self->spec = g_value_get_boxed (value);
|
||||
gst_tracer_record_build_format (self);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tracer_record_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstTracerRecord *self = GST_TRACER_RECORD_CAST (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_SPEC:
|
||||
// TODO(ensonic): copy?
|
||||
g_value_set_boxed (value, self->spec);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tracer_record_class_init (GstTracerRecordClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->set_property = gst_tracer_record_set_property;
|
||||
gobject_class->get_property = gst_tracer_record_get_property;
|
||||
gobject_class->dispose = gst_tracer_record_dispose;
|
||||
|
||||
properties[PROP_SPEC] =
|
||||
g_param_spec_boxed ("spec", "Spec", "Log record specification",
|
||||
GST_TYPE_STRUCTURE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tracer_record_init (GstTracerRecord * self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_tracer_record_new:
|
||||
* @spec: the record specification
|
||||
*
|
||||
* Create a new tracer record. The record instance can be used to efficiently
|
||||
* log entries using gst_tracer_record_log().
|
||||
*
|
||||
* The name of the @spec #GstStructure must end on '.class'. This name without
|
||||
* the suffix will be used for the log records. The @spec must have a field for
|
||||
* each value that gets logged where the field name is the value name. The field
|
||||
* must be a nested structure describing the value. The sub structure must
|
||||
* contain a field called 'type' of %G_TYPE_GTYPE that contains the GType of the
|
||||
* value.
|
||||
*
|
||||
* The way to deal with optional values is to log an additional boolean before
|
||||
* the optional field, that if %TRUE signals that the optional field is valid
|
||||
* and %FALSE signals that the optional field should be ignored. One must still
|
||||
* log a placeholder value for the optional field though. Please also note, that
|
||||
* pointer type values must not be NULL - the underlying serialisation can not
|
||||
* handle that right now.
|
||||
*
|
||||
* <note><para>
|
||||
* Please note that this is still under discussion and subject to change.
|
||||
* </para></note>
|
||||
*
|
||||
* Returns: a new #GstTracerRecord
|
||||
*/
|
||||
GstTracerRecord *
|
||||
gst_tracer_record_new (GstStructure * spec)
|
||||
{
|
||||
return g_object_new (GST_TYPE_TRACER_RECORD, "spec", spec, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_tracer_record_log:
|
||||
* @self: the tracer-record
|
||||
* @...: the args as described in the spec-
|
||||
*
|
||||
* Serialzes the trace event into the log.
|
||||
*
|
||||
* Right now this is using the gstreamer debug log with the level TRACE (7) and
|
||||
* the category "GST_TRACER".
|
||||
* <note><para>
|
||||
* Please note that this is still under discussion and subject to change.
|
||||
* </para></note>
|
||||
*/
|
||||
void
|
||||
gst_tracer_record_log (GstTracerRecord * self, ...)
|
||||
{
|
||||
va_list var_args;
|
||||
|
||||
/*
|
||||
* does it make sense to use the {file, line, func} from the tracer hook?
|
||||
* a)
|
||||
* - we'd need to pass them in the macros to gst_tracer_dispatch()
|
||||
* - and each tracer needs to grab them from the va_list and pass them here
|
||||
* b)
|
||||
* - we create a context in dispatch, pass that to the tracer
|
||||
* - and the tracer will pass that here
|
||||
* ideally we also use *our* ts instead of the one that
|
||||
* gst_debug_log_default() will pick
|
||||
*/
|
||||
|
||||
va_start (var_args, self);
|
||||
if (G_LIKELY (GST_LEVEL_TRACE <= _gst_debug_min)) {
|
||||
gst_debug_log_valist (GST_CAT_DEFAULT, GST_LEVEL_TRACE, "", "", 0, NULL,
|
||||
self->format, var_args);
|
||||
}
|
||||
va_end (var_args);
|
||||
}
|
57
gst/gsttracerrecord.h
Normal file
57
gst/gsttracerrecord.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2016 Stefan Sauer <ensonic@users.sf.net>
|
||||
*
|
||||
* gsttracerrecord.h: tracer log record class
|
||||
*
|
||||
* 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_RECORD_H__
|
||||
#define __GST_TRACER_RECORD_H__
|
||||
|
||||
#ifndef GST_USE_UNSTABLE_API
|
||||
#warning "The tracer subsystem is unstable API and may change in future."
|
||||
#warning "You can define GST_USE_UNSTABLE_API to avoid this warning."
|
||||
#endif
|
||||
|
||||
#include <gst/gstobject.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GstTracerRecord GstTracerRecord;
|
||||
typedef struct _GstTracerRecordPrivate GstTracerRecordPrivate;
|
||||
typedef struct _GstTracerRecordClass GstTracerRecordClass;
|
||||
|
||||
#define GST_TYPE_TRACER_RECORD (gst_tracer_record_get_type())
|
||||
#define GST_TRACER_RECORD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TRACER_RECORD,GstTracerRecord))
|
||||
#define GST_TRACER_RECORD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TRACER_RECORD,GstTracerRecordClass))
|
||||
#define GST_IS_TRACER_RECORD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TRACER_RECORD))
|
||||
#define GST_IS_TRACER_RECORD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TRACER_RECORD))
|
||||
#define GST_TRACER_RECORD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_TRACER_RECORD,GstTracerRecordClass))
|
||||
#define GST_TRACER_RECORD_CAST(obj) ((GstTracerRecord *)(obj))
|
||||
|
||||
GType gst_tracer_record_get_type (void);
|
||||
|
||||
GstTracerRecord * gst_tracer_record_new (GstStructure *spec);
|
||||
void gst_tracer_record_log (GstTracerRecord *self, ...);
|
||||
|
||||
#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTracerRecord, gst_object_unref)
|
||||
#endif
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_TRACER_RECORD_H__ */
|
|
@ -38,6 +38,7 @@
|
|||
#endif
|
||||
|
||||
#include "gstlatency.h"
|
||||
#include <gst/gsttracerrecord.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_latency_debug);
|
||||
#define GST_CAT_DEFAULT gst_latency_debug
|
||||
|
@ -52,6 +53,8 @@ static GQuark latency_probe_id;
|
|||
static GQuark latency_probe_pad;
|
||||
static GQuark latency_probe_ts;
|
||||
|
||||
static GstTracerRecord *tr_latency;
|
||||
|
||||
/* data helpers */
|
||||
|
||||
/*
|
||||
|
@ -103,11 +106,8 @@ log_latency (const GstStructure * data, GstPad * sink_pad, guint64 sink_ts)
|
|||
src = g_strdup_printf ("%s_%s", GST_DEBUG_PAD_NAME (src_pad));
|
||||
sink = g_strdup_printf ("%s_%s", GST_DEBUG_PAD_NAME (sink_pad));
|
||||
|
||||
/* TODO(ensonic): report format is still unstable */
|
||||
gst_tracer_log_trace (gst_structure_new ("latency",
|
||||
"src", G_TYPE_STRING, src,
|
||||
"sink", G_TYPE_STRING, sink,
|
||||
"time", G_TYPE_UINT64, GST_CLOCK_DIFF (src_ts, sink_ts), NULL));
|
||||
gst_tracer_record_log (tr_latency, src, sink,
|
||||
GST_CLOCK_DIFF (src_ts, sink_ts));
|
||||
g_free (src);
|
||||
g_free (sink);
|
||||
}
|
||||
|
@ -204,11 +204,13 @@ gst_latency_tracer_class_init (GstLatencyTracerClass * klass)
|
|||
|
||||
/* announce trace formats */
|
||||
/* *INDENT-OFF* */
|
||||
gst_tracer_log_trace (gst_structure_new ("latency.class",
|
||||
tr_latency = gst_tracer_record_new (gst_structure_new ("latency.class",
|
||||
"src", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_STRING,
|
||||
"related-to", G_TYPE_STRING, "pad", /* TODO: use genum */
|
||||
NULL),
|
||||
"sink", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_STRING,
|
||||
"related-to", G_TYPE_STRING, "pad", /* TODO: use genum */
|
||||
NULL),
|
||||
"time", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* SECTION:gstrusage
|
||||
* @short_description: log resource usage stats
|
||||
*
|
||||
* A tracing module that take rusage() snapshots and logs them.
|
||||
* A tracing module that take rusage() snapshots and logs them.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include <unistd.h>
|
||||
#include "gstrusage.h"
|
||||
#include <gst/gsttracerrecord.h>
|
||||
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
#ifndef __USE_GNU
|
||||
|
@ -56,6 +57,8 @@ G_DEFINE_TYPE_WITH_CODE (GstRUsageTracer, gst_rusage_tracer, GST_TYPE_TRACER,
|
|||
/* number of cpus to scale cpu-usage in threads */
|
||||
static glong num_cpus = 1;
|
||||
|
||||
static GstTracerRecord *tr_proc, *tr_thread;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* time spend in this thread */
|
||||
|
@ -236,13 +239,8 @@ do_stats (GstTracer * obj, guint64 ts)
|
|||
update_trace_value (stats->tvs_thread, ts, stats->tthread, &dts, &dtproc);
|
||||
cur_cpuload = (guint) gst_util_uint64_scale (dtproc,
|
||||
G_GINT64_CONSTANT (1000), dts);
|
||||
gst_tracer_log_trace (gst_structure_new ("thread-rusage",
|
||||
"ts", G_TYPE_UINT64, ts,
|
||||
"thread-id", G_TYPE_UINT, GPOINTER_TO_UINT (thread_id),
|
||||
"average-cpuload", G_TYPE_UINT, MIN (avg_cpuload, 1000),
|
||||
"current-cpuload", G_TYPE_UINT, MIN (cur_cpuload, 1000),
|
||||
"time", G_TYPE_UINT64, stats->tthread,
|
||||
NULL));
|
||||
gst_tracer_record_log (tr_thread, (guint64)thread_id, ts,
|
||||
MIN (avg_cpuload, 1000), MIN (cur_cpuload, 1000), stats->tthread);
|
||||
|
||||
avg_cpuload = (guint) gst_util_uint64_scale (tproc / num_cpus,
|
||||
G_GINT64_CONSTANT (1000), ts);
|
||||
|
@ -251,12 +249,8 @@ do_stats (GstTracer * obj, guint64 ts)
|
|||
G_UNLOCK (_proc);
|
||||
cur_cpuload = (guint) gst_util_uint64_scale (dtproc / num_cpus,
|
||||
G_GINT64_CONSTANT (1000), dts);
|
||||
gst_tracer_log_trace (gst_structure_new ("proc-rusage",
|
||||
"ts", G_TYPE_UINT64, ts,
|
||||
"average-cpuload", G_TYPE_UINT, MIN (avg_cpuload, 1000),
|
||||
"current-cpuload", G_TYPE_UINT, MIN (cur_cpuload, 1000),
|
||||
"time", G_TYPE_UINT64, tproc,
|
||||
NULL));
|
||||
gst_tracer_record_log (tr_proc, ts, MIN (avg_cpuload, 1000),
|
||||
MIN (cur_cpuload, 1000), tproc);
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
|
||||
|
@ -291,54 +285,64 @@ gst_rusage_tracer_class_init (GstRUsageTracerClass * klass)
|
|||
|
||||
/* announce trace formats */
|
||||
/* *INDENT-OFF* */
|
||||
gst_tracer_log_trace (gst_structure_new ("thread-rusage.class",
|
||||
tr_thread = gst_tracer_record_new (gst_structure_new ("thread-rusage.class",
|
||||
"thread-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT64,
|
||||
"related-to", G_TYPE_STRING, "thread", /* TODO: use genum */
|
||||
NULL),
|
||||
"ts", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT64,
|
||||
"description", G_TYPE_STRING, "event ts",
|
||||
NULL),
|
||||
"average-cpuload", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT,
|
||||
"description", G_TYPE_STRING, "average cpu usage per thread in ‰",
|
||||
"flags", G_TYPE_STRING, "aggregated", /* TODO: use gflags */
|
||||
"min", G_TYPE_UINT, 0,
|
||||
"flags", G_TYPE_STRING, "aggregated", /* TODO: use gflags */
|
||||
"min", G_TYPE_UINT, 0,
|
||||
"max", G_TYPE_UINT, 1000,
|
||||
NULL),
|
||||
"current-cpuload", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT,
|
||||
"description", G_TYPE_STRING, "current cpu usage per thread in ‰",
|
||||
"flags", G_TYPE_STRING, "windowed", /* TODO: use gflags */
|
||||
"min", G_TYPE_UINT, 0,
|
||||
"flags", G_TYPE_STRING, "windowed", /* TODO: use gflags */
|
||||
"min", G_TYPE_UINT, 0,
|
||||
"max", G_TYPE_UINT, 1000,
|
||||
NULL),
|
||||
"time", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT64,
|
||||
"description", G_TYPE_STRING, "time spent in thread in ns",
|
||||
"flags", G_TYPE_STRING, "aggregated", /* TODO: use gflags */
|
||||
"flags", G_TYPE_STRING, "aggregated", /* TODO: use gflags */
|
||||
"min", G_TYPE_UINT64, G_GUINT64_CONSTANT (0),
|
||||
"max", G_TYPE_UINT64, G_MAXUINT64,
|
||||
NULL),
|
||||
NULL));
|
||||
gst_tracer_log_trace (gst_structure_new ("proc-rusage.class",
|
||||
tr_proc = gst_tracer_record_new (gst_structure_new ("proc-rusage.class",
|
||||
"thread-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT64,
|
||||
"related-to", G_TYPE_STRING, "process", /* TODO: use genum */
|
||||
NULL),
|
||||
"ts", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT64,
|
||||
"description", G_TYPE_STRING, "event ts",
|
||||
NULL),
|
||||
"average-cpuload", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT,
|
||||
"description", G_TYPE_STRING, "average cpu usage per process in ‰",
|
||||
"flags", G_TYPE_STRING, "aggregated", /* TODO: use gflags */
|
||||
"min", G_TYPE_UINT, 0,
|
||||
"flags", G_TYPE_STRING, "aggregated", /* TODO: use gflags */
|
||||
"min", G_TYPE_UINT, 0,
|
||||
"max", G_TYPE_UINT, 1000,
|
||||
NULL),
|
||||
"current-cpuload", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT,
|
||||
"description", G_TYPE_STRING, "current cpu usage per process in ‰",
|
||||
"flags", G_TYPE_STRING, "windowed", /* TODO: use gflags */
|
||||
"min", G_TYPE_UINT, 0,
|
||||
"flags", G_TYPE_STRING, "windowed", /* TODO: use gflags */
|
||||
"min", G_TYPE_UINT, 0,
|
||||
"max", G_TYPE_UINT, 1000,
|
||||
NULL),
|
||||
"time", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT64,
|
||||
"description", G_TYPE_STRING, "time spent in process in ns",
|
||||
"flags", G_TYPE_STRING, "aggregated", /* TODO: use gflags */
|
||||
"flags", G_TYPE_STRING, "aggregated", /* TODO: use gflags */
|
||||
"min", G_TYPE_UINT64, G_GUINT64_CONSTANT (0),
|
||||
"max", G_TYPE_UINT64, G_MAXUINT64,
|
||||
NULL),
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#endif
|
||||
|
||||
#include "gststats.h"
|
||||
#include <gst/gsttracerrecord.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
@ -47,6 +48,14 @@ G_LOCK_DEFINE (_pad_stats);
|
|||
G_DEFINE_TYPE_WITH_CODE (GstStatsTracer, gst_stats_tracer, GST_TYPE_TRACER,
|
||||
_do_init);
|
||||
|
||||
static GstTracerRecord *tr_new_element;
|
||||
static GstTracerRecord *tr_new_pad;
|
||||
static GstTracerRecord *tr_buffer;
|
||||
static GstTracerRecord *tr_element_query;
|
||||
static GstTracerRecord *tr_event;
|
||||
static GstTracerRecord *tr_message;
|
||||
static GstTracerRecord *tr_query;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* we can't rely on the address to be unique over time */
|
||||
|
@ -87,14 +96,9 @@ static void
|
|||
log_new_element_stats (GstElementStats * stats, GstElement * element,
|
||||
GstClockTime elapsed)
|
||||
{
|
||||
gst_tracer_log_trace (gst_structure_new ("new-element",
|
||||
"thread-id", G_TYPE_UINT, GPOINTER_TO_UINT (g_thread_self ()),
|
||||
"ts", G_TYPE_UINT64, elapsed,
|
||||
"ix", G_TYPE_UINT, stats->index,
|
||||
"parent-ix", G_TYPE_UINT, stats->parent_ix,
|
||||
"name", G_TYPE_STRING, GST_OBJECT_NAME (element),
|
||||
"type", G_TYPE_STRING, G_OBJECT_TYPE_NAME (element),
|
||||
"is-bin", G_TYPE_BOOLEAN, GST_IS_BIN (element), NULL));
|
||||
gst_tracer_record_log (tr_new_element, (guint64) g_thread_self (),
|
||||
elapsed, stats->index, stats->parent_ix, GST_OBJECT_NAME (element),
|
||||
G_OBJECT_TYPE_NAME (element), GST_IS_BIN (element));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -194,15 +198,10 @@ fill_pad_stats (GstStatsTracer * self, GstPad * pad)
|
|||
static void
|
||||
log_new_pad_stats (GstPadStats * stats, GstPad * pad)
|
||||
{
|
||||
gst_tracer_log_trace (gst_structure_new ("new-pad",
|
||||
"thread-id", G_TYPE_UINT, GPOINTER_TO_UINT (g_thread_self ()),
|
||||
"ix", G_TYPE_UINT, stats->index,
|
||||
"parent-ix", G_TYPE_UINT, stats->parent_ix,
|
||||
"name", G_TYPE_STRING, GST_OBJECT_NAME (pad),
|
||||
"type", G_TYPE_STRING, G_OBJECT_TYPE_NAME (pad),
|
||||
"is-ghostpad", G_TYPE_BOOLEAN, GST_IS_GHOST_PAD (pad),
|
||||
"pad-direction", GST_TYPE_PAD_DIRECTION, GST_PAD_DIRECTION (pad),
|
||||
NULL));
|
||||
gst_tracer_record_log (tr_new_element, (guint64) g_thread_self (),
|
||||
stats->index, stats->parent_ix, GST_OBJECT_NAME (pad),
|
||||
G_OBJECT_TYPE_NAME (pad), GST_IS_GHOST_PAD (pad),
|
||||
GST_PAD_DIRECTION (pad));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -254,50 +253,27 @@ do_buffer_stats (GstStatsTracer * self, GstPad * this_pad,
|
|||
GstElement *that_elem = get_real_pad_parent (that_pad);
|
||||
GstElementStats *that_elem_stats = get_element_stats (self, that_elem);
|
||||
|
||||
/* TODO(ensonic): need a quark-table (shared with the tracer-front-ends?) */
|
||||
gst_tracer_log_trace (gst_structure_new ("buffer",
|
||||
"thread-id", G_TYPE_UINT, GPOINTER_TO_UINT (g_thread_self ()),
|
||||
"ts", G_TYPE_UINT64, elapsed,
|
||||
"pad-ix", G_TYPE_UINT, this_pad_stats->index,
|
||||
"elem-ix", G_TYPE_UINT, this_elem_stats->index,
|
||||
"peer-pad-ix", G_TYPE_UINT, that_pad_stats->index,
|
||||
"peer-elem-ix", G_TYPE_UINT, that_elem_stats->index,
|
||||
"buffer-size", G_TYPE_UINT, gst_buffer_get_size (buf),
|
||||
"buffer-pts", G_TYPE_UINT64, GST_BUFFER_PTS (buf),
|
||||
"buffer-dts", G_TYPE_UINT64, GST_BUFFER_DTS (buf),
|
||||
"buffer-duration", G_TYPE_UINT64, GST_BUFFER_DURATION (buf),
|
||||
"buffer-flags", GST_TYPE_BUFFER_FLAGS, GST_BUFFER_FLAGS (buf),
|
||||
/*
|
||||
scheduling-jitter: for this we need the last_ts on the pad
|
||||
*/
|
||||
NULL));
|
||||
gst_tracer_record_log (tr_buffer, (guint64) g_thread_self (), elapsed,
|
||||
this_pad_stats->index, this_elem_stats->index, that_pad_stats->index,
|
||||
that_elem_stats->index, gst_buffer_get_size (buf), GST_BUFFER_PTS (buf),
|
||||
GST_BUFFER_DTS (buf), GST_BUFFER_DURATION (buf), GST_BUFFER_FLAGS (buf));
|
||||
}
|
||||
|
||||
static void
|
||||
do_query_stats (GstStatsTracer * self, GstPad * this_pad,
|
||||
GstPadStats * this_pad_stats, GstPad * that_pad,
|
||||
GstPadStats * that_pad_stats, GstQuery * qry, GstClockTime elapsed,
|
||||
gboolean res, gboolean is_post)
|
||||
gboolean have_res, gboolean res)
|
||||
{
|
||||
GstElement *this_elem = get_real_pad_parent (this_pad);
|
||||
GstElementStats *this_elem_stats = get_element_stats (self, this_elem);
|
||||
GstElement *that_elem = get_real_pad_parent (that_pad);
|
||||
GstElementStats *that_elem_stats = get_element_stats (self, that_elem);
|
||||
GstStructure *s;
|
||||
|
||||
s = gst_structure_new ("query",
|
||||
"thread-id", G_TYPE_UINT, GPOINTER_TO_UINT (g_thread_self ()),
|
||||
"ts", G_TYPE_UINT64, elapsed,
|
||||
"pad-ix", G_TYPE_UINT, this_pad_stats->index,
|
||||
"elem-ix", G_TYPE_UINT, this_elem_stats->index,
|
||||
"peer-pad-ix", G_TYPE_UINT, that_pad_stats->index,
|
||||
"peer-elem-ix", G_TYPE_UINT, that_elem_stats->index,
|
||||
"name", G_TYPE_STRING, GST_QUERY_TYPE_NAME (qry),
|
||||
"structure", GST_TYPE_STRUCTURE, gst_query_get_structure (qry), NULL);
|
||||
if (is_post) {
|
||||
gst_structure_set (s, "res", G_TYPE_BOOLEAN, res, NULL);
|
||||
}
|
||||
gst_tracer_log_trace (s);
|
||||
gst_tracer_record_log (tr_query, (guint64) g_thread_self (), elapsed,
|
||||
this_pad_stats->index, this_elem_stats->index, that_pad_stats->index,
|
||||
that_elem_stats->index, GST_QUERY_TYPE_NAME (qry),
|
||||
gst_query_get_structure (qry), have_res, res);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -473,12 +449,8 @@ do_push_event_pre (GstStatsTracer * self, guint64 ts, GstPad * pad,
|
|||
GstPadStats *pad_stats = get_pad_stats (self, pad);
|
||||
|
||||
elem_stats->last_ts = ts;
|
||||
gst_tracer_log_trace (gst_structure_new ("event",
|
||||
"thread-id", G_TYPE_UINT, GPOINTER_TO_UINT (g_thread_self ()),
|
||||
"ts", G_TYPE_UINT64, ts,
|
||||
"pad-ix", G_TYPE_UINT, pad_stats->index,
|
||||
"elem-ix", G_TYPE_UINT, elem_stats->index,
|
||||
"name", G_TYPE_STRING, GST_EVENT_TYPE_NAME (ev), NULL));
|
||||
gst_tracer_record_log (tr_event, (guint64) g_thread_self (), ts,
|
||||
pad_stats->index, elem_stats->index, GST_EVENT_TYPE_NAME (ev));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -487,19 +459,11 @@ do_post_message_pre (GstStatsTracer * self, guint64 ts, GstElement * elem,
|
|||
{
|
||||
GstElementStats *stats = get_element_stats (self, elem);
|
||||
const GstStructure *msg_s = gst_message_get_structure (msg);
|
||||
GstStructure *s;
|
||||
|
||||
stats->last_ts = ts;
|
||||
|
||||
s = gst_structure_new ("message",
|
||||
"thread-id", G_TYPE_UINT, GPOINTER_TO_UINT (g_thread_self ()),
|
||||
"ts", G_TYPE_UINT64, ts,
|
||||
"elem-ix", G_TYPE_UINT, stats->index,
|
||||
"name", G_TYPE_STRING, GST_MESSAGE_TYPE_NAME (msg), NULL);
|
||||
if (msg_s) {
|
||||
gst_structure_set (s, "structure", GST_TYPE_STRUCTURE, msg_s, NULL);
|
||||
}
|
||||
gst_tracer_log_trace (s);
|
||||
gst_tracer_record_log (tr_message, (guint64) g_thread_self (), ts,
|
||||
stats->index, GST_MESSAGE_TYPE_NAME (msg),
|
||||
(msg_s ? msg_s : gst_structure_new_empty ("dummy")));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -518,11 +482,8 @@ do_element_query_pre (GstStatsTracer * self, guint64 ts, GstElement * elem,
|
|||
GstElementStats *stats = get_element_stats (self, elem);
|
||||
|
||||
stats->last_ts = ts;
|
||||
gst_tracer_log_trace (gst_structure_new ("element-query",
|
||||
"thread-id", G_TYPE_UINT, GPOINTER_TO_UINT (g_thread_self ()),
|
||||
"ts", G_TYPE_UINT64, ts,
|
||||
"elem-ix", G_TYPE_UINT, stats->index,
|
||||
"name", G_TYPE_STRING, GST_QUERY_TYPE_NAME (qry), NULL));
|
||||
gst_tracer_record_log (tr_element_query, (guint64) g_thread_self (), ts,
|
||||
stats->index, GST_QUERY_TYPE_NAME (qry));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -546,7 +507,7 @@ do_query_post (GstStatsTracer * self, guint64 ts, GstPad * this_pad,
|
|||
GstPadStats *that_pad_stats = get_pad_stats (self, that_pad);
|
||||
|
||||
do_query_stats (self, this_pad, this_pad_stats, that_pad, that_pad_stats,
|
||||
qry, ts, res, TRUE);
|
||||
qry, ts, TRUE, res);
|
||||
}
|
||||
|
||||
/* tracer class */
|
||||
|
@ -556,20 +517,29 @@ gst_stats_tracer_class_init (GstStatsTracerClass * klass)
|
|||
{
|
||||
/* announce trace formats */
|
||||
/* *INDENT-OFF* */
|
||||
gst_tracer_log_trace (gst_structure_new ("buffer.class",
|
||||
tr_buffer = gst_tracer_record_new (gst_structure_new ("buffer.class",
|
||||
"thread-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT64,
|
||||
"related-to", G_TYPE_STRING, "thread", /* TODO use genum */
|
||||
NULL),
|
||||
"ts", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT64,
|
||||
"description", G_TYPE_STRING, "event ts",
|
||||
NULL),
|
||||
"pad-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT,
|
||||
"related-to", G_TYPE_STRING, "pad", /* TODO: use genum */
|
||||
NULL),
|
||||
"element-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT,
|
||||
"related-to", G_TYPE_STRING, "element", /* TODO: use genum */
|
||||
NULL),
|
||||
"peer-pad-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT,
|
||||
"related-to", G_TYPE_STRING, "pad", /* TODO: use genum */
|
||||
NULL),
|
||||
"peer-element-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT,
|
||||
"related-to", G_TYPE_STRING, "element", /* TODO: use genum */
|
||||
NULL),
|
||||
"buffer-size", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
|
@ -595,14 +565,21 @@ gst_stats_tracer_class_init (GstStatsTracerClass * klass)
|
|||
NULL),
|
||||
/* TODO(ensonic): "buffer-flags" */
|
||||
NULL));
|
||||
gst_tracer_log_trace (gst_structure_new ("event.class",
|
||||
tr_event = gst_tracer_record_new (gst_structure_new ("event.class",
|
||||
"thread-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT64,
|
||||
"related-to", G_TYPE_STRING, "thread", /* TODO use genum */
|
||||
NULL),
|
||||
"ts", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT64,
|
||||
"description", G_TYPE_STRING, "event ts",
|
||||
NULL),
|
||||
"pad-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT,
|
||||
"related-to", G_TYPE_STRING, "pad", /* TODO: use genum */
|
||||
NULL),
|
||||
"element-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT,
|
||||
"related-to", G_TYPE_STRING, "element", /* TODO: use genum */
|
||||
NULL),
|
||||
"name", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
|
@ -611,11 +588,17 @@ gst_stats_tracer_class_init (GstStatsTracerClass * klass)
|
|||
"flags", G_TYPE_STRING, "", /* TODO: use gflags */
|
||||
NULL),
|
||||
NULL));
|
||||
gst_tracer_log_trace (gst_structure_new ("message.class",
|
||||
tr_message = gst_tracer_record_new (gst_structure_new ("message.class",
|
||||
"thread-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT64,
|
||||
"related-to", G_TYPE_STRING, "thread", /* TODO use genum */
|
||||
NULL),
|
||||
"ts", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT64,
|
||||
"description", G_TYPE_STRING, "event ts",
|
||||
NULL),
|
||||
"element-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT,
|
||||
"related-to", G_TYPE_STRING, "element", /* TODO: use genum */
|
||||
NULL),
|
||||
"name", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
|
@ -628,11 +611,18 @@ gst_stats_tracer_class_init (GstStatsTracerClass * klass)
|
|||
"description", G_TYPE_STRING, "message structure",
|
||||
NULL),
|
||||
NULL));
|
||||
gst_tracer_log_trace (gst_structure_new ("element-query.class",
|
||||
tr_element_query = gst_tracer_record_new (gst_structure_new (
|
||||
"element-query.class",
|
||||
"thread-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT64,
|
||||
"related-to", G_TYPE_STRING, "thread", /* TODO use genum */
|
||||
NULL),
|
||||
"ts", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT64,
|
||||
"description", G_TYPE_STRING, "event ts",
|
||||
NULL),
|
||||
"element-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT,
|
||||
"related-to", G_TYPE_STRING, "element", /* TODO: use genum */
|
||||
NULL),
|
||||
"name", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
|
@ -641,20 +631,29 @@ gst_stats_tracer_class_init (GstStatsTracerClass * klass)
|
|||
"flags", G_TYPE_STRING, "", /* TODO: use gflags */
|
||||
NULL),
|
||||
NULL));
|
||||
gst_tracer_log_trace (gst_structure_new ("query.class",
|
||||
tr_query = gst_tracer_record_new (gst_structure_new ("query.class",
|
||||
"thread-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT64,
|
||||
"related-to", G_TYPE_STRING, "thread", /* TODO use genum */
|
||||
NULL),
|
||||
"ts", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT64,
|
||||
"description", G_TYPE_STRING, "event ts",
|
||||
NULL),
|
||||
"pad-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT,
|
||||
"related-to", G_TYPE_STRING, "pad", /* TODO: use genum */
|
||||
NULL),
|
||||
"element-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT,
|
||||
"related-to", G_TYPE_STRING, "element", /* TODO: use genum */
|
||||
NULL),
|
||||
"peer-pad-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT,
|
||||
"related-to", G_TYPE_STRING, "pad", /* TODO: use genum */
|
||||
NULL),
|
||||
"peer-element-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT,
|
||||
"related-to", G_TYPE_STRING, "element", /* TODO: use genum */
|
||||
NULL),
|
||||
"name", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
|
@ -667,8 +666,81 @@ gst_stats_tracer_class_init (GstStatsTracerClass * klass)
|
|||
"description", G_TYPE_STRING, "query structure",
|
||||
"flags", G_TYPE_STRING, "", /* TODO: use gflags */
|
||||
NULL),
|
||||
"have-res", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_BOOLEAN,
|
||||
"description", G_TYPE_STRING, "have query result",
|
||||
NULL),
|
||||
"res", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_BOOLEAN,
|
||||
"description", G_TYPE_STRING, "query result",
|
||||
NULL),
|
||||
/* TODO(ensonic): "buffer-flags" */
|
||||
NULL));
|
||||
tr_new_element = gst_tracer_record_new (gst_structure_new (
|
||||
"new-element.class",
|
||||
"thread-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT64,
|
||||
"related-to", G_TYPE_STRING, "thread", /* TODO use genum */
|
||||
NULL),
|
||||
"ts", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT64,
|
||||
"description", G_TYPE_STRING, "event ts",
|
||||
NULL),
|
||||
"ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT,
|
||||
"related-to", G_TYPE_STRING, "element", /* TODO: use genum */
|
||||
NULL),
|
||||
"parent-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT,
|
||||
"related-to", G_TYPE_STRING, "element", /* TODO: use genum */
|
||||
NULL),
|
||||
"name", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_STRING,
|
||||
"description", G_TYPE_STRING, "name of the element",
|
||||
"flags", G_TYPE_STRING, "", /* TODO: use gflags */
|
||||
NULL),
|
||||
"type", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_STRING,
|
||||
"description", G_TYPE_STRING, "type name of the element",
|
||||
"flags", G_TYPE_STRING, "", /* TODO: use gflags */
|
||||
NULL),
|
||||
"is-bin", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_BOOLEAN,
|
||||
"description", G_TYPE_STRING, "is element a bin",
|
||||
NULL),
|
||||
NULL));
|
||||
tr_new_pad = gst_tracer_record_new (gst_structure_new ("new-pad.class",
|
||||
"thread-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT64,
|
||||
"related-to", G_TYPE_STRING, "thread", /* TODO use genum */
|
||||
NULL),
|
||||
"ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT,
|
||||
"related-to", G_TYPE_STRING, "pad", /* TODO: use genum */
|
||||
NULL),
|
||||
"parent-ix", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_UINT,
|
||||
"related-to", G_TYPE_STRING, "element", /* TODO: use genum */
|
||||
NULL),
|
||||
"name", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_STRING,
|
||||
"description", G_TYPE_STRING, "name of the pad",
|
||||
"flags", G_TYPE_STRING, "", /* TODO: use gflags */
|
||||
NULL),
|
||||
"type", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_STRING,
|
||||
"description", G_TYPE_STRING, "type name of the pad",
|
||||
"flags", G_TYPE_STRING, "", /* TODO: use gflags */
|
||||
NULL),
|
||||
"is-ghostpad", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_BOOLEAN,
|
||||
"description", G_TYPE_STRING, "is pad a ghostpad",
|
||||
NULL),
|
||||
"pad-direction", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, GST_TYPE_PAD_DIRECTION,
|
||||
"description", G_TYPE_STRING, "ipad direction",
|
||||
NULL),
|
||||
NULL));
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
|
||||
|
|
|
@ -139,6 +139,7 @@ check_PROGRAMS = \
|
|||
gst/gstclock \
|
||||
gst/gststructure \
|
||||
gst/gsttag \
|
||||
gst/gsttracerrecord \
|
||||
gst/gsttagsetter \
|
||||
gst/gsttask \
|
||||
gst/gsttoc \
|
||||
|
@ -206,6 +207,8 @@ gst_gstcpp_SOURCES = gst/gstcpp.cc
|
|||
|
||||
libs_gstlibscpp_SOURCES = libs/gstlibscpp.cc
|
||||
|
||||
gst_gsttracerrecord_CFLAGS = $(GST_OBJ_CFLAGS) $(AM_CFLAGS) -DGST_USE_UNSTABLE_API
|
||||
|
||||
gst_gstutils_LDADD = $(LDADD) $(GSL_LIBS) $(GMP_LIBS)
|
||||
|
||||
gst_gstprintf_LDADD = \
|
||||
|
|
1
tests/check/gst/.gitignore
vendored
1
tests/check/gst/.gitignore
vendored
|
@ -44,6 +44,7 @@ gsttag
|
|||
gsttagsetter
|
||||
gsttoc
|
||||
gsttocsetter
|
||||
gsttracerrecord
|
||||
gsturi
|
||||
gstutils
|
||||
gstvalue
|
||||
|
|
165
tests/check/gst/gsttracerrecord.c
Normal file
165
tests/check/gst/gsttracerrecord.c
Normal file
|
@ -0,0 +1,165 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* Unit tests for GstTracerRecord
|
||||
*
|
||||
* Copyright (C) 2016 Stefan Sauer <ensonic@users.sf.net>
|
||||
*
|
||||
* 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/check/gstcheck.h>
|
||||
#include <gst/gsttracerrecord.h>
|
||||
|
||||
static GList *messages; /* NULL */
|
||||
static gboolean save_messages; /* FALSE */
|
||||
|
||||
static void
|
||||
tracer_log_func (GstDebugCategory * category,
|
||||
GstDebugLevel level, const gchar * file, const gchar * function,
|
||||
gint line, GObject * object, GstDebugMessage * message, gpointer unused)
|
||||
{
|
||||
const gchar *dbg_msg;
|
||||
|
||||
if (!save_messages || level != GST_LEVEL_TRACE ||
|
||||
!g_str_equal (category->name, "GST_TRACER")) {
|
||||
return;
|
||||
}
|
||||
|
||||
dbg_msg = gst_debug_message_get (message);
|
||||
fail_unless (dbg_msg != NULL);
|
||||
|
||||
messages = g_list_append (messages, g_strdup (dbg_msg));
|
||||
}
|
||||
|
||||
static void
|
||||
setup (void)
|
||||
{
|
||||
gst_debug_remove_log_function (gst_debug_log_default);
|
||||
gst_debug_add_log_function (tracer_log_func, NULL, NULL);
|
||||
gst_debug_set_threshold_for_name ("GST_TRACER", GST_LEVEL_TRACE);
|
||||
messages = NULL;
|
||||
save_messages = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup (void)
|
||||
{
|
||||
save_messages = FALSE;
|
||||
gst_debug_set_threshold_for_name ("GST_TRACER", GST_LEVEL_NONE);
|
||||
gst_debug_add_log_function (gst_debug_log_default, NULL, NULL);
|
||||
gst_debug_remove_log_function (tracer_log_func);
|
||||
g_list_foreach (messages, (GFunc) g_free, NULL);
|
||||
messages = NULL;
|
||||
}
|
||||
|
||||
|
||||
GST_START_TEST (serialize_message_logging)
|
||||
{
|
||||
GstTracerRecord *tr;
|
||||
gchar *str;
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
tr = gst_tracer_record_new (gst_structure_new ("test.class",
|
||||
"string", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_STRING,
|
||||
NULL),
|
||||
NULL));
|
||||
/* *INDENT-ON* */
|
||||
|
||||
save_messages = TRUE;
|
||||
gst_tracer_record_log (tr, "test");
|
||||
save_messages = FALSE;
|
||||
|
||||
fail_unless_equals_int (g_list_length (messages), 1);
|
||||
str = (gchar *) messages->data;
|
||||
fail_unless (str != NULL);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
GST_START_TEST (serialize_static_record)
|
||||
{
|
||||
GstTracerRecord *tr;
|
||||
GstStructure *s;
|
||||
gchar *str;
|
||||
gchar *str_val;
|
||||
gint int_val;
|
||||
gboolean bool_val;
|
||||
GstPadDirection enum_val;
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
tr = gst_tracer_record_new (gst_structure_new ("test.class",
|
||||
"string", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_STRING,
|
||||
NULL),
|
||||
"int", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_INT,
|
||||
NULL),
|
||||
"bool", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, G_TYPE_BOOLEAN,
|
||||
NULL),
|
||||
"enum", GST_TYPE_STRUCTURE, gst_structure_new ("value",
|
||||
"type", G_TYPE_GTYPE, GST_TYPE_PAD_DIRECTION,
|
||||
NULL),
|
||||
NULL));
|
||||
/* *INDENT-ON* */
|
||||
|
||||
save_messages = TRUE;
|
||||
gst_tracer_record_log (tr, "test", 1, TRUE, GST_PAD_SRC);
|
||||
save_messages = FALSE;
|
||||
|
||||
str = (gchar *) messages->data;
|
||||
GST_INFO ("serialized to '%s'", str);
|
||||
|
||||
s = gst_structure_from_string (str, NULL);
|
||||
fail_unless (s != NULL);
|
||||
|
||||
fail_unless_equals_string (gst_structure_get_name (s), "test");
|
||||
|
||||
fail_unless (gst_structure_get (s,
|
||||
"string", G_TYPE_STRING, &str_val,
|
||||
"int", G_TYPE_INT, &int_val,
|
||||
"bool", G_TYPE_BOOLEAN, &bool_val,
|
||||
"enum", GST_TYPE_PAD_DIRECTION, &enum_val, NULL));
|
||||
fail_unless_equals_int (int_val, 1);
|
||||
fail_unless_equals_string (str_val, "test");
|
||||
fail_unless_equals_int (bool_val, TRUE);
|
||||
fail_unless_equals_int (enum_val, GST_PAD_SRC);
|
||||
|
||||
gst_structure_free (s);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
static Suite *
|
||||
gst_tracer_record_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("GstTracerRecord");
|
||||
TCase *tc_chain = tcase_create ("record");
|
||||
|
||||
suite_add_tcase (s, tc_chain);
|
||||
tcase_add_checked_fixture (tc_chain, setup, cleanup);
|
||||
tcase_add_test (tc_chain, serialize_message_logging);
|
||||
tcase_add_test (tc_chain, serialize_static_record);
|
||||
|
||||
/* FIXME: add more tests, e.g. enums, pointer types and optional fields */
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
GST_CHECK_MAIN (gst_tracer_record);
|
|
@ -1391,7 +1391,9 @@ EXPORTS
|
|||
gst_tracer_factory_get_list
|
||||
gst_tracer_factory_get_type
|
||||
gst_tracer_get_type
|
||||
gst_tracer_log_trace
|
||||
gst_tracer_record_get_type
|
||||
gst_tracer_record_log
|
||||
gst_tracer_record_new
|
||||
gst_tracer_register
|
||||
gst_tracing_register_hook
|
||||
gst_type_find_factory_call_function
|
||||
|
|
Loading…
Reference in a new issue