elementfactory: enable construct only property passing

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/736>
This commit is contained in:
Théo MAILLART 2021-01-29 20:36:51 +01:00 committed by GStreamer Marge Bot
parent a4a1782872
commit aadf84837b
2 changed files with 336 additions and 33 deletions

View file

@ -65,6 +65,8 @@
#include "glib-compat-private.h"
#include <gobject/gvaluecollector.h>
GST_DEBUG_CATEGORY_STATIC (element_factory_debug);
#define GST_CAT_DEFAULT element_factory_debug
@ -325,21 +327,94 @@ detailserror:
}
}
static gboolean
gst_element_factory_property_valist_to_array (const gchar * first,
va_list properties, GType object_type, guint * n, const gchar ** names[],
GValue ** values)
{
GObjectClass *class;
const gchar *name;
guint n_params = 0;
guint n_params_alloc = 16;
GValue *values_array;
const gchar **names_array;
if (!first)
return FALSE;
g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), FALSE);
class = g_type_class_ref (object_type);
if (!class)
return FALSE;
name = first;
names_array = g_new0 (const gchar *, n_params_alloc);
values_array = g_new0 (GValue, n_params_alloc);
do {
gchar *error = NULL;
GParamSpec *pspec;
pspec = g_object_class_find_property (class, name);
if (!pspec)
goto cleanup;
if (G_UNLIKELY (n_params == n_params_alloc)) {
n_params_alloc *= 2u;
names_array =
g_realloc (names_array, sizeof (const gchar *) * n_params_alloc);
values_array = g_realloc (values_array, sizeof (GValue) * n_params_alloc);
memset (&values_array[n_params], 0,
sizeof (GValue) * (n_params_alloc - n_params));
}
names_array[n_params] = name;
G_VALUE_COLLECT_INIT (&values_array[n_params], pspec->value_type,
properties, 0, &error);
if (error) {
g_critical ("%s", error);
g_free (error);
goto cleanup;
}
++n_params;
name = va_arg (properties, const gchar *);
} while (name);
*n = n_params;
*names = names_array;
*values = values_array;
g_type_class_unref (class);
return TRUE;
cleanup:
g_free (names_array);
g_free (values_array);
g_type_class_unref (class);
return FALSE;
}
/**
* gst_element_factory_create:
* gst_element_factory_create_with_properties:
* @factory: factory to instantiate
* @name: (allow-none): name of new element, or %NULL to automatically create
* a unique name
* @n: count of properties
* @names: (nullable): array of properties names
* @values: (nullable): array of associated properties values
*
* Create a new element of the type defined by the given elementfactory.
* It will be given the name supplied, since all elements require a name as
* their first argument.
* The supplied list of properties, will be passed at object construction.
*
* Returns: (transfer floating) (nullable): new #GstElement or %NULL
* if the element couldn't be created
*
* Since: 1.20
*/
GstElement *
gst_element_factory_create (GstElementFactory * factory, const gchar * name)
gst_element_factory_create_with_properties (GstElementFactory * factory,
guint n, const gchar * names[], const GValue values[])
{
GstElement *element;
GstElementClass *oclass;
@ -356,22 +431,14 @@ gst_element_factory_create (GstElementFactory * factory, const gchar * name)
factory = newfactory;
if (name)
GST_INFO ("creating element \"%s\" named \"%s\"",
GST_OBJECT_NAME (factory), GST_STR_NULL (name));
else
GST_INFO ("creating element \"%s\"", GST_OBJECT_NAME (factory));
GST_INFO ("creating element \"%s\"", GST_OBJECT_NAME (factory));
if (factory->type == 0)
goto no_type;
/* create an instance of the element, cast so we don't assert on NULL
* also set name as early as we can
*/
if (name)
element = g_object_new (factory->type, "name", name, NULL);
else
element = g_object_new (factory->type, NULL);
element = (GstElement *) g_object_new_with_properties (factory->type, n,
names, values);
if (G_UNLIKELY (element == NULL))
goto no_element;
@ -404,8 +471,7 @@ gst_element_factory_create (GstElementFactory * factory, const gchar * name)
/* ERRORS */
load_failed:
{
GST_WARNING_OBJECT (factory,
"loading plugin containing feature %s returned NULL!", name);
GST_WARNING_OBJECT (factory, "loading plugin returned NULL!");
return NULL;
}
no_type:
@ -423,21 +489,134 @@ no_element:
}
/**
* gst_element_factory_make:
* @factoryname: a named factory to instantiate
* @name: (allow-none): name of new element, or %NULL to automatically create
* a unique name
* gst_element_factory_create_valist:
* @factory: factory to instantiate
* @first: (nullable): name of the first property
* @properties: (nullable): list of properties
*
* Create a new element of the type defined by the given element factory.
* If name is %NULL, then the element will receive a guaranteed unique name,
* consisting of the element factory name and a number.
* If name is given, it will be given the name supplied.
* Create a new element of the type defined by the given elementfactory.
* The supplied list of properties, will be passed at object construction.
*
* Returns: (transfer floating) (nullable): new #GstElement or %NULL
* if unable to create element
* if the element couldn't be created
*
* Since: 1.20
*/
GstElement *
gst_element_factory_make (const gchar * factoryname, const gchar * name)
gst_element_factory_create_valist (GstElementFactory * factory,
const gchar * first, va_list properties)
{
GstElementFactory *newfactory;
GstElement *element;
const gchar **names = NULL;
GValue *values = NULL;
guint n = 0;
g_return_val_if_fail (factory != NULL, NULL);
newfactory =
GST_ELEMENT_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE
(factory)));
g_return_val_if_fail (newfactory != NULL, NULL);
g_return_val_if_fail (newfactory->type != 0, NULL);
factory = newfactory;
if (!first) {
element =
gst_element_factory_create_with_properties (factory, 0, NULL, NULL);
goto out;
}
if (!gst_element_factory_property_valist_to_array (first, properties,
factory->type, &n, &names, &values)) {
GST_ERROR_OBJECT (factory, "property parsing failed");
element = NULL;
goto out;
}
element = gst_element_factory_create_with_properties (factory, n, names,
values);
g_free (names);
while (n--)
g_value_unset (&values[n]);
g_free (values);
out:
gst_object_unref (factory);
return element;
}
/**
* gst_element_factory_create_full:
* @factory: factory to instantiate
* @first: (nullable): name of the first property
* @...: (nullable): %NULL terminated list of properties
*
* Create a new element of the type defined by the given elementfactory.
* The supplied list of properties, will be passed at object construction.
*
* Returns: (transfer floating) (nullable): new #GstElement or %NULL
* if the element couldn't be created
*
* Since: 1.20
*/
GstElement *
gst_element_factory_create_full (GstElementFactory * factory,
const gchar * first, ...)
{
GstElement *element;
va_list properties;
va_start (properties, first);
element = gst_element_factory_create_valist (factory, first, properties);
va_end (properties);
return element;
}
/**
* gst_element_factory_create:
* @factory: factory to instantiate
* @name: (nullable): name of new element, or %NULL to automatically create
* a unique name
*
* Create a new element of the type defined by the given elementfactory.
* It will be given the name supplied, since all elements require a name as
* their first argument.
*
* Returns: (transfer floating) (nullable): new #GstElement or %NULL
* if the element couldn't be created
*/
GstElement *
gst_element_factory_create (GstElementFactory * factory, const gchar * name)
{
if (name)
return gst_element_factory_create_full (factory, "name", name, NULL);
else
return gst_element_factory_create_with_properties (factory, 0, NULL, NULL);
}
/**
* gst_element_factory_make_with_properties:
* @factoryname: a named factory to instantiate
* @n: count of properties
* @names: (nullable): array of properties names
* @values: (nullable): array of associated properties values
*
* Create a new element of the type defined by the given elementfactory.
* The supplied list of properties, will be passed at object construction.
*
* Returns: (transfer floating) (nullable): new #GstElement or %NULL
* if the element couldn't be created
*
* Since: 1.20
*/
GstElement *
gst_element_factory_make_with_properties (const gchar * factoryname,
guint n, const gchar * names[], const GValue values[])
{
GstElementFactory *factory;
GstElement *element;
@ -445,15 +624,15 @@ gst_element_factory_make (const gchar * factoryname, const gchar * name)
g_return_val_if_fail (factoryname != NULL, NULL);
g_return_val_if_fail (gst_is_initialized (), NULL);
GST_LOG ("gstelementfactory: make \"%s\" \"%s\"",
factoryname, GST_STR_NULL (name));
GST_LOG ("gstelementfactory: make \"%s\"", factoryname);
factory = gst_element_factory_find (factoryname);
if (factory == NULL)
goto no_factory;
GST_LOG_OBJECT (factory, "found factory %p", factory);
element = gst_element_factory_create (factory, name);
element = gst_element_factory_create_with_properties (factory, n, names,
values);
if (element == NULL)
goto create_failed;
@ -475,6 +654,112 @@ create_failed:
}
}
/**
* gst_element_factory_make_valist:
* @factoryname: a named factory to instantiate
* @first: (nullable): name of first property
* @properties: (nullable): list of properties
*
* Create a new element of the type defined by the given element factory.
* The supplied list of properties, will be passed at object construction.
*
* Returns: (transfer floating) (nullable): new #GstElement or %NULL
* if unable to create element
*
* Since: 1.20
*/
GstElement *
gst_element_factory_make_valist (const gchar * factoryname,
const gchar * first, va_list properties)
{
GstElementFactory *factory;
GstElement *element;
g_return_val_if_fail (factoryname != NULL, NULL);
g_return_val_if_fail (gst_is_initialized (), NULL);
GST_LOG ("gstelementfactory: make \"%s\"", factoryname);
factory = gst_element_factory_find (factoryname);
if (factory == NULL)
goto no_factory;
GST_LOG_OBJECT (factory, "found factory %p", factory);
element = gst_element_factory_create_valist (factory, first, properties);
if (element == NULL)
goto create_failed;
gst_object_unref (factory);
return element;
/* ERRORS */
no_factory:
{
GST_WARNING ("no such element factory \"%s\"!", factoryname);
return NULL;
}
create_failed:
{
GST_INFO_OBJECT (factory, "couldn't create instance!");
gst_object_unref (factory);
return NULL;
}
}
/**
* gst_element_factory_make_full:
* @factoryname: a named factory to instantiate
* @first: (nullable): name of first property
* @...: (nullable): %NULL terminated list of properties
*
* Create a new element of the type defined by the given element factory.
* The supplied list of properties, will be passed at object construction.
*
* Returns: (transfer floating) (nullable): new #GstElement or %NULL
* if unable to create element
*
* Since: 1.20
*/
GstElement *
gst_element_factory_make_full (const gchar * factoryname,
const gchar * first, ...)
{
GstElement *element;
va_list properties;
va_start (properties, first);
element = gst_element_factory_make_valist (factoryname, first, properties);
va_end (properties);
return element;
}
/**
* gst_element_factory_make:
* @factoryname: a named factory to instantiate
* @name: (nullable): name of new element, or %NULL to automatically create
* a unique name
*
* Create a new element of the type defined by the given element factory.
* If name is %NULL, then the element will receive a guaranteed unique name,
* consisting of the element factory name and a number.
* If name is given, it will be given the name supplied.
*
* Returns: (transfer floating) (nullable): new #GstElement or %NULL
* if unable to create element
*/
GstElement *
gst_element_factory_make (const gchar * factoryname, const gchar * name)
{
if (name)
return gst_element_factory_make_full (factoryname, "name", name, NULL);
else
return gst_element_factory_make_with_properties (factoryname, 0, NULL,
NULL);
}
void
__gst_element_factory_add_static_pad_template (GstElementFactory * factory,
GstStaticPadTemplate * templ)

