caps: ensure writable caps prior to modification
[platform/upstream/gstreamer.git] / gst / gstcaps.c
index a51f113..9fd12f2 100644 (file)
@@ -606,29 +606,30 @@ gst_caps_remove_structure (GstCaps * caps, guint idx)
 GstCaps *
 gst_caps_merge_structure (GstCaps * caps, GstStructure * structure)
 {
+  GstStructure *structure1;
+  int i;
+  gboolean unique = TRUE;
+
   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
 
-  if (G_LIKELY (structure)) {
-    GstStructure *structure1;
-    int i;
-    gboolean unique = TRUE;
-
-    /* check each structure */
-    for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) {
-      structure1 = gst_caps_get_structure_unchecked (caps, i);
-      /* if structure is a subset of structure1, then skip it */
-      if (gst_structure_is_subset (structure, structure1)) {
-        unique = FALSE;
-        break;
-      }
-    }
-    if (unique) {
-      caps = gst_caps_make_writable (caps);
-      gst_caps_append_structure_unchecked (caps, structure);
-    } else {
-      gst_structure_free (structure);
+  if (G_UNLIKELY (structure == NULL))
+    return caps;
+
+  /* check each structure */
+  for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) {
+    structure1 = gst_caps_get_structure_unchecked (caps, i);
+    /* if structure is a subset of structure1, then skip it */
+    if (gst_structure_is_subset (structure, structure1)) {
+      unique = FALSE;
+      break;
     }
   }
+  if (unique) {
+    caps = gst_caps_make_writable (caps);
+    gst_caps_append_structure_unchecked (caps, structure);
+  } else {
+    gst_structure_free (structure);
+  }
   return caps;
 }
 
