gst: Add some more Since: 1.2
[platform/upstream/gstreamer.git] / gst / gstcaps.c
index 4b6350d..7e10a2a 100644 (file)
@@ -102,7 +102,7 @@ typedef struct _GstCapsImpl
 #define CAPS_IS_EMPTY_SIMPLE(caps)                                     \
   ((GST_CAPS_ARRAY (caps) == NULL) || (GST_CAPS_LEN (caps) == 0))
 
-#define gst_caps_features_copy_conditional(f) ((f && !gst_caps_features_is_equal (f, GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY)) ? gst_caps_features_copy (f) : NULL)
+#define gst_caps_features_copy_conditional(f) ((f && (gst_caps_features_is_any (f) || !gst_caps_features_is_equal (f, GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY))) ? gst_caps_features_copy (f) : NULL)
 
 /* quick way to get a caps structure at an index without doing a type or array
  * length check */
@@ -113,10 +113,6 @@ typedef struct _GstCapsImpl
 /* quick way to append a structure without checking the args */
 #define gst_caps_append_structure_unchecked(caps, s, f) G_STMT_START{\
   GstCapsArrayElement __e={s, f};                                      \
-  if (__e.features && gst_caps_features_is_equal (GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY, __e.features)) { \
-    gst_caps_features_free (__e.features); \
-    __e.features = NULL; \
-  } \
   if (gst_structure_set_parent_refcount (__e.structure, &GST_MINI_OBJECT_REFCOUNT(caps)) && \
       (!__e.features || gst_caps_features_set_parent_refcount (__e.features, &GST_MINI_OBJECT_REFCOUNT(caps))))         \
     g_array_append_val (GST_CAPS_ARRAY (caps), __e);                             \
@@ -628,6 +624,8 @@ gst_caps_append_structure (GstCaps * caps, GstStructure * structure)
  *
  * Appends @structure with @features to @caps.  The structure is not copied; @caps
  * becomes the owner of @structure.
+ *
+ * Since: 1.2
  */
 void
 gst_caps_append_structure_full (GstCaps * caps, GstStructure * structure,
@@ -693,9 +691,9 @@ gst_caps_merge_structure (GstCaps * caps, GstStructure * structure)
 
     /* if structure is a subset of structure1 and the
      * there are no existing features, then skip it */
-    if (gst_structure_is_subset (structure, structure1) &&
-        gst_caps_features_is_equal (features1,
-            GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY)) {
+    if (gst_caps_features_is_equal (features1,
+            GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY)
+        && gst_structure_is_subset (structure, structure1)) {
       unique = FALSE;
       break;
     }
@@ -718,6 +716,8 @@ gst_caps_merge_structure (GstCaps * caps, GstStructure * structure)
  * Appends @structure with @features to @caps if its not already expressed by @caps.
  *
  * Returns: (transfer full): the merged caps.
+ *
+ * Since: 1.2
  */
 GstCaps *
 gst_caps_merge_structure_full (GstCaps * caps, GstStructure * structure,
@@ -744,8 +744,15 @@ gst_caps_merge_structure_full (GstCaps * caps, GstStructure * structure,
       features1 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
     /* if structure is a subset of structure1 and the
      * the features are a subset, then skip it */
-    if (gst_structure_is_subset (structure, structure1) &&
-        gst_caps_features_is_equal (features_tmp, features1)) {
+    /* FIXME: We only skip if none of the features are
+     * ANY and are still equal. That way all ANY structures
+     * show up in the caps and no non-ANY structures are
+     * swallowed by ANY structures
+     */
+    if (((!gst_caps_features_is_any (features_tmp)
+                || gst_caps_features_is_any (features1))
+            && gst_caps_features_is_equal (features_tmp, features1))
+        && gst_structure_is_subset (structure, structure1)) {
       unique = FALSE;
       break;
     }
@@ -831,6 +838,8 @@ gst_caps_get_structure (const GstCaps * caps, guint index)
  *
  * Returns: (transfer none): a pointer to the #GstCapsFeatures corresponding
  *     to @index
+ *
+ * Since: 1.2
  */
 GstCapsFeatures *
 gst_caps_get_features (const GstCaps * caps, guint index)
@@ -842,7 +851,7 @@ gst_caps_get_features (const GstCaps * caps, guint index)
 
   features = gst_caps_get_features_unchecked (caps, index);
   if (!features)
-    features = gst_caps_features_copy (GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY);
+    features = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
 
   return features;
 }
@@ -854,6 +863,8 @@ gst_caps_get_features (const GstCaps * caps, guint index)
  * @features: (allow-none) (transfer full): the #GstFeatures to set
  *
  * Sets the #GstCapsFeatures @features for the structure at @index.
+ *
+ * Since: 1.2
  */
 void
 gst_caps_set_features (GstCaps * caps, guint index, GstCapsFeatures * features)
@@ -867,6 +878,10 @@ gst_caps_set_features (GstCaps * caps, guint index, GstCapsFeatures * features)
   storage = &gst_caps_get_features_unchecked (caps, index);
   old = *storage;
   *storage = features;
+
+  if (features)
+    gst_caps_features_set_parent_refcount (features, &GST_CAPS_REFCOUNT (caps));
+
   if (old)
     gst_caps_features_free (old);
 }
@@ -1075,12 +1090,17 @@ gboolean
 gst_caps_is_fixed (const GstCaps * caps)
 {
   GstStructure *structure;
+  GstCapsFeatures *features;
 
   g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
 
   if (GST_CAPS_LEN (caps) != 1)
     return FALSE;
 
+  features = gst_caps_get_features (caps, 0);
+  if (features && gst_caps_features_is_any (features))
+    return FALSE;
+
   structure = gst_caps_get_structure_unchecked (caps, 0);
 
   return gst_structure_foreach (structure, gst_caps_is_fixed_foreach, NULL);
@@ -1144,8 +1164,6 @@ gst_caps_is_always_compatible (const GstCaps * caps1, const GstCaps * caps2)
  * @superset: a potentially greater #GstCaps
  *
  * Checks if all caps represented by @subset are also represented by @superset.
- * <note>This function does not work reliably if optional properties for caps
- * are included on one caps and omitted on the other.</note>
  *
  * Returns: %TRUE if @subset is a subset of @superset
  */
@@ -1175,8 +1193,9 @@ gst_caps_is_subset (const GstCaps * subset, const GstCaps * superset)
       f2 = gst_caps_get_features_unchecked (superset, j);
       if (!f2)
         f2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
-      if (gst_structure_is_subset (s1, s2) &&
-          gst_caps_features_is_equal (f1, f2)) {
+      if ((!gst_caps_features_is_any (f1) || gst_caps_features_is_any (f2)) &&
+          gst_caps_features_is_equal (f1, f2)
+          && gst_structure_is_subset (s1, s2)) {
         /* If we found a superset, continue with the next
          * subset structure */
         break;
@@ -1239,6 +1258,8 @@ gst_caps_is_subset_structure (const GstCaps * caps,
  * for more information.
  *
  * Returns: %TRUE if @structure is a subset of @caps
+ *
+ * Since: 1.2
  */
 gboolean
 gst_caps_is_subset_structure_full (const GstCaps * caps,
@@ -1264,8 +1285,9 @@ gst_caps_is_subset_structure_full (const GstCaps * caps,
     f = gst_caps_get_features_unchecked (caps, i);
     if (!f)
       f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
-    if (gst_structure_is_subset (structure, s) &&
-        gst_caps_features_is_equal (features, f)) {
+    if ((!gst_caps_features_is_any (features) || gst_caps_features_is_any (f))
+        && gst_caps_features_is_equal (features, f)
+        && gst_structure_is_subset (structure, s)) {
       /* If we found a superset return TRUE */
       return TRUE;
     }
@@ -1280,8 +1302,6 @@ gst_caps_is_subset_structure_full (const GstCaps * caps,
  * @caps2: another #GstCaps
  *
  * Checks if the given caps represent the same set of caps.
- * <note>This function does not work reliably if optional properties for caps
- * are included on one caps and omitted on the other.</note>
  *
  * Returns: TRUE if both caps are equal.
  */
@@ -1335,8 +1355,9 @@ gst_caps_is_strictly_equal (const GstCaps * caps1, const GstCaps * caps2)
     if (!f2)
       f2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
 
-    if (!gst_structure_is_equal (s1, s2)
-        || !gst_caps_features_is_equal (f1, f2))
+    if (gst_caps_features_is_any (f1) != gst_caps_features_is_any (f2) ||
+        !gst_caps_features_is_equal (f1, f2) ||
+        !gst_structure_is_equal (s1, s2))
       return FALSE;
   }
 
@@ -1416,8 +1437,8 @@ gst_caps_can_intersect (const GstCaps * caps1, const GstCaps * caps2)
       features2 = gst_caps_get_features_unchecked (caps2, k);
       if (!features2)
         features2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
-      if (gst_structure_can_intersect (struct1, struct2) &&
-          gst_caps_features_is_equal (features1, features2)) {
+      if (gst_caps_features_is_equal (features1, features2) &&
+          gst_structure_can_intersect (struct1, struct2)) {
         return TRUE;
       }
       /* move down left */
@@ -1494,11 +1515,19 @@ gst_caps_intersect_zig_zag (GstCaps * caps1, GstCaps * caps2)
       features2 = gst_caps_get_features_unchecked (caps2, k);
       if (!features2)
         features2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
-      istruct = gst_structure_intersect (struct1, struct2);
-      if (istruct && gst_caps_features_is_equal (features1, features2))
-        dest =
-            gst_caps_merge_structure_full (dest, istruct,
-            gst_caps_features_copy_conditional (features1));
+      if (gst_caps_features_is_equal (features1, features2)) {
+        istruct = gst_structure_intersect (struct1, struct2);
+        if (istruct) {
+          if (gst_caps_features_is_any (features1))
+            dest =
+                gst_caps_merge_structure_full (dest, istruct,
+                gst_caps_features_copy_conditional (features2));
+          else
+            dest =
+                gst_caps_merge_structure_full (dest, istruct,
+                gst_caps_features_copy_conditional (features1));
+        }
+      }
       /* move down left */
       k++;
       if (G_UNLIKELY (j == 0))
@@ -1562,9 +1591,19 @@ gst_caps_intersect_first (GstCaps * caps1, GstCaps * caps2)
       features2 = gst_caps_get_features_unchecked (caps2, j);
       if (!features2)
         features2 = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
-      istruct = gst_structure_intersect (struct1, struct2);
-      if (istruct && gst_caps_features_is_equal (features1, features2))
-        dest = gst_caps_merge_structure (dest, istruct);
+      if (gst_caps_features_is_equal (features1, features2)) {
+        istruct = gst_structure_intersect (struct1, struct2);
+        if (istruct) {
+          if (gst_caps_features_is_any (features1))
+            dest =
+                gst_caps_merge_structure_full (dest, istruct,
+                gst_caps_features_copy_conditional (features2));
+          else
+            dest =
+                gst_caps_merge_structure_full (dest, istruct,
+                gst_caps_features_copy_conditional (features1));
+        }
+      }
     }
   }
 
@@ -1739,6 +1778,10 @@ gst_caps_subtract (GstCaps * minuend, GstCaps * subtrahend)
       min_f = gst_caps_get_features_unchecked (src, j);
       if (!min_f)
         min_f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
+
+      /* Same reason as above for ANY caps */
+      g_return_val_if_fail (!gst_caps_features_is_any (min_f), NULL);
+
       if (gst_structure_get_name_id (min) == gst_structure_get_name_id (sub) &&
           gst_caps_features_is_equal (min_f, sub_f)) {
         GSList *list;
@@ -2051,6 +2094,7 @@ GstCaps *
 gst_caps_fixate (GstCaps * caps)
 {
   GstStructure *s;
+  GstCapsFeatures *f;
 
   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
 
@@ -2060,6 +2104,13 @@ gst_caps_fixate (GstCaps * caps)
   s = gst_caps_get_structure (caps, 0);
   gst_structure_fixate (s);
 
+  /* Set features to sysmem if they're still ANY */
+  f = gst_caps_get_features (caps, 0);
+  if (f && gst_caps_features_is_any (f)) {
+    f = gst_caps_features_new_empty ();
+    gst_caps_set_features (caps, 0, f);
+  }
+
   return caps;
 }
 
@@ -2130,9 +2181,9 @@ gst_caps_to_string (const GstCaps * caps)
     features = gst_caps_get_features_unchecked (caps, i);
 
     g_string_append (s, gst_structure_get_name (structure));
-    if (features
-        && !gst_caps_features_is_equal (features,
-            GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY)) {
+    if (features && (gst_caps_features_is_any (features)
+            || !gst_caps_features_is_equal (features,
+                GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY))) {
       g_string_append_c (s, '(');
       priv_gst_caps_features_append_to_gstring (features, s);
       g_string_append_c (s, ')');