gst/gstcaps.c: check for ANY caps before appending/unioning
authorBenjamin Otte <otte@gnome.org>
Wed, 21 Apr 2004 03:25:13 +0000 (03:25 +0000)
committerBenjamin Otte <otte@gnome.org>
Wed, 21 Apr 2004 03:25:13 +0000 (03:25 +0000)
Original commit message from CVS:
* gst/gstcaps.c: (gst_caps_append), (gst_caps_union):
check for ANY caps before appending/unioning
* gst/gstcaps.c: (gst_caps_is_subset),
(gst_caps_is_equal), (gst_caps_structure_subtract_field),
(gst_caps_structure_subtract), (gst_caps_subtract):
* gst/gstcaps.h:
add gst_caps_is_equal, gst_caps_is_subset and gst_caps_subtract to
the API. deprecate gst_caps_is_equal_fixed
* gst/gstpad.c: (gst_pad_try_set_caps):
* gst/gstqueue.c: (gst_queue_link):
s/gst_caps_is_equal_fixed/gst_caps_is_equal/
* gst/gststructure.c: (gst_structure_get_name_id):
* gst/gststructure.h:
add function gst_structure_get_name_id
* gst/gstvalue.c: (gst_value_subtract_int_int_range),
(gst_value_create_new_range), (gst_value_subtract_int_range_int),
(gst_value_subtract_int_range_int_range),
(gst_value_subtract_double_double_range),
(gst_value_subtract_double_range_double),
(gst_value_subtract_double_range_double_range),
(gst_value_subtract_from_list), (gst_value_subtract_list),
(gst_value_can_intersect), (gst_value_subtract),
(gst_value_can_subtract), (gst_value_register_subtract_func),
(_gst_value_initialize):
* gst/gstvalue.h:
add support for subtracting values from each other. Note that
subtracting means subtracting as in set theory. Required for caps
stuff above.
* testsuite/caps/.cvsignore:
* testsuite/caps/Makefile.am:
* testsuite/caps/erathostenes.c: (erathostenes), (main):
* testsuite/caps/sets.c: (check_caps), (main):
* testsuite/caps/subtract.c: (check_caps), (main):
add tests for subtraction and equality code.

20 files changed:
ChangeLog
gst/gstcaps.c
gst/gstcaps.h
gst/gstpad.c
gst/gstqueue.c
gst/gststructure.c
gst/gststructure.h
gst/gstvalue.c
gst/gstvalue.h
plugins/elements/gstqueue.c
tests/old/testsuite/caps/.gitignore
tests/old/testsuite/caps/Makefile.am
tests/old/testsuite/caps/erathostenes.c [new file with mode: 0644]
tests/old/testsuite/caps/sets.c [new file with mode: 0644]
tests/old/testsuite/caps/subtract.c [new file with mode: 0644]
testsuite/caps/.gitignore
testsuite/caps/Makefile.am
testsuite/caps/erathostenes.c [new file with mode: 0644]
testsuite/caps/sets.c [new file with mode: 0644]
testsuite/caps/subtract.c [new file with mode: 0644]

index 0ea88f4..1c7dc48 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,40 @@
+2004-04-21  Benjamin Otte  <otte@gnome.org>
+
+       * gst/gstcaps.c: (gst_caps_append), (gst_caps_union):
+         check for ANY caps before appending/unioning
+       * gst/gstcaps.c: (gst_caps_is_subset),
+       (gst_caps_is_equal), (gst_caps_structure_subtract_field),
+       (gst_caps_structure_subtract), (gst_caps_subtract):
+       * gst/gstcaps.h:
+         add gst_caps_is_equal, gst_caps_is_subset and gst_caps_subtract to
+         the API. deprecate gst_caps_is_equal_fixed
+       * gst/gstpad.c: (gst_pad_try_set_caps):
+       * gst/gstqueue.c: (gst_queue_link):
+         s/gst_caps_is_equal_fixed/gst_caps_is_equal/
+       * gst/gststructure.c: (gst_structure_get_name_id):
+       * gst/gststructure.h:
+         add function gst_structure_get_name_id
+       * gst/gstvalue.c: (gst_value_subtract_int_int_range),
+       (gst_value_create_new_range), (gst_value_subtract_int_range_int),
+       (gst_value_subtract_int_range_int_range),
+       (gst_value_subtract_double_double_range),
+       (gst_value_subtract_double_range_double),
+       (gst_value_subtract_double_range_double_range),
+       (gst_value_subtract_from_list), (gst_value_subtract_list),
+       (gst_value_can_intersect), (gst_value_subtract),
+       (gst_value_can_subtract), (gst_value_register_subtract_func),
+       (_gst_value_initialize):
+       * gst/gstvalue.h:
+         add support for subtracting values from each other. Note that
+         subtracting means subtracting as in set theory. Required for caps
+         stuff above.
+       * testsuite/caps/.cvsignore:
+       * testsuite/caps/Makefile.am:
+       * testsuite/caps/erathostenes.c: (erathostenes), (main):
+       * testsuite/caps/sets.c: (check_caps), (main):
+       * testsuite/caps/subtract.c: (check_caps), (main):
+         add tests for subtraction and equality code.
+
 2004-04-20  David Schleef  <ds@schleef.org>
 
        * gst/autoplug/Makefile.am:  Fix some little buglets in last checkin.
index b5cef4a..c1ebb59 100644 (file)
@@ -295,9 +295,17 @@ gst_caps_append (GstCaps * caps1, GstCaps * caps2)
 #ifdef USE_POISONING
   CAPS_POISON (caps2);
 #endif
-  for (i = 0; i < caps2->structs->len; i++) {
-    structure = gst_caps_get_structure (caps2, i);
-    gst_caps_append_structure (caps1, structure);
+  if (gst_caps_is_any (caps1) || gst_caps_is_any (caps2)) {
+    caps1->flags |= GST_CAPS_FLAGS_ANY;
+    for (i = 0; i < caps2->structs->len; i++) {
+      structure = gst_caps_get_structure (caps2, i);
+      gst_structure_remove_all_fields (structure);
+    }
+  } else {
+    for (i = 0; i < caps2->structs->len; i++) {
+      structure = gst_caps_get_structure (caps2, i);
+      gst_caps_append_structure (caps1, structure);
+    }
   }
   g_ptr_array_free (caps2->structs, TRUE);
 #ifdef USE_POISONING
@@ -690,6 +698,38 @@ gst_caps_is_always_compatible (const GstCaps * caps1, const GstCaps * caps2)
   return FALSE;
 }
 
+gboolean
+gst_caps_is_subset (const GstCaps * subset, const GstCaps * superset)
+{
+  GstCaps *caps;
+  gboolean ret;
+
+  g_return_val_if_fail (subset != NULL, FALSE);
+  g_return_val_if_fail (superset != NULL, FALSE);
+
+  if (gst_caps_is_empty (subset) || gst_caps_is_any (superset))
+    return TRUE;
+  if (gst_caps_is_any (subset) || gst_caps_is_empty (superset))
+    return FALSE;
+
+  caps = gst_caps_subtract (subset, superset);
+  ret = gst_caps_is_empty (caps);
+  gst_caps_free (caps);
+  return ret;
+}
+
+gboolean
+gst_caps_is_equal (const GstCaps * caps1, const GstCaps * caps2)
+{
+  g_return_val_if_fail (caps1 != NULL, FALSE);
+  g_return_val_if_fail (caps2 != NULL, FALSE);
+
+  if (gst_caps_is_fixed (caps1) && gst_caps_is_fixed (caps2))
+    return gst_caps_is_equal_fixed (caps1, caps2);
+
+  return gst_caps_is_subset (caps1, caps2) && gst_caps_is_subset (caps2, caps1);
+}
+
 typedef struct
 {
   GstStructure *dest;
@@ -849,6 +889,95 @@ gst_caps_intersect (const GstCaps * caps1, const GstCaps * caps2)
 #endif
 }
 
+typedef struct
+{
+  const GstStructure *subtract_from;
+  GstCaps *put_into;
+}
+SubtractionEntry;
+
+
+gboolean
+gst_caps_structure_subtract_field (GQuark field_id, GValue * value,
+    gpointer user_data)
+{
+  SubtractionEntry *e = user_data;
+  GValue subtraction = { 0, };
+  const GValue *other;
+  GstStructure *structure;
+
+  other = gst_structure_id_get_value (e->subtract_from, field_id);
+  if (!other)
+    return TRUE;
+  if (!gst_value_subtract (&subtraction, other, value))
+    return TRUE;
+  structure = gst_structure_copy (e->subtract_from);
+  if (gst_value_compare (&subtraction, other) == GST_VALUE_EQUAL) {
+    gst_caps_append_structure (e->put_into, structure);
+    return FALSE;
+  } else {
+    gst_structure_id_set_value (structure, field_id, &subtraction);
+    g_value_unset (&subtraction);
+    gst_caps_append_structure (e->put_into, structure);
+    return TRUE;
+  }
+}
+
+static void
+gst_caps_structure_subtract (GstCaps * into, const GstStructure * minuend,
+    const GstStructure * subtrahend)
+{
+  SubtractionEntry e;
+
+  e.subtract_from = minuend;
+  e.put_into = into;
+
+  gst_structure_foreach ((GstStructure *) subtrahend,
+      gst_caps_structure_subtract_field, &e);
+}
+
+GstCaps *
+gst_caps_subtract (const GstCaps * minuend, const GstCaps * subtrahend)
+{
+  int i, j;
+  GstStructure *min;
+  GstStructure *sub;
+  GstCaps *dest = NULL, *src;
+
+  g_return_val_if_fail (minuend != NULL, NULL);
+  /* what would that be ? */
+  g_return_val_if_fail (!gst_caps_is_any (minuend), NULL);
+  g_return_val_if_fail (subtrahend != NULL, NULL);
+
+  if (gst_caps_is_empty (minuend) || gst_caps_is_any (subtrahend)) {
+    return gst_caps_new_empty ();
+  }
+  if (gst_caps_is_empty (subtrahend))
+    return gst_caps_copy (minuend);
+
+  src = gst_caps_copy (minuend);
+  for (i = 0; i < subtrahend->structs->len; i++) {
+    sub = gst_caps_get_structure (subtrahend, i);
+    if (dest) {
+      gst_caps_free (src);
+      src = dest;
+    }
+    dest = gst_caps_new_empty ();
+    for (j = 0; j < src->structs->len; j++) {
+      min = gst_caps_get_structure (src, j);
+      if (gst_structure_get_name_id (min) == gst_structure_get_name_id (sub)) {
+        gst_caps_structure_subtract (dest, min, sub);
+      } else {
+        gst_caps_append_structure (dest, gst_structure_copy (min));
+      }
+    }
+    if (gst_caps_is_empty (dest))
+      return dest;
+  }
+
+  return dest;
+}
+
 /**
  * gst_caps_union:
  * @caps1: a #GstCaps to union
@@ -865,6 +994,9 @@ gst_caps_union (const GstCaps * caps1, const GstCaps * caps2)
   GstCaps *dest1;
   GstCaps *dest2;
 
+  if (gst_caps_is_any (caps1) || gst_caps_is_any (caps2))
+    return gst_caps_new_any ();
+
   dest1 = gst_caps_copy (caps1);
   dest2 = gst_caps_copy (caps2);
   gst_caps_append (dest1, dest2);
index ef3e94f..d0ad570 100644 (file)
@@ -106,16 +106,22 @@ gboolean                 gst_caps_is_any                                (const G
 gboolean                 gst_caps_is_empty                              (const GstCaps *caps);
 #ifndef GST_DISABLE_DEPRECATED
 gboolean                 gst_caps_is_chained                            (const GstCaps *caps);
-#endif
-gboolean                 gst_caps_is_fixed                              (const GstCaps *caps);
 gboolean                 gst_caps_is_equal_fixed                        (const GstCaps *caps1,
                                                                         const GstCaps *caps2);
+#endif
+gboolean                 gst_caps_is_fixed                              (const GstCaps *caps);
 gboolean                 gst_caps_is_always_compatible                  (const GstCaps *caps1,
                                                                         const GstCaps *caps2);
+gboolean                gst_caps_is_subset                             (const GstCaps *subset,
+                                                                        const GstCaps *superset);
+gboolean                gst_caps_is_equal                              (const GstCaps *caps1,
+                                                                        const GstCaps *caps2);
 
 /* operations */
 GstCaps *                gst_caps_intersect                             (const GstCaps *caps1,
                                                                         const GstCaps *caps2);
+GstCaps *                gst_caps_subtract                             (const GstCaps *minuend,
+                                                                        const GstCaps *subtrahend);
 GstCaps *                gst_caps_union                                 (const GstCaps *caps1,
                                                                         const GstCaps *caps2);
 GstCaps *                gst_caps_normalize                             (const GstCaps *caps);
index 480a704..a953823 100644 (file)
@@ -1449,7 +1449,7 @@ gst_pad_try_set_caps (GstPad * pad, const GstCaps * caps)
   g_return_val_if_fail (GST_PAD_LINK_SINK (pad), GST_PAD_LINK_REFUSED);
 
   /* if the desired caps are already there, it's trivially ok */
-  if (GST_PAD_CAPS (pad) && gst_caps_is_equal_fixed (caps, GST_PAD_CAPS (pad))) {
+  if (GST_PAD_CAPS (pad) && gst_caps_is_equal (caps, GST_PAD_CAPS (pad))) {
     return GST_PAD_LINK_OK;
   }
 
index b86b517..3b9cb44 100644 (file)
@@ -340,7 +340,7 @@ gst_queue_link (GstPad * pad, const GstCaps * caps)
   queue = GST_QUEUE (gst_pad_get_parent (pad));
 
   if (queue->cur_level.bytes > 0) {
-    if (gst_caps_is_equal_fixed (caps, queue->negotiated_caps)) {
+    if (gst_caps_is_equal (caps, queue->negotiated_caps)) {
       return GST_PAD_LINK_OK;
     }
     return GST_PAD_LINK_REFUSED;
index d420e21..8319f5a 100644 (file)
@@ -248,6 +248,22 @@ gst_structure_get_name (const GstStructure * structure)
 }
 
 /**
+ * gst_structure_get_name:
+ * @structure: a #GstStructure
+ *
+ * Accessor fuction.
+ *
+ * Returns: the quark representing the name of the structure.
+ */
+GQuark
+gst_structure_get_name_id (const GstStructure * structure)
+{
+  g_return_val_if_fail (structure != NULL, 0);
+
+  return structure->name;
+}
+
+/**
  * gst_structure_set_name:
  * @structure: a #GstStructure
  * @name: the new name of the structure
index b2834d0..fcc4f95 100644 (file)
@@ -60,6 +60,7 @@ GstStructure *          gst_structure_copy                 (const GstStructure
 void                    gst_structure_free                 (GstStructure            *structure);
 
 G_CONST_RETURN gchar *  gst_structure_get_name             (const GstStructure      *structure);
+GQuark                 gst_structure_get_name_id          (const GstStructure      *structure);
 void                    gst_structure_set_name             (GstStructure            *structure,
                                                            const gchar             *name);
 
index efa108f..25b273f 100644 (file)
@@ -44,6 +44,15 @@ struct _GstValueIntersectInfo
   GstValueIntersectFunc func;
 };
 
+typedef struct _GstValueSubtractInfo GstValueSubtractInfo;
+struct _GstValueSubtractInfo
+{
+  GType minuend;
+  GType subtrahend;
+  GstValueSubtractFunc func;
+};
+
+GType gst_type_fourcc;
 GType gst_type_fourcc;
 GType gst_type_int_range;
 GType gst_type_double_range;
@@ -52,6 +61,7 @@ GType gst_type_list;
 static GArray *gst_value_table;
 static GArray *gst_value_union_funcs;
 static GArray *gst_value_intersect_funcs;
+static GArray *gst_value_subtract_funcs;
 
 /*************************************/
 /* list */
@@ -1235,6 +1245,252 @@ gst_value_intersect_list (GValue * dest, const GValue * value1,
   return ret;
 }
 
+/*************************************/
+/* subtraction */
+
+static gboolean
+gst_value_subtract_int_int_range (GValue * dest, const GValue * minuend,
+    const GValue * subtrahend)
+{
+  int min = gst_value_get_int_range_min (subtrahend);
+  int max = gst_value_get_int_range_max (subtrahend);
+  int val = g_value_get_int (minuend);
+
+  if (val < min || val > max) {
+    gst_value_init_and_copy (dest, minuend);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+static gboolean
+gst_value_create_new_range (GValue * dest, int min1, int max1, int min2,
+    int max2)
+{
+  GValue v1 = { 0, };
+  GValue v2 = { 0, };
+  GValue *pv1, *pv2;            /* yeah, hungarian! */
+
+  if (min1 <= max1 && min2 <= max2) {
+    pv1 = &v1;
+    pv2 = &v2;
+  } else if (min1 <= max1) {
+    pv1 = dest;
+  } else if (min2 <= max2) {
+    pv2 = dest;
+  } else {
+    return FALSE;
+  }
+
+  if (min1 < max1) {
+    g_value_init (pv1, GST_TYPE_INT_RANGE);
+    gst_value_set_int_range (pv1, min1, max1);
+  } else if (min1 == max1) {
+    g_value_init (pv1, G_TYPE_INT);
+    g_value_set_int (pv1, min1);
+  }
+  if (min2 < max2) {
+    g_value_init (pv2, GST_TYPE_INT_RANGE);
+    gst_value_set_int_range (pv2, min2, max2);
+  } else if (min2 == max2) {
+    g_value_init (pv2, G_TYPE_INT);
+    g_value_set_int (pv2, min2);
+  }
+
+  if (min1 <= max1 && min2 <= max2) {
+    gst_value_list_concat (dest, pv1, pv2);
+    g_value_unset (pv1);
+    g_value_unset (pv2);
+  }
+  return TRUE;
+}
+
+static gboolean
+gst_value_subtract_int_range_int (GValue * dest, const GValue * minuend,
+    const GValue * subtrahend)
+{
+  int min = gst_value_get_int_range_min (minuend);
+  int max = gst_value_get_int_range_max (minuend);
+  int val = g_value_get_int (subtrahend);
+
+  g_return_val_if_fail (min < max, FALSE);
+
+  if (val < min || val > max) {
+    gst_value_init_and_copy (dest, minuend);
+    return TRUE;
+  } else {
+    if (val == G_MAXINT) {
+      max--;
+      val--;
+    }
+    if (val == G_MININT) {
+      min++;
+      val++;
+    }
+    gst_value_create_new_range (dest, min, val - 1, val + 1, max);
+  }
+  return TRUE;
+}
+
+static gboolean
+gst_value_subtract_int_range_int_range (GValue * dest, const GValue * minuend,
+    const GValue * subtrahend)
+{
+  int min1 = gst_value_get_int_range_min (minuend);
+  int max1 = gst_value_get_int_range_max (minuend);
+  int min2 = gst_value_get_int_range_min (subtrahend);
+  int max2 = gst_value_get_int_range_max (subtrahend);
+
+  if (max2 == G_MAXINT) {
+    max2--;
+    max1--;
+  }
+  if (min2 == G_MININT) {
+    min2++;
+    min1++;
+  }
+  return gst_value_create_new_range (dest, min1, MIN (min2 - 1, max1),
+      MAX (max2 + 1, min1), max1);
+}
+
+static gboolean
+gst_value_subtract_double_double_range (GValue * dest, const GValue * minuend,
+    const GValue * subtrahend)
+{
+  double min = gst_value_get_double_range_min (subtrahend);
+  double max = gst_value_get_double_range_max (subtrahend);
+  double val = g_value_get_double (minuend);
+
+  if (val < min || val > max) {
+    gst_value_init_and_copy (dest, minuend);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+static gboolean
+gst_value_subtract_double_range_double (GValue * dest, const GValue * minuend,
+    const GValue * subtrahend)
+{
+  /* FIXME! */
+  gst_value_init_and_copy (dest, minuend);
+  return TRUE;
+}
+
+static gboolean
+gst_value_subtract_double_range_double_range (GValue * dest,
+    const GValue * minuend, const GValue * subtrahend)
+{
+  /* FIXME! */
+  /* done like with ints */
+  double min1 = gst_value_get_double_range_min (minuend);
+  double max2 = gst_value_get_double_range_max (minuend);
+  double max1 = MIN (gst_value_get_double_range_min (subtrahend), max2);
+  double min2 = MAX (gst_value_get_double_range_max (subtrahend), min1);
+  GValue v1 = { 0, };
+  GValue v2 = { 0, };
+  GValue *pv1, *pv2;            /* yeah, hungarian! */
+
+  if (min1 < max1 && min2 < max2) {
+    pv1 = &v1;
+    pv2 = &v2;
+  } else if (min1 < max1) {
+    pv1 = dest;
+  } else if (min2 < max2) {
+    pv2 = dest;
+  } else {
+    return FALSE;
+  }
+
+  if (min1 < max1) {
+    g_value_init (pv1, GST_TYPE_DOUBLE_RANGE);
+    gst_value_set_double_range (pv1, min1, max1);
+  }
+  if (min2 < max2) {
+    g_value_init (pv2, GST_TYPE_DOUBLE_RANGE);
+    gst_value_set_double_range (pv2, min2, max2);
+  }
+
+  if (min1 < max1 && min2 < max2) {
+    gst_value_list_concat (dest, pv1, pv2);
+    g_value_unset (pv1);
+    g_value_unset (pv2);
+  }
+  return TRUE;
+}
+
+static gboolean
+gst_value_subtract_from_list (GValue * dest, const GValue * minuend,
+    const GValue * subtrahend)
+{
+  guint i, size;
+  GValue subtraction = { 0, };
+  gboolean ret = FALSE;
+
+  g_return_val_if_fail (GST_VALUE_HOLDS_LIST (minuend), FALSE);
+
+  size = gst_value_list_get_size (minuend);
+  for (i = 0; i < size; i++) {
+    const GValue *cur = gst_value_list_get_value (minuend, i);
+
+    if (gst_value_subtract (&subtraction, cur, subtrahend)) {
+      if (!ret) {
+        gst_value_init_and_copy (dest, &subtraction);
+        ret = TRUE;
+      } else if (GST_VALUE_HOLDS_LIST (dest)
+          && GST_VALUE_HOLDS_LIST (&subtraction)) {
+        /* unroll */
+        GValue unroll = { 0, };
+
+        gst_value_init_and_copy (&unroll, dest);
+        g_value_unset (dest);
+        gst_value_list_concat (dest, &unroll, &subtraction);
+      } else if (GST_VALUE_HOLDS_LIST (dest)) {
+        gst_value_list_append_value (dest, &subtraction);
+      } else {
+        GValue temp = { 0, };
+
+        gst_value_init_and_copy (&temp, dest);
+        g_value_unset (dest);
+        gst_value_list_concat (dest, &temp, &subtraction);
+      }
+      g_value_unset (&subtraction);
+    }
+  }
+  return ret;
+}
+
+static gboolean
+gst_value_subtract_list (GValue * dest, const GValue * minuend,
+    const GValue * subtrahend)
+{
+  guint i, size;
+  GValue data[2] = { {0,}, {0,} };
+  GValue *subtraction = &data[0], *result = &data[1];
+
+  g_return_val_if_fail (GST_VALUE_HOLDS_LIST (subtrahend), FALSE);
+
+  gst_value_init_and_copy (result, minuend);
+  size = gst_value_list_get_size (subtrahend);
+  for (i = 0; i < size; i++) {
+    const GValue *cur = gst_value_list_get_value (subtrahend, i);
+
+    if (gst_value_subtract (subtraction, result, cur)) {
+      GValue *temp = result;
+
+      result = subtraction;
+      subtraction = temp;
+      g_value_unset (subtraction);
+    } else {
+      g_value_unset (result);
+      return FALSE;
+    }
+  }
+  gst_value_init_and_copy (dest, result);
+  g_value_unset (result);
+  return TRUE;
+}
+
 
 /*************************************/
 
@@ -1418,7 +1674,9 @@ gst_value_can_intersect (const GValue * value1, const GValue * value2)
         GstValueIntersectInfo, i);
     if (intersect_info->type1 == G_VALUE_TYPE (value1) &&
         intersect_info->type2 == G_VALUE_TYPE (value2))
-      return TRUE;
+      if (intersect_info->type2 == G_VALUE_TYPE (value1) &&
+          intersect_info->type1 == G_VALUE_TYPE (value2))
+        return TRUE;
   }
 
   return gst_value_can_compare (value1, value2);
@@ -1491,6 +1749,118 @@ gst_value_register_intersect_func (GType type1, GType type2,
   g_array_append_val (gst_value_intersect_funcs, intersect_info);
 }
 
+
+/* subtraction */
+
+/**
+ * gst_value_subtract:
+ * @dest: the destination value for the result if the subtraction is not empty
+ * @minuend: the value to subtract from
+ * @subtrahend: the value to subtract
+ *
+ * Subtracts @subtrahend from @minuend and stores the result in @dest.
+ * Note that this means subtraction as in sets, not as in mathematics.
+ *
+ * Returns: TRUE if the subtraction is not empty
+ */
+gboolean
+gst_value_subtract (GValue * dest, const GValue * minuend,
+    const GValue * subtrahend)
+{
+  GstValueSubtractInfo *info;
+  int i;
+
+  /* special cases first */
+  if (GST_VALUE_HOLDS_LIST (minuend))
+    return gst_value_subtract_from_list (dest, minuend, subtrahend);
+  if (GST_VALUE_HOLDS_LIST (subtrahend))
+    return gst_value_subtract_list (dest, minuend, subtrahend);
+
+  for (i = 0; i < gst_value_subtract_funcs->len; i++) {
+    info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
+    if (info->minuend == G_VALUE_TYPE (minuend) &&
+        info->subtrahend == G_VALUE_TYPE (subtrahend)) {
+      return info->func (dest, minuend, subtrahend);
+    }
+  }
+
+  if (gst_value_compare (minuend, subtrahend) != GST_VALUE_EQUAL) {
+    gst_value_init_and_copy (dest, minuend);
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+#if 0
+gboolean
+gst_value_subtract (GValue * dest, const GValue * minuend,
+    const GValue * subtrahend)
+{
+  gboolean ret = gst_value_subtract2 (dest, minuend, subtrahend);
+
+  g_printerr ("\"%s\"  -  \"%s\"  =  \"%s\"\n", gst_value_serialize (minuend),
+      gst_value_serialize (subtrahend),
+      ret ? gst_value_serialize (dest) : "---");
+  return ret;
+}
+#endif
+
+/**
+ * gst_value_can_subtract:
+ * @minuend: the value to subtract from
+ * @subtrahend: the value to subtract
+ *
+ * Checks if it's possible to subtract @subtrahend from @minuend.
+ *
+ * Returns: TRUE if a subtraction is possible
+ */
+gboolean
+gst_value_can_subtract (const GValue * minuend, const GValue * subtrahend)
+{
+  GstValueSubtractInfo *info;
+  int i;
+
+  /* special cases */
+  if (GST_VALUE_HOLDS_LIST (minuend) || GST_VALUE_HOLDS_LIST (subtrahend))
+    return TRUE;
+
+  for (i = 0; i < gst_value_subtract_funcs->len; i++) {
+    info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
+    if (info->minuend == G_VALUE_TYPE (minuend) &&
+        info->subtrahend == G_VALUE_TYPE (subtrahend))
+      return TRUE;
+  }
+
+  return gst_value_can_compare (minuend, subtrahend);
+}
+
+/**
+ * gst_value_register_subtract_func:
+ * @minuend_type: type of the minuend
+ * @subtrahend_type: type of the subtrahend
+ * @func: function to use
+ *
+ * Registers @func as a function capable of subtracting the values of 
+ * @subtrahend_type from values of @minuend_type.
+ */
+void
+gst_value_register_subtract_func (GType minuend_type, GType subtrahend_type,
+    GstValueSubtractFunc func)
+{
+  GstValueSubtractInfo info;
+
+  /* one type must be unfixed, other subtractions can be done as comparisons */
+  g_return_if_fail (!gst_type_is_fixed (minuend_type)
+      || !gst_type_is_fixed (subtrahend_type));
+
+  info.minuend = minuend_type;
+  info.subtrahend = subtrahend_type;
+  info.func = func;
+
+  g_array_append_val (gst_value_subtract_funcs, info);
+}
+
 /*
  * gst_value_register:
  * @table:
@@ -1618,6 +1988,8 @@ _gst_value_initialize (void)
       sizeof (GstValueUnionInfo));
   gst_value_intersect_funcs = g_array_new (FALSE, FALSE,
       sizeof (GstValueIntersectInfo));
+  gst_value_subtract_funcs = g_array_new (FALSE, FALSE,
+      sizeof (GstValueSubtractInfo));
 
   {
     static const GTypeValueTable value_table = {
@@ -1812,6 +2184,19 @@ _gst_value_initialize (void)
   gst_value_register_intersect_func (GST_TYPE_DOUBLE_RANGE,
       GST_TYPE_DOUBLE_RANGE, gst_value_intersect_double_range_double_range);
 
+  gst_value_register_subtract_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
+      gst_value_subtract_int_int_range);
+  gst_value_register_subtract_func (GST_TYPE_INT_RANGE, G_TYPE_INT,
+      gst_value_subtract_int_range_int);
+  gst_value_register_subtract_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
+      gst_value_subtract_int_range_int_range);
+  gst_value_register_subtract_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
+      gst_value_subtract_double_double_range);
+  gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_DOUBLE,
+      gst_value_subtract_double_range_double);
+  gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE,
+      GST_TYPE_DOUBLE_RANGE, gst_value_subtract_double_range_double_range);
+
   gst_value_register_union_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
       gst_value_union_int_int_range);
   gst_value_register_union_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
index a3b95be..9d67f9e 100644 (file)
@@ -62,6 +62,9 @@ typedef int      (* GstValueUnionFunc)       (GValue       *dest,
 typedef int      (* GstValueIntersectFunc)   (GValue       *dest,
                                              const GValue *value1,
                                              const GValue *value2);
+typedef int      (* GstValueSubtractFunc)    (GValue       *dest,
+                                             const GValue *minuend,
+                                             const GValue *subtrahend);
 
 typedef struct _GstValueTable GstValueTable;
 struct _GstValueTable {
@@ -148,6 +151,17 @@ void                     gst_value_register_intersect_func (GType
                                                            GType                 type2,
                                                            GstValueIntersectFunc func);
 
+/* subtraction */
+gboolean                gst_value_subtract                (GValue                *dest,
+                                                           const GValue          *minuend,
+                                                           const GValue          *subtrahend);
+gboolean                gst_value_can_subtract            (const GValue          *minuend,
+                                                           const GValue          *subtrahend);
+void                     gst_value_register_subtract_func  (GType                 minuend_type,
+                                                           GType                 dubtrahend_type,
+                                                           GstValueSubtractFunc  func);
+
+/* fixation */
 gboolean                 gst_type_is_fixed                 (GType type);
 
 /* private */
index b86b517..3b9cb44 100644 (file)
@@ -340,7 +340,7 @@ gst_queue_link (GstPad * pad, const GstCaps * caps)
   queue = GST_QUEUE (gst_pad_get_parent (pad));
 
   if (queue->cur_level.bytes > 0) {
-    if (gst_caps_is_equal_fixed (caps, queue->negotiated_caps)) {
+    if (gst_caps_is_equal (caps, queue->negotiated_caps)) {
       return GST_PAD_LINK_OK;
     }
     return GST_PAD_LINK_REFUSED;
index 75f6cf7..3ff4a8e 100644 (file)
@@ -12,11 +12,14 @@ Makefile.in
 app_fixate
 caps
 compatibility
+erathostenes
+fixed
+intersect2
 intersection
 normalisation
 union
-fixed
+sets
 string-conversions
-intersect2
+subtract
 value_compare
 value_intersect
index 52949f0..2b7eb47 100644 (file)
@@ -15,7 +15,10 @@ tests_pass = \
        value_intersect \
        value_serialize \
        audioscale \
-       filtercaps
+       filtercaps \
+       erathostenes \
+       subtract \
+       sets
 
 tests_fail =
 tests_ignore =
@@ -38,6 +41,10 @@ intersect2_LDADD = $(GST_LIBS)
 intersect2_CFLAGS = $(GST_CFLAGS) $(XML_CFLAGS)
 filtercaps_LDADD = $(GST_LIBS) 
 filtercaps_CFLAGS = $(GST_CFLAGS) $(XML_CFLAGS)
-
-
+erathostenes_LDADD = $(GST_LIBS) 
+ersthostenes_CFLAGS = $(GST_CFLAGS) $(XML_CFLAGS)
+subtract_LDADD = $(GST_LIBS) 
+subtract_CFLAGS = $(GST_CFLAGS) $(XML_CFLAGS)
+sets_LDADD = $(GST_LIBS) 
+sets_CFLAGS = $(GST_CFLAGS) $(XML_CFLAGS)
 
diff --git a/tests/old/testsuite/caps/erathostenes.c b/tests/old/testsuite/caps/erathostenes.c
new file mode 100644 (file)
index 0000000..9d9866a
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <gst/gst.h>
+#include <stdlib.h>
+
+#define MAX_SIEVE 20
+
+static void
+erathostenes (GValue * sieve, gboolean up, int size)
+{
+  guint i, j;
+  GValue temp = { 0, };
+  GValue list = { 0, };
+
+  g_value_init (sieve, GST_TYPE_INT_RANGE);
+  gst_value_set_int_range (sieve, 2, size * size);
+  for (i = up ? 2 : size; up ? (i <= size) : (i >= 2); i += up ? 1 : -1) {
+    g_value_init (&list, GST_TYPE_LIST);
+    for (j = 2 * i; j <= size * size; j += i) {
+      GValue v = { 0, };
+
+      g_value_init (&v, G_TYPE_INT);
+      g_value_set_int (&v, j);
+      gst_value_list_append_value (&list, &v);
+      g_value_unset (&v);
+    }
+    gst_value_subtract (&temp, sieve, &list);
+    g_value_unset (sieve);
+    gst_value_init_and_copy (sieve, &temp);
+    g_value_unset (&temp);
+    g_value_unset (&list);
+    /* g_print ("%2u:  %s\n", i, gst_value_serialize (sieve)); */
+  }
+
+  g_print ("%s\n", gst_value_serialize (sieve));
+}
+
+gint
+main (gint argc, gchar ** argv)
+{
+  GValue up = { 0, };
+  GValue down = { 0, };
+  guint size = MAX_SIEVE;
+
+  gst_init (&argc, &argv);
+
+  if (argc > 1)
+    size = atol (argv[1]);
+
+  erathostenes (&up, TRUE, size);
+  erathostenes (&down, FALSE, size);
+
+  g_assert (gst_value_compare (&up, &down) == GST_VALUE_EQUAL);
+  return 0;
+}
diff --git a/tests/old/testsuite/caps/sets.c b/tests/old/testsuite/caps/sets.c
new file mode 100644 (file)
index 0000000..740039f
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <gst/gst.h>
+#include <string.h>
+
+static const gchar *caps[] = {
+  "video/x-raw-yuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(fourcc)I420; video/x-raw-yuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(fourcc)YUY2; video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], bpp=(int)24, depth=(int)24, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, endianness=(int)4321; video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], bpp=(int)24, depth=(int)24, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, endianness=(int)4321; video/x-raw-yuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(fourcc)Y42B; video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], bpp=(int)32, depth=(int)24, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, endianness=(int)4321; video/x-raw-yuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(fourcc)YUV9; video/x-raw-yuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(fourcc)Y41B; video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], bpp=(int)16, depth=(int)16, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, endianness=(int)1234; video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], bpp=(int)16, depth=(int)15, red_mask=(int)31744, green_mask=(int)992, blue_mask=(int)31, endianness=(int)1234",
+  "video/x-raw-yuv, format=(fourcc){ YUY2, I420 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-jpeg, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-divx, divxversion=(int)[ 3, 5 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-xvid, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-3ivx, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-msmpeg, msmpegversion=(int)[ 41, 43 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/mpeg, mpegversion=(int)1, systemstream=(boolean)false, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h263, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-dv, systemstream=(boolean)false, width=(int)720, height=(int){ 576, 480 }; video/x-huffyuv, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]",
+  "video/x-raw-yuv, format=(fourcc){ YUY2, I420 }, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; image/jpeg, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-divx, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], divxversion=(int)[ 3, 5 ]; video/x-xvid, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-3ivx, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-msmpeg, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], msmpegversion=(int)[ 41, 43 ]; video/mpeg, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], mpegversion=(int)1, systemstream=(boolean)false; video/x-h263, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-dv, width=(int)720, height=(int){ 576, 480 }, systemstream=(boolean)false; video/x-huffyuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]",
+  "video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]",
+  "video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]",
+  "video/x-raw-yuv, format=(fourcc){ I420 }, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]",
+  "ANY",
+  "EMPTY"
+};
+
+static void
+check_caps (const gchar * eins, const gchar * zwei)
+{
+  GstCaps *one, *two, *test, *test2, *test3, *test4;
+
+  one = gst_caps_from_string (eins);
+  two = gst_caps_from_string (zwei);
+  g_print ("      A  =  %u\n", strlen (eins));
+  g_print ("      B  =  %u\n", strlen (zwei));
+
+  test = gst_caps_intersect (one, two);
+  if (gst_caps_is_equal (one, two)) {
+    g_print ("         EQUAL\n\n");
+    g_assert (gst_caps_is_equal (one, test));
+    g_assert (gst_caps_is_equal (two, test));
+  } else if (!gst_caps_is_any (one) || gst_caps_is_empty (two)) {
+    test2 = gst_caps_subtract (one, test);
+    g_print ("  A - B  =  %u\n", strlen (gst_caps_to_string (test2)));
+    /* test2 = one - (one A two) = one - two */
+    test3 = gst_caps_intersect (test2, two);
+    g_print ("  empty  =  %s\n", gst_caps_to_string (test3));
+    g_assert (gst_caps_is_empty (test3));
+    gst_caps_free (test3);
+    test3 = gst_caps_union (test2, two);
+    g_print ("  A + B  =  %u\n", strlen (gst_caps_to_string (test3)));
+    /* test3 = one - two + two = one + two */
+    g_print ("  A + B  =  %s\n", gst_caps_to_string (gst_caps_subtract (one,
+                test3)));
+    g_assert (gst_caps_is_subset (one, test3));
+    test4 = gst_caps_union (one, two);
+    g_assert (gst_caps_is_equal (test3, test4));
+    g_print ("         NOT EQUAL\n\n");
+    gst_caps_free (test2);
+    gst_caps_free (test3);
+    gst_caps_free (test4);
+  } else {
+    g_print ("         ANY CAPS\n\n");
+  }
+  gst_caps_free (test);
+  gst_caps_free (two);
+  gst_caps_free (one);
+}
+
+gint
+main (gint argc, gchar ** argv)
+{
+  guint i, j;
+
+  gst_init (&argc, &argv);
+
+  for (i = 0; i < G_N_ELEMENTS (caps); i++) {
+    for (j = 0; j < G_N_ELEMENTS (caps); j++) {
+      g_print ("%u - %u\n", i, j);
+      check_caps (caps[i], caps[j]);
+    }
+  }
+
+  return 0;
+}
diff --git a/tests/old/testsuite/caps/subtract.c b/tests/old/testsuite/caps/subtract.c
new file mode 100644 (file)
index 0000000..fe80d44
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <gst/gst.h>
+
+static void
+check_caps (const gchar * set, const gchar * subset)
+{
+  GstCaps *one, *two, *test, *test2;
+
+  g_print ("        A  =  %s\n", set);
+  one = gst_caps_from_string (set);
+  g_print ("        B  =  %s\n", subset);
+  two = gst_caps_from_string (subset);
+  /* basics */
+  test = gst_caps_subtract (one, one);
+  g_assert (gst_caps_is_empty (test));
+  gst_caps_free (test);
+  test = gst_caps_subtract (two, two);
+  g_assert (gst_caps_is_empty (test));
+  gst_caps_free (test);
+  test = gst_caps_subtract (two, one);
+  g_assert (gst_caps_is_empty (test));
+  gst_caps_free (test);
+  /* now the nice part */
+  test = gst_caps_subtract (one, two);
+  g_assert (!gst_caps_is_empty (test));
+  g_print ("    A - B  =  %s\n", gst_caps_to_string (test));
+  test2 = gst_caps_union (test, two);
+  g_print ("A - B + B  =  %s\n", gst_caps_to_string (test2));
+  gst_caps_free (test);
+  test = gst_caps_subtract (test2, one);
+  g_assert (gst_caps_is_empty (test));
+  gst_caps_free (test);
+}
+
+gint
+main (gint argc, gchar ** argv)
+{
+  gst_init (&argc, &argv);
+
+  check_caps ("some/mime, _int = [ 1, 2 ], list = { \"A\", \"B\", \"C\" }",
+      "some/mime, _int = 1, list = \"A\"");
+  check_caps ("some/mime, _double = (double) 1.0; other/mime, _int = { 1, 2 }",
+      "some/mime, _double = (double) 1.0");
+
+  return 0;
+}
index 75f6cf7..3ff4a8e 100644 (file)
@@ -12,11 +12,14 @@ Makefile.in
 app_fixate
 caps
 compatibility
+erathostenes
+fixed
+intersect2
 intersection
 normalisation
 union
-fixed
+sets
 string-conversions
-intersect2
+subtract
 value_compare
 value_intersect
index 52949f0..2b7eb47 100644 (file)
@@ -15,7 +15,10 @@ tests_pass = \
        value_intersect \
        value_serialize \
        audioscale \
-       filtercaps
+       filtercaps \
+       erathostenes \
+       subtract \
+       sets
 
 tests_fail =
 tests_ignore =
@@ -38,6 +41,10 @@ intersect2_LDADD = $(GST_LIBS)
 intersect2_CFLAGS = $(GST_CFLAGS) $(XML_CFLAGS)
 filtercaps_LDADD = $(GST_LIBS) 
 filtercaps_CFLAGS = $(GST_CFLAGS) $(XML_CFLAGS)
-
-
+erathostenes_LDADD = $(GST_LIBS) 
+ersthostenes_CFLAGS = $(GST_CFLAGS) $(XML_CFLAGS)
+subtract_LDADD = $(GST_LIBS) 
+subtract_CFLAGS = $(GST_CFLAGS) $(XML_CFLAGS)
+sets_LDADD = $(GST_LIBS) 
+sets_CFLAGS = $(GST_CFLAGS) $(XML_CFLAGS)
 
diff --git a/testsuite/caps/erathostenes.c b/testsuite/caps/erathostenes.c
new file mode 100644 (file)
index 0000000..9d9866a
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <gst/gst.h>
+#include <stdlib.h>
+
+#define MAX_SIEVE 20
+
+static void
+erathostenes (GValue * sieve, gboolean up, int size)
+{
+  guint i, j;
+  GValue temp = { 0, };
+  GValue list = { 0, };
+
+  g_value_init (sieve, GST_TYPE_INT_RANGE);
+  gst_value_set_int_range (sieve, 2, size * size);
+  for (i = up ? 2 : size; up ? (i <= size) : (i >= 2); i += up ? 1 : -1) {
+    g_value_init (&list, GST_TYPE_LIST);
+    for (j = 2 * i; j <= size * size; j += i) {
+      GValue v = { 0, };
+
+      g_value_init (&v, G_TYPE_INT);
+      g_value_set_int (&v, j);
+      gst_value_list_append_value (&list, &v);
+      g_value_unset (&v);
+    }
+    gst_value_subtract (&temp, sieve, &list);
+    g_value_unset (sieve);
+    gst_value_init_and_copy (sieve, &temp);
+    g_value_unset (&temp);
+    g_value_unset (&list);
+    /* g_print ("%2u:  %s\n", i, gst_value_serialize (sieve)); */
+  }
+
+  g_print ("%s\n", gst_value_serialize (sieve));
+}
+
+gint
+main (gint argc, gchar ** argv)
+{
+  GValue up = { 0, };
+  GValue down = { 0, };
+  guint size = MAX_SIEVE;
+
+  gst_init (&argc, &argv);
+
+  if (argc > 1)
+    size = atol (argv[1]);
+
+  erathostenes (&up, TRUE, size);
+  erathostenes (&down, FALSE, size);
+
+  g_assert (gst_value_compare (&up, &down) == GST_VALUE_EQUAL);
+  return 0;
+}
diff --git a/testsuite/caps/sets.c b/testsuite/caps/sets.c
new file mode 100644 (file)
index 0000000..740039f
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <gst/gst.h>
+#include <string.h>
+
+static const gchar *caps[] = {
+  "video/x-raw-yuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(fourcc)I420; video/x-raw-yuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(fourcc)YUY2; video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], bpp=(int)24, depth=(int)24, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, endianness=(int)4321; video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], bpp=(int)24, depth=(int)24, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, endianness=(int)4321; video/x-raw-yuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(fourcc)Y42B; video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], bpp=(int)32, depth=(int)24, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, endianness=(int)4321; video/x-raw-yuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(fourcc)YUV9; video/x-raw-yuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], format=(fourcc)Y41B; video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], bpp=(int)16, depth=(int)16, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, endianness=(int)1234; video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ], bpp=(int)16, depth=(int)15, red_mask=(int)31744, green_mask=(int)992, blue_mask=(int)31, endianness=(int)1234",
+  "video/x-raw-yuv, format=(fourcc){ YUY2, I420 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-jpeg, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-divx, divxversion=(int)[ 3, 5 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-xvid, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-3ivx, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-msmpeg, msmpegversion=(int)[ 41, 43 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/mpeg, mpegversion=(int)1, systemstream=(boolean)false, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-h263, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-dv, systemstream=(boolean)false, width=(int)720, height=(int){ 576, 480 }; video/x-huffyuv, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]",
+  "video/x-raw-yuv, format=(fourcc){ YUY2, I420 }, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; image/jpeg, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-divx, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], divxversion=(int)[ 3, 5 ]; video/x-xvid, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-3ivx, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-msmpeg, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], msmpegversion=(int)[ 41, 43 ]; video/mpeg, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], mpegversion=(int)1, systemstream=(boolean)false; video/x-h263, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-dv, width=(int)720, height=(int){ 576, 480 }, systemstream=(boolean)false; video/x-huffyuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]",
+  "video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]",
+  "video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(double)[ 0, 1.7976931348623157e+308 ]",
+  "video/x-raw-yuv, format=(fourcc){ I420 }, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]",
+  "ANY",
+  "EMPTY"
+};
+
+static void
+check_caps (const gchar * eins, const gchar * zwei)
+{
+  GstCaps *one, *two, *test, *test2, *test3, *test4;
+
+  one = gst_caps_from_string (eins);
+  two = gst_caps_from_string (zwei);
+  g_print ("      A  =  %u\n", strlen (eins));
+  g_print ("      B  =  %u\n", strlen (zwei));
+
+  test = gst_caps_intersect (one, two);
+  if (gst_caps_is_equal (one, two)) {
+    g_print ("         EQUAL\n\n");
+    g_assert (gst_caps_is_equal (one, test));
+    g_assert (gst_caps_is_equal (two, test));
+  } else if (!gst_caps_is_any (one) || gst_caps_is_empty (two)) {
+    test2 = gst_caps_subtract (one, test);
+    g_print ("  A - B  =  %u\n", strlen (gst_caps_to_string (test2)));
+    /* test2 = one - (one A two) = one - two */
+    test3 = gst_caps_intersect (test2, two);
+    g_print ("  empty  =  %s\n", gst_caps_to_string (test3));
+    g_assert (gst_caps_is_empty (test3));
+    gst_caps_free (test3);
+    test3 = gst_caps_union (test2, two);
+    g_print ("  A + B  =  %u\n", strlen (gst_caps_to_string (test3)));
+    /* test3 = one - two + two = one + two */
+    g_print ("  A + B  =  %s\n", gst_caps_to_string (gst_caps_subtract (one,
+                test3)));
+    g_assert (gst_caps_is_subset (one, test3));
+    test4 = gst_caps_union (one, two);
+    g_assert (gst_caps_is_equal (test3, test4));
+    g_print ("         NOT EQUAL\n\n");
+    gst_caps_free (test2);
+    gst_caps_free (test3);
+    gst_caps_free (test4);
+  } else {
+    g_print ("         ANY CAPS\n\n");
+  }
+  gst_caps_free (test);
+  gst_caps_free (two);
+  gst_caps_free (one);
+}
+
+gint
+main (gint argc, gchar ** argv)
+{
+  guint i, j;
+
+  gst_init (&argc, &argv);
+
+  for (i = 0; i < G_N_ELEMENTS (caps); i++) {
+    for (j = 0; j < G_N_ELEMENTS (caps); j++) {
+      g_print ("%u - %u\n", i, j);
+      check_caps (caps[i], caps[j]);
+    }
+  }
+
+  return 0;
+}
diff --git a/testsuite/caps/subtract.c b/testsuite/caps/subtract.c
new file mode 100644 (file)
index 0000000..fe80d44
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <gst/gst.h>
+
+static void
+check_caps (const gchar * set, const gchar * subset)
+{
+  GstCaps *one, *two, *test, *test2;
+
+  g_print ("        A  =  %s\n", set);
+  one = gst_caps_from_string (set);
+  g_print ("        B  =  %s\n", subset);
+  two = gst_caps_from_string (subset);
+  /* basics */
+  test = gst_caps_subtract (one, one);
+  g_assert (gst_caps_is_empty (test));
+  gst_caps_free (test);
+  test = gst_caps_subtract (two, two);
+  g_assert (gst_caps_is_empty (test));
+  gst_caps_free (test);
+  test = gst_caps_subtract (two, one);
+  g_assert (gst_caps_is_empty (test));
+  gst_caps_free (test);
+  /* now the nice part */
+  test = gst_caps_subtract (one, two);
+  g_assert (!gst_caps_is_empty (test));
+  g_print ("    A - B  =  %s\n", gst_caps_to_string (test));
+  test2 = gst_caps_union (test, two);
+  g_print ("A - B + B  =  %s\n", gst_caps_to_string (test2));
+  gst_caps_free (test);
+  test = gst_caps_subtract (test2, one);
+  g_assert (gst_caps_is_empty (test));
+  gst_caps_free (test);
+}
+
+gint
+main (gint argc, gchar ** argv)
+{
+  gst_init (&argc, &argv);
+
+  check_caps ("some/mime, _int = [ 1, 2 ], list = { \"A\", \"B\", \"C\" }",
+      "some/mime, _int = 1, list = \"A\"");
+  check_caps ("some/mime, _double = (double) 1.0; other/mime, _int = { 1, 2 }",
+      "some/mime, _double = (double) 1.0");
+
+  return 0;
+}