? Makefile.am.diff
? events.patch
? gst_caps_merge.diff
? gstxml.patch
? install.log
? make.log
? reentrant.patch
? gst/.gst.c.marks
? gst/.gstcaps.c.marks
? gst/.gstvalue.c.marks
? gst/gstxml.new.c
? gst/gstxml.new.h
? gst/noindex.diff
? tools/gst-launch.new.c
Index: docs/gst/gstreamer-sections.txt
===================================================================
RCS file: /cvs/gstreamer/gstreamer/docs/gst/gstreamer-sections.txt,v
retrieving revision 1.271
diff -u -r1.271 gstreamer-sections.txt
--- docs/gst/gstreamer-sections.txt	21 Aug 2006 14:54:31 -0000	1.271
+++ docs/gst/gstreamer-sections.txt	23 Aug 2006 18:40:21 -0000
@@ -223,6 +223,7 @@
 gst_caps_merge
 gst_caps_append_structure
 gst_caps_remove_structure
+gst_caps_merge_structure
 gst_caps_get_size
 gst_caps_get_structure
 gst_caps_set_simple
Index: gst/gstcaps.c
===================================================================
RCS file: /cvs/gstreamer/gstreamer/gst/gstcaps.c,v
retrieving revision 1.170
diff -u -r1.170 gstcaps.c
--- gst/gstcaps.c	21 Aug 2006 14:54:31 -0000	1.170
+++ gst/gstcaps.c	23 Aug 2006 18:40:22 -0000
@@ -480,6 +480,74 @@
   return FALSE;
 }
 
+static gboolean
+gst_caps_structure_is_subset_field (GQuark field_id, const GValue * value,
+    gpointer user_data)
+{
+  GstStructure *subtract_from = user_data;
+  GValue subtraction = { 0, };
+  const GValue *other;
+  gint res;
+
+  other = gst_structure_id_get_value (subtract_from, field_id);
+  if (!other) {
+    /* field is missing in one set */
+    return FALSE;
+  }
+  /*{
+    gchar *str = g_strdup_value_contents (value);
+    GST_DEBUG ("    value: '%s'", str);
+    g_free (str);
+    str  = g_strdup_value_contents (other);
+    GST_DEBUG ("    other: '%s'", str);
+    g_free (str);
+  }*/
+  /*
+  [1,2] - 1 = 2
+  1 - [1,2] = ø   ???
+  */
+  if (!gst_value_subtract (&subtraction, other, value)) {
+    /* empty result -> values are the same, or first was a value and
+     * second was a list
+     */
+    /* verify that result is empty by swapping args */
+    if (!gst_value_subtract (&subtraction, value, other)) {
+      /*GST_DEBUG ("  values are the same");*/
+      return TRUE;
+    }
+    g_value_unset (&subtraction);
+    return FALSE;
+  }
+  /*{
+    gchar *str = g_strdup_value_contents (&subtraction);
+    GST_DEBUG ("    diff: '%s'", str);
+    g_free (str);
+  }*/
+  res = gst_value_compare (&subtraction, other);
+  if (res == GST_VALUE_EQUAL) {
+    /* value was empty ? */
+    g_value_unset (&subtraction);
+    /*GST_DEBUG ("  compare = equal (%d)",res);*/
+    return FALSE;
+  } else {
+    /*GST_DEBUG ("  compare = unequal/unordered (%d)",res);*/
+    return TRUE;
+  }
+}
+
+static gboolean
+gst_caps_structure_is_subset (const GstStructure * minuend,
+    const GstStructure * subtrahend)
+{
+  if ((minuend->name != subtrahend->name) ||
+      (gst_structure_n_fields (minuend) != gst_structure_n_fields (subtrahend))) {
+    return FALSE;
+  }
+  
+  return gst_structure_foreach ((GstStructure *) subtrahend,
+      gst_caps_structure_is_subset_field, (gpointer)minuend);
+}
+
 /**
  * gst_caps_append:
  * @caps1: the #GstCaps that will be appended to
@@ -526,9 +594,9 @@
  * @caps1: the #GstCaps that will take the new entries
  * @caps2: the #GstCaps to merge in
  *
- * Appends the structures contained in @caps2 to @caps1 if they are not yet in
- * @caps1. The structures in @caps2 are not copied -- they are transferred to
- * @caps1, and then @caps2 is freed.
+ * Appends the structures contained in @caps2 to @caps1 if they are not yet
+ * expressed by @caps1. The structures in @caps2 are not copied -- they are
+ * transferred to @caps1, and then @caps2 is freed.
  * If either caps is ANY, the resulting caps will be ANY.
  */
 void
@@ -545,23 +613,33 @@
 #ifdef USE_POISONING
   CAPS_POISON (caps2);
 #endif
