tags: don't produce duplicated entries when merging same value twice

Add a variant of gst_value_list_concat() that skips duplicates and use that when
merging taglists.

API: gst_value_list_merge()
This commit is contained in:
Stefan Kost 2010-12-21 23:03:12 +02:00 committed by Tim-Philipp Müller
parent 655451db54
commit 373be6f14e
5 changed files with 99 additions and 2 deletions

View file

@ -2717,6 +2717,7 @@ GST_TYPE_ARRAY
gst_value_list_append_value
gst_value_list_prepend_value
gst_value_list_concat
gst_value_list_merge
gst_value_list_get_size
gst_value_list_get_value

View file

@ -755,12 +755,12 @@ gst_tag_list_add_value_internal (GstStructure * list, GstTagMergeMode mode,
gst_structure_id_set_value (list, tag, value);
break;
case GST_TAG_MERGE_PREPEND:
gst_value_list_concat (&dest, value, value2);
gst_value_list_merge (&dest, value, value2);
gst_structure_id_set_value (list, tag, &dest);
g_value_unset (&dest);
break;
case GST_TAG_MERGE_APPEND:
gst_value_list_concat (&dest, value2, value);
gst_value_list_merge (&dest, value2, value);
gst_structure_id_set_value (list, tag, &dest);
g_value_unset (&dest);
break;

View file

@ -384,6 +384,98 @@ gst_value_list_concat (GValue * dest, const GValue * value1,
}
}
/**
* gst_value_list_merge:
* @dest: (out caller-allocates): an uninitialized #GValue to take the result
* @value1: a #GValue
* @value2: a #GValue
*
* Merges copies of @value1 and @value2 into a list. Values that are not
* of type #GST_TYPE_LIST are treated as if they were lists of length 1.
* @dest will be initialized to the type #GST_TYPE_LIST.
*
* The resulting list won't have duplicated values.
*/
void
gst_value_list_merge (GValue * dest, const GValue * value1,
const GValue * value2)
{
guint i, j, k, value1_length, value2_length, skipped;
const GValue *src;
gboolean skip;
GArray *array;
g_return_if_fail (dest != NULL);
g_return_if_fail (G_VALUE_TYPE (dest) == 0);
g_return_if_fail (G_IS_VALUE (value1));
g_return_if_fail (G_IS_VALUE (value2));
value1_length =
(GST_VALUE_HOLDS_LIST (value1) ? VALUE_LIST_SIZE (value1) : 1);
value2_length =
(GST_VALUE_HOLDS_LIST (value2) ? VALUE_LIST_SIZE (value2) : 1);
g_value_init (dest, GST_TYPE_LIST);
array = (GArray *) dest->data[0].v_pointer;
g_array_set_size (array, value1_length + value2_length);
if (GST_VALUE_HOLDS_LIST (value1)) {
for (i = 0; i < value1_length; i++) {
gst_value_init_and_copy (&g_array_index (array, GValue, i),
VALUE_LIST_GET_VALUE (value1, i));
}
} else {
gst_value_init_and_copy (&g_array_index (array, GValue, 0), value1);
}
j = value1_length;
skipped = 0;
if (GST_VALUE_HOLDS_LIST (value2)) {
for (i = 0; i < value2_length; i++) {
skip = FALSE;
src = VALUE_LIST_GET_VALUE (value2, i);
for (k = 0; k < value1_length; k++) {
if (gst_value_compare (&g_array_index (array, GValue, k),
src) == GST_VALUE_EQUAL) {
skip = TRUE;
skipped++;
break;
}
}
if (!skip) {
gst_value_init_and_copy (&g_array_index (array, GValue, j), src);
j++;
}
}
} else {
skip = FALSE;
for (k = 0; k < value1_length; k++) {
if (gst_value_compare (&g_array_index (array, GValue, k),
value2) == GST_VALUE_EQUAL) {
skip = TRUE;
skipped++;
break;
}
}
if (!skip) {
gst_value_init_and_copy (&g_array_index (array, GValue, j), value2);
}
}
if (skipped) {
guint new_size = value1_length + (value2_length - skipped);
if (new_size > 1) {
/* shrink list */
g_array_set_size (array, new_size);
} else {
GValue *tmp = dest;
/* turn into single value */
gst_value_init_and_copy (dest, &g_array_index (array, GValue, 0));
g_value_unset (tmp);
}
}
}
/**
* gst_value_list_get_size:
* @value: a #GValue of type #GST_TYPE_LIST

View file

@ -466,6 +466,9 @@ void gst_value_list_prepend_value (GValue *value,
void gst_value_list_concat (GValue *dest,
const GValue *value1,
const GValue *value2);
void gst_value_list_merge (GValue *dest,
const GValue *value1,
const GValue *value2);
guint gst_value_list_get_size (const GValue *value);
G_CONST_RETURN GValue *
gst_value_list_get_value (const GValue *value,

View file

@ -1164,6 +1164,7 @@ EXPORTS
gst_value_list_get_size
gst_value_list_get_type
gst_value_list_get_value
gst_value_list_merge
gst_value_list_prepend_value
gst_value_register
gst_value_register_intersect_func