X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gst%2Fgstcaps.c;h=905c7118c308c45d1e4c6a104d1111f663878dbc;hb=bcf115a62032d56dbe9c4f0aaf87e7aebc8de1c3;hp=2119396daa157f912058fcf38a4f715df39b19b6;hpb=14f5518f3da03850158b1f931d6271aa9f6c2c4d;p=platform%2Fupstream%2Fgstreamer.git
diff --git a/gst/gstcaps.c b/gst/gstcaps.c
index 2119396..905c711 100644
--- a/gst/gstcaps.c
+++ b/gst/gstcaps.c
@@ -43,8 +43,8 @@
*
Creating caps
*
* GstCaps *caps;
- * caps = gst_caps_new_simple ("video/x-raw-yuv",
- * "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
+ * caps = gst_caps_new_simple ("video/x-raw",
+ * "format", G_TYPE_STRING, "I420",
* "framerate", GST_TYPE_FRACTION, 25, 1,
* "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
* "width", G_TYPE_INT, 320,
@@ -73,53 +73,42 @@
#include
#include
-#ifdef GST_DISABLE_DEPRECATED
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
-#include
-xmlNodePtr gst_caps_save_thyself (const GstCaps * caps, xmlNodePtr parent);
-GstCaps *gst_caps_load_thyself (xmlNodePtr parent);
-#endif
-#endif
-
#define DEBUG_REFCOUNT
-#define CAPS_POISON(caps) G_STMT_START{ \
- if (caps) { \
- GstCaps *_newcaps = gst_caps_copy (caps); \
- gst_caps_unref(caps); \
- caps = _newcaps; \
- } \
-} G_STMT_END
-#define STRUCTURE_POISON(structure) G_STMT_START{ \
- if (structure) { \
- GstStructure *_newstruct = gst_structure_copy (structure); \
- gst_structure_free(structure); \
- structure = _newstruct; \
- } \
-} G_STMT_END
+typedef struct _GstCapsImpl
+{
+ GstCaps caps;
+
+ GPtrArray *array;
+} GstCapsImpl;
+
+#define GST_CAPS_ARRAY(c) (((GstCapsImpl *)(c))->array)
+
+#define GST_CAPS_LEN(c) (GST_CAPS_ARRAY(c)->len)
+
#define IS_WRITABLE(caps) \
- (g_atomic_int_get (&(caps)->refcount) == 1)
+ (GST_CAPS_REFCOUNT_VALUE (caps) == 1)
/* same as gst_caps_is_any () */
#define CAPS_IS_ANY(caps) \
- ((caps)->flags & GST_CAPS_FLAGS_ANY)
+ (GST_CAPS_FLAGS(caps) & GST_CAPS_FLAG_ANY)
/* same as gst_caps_is_empty () */
#define CAPS_IS_EMPTY(caps) \
(!CAPS_IS_ANY(caps) && CAPS_IS_EMPTY_SIMPLE(caps))
#define CAPS_IS_EMPTY_SIMPLE(caps) \
- (((caps)->structs == NULL) || ((caps)->structs->len == 0))
+ ((GST_CAPS_ARRAY (caps) == NULL) || (GST_CAPS_LEN (caps) == 0))
/* quick way to get a caps structure at an index without doing a type or array
* length check */
#define gst_caps_get_structure_unchecked(caps, index) \
- ((GstStructure *)g_ptr_array_index ((caps)->structs, (index)))
+ ((GstStructure *)g_ptr_array_index (GST_CAPS_ARRAY (caps), (index)))
/* quick way to append a structure without checking the args */
#define gst_caps_append_structure_unchecked(caps, structure) G_STMT_START{\
GstStructure *__s=structure; \
- gst_structure_set_parent_refcount (__s, &caps->refcount); \
- g_ptr_array_add (caps->structs, __s); \
+ if (gst_structure_set_parent_refcount (__s, &GST_MINI_OBJECT_REFCOUNT(caps))) \
+ g_ptr_array_add (GST_CAPS_ARRAY (caps), __s); \
}G_STMT_END
/* lock to protect multiple invocations of static caps to caps conversion */
@@ -129,32 +118,97 @@ static void gst_caps_transform_to_string (const GValue * src_value,
GValue * dest_value);
static gboolean gst_caps_from_string_inplace (GstCaps * caps,
const gchar * string);
-static GstCaps *gst_caps_copy_conditional (GstCaps * src);
-GType
-gst_caps_get_type (void)
+GType _gst_caps_type = 0;
+GstCaps *_gst_caps_any;
+GstCaps *_gst_caps_none;
+
+GST_DEFINE_MINI_OBJECT_TYPE (GstCaps, gst_caps);
+
+void
+_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);
+}
+
+static GstCaps *
+_gst_caps_copy (const GstCaps * caps)
{
- static GType gst_caps_type = 0;
+ GstCaps *newcaps;
+ GstStructure *structure;
+ guint i, n;
+
+ g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
+
+ newcaps = gst_caps_new_empty ();
+ GST_CAPS_FLAGS (newcaps) = GST_CAPS_FLAGS (caps);
+ n = GST_CAPS_LEN (caps);
- if (G_UNLIKELY (gst_caps_type == 0)) {
- gst_caps_type = g_boxed_type_register_static ("GstCaps",
- (GBoxedCopyFunc) gst_caps_copy_conditional,
- (GBoxedFreeFunc) gst_caps_unref);
+ GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, caps, "doing copy %p -> %p",
+ caps, newcaps);
- g_value_register_transform_func (gst_caps_type,
- G_TYPE_STRING, gst_caps_transform_to_string);
+ for (i = 0; i < n; i++) {
+ structure = gst_caps_get_structure_unchecked (caps, i);
+ gst_caps_append_structure (newcaps, gst_structure_copy (structure));
}
- return gst_caps_type;
+ return newcaps;
}
/* creation/deletion */
+static void
+_gst_caps_free (GstCaps * caps)
+{
+ GstStructure *structure;
+ guint i, len;
+
+ /* The refcount must be 0, but since we're only called by gst_caps_unref,
+ * don't bother testing. */
+ len = GST_CAPS_LEN (caps);
+ /* This can be used to get statistics about caps sizes */
+ /*GST_CAT_INFO (GST_CAT_CAPS, "caps size: %d", len); */
+ for (i = 0; i < len; i++) {
+ structure = (GstStructure *) gst_caps_get_structure_unchecked (caps, i);
+ gst_structure_set_parent_refcount (structure, NULL);
+ gst_structure_free (structure);
+ }
+ g_ptr_array_free (GST_CAPS_ARRAY (caps), TRUE);
+
+#ifdef DEBUG_REFCOUNT
+ GST_CAT_LOG (GST_CAT_CAPS, "freeing caps %p", caps);
+#endif
+ g_slice_free1 (GST_MINI_OBJECT_SIZE (caps), caps);
+}
+
+static void
+gst_caps_init (GstCaps * caps, gsize size)
+{
+ gst_mini_object_init (GST_MINI_OBJECT_CAST (caps), _gst_caps_type, size);
+
+ caps->mini_object.copy = (GstMiniObjectCopyFunction) _gst_caps_copy;
+ caps->mini_object.dispose = NULL;
+ caps->mini_object.free = (GstMiniObjectFreeFunction) _gst_caps_free;
+
+ /* the 32 has been determined by logging caps sizes in _gst_caps_free
+ * but g_ptr_array uses 16 anyway if it expands once, so this does not help
+ * in practise
+ * GST_CAPS_ARRAY (caps) = g_ptr_array_sized_new (32);
+ */
+ GST_CAPS_ARRAY (caps) = g_ptr_array_new ();
+}
/**
* gst_caps_new_empty:
*
* 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
@@ -162,20 +216,14 @@ gst_caps_get_type (void)
GstCaps *
gst_caps_new_empty (void)
{
- GstCaps *caps = g_slice_new (GstCaps);
+ GstCaps *caps;
- caps->type = GST_TYPE_CAPS;
- caps->refcount = 1;
- caps->flags = GST_CAPS_FLAGS_NONE;
- caps->structs = g_ptr_array_new ();
- /* the 32 has been determined by logging caps sizes in _gst_caps_free
- * but g_ptr_array uses 16 anyway if it expands once, so this does not help
- * in practise
- * caps->structs = g_ptr_array_sized_new (32);
- */
+ caps = (GstCaps *) g_slice_new (GstCapsImpl);
+
+ gst_caps_init (caps, sizeof (GstCapsImpl));
#ifdef DEBUG_REFCOUNT
- GST_CAT_LOG (GST_CAT_CAPS, "created caps %p", caps);
+ GST_CAT_TRACE (GST_CAT_CAPS, "created caps %p", caps);
#endif
return caps;
@@ -194,7 +242,31 @@ gst_caps_new_any (void)
{
GstCaps *caps = gst_caps_new_empty ();
- caps->flags = GST_CAPS_FLAGS_ANY;
+ GST_CAPS_FLAG_SET (caps, GST_CAPS_FLAG_ANY);
+
+ return caps;
+}
+
+/**
+ * gst_caps_new_empty_simple:
+ * @media_type: the media type of the structure
+ *
+ * Creates a new #GstCaps that contains one #GstStructure with name
+ * @media_type.
+ * Caller is responsible for unreffing the returned caps.
+ *
+ * Returns: (transfer full): the new #GstCaps
+ */
+GstCaps *
+gst_caps_new_empty_simple (const char *media_type)
+{
+ GstCaps *caps;
+ GstStructure *structure;
+
+ caps = gst_caps_new_empty ();
+ structure = gst_structure_new_empty (media_type);
+ if (structure)
+ gst_caps_append_structure_unchecked (caps, structure);
return caps;
}
@@ -283,173 +355,7 @@ gst_caps_new_full_valist (GstStructure * structure, va_list var_args)
return caps;
}
-/**
- * gst_caps_copy:
- * @caps: the #GstCaps to copy
- *
- * Creates a new #GstCaps as a copy of the old @caps. The new caps will have a
- * refcount of 1, owned by the caller. The structures are copied as well.
- *
- * Note that this function is the semantic equivalent of a gst_caps_ref()
- * followed by a gst_caps_make_writable(). If you only want to hold on to a
- * reference to the data, you should use gst_caps_ref().
- *
- * When you are finished with the caps, call gst_caps_unref() on it.
- *
- * Returns: (transfer full): the new #GstCaps
- */
-GstCaps *
-gst_caps_copy (const GstCaps * caps)
-{
- GstCaps *newcaps;
- GstStructure *structure;
- guint i, n;
-
- g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
-
- newcaps = gst_caps_new_empty ();
- newcaps->flags = caps->flags;
- n = caps->structs->len;
-
- for (i = 0; i < n; i++) {
- structure = gst_caps_get_structure_unchecked (caps, i);
- gst_caps_append_structure_unchecked (newcaps,
- gst_structure_copy (structure));
- }
-
- return newcaps;
-}
-
-static void
-_gst_caps_free (GstCaps * caps)
-{
- GstStructure *structure;
- guint i, len;
-
- /* The refcount must be 0, but since we're only called by gst_caps_unref,
- * don't bother testing. */
- len = caps->structs->len;
- /* This can be used to get statistics about caps sizes */
- /*GST_CAT_INFO (GST_CAT_CAPS, "caps size: %d", len); */
- for (i = 0; i < len; i++) {
- structure = (GstStructure *) gst_caps_get_structure_unchecked (caps, i);
- gst_structure_set_parent_refcount (structure, NULL);
- gst_structure_free (structure);
- }
- g_ptr_array_free (caps->structs, TRUE);
-#ifdef USE_POISONING
- memset (caps, 0xff, sizeof (GstCaps));
-#endif
-
-#ifdef DEBUG_REFCOUNT
- GST_CAT_LOG (GST_CAT_CAPS, "freeing caps %p", caps);
-#endif
- g_slice_free (GstCaps, caps);
-}
-
-/**
- * gst_caps_make_writable:
- * @caps: (transfer full): the #GstCaps to make writable
- *
- * Returns a writable copy of @caps.
- *
- * If there is only one reference count on @caps, the caller must be the owner,
- * and so this function will return the caps object unchanged. If on the other
- * hand there is more than one reference on the object, a new caps object will
- * be returned. The caller's reference on @caps will be removed, and instead the
- * caller will own a reference to the returned object.
- *
- * In short, this function unrefs the caps in the argument and refs the caps
- * that it returns. Don't access the argument after calling this function. See
- * also: gst_caps_ref().
- *
- * Returns: (transfer full): the same #GstCaps object.
- */
-GstCaps *
-gst_caps_make_writable (GstCaps * caps)
-{
- GstCaps *copy;
-
- g_return_val_if_fail (caps != NULL, NULL);
-
- /* we are the only instance reffing this caps */
- if (IS_WRITABLE (caps))
- return caps;
-
- /* else copy */
- GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy caps");
- copy = gst_caps_copy (caps);
- gst_caps_unref (caps);
-
- return copy;
-}
-
-/**
- * gst_caps_ref:
- * @caps: the #GstCaps to reference
- *
- * Add a reference to a #GstCaps object.
- *
- * From this point on, until the caller calls gst_caps_unref() or
- * gst_caps_make_writable(), it is guaranteed that the caps object will not
- * change. This means its structures won't change, etc. To use a #GstCaps
- * object, you must always have a refcount on it -- either the one made
- * implicitly by e.g. gst_caps_new_simple(), or via taking one explicitly with
- * this function.
- *
- * Returns: (transfer full): the same #GstCaps object.
- */
-GstCaps *
-gst_caps_ref (GstCaps * caps)
-{
- g_return_val_if_fail (caps != NULL, NULL);
-
-#ifdef DEBUG_REFCOUNT
- GST_CAT_TRACE (GST_CAT_REFCOUNTING, "%p %d->%d", caps,
- GST_CAPS_REFCOUNT_VALUE (caps), GST_CAPS_REFCOUNT_VALUE (caps) + 1);
-#endif
- g_return_val_if_fail (GST_CAPS_REFCOUNT_VALUE (caps) > 0, NULL);
-
- g_atomic_int_inc (&caps->refcount);
-
- return caps;
-}
-
-/**
- * gst_caps_unref:
- * @caps: (transfer full): the #GstCaps to unref
- *
- * Unref a #GstCaps and free all its structures and the
- * structures' values when the refcount reaches 0.
- */
-void
-gst_caps_unref (GstCaps * caps)
-{
- g_return_if_fail (caps != NULL);
-
-#ifdef DEBUG_REFCOUNT
- GST_CAT_TRACE (GST_CAT_REFCOUNTING, "%p %d->%d", caps,
- GST_CAPS_REFCOUNT_VALUE (caps), GST_CAPS_REFCOUNT_VALUE (caps) - 1);
-#endif
-
- g_return_if_fail (GST_CAPS_REFCOUNT_VALUE (caps) > 0);
-
- /* if we ended up with the refcount at zero, free the caps */
- if (G_UNLIKELY (g_atomic_int_dec_and_test (&caps->refcount)))
- _gst_caps_free (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:
@@ -464,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 (g_atomic_int_get (&caps->refcount) == 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 (g_atomic_int_get (&caps->refcount) > 0))
+ if (G_UNLIKELY (*caps != NULL))
goto done;
string = static_caps->string;
@@ -485,39 +390,22 @@ gst_static_caps_get (GstStaticCaps * static_caps)
if (G_UNLIKELY (string == NULL))
goto no_string;
- GST_CAT_LOG (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. */
- temp.type = GST_TYPE_CAPS;
- temp.flags = GST_CAPS_FLAGS_NONE;
- temp.structs = g_ptr_array_new ();
-
- /* initialize the caps to a refcount of 1 so the caps can be writable for
- * the next statement */
- temp.refcount = 1;
+ *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);
- /* now copy stuff over to the real caps. */
- caps->type = temp.type;
- caps->flags = temp.flags;
- caps->structs = temp.structs;
- /* and bump the refcount so other threads can now read */
- g_atomic_int_set (&caps->refcount, 1);
-
- GST_CAT_LOG (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:
@@ -528,13 +416,27 @@ no_string:
}
}
+/**
+ * gst_static_caps_cleanup:
+ * @static_caps: the #GstStaticCaps to clean
+ *
+ * Clean up the cached caps contained in @static_caps.
+ */
+void
+gst_static_caps_cleanup (GstStaticCaps * static_caps)
+{
+ G_LOCK (static_caps_lock);
+ gst_caps_replace (&static_caps->caps, NULL);
+ G_UNLOCK (static_caps_lock);
+}
+
/* manipulation */
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 */
- GstStructure *s = g_ptr_array_remove_index (caps->structs, idx);
+ /* 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);
return s;
@@ -559,7 +461,7 @@ gst_caps_steal_structure (GstCaps * caps, guint index)
g_return_val_if_fail (caps != NULL, NULL);
g_return_val_if_fail (IS_WRITABLE (caps), NULL);
- if (G_UNLIKELY (index >= caps->structs->len))
+ if (G_UNLIKELY (index >= GST_CAPS_LEN (caps)))
return NULL;
return gst_caps_remove_and_get_structure (caps, index);
@@ -583,69 +485,61 @@ gst_caps_append (GstCaps * caps1, GstCaps * caps2)
g_return_if_fail (GST_IS_CAPS (caps1));
g_return_if_fail (GST_IS_CAPS (caps2));
g_return_if_fail (IS_WRITABLE (caps1));
- g_return_if_fail (IS_WRITABLE (caps2));
-#ifdef USE_POISONING
- CAPS_POISON (caps2);
-#endif
if (G_UNLIKELY (CAPS_IS_ANY (caps1) || CAPS_IS_ANY (caps2))) {
- /* FIXME: this leaks */
- caps1->flags |= GST_CAPS_FLAGS_ANY;
- for (i = caps2->structs->len - 1; i >= 0; i--) {
- structure = gst_caps_remove_and_get_structure (caps2, i);
- gst_structure_free (structure);
- }
+ GST_CAPS_FLAGS (caps1) |= GST_CAPS_FLAG_ANY;
+ gst_caps_unref (caps2);
} else {
- for (i = caps2->structs->len; i; i--) {
+ 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));
- g_return_if_fail (IS_WRITABLE (caps2));
+ g_return_val_if_fail (GST_IS_CAPS (caps1), NULL);
+ g_return_val_if_fail (GST_IS_CAPS (caps2), NULL);
-#ifdef USE_POISONING
- CAPS_POISON (caps2);
-#endif
if (G_UNLIKELY (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);
- }
+ gst_caps_unref (caps2);
+ result = caps1;
} else if (G_UNLIKELY (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);
- }
+ gst_caps_unref (caps1);
+ result = caps2;
} else {
- for (i = caps2->structs->len; i; i--) {
+ 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);
@@ -656,7 +550,8 @@ gst_caps_merge (GstCaps * caps1, GstCaps * caps2)
gst_caps_unref (com);
*/
}
- gst_caps_unref (caps2); /* guaranteed to free it */
+
+ return result;
}
/**
@@ -674,12 +569,6 @@ gst_caps_append_structure (GstCaps * caps, GstStructure * structure)
g_return_if_fail (IS_WRITABLE (caps));
if (G_LIKELY (structure)) {
- g_return_if_fail (structure->parent_refcount == NULL);
-#if 0
-#ifdef USE_POISONING
- STRUCTURE_POISON (structure);
-#endif
-#endif
gst_caps_append_structure_unchecked (caps, structure);
}
}
@@ -707,44 +596,41 @@ 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));
+ GstStructure *structure1;
+ int i;
+ gboolean unique = TRUE;
- if (G_LIKELY (structure)) {
- GstStructure *structure1;
- int i;
- gboolean unique = TRUE;
-
- g_return_if_fail (structure->parent_refcount == NULL);
-#if 0
-#ifdef USE_POISONING
- STRUCTURE_POISON (structure);
-#endif
-#endif
- /* check each 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_structure_is_subset (structure, structure1)) {
- unique = FALSE;
- break;
- }
- }
- if (unique) {
- gst_caps_append_structure_unchecked (caps, structure);
- } else {
- gst_structure_free (structure);
+ g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
+
+ if (G_UNLIKELY (structure == NULL))
+ return caps;
+
+ /* check each structure */
+ for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) {
+ structure1 = gst_caps_get_structure_unchecked (caps, i);
+ /* if structure is a subset of structure1, then skip it */
+ if (gst_structure_is_subset (structure, structure1)) {
+ unique = FALSE;
+ break;
}
}
+ if (unique) {
+ caps = gst_caps_make_writable (caps);
+ gst_caps_append_structure_unchecked (caps, structure);
+ } else {
+ gst_structure_free (structure);
+ }
+ return caps;
}
/**
@@ -760,7 +646,7 @@ gst_caps_get_size (const GstCaps * caps)
{
g_return_val_if_fail (GST_IS_CAPS (caps), 0);
- return caps->structs->len;
+ return GST_CAPS_LEN (caps);
}
/**
@@ -790,7 +676,7 @@ GstStructure *
gst_caps_get_structure (const GstCaps * caps, guint index)
{
g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
- g_return_val_if_fail (index < caps->structs->len, NULL);
+ g_return_val_if_fail (index < GST_CAPS_LEN (caps), NULL);
return gst_caps_get_structure_unchecked (caps, index);
}
@@ -814,9 +700,9 @@ gst_caps_copy_nth (const GstCaps * caps, guint nth)
g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
newcaps = gst_caps_new_empty ();
- newcaps->flags = caps->flags;
+ GST_CAPS_FLAGS (newcaps) = GST_CAPS_FLAGS (caps);
- if (G_LIKELY (caps->structs->len > nth)) {
+ if (G_LIKELY (GST_CAPS_LEN (caps) > nth)) {
structure = gst_caps_get_structure_unchecked (caps, nth);
gst_caps_append_structure_unchecked (newcaps,
gst_structure_copy (structure));
@@ -827,23 +713,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 = caps->structs->len - 1;
+ 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;
}
/**
@@ -868,7 +760,7 @@ gst_caps_set_value (GstCaps * caps, const char *field, const GValue * value)
g_return_if_fail (field != NULL);
g_return_if_fail (G_IS_VALUE (value));
- len = caps->structs->len;
+ len = GST_CAPS_LEN (caps);
for (i = 0; i < len; i++) {
GstStructure *structure = gst_caps_get_structure_unchecked (caps, i);
gst_structure_set_value (structure, field, value);
@@ -902,10 +794,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);
@@ -1007,7 +895,7 @@ gst_caps_is_fixed (const GstCaps * caps)
g_return_val_if_fail (GST_IS_CAPS (caps), FALSE);
- if (caps->structs->len != 1)
+ if (GST_CAPS_LEN (caps) != 1)
return FALSE;
structure = gst_caps_get_structure_unchecked (caps, 0);
@@ -1085,8 +973,8 @@ gst_caps_is_subset (const GstCaps * subset, const GstCaps * superset)
if (CAPS_IS_ANY (subset) || CAPS_IS_EMPTY (superset))
return FALSE;
- for (i = subset->structs->len - 1; i >= 0; i--) {
- for (j = superset->structs->len - 1; j >= 0; j--) {
+ for (i = GST_CAPS_LEN (subset) - 1; i >= 0; i--) {
+ for (j = GST_CAPS_LEN (superset) - 1; j >= 0; j--) {
s1 = gst_caps_get_structure_unchecked (subset, i);
s2 = gst_caps_get_structure_unchecked (superset, j);
if (gst_structure_is_subset (s1, s2)) {
@@ -1116,7 +1004,7 @@ gst_caps_is_subset (const GstCaps * subset, const GstCaps * superset)
*
* Returns: %TRUE if @structure is a subset of @caps
*
- * Since: 0.10.35
+ * Since: 0.10.36
*/
gboolean
gst_caps_is_subset_structure (const GstCaps * caps,
@@ -1133,7 +1021,7 @@ gst_caps_is_subset_structure (const GstCaps * caps,
if (CAPS_IS_EMPTY (caps))
return FALSE;
- for (i = caps->structs->len - 1; i >= 0; i--) {
+ for (i = GST_CAPS_LEN (caps) - 1; i >= 0; i--) {
s = gst_caps_get_structure_unchecked (caps, i);
if (gst_structure_is_subset (structure, s)) {
/* If we found a superset return TRUE */
@@ -1160,24 +1048,54 @@ 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);
return gst_caps_is_subset (caps1, caps2) && gst_caps_is_subset (caps2, caps1);
}
+/**
+ * gst_caps_is_strictly_equal:
+ * @caps1: a #GstCaps
+ * @caps2: another #GstCaps
+ *
+ * Checks if the given caps are exactly the same set of caps.
+ *
+ * This function deals correctly with passing NULL for any of the caps.
+ *
+ * Returns: TRUE if both caps are strictly equal.
+ *
+ * Since: 0.10.36
+ */
+gboolean
+gst_caps_is_strictly_equal (const GstCaps * caps1, const GstCaps * caps2)
+{
+ int i;
+
+ 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;
+
+ if (GST_CAPS_LEN (caps1) != GST_CAPS_LEN (caps2))
+ return FALSE;
+
+ for (i = 0; i < GST_CAPS_LEN (caps1); i++) {
+ if (!gst_structure_is_equal (gst_caps_get_structure_unchecked (caps1, i),
+ gst_caps_get_structure_unchecked (caps2, i)))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/* intersect operation */
/**
@@ -1232,8 +1150,8 @@ gst_caps_can_intersect (const GstCaps * caps1, const GstCaps * caps2)
* structures. The result is that the intersections are ordered based on the
* sum of the indexes in the list.
*/
- len1 = caps1->structs->len;
- len2 = caps2->structs->len;
+ len1 = GST_CAPS_LEN (caps1);
+ len2 = GST_CAPS_LEN (caps2);
for (i = 0; i < len1 + len2 - 1; i++) {
/* superset index goes from 0 to sgst_caps_structure_intersectuperset->structs->len-1 */
j = MIN (i, len1 - 1);
@@ -1261,7 +1179,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;
@@ -1273,17 +1191,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 ();
@@ -1303,13 +1221,13 @@ gst_caps_intersect_zig_zag (const GstCaps * caps1, const GstCaps * caps2)
* the structures diagonally down, then we iterate over the caps2
* structures.
*/
- len1 = caps1->structs->len;
- len2 = caps2->structs->len;
+ len1 = GST_CAPS_LEN (caps1);
+ len2 = GST_CAPS_LEN (caps2);
for (i = 0; i < len1 + len2 - 1; i++) {
- /* caps1 index goes from 0 to caps1->structs->len-1 */
+ /* caps1 index goes from 0 to GST_CAPS_LEN (caps1)-1 */
j = MIN (i, len1 - 1);
- /* caps2 index stays 0 until i reaches caps1->structs->len, then it counts
- * up from 1 to caps2->structs->len - 1 */
+ /* caps2 index stays 0 until i reaches GST_CAPS_LEN (caps1), then it counts
+ * up from 1 to GST_CAPS_LEN (caps2) - 1 */
k = (i > j) ? (i - j) : 0; /* MAX (0, i - j) */
/* now run the diagonal line, end condition is the left or bottom
@@ -1320,7 +1238,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))
@@ -1345,9 +1263,9 @@ 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)
{
- guint64 i; /* index can be up to 2 * G_MAX_UINT */
+ guint i;
guint j, len1, len2;
GstStructure *struct1;
@@ -1357,29 +1275,29 @@ 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 ();
- len1 = caps1->structs->len;
- len2 = caps2->structs->len;
+ len1 = GST_CAPS_LEN (caps1);
+ len2 = GST_CAPS_LEN (caps2);
for (i = 0; i < len1; i++) {
struct1 = gst_caps_get_structure_unchecked (caps1, i);
for (j = 0; j < len2; j++) {
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);
}
}
@@ -1400,7 +1318,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);
@@ -1428,7 +1346,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);
}
@@ -1507,7 +1425,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;
@@ -1521,7 +1439,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
@@ -1529,10 +1447,10 @@ gst_caps_subtract (const GstCaps * minuend, const GstCaps * subtrahend)
You can only remove everything or nothing and that is done above.
Note: there's a test that checks this behaviour. */
g_return_val_if_fail (!CAPS_IS_ANY (minuend), NULL);
- sublen = subtrahend->structs->len;
+ sublen = GST_CAPS_LEN (subtrahend);
g_assert (sublen > 0);
- src = gst_caps_copy (minuend);
+ src = _gst_caps_copy (minuend);
for (i = 0; i < sublen; i++) {
guint srclen;
@@ -1542,7 +1460,7 @@ gst_caps_subtract (const GstCaps * minuend, const GstCaps * subtrahend)
src = dest;
}
dest = gst_caps_new_empty ();
- srclen = src->structs->len;
+ srclen = GST_CAPS_LEN (src);
for (j = 0; j < srclen; j++) {
min = gst_caps_get_structure_unchecked (src, j);
if (gst_structure_get_name_id (min) == gst_structure_get_name_id (sub)) {
@@ -1570,95 +1488,17 @@ 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;
}
-/* union operation */
-
-#if 0
-static GstStructure *
-gst_caps_structure_union (const GstStructure * struct1,
- const GstStructure * struct2)
-{
- int i;
- GstStructure *dest;
- const GstStructureField *field1;
- const GstStructureField *field2;
- int ret;
-
- /* FIXME this doesn't actually work */
-
- if (struct1->name != struct2->name)
- return NULL;
-
- dest = gst_structure_id_empty_new (struct1->name);
-
- for (i = 0; i < struct1->fields->len; i++) {
- GValue dest_value = { 0 };
-
- field1 = GST_STRUCTURE_FIELD (struct1, i);
- field2 = gst_structure_id_get_field (struct2, field1->name);
-
- if (field2 == NULL) {
- continue;
- } else {
- if (gst_value_union (&dest_value, &field1->value, &field2->value)) {
- gst_structure_set_value (dest, g_quark_to_string (field1->name),
- &dest_value);
- } else {
- ret = gst_value_compare (&field1->value, &field2->value);
- }
- }
- }
-
- return dest;
-}
-#endif
-
-/**
- * gst_caps_union:
- * @caps1: a #GstCaps to union
- * @caps2: a #GstCaps to union
- *
- * Creates a new #GstCaps that contains all the formats that are in
- * either @caps1 and @caps2.
- *
- * Returns: the new #GstCaps
- */
-GstCaps *
-gst_caps_union (const GstCaps * caps1, const 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);
-
- if (CAPS_IS_EMPTY (caps2))
- return gst_caps_copy (caps1);
-
- if (CAPS_IS_ANY (caps1) || CAPS_IS_ANY (caps2))
- return gst_caps_new_any ();
-
- dest1 = gst_caps_copy (caps1);
- dest2 = gst_caps_copy (caps2);
- gst_caps_append (dest1, dest2);
-
- gst_caps_do_simplify (dest1);
- return dest1;
-}
-
/* normalize/simplify operations */
typedef struct _NormalizeForeach
{
GstCaps *caps;
GstStructure *structure;
+ gboolean writable;
}
NormalizeForeach;
@@ -1676,6 +1516,10 @@ gst_caps_normalize_foreach (GQuark field_id, const GValue * value, gpointer ptr)
GstStructure *structure = gst_structure_copy (nf->structure);
gst_structure_id_set_value (structure, field_id, v);
+ if (G_UNLIKELY (!nf->writable)) {
+ nf->caps = gst_caps_make_writable (nf->caps);
+ nf->writable = TRUE;
+ }
gst_caps_append_structure_unchecked (nf->caps, structure);
}
@@ -1690,34 +1534,35 @@ 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;
guint i;
g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
- newcaps = gst_caps_copy (caps);
- nf.caps = newcaps;
+ nf.caps = caps;
+ nf.writable = FALSE;
- for (i = 0; i < gst_caps_get_size (newcaps); i++) {
- nf.structure = gst_caps_get_structure_unchecked (newcaps, i);
+ for (i = 0; i < gst_caps_get_size (nf.caps); i++) {
+ nf.structure = gst_caps_get_structure_unchecked (nf.caps, i);
while (!gst_structure_foreach (nf.structure,
gst_caps_normalize_foreach, &nf));
}
- return newcaps;
+ return nf.caps;
}
static gint
@@ -1770,7 +1615,7 @@ gst_caps_structure_figure_out_union (GQuark field_id, const GValue * value,
static gboolean
gst_caps_structure_simplify (GstStructure ** result,
- const GstStructure * simplify, GstStructure * compare)
+ GstStructure * simplify, GstStructure * compare)
{
GSList *list;
UnionField field = { 0, {0,}, NULL };
@@ -1793,7 +1638,7 @@ gst_caps_structure_simplify (GstStructure ** result,
/* try to union both structs */
field.compare = compare;
- if (gst_structure_foreach ((GstStructure *) simplify,
+ if (gst_structure_foreach (simplify,
gst_caps_structure_figure_out_union, &field)) {
gboolean ret = FALSE;
@@ -1833,42 +1678,45 @@ gst_caps_switch_structures (GstCaps * caps, GstStructure * old,
{
gst_structure_set_parent_refcount (old, NULL);
gst_structure_free (old);
- gst_structure_set_parent_refcount (new, &caps->refcount);
- g_ptr_array_index (caps->structs, i) = new;
+ gst_structure_set_parent_refcount (new, &GST_CAPS_REFCOUNT (caps));
+ g_ptr_array_index (GST_CAPS_ARRAY (caps), i) = new;
}
/**
- * 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
+ * This method does not preserve the original order of @caps.
+ *
+ * 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;
+ start = GST_CAPS_LEN (caps) - 1;
+ /* one caps, already as simple as can be */
+ if (start == 0)
+ return caps;
- g_ptr_array_sort (caps->structs, gst_caps_compare_structures);
+ caps = gst_caps_make_writable (caps);
- start = caps->structs->len - 1;
- for (i = caps->structs->len - 1; i >= 0; i--) {
+ g_ptr_array_sort (GST_CAPS_ARRAY (caps), gst_caps_compare_structures);
+
+ 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)
@@ -1887,96 +1735,41 @@ gst_caps_do_simplify (GstCaps * caps)
start--;
break;
}
- changed = TRUE;
}
}
}
-
- if (!changed)
- return FALSE;
-
- /* gst_caps_do_simplify (caps); */
- return TRUE;
+ return caps;
}
-/* persistence */
-
-#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
/**
- * gst_caps_save_thyself:
- * @caps: a #GstCaps structure
- * @parent: a XML parent node
+ * gst_caps_fixate:
+ * @caps: (transfer full): a #GstCaps to fixate
*
- * Serializes a #GstCaps to XML and adds it as a child node of @parent.
+ * 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().
*
- * Returns: a XML node pointer
+ * Returns: (transfer full): the fixated caps
*/
-xmlNodePtr
-gst_caps_save_thyself (const GstCaps * caps, xmlNodePtr parent)
+GstCaps *
+gst_caps_fixate (GstCaps * caps)
{
- char *s = gst_caps_to_string (caps);
+ GstStructure *s;
- xmlNewChild (parent, NULL, (xmlChar *) "caps", (xmlChar *) s);
- g_free (s);
- return parent;
-}
+ g_return_val_if_fail (GST_IS_CAPS (caps), NULL);
-/**
- * gst_caps_load_thyself:
- * @parent: a XML node
- *
- * Creates a #GstCaps from its XML serialization.
- *
- * Returns: a new #GstCaps structure
- */
-GstCaps *
-gst_caps_load_thyself (xmlNodePtr parent)
-{
- if (strcmp ("caps", (char *) parent->name) == 0) {
- return gst_caps_from_string ((gchar *) xmlNodeGetContent (parent));
- }
+ /* default fixation */
+ caps = gst_caps_truncate (caps);
+ caps = gst_caps_make_writable (caps);
+ s = gst_caps_get_structure (caps, 0);
+ gst_structure_fixate (s);
- return NULL;
+ return caps;
}
-#endif
/* utility */
/**
- * gst_caps_replace:
- * @caps: (inout) (transfer full): a pointer to #GstCaps
- * @newcaps: a #GstCaps to replace *caps
- *
- * Replaces *caps with @newcaps. Unrefs the #GstCaps in the location
- * pointed to by @caps, if applicable, then modifies @caps to point to
- * @newcaps. An additional ref on @newcaps is taken.
- *
- * This function does not take any locks so you might want to lock
- * the object owning @caps pointer.
- */
-void
-gst_caps_replace (GstCaps ** caps, GstCaps * newcaps)
-{
- GstCaps *oldcaps;
-
- g_return_if_fail (caps != NULL);
-
- oldcaps = *caps;
-
- GST_CAT_TRACE (GST_CAT_REFCOUNTING, "%p, %p -> %p", caps, oldcaps, newcaps);
-
- if (newcaps != oldcaps) {
- if (newcaps)
- gst_caps_ref (newcaps);
-
- *caps = newcaps;
-
- if (oldcaps)
- gst_caps_unref (oldcaps);
- }
-}
-
-/**
* gst_caps_to_string:
* @caps: a #GstCaps
*
@@ -2015,7 +1808,7 @@ gst_caps_to_string (const GstCaps * caps)
/* estimate a rough string length to avoid unnecessary reallocs in GString */
slen = 0;
- clen = caps->structs->len;
+ clen = GST_CAPS_LEN (caps);
for (i = 0; i < clen; i++) {
slen +=
STRUCTURE_ESTIMATED_STRING_LEN (gst_caps_get_structure_unchecked (caps,
@@ -2048,7 +1841,7 @@ gst_caps_from_string_inplace (GstCaps * caps, const gchar * string)
gchar *s;
if (strcmp ("ANY", string) == 0) {
- caps->flags = GST_CAPS_FLAGS_ANY;
+ GST_CAPS_FLAGS (caps) = GST_CAPS_FLAG_ANY;
return TRUE;
}
if (strcmp ("EMPTY", string) == 0) {
@@ -2112,16 +1905,6 @@ gst_caps_transform_to_string (const GValue * src_value, GValue * dest_value)
g_return_if_fail (G_VALUE_HOLDS (dest_value, G_TYPE_STRING)
|| G_VALUE_HOLDS (dest_value, G_TYPE_POINTER));
- dest_value->data[0].v_pointer =
- gst_caps_to_string (src_value->data[0].v_pointer);
-}
-
-static GstCaps *
-gst_caps_copy_conditional (GstCaps * src)
-{
- if (src) {
- return gst_caps_ref (src);
- } else {
- return NULL;
- }
+ g_value_take_string (dest_value,
+ gst_caps_to_string (gst_value_get_caps (src_value)));
}