View file

@ -84,8 +84,26 @@ GST_API
GstElement* gst_element_factory_create (GstElementFactory *factory,
const gchar *name) G_GNUC_MALLOC;
GST_API
GstElement* gst_element_factory_create_full (GstElementFactory * factory,
const gchar * first, ...) G_GNUC_MALLOC;
GST_API
GstElement * gst_element_factory_create_valist (GstElementFactory * factory,
const gchar * first, va_list properties) G_GNUC_MALLOC;
GST_API
GstElement * gst_element_factory_create_with_properties (GstElementFactory * factory,
guint n, const gchar *names[], const GValue values[]) G_GNUC_MALLOC;
GST_API
GstElement* gst_element_factory_make (const gchar *factoryname, const gchar *name) G_GNUC_MALLOC;
GST_API
GstElement* gst_element_factory_make_full (const gchar *factoryname,
const gchar *first, ...) G_GNUC_MALLOC;
GST_API
GstElement* gst_element_factory_make_valist (const gchar *factoryname,
const gchar *first, va_list properties) G_GNUC_MALLOC;
GST_API
GstElement* gst_element_factory_make_with_properties (const gchar *factoryname,
guint n, const gchar *names[], const GValue values[]) G_GNUC_MALLOC;
GST_API
gboolean gst_element_register (GstPlugin *plugin, const gchar *name,
guint rank, GType type);