caps: fix is_strictly_equal
authorHenry Wilkes <hwilkes@igalia.com>
Tue, 21 Jan 2020 19:02:48 +0000 (19:02 +0000)
committerJan Schmidt <thaytan@noraisin.net>
Wed, 12 Feb 2020 14:41:40 +0000 (14:41 +0000)
Fixed gst_caps_is_strictly_equal() to take into account whether either of
the caps are ANY caps. Previously, two ANY caps could be considered not
strictly equal if one of them still contained some remnant *internal*
structure (this can happen if an ANY caps has emerged from an append or
merge operation). Also, an ANY caps with no remnant internal structures
was considered strictly equal to an EMPTY caps. Similarly, a non-ANY caps
was considered strictly equal to an ANY caps if its remnant internal
structures happened to match.

Also changed gst_caps_is_fixed to take into account that an ANY caps
should not be considered fixed even if it contains a single remnant
internal fixed structure. This affects gst_caps_is_equal(), which uses a
separate method if both caps are fixed. Previously, this meant that a
non-ANY fixed caps was considered equal to an ANY caps if it contained a
single matching remnant internal structure.

Added some tests for these two equality methods, which covers the above
examples, as well as asserts existing behaviour.

Fixes #496

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

index 9e6408d574ea34d19b1557bd9575d4de197b992e..8ab0073e2f1d3535b26c27679fa6851eba992afe 100644 (file)
@@ -1182,6 +1182,12 @@ gst_caps_is_fixed (const GstCaps * caps)
   if (GST_CAPS_LEN (caps) != 1)
     return FALSE;
 
+  /* an ANY caps can have length 1 (rather than the usual 0) if it
+   * has had a structure appended, or if it was created from a merge
+   * or append of caps */
+  if (CAPS_IS_ANY (caps))
+    return FALSE;
+
   features = gst_caps_get_features_unchecked (caps, 0);
   if (features && gst_caps_features_is_any (features))
     return FALSE;
@@ -1427,6 +1433,14 @@ gst_caps_is_strictly_equal (const GstCaps * caps1, const GstCaps * caps2)
   if (G_UNLIKELY (caps1 == caps2))
     return TRUE;
 
+  /* if both are ANY caps, consider them strictly equal, even if
+   * internally they contain differing structures from
+   * gst_caps_append, gst_caps_merge or gst_caps_append_structure */
+  if (CAPS_IS_ANY (caps1))
+    return (CAPS_IS_ANY (caps2));
+  else if (CAPS_IS_ANY (caps2))
+    return FALSE;
+
   if (GST_CAPS_LEN (caps1) != GST_CAPS_LEN (caps2))
     return FALSE;
 
index c80d02b6b263c2c6ebeec929f42c1dbddbb23d6e..cd755667ea561fde815af52a99da61d342d478ba 100644 (file)
@@ -1408,6 +1408,202 @@ GST_START_TEST (test_filter_and_map_in_place)
 
 GST_END_TEST;
 
