diff options
author | Stefan Sauer <ensonic@users.sf.net> | 2016-01-21 08:12:01 +0100 |
---|---|---|
committer | Stefan Sauer <ensonic@users.sf.net> | 2016-01-22 10:07:26 +0100 |
commit | ec75b68984d5ae57722791ea97d292b862e149cd (patch) | |
tree | 6dde9b3959b08458a8d9ec6dc5f9a460aa6bcbf4 /gst/gsttracerrecord.c | |
parent | 05a96555233649eb132c366ae54ee330d267ddd9 (diff) |
tracerrecord: don't leak the spec structures
Change the gst_tracer_record_new() api to take the parameters the make the
spec structure directly. This allows us to own the top-level structure and
also collect the args so that we can take ownership of the sub-structures.
https://bugzilla.gnome.org/show_bug.cgi?id=760821
Diffstat (limited to 'gst/gsttracerrecord.c')
-rw-r--r-- | gst/gsttracerrecord.c | 129 |
1 files changed, 65 insertions, 64 deletions
diff --git a/gst/gsttracerrecord.c b/gst/gsttracerrecord.c index 54429a4298..9a99e23690 100644 --- a/gst/gsttracerrecord.c +++ b/gst/gsttracerrecord.c @@ -37,20 +37,11 @@ #include "gststructure.h" #include "gsttracerrecord.h" #include "gstvalue.h" +#include <gobject/gvaluecollector.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; @@ -77,7 +68,11 @@ build_field_template (GQuark field_id, const GValue * value, gpointer user_data) GstTracerValueFlags flags = GST_TRACER_VALUE_FLAGS_NONE; gboolean res; - g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_STRUCTURE, FALSE); + if (G_VALUE_TYPE (value) != GST_TYPE_STRUCTURE) { + GST_WARNING ("expected field of type GstStructure, but %s is %s", + g_quark_to_string (field_id), G_VALUE_TYPE_NAME (value)); + return FALSE; + } sub = gst_value_get_structure (value); gst_structure_get (sub, "type", G_TYPE_GTYPE, &type, "flags", @@ -125,7 +120,7 @@ gst_tracer_record_build_format (GstTracerRecord * self) g_string_append_c (s, ';'); self->format = g_string_free (s, FALSE); - GST_INFO ("new format string: %s", self->format); + GST_DEBUG ("new format string: %s", self->format); g_free (name); } @@ -134,41 +129,12 @@ gst_tracer_record_dispose (GObject * object) { GstTracerRecord *self = GST_TRACER_RECORD (object); - 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; + if (self->spec) { + gst_structure_free (self->spec); + self->spec = NULL; } + g_free (self->format); + self->format = NULL; } static void @@ -176,16 +142,7 @@ 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 @@ -195,17 +152,20 @@ gst_tracer_record_init (GstTracerRecord * self) /** * gst_tracer_record_new: - * @spec: the record specification + * @name: name of new record, must end on ".class". + * @firstfield: name of first field to set + * @...: additional arguments + * * 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 @name without the ".class" suffix will be used for the log records. + * There must be fields for each value that gets logged where the field name is + * the value name. The field must be a #GstStructure describing the value. The + * sub structure must contain a field called 'type' of %G_TYPE_GTYPE that + * contains the GType of the value. The resulting #GstTracerRecord will take + * ownership of the field structures. * * 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 @@ -221,9 +181,50 @@ gst_tracer_record_init (GstTracerRecord * self) * Returns: a new #GstTracerRecord */ GstTracerRecord * -gst_tracer_record_new (GstStructure * spec) +gst_tracer_record_new (const gchar * name, const gchar * firstfield, ...) { - return g_object_new (GST_TYPE_TRACER_RECORD, "spec", spec, NULL); + GstTracerRecord *self; + GstStructure *structure; + va_list varargs; + + va_start (varargs, firstfield); + structure = gst_structure_new_empty (name); + if (structure) { + gchar *err = NULL; + GType type; + GQuark id; + + while (firstfield) { + GValue val = { 0, }; + + id = g_quark_from_string (firstfield); + type = va_arg (varargs, GType); + + /* all fields passed here must be GstStructures which we take over */ + if (type != GST_TYPE_STRUCTURE) { + GST_WARNING ("expected field of type GstStructure, but %s is %s", + firstfield, g_type_name (type)); + } + + G_VALUE_COLLECT_INIT (&val, type, varargs, G_VALUE_NOCOPY_CONTENTS, &err); + if (G_UNLIKELY (err)) { + g_critical ("%s", err); + break; + } + /* see boxed_proxy_collect_value */ + val.data[1].v_uint &= ~G_VALUE_NOCOPY_CONTENTS; + gst_structure_id_take_value (structure, id, &val); + + firstfield = va_arg (varargs, gchar *); + } + } + va_end (varargs); + + self = g_object_newv (GST_TYPE_TRACER_RECORD, 0, NULL); + self->spec = structure; + gst_tracer_record_build_format (self); + + return self; } #ifndef GST_DISABLE_GST_DEBUG |