summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Kost <ensonic@users.sf.net>2010-12-21 23:03:12 +0200
committerTim-Philipp Müller <tim.muller@collabora.co.uk>2011-01-02 22:35:08 +0000
commit373be6f14ea8f548360dc565c6124c5368cc273c (patch)
treee5beba762c9fccd17e200a2ebf1a801e9b0d341b
parent655451db5462bc19f0a8289dc271f1ad2644af6b (diff)
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()
-rw-r--r--docs/gst/gstreamer-sections.txt1
-rw-r--r--gst/gsttaglist.c4
-rw-r--r--gst/gstvalue.c92
-rw-r--r--gst/gstvalue.h3
-rw-r--r--win32/common/libgstreamer.def1
5 files changed, 99 insertions, 2 deletions
diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt
index 6aab4f750a..03ecc96408 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 0e4fdc6b46..06ae247c86 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 f03ebf89d2..84a4405595 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 9e921715e8..5de7449cd5 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 4075d1abfa..8f5055a6e5 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