-  if (gst_caps_is_any (caps1) || gst_caps_is_any (caps2)) {
-    /* FIXME: this leaks */
-    caps1->flags |= GST_CAPS_FLAGS_ANY;
+  if (gst_caps_is_any (caps1)) {
     for (i = caps2->structs->len - 1; i >= 0; i--) {
-      structure = gst_caps_remove_and_get_structure (caps2, i);
+      structure = gst_caps_remove_and_get_structure (caps2, 0);
+      gst_structure_free (structure);
+    }
+  } else if (gst_caps_is_any (caps2)) {
+    caps1->flags |= GST_CAPS_FLAGS_ANY;
+    for (i = caps1->structs->len - 1; i >= 0; i--) {
+      structure = gst_caps_remove_and_get_structure (caps1, 0);
       gst_structure_free (structure);
     }
   } else {
+    int len = caps2->structs->len;
+
+    for (i = 0; i < len; i++) {
+      structure = gst_caps_remove_and_get_structure (caps2, 0);
+      gst_caps_merge_structure (caps1, structure);
+    }
+    /* this is too naive
     GstCaps *com = gst_caps_intersect (caps1, caps2);
     GstCaps *add = gst_caps_subtract (caps2, com);
 
-    /*
-       GST_DEBUG ("common : %d", gst_caps_get_size (com));
-       GST_DEBUG ("adding : %d", gst_caps_get_size (add));
-     */
+    GST_DEBUG ("common : %d", gst_caps_get_size (com));
+    GST_DEBUG ("adding : %d", gst_caps_get_size (add));
     gst_caps_append (caps1, add);
     gst_caps_unref (com);
+    */
   }
   gst_caps_unref (caps2);       /* guaranteed to free it */
 }
@@ -614,6 +692,52 @@
 }
 
 /**
+ * gst_caps_merge_structure:
+ * @caps: the #GstCaps that will the the new structure
+ * @structure: the #GstStructure to merge
+ *
+ * Appends @structure to @caps if its not already expressed by @caps.  The
+ * structure is not copied; @caps becomes the owner of @structure.
+ */
+void
+gst_caps_merge_structure (GstCaps * caps, GstStructure * structure2)
+{
+  g_return_if_fail (GST_IS_CAPS (caps));
+  g_return_if_fail (IS_WRITABLE (caps));
+
+  if (G_LIKELY (structure2)) {
+    GstStructure * structure1;
+    int i;
+    gboolean unique=TRUE;
+    
+    g_return_if_fail (structure2->parent_refcount == NULL);
+#if 0
+#ifdef USE_POISONING
+    STRUCTURE_POISON (structure2);
+#endif
+#endif
+    /*GST_DEBUG ("merge ?: %" GST_PTR_FORMAT, structure2);*/
+    /* check each structure */
+    for (i = caps->structs->len - 1; i >= 0; i--) {
+      structure1 = gst_caps_get_structure (caps, i);
+      /*GST_DEBUG ("  with: %" GST_PTR_FORMAT, structure1);*/
+      /* if structure2 is a subset of structure1, then skip it */
+      if (gst_caps_structure_is_subset (structure1, structure2)) {
+	/*GST_DEBUG ("  no");*/
+	unique=FALSE;
+	break;
+      }
+    }
+    if(unique) {
+      /*GST_DEBUG ("  yes");*/
+      gst_structure_set_parent_refcount (structure2, &caps->refcount);
+      g_ptr_array_add (caps->structs, structure2);
+    }
+  }
+}
+
+
+/**
  * gst_caps_get_size:
  * @caps: a #GstCaps
  *
Index: gst/gstcaps.h
===================================================================
RCS file: /cvs/gstreamer/gstreamer/gst/gstcaps.h,v
retrieving revision 1.102
diff -u -r1.102 gstcaps.h
--- gst/gstcaps.h	21 Aug 2006 14:54:31 -0000	1.102
+++ gst/gstcaps.h	23 Aug 2006 18:40:22 -0000
@@ -199,6 +199,8 @@
 void              gst_caps_append_structure        (GstCaps       *caps,
 						 GstStructure  *structure);
 void              gst_caps_remove_structure        (GstCaps * caps, guint idx);
+void              gst_caps_merge_structure         (GstCaps * caps1,
+                                                    GstStructure * structure2);
 guint             gst_caps_get_size                (const GstCaps *caps);
 GstStructure *    gst_caps_get_structure           (const GstCaps *caps,
 						 guint          index);
Index: libs/gst/base/gstbasetransform.c
===================================================================
RCS file: /cvs/gstreamer/gstreamer/libs/gst/base/gstbasetransform.c,v
retrieving revision 1.88
diff -u -r1.88 gstbasetransform.c
--- libs/gst/base/gstbasetransform.c	21 Aug 2006 14:54:31 -0000	1.88
+++ libs/gst/base/gstbasetransform.c	23 Aug 2006 18:40:24 -0000
@@ -453,10 +453,11 @@
         gst_caps_unref (nth);
         GST_DEBUG_OBJECT (trans, "  to[%d]: %" GST_PTR_FORMAT, i, temp);
 
-        /* FIXME: here we need to only append those structures, that are not yet
-         * in there */
         temp = gst_caps_make_writable (temp);
