mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-18 07:47:17 +00:00
implement caps merging (fixes #352580)
Original commit message from CVS: * docs/gst/gstreamer-sections.txt: * gst/gstcaps.c: (gst_caps_structure_is_subset_field), (gst_caps_structure_is_subset), (gst_caps_merge), (gst_caps_merge_structure): * gst/gstcaps.h: * libs/gst/base/gstbasetransform.c: (gst_base_transform_transform_caps): * tests/check/gst/gstcaps.c: (GST_START_TEST), (gst_caps_suite): implement caps merging (fixes #352580)
This commit is contained in:
parent
7c84afffac
commit
fc8d184bba
6 changed files with 249 additions and 14 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
|||
2006-08-24 Stefan Kost <ensonic@users.sf.net>
|
||||
|
||||
* docs/gst/gstreamer-sections.txt:
|
||||
* gst/gstcaps.c: (gst_caps_structure_is_subset_field),
|
||||
(gst_caps_structure_is_subset), (gst_caps_merge),
|
||||
(gst_caps_merge_structure):
|
||||
* gst/gstcaps.h:
|
||||
* libs/gst/base/gstbasetransform.c:
|
||||
(gst_base_transform_transform_caps):
|
||||
* tests/check/gst/gstcaps.c: (GST_START_TEST), (gst_caps_suite):
|
||||
implement caps merging (fixes #352580)
|
||||
|
||||
2006-08-23 Stefan Kost <ensonic@users.sf.net>
|
||||
|
||||
* tools/Makefile.am:
|
||||
|
|
|
@ -223,6 +223,7 @@ gst_caps_append
|
|||
gst_caps_merge
|
||||
gst_caps_append_structure
|
||||
gst_caps_remove_structure
|
||||
gst_caps_merge_structure
|
||||
gst_caps_get_size
|
||||
gst_caps_get_structure
|
||||
gst_caps_set_simple
|
||||
|
|
143
gst/gstcaps.c
143
gst/gstcaps.c
|
@ -480,6 +480,75 @@ gst_structure_is_equal_foreach (GQuark field_id, const GValue * val2,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_caps_structure_is_subset_field (GQuark field_id, const GValue * value,
|
||||
gpointer user_data)
|
||||
{
|
||||
GstStructure *subtract_from = user_data;
|
||||
GValue subtraction = { 0, };
|
||||
const GValue *other;
|
||||
gint res;
|
||||
|
||||
other = gst_structure_id_get_value (subtract_from, field_id);
|
||||
if (!other) {
|
||||
/* field is missing in one set */
|
||||
return FALSE;
|
||||
}
|
||||
/*{
|
||||
gchar *str = g_strdup_value_contents (value);
|
||||
GST_DEBUG (" value: '%s'", str);
|
||||
g_free (str);
|
||||
str = g_strdup_value_contents (other);
|
||||
GST_DEBUG (" other: '%s'", str);
|
||||
g_free (str);
|
||||
} */
|
||||
/*
|
||||
[1,2] - 1 = 2
|
||||
1 - [1,2] = <EFBFBD> ???
|
||||
*/
|
||||
if (!gst_value_subtract (&subtraction, other, value)) {
|
||||
/* empty result -> values are the same, or first was a value and
|
||||
* second was a list
|
||||
*/
|
||||
/* verify that result is empty by swapping args */
|
||||
if (!gst_value_subtract (&subtraction, value, other)) {
|
||||
/*GST_DEBUG (" values are the same"); */
|
||||
return TRUE;
|
||||
}
|
||||
g_value_unset (&subtraction);
|
||||
return FALSE;
|
||||
}
|
||||
/*{
|
||||
gchar *str = g_strdup_value_contents (&subtraction);
|
||||
GST_DEBUG (" diff: '%s'", str);
|
||||
g_free (str);
|
||||
} */
|
||||
res = gst_value_compare (&subtraction, other);
|
||||
if (res == GST_VALUE_EQUAL) {
|
||||
/* value was empty ? */
|
||||
g_value_unset (&subtraction);
|
||||
/*GST_DEBUG (" compare = equal (%d)",res); */
|
||||
return FALSE;
|
||||
} else {
|
||||
/*GST_DEBUG (" compare = unequal/unordered (%d)",res); */
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_caps_structure_is_subset (const GstStructure * minuend,
|
||||
const GstStructure * subtrahend)
|
||||
{
|
||||
if ((minuend->name != subtrahend->name) ||
|
||||
(gst_structure_n_fields (minuend) !=
|
||||
gst_structure_n_fields (subtrahend))) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return gst_structure_foreach ((GstStructure *) subtrahend,
|
||||
gst_caps_structure_is_subset_field, (gpointer) minuend);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_caps_append:
|
||||
* @caps1: the #GstCaps that will be appended to
|
||||
|
@ -526,9 +595,9 @@ gst_caps_append (GstCaps * caps1, GstCaps * caps2)
|
|||
* @caps1: the #GstCaps that will take the new entries
|
||||
* @caps2: the #GstCaps to merge in
|
||||
*
|
||||
* Appends the structures contained in @caps2 to @caps1 if they are not yet in
|
||||
* @caps1. The structures in @caps2 are not copied -- they are transferred to
|
||||
* @caps1, and then @caps2 is freed.
|
||||
* Appends the structures contained in @caps2 to @caps1 if they are not yet
|
||||
* expressed by @caps1. The structures in @caps2 are not copied -- they are
|
||||
* transferred to @caps1, and then @caps2 is freed.
|
||||
* If either caps is ANY, the resulting caps will be ANY.
|
||||
*/
|
||||
void
|
||||
|
@ -545,23 +614,33 @@ gst_caps_merge (GstCaps * caps1, GstCaps * caps2)
|
|||
#ifdef USE_POISONING
|
||||
CAPS_POISON (caps2);
|
||||
#endif
|
||||
if (gst_caps_is_any (caps1) || gst_caps_is_any (caps2)) {
|
||||
/* FIXME: this leaks */
|
||||
caps1->flags |= GST_CAPS_FLAGS_ANY;
|
||||
if (gst_caps_is_any (caps1)) {
|
||||
for (i = caps2->structs->len - 1; i >= 0; i--) {
|
||||
structure = gst_caps_remove_and_get_structure (caps2, i);
|
||||
gst_structure_free (structure);
|
||||
}
|
||||
} else if (gst_caps_is_any (caps2)) {
|
||||
caps1->flags |= GST_CAPS_FLAGS_ANY;
|
||||
for (i = caps1->structs->len - 1; i >= 0; i--) {
|
||||
structure = gst_caps_remove_and_get_structure (caps1, i);
|
||||
gst_structure_free (structure);
|
||||
}
|
||||
} else {
|
||||
int len = caps2->structs->len;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
structure = gst_caps_remove_and_get_structure (caps2, 0);
|
||||
gst_caps_merge_structure (caps1, structure);
|
||||
}
|
||||
/* this is too naive
|
||||
GstCaps *com = gst_caps_intersect (caps1, caps2);
|
||||
GstCaps *add = gst_caps_subtract (caps2, com);
|
||||
|
||||
/*
|
||||
GST_DEBUG ("common : %d", gst_caps_get_size (com));
|
||||
GST_DEBUG ("adding : %d", gst_caps_get_size (add));
|
||||
*/
|
||||
gst_caps_append (caps1, add);
|
||||
gst_caps_unref (com);
|
||||
*/
|
||||
}
|
||||
gst_caps_unref (caps2); /* guaranteed to free it */
|
||||
}
|
||||
|
@ -613,6 +692,54 @@ gst_caps_remove_structure (GstCaps * caps, guint idx)
|
|||
gst_structure_free (structure);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_caps_merge_structure:
|
||||
* @caps: the #GstCaps that will the the new structure
|
||||
* @structure: the #GstStructure to merge
|
||||
*
|
||||
* Appends @structure to @caps if its not already expressed by @caps. The
|
||||
* structure is not copied; @caps becomes the owner of @structure.
|
||||
*/
|
||||
void
|
||||
gst_caps_merge_structure (GstCaps * caps, GstStructure * structure2)
|
||||
{
|
||||
g_return_if_fail (GST_IS_CAPS (caps));
|
||||
g_return_if_fail (IS_WRITABLE (caps));
|
||||
|
||||
if (G_LIKELY (structure2)) {
|
||||
GstStructure *structure1;
|
||||
int i;
|
||||
gboolean unique = TRUE;
|
||||
|
||||
g_return_if_fail (structure2->parent_refcount == NULL);
|
||||
#if 0
|
||||
#ifdef USE_POISONING
|
||||
STRUCTURE_POISON (structure2);
|
||||
#endif
|
||||
#endif
|
||||
/*GST_DEBUG ("merge ?: %" GST_PTR_FORMAT, structure2); */
|
||||
/* check each structure */
|
||||
for (i = caps->structs->len - 1; i >= 0; i--) {
|
||||
structure1 = gst_caps_get_structure (caps, i);
|
||||
/*GST_DEBUG (" with: %" GST_PTR_FORMAT, structure1); */
|
||||
/* if structure2 is a subset of structure1, then skip it */
|
||||
if (gst_caps_structure_is_subset (structure1, structure2)) {
|
||||
/*GST_DEBUG (" no"); */
|
||||
unique = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (unique) {
|
||||
/*GST_DEBUG (" yes"); */
|
||||
gst_structure_set_parent_refcount (structure2, &caps->refcount);
|
||||
g_ptr_array_add (caps->structs, structure2);
|
||||
} else {
|
||||
gst_structure_free (structure2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_caps_get_size:
|
||||
* @caps: a #GstCaps
|
||||
|
|
|
@ -199,6 +199,8 @@ void gst_caps_merge (GstCaps *caps1,
|
|||
void gst_caps_append_structure (GstCaps *caps,
|
||||
GstStructure *structure);
|
||||
void gst_caps_remove_structure (GstCaps * caps, guint idx);
|
||||
void gst_caps_merge_structure (GstCaps * caps1,
|
||||
GstStructure * structure2);
|
||||
guint gst_caps_get_size (const GstCaps *caps);
|
||||
GstStructure * gst_caps_get_structure (const GstCaps *caps,
|
||||
guint index);
|
||||
|
|
|
@ -453,10 +453,11 @@ gst_base_transform_transform_caps (GstBaseTransform * trans,
|
|||
gst_caps_unref (nth);
|
||||
GST_DEBUG_OBJECT (trans, " to[%d]: %" GST_PTR_FORMAT, i, temp);
|
||||
|
||||
/* FIXME: here we need to only append those structures, that are not yet
|
||||
* in there */
|
||||
temp = gst_caps_make_writable (temp);
|
||||
/*gst_caps_append (ret, temp); */
|
||||
/* FIXME: here we need to only append those structures, that are not yet
|
||||
* in there
|
||||
* gst_caps_append (ret, temp);
|
||||
*/
|
||||
gst_caps_merge (ret, temp);
|
||||
}
|
||||
GST_DEBUG_OBJECT (trans, "merged: (%d)", gst_caps_get_size (ret));
|
||||
|
|
|
@ -348,6 +348,95 @@ GST_START_TEST (test_truncate)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_merge_fundamental)
|
||||
{
|
||||
GstCaps *c1, *c2;
|
||||
|
||||
/* ANY + specific = ANY */
|
||||
c1 = gst_caps_from_string ("audio/x-raw-int,rate=44100");
|
||||
c2 = gst_caps_new_any ();
|
||||
gst_caps_merge (c2, c1);
|
||||
GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
|
||||
fail_unless (gst_caps_get_size (c2) == 0, NULL);
|
||||
fail_unless (gst_caps_is_any (c2), NULL);
|
||||
gst_caps_unref (c2);
|
||||
|
||||
/* specific + ANY = ANY */
|
||||
c2 = gst_caps_from_string ("audio/x-raw-int,rate=44100");
|
||||
c1 = gst_caps_new_any ();
|
||||
gst_caps_merge (c2, c1);
|
||||
GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
|
||||
fail_unless (gst_caps_get_size (c2) == 0, NULL);
|
||||
fail_unless (gst_caps_is_any (c2), NULL);
|
||||
gst_caps_unref (c2);
|
||||
|
||||
/* EMPTY + specific = specific */
|
||||
c1 = gst_caps_from_string ("audio/x-raw-int,rate=44100");
|
||||
c2 = gst_caps_new_empty ();
|
||||
gst_caps_merge (c2, c1);
|
||||
GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
|
||||
fail_unless (gst_caps_get_size (c2) == 1, NULL);
|
||||
fail_if (gst_caps_is_empty (c2), NULL);
|
||||
gst_caps_unref (c2);
|
||||
|
||||
/* specific + EMPTY = specific */
|
||||
c2 = gst_caps_from_string ("audio/x-raw-int,rate=44100");
|
||||
c1 = gst_caps_new_empty ();
|
||||
gst_caps_merge (c2, c1);
|
||||
GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
|
||||
fail_unless (gst_caps_get_size (c2) == 1, NULL);
|
||||
fail_if (gst_caps_is_empty (c2), NULL);
|
||||
gst_caps_unref (c2);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_merge_same)
|
||||
{
|
||||
GstCaps *c1, *c2;
|
||||
|
||||
/* this is the same */
|
||||
c1 = gst_caps_from_string ("audio/x-raw-int,rate=44100,channels=1");
|
||||
c2 = gst_caps_from_string ("audio/x-raw-int,rate=44100,channels=1");
|
||||
gst_caps_merge (c2, c1);
|
||||
GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
|
||||
fail_unless (gst_caps_get_size (c2) == 1, NULL);
|
||||
|
||||
/* and so is this */
|
||||
c1 = gst_caps_from_string ("audio/x-raw-int,rate=44100,channels=1");
|
||||
c2 = gst_caps_from_string ("audio/x-raw-int,channels=1,rate=44100");
|
||||
gst_caps_merge (c2, c1);
|
||||
GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
|
||||
fail_unless (gst_caps_get_size (c2) == 1, NULL);
|
||||
|
||||
gst_caps_unref (c2);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_merge_subset)
|
||||
{
|
||||
GstCaps *c1, *c2;
|
||||
|
||||
/* the 2nd is already covered */
|
||||
c2 = gst_caps_from_string ("audio/x-raw-int,channels=[1,2]");
|
||||
c1 = gst_caps_from_string ("audio/x-raw-int,channels=1");
|
||||
gst_caps_merge (c2, c1);
|
||||
GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
|
||||
fail_unless (gst_caps_get_size (c2) == 1, NULL);
|
||||
|
||||
/* here it is not */
|
||||
c2 = gst_caps_from_string ("audio/x-raw-int,channels=1,rate=44100");
|
||||
c1 = gst_caps_from_string ("audio/x-raw-int,channels=[1,2],rate=44100");
|
||||
gst_caps_merge (c2, c1);
|
||||
GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
|
||||
fail_unless (gst_caps_get_size (c2) == 2, NULL);
|
||||
|
||||
gst_caps_unref (c2);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
Suite *
|
||||
gst_caps_suite (void)
|
||||
|
@ -363,6 +452,9 @@ gst_caps_suite (void)
|
|||
tcase_add_test (tc_chain, test_static_caps);
|
||||
tcase_add_test (tc_chain, test_simplify);
|
||||
tcase_add_test (tc_chain, test_truncate);
|
||||
tcase_add_test (tc_chain, test_merge_fundamental);
|
||||
tcase_add_test (tc_chain, test_merge_same);
|
||||
tcase_add_test (tc_chain, test_merge_subset);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue