Simplify properties which contain lists of integer and integer range entries to minimal combination of ints and range...

Original commit message from CVS:
Simplify properties which contain lists of integer and integer range
entries to minimal combination of ints and ranges that is equivalent.
eg, (1,2,3,7-12,13) becomes (1-3,7-13)

Don't bother with floats for the moment, though it would be easy to add
an equivalent, which would simplify overlapping ranges.
This commit is contained in:
Richard Boulton 2001-06-18 22:33:35 +00:00
parent 55746a46af
commit 5bac75942d

View file

@ -55,6 +55,9 @@ gst_props_debug_entry (GstPropsEntry *entry)
case GST_PROPS_INT_ID: case GST_PROPS_INT_ID:
GST_DEBUG (GST_CAT_PROPERTIES, "%d\n", entry->data.int_data); GST_DEBUG (GST_CAT_PROPERTIES, "%d\n", entry->data.int_data);
break; break;
case GST_PROPS_FLOAT_ID:
GST_DEBUG (GST_CAT_PROPERTIES, "%f\n", entry->data.float_data);
break;
case GST_PROPS_FOURCC_ID: case GST_PROPS_FOURCC_ID:
GST_DEBUG (GST_CAT_PROPERTIES, "%4.4s\n", (gchar*)&entry->data.fourcc_data); GST_DEBUG (GST_CAT_PROPERTIES, "%4.4s\n", (gchar*)&entry->data.fourcc_data);
break; break;
@ -68,6 +71,12 @@ gst_props_debug_entry (GstPropsEntry *entry)
GST_DEBUG (GST_CAT_PROPERTIES, "%d-%d\n", entry->data.int_range_data.min, GST_DEBUG (GST_CAT_PROPERTIES, "%d-%d\n", entry->data.int_range_data.min,
entry->data.int_range_data.max); entry->data.int_range_data.max);
break; break;
case GST_PROPS_FLOAT_RANGE_ID:
GST_DEBUG (GST_CAT_PROPERTIES, "%f-%f\n", entry->data.float_range_data.min,
entry->data.float_range_data.max);
break;
case GST_PROPS_LIST_ID:
GST_DEBUG (GST_CAT_PROPERTIES, "[list]\n");
default: default:
break; break;
} }
@ -151,6 +160,129 @@ gst_props_new (const gchar *firstname, ...)
va_end (var_args); va_end (var_args);
return props; return props;
}
/**
* gst_props_add_to_list:
* @entries: the existing list of entries
* @entry: the new entry to add to the list
*
* Add a property to a list of properties.
*
* Returns: a pointer to a list with the new entry added.
*/
static GList *
gst_props_add_to_list (GList * entries, GstPropsEntry *entry)
{
return g_list_prepend (entries, entry);
}
/**
* gst_props_merge_int_entries:
* @newentry: the new entry
* @oldentry: an old entry
*
* Tries to merge oldentry into newentry, if there is a simpler single entry which represents
*
* Assumes that the entries are either ints or int ranges.
*
* Returns: TRUE if the entries were merged, FALSE otherwise.
*/
static gboolean
gst_props_merge_int_entries(GstPropsEntry * newentry, GstPropsEntry * oldentry)
{
gint new_min, new_max, old_min, old_max;
gboolean can_merge = FALSE;
if (newentry->propstype == GST_PROPS_INT_ID) {
new_min = newentry->data.int_data;
new_max = newentry->data.int_data;
} else {
new_min = newentry->data.int_range_data.min;
new_max = newentry->data.int_range_data.max;
}
if (oldentry->propstype == GST_PROPS_INT_ID) {
old_min = oldentry->data.int_data;
old_max = oldentry->data.int_data;
} else {
old_min = oldentry->data.int_range_data.min;
old_max = oldentry->data.int_range_data.max;
}
// Put range which starts lower into (new_min, new_max)
if (old_min < new_min) {
gint tmp;
tmp = old_min;
old_min = new_min;
new_min = tmp;
tmp = old_max;
old_max = new_max;
new_max = tmp;
}
// new_min is min of either entry - second half of the following conditional
// is to avoid overflow problems.
if (new_max >= old_min - 1 && old_min - 1 < old_min) {
// ranges overlap, or are adjacent. Pick biggest maximum.
can_merge = TRUE;
if (old_max > new_max) new_max = old_max;
}
if (can_merge) {
if (new_min == new_max) {
newentry->propstype = GST_PROPS_INT_ID;
newentry->data.int_data = new_min;
} else {
newentry->propstype = GST_PROPS_INT_RANGE_ID;
newentry->data.int_range_data.min = new_min;
newentry->data.int_range_data.max = new_max;
}
}
return can_merge;
}
/**
* gst_props_add_to_int_list:
* @entries: the existing list of entries
* @entry: the new entry to add to the list
*
* Add an integer property to a list of properties, removing duplicates
* and merging ranges.
*
* Assumes that the existing list is in simplest form, contains
* only ints and int ranges, and that the new entry is an int or
* an int range.
*
* Returns: a pointer to a list with the new entry added.
*/
static GList *
gst_props_add_to_int_list (GList * entries, GstPropsEntry * newentry)
{
GList * i;
i = entries;
while (i) {
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);
entries = g_list_remove_link (entries, i);
g_list_free_1 (i);
// start again: it's possible that this change made an earlier entry
// mergeable, and the pointer is now invalid anyway.
i = entries;
}
i = g_list_next (i);
}
return gst_props_add_to_list (entries, newentry);
} }
/** /**
@ -170,6 +302,18 @@ gst_props_newv (const gchar *firstname, va_list var_args)
const gchar *prop_name; const gchar *prop_name;
GstPropsEntry *list_entry = NULL; 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;
@ -196,20 +340,40 @@ gst_props_newv (const gchar *firstname, va_list var_args)
switch (entry->propstype) { switch (entry->propstype) {
case GST_PROPS_INT_ID: case GST_PROPS_INT_ID:
case GST_PROPS_INT_RANGE_ID: case GST_PROPS_INT_RANGE_ID:
entry_type = GST_PROPS_LIST_T_INTS;
break;
case GST_PROPS_FLOAT_ID: case GST_PROPS_FLOAT_ID:
case GST_PROPS_FLOAT_RANGE_ID: case GST_PROPS_FLOAT_RANGE_ID:
entry_type = GST_PROPS_LIST_T_FLOATS;
break;
case GST_PROPS_FOURCC_ID: case GST_PROPS_FOURCC_ID:
case GST_PROPS_BOOL_ID: case GST_PROPS_BOOL_ID:
case GST_PROPS_STRING_ID: case GST_PROPS_STRING_ID:
entry_type = GST_PROPS_LIST_T_MISC;
break; break;
case GST_PROPS_LIST_ID: case GST_PROPS_LIST_ID:
g_return_val_if_fail (inlist == FALSE, NULL); g_return_val_if_fail (inlist == FALSE, NULL);
inlist = TRUE; inlist = TRUE;
list_entry = entry; list_entry = entry;
list_type = GST_PROPS_LIST_T_UNSET;
list_entry->data.list_data.entries = NULL; list_entry->data.list_data.entries = NULL;
break; break;
case GST_PROPS_END_ID: case GST_PROPS_END_ID:
g_return_val_if_fail (inlist == TRUE, NULL); 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;
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);
}
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);
inlist = FALSE; inlist = FALSE;
list_entry = NULL; list_entry = NULL;
prop_name = va_arg (var_args, gchar*); prop_name = va_arg (var_args, gchar*);
@ -223,7 +387,21 @@ gst_props_newv (const gchar *firstname, va_list var_args)
} }
if (inlist && (list_entry != entry)) { if (inlist && (list_entry != entry)) {
list_entry->data.list_data.entries = g_list_prepend (list_entry->data.list_data.entries, 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 =
gst_props_add_to_list (list_entry->data.list_data.entries, entry);
break;
}
}
} }
else { else {
props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func); props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
@ -621,6 +799,8 @@ gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry
{ {
GST_DEBUG (GST_CAT_PROPERTIES,"compare: %s %s\n", g_quark_to_string (entry1->propid), GST_DEBUG (GST_CAT_PROPERTIES,"compare: %s %s\n", g_quark_to_string (entry1->propid),
g_quark_to_string (entry2->propid)); g_quark_to_string (entry2->propid));
gst_props_debug_entry (entry1);
gst_props_debug_entry (entry2);
switch (entry1->propstype) { switch (entry1->propstype) {
case GST_PROPS_LIST_ID: case GST_PROPS_LIST_ID:
{ {