-        /*gst_caps_append (ret, temp); */
+        /* FIXME: here we need to only append those structures, that are not yet
+         * in there
+         * gst_caps_append (ret, temp);
+	 */
         gst_caps_merge (ret, temp);
       }
       GST_DEBUG_OBJECT (trans, "merged: (%d)", gst_caps_get_size (ret));
Index: tests/check/gst/gstcaps.c
===================================================================
RCS file: /cvs/gstreamer/gstreamer/tests/check/gst/gstcaps.c,v
retrieving revision 1.16
diff -u -r1.16 gstcaps.c
--- tests/check/gst/gstcaps.c	2 Jul 2006 12:57:19 -0000	1.16
+++ tests/check/gst/gstcaps.c	23 Aug 2006 18:40:24 -0000
@@ -348,6 +348,95 @@
 
 GST_END_TEST;
 
+GST_START_TEST (test_merge_fundamental)
+{
+  GstCaps *c1, *c2;
+
+  /* ANY + specific = ANY */
+  c1 = gst_caps_from_string ("audio/x-raw-int,rate=44100");
+  c2 = gst_caps_new_any ();
+  gst_caps_merge (c2, c1);
+  GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
+  fail_unless (gst_caps_get_size (c2) == 0, NULL);
+  fail_unless (gst_caps_is_any (c2), NULL);
+  gst_caps_unref (c2);
+
+  /* specific + ANY = ANY */
+  c2 = gst_caps_from_string ("audio/x-raw-int,rate=44100");
+  c1 = gst_caps_new_any ();
+  gst_caps_merge (c2, c1);
+  GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
+  fail_unless (gst_caps_get_size (c2) == 0, NULL);
+  fail_unless (gst_caps_is_any (c2), NULL);
+  gst_caps_unref (c2);
+  
+  /* EMPTY + specific = specific */
+  c1 = gst_caps_from_string ("audio/x-raw-int,rate=44100");
+  c2 = gst_caps_new_empty ();
+  gst_caps_merge (c2, c1);
+  GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
+  fail_unless (gst_caps_get_size (c2) == 1, NULL);
+  fail_if (gst_caps_is_empty (c2), NULL);
+  gst_caps_unref (c2);
+
+  /* specific + EMPTY = specific */
+  c2 = gst_caps_from_string ("audio/x-raw-int,rate=44100");
+  c1 = gst_caps_new_empty ();
+  gst_caps_merge (c2, c1);
+  GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
+  fail_unless (gst_caps_get_size (c2) == 1, NULL);
+  fail_if (gst_caps_is_empty (c2), NULL);
+  gst_caps_unref (c2);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_merge_same)
+{
+  GstCaps *c1, *c2;
+
+  /* this is the same */
+  c1 = gst_caps_from_string ("audio/x-raw-int,rate=44100,channels=1");
+  c2 = gst_caps_from_string ("audio/x-raw-int,rate=44100,channels=1");
+  gst_caps_merge (c2, c1);
+  GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
+  fail_unless (gst_caps_get_size (c2) == 1, NULL);
+  
+  /* and so is this */
+  c1 = gst_caps_from_string ("audio/x-raw-int,rate=44100,channels=1");
+  c2 = gst_caps_from_string ("audio/x-raw-int,channels=1,rate=44100");
+  gst_caps_merge (c2, c1);
+  GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
+  fail_unless (gst_caps_get_size (c2) == 1, NULL);
+
+  gst_caps_unref (c2);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_merge_subset)
+{
+  GstCaps *c1, *c2;
+
+  /* the 2nd is already covered */
+  c2 = gst_caps_from_string ("audio/x-raw-int,channels=[1,2]");
+  c1 = gst_caps_from_string ("audio/x-raw-int,channels=1");
+  gst_caps_merge (c2, c1);
+  GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
+  fail_unless (gst_caps_get_size (c2) == 1, NULL);
+  
+  /* here it is not */
+  c2 = gst_caps_from_string ("audio/x-raw-int,channels=1,rate=44100");
+  c1 = gst_caps_from_string ("audio/x-raw-int,channels=[1,2],rate=44100");
+  gst_caps_merge (c2, c1);
+  GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
+  fail_unless (gst_caps_get_size (c2) == 2, NULL);
+
+  gst_caps_unref (c2);
+}
+
+GST_END_TEST;
+
 
 Suite *
 gst_caps_suite (void)
@@ -363,6 +452,9 @@
   tcase_add_test (tc_chain, test_static_caps);
   tcase_add_test (tc_chain, test_simplify);
   tcase_add_test (tc_chain, test_truncate);
+  tcase_add_test (tc_chain, test_merge_fundamental);
+  tcase_add_test (tc_chain, test_merge_same);
+  tcase_add_test (tc_chain, test_merge_subset);
 
   return s;
 }
