#include "gstlog.h"
#include "gstprops.h"
+#include "gstmemchunk.h"
+
+/* #define GST_WITH_ALLOC_TRACE */
+#include "gsttrace.h"
GType _gst_props_type;
GType _gst_props_entry_type;
+static GstAllocTrace *_props_trace;
+static GstAllocTrace *_entries_trace;
+
#define GST_PROPS_ENTRY_IS_VARIABLE(a) (((GstPropsEntry*)(a))->propstype > GST_PROPS_VAR_TYPE)
struct _GstPropsEntry {
} data;
};
-static GMemChunk *_gst_props_entries_chunk;
-static GMutex *_gst_props_entries_chunk_lock;
-
-static GMemChunk *_gst_props_chunk;
-static GMutex *_gst_props_chunk_lock;
+static GstMemChunk *_gst_props_entries_chunk;
+static GstMemChunk *_gst_props_chunk;
static gboolean gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry2);
static GList* gst_props_list_copy (GList *propslist);
const gchar *name = g_quark_to_string (entry->propid);
switch (entry->propstype) {
- case GST_PROPS_STRING_TYPE:
- g_string_append_printf (result, "%s=(string) '%s'", name, entry->data.string_data.string);
- break;
case GST_PROPS_INT_TYPE:
g_string_append_printf (result, "%s=(int) %d", name, entry->data.int_data);
break;
break;
case GST_PROPS_BOOLEAN_TYPE:
g_string_append_printf (result, "%s=(boolean) %s", name,
- (entry->data.bool_data ? "TRUE" : "FALSE"));
+ (entry->data.bool_data ? "TRUE" : "FALSE"));
+ break;
+ case GST_PROPS_STRING_TYPE:
+ g_string_append_printf (result, "%s=(string) '%s'", name, entry->data.string_data.string);
break;
default:
break;
}
}
dest_value->data[0].v_pointer = result->str;
+ g_string_free (result, FALSE);
}
void
_gst_props_initialize (void)
{
- _gst_props_entries_chunk = g_mem_chunk_new ("GstPropsEntries",
- sizeof (GstPropsEntry), sizeof (GstPropsEntry) * 256,
+ _gst_props_entries_chunk = gst_mem_chunk_new ("GstPropsEntries",
+ sizeof (GstPropsEntry), sizeof (GstPropsEntry) * 1024,
G_ALLOC_AND_FREE);
- _gst_props_entries_chunk_lock = g_mutex_new ();
- _gst_props_chunk = g_mem_chunk_new ("GstProps",
+ _gst_props_chunk = gst_mem_chunk_new ("GstProps",
sizeof (GstProps), sizeof (GstProps) * 256,
G_ALLOC_AND_FREE);
- _gst_props_chunk_lock = g_mutex_new ();
_gst_props_type = g_boxed_type_register_static ("GstProps",
(GBoxedCopyFunc) gst_props_ref,
_gst_props_entry_type = g_boxed_type_register_static ("GstPropsEntry",
(GBoxedCopyFunc) gst_props_entry_copy,
(GBoxedFreeFunc) gst_props_entry_destroy);
+
+ _props_trace = gst_alloc_trace_register (GST_PROPS_TRACE_NAME);
+ _entries_trace = gst_alloc_trace_register (GST_PROPS_ENTRY_TRACE_NAME);
}
static void
switch (entry->propstype) {
case GST_PROPS_INT_TYPE:
- GST_DEBUG (GST_CAT_PROPERTIES, "%s: int %d", name, entry->data.int_data);
+ GST_DEBUG (GST_CAT_PROPERTIES, "%p: %s: int %d", entry, name, entry->data.int_data);
break;
case GST_PROPS_FLOAT_TYPE:
- GST_DEBUG (GST_CAT_PROPERTIES, "%s: float %f", name, entry->data.float_data);
+ GST_DEBUG (GST_CAT_PROPERTIES, "%p: %s: float %f", entry, name, entry->data.float_data);
break;
case GST_PROPS_FOURCC_TYPE:
- GST_DEBUG (GST_CAT_PROPERTIES, "%s: fourcc %c%c%c%c", name,
+ GST_DEBUG (GST_CAT_PROPERTIES, "%p: %s: fourcc %c%c%c%c", entry, name,
(entry->data.fourcc_data>>0)&0xff,
(entry->data.fourcc_data>>8)&0xff,
(entry->data.fourcc_data>>16)&0xff,
(entry->data.fourcc_data>>24)&0xff);
break;
case GST_PROPS_BOOLEAN_TYPE:
- GST_DEBUG (GST_CAT_PROPERTIES, "%s: bool %d", name, entry->data.bool_data);
+ GST_DEBUG (GST_CAT_PROPERTIES, "%p: %s: bool %d", entry, name, entry->data.bool_data);
break;
case GST_PROPS_STRING_TYPE:
- GST_DEBUG (GST_CAT_PROPERTIES, "%s: string \"%s\"", name, entry->data.string_data.string);
+ GST_DEBUG (GST_CAT_PROPERTIES, "%p: %s: string \"%s\"", entry, name, entry->data.string_data.string);
break;
case GST_PROPS_INT_RANGE_TYPE:
- GST_DEBUG (GST_CAT_PROPERTIES, "%s: int range %d-%d", name, entry->data.int_range_data.min,
+ GST_DEBUG (GST_CAT_PROPERTIES, "%p: %s: int range %d-%d", entry, name, entry->data.int_range_data.min,
entry->data.int_range_data.max);
break;
case GST_PROPS_FLOAT_RANGE_TYPE:
- GST_DEBUG (GST_CAT_PROPERTIES, "%s: float range %f-%f", name, entry->data.float_range_data.min,
+ GST_DEBUG (GST_CAT_PROPERTIES, "%p: %s: float range %f-%f", entry, name, entry->data.float_range_data.min,
entry->data.float_range_data.max);
break;
case GST_PROPS_LIST_TYPE:
- GST_DEBUG (GST_CAT_PROPERTIES, "[list]");
+ GST_DEBUG (GST_CAT_PROPERTIES, "%p: [list]", entry);
{
GList *entries = entry->data.list_data.entries;
}
break;
default:
- g_warning ("unknown property type %d", entry->propstype);
+ g_warning ("unknown property type %d at %p", entry->propstype, entry);
break;
}
}
{
GstPropsEntry *entry;
- g_mutex_lock (_gst_props_entries_chunk_lock);
- entry = g_mem_chunk_alloc (_gst_props_entries_chunk);
- g_mutex_unlock (_gst_props_entries_chunk_lock);
+ entry = gst_mem_chunk_alloc (_gst_props_entries_chunk);
+ gst_alloc_trace_new (_entries_trace, entry);
+
+ GST_DEBUG (GST_CAT_PROPERTIES, "new entry %p", entry);
return entry;
}
-void
-gst_props_entry_destroy (GstPropsEntry *entry)
+static void
+gst_props_entry_clean (GstPropsEntry *entry)
{
switch (entry->propstype) {
case GST_PROPS_STRING_TYPE:
default:
break;
}
- g_mutex_lock (_gst_props_entries_chunk_lock);
- g_mem_chunk_free (_gst_props_entries_chunk, entry);
- g_mutex_unlock (_gst_props_entries_chunk_lock);
+}
+
+void
+gst_props_entry_destroy (GstPropsEntry *entry)
+{
+ GST_DEBUG (GST_CAT_PROPERTIES, "destroy entry %p", entry);
+
+ gst_props_entry_clean (entry);
+
+ gst_mem_chunk_free (_gst_props_entries_chunk, entry);
+ gst_alloc_trace_free (_entries_trace, entry);
}
/**
{
GstProps *props;
- g_mutex_lock (_gst_props_chunk_lock);
- props = g_mem_chunk_alloc (_gst_props_chunk);
- g_mutex_unlock (_gst_props_chunk_lock);
+ props = gst_mem_chunk_alloc (_gst_props_chunk);
+ gst_alloc_trace_new (_props_trace, props);
+
+ GST_DEBUG (GST_CAT_PROPERTIES, "new %p", props);
props->properties = NULL;
props->refcount = 1;
- props->fixed = TRUE;
+ GST_PROPS_FLAG_SET (props, GST_PROPS_FLOATING);
+ GST_PROPS_FLAG_SET (props, GST_PROPS_FIXED);
return props;
}
/**
+ * gst_props_replace:
+ * @oldprops: the props to take replace
+ * @newprops: the props to take replace
+ *
+ * Replace the pointer to the props, doing proper
+ * refcounting.
+ */
+void
+gst_props_replace (GstProps **oldprops, GstProps *newprops)
+{
+ if (*oldprops != newprops) {
+ if (newprops) gst_props_ref (newprops);
+ if (*oldprops) gst_props_unref (*oldprops);
+
+ *oldprops = newprops;
+ }
+}
+
+/**
+ * gst_props_replace_sink:
+ * @oldprops: the props to take replace
+ * @newprops: the props to take replace
+ *
+ * Replace the pointer to the props and take ownership.
+ */
+void
+gst_props_replace_sink (GstProps **oldprops, GstProps *newprops)
+{
+ gst_props_replace (oldprops, newprops);
+ gst_props_sink (newprops);
+}
+
+/**
* gst_props_add_entry:
* @props: the property to add the entry to
* @entry: the entry to add
g_return_if_fail (props);
g_return_if_fail (entry);
- if (props->fixed && GST_PROPS_ENTRY_IS_VARIABLE (entry)) {
- props->fixed = FALSE;
+ if (GST_PROPS_IS_FIXED (props) && GST_PROPS_ENTRY_IS_VARIABLE (entry)) {
+ GST_PROPS_FLAG_UNSET (props, GST_PROPS_FIXED);
}
props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
}
/**
+ * gst_props_remove_entry:
+ * @props: the property to remove the entry from
+ * @entry: the entry to remove
+ *
+ * Removes the given propsentry from the props.
+ */
+void
+gst_props_remove_entry (GstProps *props, GstPropsEntry *entry)
+{
+ g_return_if_fail (props != NULL);
+ g_return_if_fail (entry != NULL);
+
+ props->properties = g_list_remove (props->properties, entry);
+}
+
+/**
+ * gst_props_remove_entry_by_name:
+ * @props: the property to remove the entry from
+ * @name: the name of the entry to remove
+ *
+ * Removes the propsentry with the given name from the props.
+ */
+void
+gst_props_remove_entry_by_name (GstProps *props, const gchar *name)
+{
+ GList *lentry;
+ GQuark quark;
+
+ g_return_if_fail (props != NULL);
+ g_return_if_fail (name != NULL);
+
+ quark = g_quark_from_string (name);
+
+ lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
+ if (lentry) {
+ gst_props_remove_entry (props, (GstPropsEntry *)lentry->data);
+ }
+}
+
+/**
* gst_props_new:
* @firstname: the first property name
* @...: the property values
{
GList *propslist = props->properties;
+ GST_DEBUG (GST_CAT_PROPERTIES, "props %p, refcount %d, flags %d", props, props->refcount, props->flags);
+
while (propslist) {
GstPropsEntry *entry = (GstPropsEntry *)propslist->data;
* Returns: TRUE if the entries were merged, FALSE otherwise.
*/
static gboolean
-gst_props_merge_int_entries(GstPropsEntry * newentry, GstPropsEntry * oldentry)
+gst_props_merge_int_entries(GstPropsEntry *newentry, GstPropsEntry *oldentry)
{
gint new_min, new_max, old_min, old_max;
gboolean can_merge = FALSE;
*
* Returns: a pointer to a list with the new entry added.
*/
-static GList *
-gst_props_add_to_int_list (GList * entries, GstPropsEntry * newentry)
+static GList*
+gst_props_add_to_int_list (GList *entries, GstPropsEntry *newentry)
{
- GList * i;
+ GList *i;
i = entries;
while (i) {
- GstPropsEntry * oldentry = (GstPropsEntry *)(i->data);
+ GstPropsEntry *oldentry = (GstPropsEntry *)(i->data);
gboolean merged = gst_props_merge_int_entries(newentry, oldentry);
if (merged) {
/* replace the existing one with the merged one */
- g_mutex_lock (_gst_props_entries_chunk_lock);
- g_mem_chunk_free (_gst_props_entries_chunk, oldentry);
- g_mutex_unlock (_gst_props_entries_chunk_lock);
+ gst_props_entry_destroy (oldentry);
+
entries = g_list_remove_link (entries, i);
g_list_free_1 (i);
/* 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);
+ GstPropsEntry *subentry = (GstPropsEntry *)(list_entry->data.list_data.entries->data);
list_entry->propstype = subentry->propstype;
list_entry->data = subentry->data;
- g_mutex_lock (_gst_props_entries_chunk_lock);
- g_mem_chunk_free (_gst_props_entries_chunk, subentry);
- g_mutex_unlock (_gst_props_entries_chunk_lock);
+ gst_props_entry_destroy (subentry);
}
else {
list_entry->data.list_data.entries =
g_list_reverse (list_entry->data.list_data.entries);
}
- g_mutex_lock (_gst_props_entries_chunk_lock);
- g_mem_chunk_free (_gst_props_entries_chunk, entry);
- g_mutex_unlock (_gst_props_entries_chunk_lock);
+ 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);
- g_mutex_lock (_gst_props_entries_chunk_lock);
- g_mem_chunk_free (_gst_props_entries_chunk, entry);
- g_mutex_unlock (_gst_props_entries_chunk_lock);
+ gst_props_entry_destroy (entry);
break;
}
entry = (GstPropsEntry *)lentry->data;
va_start (var_args, name);
-
+ gst_props_entry_clean (entry);
GST_PROPS_ENTRY_FILL (entry, var_args);
-
va_end (var_args);
}
else {
*
* Decrease the refcount of the property structure, destroying
* the property if the refcount is 0.
+ *
+ * Returns: handle to unrefed props or NULL when it was
+ * destroyed.
*/
-void
+GstProps*
gst_props_unref (GstProps *props)
{
if (props == NULL)
- return;
+ return NULL;
+ g_return_val_if_fail (props->refcount > 0, NULL);
+
+ GST_DEBUG (GST_CAT_PROPERTIES, "unref %p (%d->%d)", props, props->refcount, props->refcount-1);
props->refcount--;
- if (props->refcount == 0)
+ if (props->refcount == 0) {
gst_props_destroy (props);
+ return NULL;
+ }
+
+ return props;
}
/**
* @props: the props to ref
*
* Increase the refcount of the property structure.
+ *
+ * Returns: handle to refed props.
*/
-void
+GstProps*
gst_props_ref (GstProps *props)
{
- g_return_if_fail (props != NULL);
+ if (props == NULL)
+ return NULL;
+
+ g_return_val_if_fail (props->refcount > 0, NULL);
+
+ GST_DEBUG (GST_CAT_PROPERTIES, "ref %p (%d->%d)", props, props->refcount, props->refcount+1);
props->refcount++;
+
+ return props;
}
+/**
+ * gst_props_sink:
+ * @props: the props to sink
+ *
+ * If the props if floating, decrease its refcount. Usually used
+ * with gst_props_ref() to take ownership of the props.
+ */
+void
+gst_props_sink (GstProps *props)
+{
+ if (props == NULL)
+ return;
+
+ GST_DEBUG (GST_CAT_PROPERTIES, "sink %p", props);
+
+ if (GST_PROPS_IS_FLOATING (props)) {
+ GST_PROPS_FLAG_UNSET (props, GST_PROPS_FLOATING);
+ gst_props_unref (props);
+ }
+}
/**
* gst_props_destroy:
}
g_list_free (props->properties);
- g_mutex_lock (_gst_props_chunk_lock);
- g_mem_chunk_free (_gst_props_chunk, props);
- g_mutex_unlock (_gst_props_chunk_lock);
+ gst_mem_chunk_free (_gst_props_chunk, props);
+ gst_alloc_trace_free (_props_trace, props);
}
/*
* copy entries
*/
GstPropsEntry*
-gst_props_entry_copy (GstPropsEntry *entry)
+gst_props_entry_copy (const GstPropsEntry *entry)
{
GstPropsEntry *newentry;
newentry = gst_props_alloc_entry ();
memcpy (newentry, entry, sizeof (GstPropsEntry));
- if (entry->propstype == GST_PROPS_LIST_TYPE) {
- newentry->data.list_data.entries = gst_props_list_copy (entry->data.list_data.entries);
- }
- else if (entry->propstype == GST_PROPS_STRING_TYPE) {
- newentry->data.string_data.string = g_strdup (entry->data.string_data.string);
+
+ switch (entry->propstype) {
+ case GST_PROPS_LIST_TYPE:
+ newentry->data.list_data.entries = gst_props_list_copy (entry->data.list_data.entries);
+ break;
+ case GST_PROPS_STRING_TYPE:
+ newentry->data.string_data.string = g_strdup (entry->data.string_data.string);
+ break;
+ default:
+ /* FIXME more? */
+ break;
}
return newentry;
new = gst_props_empty_new ();
new->properties = gst_props_list_copy (props->properties);
- new->fixed = props->fixed;
+ GST_PROPS_FLAGS (new) = GST_PROPS_FLAGS (props) | GST_PROPS_FLOATING;
return new;
}
gboolean result;
if (!entry) return FALSE;
- GST_PROPS_ENTRY_READ (entry, var_args, FALSE, &result);
+ GST_PROPS_ENTRY_READ (entry, var_args, safe, &result);
if (!result) return FALSE;
first_name = va_arg (var_args, gchar *);
* @...: a pointer to a datastructure that can hold the value.
*
* Gets the contents of the props into given key/value pairs.
+ * Make sure you pass a NULL terminated list.
*
- * Returns: TRUE is the props entry could be fetched.
+ * Returns: TRUE if all of the props entries could be fetched.
*/
gboolean
gst_props_get (GstProps *props, gchar *first_name, ...)
*
* Gets the contents of the props into given key/value pairs.
*
- * Returns: TRUE is the props entry could be fetched.
+ * Returns: TRUE if all of the props entries could be fetched.
*/
gboolean
gst_props_get_safe (GstProps *props, gchar *first_name, ...)
* Get the contents of the entry into the given gint.
*
* Returns: TRUE is the value could be fetched. FALSE if the
- * entry is not of given type.
+ * entry is not of given type or did not exist.
*/
gboolean
gst_props_entry_get_int (const GstPropsEntry *entry, gint *val)
* Get the contents of the entry into the given gfloat.
*
* Returns: TRUE is the value could be fetched. FALSE if the
- * entry is not of given type.
+ * entry is not of given type or did not exist.
*/
gboolean
gst_props_entry_get_float (const GstPropsEntry *entry, gfloat *val)
* Get the contents of the entry into the given guint32.
*
* Returns: TRUE is the value could be fetched. FALSE if the
- * entry is not of given type.
+ * entry is not of given type or did not exist.
*/
gboolean
gst_props_entry_get_fourcc_int (const GstPropsEntry *entry, guint32 *val)
* Get the contents of the entry into the given gboolean.
*
* Returns: TRUE is the value could be fetched. FALSE if the
- * entry is not of given type.
+ * entry is not of given type or did not exist.
*/
gboolean
gst_props_entry_get_boolean (const GstPropsEntry *entry, gboolean *val)
* Get the contents of the entry into the given gchar*.
*
* Returns: TRUE is the value could be fetched. FALSE if the
- * entry is not of given type.
+ * entry is not of given type or did not exist.
*/
gboolean
gst_props_entry_get_string (const GstPropsEntry *entry, const gchar **val)
* Get the contents of the entry into the given gints.
*
* Returns: TRUE is the value could be fetched. FALSE if the
- * entry is not of given type.
+ * entry is not of given type or did not exist.
*/
gboolean
gst_props_entry_get_int_range (const GstPropsEntry *entry, gint *min, gint *max)
* Get the contents of the entry into the given gfloats.
*
* Returns: TRUE is the value could be fetched. FALSE if the
- * entry is not of given type.
+ * entry is not of given type or did not exist.
*/
gboolean
gst_props_entry_get_float_range (const GstPropsEntry *entry, gfloat *min, gfloat *max)
* Get the contents of the entry into the given GList.
*
* Returns: TRUE is the value could be fetched. FALSE if the
- * entry is not of given type.
+ * entry is not of given type or did not exist.
*/
gboolean
gst_props_entry_get_list (const GstPropsEntry *entry, const GList **val)
if (intersectentry) {
if (intersectentry->propstype == GST_PROPS_LIST_TYPE) {
intersection = g_list_concat (intersection,
- g_list_copy (intersectentry->data.list_data.entries));
+ intersectentry->data.list_data.entries);
/* set the list to NULL because the entries are concatenated to the above
* list and we don't want to free them */
intersectentry->data.list_data.entries = NULL;
result->propstype = GST_PROPS_LIST_TYPE;
result->data.list_data.entries = NULL;
while (entries) {
- GstPropsEntry * this = (GstPropsEntry *)entries->data;
+ GstPropsEntry *this = (GstPropsEntry *)entries->data;
if (this->propstype != GST_PROPS_INT_TYPE) {
/* no hope, this list doesn't even contain ints! */
gst_props_entry_destroy (result);
break;
}
if (this->data.int_data >= entry1->data.int_range_data.min &&
- this->data.int_data <= entry1->data.int_range_data.max) {
- result->data.list_data.entries = g_list_append (result->data.list_data.entries,
- gst_props_entry_copy (this));
+ this->data.int_data <= entry1->data.int_range_data.max)
+ {
+ /* prepend and reverse at the end */
+ result->data.list_data.entries = g_list_prepend (result->data.list_data.entries,
+ gst_props_entry_copy (this));
}
entries = g_list_next (entries);
}
+ if (result) {
+ result->data.list_data.entries = g_list_reverse (result->data.list_data.entries);
+ }
break;
}
case GST_PROPS_INT_TYPE:
{
if (entry1->data.int_range_data.min <= entry2->data.int_data &&
- entry1->data.int_range_data.max >= entry2->data.int_data) {
+ entry1->data.int_range_data.max >= entry2->data.int_data)
+ {
result = gst_props_entry_copy (entry2);
}
break;
}
case GST_PROPS_FLOAT_TYPE:
if (entry1->data.float_range_data.min <= entry2->data.float_data &&
- entry1->data.float_range_data.max >= entry2->data.float_data) {
+ entry1->data.float_range_data.max >= entry2->data.float_data)
+ {
result = gst_props_entry_copy (entry2);
}
default:
return result;
}
+/* when running over the entries in sorted order we can
+ * optimize addition with _prepend and a reverse at the end */
+#define gst_props_entry_add_sorted_prepend(props, entry) \
+G_STMT_START { \
+ /* avoid double evaluation of input */ \
+ GstPropsEntry *toadd = (entry); \
+ if (GST_PROPS_ENTRY_IS_VARIABLE (toadd)) \
+ GST_PROPS_FLAG_UNSET ((props), GST_PROPS_FIXED); \
+ props->properties = g_list_prepend ((props)->properties, toadd); \
+} G_STMT_END
+
/**
* gst_props_intersect:
* @props1: a property
* Calculates the intersection bewteen two GstProps.
*
* Returns: a GstProps with the intersection or NULL if the
- * intersection is empty.
+ * intersection is empty. The new GstProps is floating and must
+ * be unreffed afetr use.
*/
GstProps*
gst_props_intersect (GstProps *props1, GstProps *props2)
GList *leftovers;
GstPropsEntry *iprops = NULL;
- intersection = gst_props_empty_new ();
- intersection->fixed = TRUE;
-
g_return_val_if_fail (props1 != NULL, NULL);
g_return_val_if_fail (props2 != NULL, NULL);
+
+ intersection = gst_props_empty_new ();
props1list = props1->properties;
props2list = props2->properties;
entry2 = (GstPropsEntry *)props2list->data;
while (entry1->propid < entry2->propid) {
- GstPropsEntry *toadd;
-
- /* FIXME: this needs more explanation;
- * I've had format "int" < format "int" ! */
- GST_DEBUG (GST_CAT_PROPERTIES, "source is more specific in \"%s\"",
- g_quark_to_string (entry1->propid));
-
- toadd = gst_props_entry_copy (entry1);
- if (GST_PROPS_ENTRY_IS_VARIABLE (toadd))
- intersection->fixed = FALSE;
-
- intersection->properties = g_list_prepend (intersection->properties, toadd);
+ gst_props_entry_add_sorted_prepend (intersection, gst_props_entry_copy (entry1));
props1list = g_list_next (props1list);
- if (props1list)
- entry1 = (GstPropsEntry *)props1list->data;
- else
+ if (!props1list)
goto end;
+
+ entry1 = (GstPropsEntry *)props1list->data;
}
while (entry1->propid > entry2->propid) {
- GstPropsEntry *toadd;
-
- toadd = gst_props_entry_copy (entry2);
- if (GST_PROPS_ENTRY_IS_VARIABLE (toadd))
- intersection->fixed = FALSE;
-
- intersection->properties = g_list_prepend (intersection->properties, toadd);
+ gst_props_entry_add_sorted_prepend (intersection, gst_props_entry_copy (entry2));
props2list = g_list_next (props2list);
- if (props2list)
- entry2 = (GstPropsEntry *)props2list->data;
- else
+ if (!props2list)
goto end;
+
+ entry2 = (GstPropsEntry *)props2list->data;
}
/* at this point we are talking about the same property */
iprops = gst_props_entry_intersect (entry1, entry2);
-
- if (iprops) {
- if (GST_PROPS_ENTRY_IS_VARIABLE (iprops))
- intersection->fixed = FALSE;
- intersection->properties = g_list_prepend (intersection->properties, iprops);
- }
- else {
+ if (!iprops) {
+ /* common properties did not intersect, intersection is empty */
gst_props_unref (intersection);
return NULL;
}
+ gst_props_entry_add_sorted_prepend (intersection, iprops);
+
props1list = g_list_next (props1list);
props2list = g_list_next (props2list);
}
end:
- /* at this point one of the lists could contain leftover properties */
- if (props1list)
- leftovers = props1list;
- else if (props2list)
+ /* at this point one of the lists could contain leftover properties, while
+ * the other one is NULL */
+ leftovers = props1list;
+ if (!leftovers)
leftovers = props2list;
- else
- leftovers = NULL;
while (leftovers) {
- GstPropsEntry *entry;
-
- entry = (GstPropsEntry *) leftovers->data;
- if (GST_PROPS_ENTRY_IS_VARIABLE (entry))
- intersection->fixed = FALSE;
- intersection->properties = g_list_prepend (intersection->properties, gst_props_entry_copy (entry));
-
+ gst_props_entry_add_sorted_prepend (intersection,
+ gst_props_entry_copy ((GstPropsEntry *) leftovers->data));
leftovers = g_list_next (leftovers);
}
* Unrolls all lists in the given GstProps. This is usefull if you
* want to loop over the props.
*
- * Returns: A GList with the unrolled props entries.
+ * Returns: A GList with the unrolled props entries. g_list_free
+ * after usage.
*/
GList*
gst_props_normalize (GstProps *props)
GstProps *newprops;
GList *lentry;
- newprops = gst_props_empty_new ();
- newprops->properties = gst_props_list_copy (props->properties);
+ /* FIXME fixed flags is probably messed up here */
+ newprops = gst_props_copy (props);
lentry = g_list_find_custom (newprops->properties, GINT_TO_POINTER (list_entry->propid), props_find_func);
if (lentry) {
- GList *new_list = NULL;
+ GList *new_list;
new_entry = (GstPropsEntry *) lentry->data;
memcpy (new_entry, list_entry, sizeof (GstPropsEntry));
result = g_list_concat (new_list, result);
}
else {
+ /* FIXME append or prepend */
result = g_list_append (result, newprops);
}
entries = g_list_next (entries);
}
if (!result) {
+ /* no result, create list with input props */
result = g_list_prepend (result, props);
}
else {
result = g_list_reverse (result);
- gst_props_unref (props);
}
return result;
}
entry->data.string_data.string = xmlGetProp (field, "value");
}
else {
- g_mutex_lock (_gst_props_entries_chunk_lock);
- g_mem_chunk_free (_gst_props_entries_chunk, entry);
- g_mutex_unlock (_gst_props_entries_chunk_lock);
+ gst_props_entry_destroy (entry);
entry = NULL;
}