docs: convert NULL, TRUE, and FALSE to %NULL, %TRUE, and %FALSE
[platform/upstream/gstreamer.git] / gst / gstvalue.c
index 80c59fe..a38cce0 100644 (file)
@@ -13,8 +13,8 @@
  *
  * You should have received a copy of the GNU Library General Public
  * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
  */
 
 /**
@@ -26,8 +26,6 @@
  *
  * Note that operations on the same #GValue from multiple threads may lead to
  * undefined behaviour.
- *
- * Last reviewed on 2008-03-11 (0.10.18)
  */
 
 #ifdef HAVE_CONFIG_H
@@ -65,8 +63,8 @@ typedef gboolean (*GstValueUnionFunc) (GValue * dest,
  *
  * Used by gst_value_intersect() to perform intersection for a specific #GValue
  * type. If the intersection is non-empty, the result is
- * placed in @dest and TRUE is returned.  If the intersection is
- * empty, @dest is unmodified and FALSE is returned.
+ * placed in @dest and %TRUE is returned.  If the intersection is
+ * empty, @dest is unmodified and %FALSE is returned.
  * Register a new implementation with gst_value_register_intersect_func().
  *
  * Returns: %TRUE if the values can intersect
@@ -144,6 +142,12 @@ static gchar *gst_string_wrap (const gchar * s);
 static gchar *gst_string_take_and_wrap (gchar * s);
 static gchar *gst_string_unwrap (const gchar * s);
 
+static void gst_value_move (GValue * dest, GValue * src);
+static void _gst_value_list_append_and_take_value (GValue * value,
+    GValue * append_value);
+static void _gst_value_array_append_and_take_value (GValue * value,
+    GValue * append_value);
+
 static inline GstValueTable *
 gst_value_hash_lookup_type (GType type)
 {
@@ -407,10 +411,37 @@ gst_value_list_or_array_are_compatible (const GValue * value1,
   return FALSE;
 }
 
+static inline void
+_gst_value_list_append_and_take_value (GValue * value, GValue * append_value)
+{
+  g_array_append_vals ((GArray *) value->data[0].v_pointer, append_value, 1);
+  memset (append_value, 0, sizeof (GValue));
+}
+
+/**
+ * gst_value_list_append_and_take_value:
+ * @value: a #GValue of type #GST_TYPE_LIST
+ * @append_value: (transfer full): the value to append
+ *
+ * Appends @append_value to the GstValueList in @value.
+ *
+ * Since: 1.2
+ */
+void
+gst_value_list_append_and_take_value (GValue * value, GValue * append_value)
+{
+  g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
+  g_return_if_fail (G_IS_VALUE (append_value));
+  g_return_if_fail (gst_value_list_or_array_are_compatible (value,
+          append_value));
+
+  _gst_value_list_append_and_take_value (value, append_value);
+}
+
 /**
  * gst_value_list_append_value:
  * @value: a #GValue of type #GST_TYPE_LIST
- * @append_value: the value to append
+ * @append_value: (transfer none): the value to append
  *
  * Appends @append_value to the GstValueList in @value.
  */
@@ -659,6 +690,33 @@ gst_value_array_append_value (GValue * value, const GValue * append_value)
   g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1);
 }
 
+static inline void
+_gst_value_array_append_and_take_value (GValue * value, GValue * append_value)
+{
+  g_array_append_vals ((GArray *) value->data[0].v_pointer, append_value, 1);
+  memset (append_value, 0, sizeof (GValue));
+}
+
+/**
+ * gst_value_array_append_and_take_value:
+ * @value: a #GValue of type #GST_TYPE_ARRAY
+ * @append_value: (transfer full): the value to append
+ *
+ * Appends @append_value to the GstValueArray in @value.
+ *
+ * Since: 1.2
+ */
+void
+gst_value_array_append_and_take_value (GValue * value, GValue * append_value)
+{
+  g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value));
+  g_return_if_fail (G_IS_VALUE (append_value));
+  g_return_if_fail (gst_value_list_or_array_are_compatible (value,
+          append_value));
+
+  _gst_value_array_append_and_take_value (value, append_value);
+}
+
 /**
  * gst_value_array_prepend_value:
  * @value: a #GValue of type #GST_TYPE_ARRAY
@@ -992,7 +1050,7 @@ gst_value_get_int_range_min (const GValue * value)
  *
  * Gets the maximum of the range specified by @value.
  *
- * Returns: the maxumum of the range
+ * Returns: the maximum of the range
  */
 gint
 gst_value_get_int_range_max (const GValue * value)
@@ -1051,8 +1109,8 @@ gst_value_compare_int_range (const GValue * value1, const GValue * value2)
      and bounds lie on the same value */
   if (n1 > 1) {
     if (INT_RANGE_STEP (value1) == INT_RANGE_STEP (value2) &&
-        INT_RANGE_STEP (value1) == INT_RANGE_STEP (value2) &&
-        INT_RANGE_STEP (value1) == INT_RANGE_STEP (value2)) {
+        INT_RANGE_MIN (value1) == INT_RANGE_MIN (value2) &&
+        INT_RANGE_MAX (value1) == INT_RANGE_MAX (value2)) {
       return GST_VALUE_EQUAL;
     }
     return GST_VALUE_UNORDERED;
@@ -1244,7 +1302,7 @@ gst_value_get_int64_range_min (const GValue * value)
  *
  * Gets the maximum of the range specified by @value.
  *
- * Returns: the maxumum of the range
+ * Returns: the maximum of the range
  */
 gint64
 gst_value_get_int64_range_max (const GValue * value)
@@ -1306,8 +1364,8 @@ gst_value_compare_int64_range (const GValue * value1, const GValue * value2)
      and bounds lie on the same value */
   if (n1 > 1) {
     if (INT64_RANGE_STEP (value1) == INT64_RANGE_STEP (value2) &&
-        INT64_RANGE_STEP (value1) == INT64_RANGE_STEP (value2) &&
-        INT64_RANGE_STEP (value1) == INT64_RANGE_STEP (value2)) {
+        INT64_RANGE_MIN (value1) == INT64_RANGE_MIN (value2) &&
+        INT64_RANGE_MAX (value1) == INT64_RANGE_MAX (value2)) {
       return GST_VALUE_EQUAL;
     }
     return GST_VALUE_UNORDERED;
@@ -1435,7 +1493,7 @@ gst_value_get_double_range_min (const GValue * value)
  *
  * Gets the maximum of the range specified by @value.
  *
- * Returns: the maxumum of the range
+ * Returns: the maximum of the range
  */
 gdouble
 gst_value_get_double_range_max (const GValue * value)
@@ -1462,7 +1520,7 @@ static gint
 gst_value_compare_double_range (const GValue * value1, const GValue * value2)
 {
   if (value2->data[0].v_double == value1->data[0].v_double &&
-      value2->data[0].v_double == value1->data[0].v_double)
+      value2->data[1].v_double == value1->data[1].v_double)
     return GST_VALUE_EQUAL;
   return GST_VALUE_UNORDERED;
 }
@@ -1812,12 +1870,22 @@ gst_value_get_caps (const GValue * value)
   return (GstCaps *) g_value_get_boxed (value);
 }
 
+static gint
+gst_value_compare_caps (const GValue * value1, const GValue * value2)
+{
+  GstCaps *caps1 = GST_CAPS (gst_value_get_caps (value1));
+  GstCaps *caps2 = GST_CAPS (gst_value_get_caps (value2));
+
+  if (gst_caps_is_equal (caps1, caps2))
+    return GST_VALUE_EQUAL;
+  return GST_VALUE_UNORDERED;
+}
+
 static gchar *
 gst_value_serialize_caps (const GValue * value)
 {
   GstCaps *caps = g_value_get_boxed (value);
-
-  return gst_caps_to_string (caps);
+  return gst_string_take_and_wrap (gst_caps_to_string (caps));
 }
 
 static gboolean
@@ -1825,7 +1893,17 @@ gst_value_deserialize_caps (GValue * dest, const gchar * s)
 {
   GstCaps *caps;
 
-  caps = gst_caps_from_string (s);
+  if (*s != '"') {
+    caps = gst_caps_from_string (s);
+  } else {
+    gchar *str = gst_string_unwrap (s);
+
+    if (G_UNLIKELY (!str))
+      return FALSE;
+
+    caps = gst_caps_from_string (str);
+    g_free (str);
+  }
 
   if (caps) {
     g_value_take_boxed (dest, caps);
@@ -1845,13 +1923,13 @@ gst_value_serialize_segment_internal (const GValue * value, gboolean escape)
   gchar *t, *res;
   GstStructure *s;
 
-  /* FIXME: serialize segment offset as well ? */
   s = gst_structure_new ("GstSegment",
       "flags", GST_TYPE_SEGMENT_FLAGS, seg->flags,
       "rate", G_TYPE_DOUBLE, seg->rate,
       "applied-rate", G_TYPE_DOUBLE, seg->applied_rate,
       "format", GST_TYPE_FORMAT, seg->format,
       "base", G_TYPE_UINT64, seg->base,
+      "offset", G_TYPE_UINT64, seg->offset,
       "start", G_TYPE_UINT64, seg->start,
       "stop", G_TYPE_UINT64, seg->stop,
       "time", G_TYPE_UINT64, seg->time,
@@ -1892,6 +1970,7 @@ gst_value_deserialize_segment (GValue * dest, const gchar * s)
       "applied-rate", G_TYPE_DOUBLE, &seg.applied_rate,
       "format", GST_TYPE_FORMAT, &seg.format,
       "base", G_TYPE_UINT64, &seg.base,
+      "offset", G_TYPE_UINT64, &seg.offset,
       "start", G_TYPE_UINT64, &seg.start,
       "stop", G_TYPE_UINT64, &seg.stop,
       "time", G_TYPE_UINT64, &seg.time,
@@ -1975,6 +2054,76 @@ gst_value_deserialize_structure (GValue * dest, const gchar * s)
   return FALSE;
 }
 
+/*******************
+ * GstCapsFeatures *
+ *******************/
+
+/**
+ * gst_value_set_caps_features:
+ * @value: a GValue initialized to GST_TYPE_CAPS_FEATURES
+ * @features: the features to set the value to
+ *
+ * Sets the contents of @value to @features.
+ */
+void
+gst_value_set_caps_features (GValue * value, const GstCapsFeatures * features)
+{
+  g_return_if_fail (G_IS_VALUE (value));
+  g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS_FEATURES);
+  g_return_if_fail (features == NULL || GST_IS_CAPS_FEATURES (features));
+
+  g_value_set_boxed (value, features);
+}
+
+/**
+ * gst_value_get_caps_features:
+ * @value: a GValue initialized to GST_TYPE_CAPS_FEATURES
+ *
+ * Gets the contents of @value.
+ *
+ * Returns: (transfer none): the contents of @value
+ */
+const GstCapsFeatures *
+gst_value_get_caps_features (const GValue * value)
+{
+  g_return_val_if_fail (G_IS_VALUE (value), NULL);
+  g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS_FEATURES, NULL);
+
+  return (GstCapsFeatures *) g_value_get_boxed (value);
+}
+
+static gchar *
+gst_value_serialize_caps_features (const GValue * value)
+{
+  GstCapsFeatures *features = g_value_get_boxed (value);
+
+  return gst_string_take_and_wrap (gst_caps_features_to_string (features));
+}
+
+static gboolean
+gst_value_deserialize_caps_features (GValue * dest, const gchar * s)
+{
+  GstCapsFeatures *features;
+
+  if (*s != '"') {
+    features = gst_caps_features_from_string (s);
+  } else {
+    gchar *str = gst_string_unwrap (s);
+
+    if (G_UNLIKELY (!str))
+      return FALSE;
+
+    features = gst_caps_features_from_string (str);
+    g_free (str);
+  }
+
+  if (G_LIKELY (features)) {
+    g_value_take_boxed (dest, features);
+    return TRUE;
+  }
+  return FALSE;
+}
+
 /**************
  * GstTagList *
  **************/
@@ -2381,7 +2530,7 @@ gst_value_deserialize_int_helper (gint64 * to, const gchar * s,
 {
   gboolean ret = FALSE;
   gchar *end;
-  gint64 mask = -1;
+  guint64 mask = ~0;
 
   errno = 0;
   *to = g_ascii_strtoull (s, &end, 0);
@@ -2744,7 +2893,7 @@ gst_string_take_and_wrap (gchar * s)
  * 0->3, y is copied unescaped.
  *
  * If \xyy is found where x is an octal number but y is not, an
- * error is encountered and NULL is returned.
+ * error is encountered and %NULL is returned.
  *
  * the input string must be \0 terminated.
  */
@@ -2942,16 +3091,20 @@ gst_value_deserialize_enum (GValue * dest, const gchar * s)
     found = gst_iterator_find_custom (iter,
         (GCompareFunc) gst_value_deserialize_enum_iter_cmp, &res, (gpointer) s);
 
-    g_return_val_if_fail (found, FALSE);
-    format_def = g_value_get_pointer (&res);
-    g_return_val_if_fail (format_def != NULL, FALSE);
-    g_value_set_enum (dest, (gint) format_def->value);
-    g_value_unset (&res);
+    if (found) {
+      format_def = g_value_get_pointer (&res);
+      g_return_val_if_fail (format_def != NULL, FALSE);
+      g_value_set_enum (dest, (gint) format_def->value);
+      g_value_unset (&res);
+    }
     gst_iterator_free (iter);
-    return TRUE;
+    return found;
   }
 
-  g_return_val_if_fail (en, FALSE);
+  /* enum name/nick not found */
+  if (en == NULL)
+    return FALSE;
+
   g_value_set_enum (dest, en->value);
   return TRUE;
 }
@@ -3489,19 +3642,18 @@ gst_value_intersect_list (GValue * dest, const GValue * value1,
     if (gst_value_intersect (&intersection, cur, value2)) {
       /* append value */
       if (!ret) {
-        gst_value_init_and_copy (dest, &intersection);
+        gst_value_move (dest, &intersection);
         ret = TRUE;
       } else if (GST_VALUE_HOLDS_LIST (dest)) {
-        gst_value_list_append_value (dest, &intersection);
+        _gst_value_list_append_and_take_value (dest, &intersection);
       } else {
-        GValue temp = { 0, };
+        GValue temp;
 
-        gst_value_init_and_copy (&temp, dest);
-        g_value_unset (dest);
-        gst_value_list_concat (dest, &temp, &intersection);
+        gst_value_move (&temp, dest);
+        gst_value_list_merge (dest, &temp, &intersection);
         g_value_unset (&temp);
+        g_value_unset (&intersection);
       }
-      g_value_unset (&intersection);
     }
   }
 
