mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 06:58:56 +00:00
rewrite vararg prop entry using functions to cope with GST_PROPS_TYPE_LIST - fixes loads of segfaults in caps rewrite
Original commit message from CVS: rewrite vararg prop entry using functions to cope with GST_PROPS_TYPE_LIST - fixes loads of segfaults in caps rewrite
This commit is contained in:
parent
f5e3267133
commit
4ef9f4abc2
2 changed files with 87 additions and 99 deletions
182
gst/gstprops.c
182
gst/gstprops.c
|
@ -79,6 +79,7 @@ static gboolean gst_props_entry_check_compatibility (GstPropsEntry *entry1, Gs
|
||||||
static GList* gst_props_list_copy (GList *propslist);
|
static GList* gst_props_list_copy (GList *propslist);
|
||||||
|
|
||||||
static GstPropsEntry* gst_props_alloc_entry (void);
|
static GstPropsEntry* gst_props_alloc_entry (void);
|
||||||
|
static inline void gst_props_entry_free (GstPropsEntry *entry);
|
||||||
|
|
||||||
static void gst_props_destroy (GstProps *props);
|
static void gst_props_destroy (GstProps *props);
|
||||||
|
|
||||||
|
@ -653,10 +654,70 @@ props_find_func (gconstpointer a,
|
||||||
/* This is implemented as a huge macro because we cannot pass
|
/* This is implemented as a huge macro because we cannot pass
|
||||||
* va_list variables by reference on some architectures.
|
* va_list variables by reference on some architectures.
|
||||||
*/
|
*/
|
||||||
|
static inline GstPropsType
|
||||||
|
gst_props_type_sanitize (GstPropsType type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case GST_PROPS_INT_TYPE:
|
||||||
|
case GST_PROPS_INT_RANGE_TYPE:
|
||||||
|
return GST_PROPS_INT_TYPE;
|
||||||
|
case GST_PROPS_FLOAT_TYPE:
|
||||||
|
case GST_PROPS_FLOAT_RANGE_TYPE:
|
||||||
|
return GST_PROPS_FLOAT_TYPE;
|
||||||
|
case GST_PROPS_FOURCC_TYPE:
|
||||||
|
case GST_PROPS_BOOLEAN_TYPE:
|
||||||
|
case GST_PROPS_STRING_TYPE:
|
||||||
|
return type;
|
||||||
|
case GST_PROPS_LIST_TYPE:
|
||||||
|
case GST_PROPS_GLIST_TYPE:
|
||||||
|
return GST_PROPS_LIST_TYPE;
|
||||||
|
case GST_PROPS_END_TYPE:
|
||||||
|
case GST_PROPS_INVALID_TYPE:
|
||||||
|
case GST_PROPS_VAR_TYPE:
|
||||||
|
case GST_PROPS_LAST_TYPE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
g_assert_not_reached ();
|
||||||
|
return GST_PROPS_END_TYPE;
|
||||||
|
}
|
||||||
#define GST_PROPS_ENTRY_FILL(entry, var_args) \
|
#define GST_PROPS_ENTRY_FILL(entry, var_args) \
|
||||||
G_STMT_START { \
|
G_STMT_START { \
|
||||||
entry->propstype = va_arg (var_args, GstPropsType); \
|
entry->propstype = va_arg (var_args, GstPropsType); \
|
||||||
\
|
if (entry->propstype == GST_PROPS_LIST_TYPE) { \
|
||||||
|
GList *_list = NULL; \
|
||||||
|
GstPropsEntry *_cur; \
|
||||||
|
GstPropsType _cur_type; \
|
||||||
|
GstPropsType _type = va_arg (var_args, GstPropsType); \
|
||||||
|
_cur_type = _type; \
|
||||||
|
_type = gst_props_type_sanitize (_type); \
|
||||||
|
while (_cur_type != GST_PROPS_END_TYPE) { \
|
||||||
|
_cur = gst_props_alloc_entry (); \
|
||||||
|
_cur->propid = entry->propid; \
|
||||||
|
_cur->propstype = _cur_type; \
|
||||||
|
_cur_type = gst_props_type_sanitize (_cur_type); \
|
||||||
|
g_assert (_cur_type == _type); \
|
||||||
|
GST_PROPS_ENTRY_FILL_DATA(_cur, var_args); \
|
||||||
|
if (_cur_type == GST_PROPS_INT_TYPE) { \
|
||||||
|
_list = gst_props_add_to_int_list (_list, _cur); \
|
||||||
|
} else { \
|
||||||
|
_list = g_list_prepend (_list, _cur); \
|
||||||
|
} \
|
||||||
|
_cur_type = va_arg (var_args, GstPropsType); \
|
||||||
|
} \
|
||||||
|
if (g_list_next (_list)) { \
|
||||||
|
entry->data.list_data.entries = _list; \
|
||||||
|
} else { \
|
||||||
|
entry->propstype = _cur->propstype; \
|
||||||
|
entry->data = _cur->data; \
|
||||||
|
gst_props_entry_free (_cur); \
|
||||||
|
} \
|
||||||
|
} else { \
|
||||||
|
GST_PROPS_ENTRY_FILL_DATA(entry, var_args); \
|
||||||
|
} \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
|
#define GST_PROPS_ENTRY_FILL_DATA(entry, var_args) \
|
||||||
|
G_STMT_START { \
|
||||||
switch (entry->propstype) { \
|
switch (entry->propstype) { \
|
||||||
case GST_PROPS_INT_TYPE: \
|
case GST_PROPS_INT_TYPE: \
|
||||||
entry->data.int_data = va_arg (var_args, gint); \
|
entry->data.int_data = va_arg (var_args, gint); \
|
||||||
|
@ -686,7 +747,7 @@ G_STMT_START { \
|
||||||
entry->data.list_data.entries = g_list_copy (va_arg (var_args, GList*)); \
|
entry->data.list_data.entries = g_list_copy (va_arg (var_args, GList*)); \
|
||||||
break; \
|
break; \
|
||||||
default: \
|
default: \
|
||||||
break; \
|
g_assert_not_reached (); \
|
||||||
} \
|
} \
|
||||||
} G_STMT_END
|
} G_STMT_END
|
||||||
|
|
||||||
|
@ -767,7 +828,14 @@ gst_props_entry_clean (GstPropsEntry *entry)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static inline void
|
||||||
|
gst_props_entry_free (GstPropsEntry *entry)
|
||||||
|
{
|
||||||
|
gst_mem_chunk_free (_gst_props_entries_chunk, entry);
|
||||||
|
#ifndef GST_DISABLE_TRACE
|
||||||
|
gst_alloc_trace_free (_entries_trace, entry);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* gst_props_entry_destroy:
|
* gst_props_entry_destroy:
|
||||||
* @entry: the entry to destroy
|
* @entry: the entry to destroy
|
||||||
|
@ -777,14 +845,13 @@ gst_props_entry_clean (GstPropsEntry *entry)
|
||||||
void
|
void
|
||||||
gst_props_entry_destroy (GstPropsEntry *entry)
|
gst_props_entry_destroy (GstPropsEntry *entry)
|
||||||
{
|
{
|
||||||
|
if (!entry) return;
|
||||||
|
|
||||||
GST_CAT_LOG (GST_CAT_PROPERTIES, "destroy entry %p", entry);
|
GST_CAT_LOG (GST_CAT_PROPERTIES, "destroy entry %p", entry);
|
||||||
|
|
||||||
gst_props_entry_clean (entry);
|
gst_props_entry_clean (entry);
|
||||||
|
|
||||||
gst_mem_chunk_free (_gst_props_entries_chunk, entry);
|
gst_props_entry_free (entry);
|
||||||
#ifndef GST_DISABLE_TRACE
|
|
||||||
gst_alloc_trace_free (_entries_trace, entry);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GType
|
GType
|
||||||
|
@ -1096,14 +1163,18 @@ gst_props_entry_get_type (void)
|
||||||
return _gst_props_entry_type;
|
return _gst_props_entry_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define GST_PROPS_ENTRY_NEW(entry, name,var_args) \
|
||||||
|
G_STMT_START { \
|
||||||
|
entry = gst_props_alloc_entry (); \
|
||||||
|
entry->propid = g_quark_from_string (name); \
|
||||||
|
GST_PROPS_ENTRY_FILL (entry, var_args); \
|
||||||
|
} G_STMT_END
|
||||||
static GstPropsEntry*
|
static GstPropsEntry*
|
||||||
gst_props_entry_newv (const gchar *name, va_list var_args)
|
gst_props_entry_newv (const gchar *name, va_list var_args)
|
||||||
{
|
{
|
||||||
GstPropsEntry *entry;
|
GstPropsEntry *entry;
|
||||||
|
|
||||||
entry = gst_props_alloc_entry ();
|
GST_PROPS_ENTRY_NEW (entry, name, var_args);
|
||||||
entry->propid = g_quark_from_string (name);
|
|
||||||
GST_PROPS_ENTRY_FILL (entry, var_args);
|
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
@ -1143,21 +1214,7 @@ GstProps*
|
||||||
gst_props_newv (const gchar *firstname, va_list var_args)
|
gst_props_newv (const gchar *firstname, va_list var_args)
|
||||||
{
|
{
|
||||||
GstProps *props;
|
GstProps *props;
|
||||||
gboolean inlist = FALSE;
|
|
||||||
const gchar *prop_name;
|
const gchar *prop_name;
|
||||||
GstPropsEntry *list_entry = NULL;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
GST_PROPS_LIST_T_UNSET,
|
|
||||||
GST_PROPS_LIST_T_INTS,
|
|
||||||
GST_PROPS_LIST_T_FLOATS,
|
|
||||||
GST_PROPS_LIST_T_MISC,
|
|
||||||
} list_types;
|
|
||||||
|
|
||||||
/* type of the list */
|
|
||||||
list_types list_type = GST_PROPS_LIST_T_UNSET;
|
|
||||||
/* type of current item */
|
|
||||||
list_types entry_type = GST_PROPS_LIST_T_UNSET;
|
|
||||||
|
|
||||||
if (firstname == NULL)
|
if (firstname == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1170,79 +1227,10 @@ gst_props_newv (const gchar *firstname, va_list var_args)
|
||||||
while (prop_name) {
|
while (prop_name) {
|
||||||
GstPropsEntry *entry;
|
GstPropsEntry *entry;
|
||||||
|
|
||||||
entry = gst_props_alloc_entry ();
|
GST_PROPS_ENTRY_NEW (entry, prop_name, var_args);
|
||||||
entry->propid = g_quark_from_string (prop_name);
|
gst_props_add_entry (props, entry);
|
||||||
GST_PROPS_ENTRY_FILL (entry, var_args);
|
|
||||||
|
prop_name = va_arg (var_args, gchar*);
|
||||||
switch (entry->propstype) {
|
|
||||||
case GST_PROPS_INT_TYPE:
|
|
||||||
case GST_PROPS_INT_RANGE_TYPE:
|
|
||||||
entry_type = GST_PROPS_LIST_T_INTS;
|
|
||||||
break;
|
|
||||||
case GST_PROPS_FLOAT_TYPE:
|
|
||||||
case GST_PROPS_FLOAT_RANGE_TYPE:
|
|
||||||
entry_type = GST_PROPS_LIST_T_FLOATS;
|
|
||||||
break;
|
|
||||||
case GST_PROPS_FOURCC_TYPE:
|
|
||||||
case GST_PROPS_BOOLEAN_TYPE:
|
|
||||||
case GST_PROPS_STRING_TYPE:
|
|
||||||
entry_type = GST_PROPS_LIST_T_MISC;
|
|
||||||
break;
|
|
||||||
case GST_PROPS_LIST_TYPE:
|
|
||||||
g_return_val_if_fail (inlist == FALSE, NULL);
|
|
||||||
inlist = TRUE;
|
|
||||||
list_entry = entry;
|
|
||||||
list_type = GST_PROPS_LIST_T_UNSET;
|
|
||||||
list_entry->data.list_data.entries = NULL;
|
|
||||||
break;
|
|
||||||
case GST_PROPS_END_TYPE:
|
|
||||||
g_return_val_if_fail (inlist == TRUE, NULL);
|
|
||||||
|
|
||||||
/* if list was of size 1, replace the list by a the item it contains */
|
|
||||||
if (g_list_length(list_entry->data.list_data.entries) == 1) {
|
|
||||||
GstPropsEntry *subentry = (GstPropsEntry *)(list_entry->data.list_data.entries->data);
|
|
||||||
list_entry->propstype = subentry->propstype;
|
|
||||||
list_entry->data = subentry->data;
|
|
||||||
gst_props_entry_destroy (subentry);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
list_entry->data.list_data.entries =
|
|
||||||
g_list_reverse (list_entry->data.list_data.entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_props_entry_destroy (entry);
|
|
||||||
inlist = FALSE;
|
|
||||||
list_entry = NULL;
|
|
||||||
prop_name = va_arg (var_args, gchar*);
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
g_warning ("unknown property type found %d for '%s'\n", entry->propstype, prop_name);
|
|
||||||
gst_props_entry_destroy (entry);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inlist && (list_entry != entry)) {
|
|
||||||
if (list_type == GST_PROPS_LIST_T_UNSET) list_type = entry_type;
|
|
||||||
if (list_type != entry_type) {
|
|
||||||
g_warning ("property list contained incompatible entry types\n");
|
|
||||||
} else {
|
|
||||||
switch (list_type) {
|
|
||||||
case GST_PROPS_LIST_T_INTS:
|
|
||||||
list_entry->data.list_data.entries =
|
|
||||||
gst_props_add_to_int_list (list_entry->data.list_data.entries, entry);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
list_entry->data.list_data.entries =
|
|
||||||
g_list_prepend (list_entry->data.list_data.entries, entry);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
gst_props_add_entry (props, entry);
|
|
||||||
}
|
|
||||||
if (!inlist)
|
|
||||||
prop_name = va_arg (var_args, gchar*);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return props;
|
return props;
|
||||||
|
|
|
@ -69,9 +69,9 @@ typedef enum {
|
||||||
((gchar) (((fourcc)>>24)&0xff))
|
((gchar) (((fourcc)>>24)&0xff))
|
||||||
|
|
||||||
#ifdef G_HAVE_ISO_VARARGS
|
#ifdef G_HAVE_ISO_VARARGS
|
||||||
# define GST_PROPS_LIST(...) GST_PROPS_LIST_TYPE,__VA_ARGS__,NULL
|
# define GST_PROPS_LIST(...) GST_PROPS_LIST_TYPE,__VA_ARGS__,GST_PROPS_END_TYPE
|
||||||
#elif defined(G_HAVE_GNUC_VARARGS)
|
#elif defined(G_HAVE_GNUC_VARARGS)
|
||||||
# define GST_PROPS_LIST(a...) GST_PROPS_LIST_TYPE,a,NULL
|
# define GST_PROPS_LIST(a...) GST_PROPS_LIST_TYPE,a,GST_PROPS_END_TYPE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define GST_PROPS_GLIST(a) GST_PROPS_GLIST_TYPE,(a)
|
#define GST_PROPS_GLIST(a) GST_PROPS_GLIST_TYPE,(a)
|
||||||
|
|
Loading…
Reference in a new issue