+GST_START_TEST (test_equality)
+{
+  GstCaps *empty1, *empty2, *any1, *any2, *caps1, *caps2, *caps3, *caps4,
+      *caps5, *caps6, *caps7, *caps8, *caps9;
+  GstStructure *s;
+
+  empty1 = gst_caps_new_empty ();
+
+  empty2 = gst_caps_new_empty ();
+
+  any1 = gst_caps_new_any ();
+
+  any2 = gst_caps_new_any ();
+  s = gst_structure_new ("structure", "int", G_TYPE_INT, 4, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (s);
+  gst_caps_append_structure (any2, s);
+
+  caps1 = gst_caps_new_simple ("structure", "int", G_TYPE_INT, 4, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (caps1);
+
+  caps2 = gst_caps_new_simple ("structure", "int", G_TYPE_INT, 4, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (caps2);
+  /* append an identical structure */
+  s = gst_structure_new ("structure", "int", G_TYPE_INT, 4, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (s);
+  gst_caps_append_structure (caps2, s);
+
+  /* change field name */
+  caps3 = gst_caps_new_simple ("structure", "intX", G_TYPE_INT, 4, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (caps3);
+
+  /* change field type */
+  caps4 = gst_caps_new_simple ("structure", "int", G_TYPE_UINT, 4, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (caps4);
+
+  /* change structure name */
+  caps5 = gst_caps_new_simple ("structureX", "int", G_TYPE_INT, 4, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (caps5);
+
+  /* change field value */
+  caps6 = gst_caps_new_simple ("structure", "int", G_TYPE_INT, 3, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (caps6);
+
+  /* change caps features */
+  caps7 = gst_caps_new_simple ("structure", "int", G_TYPE_INT, 4, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (caps6);
+  gst_caps_set_features (caps7, 0, gst_caps_features_new_any ());
+
+  /* add structure */
+  caps8 = gst_caps_new_simple ("structure", "int", G_TYPE_INT, 4, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (caps8);
+  s = gst_structure_new ("structure2", "string", G_TYPE_STRING, "val", NULL);
+  fail_unless (s);
+  gst_caps_append_structure (caps8, s);
+
+  /* reverse the order of the structures */
+  caps9 = gst_caps_new_simple ("structure2", "string", G_TYPE_STRING, "val",
+      NULL);
+  fail_unless (caps9);
+  s = gst_structure_new ("structure", "int", G_TYPE_INT, 4, "float",
+      G_TYPE_FLOAT, 5.7, NULL);
+  fail_unless (s);
+  gst_caps_append_structure (caps9, s);
+
+  fail_unless (gst_caps_is_equal (empty1, empty2) == TRUE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, empty2) == TRUE);
+  fail_unless (gst_caps_is_equal (empty1, any1) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, any1) == FALSE);
+  fail_unless (gst_caps_is_equal (empty1, any2) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, any2) == FALSE);
+  fail_unless (gst_caps_is_equal (empty1, caps1) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, caps1) == FALSE);
+  fail_unless (gst_caps_is_equal (empty1, caps2) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, caps2) == FALSE);
+  fail_unless (gst_caps_is_equal (empty1, caps3) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, caps3) == FALSE);
+  fail_unless (gst_caps_is_equal (empty1, caps4) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, caps4) == FALSE);
+  fail_unless (gst_caps_is_equal (empty1, caps5) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, caps5) == FALSE);
+  fail_unless (gst_caps_is_equal (empty1, caps6) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, caps6) == FALSE);
+  fail_unless (gst_caps_is_equal (empty1, caps7) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, caps7) == FALSE);
+  fail_unless (gst_caps_is_equal (empty1, caps8) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, caps8) == FALSE);
+  fail_unless (gst_caps_is_equal (empty1, caps9) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (empty1, caps9) == FALSE);
+
+  fail_unless (gst_caps_is_equal (any1, any2) == TRUE);
+  fail_unless (gst_caps_is_strictly_equal (any1, any2) == TRUE);
+  fail_unless (gst_caps_is_equal (any1, caps1) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any1, caps1) == FALSE);
+  fail_unless (gst_caps_is_equal (any1, caps2) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any1, caps2) == FALSE);
+  fail_unless (gst_caps_is_equal (any1, caps3) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any1, caps3) == FALSE);
+  fail_unless (gst_caps_is_equal (any1, caps4) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any1, caps4) == FALSE);
+  fail_unless (gst_caps_is_equal (any1, caps5) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any1, caps5) == FALSE);
+  fail_unless (gst_caps_is_equal (any1, caps6) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any1, caps6) == FALSE);
+  fail_unless (gst_caps_is_equal (any1, caps7) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any1, caps7) == FALSE);
+  fail_unless (gst_caps_is_equal (any1, caps8) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any1, caps8) == FALSE);
+  fail_unless (gst_caps_is_equal (any1, caps9) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any1, caps9) == FALSE);
+
+  fail_unless (gst_caps_is_equal (any2, caps1) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any2, caps1) == FALSE);
+  fail_unless (gst_caps_is_equal (any2, caps2) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any2, caps2) == FALSE);
+  fail_unless (gst_caps_is_equal (any2, caps3) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any2, caps3) == FALSE);
+  fail_unless (gst_caps_is_equal (any2, caps4) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any2, caps4) == FALSE);
+  fail_unless (gst_caps_is_equal (any2, caps5) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any2, caps5) == FALSE);
+  fail_unless (gst_caps_is_equal (any2, caps6) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any2, caps6) == FALSE);
+  fail_unless (gst_caps_is_equal (any2, caps7) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any2, caps7) == FALSE);
+  fail_unless (gst_caps_is_equal (any2, caps8) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any2, caps8) == FALSE);
+  fail_unless (gst_caps_is_equal (any2, caps9) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (any2, caps9) == FALSE);
+
+  /* caps1 and caps2 are equal, but not strictly equal because one has
+   * two copies of the same structure */
+  fail_unless (gst_caps_is_equal (caps1, caps2) == TRUE);
+  fail_unless (gst_caps_is_strictly_equal (caps1, caps2) == FALSE);
+  fail_unless (gst_caps_is_equal (caps1, caps3) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps1, caps3) == FALSE);
+  fail_unless (gst_caps_is_equal (caps1, caps4) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps1, caps4) == FALSE);
+  fail_unless (gst_caps_is_equal (caps1, caps5) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps1, caps5) == FALSE);
+  fail_unless (gst_caps_is_equal (caps1, caps6) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps1, caps6) == FALSE);
+  fail_unless (gst_caps_is_equal (caps1, caps7) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps1, caps7) == FALSE);
+  fail_unless (gst_caps_is_equal (caps1, caps8) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps1, caps8) == FALSE);
+  fail_unless (gst_caps_is_equal (caps1, caps9) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps1, caps9) == FALSE);
+
+  fail_unless (gst_caps_is_equal (caps2, caps3) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps2, caps3) == FALSE);
+  fail_unless (gst_caps_is_equal (caps2, caps4) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps2, caps4) == FALSE);
+  fail_unless (gst_caps_is_equal (caps2, caps5) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps2, caps5) == FALSE);
+  fail_unless (gst_caps_is_equal (caps2, caps6) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps2, caps6) == FALSE);
+  fail_unless (gst_caps_is_equal (caps2, caps7) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps2, caps7) == FALSE);
+  fail_unless (gst_caps_is_equal (caps2, caps8) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps2, caps8) == FALSE);
+  fail_unless (gst_caps_is_equal (caps2, caps9) == FALSE);
+  fail_unless (gst_caps_is_strictly_equal (caps2, caps9) == FALSE);
+
+  /* caps8 and caps9 are equal, but not strictly equal because their
+   * order of structures is different */
+  fail_unless (gst_caps_is_equal (caps8, caps9) == TRUE);
+  fail_unless (gst_caps_is_strictly_equal (caps8, caps9) == FALSE);
+
+  gst_caps_unref (empty1);
+  gst_caps_unref (empty2);
+  gst_caps_unref (any1);
+  gst_caps_unref (any2);
+  gst_caps_unref (caps1);
+  gst_caps_unref (caps2);
+  gst_caps_unref (caps3);
+  gst_caps_unref (caps4);
+  gst_caps_unref (caps5);
+  gst_caps_unref (caps6);
+  gst_caps_unref (caps7);
+  gst_caps_unref (caps8);
+  gst_caps_unref (caps9);
+}
+
+GST_END_TEST;
+
+
 static Suite *
 gst_caps_suite (void)
 {
@@ -1442,6 +1638,7 @@ gst_caps_suite (void)
   tcase_add_test (tc_chain, test_foreach);
   tcase_add_test (tc_chain, test_map_in_place);
   tcase_add_test (tc_chain, test_filter_and_map_in_place);
+  tcase_add_test (tc_chain, test_equality);
 
   return s;
 }