X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gst%2Fgstcaps.c;h=b3c9da5b32a6b83563b6e0c4c421a3b5a7b1ea1a;hb=1bc93bbf8f4f02722ed8e85944201f6978e47cc0;hp=8efd341d36ac160b9bac6693febb542bbec3c3db;hpb=2fe5b4cf91baa94c91b57914238f7e1773656c15;p=platform%2Fupstream%2Fgstreamer.git diff --git a/gst/gstcaps.c b/gst/gstcaps.c index 8efd341..b3c9da5 100644 --- a/gst/gstcaps.c +++ b/gst/gstcaps.c @@ -44,7 +44,7 @@ * * GstCaps *caps; * caps = gst_caps_new_simple ("video/x-raw", - * "format", G_TYPE_STRING, "I420"), + * "format", G_TYPE_STRING, "I420", * "framerate", GST_TYPE_FRACTION, 25, 1, * "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, * "width", G_TYPE_INT, 320, @@ -75,8 +75,14 @@ #define DEBUG_REFCOUNT +typedef struct _GstCapsImpl +{ + GstCaps caps; + + GPtrArray *array; +} GstCapsImpl; -#define GST_CAPS_ARRAY(c) ((GPtrArray *)((c)->priv)) +#define GST_CAPS_ARRAY(c) (((GstCapsImpl *)(c))->array) #define GST_CAPS_LEN(c) (GST_CAPS_ARRAY(c)->len) @@ -114,6 +120,8 @@ static gboolean gst_caps_from_string_inplace (GstCaps * caps, const gchar * string); GType _gst_caps_type = 0; +GstCaps *_gst_caps_any; +GstCaps *_gst_caps_none; GST_DEFINE_MINI_OBJECT_TYPE (GstCaps, gst_caps); @@ -122,6 +130,9 @@ _priv_gst_caps_initialize (void) { _gst_caps_type = gst_caps_get_type (); + _gst_caps_any = gst_caps_new_any (); + _gst_caps_none = gst_caps_new_empty (); + g_value_register_transform_func (_gst_caps_type, G_TYPE_STRING, gst_caps_transform_to_string); } @@ -139,6 +150,9 @@ _gst_caps_copy (const GstCaps * caps) GST_CAPS_FLAGS (newcaps) = GST_CAPS_FLAGS (caps); n = GST_CAPS_LEN (caps); + GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, caps, "doing copy %p -> %p", + caps, newcaps); + for (i = 0; i < n; i++) { structure = gst_caps_get_structure_unchecked (caps, i); gst_caps_append_structure (newcaps, gst_structure_copy (structure)); @@ -186,7 +200,7 @@ gst_caps_init (GstCaps * caps, gsize size) * in practise * GST_CAPS_ARRAY (caps) = g_ptr_array_sized_new (32); */ - caps->priv = g_ptr_array_new (); + GST_CAPS_ARRAY (caps) = g_ptr_array_new (); } /** @@ -194,6 +208,7 @@ gst_caps_init (GstCaps * caps, gsize size) * * Creates a new #GstCaps that is empty. That is, the returned * #GstCaps contains no media formats. + * The #GstCaps is guaranteed to be writable. * Caller is responsible for unreffing the returned caps. * * Returns: (transfer full): the new #GstCaps @@ -203,9 +218,9 @@ gst_caps_new_empty (void) { GstCaps *caps; - caps = g_slice_new (GstCaps); + caps = (GstCaps *) g_slice_new (GstCapsImpl); - gst_caps_init (caps, sizeof (GstCaps)); + gst_caps_init (caps, sizeof (GstCapsImpl)); #ifdef DEBUG_REFCOUNT GST_CAT_TRACE (GST_CAT_CAPS, "created caps %p", caps); @@ -340,17 +355,7 @@ gst_caps_new_full_valist (GstStructure * structure, va_list var_args) return caps; } -GType -gst_static_caps_get_type (void) -{ - static GType staticcaps_type = 0; - - if (G_UNLIKELY (staticcaps_type == 0)) { - staticcaps_type = g_pointer_type_register_static ("GstStaticCaps"); - } - return staticcaps_type; -} - +G_DEFINE_POINTER_TYPE (GstStaticCaps, gst_static_caps); /** * gst_static_caps_get: @@ -365,20 +370,19 @@ gst_static_caps_get_type (void) GstCaps * gst_static_caps_get (GstStaticCaps * static_caps) { - GstCaps *caps; + GstCaps **caps; g_return_val_if_fail (static_caps != NULL, NULL); - caps = (GstCaps *) static_caps; + caps = &static_caps->caps; /* refcount is 0 when we need to convert */ - if (G_UNLIKELY (GST_CAPS_REFCOUNT_VALUE (caps) == 0)) { + if (G_UNLIKELY (*caps == NULL)) { const char *string; - GstCaps temp; G_LOCK (static_caps_lock); /* check if other thread already updated */ - if (G_UNLIKELY (GST_CAPS_REFCOUNT_VALUE (caps) > 0)) + if (G_UNLIKELY (*caps != NULL)) goto done; string = static_caps->string; @@ -386,30 +390,22 @@ gst_static_caps_get (GstStaticCaps * static_caps) if (G_UNLIKELY (string == NULL)) goto no_string; - GST_CAT_TRACE (GST_CAT_CAPS, "creating %p", static_caps); - - /* we construct the caps on the stack, then copy over the struct into our - * real caps, refcount last. We do this because we must leave the refcount - * of the result caps to 0 so that other threads don't run away with the - * caps while we are constructing it. */ - gst_caps_init (&temp, sizeof (GstCaps)); + *caps = gst_caps_from_string (string); /* convert to string */ - if (G_UNLIKELY (!gst_caps_from_string_inplace (&temp, string))) + if (G_UNLIKELY (*caps == NULL)) g_critical ("Could not convert static caps \"%s\"", string); - GST_MINI_OBJECT_REFCOUNT (&temp) = 0; - memcpy (caps, &temp, sizeof (GstCaps)); - gst_caps_ref (caps); - - GST_CAT_TRACE (GST_CAT_CAPS, "created %p", static_caps); + GST_CAT_TRACE (GST_CAT_CAPS, "created %p from string %s", static_caps, + string); done: G_UNLOCK (static_caps_lock); } /* ref the caps, makes it not writable */ - gst_caps_ref (caps); + if (G_LIKELY (*caps != NULL)) + gst_caps_ref (*caps); - return caps; + return *caps; /* ERRORS */ no_string: @@ -422,30 +418,16 @@ no_string: /** * gst_static_caps_cleanup: - * @static_caps: the #GstStaticCaps to convert + * @static_caps: the #GstStaticCaps to clean * - * Clean up the caps contained in @static_caps when the refcount is 0. + * Clean up the cached caps contained in @static_caps. */ void gst_static_caps_cleanup (GstStaticCaps * static_caps) { - GstCaps *caps = (GstCaps *) static_caps; - - /* FIXME: this is not threadsafe */ - if (GST_CAPS_REFCOUNT_VALUE (caps) == 1) { - GstStructure *structure; - guint i, clen; - - clen = GST_CAPS_LEN (caps); - - for (i = 0; i < clen; i++) { - structure = (GstStructure *) gst_caps_get_structure (caps, i); - gst_structure_set_parent_refcount (structure, NULL); - gst_structure_free (structure); - } - g_ptr_array_free (GST_CAPS_ARRAY (caps), TRUE); - GST_CAPS_REFCOUNT (caps) = 0; - } + G_LOCK (static_caps_lock); + gst_caps_replace (&static_caps->caps, NULL); + G_UNLOCK (static_caps_lock); } /* manipulation */ @@ -453,7 +435,7 @@ gst_static_caps_cleanup (GstStaticCaps * static_caps) static GstStructure * gst_caps_remove_and_get_structure (GstCaps * caps, guint idx) { - /* don't use index_fast, gst_caps_do_simplify relies on the order */ + /* don't use index_fast, gst_caps_simplify relies on the order */ GstStructure *s = g_ptr_array_remove_index (GST_CAPS_ARRAY (caps), idx); gst_structure_set_parent_refcount (s, NULL); @@ -504,64 +486,60 @@ gst_caps_append (GstCaps * caps1, GstCaps * caps2) g_return_if_fail (GST_IS_CAPS (caps2)); g_return_if_fail (IS_WRITABLE (caps1)); - caps2 = gst_caps_make_writable (caps2); - if (G_UNLIKELY (CAPS_IS_ANY (caps1) || CAPS_IS_ANY (caps2))) { - /* FIXME: this leaks */ GST_CAPS_FLAGS (caps1) |= GST_CAPS_FLAG_ANY; - for (i = GST_CAPS_LEN (caps2) - 1; i >= 0; i--) { - structure = gst_caps_remove_and_get_structure (caps2, i); - gst_structure_free (structure); - } + gst_caps_unref (caps2); } else { + caps2 = gst_caps_make_writable (caps2); + for (i = GST_CAPS_LEN (caps2); i; i--) { structure = gst_caps_remove_and_get_structure (caps2, 0); gst_caps_append_structure_unchecked (caps1, structure); } + gst_caps_unref (caps2); /* guaranteed to free it */ } - gst_caps_unref (caps2); /* guaranteed to free it */ } /** * gst_caps_merge: - * @caps1: the #GstCaps that will take the new entries + * @caps1: (transfer full): the #GstCaps that will take the new entries * @caps2: (transfer full): the #GstCaps to merge in * * 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. + * transferred to a writable copy of @caps1, and then @caps2 is freed. * If either caps is ANY, the resulting caps will be ANY. * + * Returns: (transfer full): the merged caps. + * * Since: 0.10.10 */ -void +GstCaps * gst_caps_merge (GstCaps * caps1, GstCaps * caps2) { GstStructure *structure; int i; + GstCaps *result; - g_return_if_fail (GST_IS_CAPS (caps1)); - g_return_if_fail (GST_IS_CAPS (caps2)); - g_return_if_fail (IS_WRITABLE (caps1)); - - caps2 = gst_caps_make_writable (caps2); + g_return_val_if_fail (GST_IS_CAPS (caps1), NULL); + g_return_val_if_fail (GST_IS_CAPS (caps2), NULL); if (G_UNLIKELY (CAPS_IS_ANY (caps1))) { - for (i = GST_CAPS_LEN (caps2) - 1; i >= 0; i--) { - structure = gst_caps_remove_and_get_structure (caps2, i); - gst_structure_free (structure); - } + gst_caps_unref (caps2); + result = caps1; } else if (G_UNLIKELY (CAPS_IS_ANY (caps2))) { - GST_CAPS_FLAGS (caps1) |= GST_CAPS_FLAG_ANY; - for (i = GST_CAPS_LEN (caps1) - 1; i >= 0; i--) { - structure = gst_caps_remove_and_get_structure (caps1, i); - gst_structure_free (structure); - } + gst_caps_unref (caps1); + result = caps2; } else { + caps2 = gst_caps_make_writable (caps2); + for (i = GST_CAPS_LEN (caps2); i; i--) { structure = gst_caps_remove_and_get_structure (caps2, 0); - gst_caps_merge_structure (caps1, structure); + caps1 = gst_caps_merge_structure (caps1, structure); } + gst_caps_unref (caps2); + result = caps1; + /* this is too naive GstCaps *com = gst_caps_intersect (caps1, caps2); GstCaps *add = gst_caps_subtract (caps2, com); @@ -572,7 +550,8 @@ gst_caps_merge (GstCaps * caps1, GstCaps * caps2) gst_caps_unref (com); */ } - gst_caps_unref (caps2); /* guaranteed to free it */ + + return result; } /** @@ -617,17 +596,17 @@ gst_caps_remove_structure (GstCaps * caps, guint idx) /** * gst_caps_merge_structure: - * @caps: the #GstCaps that will the new structure + * @caps: (transfer full): the #GstCaps to merge into * @structure: (transfer full): 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. + * Appends @structure to @caps if its not already expressed by @caps. + * + * Returns: (transfer full): the merged caps. */ -void +GstCaps * gst_caps_merge_structure (GstCaps * caps, GstStructure * structure) { - g_return_if_fail (GST_IS_CAPS (caps)); - g_return_if_fail (IS_WRITABLE (caps)); + g_return_val_if_fail (GST_IS_CAPS (caps), NULL); if (G_LIKELY (structure)) { GstStructure *structure1; @@ -644,11 +623,13 @@ gst_caps_merge_structure (GstCaps * caps, GstStructure * structure) } } if (unique) { + caps = gst_caps_make_writable (caps); gst_caps_append_structure_unchecked (caps, structure); } else { gst_structure_free (structure); } } + return caps; } /** @@ -731,23 +712,29 @@ gst_caps_copy_nth (const GstCaps * caps, guint nth) /** * gst_caps_truncate: - * @caps: the #GstCaps to truncate + * @caps: (transfer full): the #GstCaps to truncate + * + * Discard all but the first structure from @caps. Useful when + * fixating. * - * Destructively discard all but the first structure from @caps. Useful when - * fixating. @caps must be writable. + * Returns: (transfer full): truncated caps */ -void +GstCaps * gst_caps_truncate (GstCaps * caps) { gint i; - g_return_if_fail (GST_IS_CAPS (caps)); - g_return_if_fail (IS_WRITABLE (caps)); + g_return_val_if_fail (GST_IS_CAPS (caps), NULL); i = GST_CAPS_LEN (caps) - 1; + if (i == 0) + return caps; + caps = gst_caps_make_writable (caps); while (i > 0) gst_caps_remove_structure (caps, i--); + + return caps; } /** @@ -806,10 +793,6 @@ gst_caps_set_simple_valist (GstCaps * caps, const char *field, va_list varargs) type = va_arg (varargs, GType); - if (G_UNLIKELY (type == G_TYPE_DATE)) { - g_warning ("Don't use G_TYPE_DATE, use GST_TYPE_DATE instead\n"); - type = GST_TYPE_DATE; - } G_VALUE_COLLECT_INIT (&value, type, varargs, 0, &err); if (G_UNLIKELY (err)) { g_critical ("%s", err); @@ -1064,18 +1047,12 @@ gst_caps_is_subset_structure (const GstCaps * caps, gboolean gst_caps_is_equal (const GstCaps * caps1, const GstCaps * caps2) { - /* FIXME 0.11: NULL pointers are no valid Caps but indicate an error - * So there should be an assertion that caps1 and caps2 != NULL */ + g_return_val_if_fail (GST_IS_CAPS (caps1), FALSE); + g_return_val_if_fail (GST_IS_CAPS (caps2), FALSE); - /* NULL <-> NULL is allowed here */ if (G_UNLIKELY (caps1 == caps2)) return TRUE; - /* one of them NULL => they are different (can't be both NULL because - * we checked that above) */ - if (G_UNLIKELY (caps1 == NULL || caps2 == NULL)) - return FALSE; - if (G_UNLIKELY (gst_caps_is_fixed (caps1) && gst_caps_is_fixed (caps2))) return gst_caps_is_equal_fixed (caps1, caps2); @@ -1099,18 +1076,13 @@ gboolean gst_caps_is_strictly_equal (const GstCaps * caps1, const GstCaps * caps2) { int i; - /* FIXME 0.11: NULL pointers are no valid Caps but indicate an error - * So there should be an assertion that caps1 and caps2 != NULL */ - /* NULL <-> NULL is allowed here */ + g_return_val_if_fail (GST_IS_CAPS (caps1), FALSE); + g_return_val_if_fail (GST_IS_CAPS (caps2), FALSE); + if (G_UNLIKELY (caps1 == caps2)) return TRUE; - /* one of them NULL => they are different (can't be both NULL because - * we checked that above) */ - if (G_UNLIKELY (caps1 == NULL || caps2 == NULL)) - return FALSE; - if (GST_CAPS_LEN (caps1) != GST_CAPS_LEN (caps2)) return FALSE; @@ -1206,7 +1178,7 @@ gst_caps_can_intersect (const GstCaps * caps1, const GstCaps * caps2) } static GstCaps * -gst_caps_intersect_zig_zag (const GstCaps * caps1, const GstCaps * caps2) +gst_caps_intersect_zig_zag (GstCaps * caps1, GstCaps * caps2) { guint64 i; /* index can be up to 2 * G_MAX_UINT */ guint j, k, len1, len2; @@ -1218,17 +1190,17 @@ gst_caps_intersect_zig_zag (const GstCaps * caps1, const GstCaps * caps2) /* caps are exactly the same pointers, just copy one caps */ if (G_UNLIKELY (caps1 == caps2)) - return _gst_caps_copy (caps1); + return gst_caps_ref (caps1); /* empty caps on either side, return empty */ if (G_UNLIKELY (CAPS_IS_EMPTY (caps1) || CAPS_IS_EMPTY (caps2))) - return gst_caps_new_empty (); + return gst_caps_ref (GST_CAPS_NONE); /* one of the caps is any, just copy the other caps */ if (G_UNLIKELY (CAPS_IS_ANY (caps1))) - return _gst_caps_copy (caps2); + return gst_caps_ref (caps2); if (G_UNLIKELY (CAPS_IS_ANY (caps2))) - return _gst_caps_copy (caps1); + return gst_caps_ref (caps1); dest = gst_caps_new_empty (); @@ -1265,7 +1237,7 @@ gst_caps_intersect_zig_zag (const GstCaps * caps1, const GstCaps * caps2) istruct = gst_structure_intersect (struct1, struct2); - gst_caps_merge_structure (dest, istruct); + dest = gst_caps_merge_structure (dest, istruct); /* move down left */ k++; if (G_UNLIKELY (j == 0)) @@ -1290,7 +1262,7 @@ gst_caps_intersect_zig_zag (const GstCaps * caps1, const GstCaps * caps2) * Returns: the new #GstCaps */ static GstCaps * -gst_caps_intersect_first (const GstCaps * caps1, const GstCaps * caps2) +gst_caps_intersect_first (GstCaps * caps1, GstCaps * caps2) { guint i; guint j, len1, len2; @@ -1302,17 +1274,17 @@ gst_caps_intersect_first (const GstCaps * caps1, const GstCaps * caps2) /* caps are exactly the same pointers, just copy one caps */ if (G_UNLIKELY (caps1 == caps2)) - return gst_caps_copy (caps1); + return gst_caps_ref (caps1); /* empty caps on either side, return empty */ if (G_UNLIKELY (CAPS_IS_EMPTY (caps1) || CAPS_IS_EMPTY (caps2))) - return gst_caps_new_empty (); + return gst_caps_ref (GST_CAPS_NONE); /* one of the caps is any, just copy the other caps */ if (G_UNLIKELY (CAPS_IS_ANY (caps1))) - return gst_caps_copy (caps2); + return gst_caps_ref (caps2); if (G_UNLIKELY (CAPS_IS_ANY (caps2))) - return gst_caps_copy (caps1); + return gst_caps_ref (caps1); dest = gst_caps_new_empty (); @@ -1324,7 +1296,7 @@ gst_caps_intersect_first (const GstCaps * caps1, const GstCaps * caps2) struct2 = gst_caps_get_structure_unchecked (caps2, j); istruct = gst_structure_intersect (struct1, struct2); if (istruct) - gst_caps_merge_structure (dest, istruct); + dest = gst_caps_merge_structure (dest, istruct); } } @@ -1345,7 +1317,7 @@ gst_caps_intersect_first (const GstCaps * caps1, const GstCaps * caps2) * Since: 0.10.33 */ GstCaps * -gst_caps_intersect_full (const GstCaps * caps1, const GstCaps * caps2, +gst_caps_intersect_full (GstCaps * caps1, GstCaps * caps2, GstCapsIntersectMode mode) { g_return_val_if_fail (GST_IS_CAPS (caps1), NULL); @@ -1373,7 +1345,7 @@ gst_caps_intersect_full (const GstCaps * caps1, const GstCaps * caps2, * Returns: the new #GstCaps */ GstCaps * -gst_caps_intersect (const GstCaps * caps1, const GstCaps * caps2) +gst_caps_intersect (GstCaps * caps1, GstCaps * caps2) { return gst_caps_intersect_full (caps1, caps2, GST_CAPS_INTERSECT_ZIG_ZAG); } @@ -1452,7 +1424,7 @@ gst_caps_structure_subtract (GSList ** into, const GstStructure * minuend, * Returns: the resulting caps */ GstCaps * -gst_caps_subtract (const GstCaps * minuend, const GstCaps * subtrahend) +gst_caps_subtract (GstCaps * minuend, GstCaps * subtrahend) { guint i, j, sublen; GstStructure *min; @@ -1466,7 +1438,7 @@ gst_caps_subtract (const GstCaps * minuend, const GstCaps * subtrahend) return gst_caps_new_empty (); } if (CAPS_IS_EMPTY_SIMPLE (subtrahend)) - return _gst_caps_copy (minuend); + return gst_caps_ref (minuend); /* FIXME: Do we want this here or above? The reason we need this is that there is no definition about what @@ -1515,7 +1487,7 @@ gst_caps_subtract (const GstCaps * minuend, const GstCaps * subtrahend) } gst_caps_unref (src); - gst_caps_do_simplify (dest); + dest = gst_caps_simplify (dest); return dest; } @@ -1572,29 +1544,27 @@ gst_caps_structure_union (const GstStructure * struct1, * Returns: the new #GstCaps */ GstCaps * -gst_caps_union (const GstCaps * caps1, const GstCaps * caps2) +gst_caps_union (GstCaps * caps1, GstCaps * caps2) { GstCaps *dest1; - GstCaps *dest2; /* NULL pointers are no correct GstCaps */ g_return_val_if_fail (caps1 != NULL, NULL); g_return_val_if_fail (caps2 != NULL, NULL); if (CAPS_IS_EMPTY (caps1)) - return _gst_caps_copy (caps2); + return gst_caps_ref (caps2); if (CAPS_IS_EMPTY (caps2)) - return _gst_caps_copy (caps1); + return gst_caps_ref (caps1); if (CAPS_IS_ANY (caps1) || CAPS_IS_ANY (caps2)) - return gst_caps_new_any (); + return gst_caps_ref (caps1); dest1 = _gst_caps_copy (caps1); - dest2 = _gst_caps_copy (caps2); - gst_caps_append (dest1, dest2); + gst_caps_append (dest1, gst_caps_ref (caps2)); - gst_caps_do_simplify (dest1); + dest1 = gst_caps_simplify (dest1); return dest1; } @@ -1635,16 +1605,18 @@ gst_caps_normalize_foreach (GQuark field_id, const GValue * value, gpointer ptr) /** * gst_caps_normalize: - * @caps: a #GstCaps to normalize + * @caps: (transfer full): a #GstCaps to normalize * - * Creates a new #GstCaps that represents the same set of formats as + * Returns a #GstCaps that represents the same set of formats as * @caps, but contains no lists. Each list is expanded into separate * @GstStructures. * - * Returns: the new #GstCaps + * This function takes ownership of @caps. + * + * Returns: (transfer full): the normalized #GstCaps */ GstCaps * -gst_caps_normalize (const GstCaps * caps) +gst_caps_normalize (GstCaps * caps) { NormalizeForeach nf; GstCaps *newcaps; @@ -1652,7 +1624,7 @@ gst_caps_normalize (const GstCaps * caps) g_return_val_if_fail (GST_IS_CAPS (caps), NULL); - newcaps = _gst_caps_copy (caps); + newcaps = gst_caps_make_writable (caps); nf.caps = newcaps; for (i = 0; i < gst_caps_get_size (newcaps); i++) { @@ -1783,37 +1755,37 @@ gst_caps_switch_structures (GstCaps * caps, GstStructure * old, } /** - * gst_caps_do_simplify: - * @caps: a #GstCaps to simplify + * gst_caps_simplify: + * @caps: (transfer full): a #GstCaps to simplify * - * Modifies the given @caps inplace into a representation that represents the + * Converts the given @caps into a representation that represents the * same set of formats, but in a simpler form. Component structures that are * identical are merged. Component structures that have values that can be * merged are also merged. * - * Returns: TRUE, if the caps could be simplified + * Returns: The simplified caps. */ -gboolean -gst_caps_do_simplify (GstCaps * caps) +GstCaps * +gst_caps_simplify (GstCaps * caps) { GstStructure *simplify, *compare, *result = NULL; gint i, j, start; - gboolean changed = FALSE; - g_return_val_if_fail (caps != NULL, FALSE); - g_return_val_if_fail (IS_WRITABLE (caps), FALSE); + g_return_val_if_fail (GST_IS_CAPS (caps), NULL); - if (gst_caps_get_size (caps) < 2) - return FALSE; + if (gst_caps_is_fixed (caps)) + return caps; + + caps = gst_caps_make_writable (caps); g_ptr_array_sort (GST_CAPS_ARRAY (caps), gst_caps_compare_structures); start = GST_CAPS_LEN (caps) - 1; - for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) { + for (i = start; i >= 0; i--) { simplify = gst_caps_get_structure_unchecked (caps, i); + compare = gst_caps_get_structure_unchecked (caps, start); if (gst_structure_get_name_id (simplify) != - gst_structure_get_name_id (gst_caps_get_structure_unchecked (caps, - start))) + gst_structure_get_name_id (compare)) start = i; for (j = start; j >= 0; j--) { if (j == i) @@ -1832,38 +1804,36 @@ gst_caps_do_simplify (GstCaps * caps) start--; break; } - changed = TRUE; } } } - - if (!changed) - return FALSE; - - /* gst_caps_do_simplify (caps); */ - return TRUE; + return caps; } /** * gst_caps_fixate: - * @caps: a #GstCaps to fixate + * @caps: (transfer full): a #GstCaps to fixate * - * Modifies the given @caps inplace into a representation with only fixed + * Modifies the given @caps into a representation with only fixed * values. First the caps will be truncated and then the first structure will be - * fixated with gst_structure_fixate(). @caps should be writable. + * fixated with gst_structure_fixate(). + * + * Returns: (transfer full): the fixated caps */ -void +GstCaps * gst_caps_fixate (GstCaps * caps) { GstStructure *s; - g_return_if_fail (GST_IS_CAPS (caps)); - g_return_if_fail (IS_WRITABLE (caps)); + g_return_val_if_fail (GST_IS_CAPS (caps), NULL); /* default fixation */ - gst_caps_truncate (caps); + caps = gst_caps_truncate (caps); + caps = gst_caps_make_writable (caps); s = gst_caps_get_structure (caps, 0); gst_structure_fixate (s); + + return caps; } /* utility */