structure/caps: Add gst_{structure,caps}_filter_and_map_in_place()
authorSebastian Dröge <sebastian@centricular.com>
Tue, 16 Dec 2014 15:31:21 +0000 (16:31 +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
gst/gststructure.c
gst/gststructure.h
tests/check/gst/gstcaps.c
tests/check/gst/gststructure.c
win32/common/libgstreamer.def

index f5863bb..4d36c26 100644 (file)
@@ -400,6 +400,7 @@ GST_CAPS_FLAG_UNSET
 
 GstCapsForeachFunc
 GstCapsMapFunc
+GstCapsFilterMapFunc
 
 gst_caps_new_empty
 gst_caps_new_empty_simple
@@ -429,6 +430,7 @@ gst_caps_set_simple
 gst_caps_set_simple_valist
 gst_caps_foreach
 gst_caps_map_in_place
+gst_caps_filter_and_map_in_place
 gst_caps_is_any
 gst_caps_is_empty
 gst_caps_is_fixed
@@ -2525,6 +2527,7 @@ gst_segment_flags_get_type
 GstStructure
 GstStructureForeachFunc
 GstStructureMapFunc
+GstStructureFilterMapFunc
 gst_structure_new_empty
 gst_structure_new_id_empty
 gst_structure_new
@@ -2556,7 +2559,6 @@ gst_structure_remove_fields
 gst_structure_remove_fields_valist
 gst_structure_remove_all_fields
 gst_structure_get_field_type
-gst_structure_foreach
 gst_structure_n_fields
 gst_structure_has_field
 gst_structure_has_field_typed
@@ -2578,7 +2580,9 @@ gst_structure_get_date_time
 gst_structure_get_clock_time
 gst_structure_get_enum
 gst_structure_get_fraction
+gst_structure_foreach
 gst_structure_map_in_place
+gst_structure_filter_and_map_in_place
 gst_structure_nth_field_name
 gst_structure_set_parent_refcount
 gst_structure_to_string
index c9b72df..147b32c 100644 (file)
@@ -484,8 +484,6 @@ gst_caps_remove_and_get_structure (GstCaps * caps, guint idx)
   return s;
 }
 
-
-
 /**
  * gst_caps_steal_structure:
  * @caps: the #GstCaps to retrieve from
@@ -2367,7 +2365,7 @@ gst_caps_transform_to_string (const GValue * src_value, GValue * dest_value)
  *
  * 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().
+ * Also see gst_caps_map_in_place() and gst_caps_filter_and_map_in_place().
  *
  * Returns: %TRUE if the supplied function returns %TRUE for each call,
  * %FALSE otherwise.
@@ -2447,3 +2445,62 @@ gst_caps_map_in_place (GstCaps * caps, GstCapsMapFunc func, gpointer user_data)
 
   return TRUE;
 }
+
+/**
+ * gst_caps_filter_and_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 the
+ * structure and features. In contrast to gst_caps_filter_and_map_in_place(),
+ * the structure and features are removed from the caps if %FALSE is returned
+ * from the function.
+ * The caps must be mutable.
+ *
+ * Since: 1.6
+ */
+void
+gst_caps_filter_and_map_in_place (GstCaps * caps, GstCapsFilterMapFunc func,
+    gpointer user_data)
+{
+  guint i, n;
+  GstCapsFeatures *features;
+  GstStructure *structure;
+  gboolean ret;
+
+  g_return_if_fail (GST_IS_CAPS (caps));
+  g_return_if_fail (gst_caps_is_writable (caps));
+  g_return_if_fail (func != NULL);
+
+  n = GST_CAPS_LEN (caps);
+
+  for (i = 0; i < n;) {
+    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 (!ret) {
+      GST_CAPS_ARRAY (caps) = g_array_remove_index (GST_CAPS_ARRAY (caps), i);
+
+      gst_structure_set_parent_refcount (structure, NULL);
+      gst_structure_free (structure);
+      if (features) {
+        gst_caps_features_set_parent_refcount (features, NULL);
+        gst_caps_features_free (features);
+      }
+
+      n = GST_CAPS_LEN (caps);
+    } else {
+      i++;
+    }
+  }
+}
index 4102f27..5cd1b78 100644 (file)
@@ -397,6 +397,23 @@ typedef gboolean (*GstCapsMapFunc)     (GstCapsFeatures *features,
                                         GstStructure    *structure,
                                         gpointer         user_data);
 
+/**
+ * GstCapsFilterMapFunc:
+ * @features: the #GstCapsFeatures
+ * @structure: the #GstStructure
+ * @user_data: user data
+ *
+ * A function that will be called in gst_caps_filter_and_map_in_place().
+ * The function may modify @features and @structure, and both will be
+ * removed from the caps if %FALSE is returned.
+ *
+ * Returns: %TRUE if the features and structure should be preserved,
+ * %FALSE if it should be removed.
+ */
+typedef gboolean (*GstCapsFilterMapFunc) (GstCapsFeatures *features,
+                                          GstStructure    *structure,
+                                          gpointer user_data);
+
 
 GType             gst_caps_get_type                (void);
 
@@ -460,6 +477,10 @@ gboolean          gst_caps_map_in_place            (GstCaps        *caps,
                                                     GstCapsMapFunc  func,
                                                     gpointer        user_data);
 
+void              gst_caps_filter_and_map_in_place (GstCaps              *caps,
+                                                    GstCapsFilterMapFunc  func,
+                                                    gpointer              user_data);
+
 /* tests */
 gboolean          gst_caps_is_any                  (const GstCaps *caps);
 gboolean          gst_caps_is_empty                (const GstCaps *caps);
index 3781615..8b0b54b 100644 (file)
@@ -1100,7 +1100,8 @@ gst_structure_nth_field_name (const GstStructure * structure, guint index)
  * @user_data: (closure): private data
  *
  * Calls the provided function once for each field in the #GstStructure. The
- * function must not modify the fields. Also see gst_structure_map_in_place().
+ * function must not modify the fields. Also see gst_structure_map_in_place()
+ * and gst_structure_filter_and_map_in_place().
  *
  * Returns: %TRUE if the supplied function returns %TRUE For each of the fields,
  * %FALSE otherwise.
