caps: Optimize gst_caps_is_subset()
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Fri, 27 May 2011 11:38:51 +0000 (13:38 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Fri, 27 May 2011 11:38:51 +0000 (13:38 +0200)
..and as a result gst_caps_is_equal() and others.

This now only checks if for every subset structure there is
a superset structure in the superset caps. Previously we were
subtracting one from another, creating completely new caps
and then even simplified them.

The new implemention now is about 1.27 times faster and doesn't
break the -base unit tests are anything anymore.

gst/gstcaps.c
tests/check/gst/gstcaps.c

index 10dbff7..bc89baa 100644 (file)
@@ -1131,8 +1131,9 @@ gst_caps_is_always_compatible (const GstCaps * caps1, const GstCaps * caps2)
 gboolean
 gst_caps_is_subset (const GstCaps * subset, const GstCaps * superset)
 {
-  GstCaps *caps;
-  gboolean ret;
+  GstStructure *s1, *s2;
+  gboolean ret = TRUE;
+  gint i, j;
 
   g_return_val_if_fail (subset != NULL, FALSE);
   g_return_val_if_fail (superset != NULL, FALSE);
@@ -1142,9 +1143,24 @@ gst_caps_is_subset (const GstCaps * subset, const GstCaps * superset)
   if (CAPS_IS_ANY (subset) || CAPS_IS_EMPTY (superset))
     return FALSE;
 
-  caps = gst_caps_subtract (subset, superset);
-  ret = CAPS_IS_EMPTY_SIMPLE (caps);
-  gst_caps_unref (caps);
+  for (i = subset->structs->len - 1; i >= 0; i--) {
+    for (j = superset->structs->len - 1; j >= 0; j--) {
+      s1 = gst_caps_get_structure_unchecked (subset, i);
+      s2 = gst_caps_get_structure_unchecked (superset, j);
+      if (gst_caps_structure_is_subset (s2, s1)) {
+        /* If we found a superset, continue with the next
+         * subset structure */
+        break;
+      }
+    }
+    /* If we found no superset for this subset structure
+     * we return FALSE immediately */
+    if (j == -1) {
+      ret = FALSE;
+      break;
+    }
+  }
+
   return ret;
 }
 
index 12e9e44..235e588 100644 (file)
@@ -348,6 +348,29 @@ GST_START_TEST (test_truncate)
 
 GST_END_TEST;
 
+GST_START_TEST (test_subset)
+{
+  GstCaps *c1, *c2;
+
+  c1 = gst_caps_from_string ("video/x-raw-yuv; video/x-raw-rgb");
+  c2 = gst_caps_from_string ("video/x-raw-yuv, format=(fourcc)YUY2");
+  fail_unless (gst_caps_is_subset (c2, c1));
+  fail_if (gst_caps_is_subset (c1, c2));
+  gst_caps_unref (c1);
+  gst_caps_unref (c2);
+
+  c1 = gst_caps_from_string
+      ("audio/x-raw-int, channels=(int)[ 1, 2 ], rate=(int)44100");
+  c2 = gst_caps_from_string
+      ("audio/x-raw-int, channels=(int)1, rate=(int)44100");
+  fail_unless (gst_caps_is_subset (c2, c1));
+  fail_if (gst_caps_is_subset (c1, c2));
+  gst_caps_unref (c1);
+  gst_caps_unref (c2);
+}
+
+GST_END_TEST;
+
 GST_START_TEST (test_merge_fundamental)
 {
   GstCaps *c1, *c2;
@@ -951,6 +974,7 @@ gst_caps_suite (void)
   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_subset);
   tcase_add_test (tc_chain, test_merge_fundamental);
   tcase_add_test (tc_chain, test_merge_same);
   tcase_add_test (tc_chain, test_merge_subset);