caps: Add gst_caps_foreach() and gst_caps_map_in_place()
authorSebastian Dröge <sebastian@centricular.com>
Fri, 7 Nov 2014 10:15:09 +0000 (11:15 +0100)
committerSebastian Dröge <sebastian@centricular.com>
Tue, 16 Dec 2014 17:22:46 +0000 (18:22 +0100)
https://bugzilla.gnome.org/show_bug.cgi?id=739765

docs/gst/gstreamer-sections.txt
gst/gstcaps.c
gst/gstcaps.h
tests/check/gst/gstcaps.c

index c69d06a..f5863bb 100644 (file)
@@ -398,6 +398,9 @@ GST_CAPS_FLAG_IS_SET
 GST_CAPS_FLAG_SET
 GST_CAPS_FLAG_UNSET
 
+GstCapsForeachFunc
+GstCapsMapFunc
+
 gst_caps_new_empty
 gst_caps_new_empty_simple
 gst_caps_new_any
@@ -424,6 +427,8 @@ gst_caps_set_features
 gst_caps_set_value
 gst_caps_set_simple
 gst_caps_set_simple_valist
+gst_caps_foreach
+gst_caps_map_in_place
 gst_caps_is_any
 gst_caps_is_empty
 gst_caps_is_fixed
index 51f7ae4..c9b72df 100644 (file)
@@ -2358,3 +2358,92 @@ gst_caps_transform_to_string (const GValue * src_value, GValue * dest_value)
   g_value_take_string (dest_value,
       gst_caps_to_string (gst_value_get_caps (src_value)));
 }
