mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-10 17:35:59 +00:00
structure/caps: Add gst_{structure,caps}_filter_and_map_in_place()
https://bugzilla.gnome.org/show_bug.cgi?id=739765
This commit is contained in:
parent
6925fa1b7c
commit
1f6d5d3ff5
8 changed files with 233 additions and 5 deletions
|
@ -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
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
@ -1166,6 +1167,51 @@ gst_structure_map_in_place (GstStructure * structure,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
|
@ -70,6 +70,23 @@ typedef gboolean (*GstStructureMapFunc) (GQuark field_id,
|
|||
GValue * value,
|
||||
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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue