structure: Add gst_structure_is_subset()

API: gst_structure_is_subset()
This commit is contained in:
Sebastian Dröge 2011-05-27 13:47:11 +02:00
parent d98e9acb0f
commit da58834884
5 changed files with 77 additions and 60 deletions

View file

@ -2209,6 +2209,7 @@ gst_structure_n_fields
gst_structure_has_field
gst_structure_has_field_typed
gst_structure_is_equal
gst_structure_is_subset
gst_structure_can_intersect
gst_structure_intersect
gst_structure_id_has_field

View file

@ -565,64 +565,6 @@ gst_caps_steal_structure (GstCaps * caps, guint index)
return gst_caps_remove_and_get_structure (caps, index);
}
static gboolean
gst_caps_structure_is_subset_field (GQuark field_id, const GValue * value,
gpointer user_data)
{
GstStructure *superset = user_data;
GValue subtraction = { 0, };
const GValue *other;
if (!(other = gst_structure_id_get_value (superset, field_id)))
/* field is missing in the superset => is subset */
return TRUE;
/* equal values are subset */
if (gst_value_compare (other, value) == GST_VALUE_EQUAL)
return TRUE;
/*
* 1 - [1,2] = empty
* -> !subset
*
* [1,2] - 1 = 2
* -> 1 - [1,2] = empty
* -> subset
*
* [1,3] - [1,2] = 3
* -> [1,2] - [1,3] = empty
* -> subset
*
* {1,2} - {1,3} = 2
* -> {1,3} - {1,2} = 3
* -> !subset
*
* First caps subtraction needs to return a non-empty set, second
* subtractions needs to give en empty set.
*/
if (gst_value_subtract (&subtraction, other, value)) {
g_value_unset (&subtraction);
/* !empty result, swapping must be empty */
if (!gst_value_subtract (&subtraction, value, other))
return TRUE;
g_value_unset (&subtraction);
}
return FALSE;
}
static gboolean
gst_caps_structure_is_subset (const GstStructure * superset,
const GstStructure * subset)
{
if ((superset->name != subset->name) ||
(gst_structure_n_fields (superset) > gst_structure_n_fields (subset)))
return FALSE;
return gst_structure_foreach ((GstStructure *) subset,
gst_caps_structure_is_subset_field, (gpointer) superset);
}
/**
* gst_caps_append:
* @caps1: the #GstCaps that will be appended to
@ -792,7 +734,7 @@ gst_caps_merge_structure (GstCaps * caps, GstStructure * structure)
for (i = caps->structs->len - 1; i >= 0; i--) {
structure1 = gst_caps_get_structure_unchecked (caps, i);
/* if structure is a subset of structure1, then skip it */
if (gst_caps_structure_is_subset (structure1, structure)) {
if (gst_structure_is_subset (structure, structure1)) {
unique = FALSE;
break;
}
@ -1147,7 +1089,7 @@ gst_caps_is_subset (const GstCaps * subset, const GstCaps * superset)
for (j = superset->structs->len - 1; j >= 0; j--) {
s1 = gst_caps_get_structure_unchecked (subset, i);
s2 = gst_caps_get_structure_unchecked (superset, j);
if (gst_caps_structure_is_subset (s2, s1)) {
if (gst_structure_is_subset (s1, s2)) {
/* If we found a superset, continue with the next
* subset structure */
break;

View file

@ -3099,3 +3099,74 @@ gst_structure_can_intersect (const GstStructure * struct1,
return TRUE;
}
static gboolean
gst_caps_structure_is_subset_field (GQuark field_id, const GValue * value,
gpointer user_data)
{
GstStructure *superset = user_data;
GValue subtraction = { 0, };
const GValue *other;
if (!(other = gst_structure_id_get_value (superset, field_id)))
/* field is missing in the superset => is subset */
return TRUE;
/* equal values are subset */
if (gst_value_compare (other, value) == GST_VALUE_EQUAL)
return TRUE;
/*
* 1 - [1,2] = empty
* -> !subset
*
* [1,2] - 1 = 2
* -> 1 - [1,2] = empty
* -> subset
*
* [1,3] - [1,2] = 3
* -> [1,2] - [1,3] = empty
* -> subset
*
* {1,2} - {1,3} = 2
* -> {1,3} - {1,2} = 3
* -> !subset
*
* First caps subtraction needs to return a non-empty set, second
* subtractions needs to give en empty set.
*/
if (gst_value_subtract (&subtraction, other, value)) {
g_value_unset (&subtraction);
/* !empty result, swapping must be empty */
if (!gst_value_subtract (&subtraction, value, other))
return TRUE;
g_value_unset (&subtraction);
}
return FALSE;
}
/**
* gst_structure_is_subset:
* @subset: a #GstStructure
* @superset: a potentially greater #GstStructure
*
* Checks if @subset is a subset of @superset, i.e. has the same
* structure name and for all fields that are existing in @superset,
* @subset has a value that is a subset of the value in @superset.
*
* Returns: %TRUE if @subset is a subset of @superset
*
* Since: 0.10.35
*/
gboolean
gst_structure_is_subset (const GstStructure * subset,
const GstStructure * superset)
{
if ((superset->name != subset->name) ||
(gst_structure_n_fields (superset) > gst_structure_n_fields (subset)))
return FALSE;
return gst_structure_foreach ((GstStructure *) subset,
gst_caps_structure_is_subset_field, (gpointer) superset);
}

View file

@ -250,6 +250,8 @@ gboolean gst_structure_fixate_field_nearest_fraction (GstStructu
gboolean gst_structure_is_equal(const GstStructure *structure1,
const GstStructure *structure2);
gboolean gst_structure_is_subset(const GstStructure *subset,
const GstStructure *superset);
gboolean gst_structure_can_intersect(const GstStructure *struct1,
const GstStructure *struct2);
GstStructure* gst_structure_intersect (const GstStructure *struct1,

View file

@ -1010,6 +1010,7 @@ EXPORTS
gst_structure_id_take_value
gst_structure_intersect
gst_structure_is_equal
gst_structure_is_subset
gst_structure_map_in_place
gst_structure_n_fields
gst_structure_new