+
+/**
+ * gst_caps_foreach:
+ * @caps: a #GstCaps
+ * @func: (scope call): a function to call for each field
+ * @user_data: (closure): private data
+ *
+ * Calls the provided function once for each structure and caps feature in the
+ * #GstCaps. The function must not modify the fields.
+ * Also see gst_caps_map_in_place().
+ *
+ * Returns: %TRUE if the supplied function returns %TRUE for each call,
+ * %FALSE otherwise.
+ *
+ * Since: 1.6
+ */
+gboolean
+gst_caps_foreach (const GstCaps * caps, GstCapsForeachFunc func,
+    gpointer user_data)
+{
+  guint i, n;
+  GstCapsFeatures *features;
+  GstStructure *structure;
+  gboolean ret;
+
+  g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
+  g_return_val_if_fail (func != NULL, FALSE);
+
+  n = GST_CAPS_LEN (caps);
+
+  for (i = 0; i < n; i++) {
+    features = gst_caps_get_features_unchecked (caps, i);
+    structure = gst_caps_get_structure_unchecked (caps, i);
+
+    ret = func (features, structure, user_data);
+    if (G_UNLIKELY (!ret))
+      return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+ * gst_caps_map_in_place:
+ * @caps: a #GstCaps
+ * @func: (scope call): a function to call for each field
+ * @user_data: (closure): private data
+ *
+ * Calls the provided function once for each structure and caps feature in the
+ * #GstCaps. In contrast to gst_caps_foreach(), the function may modify but not
+ * delete the structures and features. The caps must be mutable.
+ *
+ * Returns: %TRUE if the supplied function returns %TRUE for each call,
+ * %FALSE otherwise.
+ *
+ * Since: 1.6
+ */
+gboolean
+gst_caps_map_in_place (GstCaps * caps, GstCapsMapFunc func, gpointer user_data)
+{
+  guint i, n;
+  GstCapsFeatures *features;
+  GstStructure *structure;
+  gboolean ret;
+
+  g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
+  g_return_val_if_fail (gst_caps_is_writable (caps), FALSE);
+  g_return_val_if_fail (func != NULL, FALSE);
+
+  n = GST_CAPS_LEN (caps);
+
+  for (i = 0; i < n; i++) {
+    features = gst_caps_get_features_unchecked (caps, i);
+    structure = gst_caps_get_structure_unchecked (caps, i);
+
+    /* Provide sysmem features if there are none yet */
+    if (!features) {
+      features =
+          gst_caps_features_copy (GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY);
+      gst_caps_set_features (caps, i, features);
+    }
+
+    ret = func (features, structure, user_data);
+    if (G_UNLIKELY (!ret))
+      return FALSE;
+  }
+
+  return TRUE;
+}
index 4b09b8e..4102f27 100644 (file)
@@ -363,6 +363,41 @@ struct _GstStaticCaps {
   gpointer _gst_reserved[GST_PADDING];
 };
 
+/**
+ * GstCapsForeachFunc:
+ * @features: the #GstCapsFeatures
+ * @structure: the #GstStructure
+ * @user_data: user data
+ *
+ * A function that will be called in gst_caps_foreach(). The function may
+ * not modify @features or @structure.
+ *
+ * Returns: %TRUE if the foreach operation should continue, %FALSE if
+ * the foreach operation should stop with %FALSE.
+ *
+ * Since: 1.6
+ */
+typedef gboolean (*GstCapsForeachFunc) (GstCapsFeatures *features,
+                                        GstStructure    *structure,
+                                        gpointer         user_data);
+
+/**
+ * GstCapsMapFunc:
+ * @features: the #GstCapsFeatures
+ * @structure: the #GstStructure
+ * @user_data: user data
+ *
+ * A function that will be called in gst_caps_map_in_place(). The function
+ * may modify @features and @structure.
+ *
+ * Returns: %TRUE if the map operation should continue, %FALSE if
+ * the map operation should stop with %FALSE.
+ */
+typedef gboolean (*GstCapsMapFunc)     (GstCapsFeatures *features,
+                                        GstStructure    *structure,
+                                        gpointer         user_data);
+
+
 GType             gst_caps_get_type                (void);
 
 GstCaps *         gst_caps_new_empty               (void);
@@ -417,6 +452,14 @@ void              gst_caps_set_simple_valist       (GstCaps       *caps,
                                                     const char    *field,
                                                     va_list        varargs);
 
+gboolean          gst_caps_foreach                 (const GstCaps       *caps,
+                                                    GstCapsForeachFunc   func,
+                                                    gpointer             user_data);
+
+gboolean          gst_caps_map_in_place            (GstCaps        *caps,
+                                                    GstCapsMapFunc  func,
+                                                    gpointer        user_data);
+
 /* tests */
 gboolean          gst_caps_is_any                  (const GstCaps *caps);
 gboolean          gst_caps_is_empty                (const GstCaps *caps);
index 7fb0b3e..cb6128b 100644 (file)
@@ -1161,6 +1161,85 @@ GST_START_TEST (test_special_caps)
 }
 
 GST_END_TEST;
+
+static gboolean
+foreach_append_function (GstCapsFeatures * features, GstStructure * structure,
+    gpointer user_data)
+{
+  GstCaps *caps = user_data;
+
+  gst_caps_append_structure_full (caps, gst_structure_copy (structure),
+      features ? gst_caps_features_copy (features) : NULL);
+
+  return TRUE;
+}
+
+GST_START_TEST (test_foreach)
+{
+  GstCaps *caps, *caps2;
+
+  caps =
+      gst_caps_from_string
+      ("video/x-raw, format=I420; video/x-raw(foo:bar); video/x-h264");
+  caps2 = gst_caps_new_empty ();
+  fail_unless (gst_caps_foreach (caps, foreach_append_function, caps2));
+  fail_unless (gst_caps_is_strictly_equal (caps, caps2));
+  gst_caps_unref (caps);
+  gst_caps_unref (caps2);
+
+  caps = gst_caps_new_empty ();
+  caps2 = gst_caps_new_empty ();
+  fail_unless (gst_caps_foreach (caps, foreach_append_function, caps2));
+  fail_unless (gst_caps_is_strictly_equal (caps, caps2));
+  gst_caps_unref (caps);
+  gst_caps_unref (caps2);
+}
+
+GST_END_TEST;
+
+static gboolean
+map_function (GstCapsFeatures * features, GstStructure * structure,
+    gpointer user_data)
+{
+  /* Remove caps features if there are any, otherwise add some dummy */
+  if (gst_caps_features_contains (features, "foo:bar")) {
+    gst_caps_features_remove (features, "foo:bar");
+  } else {
+    gst_caps_features_add (features, "foo:bar");
+    gst_caps_features_remove (features, GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY);
+  }
+
+  /* Set some dummy integer in the structure */
+  gst_structure_set (structure, "foo", G_TYPE_INT, 123, NULL);
+
+  return TRUE;
+}
+
+GST_START_TEST (test_map_in_place)
+{
+  GstCaps *caps, *caps2;
+
+  caps =
+      gst_caps_from_string
+      ("video/x-raw, format=I420; video/x-raw(foo:bar); video/x-h264");
+  caps2 =
+      gst_caps_from_string
+      ("video/x-raw(foo:bar), foo=(int)123, format=I420; video/x-raw, foo=(int)123; video/x-h264(foo:bar), foo=(int)123");
+  fail_unless (gst_caps_map_in_place (caps, map_function, NULL));
+  fail_unless (gst_caps_is_strictly_equal (caps, caps2));
+  gst_caps_unref (caps);
+  gst_caps_unref (caps2);
+
+  caps = gst_caps_new_empty ();
+  caps2 = gst_caps_new_empty ();
+  fail_unless (gst_caps_map_in_place (caps, map_function, NULL));
+  fail_unless (gst_caps_is_strictly_equal (caps, caps2));
+  gst_caps_unref (caps);
+  gst_caps_unref (caps2);
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_caps_suite (void)
 {
@@ -1190,6 +1269,8 @@ gst_caps_suite (void)
   tcase_add_test (tc_chain, test_broken);
   tcase_add_test (tc_chain, test_features);
   tcase_add_test (tc_chain, test_special_caps);
+  tcase_add_test (tc_chain, test_foreach);
+  tcase_add_test (tc_chain, test_map_in_place);
 
   return s;
 }