aggregator: Assert if the sink/src pad type that is to be used is not a GstAggregator...
[platform/upstream/gstreamer.git] / gst / gstcapsfeatures.c
index 3a50254..2f433a2 100644 (file)
@@ -20,7 +20,8 @@
 
 /**
  * SECTION:gstcapsfeatures
- * @short_description: A set of features in caps 
+ * @title: GstCapsFeatures
+ * @short_description: A set of features in caps
  * @see_also: #GstCaps
  *
  * #GstCapsFeatures can optionally be set on a #GstCaps to add requirements
  * structures with different feature sets to the caps.
  *
  * Empty #GstCapsFeatures are equivalent with the #GstCapsFeatures that only
- * contain #GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY.
+ * contain #GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY. ANY #GstCapsFeatures as
+ * created by gst_caps_features_new_any() are equal to any other #GstCapsFeatures
+ * and can be used to specify that any #GstCapsFeatures would be supported, e.g.
+ * for elements that don't touch buffer memory. #GstCaps with ANY #GstCapsFeatures
+ * are considered non-fixed and during negotiation some #GstCapsFeatures have
+ * to be selected.
  *
  * Examples for caps features would be the requirement of a specific #GstMemory
  * types or the requirement of having a specific #GstMeta on the buffer. Features
  * are given as a string of the format "memory:GstMemoryTypeName" or
  * "meta:GstMetaAPIName".
+ *
+ * Since: 1.2
  */
 
 #ifdef HAVE_CONFIG_H
@@ -55,9 +63,12 @@ struct _GstCapsFeatures
   GType type;
   gint *parent_refcount;
   GArray *array;
+  gboolean is_any;
 };
 
 GType _gst_caps_features_type = 0;
+static gint static_caps_features_parent_refcount = G_MAXINT;
+GstCapsFeatures *_gst_caps_features_any = NULL;
 GstCapsFeatures *_gst_caps_features_memory_system_memory = NULL;
 static GQuark _gst_caps_feature_memory_system_memory = 0;
 
@@ -75,6 +86,9 @@ gst_caps_features_transform_to_string (const GValue * src_value,
 void
 _priv_gst_caps_features_initialize (void)
 {
+  GST_DEBUG_CATEGORY_INIT (gst_caps_features_debug, "caps-features", 0,
+      "GstCapsFeatures debug");
+
   _gst_caps_features_type = gst_caps_features_get_type ();
   _gst_caps_feature_memory_system_memory =
       g_quark_from_static_string (GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY);
@@ -82,11 +96,26 @@ _priv_gst_caps_features_initialize (void)
   g_value_register_transform_func (_gst_caps_features_type, G_TYPE_STRING,
       gst_caps_features_transform_to_string);
 
+  _gst_caps_features_any = gst_caps_features_new_any ();
+  gst_caps_features_set_parent_refcount (_gst_caps_features_any,
+      &static_caps_features_parent_refcount);
   _gst_caps_features_memory_system_memory =
       gst_caps_features_new_id (_gst_caps_feature_memory_system_memory, 0);
+  gst_caps_features_set_parent_refcount
+      (_gst_caps_features_memory_system_memory,
+      &static_caps_features_parent_refcount);
+}
 
-  GST_DEBUG_CATEGORY_INIT (gst_caps_features_debug, "caps-features", 0,
-      "GstCapsFeatures debug");
+void
+_priv_gst_caps_features_cleanup (void)
+{
+  gst_caps_features_set_parent_refcount (_gst_caps_features_any, NULL);
+  gst_caps_features_free (_gst_caps_features_any);
+  _gst_caps_features_any = NULL;
+  gst_caps_features_set_parent_refcount
+      (_gst_caps_features_memory_system_memory, NULL);
+  gst_caps_features_free (_gst_caps_features_memory_system_memory);
+  _gst_caps_features_memory_system_memory = NULL;
 }
 
 gboolean
@@ -138,6 +167,8 @@ gst_caps_feature_name_is_valid (const gchar * feature)
  * Free-function: gst_caps_features_free
  *
  * Returns: (transfer full): a new, empty #GstCapsFeatures
+ *
+ * Since: 1.2
  */
 GstCapsFeatures *
 gst_caps_features_new_empty (void)
@@ -148,6 +179,7 @@ gst_caps_features_new_empty (void)
   features->type = _gst_caps_features_type;
   features->parent_refcount = NULL;
   features->array = g_array_new (FALSE, FALSE, sizeof (GQuark));
+  features->is_any = FALSE;
 
   GST_TRACE ("created caps features %p", features);
 
@@ -155,16 +187,42 @@ gst_caps_features_new_empty (void)
 }
 
 /**
+ * gst_caps_features_new_any:
+ *
+ * Creates a new, ANY #GstCapsFeatures. This will be equal
+ * to any other #GstCapsFeatures but caps with these are
+ * unfixed.
+ *
+ * Free-function: gst_caps_features_free
+ *
+ * Returns: (transfer full): a new, ANY #GstCapsFeatures
+ *
+ * Since: 1.2
+ */
+GstCapsFeatures *
+gst_caps_features_new_any (void)
+{
+  GstCapsFeatures *features;
+
+  features = gst_caps_features_new_empty ();
+  features->is_any = TRUE;
+
+  return features;
+}
+
+/**
  * gst_caps_features_new:
  * @feature1: name of first feature to set
  * @...: additional features
  *
  * Creates a new #GstCapsFeatures with the given features.
- * The last argument must be NULL.
+ * The last argument must be %NULL.
  *
  * Free-function: gst_caps_features_free
  *
  * Returns: (transfer full): a new, empty #GstCapsFeatures
+ *
+ * Since: 1.2
  */
 GstCapsFeatures *
 gst_caps_features_new (const gchar * feature1, ...)
@@ -191,6 +249,8 @@ gst_caps_features_new (const gchar * feature1, ...)
  * Free-function: gst_caps_features_free
  *
  * Returns: (transfer full): a new, empty #GstCapsFeatures
+ *
+ * Since: 1.2
  */
 GstCapsFeatures *
 gst_caps_features_new_valist (const gchar * feature1, va_list varargs)
@@ -220,6 +280,8 @@ gst_caps_features_new_valist (const gchar * feature1, va_list varargs)
  * Free-function: gst_caps_features_free
  *
  * Returns: (transfer full): a new, empty #GstCapsFeatures
+ *
+ * Since: 1.2
  */
 GstCapsFeatures *
 gst_caps_features_new_id (GQuark feature1, ...)
@@ -246,6 +308,8 @@ gst_caps_features_new_id (GQuark feature1, ...)
  * Free-function: gst_caps_features_free
  *
  * Returns: (transfer full): a new, empty #GstCapsFeatures
+ *
+ * Since: 1.2
  */
 GstCapsFeatures *
 gst_caps_features_new_id_valist (GQuark feature1, va_list varargs)
@@ -275,6 +339,8 @@ gst_caps_features_new_id_valist (GQuark feature1, va_list varargs)
  * the MT Refcounting section of the design documents.
  *
  * Returns: %TRUE if the parent refcount could be set.
+ *
+ * Since: 1.2
  */
 gboolean
 gst_caps_features_set_parent_refcount (GstCapsFeatures * features,
@@ -310,6 +376,8 @@ gst_caps_features_set_parent_refcount (GstCapsFeatures * features,
  * Free-function: gst_caps_features_free
  *
  * Returns: (transfer full): a new #GstCapsFeatures.
+ *
+ * Since: 1.2
  */
 GstCapsFeatures *
 gst_caps_features_copy (const GstCapsFeatures * features)
@@ -323,6 +391,7 @@ gst_caps_features_copy (const GstCapsFeatures * features)
   n = gst_caps_features_get_size (features);
   for (i = 0; i < n; i++)
     gst_caps_features_add_id (copy, gst_caps_features_get_nth_id (features, i));
+  copy->is_any = features->is_any;
 
   return copy;
 }
@@ -333,6 +402,8 @@ gst_caps_features_copy (const GstCapsFeatures * features)
  *
  * Frees a #GstCapsFeatures and all its values. The caps features must not
  * have a parent when this function is called.
+ *
+ * Since: 1.2
  */
 void
 gst_caps_features_free (GstCapsFeatures * features)
@@ -356,15 +427,17 @@ gst_caps_features_free (GstCapsFeatures * features)
  * Converts @features to a human-readable string representation.
  *
  * For debugging purposes its easier to do something like this:
- * |[
+ * |[<!-- language="C" -->
  * GST_LOG ("features is %" GST_PTR_FORMAT, features);
  * ]|
- * This prints the features in human readble form.
+ * This prints the features in human readable form.
  *
  * Free-function: g_free
  *
  * Returns: (transfer full): a pointer to string allocated by g_malloc().
  *     g_free() after usage.
+ *
+ * Since: 1.2
  */
 gchar *
 gst_caps_features_to_string (const GstCapsFeatures * features)
@@ -388,6 +461,11 @@ priv_gst_caps_features_append_to_gstring (const GstCapsFeatures * features,
 
   g_return_if_fail (features != NULL);
 
+  if (features->array->len == 0 && features->is_any) {
+    g_string_append (s, "ANY");
+    return;
+  }
+
   n = features->array->len;
   for (i = 0; i < n; i++) {
     GQuark *quark = &g_array_index (features->array, GQuark, i);
@@ -406,8 +484,11 @@ priv_gst_caps_features_append_to_gstring (const GstCapsFeatures * features,
  *
  * Free-function: gst_caps_features_free
  *
- * Returns: (transfer full): a new #GstCapsFeatures or NULL when the string could
- *     not be parsed. Free with gst_caps_features_free() after use.
+ * Returns: (transfer full) (nullable): a new #GstCapsFeatures or
+ *     %NULL when the string could not be parsed. Free with
+ *     gst_caps_features_free() after use.
+ *
+ * Since: 1.2
  */
 GstCapsFeatures *
 gst_caps_features_from_string (const gchar * features)
@@ -422,6 +503,11 @@ gst_caps_features_from_string (const gchar * features)
   if (!features || *features == '\0')
     return ret;
 
+  if (strcmp (features, "ANY") == 0) {
+    ret->is_any = TRUE;
+    return ret;
+  }
+
   /* Skip trailing spaces */
   while (*features == ' ')
     features++;
@@ -489,6 +575,8 @@ gst_caps_features_from_string (const gchar * features)
  * Returns the number of features in @features.
  *
  * Returns: The number of features in @features.
+ *
+ * Since: 1.2
  */
 guint
 gst_caps_features_get_size (const GstCapsFeatures * features)
@@ -505,7 +593,9 @@ gst_caps_features_get_size (const GstCapsFeatures * features)
  *
  * Returns the @i-th feature of @features.
  *
- * Returns: The @i-th feature of @features.
+ * Returns: (nullable): The @i-th feature of @features.
+ *
+ * Since: 1.2
  */
 const gchar *
 gst_caps_features_get_nth (const GstCapsFeatures * features, guint i)
@@ -531,6 +621,8 @@ gst_caps_features_get_nth (const GstCapsFeatures * features, guint i)
  * Returns the @i-th feature of @features.
  *
  * Returns: The @i-th feature of @features.
+ *
+ * Since: 1.2
  */
 GQuark
 gst_caps_features_get_nth_id (const GstCapsFeatures * features, guint i)
@@ -550,9 +642,11 @@ gst_caps_features_get_nth_id (const GstCapsFeatures * features, guint i)
  * @features: a #GstCapsFeatures.
  * @feature: a feature
  *
- * Returns %TRUE if @features contains @feature.
+ * Check if @features contains @feature.
  *
  * Returns: %TRUE if @features contains @feature.
+ *
+ * Since: 1.2
  */
 gboolean
 gst_caps_features_contains (const GstCapsFeatures * features,
@@ -570,9 +664,11 @@ gst_caps_features_contains (const GstCapsFeatures * features,
  * @features: a #GstCapsFeatures.
  * @feature: a feature
  *
- * Returns %TRUE if @features contains @feature.
+ * Check if @features contains @feature.
  *
  * Returns: %TRUE if @features contains @feature.
+ *
+ * Since: 1.2
  */
 gboolean
 gst_caps_features_contains_id (const GstCapsFeatures * features, GQuark feature)
@@ -582,6 +678,9 @@ gst_caps_features_contains_id (const GstCapsFeatures * features, GQuark feature)
   g_return_val_if_fail (features != NULL, FALSE);
   g_return_val_if_fail (feature != 0, FALSE);
 
+  if (features->is_any)
+    return TRUE;
+
   n = features->array->len;
   if (n == 0)
     return feature == _gst_caps_feature_memory_system_memory;
@@ -599,9 +698,11 @@ gst_caps_features_contains_id (const GstCapsFeatures * features, GQuark feature)
  * @features1: a #GstCapsFeatures.
  * @features2: a #GstCapsFeatures.
  *
- * Returns %TRUE if @features1 and @features2 are equal.
+ * Check if @features1 and @features2 are equal.
  *
  * Returns: %TRUE if @features1 and @features2 are equal.
+ *
+ * Since: 1.2
  */
 gboolean
 gst_caps_features_is_equal (const GstCapsFeatures * features1,
@@ -612,6 +713,9 @@ gst_caps_features_is_equal (const GstCapsFeatures * features1,
   g_return_val_if_fail (features1 != NULL, FALSE);
   g_return_val_if_fail (features2 != NULL, FALSE);
 
+  if (features1->is_any || features2->is_any)
+    return TRUE;
+
   /* Check for the sysmem==empty case */
   if (features1->array->len == 0 && features2->array->len == 0)
     return TRUE;
@@ -637,11 +741,31 @@ gst_caps_features_is_equal (const GstCapsFeatures * features1,
 }
 
 /**
+ * gst_caps_features_is_any:
+ * @features: a #GstCapsFeatures.
+ *
+ * Check if @features is %GST_CAPS_FEATURES_ANY.
+ *
+ * Returns: %TRUE if @features is %GST_CAPS_FEATURES_ANY.
+ *
+ * Since: 1.2
+ */
+gboolean
+gst_caps_features_is_any (const GstCapsFeatures * features)
+{
+  g_return_val_if_fail (features != NULL, FALSE);
+
+  return features->is_any;
+}
+
+/**
  * gst_caps_features_add:
  * @features: a #GstCapsFeatures.
  * @feature: a feature.
  *
  * Adds @feature to @features.
+ *
+ * Since: 1.2
  */
 void
 gst_caps_features_add (GstCapsFeatures * features, const gchar * feature)
@@ -649,6 +773,7 @@ gst_caps_features_add (GstCapsFeatures * features, const gchar * feature)
   g_return_if_fail (features != NULL);
   g_return_if_fail (IS_MUTABLE (features));
   g_return_if_fail (feature != NULL);
+  g_return_if_fail (!features->is_any);
 
   gst_caps_features_add_id (features, g_quark_from_string (feature));
 }
@@ -659,6 +784,8 @@ gst_caps_features_add (GstCapsFeatures * features, const gchar * feature)
  * @feature: a feature.
  *
  * Adds @feature to @features.
+ *
+ * Since: 1.2
  */
 void
 gst_caps_features_add_id (GstCapsFeatures * features, GQuark feature)
@@ -666,6 +793,7 @@ gst_caps_features_add_id (GstCapsFeatures * features, GQuark feature)
   g_return_if_fail (features != NULL);
   g_return_if_fail (IS_MUTABLE (features));
   g_return_if_fail (feature != 0);
+  g_return_if_fail (!features->is_any);
 
   if (!gst_caps_feature_name_is_valid (g_quark_to_string (feature))) {
     g_warning ("Invalid caps feature name: %s", g_quark_to_string (feature));
@@ -673,7 +801,7 @@ gst_caps_features_add_id (GstCapsFeatures * features, GQuark feature)
   }
 
   /* If features is empty it will contain sysmem, however
-   * we want to add it explicitely if it is tried to be
+   * we want to add it explicitly if it is attempted to be
    * added as first features
    */
   if (features->array->len > 0
@@ -689,6 +817,8 @@ gst_caps_features_add_id (GstCapsFeatures * features, GQuark feature)
  * @feature: a feature.
  *
  * Removes @feature from @features.
+ *
+ * Since: 1.2
  */
 void
 gst_caps_features_remove (GstCapsFeatures * features, const gchar * feature)
@@ -706,6 +836,8 @@ gst_caps_features_remove (GstCapsFeatures * features, const gchar * feature)
  * @feature: a feature.
  *
  * Removes @feature from @features.
+ *
+ * Since: 1.2
  */
 void
 gst_caps_features_remove_id (GstCapsFeatures * features, GQuark feature)