@@ -3540,8 +3692,7 @@ gst_value_intersect_array (GValue * dest, const GValue * src1,
       g_value_unset (dest);
       return FALSE;
     }
-    gst_value_array_append_value (dest, &val);
-    g_value_unset (&val);
+    _gst_value_array_append_and_take_value (dest, &val);
   }
 
   return TRUE;
@@ -3640,6 +3791,9 @@ gst_value_subtract_int_int_range (GValue * dest, const GValue * minuend,
   gint step = gst_value_get_int_range_step (subtrahend);
   gint val = g_value_get_int (minuend);
 
+  if (step == 0)
+    return FALSE;
+
   /* subtracting a range from an int only works if the int is not in the
    * range */
   if (val < min || val > max || val % step) {
@@ -3717,6 +3871,9 @@ gst_value_subtract_int_range_int (GValue * dest, const GValue * minuend,
 
   g_return_val_if_fail (min < max, FALSE);
 
+  if (step == 0)
+    return FALSE;
+
   /* value is outside of the range, return range unchanged */
   if (val < min || val > max || val % step) {
     if (dest)
@@ -3758,6 +3915,9 @@ gst_value_subtract_int_range_int_range (GValue * dest, const GValue * minuend,
   }
   step = step1;
 
+  if (step == 0)
+    return FALSE;
+
   if (max2 >= max1 && min2 <= min1) {
     return FALSE;
   } else if (max2 >= max1) {
@@ -3781,6 +3941,8 @@ gst_value_subtract_int64_int64_range (GValue * dest, const GValue * minuend,
   gint64 step = gst_value_get_int64_range_step (subtrahend);
   gint64 val = g_value_get_int64 (minuend);
 
+  if (step == 0)
+    return FALSE;
   /* subtracting a range from an int64 only works if the int64 is not in the
    * range */
   if (val < min || val > max || val % step) {
@@ -3858,6 +4020,9 @@ gst_value_subtract_int64_range_int64 (GValue * dest, const GValue * minuend,
 
   g_return_val_if_fail (min < max, FALSE);
 
+  if (step == 0)
+    return FALSE;
+
   /* value is outside of the range, return range unchanged */
   if (val < min || val > max || val % step) {
     if (dest)
@@ -3898,6 +4063,10 @@ gst_value_subtract_int64_range_int64_range (GValue * dest,
     g_assert (FALSE);
     return FALSE;
   }
+
+  if (step1 == 0)
+    return FALSE;
+
   step = step1;
 
   if (max2 >= max1 && min2 <= min1) {
@@ -4014,20 +4183,19 @@ gst_value_subtract_from_list (GValue * dest, const GValue * minuend,
 
     if (gst_value_subtract (&subtraction, cur, subtrahend)) {
       if (!ret) {
-        gst_value_init_and_copy (dest, &subtraction);
+        gst_value_move (dest, &subtraction);
         ret = TRUE;
       } else if (G_VALUE_HOLDS (dest, ltype)
           && !G_VALUE_HOLDS (&subtraction, ltype)) {
-        gst_value_list_append_value (dest, &subtraction);
+        _gst_value_list_append_and_take_value (dest, &subtraction);
       } else {
-        GValue temp = { 0, };
+        GValue temp;
 
-        gst_value_init_and_copy (&temp, dest);
-        g_value_unset (dest);
+        gst_value_move (&temp, dest);
         gst_value_list_concat (dest, &temp, &subtraction);
         g_value_unset (&temp);
+        g_value_unset (&subtraction);
       }
-      g_value_unset (&subtraction);
     }
   }
   return ret;
@@ -4057,9 +4225,11 @@ gst_value_subtract_list (GValue * dest, const GValue * minuend,
       return FALSE;
     }
   }
-  if (dest)
-    gst_value_init_and_copy (dest, result);
-  g_value_unset (result);
+  if (dest) {
+    gst_value_move (dest, result);
+  } else {
+    g_value_unset (result);
+  }
   return TRUE;
 }
 
@@ -4217,7 +4387,7 @@ gst_value_get_compare_func (const GValue * value1)
  *
  * Determines if @value1 and @value2 can be compared.
  *
- * Returns: TRUE if the values can be compared
+ * Returns: %TRUE if the values can be compared
  */
 gboolean
 gst_value_can_compare (const GValue * value1, const GValue * value2)
@@ -4254,6 +4424,8 @@ gst_value_list_equals_range (const GValue * list, const GValue * value)
     const gint rmin = gst_value_get_int_range_min (value);
     const gint rmax = gst_value_get_int_range_max (value);
     const gint rstep = gst_value_get_int_range_step (value);
+    if (rstep == 0)
+      return FALSE;
     /* note: this will overflow for min 0 and max INT_MAX, but this
        would only be equal to a list of INT_MAX elements, which seems
        very unlikely */
@@ -4271,6 +4443,8 @@ gst_value_list_equals_range (const GValue * list, const GValue * value)
     const gint64 rmax = gst_value_get_int64_range_max (value);
     const gint64 rstep = gst_value_get_int64_range_step (value);
     GST_DEBUG ("List/range of int64s");
+    if (rstep == 0)
+      return FALSE;
     if (list_size != rmax / rstep - rmin / rstep + 1)
       return FALSE;
     for (n = 0; n < list_size; ++n) {
@@ -4312,24 +4486,51 @@ gst_value_compare (const GValue * value1, const GValue * value2)
      as well as lists and ranges ("{ 1, 2 }" and "[ 1, 2 ]" are equal) */
   ltype = gst_value_list_get_type ();
   if (G_VALUE_HOLDS (value1, ltype) && !G_VALUE_HOLDS (value2, ltype)) {
+    gint i, n, ret;
 
     if (gst_value_list_equals_range (value1, value2)) {
       return GST_VALUE_EQUAL;
-    } else if (gst_value_list_get_size (value1) == 1) {
+    }
+
+    n = gst_value_list_get_size (value1);
+    if (n == 0)
+      return GST_VALUE_UNORDERED;
+
+    for (i = 0; i < n; i++) {
       const GValue *elt;
 
-      elt = gst_value_list_get_value (value1, 0);
-      return gst_value_compare (elt, value2);
+      elt = gst_value_list_get_value (value1, i);
+      ret = gst_value_compare (elt, value2);
+      if (ret != GST_VALUE_EQUAL && n == 1)
+        return ret;
+      else if (ret != GST_VALUE_EQUAL)
+        return GST_VALUE_UNORDERED;
     }
+
+    return GST_VALUE_EQUAL;
   } else if (G_VALUE_HOLDS (value2, ltype) && !G_VALUE_HOLDS (value1, ltype)) {
+    gint i, n, ret;
+
     if (gst_value_list_equals_range (value2, value1)) {
       return GST_VALUE_EQUAL;
-    } else if (gst_value_list_get_size (value2) == 1) {
+    }
+
+    n = gst_value_list_get_size (value2);
+    if (n == 0)
+      return GST_VALUE_UNORDERED;
+
+    for (i = 0; i < n; i++) {
       const GValue *elt;
 
-      elt = gst_value_list_get_value (value2, 0);
-      return gst_value_compare (elt, value1);
+      elt = gst_value_list_get_value (value2, i);
+      ret = gst_value_compare (elt, value1);
+      if (ret != GST_VALUE_EQUAL && n == 1)
+        return ret;
+      else if (ret != GST_VALUE_EQUAL)
+        return GST_VALUE_UNORDERED;
     }
+
+    return GST_VALUE_EQUAL;
   }
 
   if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
@@ -4378,13 +4579,13 @@ gst_value_compare_with_func (const GValue * value1, const GValue * value2,
  *
  * Determines if @value1 and @value2 can be non-trivially unioned.
  * Any two values can be trivially unioned by adding both of them
- * to a GstValueList.  However, certain types have the possibility
+ * to a #GstValueList.  However, certain types have the possibility
  * to be unioned in a simpler way.  For example, an integer range
  * and an integer can be unioned if the integer is a subset of the
  * integer range.  If there is the possibility that two values can
- * be unioned, this function returns TRUE.
+ * be unioned, this function returns %TRUE.
  *
- * Returns: TRUE if there is a function allowing the two values to
+ * Returns: %TRUE if there is a function allowing the two values to
  * be unioned.
  */
 gboolean
@@ -4419,7 +4620,7 @@ gst_value_can_union (const GValue * value1, const GValue * value2)
  *
  * Creates a GValue corresponding to the union of @value1 and @value2.
  *
- * Returns: TRUE if the union suceeded.
+ * Returns: %TRUE if the union succeeded.
  */
 gboolean
 gst_value_union (GValue * dest, const GValue * value1, const GValue * value2)
@@ -4485,10 +4686,9 @@ gst_value_register_union_func (GType type1, GType type2, GstValueUnionFunc func)
  *
  * Determines if intersecting two values will produce a valid result.
  * Two values will produce a valid intersection if they have the same
- * type, or if there is a method (registered by
- * gst_value_register_intersect_func()) to calculate the intersection.
+ * type.
  *
- * Returns: TRUE if the values can intersect
+ * Returns: %TRUE if the values can intersect
  */
 gboolean
 gst_value_can_intersect (const GValue * value1, const GValue * value2)
@@ -4530,16 +4730,16 @@ gst_value_can_intersect (const GValue * value1, const GValue * value2)
 /**
  * gst_value_intersect:
  * @dest: (out caller-allocates) (transfer full): a uninitialized #GValue that will hold the calculated
- * intersection value. May be NULL if the resulting set if not needed.
+ * intersection value. May be %NULL if the resulting set if not needed.
  * @value1: a value to intersect
  * @value2: another value to intersect
  *
  * Calculates the intersection of two values.  If the values have
  * a non-empty intersection, the value representing the intersection
- * is placed in @dest, unless NULL.  If the intersection is non-empty,
+ * is placed in @dest, unless %NULL.  If the intersection is non-empty,
  * @dest is not modified.
  *
- * Returns: TRUE if the intersection is non-empty
+ * Returns: %TRUE if the intersection is non-empty
  */
 gboolean
 gst_value_intersect (GValue * dest, const GValue * value1,
@@ -4617,7 +4817,7 @@ gst_value_register_intersect_func (GType type1, GType type2,
 /**
  * gst_value_subtract:
  * @dest: (out caller-allocates): the destination value for the result if the
- *     subtraction is not empty. May be NULL, in which case the resulting set
+ *     subtraction is not empty. May be %NULL, in which case the resulting set
  *     will not be computed, which can give a fair speedup.
  * @minuend: the value to subtract from
  * @subtrahend: the value to subtract
@@ -4687,7 +4887,7 @@ gst_value_subtract (GValue * dest, const GValue * minuend,
  *
  * Checks if it's possible to subtract @subtrahend from @minuend.
  *
- * Returns: TRUE if a subtraction is possible
+ * Returns: %TRUE if a subtraction is possible
  */
 gboolean
 gst_value_can_subtract (const GValue * minuend, const GValue * subtrahend)
@@ -4736,11 +4936,8 @@ gst_value_register_subtract_func (GType minuend_type, GType subtrahend_type,
 {
   GstValueSubtractInfo info;
 
-  /* one type must be unfixed, other subtractions can be done as comparisons,
-   * special case: bitmasks */
-  if (minuend_type != GST_TYPE_BITMASK)
-    g_return_if_fail (!gst_type_is_fixed (minuend_type)
-        || !gst_type_is_fixed (subtrahend_type));
+  g_return_if_fail (!gst_type_is_fixed (minuend_type)
+      || !gst_type_is_fixed (subtrahend_type));
 
   info.minuend = minuend_type;
   info.subtrahend = subtrahend_type;
@@ -4792,6 +4989,17 @@ gst_value_init_and_copy (GValue * dest, const GValue * src)
   g_value_copy (src, dest);
 }
 
+/* move src into dest and clear src */
+static void
+gst_value_move (GValue * dest, GValue * src)
+{
+  g_assert (G_IS_VALUE (src));
+  g_assert (dest != NULL);
+
+  *dest = *src;
+  memset (src, 0, sizeof (GValue));
+}
+
 /**
  * gst_value_serialize:
  * @value: a #GValue to serialize
@@ -4801,7 +5009,7 @@ gst_value_init_and_copy (GValue * dest, const GValue * src)
  *
  * Free-function: g_free
  *
- * Returns: (transfer full): the serialization for @value or NULL if none exists
+ * Returns: (transfer full): the serialization for @value or %NULL if none exists
  */
 gchar *
 gst_value_serialize (const GValue * value)
@@ -4850,9 +5058,9 @@ gst_value_serialize (const GValue * value)
  * @src: string to deserialize
  *
  * Tries to deserialize a string into the type specified by the given GValue.
- * If the operation succeeds, TRUE is returned, FALSE otherwise.
+ * If the operation succeeds, %TRUE is returned, %FALSE otherwise.
  *
- * Returns: TRUE on success
+ * Returns: %TRUE on success
  */
 gboolean
 gst_value_deserialize (GValue * dest, const gchar * src)
@@ -4934,9 +5142,9 @@ gst_value_is_fixed (const GValue * value)
  * Fixate @src into a new value @dest.
  * For ranges, the first element is taken. For lists and arrays, the
  * first item is fixated and returned.
- * If @src is already fixed, this function returns FALSE.
+ * If @src is already fixed, this function returns %FALSE.
  *
- * Returns: true if @dest contains a fixated version of @src.
+ * Returns: %TRUE if @dest contains a fixated version of @src.
  */
 gboolean
 gst_value_fixate (GValue * dest, const GValue * src)
@@ -4961,9 +5169,11 @@ gst_value_fixate (GValue * dest, const GValue * src)
 
     gst_value_init_and_copy (&temp, gst_value_list_get_value (src, 0));
 
-    if (!gst_value_fixate (dest, &temp))
-      gst_value_init_and_copy (dest, &temp);
-    g_value_unset (&temp);
+    if (!gst_value_fixate (dest, &temp)) {
+      gst_value_move (dest, &temp);
+    } else {
+      g_value_unset (&temp);
+    }
   } else if (G_VALUE_TYPE (src) == GST_TYPE_ARRAY) {
     gboolean res = FALSE;
     guint n, len;
@@ -4978,8 +5188,7 @@ gst_value_fixate (GValue * dest, const GValue * src)
         gst_value_init_and_copy (&kid, orig_kid);
       else
         res = TRUE;
-      gst_value_array_append_value (dest, &kid);
-      g_value_unset (&kid);
+      _gst_value_array_append_and_take_value (dest, &kid);
     }
 
     if (!res)
@@ -5139,7 +5348,7 @@ gst_value_get_fraction_denominator (const GValue * value)
  * Multiplies the two #GValue items containing a #GST_TYPE_FRACTION and sets
  * @product to the product of the two fractions.
  *
- * Returns: FALSE in case of an error (like integer overflow), TRUE otherwise.
+ * Returns: %FALSE in case of an error (like integer overflow), %TRUE otherwise.
  */
 gboolean
 gst_value_fraction_multiply (GValue * product, const GValue * factor1,
@@ -5173,7 +5382,7 @@ gst_value_fraction_multiply (GValue * product, const GValue * factor1,
  *
  * Subtracts the @subtrahend from the @minuend and sets @dest to the result.
  *
- * Returns: FALSE in case of an error (like integer overflow), TRUE otherwise.
+ * Returns: %FALSE in case of an error (like integer overflow), %TRUE otherwise.
  */
 gboolean
 gst_value_fraction_subtract (GValue * dest,
@@ -5528,7 +5737,7 @@ gst_value_lcopy_bitmask (const GValue * value, guint n_collect_values,
 
 /**
  * gst_value_set_bitmask:
- * @value: a GValue initialized to #GST_TYPE_FRACTION
+ * @value: a GValue initialized to #GST_TYPE_BITMASK
  * @bitmask: the bitmask
  *
  * Sets @value to the bitmask specified by @bitmask.
@@ -5543,7 +5752,7 @@ gst_value_set_bitmask (GValue * value, guint64 bitmask)
 
 /**
  * gst_value_get_bitmask:
- * @value: a GValue initialized to #GST_TYPE_FRACTION
+ * @value: a GValue initialized to #GST_TYPE_BITMASK
  *
  * Gets the bitmask specified by @value.
  *
@@ -5617,65 +5826,58 @@ gst_value_transform_bitmask_uint64 (const GValue * src_value,
   dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
 }
 
-static gboolean
-gst_value_intersect_bitmask_bitmask (GValue * dest, const GValue * src1,
-    const GValue * src2)
+static gint
+gst_value_compare_bitmask (const GValue * value1, const GValue * value2)
 {
-  guint64 s1, s2;
+  guint64 v1, v2;
 
-  s1 = gst_value_get_bitmask (src1);
-  s2 = gst_value_get_bitmask (src2);
+  v1 = value1->data[0].v_uint64;
+  v2 = value2->data[0].v_uint64;
 
-  if (dest) {
-    g_value_init (dest, GST_TYPE_BITMASK);
-    gst_value_set_bitmask (dest, s1 & s2);
-  }
+  if (v1 == v2)
+    return GST_VALUE_EQUAL;
 
-  return TRUE;
+  return GST_VALUE_UNORDERED;
 }
 
-static gboolean
-gst_value_union_bitmask_bitmask (GValue * dest, const GValue * src1,
-    const GValue * src2)
+
+/***********************
+ * GstAllocationParams *
+ ***********************/
+static gint
+gst_value_compare_allocation_params (const GValue * value1,
+    const GValue * value2)
 {
-  guint64 s1, s2;
+  GstAllocationParams *v1, *v2;
 
-  s1 = gst_value_get_bitmask (src1);
-  s2 = gst_value_get_bitmask (src2);
+  v1 = value1->data[0].v_pointer;
+  v2 = value2->data[0].v_pointer;
 
-  g_value_init (dest, GST_TYPE_BITMASK);
-  gst_value_set_bitmask (dest, s1 | s2);
+  if (v1 == NULL && v1 == v2)
+    return GST_VALUE_EQUAL;
 
-  return TRUE;
-}
+  if (v1 == NULL || v2 == NULL)
+    return GST_VALUE_UNORDERED;
 
-static gboolean
-gst_value_subtract_bitmask_bitmask (GValue * dest,
-    const GValue * minuend, const GValue * subtrahend)
-{
-  guint64 m, s, r;
+  if (v1->flags == v2->flags && v1->align == v2->align &&
+      v1->prefix == v2->prefix && v1->padding == v2->padding)
+    return GST_VALUE_EQUAL;
 
-  g_return_val_if_fail (GST_VALUE_HOLDS_BITMASK (minuend), FALSE);
-  g_return_val_if_fail (GST_VALUE_HOLDS_BITMASK (subtrahend), FALSE);
+  return GST_VALUE_UNORDERED;
+}
 
-  m = minuend->data[0].v_uint64;
-  s = subtrahend->data[0].v_uint64;
-  r = m & (~s);
 
-  if (dest) {
-    g_value_init (dest, GST_TYPE_BITMASK);
-    gst_value_set_bitmask (dest, r);
-  }
-  return (r != 0);
-}
+/************
+ * GObject *
+ ************/
 
 static gint
-gst_value_compare_bitmask (const GValue * value1, const GValue * value2)
+gst_value_compare_object (const GValue * value1, const GValue * value2)
 {
-  guint64 v1, v2;
+  gpointer v1, v2;
 
-  v1 = value1->data[0].v_uint64;
-  v2 = value2->data[0].v_uint64;
+  v1 = value1->data[0].v_pointer;
+  v2 = value2->data[0].v_pointer;
 
   if (v1 == v2)
     return GST_VALUE_EQUAL;
@@ -5843,6 +6045,25 @@ static const GTypeValueTable _gst_bitmask_value_table = {
 
 FUNC_VALUE_GET_TYPE (bitmask, "GstBitmask");
 
+GType
+gst_g_thread_get_type (void)
+{
+#if GLIB_CHECK_VERSION(2,35,3)
+  return G_TYPE_THREAD;
+#else
+  static volatile gsize type_id = 0;
+
+  if (g_once_init_enter (&type_id)) {
+    GType tmp =
+        g_boxed_type_register_static (g_intern_static_string ("GstGThread"),
+        (GBoxedCopyFunc) g_thread_ref,
+        (GBoxedFreeFunc) g_thread_unref);
+    g_once_init_leave (&type_id, tmp);
+  }
+
+  return type_id;
+#endif
+}
 
 void
 _priv_gst_value_initialize (void)
@@ -5976,7 +6197,7 @@ _priv_gst_value_initialize (void)
   {
     static GstValueTable gst_value = {
       0,
-      NULL,
+      gst_value_compare_caps,
       gst_value_serialize_caps,
       gst_value_deserialize_caps,
     };
@@ -6010,6 +6231,17 @@ _priv_gst_value_initialize (void)
     static GstValueTable gst_value = {
       0,
       NULL,
+      gst_value_serialize_caps_features,
+      gst_value_deserialize_caps_features,
+    };
+
+    gst_value.type = GST_TYPE_CAPS_FEATURES;
+    gst_value_register (&gst_value);
+  }
+  {
+    static GstValueTable gst_value = {
+      0,
+      NULL,
       gst_value_serialize_tag_list,
       gst_value_deserialize_tag_list,
     };
@@ -6052,6 +6284,30 @@ _priv_gst_value_initialize (void)
     gst_value_register (&gst_value);
   }
 
+  {
+    static GstValueTable gst_value = {
+      0,
+      gst_value_compare_allocation_params,
+      NULL,
+      NULL,
+    };
+
+    gst_value.type = gst_allocation_params_get_type ();
+    gst_value_register (&gst_value);
+  }
+
+  {
+    static GstValueTable gst_value = {
+      0,
+      gst_value_compare_object,
+      NULL,
+      NULL,
+    };
+
+    gst_value.type = G_TYPE_OBJECT;
+    gst_value_register (&gst_value);
+  }
+
   REGISTER_SERIALIZATION (G_TYPE_DOUBLE, double);
   REGISTER_SERIALIZATION (G_TYPE_FLOAT, float);
 
@@ -6130,8 +6386,6 @@ _priv_gst_value_initialize (void)
   gst_value_register_intersect_func (GST_TYPE_FRACTION_RANGE,
       GST_TYPE_FRACTION_RANGE,
       gst_value_intersect_fraction_range_fraction_range);
-  gst_value_register_intersect_func (GST_TYPE_BITMASK,
-      GST_TYPE_BITMASK, gst_value_intersect_bitmask_bitmask);
 
   gst_value_register_subtract_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
       gst_value_subtract_int_int_range);
@@ -6158,8 +6412,6 @@ _priv_gst_value_initialize (void)
   gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE,
       GST_TYPE_FRACTION_RANGE,
       gst_value_subtract_fraction_range_fraction_range);
-  gst_value_register_subtract_func (GST_TYPE_BITMASK,
-      GST_TYPE_BITMASK, gst_value_subtract_bitmask_bitmask);
 
   /* see bug #317246, #64994, #65041 */
   {
@@ -6172,8 +6424,6 @@ _priv_gst_value_initialize (void)
       gst_value_union_int_int_range);
   gst_value_register_union_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
       gst_value_union_int_range_int_range);
-  gst_value_register_union_func (GST_TYPE_BITMASK,
-      GST_TYPE_BITMASK, gst_value_union_bitmask_bitmask);
 
 #if 0
   /* Implement these if needed */