mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-19 06:46:38 +00:00
tracers: Simplify params handling using GstStructure and object properties
Instead of having each tracer implement its own parameter parsing, centralize the handling in the tracer subsystem using GstStructure. This simplifies tracer implementations and provides a consistent way to handle properties. It also allows for much better documentation by forcing tracer object to expose properties Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8086>
This commit is contained in:
parent
18d83192be
commit
5e18499372
6 changed files with 267 additions and 16 deletions
|
@ -49595,6 +49595,42 @@ contextual data, which they must not modify.</doc>
|
|||
<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
|
||||
|
|
|
@ -52,6 +52,11 @@ enum
|
|||
|
||||
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,
|
||||
|
@ -62,8 +67,13 @@ struct _GstTracerPrivate
|
|||
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)
|
||||
|
@ -192,3 +202,48 @@ gst_tracer_register (GstPlugin * plugin, const gchar * name, GType type)
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -75,6 +75,12 @@ gboolean gst_tracer_register (GstPlugin * plugin, const gchar * name, GType type
|
|||
GST_API
|
||||
GList* gst_tracing_get_active_tracers (void);
|
||||
|
||||
GST_API
|
||||
gboolean gst_tracer_class_uses_structure_params (GstTracerClass *tracer_class);
|
||||
GST_API
|
||||
void gst_tracer_class_set_use_structure_params (GstTracerClass *tracer_class,
|
||||
gboolean use_structure_params);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTracer, gst_object_unref)
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "gstinfo.h"
|
||||
#include "gsttracerfactory.h"
|
||||
#include "gstregistry.h"
|
||||
#include "gsttracer.h"
|
||||
|
||||
GST_DEBUG_CATEGORY (tracer_debug);
|
||||
#define GST_CAT_DEFAULT tracer_debug
|
||||
|
|
|
@ -57,6 +57,7 @@ GList * gst_tracer_factory_get_list (void);
|
|||
GST_API
|
||||
GType gst_tracer_factory_get_tracer_type (GstTracerFactory * factory);
|
||||
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTracerFactory, gst_object_unref)
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "gst_private.h"
|
||||
#include "gsttracer.h"
|
||||
#include "gsttracerfactory.h"
|
||||
#include "gstvalue.h"
|
||||
#include "gsttracerutils.h"
|
||||
|
||||
#ifndef GST_DISABLE_GST_TRACER_HOOKS
|
||||
|
@ -66,6 +67,169 @@ GQuark _priv_gst_tracer_quark_table[GST_TRACER_QUARK_MAX];
|
|||
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)
|
||||
|
@ -128,24 +292,12 @@ _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++;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue