summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Kost <ensonic@users.sf.net>2010-06-08 13:19:56 +0300
committerStefan Kost <ensonic@users.sf.net>2010-09-14 10:43:40 +0300
commitbb5ac329311523289225dfee31e79290be069b2a (patch)
tree043f1a144acda06b6fc021d72dec3b8a27f2c124
parent60fba4df8b53226b019a1cc72405afbf8b708d06 (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.txt7
-rw-r--r--gst/gstcaps.c294
-rw-r--r--gst/gstcaps.h55
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);