diff options
author | Stefan Kost <ensonic@users.sf.net> | 2010-06-08 13:19:56 +0300 |
---|---|---|
committer | Stefan Kost <ensonic@users.sf.net> | 2010-09-14 10:43:40 +0300 |
commit | bb5ac329311523289225dfee31e79290be069b2a (patch) | |
tree | 043f1a144acda06b6fc021d72dec3b8a27f2c124 | |
parent | 60fba4df8b53226b019a1cc72405afbf8b708d06 (diff) |
caps: add lazy caps
Add a new constructor for caps that are evaluated as needed. Patching the caps
operations to check for lazy caps before accessing fields directly.
API: gst_caps_new_lazy
-rw-r--r-- | docs/gst/gstreamer-sections.txt | 7 | ||||
-rw-r--r-- | gst/gstcaps.c | 294 | ||||
-rw-r--r-- | gst/gstcaps.h | 55 |
3 files changed, 339 insertions, 17 deletions
diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index 2f08eed19..06af677ca 100644 --- a/docs/gst/gstreamer-sections.txt +++ b/docs/gst/gstreamer-sections.txt @@ -282,6 +282,7 @@ gst_caps_new_any gst_caps_new_simple gst_caps_new_full gst_caps_new_full_valist +gst_caps_new_lazy gst_caps_copy gst_caps_copy_nth gst_static_caps_get @@ -318,12 +319,18 @@ gst_caps_make_writable gst_caps_ref gst_caps_truncate gst_caps_unref + +GstCapsEvalStructureFunc +GstCapsFreeFunc +GstCapsCopyFunc + <SUBSECTION Standard> GST_CAPS GST_IS_CAPS GST_TYPE_CAPS GST_TYPE_CAPS_FLAGS <SUBSECTION Private> +GstCapsPrivate gst_caps_flags_get_type gst_caps_get_type </SECTION> diff --git a/gst/gstcaps.c b/gst/gstcaps.c index 00fbc851f..f426fc176 100644 --- a/gst/gstcaps.c +++ b/gst/gstcaps.c @@ -1,5 +1,6 @@ /* GStreamer * Copyright (C) <2003> David A. Schleef <ds@schleef.org> + * <2010> Setfan Kost <ensonic@users.sf.net> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -104,12 +105,16 @@ GstCaps *gst_caps_load_thyself (xmlNodePtr parent); #define CAPS_IS_ANY(caps) \ ((caps)->flags & GST_CAPS_FLAGS_ANY) +#define CAPS_IS_LAZY(caps) \ + ((caps)->priv != NULL) + /* 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)) +static inline gboolean gst_caps_is_empty_simple (GstCaps * caps); +#define CAPS_IS_EMPTY_SIMPLE(caps) \ + gst_caps_is_empty_simple((GstCaps *)caps) /* quick way to get a caps structure at an index without doing a type or array * length check */ @@ -122,6 +127,22 @@ GstCaps *gst_caps_load_thyself (xmlNodePtr parent); g_ptr_array_add (caps->structs, __s); \ }G_STMT_END +#define USE_MUTEX +//#define USE_STATIC_REC_MUTEX +struct _GstCapsPrivate +{ + GstCapsEvalStructureFunc eval_structure_func; + GstCapsFreeFunc free_func; + GstCapsCopyFunc copy_func; + gpointer user_data; +#ifdef USE_MUTEX + GMutex *eval_lock; +#endif +#ifdef USE_STATIC_REC_MUTEX + GStaticRecMutex eval_lock; +#endif +}; + /* lock to protect multiple invocations of static caps to caps conversion */ G_LOCK_DEFINE_STATIC (static_caps_lock); @@ -130,6 +151,7 @@ static void gst_caps_transform_to_string (const GValue * src_value, static gboolean gst_caps_from_string_inplace (GstCaps * caps, const gchar * string); static GstCaps *gst_caps_copy_conditional (GstCaps * src); +static inline void gst_caps_eval_structure (GstCaps * caps, guint index); GType gst_caps_get_type (void) @@ -173,11 +195,11 @@ gst_caps_new_empty (void) * in practise * caps->structs = g_ptr_array_sized_new (32); */ + caps->priv = NULL; #ifdef DEBUG_REFCOUNT GST_CAT_LOG (GST_CAT_CAPS, "created caps %p", caps); #endif - return caps; } @@ -281,6 +303,48 @@ gst_caps_new_full_valist (GstStructure * structure, va_list var_args) } /** + * gst_caps_new_lazy: + * @eval_structure_func: function to eval given structrue index + * @free_func: function to free @user_data + * @copy_func: function to copy this lanzy caps + * @user_data: extra data + * + * Create new caps. Compared to traditional caps, the actual structures are + * made when requested. + * + * Returns: new caps that are lazyly evaluated. + * + * Since: 0.10.XXX + */ +GstCaps * +gst_caps_new_lazy (GstCapsEvalStructureFunc eval_structure_func, + GstCapsFreeFunc free_func, GstCapsCopyFunc copy_func, gpointer user_data) +{ + GstCaps *caps; + GstCapsPrivate *priv; + + caps = gst_caps_new_empty (); + caps->priv = priv = g_slice_new (GstCapsPrivate); + + priv->eval_structure_func = eval_structure_func; + priv->free_func = free_func; + priv->copy_func = copy_func; + + priv->user_data = user_data; + +#ifdef USE_MUTEX + priv->eval_lock = g_mutex_new (); +#endif +#ifdef USE_STATIC_REC_MUTEX + g_static_rec_mutex_init (&priv->eval_lock); +#endif + + GST_INFO ("new lazy caps=%p", caps); + + return caps; +} + +/** * gst_caps_copy: * @caps: the #GstCaps to copy * @@ -303,10 +367,16 @@ gst_caps_copy (const GstCaps * caps) guint i, n; g_return_val_if_fail (GST_IS_CAPS (caps), NULL); - - newcaps = gst_caps_new_empty (); + if (CAPS_IS_LAZY (caps)) { + newcaps = caps->priv->copy_func ((GstCaps *) caps, caps->priv->user_data); + } else { + newcaps = gst_caps_new_empty (); + } newcaps->flags = caps->flags; + n = caps->structs->len; + GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy%s caps=%p (%d structures) -> %p", + (CAPS_IS_LAZY (caps) ? " lazy" : ""), caps, n, newcaps); for (i = 0; i < n; i++) { structure = gst_caps_get_structure_unchecked (caps, i); @@ -318,20 +388,55 @@ gst_caps_copy (const GstCaps * caps) } static void +_gst_caps_lazy_free (GstCaps * caps) +{ + if (CAPS_IS_LAZY (caps)) { + GstCapsPrivate *priv = caps->priv; + + priv->free_func (caps, priv->user_data); + caps->priv = NULL; +#ifdef USE_MUTEX + g_mutex_free (priv->eval_lock); +#endif +#ifdef USE_STATIC_REC_MUTEX + g_static_rec_mutex_free (&priv->eval_lock); +#endif + g_slice_free (GstCapsPrivate, priv); + } +} + +static void _gst_caps_free (GstCaps * caps) { - GstStructure *structure; + GstStructure *s; guint i, len; + if (CAPS_IS_LAZY (caps)) { +#ifndef GST_DISABLE_GST_DEBUG + if (gst_debug_category_get_threshold (GST_CAT_PERFORMANCE) > GST_LEVEL_INFO) { + GstCapsPrivate *priv = caps->priv; + + i = len = caps->structs->len; + while ((s = priv->eval_structure_func (caps, i, priv->user_data))) { + gst_caps_append_structure_unchecked (caps, s); + i++; + } + GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "lazy caps saved %d of %d structures", + caps->structs->len - len, caps->structs->len); + } +#endif + _gst_caps_lazy_free (caps); + } + /* 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); + s = (GstStructure *) gst_caps_get_structure_unchecked (caps, i); + gst_structure_set_parent_refcount (s, NULL); + gst_structure_free (s); } g_ptr_array_free (caps->structs, TRUE); #ifdef USE_POISONING @@ -374,7 +479,6 @@ gst_caps_make_writable (GstCaps * caps) return caps; /* else copy */ - GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy caps"); copy = gst_caps_copy (caps); gst_caps_unref (caps); @@ -491,6 +595,7 @@ gst_static_caps_get (GstStaticCaps * static_caps) temp.type = GST_TYPE_CAPS; temp.flags = 0; temp.structs = g_ptr_array_new (); + temp.priv = NULL; /* initialize the caps to a refcount of 1 so the caps can be writable for * the next statement */ @@ -504,6 +609,7 @@ gst_static_caps_get (GstStaticCaps * static_caps) caps->type = temp.type; caps->flags = temp.flags; caps->structs = temp.structs; + caps->priv = NULL; /* and bump the refcount so other threads can now read */ g_atomic_int_set (&caps->refcount, 1); @@ -660,14 +766,30 @@ gst_caps_append (GstCaps * caps1, GstCaps * caps2) #ifdef USE_POISONING CAPS_POISON (caps2); #endif + if (CAPS_IS_LAZY (caps2)) { + GST_CAT_INFO (GST_CAT_PERFORMANCE, "need to fully evaluate lazy caps=%p", + caps2); + gst_caps_eval_structure ((GstCaps *) caps2, G_MAXUINT); + } if (G_UNLIKELY (CAPS_IS_ANY (caps1) || CAPS_IS_ANY (caps2))) { - /* FIXME: this leaks */ caps1->flags |= GST_CAPS_FLAGS_ANY; + if (CAPS_IS_LAZY (caps1)) { + _gst_caps_lazy_free (caps1); + } + for (i = caps1->structs->len - 1; i >= 0; i--) { + structure = gst_caps_remove_and_get_structure (caps1, i); + gst_structure_free (structure); + } for (i = caps2->structs->len - 1; i >= 0; i--) { structure = gst_caps_remove_and_get_structure (caps2, i); gst_structure_free (structure); } } else { + if (CAPS_IS_LAZY (caps1)) { + GST_CAT_INFO (GST_CAT_PERFORMANCE, "need to fully evaluate lazy caps=%p", + caps1); + gst_caps_eval_structure ((GstCaps *) caps1, G_MAXUINT); + } for (i = caps2->structs->len; i; i--) { structure = gst_caps_remove_and_get_structure (caps2, 0); gst_caps_append_structure_unchecked (caps1, structure); @@ -709,11 +831,24 @@ gst_caps_merge (GstCaps * caps1, GstCaps * caps2) } } else if (G_UNLIKELY (CAPS_IS_ANY (caps2))) { caps1->flags |= GST_CAPS_FLAGS_ANY; + if (CAPS_IS_LAZY (caps1)) { + _gst_caps_lazy_free (caps1); + } for (i = caps1->structs->len - 1; i >= 0; i--) { structure = gst_caps_remove_and_get_structure (caps1, i); gst_structure_free (structure); } } else { + if (CAPS_IS_LAZY (caps1)) { + GST_CAT_INFO (GST_CAT_PERFORMANCE, "need to fully evaluate lazy caps=%p", + caps1); + gst_caps_eval_structure ((GstCaps *) caps1, G_MAXUINT); + } + if (CAPS_IS_LAZY (caps2)) { + GST_CAT_INFO (GST_CAT_PERFORMANCE, "need to fully evaluate lazy caps=%p", + caps2); + gst_caps_eval_structure ((GstCaps *) caps2, G_MAXUINT); + } for (i = caps2->structs->len; i; i--) { structure = gst_caps_remove_and_get_structure (caps2, 0); gst_caps_merge_structure (caps1, structure); @@ -752,6 +887,11 @@ gst_caps_append_structure (GstCaps * caps, GstStructure * structure) STRUCTURE_POISON (structure); #endif #endif + if (CAPS_IS_LAZY (caps)) { + GST_CAT_INFO (GST_CAT_PERFORMANCE, "need to fully evaluate lazy caps=%p", + caps); + gst_caps_eval_structure ((GstCaps *) caps, G_MAXUINT); + } gst_caps_append_structure_unchecked (caps, structure); } } @@ -770,7 +910,14 @@ gst_caps_remove_structure (GstCaps * caps, guint idx) GstStructure *structure; g_return_if_fail (caps != NULL); - g_return_if_fail (idx <= gst_caps_get_size (caps)); + + if (CAPS_IS_LAZY (caps)) { + GST_CAT_INFO (GST_CAT_PERFORMANCE, "need to fully evaluate lazy caps=%p", + caps); + gst_caps_eval_structure ((GstCaps *) caps, G_MAXUINT); + } + + g_return_if_fail (idx <= caps->structs->len); g_return_if_fail (IS_WRITABLE (caps)); structure = gst_caps_remove_and_get_structure (caps, idx); @@ -802,6 +949,11 @@ gst_caps_merge_structure (GstCaps * caps, GstStructure * structure) STRUCTURE_POISON (structure); #endif #endif + if (CAPS_IS_LAZY (caps)) { + GST_CAT_INFO (GST_CAT_PERFORMANCE, "need to fully evaluate lazy caps=%p", + caps); + gst_caps_eval_structure ((GstCaps *) caps, G_MAXUINT); + } /* check each structure */ for (i = caps->structs->len - 1; i >= 0; i--) { structure1 = gst_caps_get_structure_unchecked (caps, i); @@ -831,6 +983,11 @@ guint gst_caps_get_size (const GstCaps * caps) { g_return_val_if_fail (GST_IS_CAPS (caps), 0); + if (CAPS_IS_LAZY (caps)) { + GST_CAT_INFO (GST_CAT_PERFORMANCE, "need to fully evaluate lazy caps=%p", + caps); + gst_caps_eval_structure ((GstCaps *) caps, G_MAXUINT); + } return caps->structs->len; } @@ -861,7 +1018,11 @@ 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); + if (CAPS_IS_LAZY (caps)) { + gst_caps_eval_structure ((GstCaps *) caps, index); + } + if (index >= caps->structs->len) + return NULL; return gst_caps_get_structure_unchecked (caps, index); } @@ -884,6 +1045,9 @@ gst_caps_copy_nth (const GstCaps * caps, guint nth) g_return_val_if_fail (GST_IS_CAPS (caps), NULL); + if (CAPS_IS_LAZY (caps)) + gst_caps_eval_structure ((GstCaps *) caps, nth); + newcaps = gst_caps_new_empty (); newcaps->flags = caps->flags; @@ -909,6 +1073,10 @@ gst_caps_truncate (GstCaps * caps) gint i; g_return_if_fail (GST_IS_CAPS (caps)); + if (CAPS_IS_LAZY (caps)) { + gst_caps_eval_structure ((GstCaps *) caps, 0); + _gst_caps_lazy_free (caps); + } g_return_if_fail (IS_WRITABLE (caps)); i = caps->structs->len - 1; @@ -939,6 +1107,12 @@ 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)); + if (CAPS_IS_LAZY (caps)) { + GST_CAT_INFO (GST_CAT_PERFORMANCE, "need to fully evaluate lazy caps=%p", + caps); + gst_caps_eval_structure ((GstCaps *) caps, G_MAXUINT); + } + len = caps->structs->len; for (i = 0; i < len; i++) { GstStructure *structure = gst_caps_get_structure_unchecked (caps, i); @@ -1083,6 +1257,9 @@ gst_caps_is_fixed (const GstCaps * caps) g_return_val_if_fail (GST_IS_CAPS (caps), FALSE); + if (CAPS_IS_LAZY (caps)) + gst_caps_eval_structure ((GstCaps *) caps, 1); + if (caps->structs->len != 1) return FALSE; @@ -1109,6 +1286,11 @@ gst_caps_is_equal_fixed (const GstCaps * caps1, const GstCaps * caps2) g_return_val_if_fail (gst_caps_is_fixed (caps1), FALSE); g_return_val_if_fail (gst_caps_is_fixed (caps2), FALSE); + if (G_UNLIKELY (CAPS_IS_LAZY (caps1))) + gst_caps_eval_structure ((GstCaps *) caps1, 0); + if (G_UNLIKELY (CAPS_IS_LAZY (caps2))) + gst_caps_eval_structure ((GstCaps *) caps2, 0); + struct1 = gst_caps_get_structure_unchecked (caps1, 0); struct2 = gst_caps_get_structure_unchecked (caps2, 0); @@ -1577,9 +1759,8 @@ gst_caps_subtract (const GstCaps * minuend, const GstCaps * subtrahend) g_return_val_if_fail (minuend != NULL, NULL); g_return_val_if_fail (subtrahend != NULL, NULL); - if (CAPS_IS_EMPTY (minuend) || CAPS_IS_ANY (subtrahend)) { + if (CAPS_IS_EMPTY (minuend) || CAPS_IS_ANY (subtrahend)) return gst_caps_new_empty (); - } if (CAPS_IS_EMPTY_SIMPLE (subtrahend)) return gst_caps_copy (minuend); @@ -1589,6 +1770,12 @@ 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); + + if (CAPS_IS_LAZY (subtrahend)) { + GST_CAT_INFO (GST_CAT_PERFORMANCE, "need to fully evaluate lazy caps=%p", + subtrahend); + gst_caps_eval_structure ((GstCaps *) subtrahend, G_MAXUINT); + } sublen = subtrahend->structs->len; g_assert (sublen > 0); @@ -1602,6 +1789,11 @@ gst_caps_subtract (const GstCaps * minuend, const GstCaps * subtrahend) src = dest; } dest = gst_caps_new_empty (); + if (CAPS_IS_LAZY (src)) { + GST_CAT_INFO (GST_CAT_PERFORMANCE, "need to fully evaluate lazy caps=%p", + src); + gst_caps_eval_structure ((GstCaps *) src, G_MAXUINT); + } srclen = src->structs->len; for (j = 0; j < srclen; j++) { min = gst_caps_get_structure_unchecked (src, j); @@ -1770,6 +1962,12 @@ gst_caps_normalize (const GstCaps * caps) newcaps = gst_caps_copy (caps); nf.caps = newcaps; + if (CAPS_IS_LAZY (newcaps)) { + GST_CAT_INFO (GST_CAT_PERFORMANCE, "need to fully evaluate lazy caps=%p", + newcaps); + gst_caps_eval_structure ((GstCaps *) newcaps, G_MAXUINT); + } + for (i = 0; i < gst_caps_get_size (newcaps); i++) { nf.structure = gst_caps_get_structure_unchecked (newcaps, i); @@ -2056,6 +2254,7 @@ gst_caps_to_string (const GstCaps * caps) { guint i, slen, clen; GString *s; + GstCaps *temp = NULL; /* NOTE: This function is potentially called by the debug system, * so any calls to gst_log() (and GST_DEBUG(), GST_LOG(), etc.) @@ -2069,6 +2268,11 @@ gst_caps_to_string (const GstCaps * caps) if (CAPS_IS_ANY (caps)) { return g_strdup ("ANY"); } + if (CAPS_IS_LAZY (caps)) { + /* use a copy to be free of side effects */ + caps = temp = gst_caps_copy (caps); + gst_caps_eval_structure ((GstCaps *) caps, G_MAXUINT); + } if (CAPS_IS_EMPTY_SIMPLE (caps)) { return g_strdup ("EMPTY"); } @@ -2098,6 +2302,10 @@ gst_caps_to_string (const GstCaps * caps) /* remove latest ';' */ s->str[--s->len] = '\0'; } + + if (temp) + gst_caps_unref (temp); + return g_string_free (s, FALSE); } @@ -2185,3 +2393,59 @@ gst_caps_copy_conditional (GstCaps * src) return NULL; } } + +static inline gboolean +gst_caps_is_empty_simple (GstCaps * caps) +{ + if (CAPS_IS_LAZY (caps)) + gst_caps_eval_structure ((GstCaps *) caps, 0); + return (caps->structs == NULL) || (caps->structs->len == 0); +} + +static inline void +gst_caps_eval_structure (GstCaps * caps, guint index) +{ + GstCapsPrivate *priv = caps->priv; + GstStructure *s = NULL; + guint i; + + /* no need to do anything */ + if (index < caps->structs->len) + return; + + GST_INFO ("need to evaluate lazy caps %p from %u to %u", caps, + caps->structs->len, (index == G_MAXUINT ? G_MAXUINT : index + 1)); + + /* FIXME: somehow this can lock up when using locks :/ + * also ideally we would like to use the look in the iterator + * - maybe we can use the lock only for gst_caps_append_structure_unchecked + */ +#ifdef USE_MUTEX + g_mutex_lock (priv->eval_lock); +#endif +#ifdef USE_STATIC_REC_MUTEX + g_static_rec_mutex_lock (&priv->eval_lock); +#endif + for (i = caps->structs->len; i <= index; i++) { + if ((s = priv->eval_structure_func (caps, i, priv->user_data))) { + gst_caps_append_structure_unchecked (caps, s); + } else { + break; + } + } +#ifdef USE_MUTEX + g_mutex_unlock (priv->eval_lock); +#endif +#ifdef USE_STATIC_REC_MUTEX + g_static_rec_mutex_unlock (&priv->eval_lock); +#endif + + if (!s) { + _gst_caps_lazy_free (caps); + /* FIXME: this is unsafe, gst_caps_to_string() will fully eval lazy caps and + * we should not use GST_PTR_FORMAT here to avoid recursion + */ + GST_INFO ("final caps len=%d, %p: %" GST_PTR_FORMAT, caps->structs->len, + caps, caps); + } +} diff --git a/gst/gstcaps.h b/gst/gstcaps.h index 47d10326d..2bdb179da 100644 --- a/gst/gstcaps.h +++ b/gst/gstcaps.h @@ -22,6 +22,7 @@ #include <gst/gstconfig.h> #include <gst/gststructure.h> +#include <gst/gstiterator.h> #include <gst/glib-compat.h> G_BEGIN_DECLS @@ -106,12 +107,14 @@ typedef enum { */ #define GST_STATIC_CAPS(string) \ { \ - /* caps */ { 0, 0, (GstCapsFlags) 0, NULL, GST_PADDING_INIT }, \ + /* caps */ { 0, 0, (GstCapsFlags) 0, NULL, NULL, GST_PADDING_INIT }, \ /* string */ string, \ GST_PADDING_INIT \ } + typedef struct _GstCaps GstCaps; +typedef struct _GstCapsPrivate GstCapsPrivate; typedef struct _GstStaticCaps GstStaticCaps; /* refcount */ @@ -152,7 +155,11 @@ struct _GstCaps { GPtrArray *structs; /*< private >*/ - gpointer _gst_reserved[GST_PADDING]; + /* lazy caps */ + GstCapsPrivate *priv; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING - 1]; }; /** @@ -173,6 +180,45 @@ struct _GstStaticCaps { gpointer _gst_reserved[GST_PADDING]; }; + +/** + * GstCapsEvalStructureFunc: + * @caps: the lazy caps + * @index: the structure index + * @user_data: the data that was passed to gst_caps_new_lazy() + * + * Evaluate the given structure @index in lazy @capss. + * + * Return: the structure or %NULL when caps are fully evaluated + * + * Since: 0.10.XXX + */ +typedef GstStructure * (*GstCapsEvalStructureFunc) (GstCaps *caps, guint index, gpointer user_data); +/** + * GstCapsFreeFunc: + * @caps: the lazy caps + * @user_data: the data that was passed to gst_caps_new_lazy() + * + * Free user data allocated by lazy @caps. + * + * Since: 0.10.XXX + */ +typedef void (*GstCapsFreeFunc) (const GstCaps *caps, gpointer user_data); +/** + * GstCapsCopyFunc: + * @caps: the lazy caps + * @user_data: the data that was passed to gst_caps_new_lazy() + * + * Copy lazy @caps. + * + * Returns: new lazy caps that is at the same state as the given @caps. + * + * Since: 0.10.XXX + */ +typedef GstCaps * (*GstCapsCopyFunc) (const GstCaps *caps, gpointer user_data); + + + GType gst_caps_get_type (void); GstCaps * gst_caps_new_empty (void); GstCaps * gst_caps_new_any (void); @@ -183,6 +229,11 @@ GstCaps * gst_caps_new_full (GstStructure *struct1, ...) GstCaps * gst_caps_new_full_valist (GstStructure *structure, va_list var_args); +GstCaps * gst_caps_new_lazy (GstCapsEvalStructureFunc eval_structure_func, + GstCapsFreeFunc free_func, + GstCapsCopyFunc copy_func, + gpointer user_data); + /* reference counting */ GstCaps * gst_caps_ref (GstCaps *caps); GstCaps * gst_caps_copy (const GstCaps *caps); |