From: Stefan Sauer Date: Tue, 12 Jan 2016 13:59:04 +0000 (+0100) Subject: tracerrecord: add a log record class X-Git-Tag: 1.10.4~491 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=10b78d872b5a0050c8a4572267879b0adbb578f8;p=platform%2Fupstream%2Fgstreamer.git 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 --- diff --git a/docs/gst/gstreamer-docs.sgml b/docs/gst/gstreamer-docs.sgml index cf476cd..dfa293b 100644 --- a/docs/gst/gstreamer-docs.sgml +++ b/docs/gst/gstreamer-docs.sgml @@ -135,6 +135,7 @@ Windows. It is released under the GNU Library General Public License + diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index b15d037..8c04414 100644 --- a/docs/gst/gstreamer-sections.txt +++ b/docs/gst/gstreamer-sections.txt @@ -3047,7 +3047,6 @@ gst_toc_scope_get_type GstTracer gst_tracer_register gst_tracing_register_hook -gst_tracer_log_trace GstTracerHookBinAddPost GstTracerHookBinAddPre @@ -3144,6 +3143,26 @@ gst_tracer_factory_get_type
+gsttracerrecord +GstTracerRecord +GstTracerRecord +gst_tracer_record_new +gst_tracer_record_log + +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 + +gst_tracer_record_get_type +
+ + +
gsttocsetter GstTocSetter GstTocSetter diff --git a/docs/gst/gstreamer.types.in b/docs/gst/gstreamer.types.in index d917301..8522c1e 100644 --- a/docs/gst/gstreamer.types.in +++ b/docs/gst/gstreamer.types.in @@ -8,6 +8,7 @@ #include #include +#include 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 diff --git a/gst/Makefile.am b/gst/Makefile.am index fa1ea7b..224544c 100644 --- a/gst/Makefile.am +++ b/gst/Makefile.am @@ -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 \ diff --git a/gst/gst_private.h b/gst/gst_private.h index c8cdda9..ac0b1b5 100644 --- a/gst/gst_private.h +++ b/gst/gst_private.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 diff --git a/gst/gststructure.c b/gst/gststructure.c index 2f8fc95..08a82fc 100644 --- a/gst/gststructure.c +++ b/gst/gststructure.c @@ -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 diff --git a/gst/gsttracer.c b/gst/gsttracer.c index 8cb9357..e5645dc 100644 --- a/gst/gsttracer.c +++ b/gst/gsttracer.c @@ -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". - * - * Please note that this is still under discussion and subject to change. - * - */ -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); -} diff --git a/gst/gsttracer.h b/gst/gsttracer.h index 059433b..cdf1461 100644 --- a/gst/gsttracer.h +++ b/gst/gsttracer.h @@ -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 diff --git a/gst/gsttracerrecord.c b/gst/gsttracerrecord.c new file mode 100644 index 0000000..060aead --- /dev/null +++ b/gst/gsttracerrecord.c @@ -0,0 +1,251 @@ +/* GStreamer + * Copyright (C) 2016 Stefan Sauer + * + * 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. + * + * + * Please note that this is still under discussion and subject to change. + * + * + * 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". + * + * Please note that this is still under discussion and subject to change. + * + */ +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); +} diff --git a/gst/gsttracerrecord.h b/gst/gsttracerrecord.h new file mode 100644 index 0000000..c69f6e8 --- /dev/null +++ b/gst/gsttracerrecord.h @@ -0,0 +1,57 @@ +/* GStreamer + * Copyright (C) 2016 Stefan Sauer + * + * 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 + +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__ */ diff --git a/plugins/tracers/gstlatency.c b/plugins/tracers/gstlatency.c index 1edd1a5..93d93eb 100644 --- a/plugins/tracers/gstlatency.c +++ b/plugins/tracers/gstlatency.c @@ -38,6 +38,7 @@ #endif #include "gstlatency.h" +#include 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", diff --git a/plugins/tracers/gstrusage.c b/plugins/tracers/gstrusage.c index 3db1011..c455dab 100644 --- a/plugins/tracers/gstrusage.c +++ b/plugins/tracers/gstrusage.c @@ -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 #include "gstrusage.h" +#include #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), diff --git a/plugins/tracers/gststats.c b/plugins/tracers/gststats.c index 1c93123..87c1927 100644 --- a/plugins/tracers/gststats.c +++ b/plugins/tracers/gststats.c @@ -30,6 +30,7 @@ #endif #include "gststats.h" +#include #include @@ -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* */ } diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 07ad657..560b5b1 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -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 = \ diff --git a/tests/check/gst/.gitignore b/tests/check/gst/.gitignore index fcea84e..623abee 100644 --- a/tests/check/gst/.gitignore +++ b/tests/check/gst/.gitignore @@ -44,6 +44,7 @@ gsttag gsttagsetter gsttoc gsttocsetter +gsttracerrecord gsturi gstutils gstvalue diff --git a/tests/check/gst/gsttracerrecord.c b/tests/check/gst/gsttracerrecord.c new file mode 100644 index 0000000..f786fd9 --- /dev/null +++ b/tests/check/gst/gsttracerrecord.c @@ -0,0 +1,165 @@ +/* GStreamer + * + * Unit tests for GstTracerRecord + * + * Copyright (C) 2016 Stefan Sauer + * + * 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 +#include + +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); diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index 7179df5..860306d 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -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