@@ -1047,18 +1048,12 @@ gst_caps_is_subset_structure (const GstCaps * caps,
 gboolean
 gst_caps_is_equal (const GstCaps * caps1, const GstCaps * caps2)
 {
-  /* FIXME 0.11: NULL pointers are no valid Caps but indicate an error
-   * So there should be an assertion that caps1 and caps2 != NULL */
+  g_return_val_if_fail (GST_IS_CAPS (caps1), FALSE);
+  g_return_val_if_fail (GST_IS_CAPS (caps2), FALSE);
 
-  /* NULL <-> NULL is allowed here */
   if (G_UNLIKELY (caps1 == caps2))
     return TRUE;
 
-  /* one of them NULL => they are different (can't be both NULL because
-   * we checked that above) */
-  if (G_UNLIKELY (caps1 == NULL || caps2 == NULL))
-    return FALSE;
-
   if (G_UNLIKELY (gst_caps_is_fixed (caps1) && gst_caps_is_fixed (caps2)))
     return gst_caps_is_equal_fixed (caps1, caps2);
 
@@ -1082,18 +1077,13 @@ gboolean
 gst_caps_is_strictly_equal (const GstCaps * caps1, const GstCaps * caps2)
 {
   int i;
-  /* FIXME 0.11: NULL pointers are no valid Caps but indicate an error
-   * So there should be an assertion that caps1 and caps2 != NULL */
 
-  /* NULL <-> NULL is allowed here */
+  g_return_val_if_fail (GST_IS_CAPS (caps1), FALSE);
+  g_return_val_if_fail (GST_IS_CAPS (caps2), FALSE);
+
   if (G_UNLIKELY (caps1 == caps2))
     return TRUE;
 
-  /* one of them NULL => they are different (can't be both NULL because
-   * we checked that above) */
-  if (G_UNLIKELY (caps1 == NULL || caps2 == NULL))
-    return FALSE;
-
   if (GST_CAPS_LEN (caps1) != GST_CAPS_LEN (caps2))
     return FALSE;
 
@@ -1502,89 +1492,13 @@ gst_caps_subtract (GstCaps * minuend, GstCaps * subtrahend)
   return dest;
 }
 
-/* union operation */
-
-#if 0
-static GstStructure *
-gst_caps_structure_union (const GstStructure * struct1,
-    const GstStructure * struct2)
-{
-  int i;
-  GstStructure *dest;
-  const GstStructureField *field1;
-  const GstStructureField *field2;
-  int ret;
-
-  /* FIXME this doesn't actually work */
-
-  if (struct1->name != struct2->name)
-    return NULL;
-
-  dest = gst_structure_new_id_empty (struct1->name);
-
-  for (i = 0; i < struct1->fields->len; i++) {
-    GValue dest_value = { 0 };
-
-    field1 = GST_STRUCTURE_FIELD (struct1, i);
-    field2 = gst_structure_id_get_field (struct2, field1->name);
-
-    if (field2 == NULL) {
-      continue;
-    } else {
-      if (gst_value_union (&dest_value, &field1->value, &field2->value)) {
-        gst_structure_set_value (dest, g_quark_to_string (field1->name),
-            &dest_value);
-      } else {
-        ret = gst_value_compare (&field1->value, &field2->value);
-      }
-    }
-  }
-
-  return dest;
-}
-#endif
-
-/**
- * gst_caps_union:
- * @caps1: a #GstCaps to union
- * @caps2: a #GstCaps to union
- *
- * Creates a new #GstCaps that contains all the formats that are in
- * either @caps1 and @caps2.
- *
- * Returns: the new #GstCaps
- */
-GstCaps *
-gst_caps_union (GstCaps * caps1, GstCaps * caps2)
-{
-  GstCaps *dest1;
-
-  /* NULL pointers are no correct GstCaps */
-  g_return_val_if_fail (caps1 != NULL, NULL);
-  g_return_val_if_fail (caps2 != NULL, NULL);
-
-  if (CAPS_IS_EMPTY (caps1))
-    return gst_caps_ref (caps2);
-
-  if (CAPS_IS_EMPTY (caps2))
-    return gst_caps_ref (caps1);
-
-  if (CAPS_IS_ANY (caps1) || CAPS_IS_ANY (caps2))
-    return gst_caps_ref (caps1);
-
-  dest1 = _gst_caps_copy (caps1);
-  gst_caps_append (dest1, gst_caps_ref (caps2));
-
-  dest1 = gst_caps_simplify (dest1);
-  return dest1;
-}
-
 /* normalize/simplify operations */
 
 typedef struct _NormalizeForeach
 {
   GstCaps *caps;
   GstStructure *structure;
+  gboolean writable;
 }
 NormalizeForeach;
 
@@ -1602,6 +1516,10 @@ gst_caps_normalize_foreach (GQuark field_id, const GValue * value, gpointer ptr)
       GstStructure *structure = gst_structure_copy (nf->structure);
 
       gst_structure_id_set_value (structure, field_id, v);
+      if (G_UNLIKELY (!nf->writable)) {
+        nf->caps = gst_caps_make_writable (nf->caps);
+        nf->writable = TRUE;
+      }
       gst_caps_append_structure_unchecked (nf->caps, structure);
     }
 
@@ -1630,22 +1548,23 @@ GstCaps *
 gst_caps_normalize (GstCaps * caps)
 {
   NormalizeForeach nf;
-  GstCaps *newcaps;
   guint i;
 
   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
 
-  newcaps = gst_caps_make_writable (caps);
-  nf.caps = newcaps;
+  caps = gst_caps_make_writable (caps);
+
+  nf.caps = caps;
+  nf.writable = FALSE;
 
-  for (i = 0; i < gst_caps_get_size (newcaps); i++) {
-    nf.structure = gst_caps_get_structure_unchecked (newcaps, i);
+  for (i = 0; i < gst_caps_get_size (nf.caps); i++) {
+    nf.structure = gst_caps_get_structure_unchecked (nf.caps, i);
 
     while (!gst_structure_foreach (nf.structure,
             gst_caps_normalize_foreach, &nf));
   }
 
-  return newcaps;
+  return nf.caps;
 }
 
 static gint
@@ -1698,7 +1617,7 @@ gst_caps_structure_figure_out_union (GQuark field_id, const GValue * value,
 
 static gboolean
 gst_caps_structure_simplify (GstStructure ** result,
-    const GstStructure * simplify, GstStructure * compare)
+    GstStructure * simplify, GstStructure * compare)
 {
   GSList *list;
   UnionField field = { 0, {0,}, NULL };
@@ -1721,7 +1640,7 @@ gst_caps_structure_simplify (GstStructure ** result,
 
   /* try to union both structs */
   field.compare = compare;
-  if (gst_structure_foreach ((GstStructure *) simplify,
+  if (gst_structure_foreach (simplify,
           gst_caps_structure_figure_out_union, &field)) {
     gboolean ret = FALSE;
 
@@ -1769,11 +1688,13 @@ gst_caps_switch_structures (GstCaps * caps, GstStructure * old,
  * gst_caps_simplify:
  * @caps: (transfer full): a #GstCaps to simplify
  *
- * Modifies the given @caps inplace into a representation that represents the
+ * Converts the given @caps into a representation that represents the
  * same set of formats, but in a simpler form.  Component structures that are
  * identical are merged.  Component structures that have values that can be
  * merged are also merged.
  *
+ * This method does not preserve the original order of @caps.
+ *
  * Returns: The simplified caps.
  */
 GstCaps *
@@ -1784,14 +1705,15 @@ gst_caps_simplify (GstCaps * caps)
 
   g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
 
-  if (gst_caps_is_fixed (caps))
+  start = GST_CAPS_LEN (caps) - 1;
+  /* one caps, already as simple as can be */
+  if (start == 0)
     return caps;
 
   caps = gst_caps_make_writable (caps);
 
   g_ptr_array_sort (GST_CAPS_ARRAY (caps), gst_caps_compare_structures);
 
-  start = GST_CAPS_LEN (caps) - 1;
   for (i = start; i >= 0; i--) {
     simplify = gst_caps_get_structure_unchecked (caps, i);
     compare = gst_caps_get_structure_unchecked (caps, start);