@@ -1167,6 +1168,51 @@ gst_structure_map_in_place (GstStructure * structure,
 }
 
 /**
+ * gst_structure_filter_and_map_in_place:
+ * @structure: a #GstStructure
+ * @func: (scope call): a function to call for each field
+ * @user_data: (closure): private data
+ *
+ * Calls the provided function once for each field in the #GstStructure. In
+ * contrast to gst_structure_foreach(), the function may modify the fields.
+ * In contrast to gst_structure_map_in_place(), the field is removed from
+ * the structure if %FALSE is returned from the function.
+ * The structure must be mutable.
+ *
+ * Since: 1.6
+ */
+void
+gst_structure_filter_and_map_in_place (GstStructure * structure,
+    GstStructureFilterMapFunc func, gpointer user_data)
+{
+  guint i, len;
+  GstStructureField *field;
+  gboolean ret;
+
+  g_return_if_fail (structure != NULL);
+  g_return_if_fail (IS_MUTABLE (structure));
+  g_return_if_fail (func != NULL);
+  len = GST_STRUCTURE_FIELDS (structure)->len;
+
+  for (i = 0; i < len;) {
+    field = GST_STRUCTURE_FIELD (structure, i);
+
+    ret = func (field->name, &field->value, user_data);
+
+    if (!ret) {
+      if (G_IS_VALUE (&field->value)) {
+        g_value_unset (&field->value);
+      }
+      GST_STRUCTURE_FIELDS (structure) =
+          g_array_remove_index (GST_STRUCTURE_FIELDS (structure), i);
+      len = GST_STRUCTURE_FIELDS (structure)->len;
+    } else {
+      i++;
+    }
+  }
+}
+
+/**
  * gst_structure_id_has_field:
  * @structure: a #GstStructure
  * @field: #GQuark of the field name
index 6687970..014ef37 100644 (file)
@@ -71,6 +71,23 @@ typedef gboolean (*GstStructureMapFunc)     (GQuark   field_id,
                                              gpointer user_data);
 
 /**
+ * GstStructureFilterMapFunc:
+ * @field_id: the #GQuark of the field name
+ * @value: the #GValue of the field
+ * @user_data: user data
+ *
+ * A function that will be called in gst_structure_filter_and_map_in_place().
+ * The function may modify @value, and the value will be removed from
+ * the structure if %FALSE is returned.
+ *
+ * Returns: %TRUE if the field should be preserved, %FALSE if it
+ * should be removed.
+ */
+typedef gboolean (*GstStructureFilterMapFunc) (GQuark   field_id,
+                                               GValue * value,
+                                               gpointer user_data);
+
+/**
  * GstStructure:
  * @type: the GType of a structure
  *
@@ -198,6 +215,10 @@ gboolean              gst_structure_map_in_place         (GstStructure        *
                                                           GstStructureMapFunc   func,
                                                           gpointer              user_data);
 
+void                  gst_structure_filter_and_map_in_place (GstStructure        * structure,
+                                                          GstStructureFilterMapFunc   func,
+                                                          gpointer              user_data);
+
 gint                  gst_structure_n_fields             (const GstStructure  * structure);
 
 const gchar *         gst_structure_nth_field_name       (const GstStructure  * structure,
index cb6128b..6645361 100644 (file)
@@ -1240,6 +1240,52 @@ GST_START_TEST (test_map_in_place)
 
 GST_END_TEST;
 
+static gboolean
+filter_map_function (GstCapsFeatures * features, GstStructure * structure,
+    gpointer user_data)
+{
+  if (!gst_structure_has_name (structure, "video/x-raw"))
+    return FALSE;
+
+  if (!gst_caps_features_contains (features, "foo:bar"))
+    return FALSE;
+
+  /* Set some dummy integer in the structure */
+  gst_structure_set (structure, "foo", G_TYPE_INT, 123, NULL);
+
+  return TRUE;
+}
+
+GST_START_TEST (test_filter_and_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");
+  gst_caps_filter_and_map_in_place (caps, filter_map_function, NULL);
+  fail_unless (gst_caps_is_strictly_equal (caps, caps2));
+  gst_caps_unref (caps);
+  gst_caps_unref (caps2);
+
+  caps = gst_caps_from_string ("video/x-raw, format=I420; video/x-h264");
+  caps2 = gst_caps_new_empty ();
+  gst_caps_filter_and_map_in_place (caps, filter_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 ();
+  gst_caps_filter_and_map_in_place (caps, filter_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)
 {
@@ -1271,6 +1317,7 @@ gst_caps_suite (void)
   tcase_add_test (tc_chain, test_special_caps);
   tcase_add_test (tc_chain, test_foreach);
   tcase_add_test (tc_chain, test_map_in_place);
+  tcase_add_test (tc_chain, test_filter_and_map_in_place);
 
   return s;
 }
index a73db33..18c58f6 100644 (file)
@@ -722,6 +722,33 @@ GST_START_TEST (test_map_in_place)
 
 GST_END_TEST;
 
+static gboolean
+filter_map_func (GQuark field_id, GValue * value, gpointer user_data)
+{
+  if (strcmp (g_quark_to_string (field_id), "bla") == 0)
+    return FALSE;
+
+  if (G_VALUE_HOLDS_INT (value))
+    g_value_set_int (value, 2);
+
+  return TRUE;
+}
+
+GST_START_TEST (test_filter_and_map_in_place)
+{
+  GstStructure *s, *s2;
+
+  s = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 1, "bla", G_TYPE_INT, 3,
+      NULL);
+  s2 = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 2, NULL);
+  gst_structure_filter_and_map_in_place (s, filter_map_func, NULL);
+  fail_unless (gst_structure_is_equal (s, s2));
+  gst_structure_free (s);
+  gst_structure_free (s2);
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_structure_suite (void)
 {
@@ -746,6 +773,7 @@ gst_structure_suite (void)
   tcase_add_test (tc_chain, test_vararg_getters);
   tcase_add_test (tc_chain, test_foreach);
   tcase_add_test (tc_chain, test_map_in_place);
+  tcase_add_test (tc_chain, test_filter_and_map_in_place);
   return s;
 }
 
index 5908d42..98cb12d 100644 (file)
@@ -241,8 +241,10 @@ EXPORTS
        gst_caps_features_remove_id
        gst_caps_features_set_parent_refcount
        gst_caps_features_to_string
+       gst_caps_filter_and_map_in_place
        gst_caps_fixate
        gst_caps_flags_get_type
+       gst_caps_foreach
        gst_caps_from_string
        gst_caps_get_features
        gst_caps_get_size
@@ -261,6 +263,7 @@ EXPORTS
        gst_caps_is_subset
        gst_caps_is_subset_structure
        gst_caps_is_subset_structure_full
+       gst_caps_map_in_place
        gst_caps_merge
        gst_caps_merge_structure
        gst_caps_merge_structure_full
@@ -1139,6 +1142,7 @@ EXPORTS
        gst_structure_can_intersect
        gst_structure_change_type_get_type
        gst_structure_copy
+       gst_structure_filter_and_map_in_place
        gst_structure_fixate
        gst_structure_fixate_field
        gst_structure_fixate_field_boolean