From 373be6f14ea8f548360dc565c6124c5368cc273c Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Tue, 21 Dec 2010 23:03:12 +0200 Subject: [PATCH] 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() --- docs/gst/gstreamer-sections.txt | 1 + gst/gsttaglist.c | 4 +- gst/gstvalue.c | 92 +++++++++++++++++++++++++++++++++++++++++ gst/gstvalue.h | 3 ++ win32/common/libgstreamer.def | 1 + 5 files changed, 99 insertions(+), 2 deletions(-) diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index 6aab4f7..03ecc96 100644 --- a/docs/gst/gstreamer-sections.txt +++ b/docs/gst/gstreamer-sections.txt @@ -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 diff --git a/gst/gsttaglist.c b/gst/gsttaglist.c index 0e4fdc6..06ae247 100644 --- a/gst/gsttaglist.c +++ b/gst/gsttaglist.c @@ -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; diff --git a/gst/gstvalue.c b/gst/gstvalue.c index f03ebf8..84a4405 100644 --- a/gst/gstvalue.c +++ b/gst/gstvalue.c @@ -385,6 +385,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 * diff --git a/gst/gstvalue.h b/gst/gstvalue.h index 9e92171..5de7449 100644 --- a/gst/gstvalue.h +++ b/gst/gstvalue.h @@ -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, diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index 4075d1a..8f5055a 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -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 -- 2.7.4