<type name="gpointer" c:type="gpointer"/>
</array>
</field>
+ <method name="set_use_structure_params" c:identifier="gst_tracer_class_set_use_structure_params" version="1.26">
+ <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gsttracer.c">Sets whether the tracer should use structure parameters for configuration.
+This function configures how parameters should be passed when instantiating
+the tracer.
+
+This is typically called in the tracer's class initialization function to
+indicate its parameter handling preference.</doc>
+ <source-position filename="../subprojects/gstreamer/gst/gsttracer.h"/>
+ <return-value transfer-ownership="none">
+ <type name="none" c:type="void"/>
+ </return-value>
+ <parameters>
+ <instance-parameter name="tracer_class" transfer-ownership="none">
+ <type name="TracerClass" c:type="GstTracerClass*"/>
+ </instance-parameter>
+ <parameter name="use_structure_params" transfer-ownership="none">
+ <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gsttracer.c">%TRUE to use structure parameters, %FALSE otherwise</doc>
+ <type name="gboolean" c:type="gboolean"/>
+ </parameter>
+ </parameters>
+ </method>
+ <method name="uses_structure_params" c:identifier="gst_tracer_class_uses_structure_params" version="1.26">
+ <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gsttracer.c">If set, the tracer subsystem will consider parameters passed to the
+`GST_TRACERS` environment variable as a #GstStructure and use its
+fields as properties to instanciate the tracer.</doc>
+ <source-position filename="../subprojects/gstreamer/gst/gsttracer.h"/>
+ <return-value transfer-ownership="none">
+ <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gsttracer.c">%TRUE if the tracer uses structure parameters, %FALSE otherwise</doc>
+ <type name="gboolean" c:type="gboolean"/>
+ </return-value>
+ <parameters>
+ <instance-parameter name="tracer_class" transfer-ownership="none">
+ <type name="TracerClass" c:type="GstTracerClass*"/>
+ </instance-parameter>
+ </parameters>
+ </method>
</record>
<class name="TracerFactory" c:symbol-prefix="tracer_factory" c:type="GstTracerFactory" version="1.8" parent="PluginFeature" glib:type-name="GstTracerFactory" glib:get-type="gst_tracer_factory_get_type" glib:type-struct="TracerFactoryClass">
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gsttracerfactory.c">Use gst_tracer_factory_get_list() to get a list of tracer factories known to
static GParamSpec *properties[PROP_LAST];
+typedef struct
+{
+ gboolean use_structure_params;
+} GstTracerClassPrivate;
+
static void gst_tracer_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_tracer_get_property (GObject * object, guint prop_id,
gchar *params;
};
+#define _do_init \
+ g_type_add_class_private (g_define_type_id, \
+ sizeof (GstTracerClassPrivate));
+
#define gst_tracer_parent_class parent_class
-G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GstTracer, gst_tracer, GST_TYPE_OBJECT);
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstTracer, gst_tracer, GST_TYPE_OBJECT,
+ G_ADD_PRIVATE (GstTracer) _do_init);
static void
gst_tracer_dispose (GObject * object)
return TRUE;
}
+
+/**
+ * gst_tracer_class_uses_structure_params:
+ * @klass: the #GstTracerClass to to check
+ *
+ * If set, the tracer subsystem will consider parameters passed to the
+ * `GST_TRACERS` environment variable as a #GstStructure and use its
+ * fields as properties to instanciate the tracer.
+ *
+ * Returns: %TRUE if the tracer uses structure parameters, %FALSE otherwise
+ *
+ * Since: 1.26
+ */
+gboolean
+gst_tracer_class_uses_structure_params (GstTracerClass * klass)
+{
+ g_return_val_if_fail (GST_IS_TRACER_CLASS (klass), FALSE);
+
+ return G_TYPE_CLASS_GET_PRIVATE (klass, GST_TYPE_TRACER,
+ GstTracerClassPrivate)->use_structure_params;
+}
+
+/**
+ * gst_tracer_class_set_use_structure_params:
+ * @klass: the #GstTracerFactoryClass to mark as using structure parameters
+ * @use_structure_params: %TRUE to use structure parameters, %FALSE otherwise
+ *
+ * Sets whether the tracer should use structure parameters for configuration.
+ * This function configures how parameters should be passed when instantiating
+ * the tracer.
+ *
+ * This is typically called in the tracer's class initialization function to
+ * indicate its parameter handling preference.
+ *
+ * Since: 1.26
+ */
+void
+gst_tracer_class_set_use_structure_params (GstTracerClass * klass,
+ gboolean use_structure_params)
+{
+ g_return_if_fail (GST_IS_TRACER_CLASS (klass));
+
+ G_TYPE_CLASS_GET_PRIVATE (klass, GST_TYPE_TRACER,
+ GstTracerClassPrivate)->use_structure_params = use_structure_params;
+}
#include "gst_private.h"
#include "gsttracer.h"
#include "gsttracerfactory.h"
+#include "gstvalue.h"
#include "gsttracerutils.h"
#ifndef GST_DISABLE_GST_TRACER_HOOKS
gboolean _priv_tracer_enabled = FALSE;
GHashTable *_priv_tracers = NULL;
+static gchar *
+list_available_tracer_properties (GObjectClass * class)
+{
+ GParamSpec **properties;
+ guint n_properties;
+ GString *props_str;
+ guint i;
+
+ props_str = g_string_new (NULL);
+ properties = g_object_class_list_properties (class, &n_properties);
+
+ if (n_properties == 0) {
+ g_string_append (props_str, "No properties available");
+ g_free (properties);
+ return g_string_free (props_str, FALSE);
+ }
+
+ g_string_append (props_str, "Available properties:");
+
+ for (i = 0; i < n_properties; i++) {
+ GParamSpec *prop = properties[i];
+
+ if (!((prop->flags & G_PARAM_CONSTRUCT)
+ || (prop->flags & G_PARAM_CONSTRUCT_ONLY))
+ || !(prop->flags & G_PARAM_WRITABLE))
+ continue;
+
+ if (!g_strcmp0 (g_param_spec_get_name (prop), "parent"))
+ continue;
+ if (!g_strcmp0 (g_param_spec_get_name (prop), "params"))
+ continue;
+
+ const gchar *type_name = G_PARAM_SPEC_TYPE_NAME (prop);
+ GValue default_value = G_VALUE_INIT;
+
+ /* Get default value if possible */
+ g_value_init (&default_value, prop->value_type);
+ g_param_value_set_default (prop, &default_value);
+ gchar *default_str = g_strdup_value_contents (&default_value);
+
+ g_string_append_printf (props_str,
+ "\n '%s' (%s) (Default: %s): %s",
+ g_param_spec_get_name (prop),
+ type_name,
+ default_str,
+ g_param_spec_get_blurb (prop) ? g_param_spec_get_blurb (prop) :
+ "(no description available)");
+
+ g_free (default_str);
+ g_value_unset (&default_value);
+ }
+
+ g_free (properties);
+ return g_string_free (props_str, FALSE);
+}
+
+static void
+gst_tracer_utils_create_tracer (GstTracerFactory * factory, const gchar * name,
+ const gchar * params)
+{
+ gchar *available_props = NULL;
+ GObjectClass *gobject_class = g_type_class_ref (factory->type);
+ GstTracer *tracer;
+ const gchar **names = NULL;
+ GValue *values = NULL;
+ gint n_properties = 1;
+
+ if (gst_tracer_class_uses_structure_params (GST_TRACER_CLASS (gobject_class))) {
+ GST_DEBUG ("Use structure parameters for %s", params);
+
+ if (!params) {
+ n_properties = 0;
+ goto create;
+ }
+
+ gchar *struct_str = g_strdup_printf ("%s,%s", name, params);
+ GstStructure *structure = gst_structure_from_string (struct_str, NULL);
+ g_free (struct_str);
+
+ if (!structure) {
+ available_props = list_available_tracer_properties (gobject_class);
+ g_warning
+ ("Can't instantiate `%s` tracer: invalid parameters '%s'\n %s\n",
+ name, params, available_props);
+ goto done;
+ }
+ n_properties = gst_structure_n_fields (structure);
+
+ names = g_new0 (const gchar *, n_properties);
+ values = g_new0 (GValue, n_properties);
+ for (gint i = 0; i < n_properties; i++) {
+ const gchar *field_name = gst_structure_nth_field_name (structure, i);
+ const GValue *field_value =
+ gst_structure_get_value (structure, field_name);
+ GParamSpec *pspec =
+ g_object_class_find_property (gobject_class, field_name);
+
+ if (!pspec) {
+ available_props = list_available_tracer_properties (gobject_class);
+ g_warning
+ ("Can't instantiate `%s` tracer: property '%s' not found\n %s\n",
+ name, field_name, available_props);
+ goto done;
+ }
+
+ if (G_VALUE_TYPE (field_value) == pspec->value_type) {
+ names[i] = field_name;
+ g_value_init (&values[i], G_VALUE_TYPE (field_value));
+ g_value_copy (field_value, &values[i]);
+ } else if (G_VALUE_TYPE (field_value) == G_TYPE_STRING) {
+ names[i] = field_name;
+ g_value_init (&values[i], G_PARAM_SPEC_VALUE_TYPE (pspec));
+ if (!gst_value_deserialize_with_pspec (&values[i],
+ g_value_get_string (field_value), pspec)) {
+ available_props = list_available_tracer_properties (gobject_class);
+ g_warning
+ ("Can't instantiate `%s` tracer: invalid property '%s' value: '%s'\n %s\n",
+ name, field_name, g_value_get_string (field_value),
+ available_props);
+ goto done;
+ }
+ } else {
+ available_props = list_available_tracer_properties (gobject_class);
+ g_warning
+ ("Can't instantiate `%s` tracer: property '%s' type mismatch, expected %s, got %s\n %s\n",
+ name, field_name, g_type_name (pspec->value_type),
+ g_type_name (G_VALUE_TYPE (field_value)), available_props);
+ goto done;
+ }
+ }
+
+ g_type_class_unref (gobject_class);
+ } else {
+ names = g_new0 (const gchar *, n_properties);
+ names[0] = (const gchar *) "params";
+ values = g_new0 (GValue, 1);
+ g_value_init (&values[0], G_TYPE_STRING);
+ g_value_set_string (&values[0], name);
+ }
+ GST_INFO_OBJECT (factory, "creating tracer: type-id=%u",
+ (guint) factory->type);
+
+create:
+ tracer =
+ GST_TRACER (g_object_new_with_properties (factory->type,
+ n_properties, names, values));
+
+ for (gint j = 0; j < n_properties; j++) {
+ g_value_unset (&values[j]);
+ }
+ g_free (names);
+ g_free (values);
+
+ /* Clear floating flag */
+ gst_object_ref_sink (tracer);
+
+ /* tracers register them self to the hooks */
+ gst_object_unref (tracer);
+
+done:
+ g_free (available_props);
+}
+
/* Initialize the tracing system */
void
_priv_gst_tracing_init (void)
if ((feature = gst_registry_lookup_feature (registry, t[i]))) {
factory = GST_TRACER_FACTORY (gst_plugin_feature_load (feature));
if (factory) {
- GstTracer *tracer;
-
- GST_INFO_OBJECT (factory, "creating tracer: type-id=%u",
- (guint) factory->type);
-
- tracer = g_object_new (factory->type, "params", params, NULL);
-
- /* Clear floating flag */
- gst_object_ref_sink (tracer);
-
- /* tracers register them self to the hooks */
- gst_object_unref (tracer);
+ gst_tracer_utils_create_tracer (factory, t[i], params);
} else {
- GST_WARNING_OBJECT (feature,
- "loading plugin containing feature %s failed!", t[i]);
+ g_warning ("loading plugin containing feature %s failed!", t[i]);
}
} else {
- GST_WARNING ("no tracer named '%s'", t[i]);
+ g_warning ("no tracer named '%s'", t[i]);
}
i++;
}