From: Sebastian Dröge Date: Fri, 7 Nov 2014 10:15:09 +0000 (+0100) Subject: caps: Add gst_caps_foreach() and gst_caps_map_in_place() X-Git-Tag: 1.6.1~625 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bc11a1b79dace8ca73d3367d7c70629f8a6dd7fd;p=platform%2Fupstream%2Fgstreamer.git caps: Add gst_caps_foreach() and gst_caps_map_in_place() https://bugzilla.gnome.org/show_bug.cgi?id=739765 --- diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index c69d06a..f5863bb 100644 --- a/docs/gst/gstreamer-sections.txt +++ b/docs/gst/gstreamer-sections.txt @@ -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 diff --git a/gst/gstcaps.c b/gst/gstcaps.c index 51f7ae4..c9b72df 100644 --- a/gst/gstcaps.c +++ b/gst/gstcaps.c @@ -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; +} diff --git a/gst/gstcaps.h b/gst/gstcaps.h index 4b09b8e..4102f27 100644 --- a/gst/gstcaps.h +++ b/gst/gstcaps.h @@ -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); diff --git a/tests/check/gst/gstcaps.c b/tests/check/gst/gstcaps.c index 7fb0b3e..cb6128b 100644 --- a/tests/check/gst/gstcaps.c +++ b/tests/check/gst/gstcaps.c @@ -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; }