diff options
author | Stefan Kost <ensonic@users.sf.net> | 2010-07-05 14:05:18 +0300 |
---|---|---|
committer | Stefan Kost <ensonic@users.sf.net> | 2010-09-14 10:43:40 +0300 |
commit | 008f5f632967bd6b807d66f22feff8cce552bfc4 (patch) | |
tree | ddc3dc5b3a7126dc8bbfccdf37622202320b9fb8 | |
parent | 2405c78c1febde4eda8ad214dd5bb165179b93f3 (diff) |
basetransform: use lazy caps in gst_base_transform_transform_caps().lazycaps
Use an iterator for transform_caps.
-rw-r--r-- | libs/gst/base/gstbasetransform.c | 221 |
1 files changed, 210 insertions, 11 deletions
diff --git a/libs/gst/base/gstbasetransform.c b/libs/gst/base/gstbasetransform.c index 8460be03f..645ef631d 100644 --- a/libs/gst/base/gstbasetransform.c +++ b/libs/gst/base/gstbasetransform.c @@ -456,6 +456,165 @@ gst_base_transform_init (GstBaseTransform * trans, trans->priv->dropped = 0; } +#define USE_TRANSFORM_ITERATOR +/* make check issues: + * libs/transform1.c:1196:F:general:basetransform_chain_ct3:0: Assertion 'transform_ct2_called == TRUE' failed + */ + +#ifdef USE_TRANSFORM_ITERATOR +typedef struct _GstCapsTransformIterator +{ + GstIterator it; + GstBaseTransform *trans; + GstBaseTransformClass *klass; + GstPadDirection direction; + const GstCaps *caps; + GstCaps *in, *out; + guint i, j; + GstCaps *self; +} GstCapsTransformIterator; + +static GstIteratorResult +gst_base_transform_transform_iterator_next (GstCapsTransformIterator * it, + gpointer * result) +{ + GstStructure *s; + +restart: + while (!it->out) { + if (!(s = gst_caps_get_structure (it->caps, it->i))) { + GST_INFO ("transform_caps done, caps=%p, size=%d", + it->self, it->self->structs->len); + return GST_ITERATOR_DONE; + } + + /* some classes return it->in below and thus make in not writeable for a + * while! */ + if (!gst_caps_is_empty (it->in)) { + gst_caps_remove_structure (it->in, 0); + } + gst_caps_append_structure (it->in, gst_structure_copy (s)); + GST_LOG_OBJECT (it->trans, "from[%u]: %" GST_PTR_FORMAT, it->i, it->in); + it->out = it->klass->transform_caps (it->trans, it->direction, it->in); + GST_LOG_OBJECT (it->trans, " to[%u]: %" GST_PTR_FORMAT, it->i, it->out); + it->i++; + + /* FIXME: we need special handling of any caps */ + if (gst_caps_is_any (it->out)) { + GST_WARNING + ("bork! bork! we got any caps and are supposed to return a structure"); + } + if (gst_caps_is_empty (it->out)) { + gst_caps_replace (&it->out, NULL); + } else { + it->j = 0; + } + } + /* iterate over temp */ + if (!(s = gst_caps_get_structure (it->out, it->j))) { + gst_caps_replace (&it->out, NULL); + goto restart; + } + it->j++; + + /* skip those that are already in caps */ + if (gst_caps_structure_is_subset (it->self, s)) { + GST_INFO ("caps=%p, skip not unique structure %" GST_PTR_FORMAT, it->self, + s); + goto restart; + } + + *result = gst_structure_copy (s); + GST_INFO ("caps=%p, return structure %" GST_PTR_FORMAT, it->self, s); + + return GST_ITERATOR_OK; +} + +static void +gst_base_transform_transform_iterator_resync (GstCapsTransformIterator * it) +{ + it->i = it->j = 0; + gst_caps_replace (&it->out, NULL); +} + +static void +gst_base_transform_transform_iterator_free (GstCapsTransformIterator * it) +{ + gst_caps_unref ((GstCaps *) it->caps); + gst_caps_unref (it->in); + gst_caps_replace (&it->out, NULL); + g_free (it); +} + +static GstStructure * +gst_base_transform_transform_eval_structure (GstCaps * caps, guint index, + gpointer user_data) +{ + GstIterator *it = (GstIterator *) user_data; + GstIteratorResult res; + gpointer item; + GstStructure *s = NULL; + + res = gst_iterator_next (it, &item); + switch (res) { + case GST_ITERATOR_OK: + s = (GstStructure *) item; + break; + default: + break; + } + return s; +} + +static void +gst_base_transform_transform_free (const GstCaps * caps, gpointer user_data) +{ + gst_iterator_free ((GstIterator *) user_data); +} + +static GstCaps * +gst_base_transform_transform_copy (const GstCaps * caps, gpointer user_data) +{ + GstCapsTransformIterator *new_it; + GstCapsTransformIterator *old_it = (GstCapsTransformIterator *) user_data; + static guint32 cookie_hack = 0; + GstCaps *ret; + + GST_INFO ("copy lazy caps=%p: cur-size=%d", caps, caps->structs->len); + + new_it = (GstCapsTransformIterator *) + gst_iterator_new (sizeof (GstCapsTransformIterator), GST_TYPE_STRUCTURE, + /*GST_OBJECT_GET_LOCK (XXX) */ NULL, + &cookie_hack, + (GstIteratorNextFunction) gst_base_transform_transform_iterator_next, + (GstIteratorItemFunction) NULL, + (GstIteratorResyncFunction) gst_base_transform_transform_iterator_resync, + (GstIteratorFreeFunction) gst_base_transform_transform_iterator_free); + + new_it->caps = gst_caps_ref ((GstCaps *) old_it->caps); + new_it->trans = old_it->trans; + new_it->klass = old_it->klass; + new_it->direction = old_it->direction; + new_it->in = gst_caps_new_empty (); + + new_it->i = old_it->i; + if (old_it->out) { + new_it->out = gst_caps_ref (old_it->out); + new_it->j = old_it->j; + } else { + new_it->out = NULL; + new_it->j = 0; + } + + ret = gst_caps_new_lazy (gst_base_transform_transform_eval_structure, + gst_base_transform_transform_free, gst_base_transform_transform_copy, + new_it); + new_it->self = ret; + + return ret; +} +#endif + /* given @caps on the src or sink pad (given by @direction) * calculate the possible caps on the other pad. * @@ -476,11 +635,9 @@ gst_base_transform_transform_caps (GstBaseTransform * trans, /* if there is a custom transform function, use this */ if (klass->transform_caps) { GstCaps *temp; - gint i; - /* start with empty caps */ - ret = gst_caps_new_empty (); - GST_DEBUG_OBJECT (trans, "transform caps (direction = %d)", direction); + GST_INFO_OBJECT (trans, "transform caps=%p: cur-size=%d, direction = %d", + caps, caps->structs->len, direction); if (gst_caps_is_any (caps)) { /* for any caps we still have to call the transform function */ @@ -488,19 +645,54 @@ gst_base_transform_transform_caps (GstBaseTransform * trans, temp = klass->transform_caps (trans, direction, caps); GST_DEBUG_OBJECT (trans, " to: %" GST_PTR_FORMAT, temp); - temp = gst_caps_make_writable (temp); - gst_caps_append (ret, temp); + ret = gst_caps_make_writable (temp); } else { +#ifdef USE_TRANSFORM_ITERATOR + GstCapsTransformIterator *it; + static guint32 cookie_hack = 0; + + it = (GstCapsTransformIterator *) + gst_iterator_new (sizeof (GstCapsTransformIterator), + GST_TYPE_STRUCTURE, + /*GST_OBJECT_GET_LOCK (XXX) */ NULL, + &cookie_hack, + (GstIteratorNextFunction) gst_base_transform_transform_iterator_next, + (GstIteratorItemFunction) NULL, (GstIteratorResyncFunction) + gst_base_transform_transform_iterator_resync, + (GstIteratorFreeFunction) gst_base_transform_transform_iterator_free); + + it->caps = gst_caps_ref ((GstCaps *) caps); + it->trans = trans; + it->klass = klass; + it->direction = direction; + it->in = gst_caps_new_empty (); + it->out = NULL; + + gst_base_transform_transform_iterator_resync (it); + + ret = gst_caps_new_lazy (gst_base_transform_transform_eval_structure, + gst_base_transform_transform_free, + gst_base_transform_transform_copy, it); + it->self = ret; + + GST_INFO_OBJECT (trans, "created iterator"); +#else + gint i; gint n = gst_caps_get_size (caps); + GstCaps *nth = gst_caps_new_empty (); + + /* start with empty caps */ + ret = gst_caps_new_empty (); /* we send caps with just one structure to the transform * function as this is easier for the element */ for (i = 0; i < n; i++) { - GstCaps *nth; - - nth = gst_caps_copy_nth (caps, i); + if (!gst_caps_is_empty (nth)) { + gst_caps_remove_structure (nth, 0); + } + gst_caps_append_structure (nth, + gst_structure_copy (gst_caps_get_structure (caps, i))); GST_LOG_OBJECT (trans, "from[%d]: %" GST_PTR_FORMAT, i, nth); temp = klass->transform_caps (trans, direction, nth); - gst_caps_unref (nth); GST_LOG_OBJECT (trans, " to[%d]: %" GST_PTR_FORMAT, i, temp); temp = gst_caps_make_writable (temp); @@ -511,12 +703,14 @@ gst_base_transform_transform_caps (GstBaseTransform * trans, GST_LOG_OBJECT (trans, " merged[%d]: %" GST_PTR_FORMAT, i, ret); } + gst_caps_unref (nth); GST_LOG_OBJECT (trans, "merged: (%d)", gst_caps_get_size (ret)); /* FIXME: we can't do much simplification here because we don't really want to * change the caps order gst_caps_do_simplify (ret); GST_DEBUG_OBJECT (trans, "simplified: (%d)", gst_caps_get_size (ret)); */ +#endif } } else { GST_DEBUG_OBJECT (trans, "identity from: %" GST_PTR_FORMAT, caps); @@ -642,6 +836,9 @@ gst_base_transform_getcaps (GstPad * pad) GstCaps *temp; const GstCaps *templ; + GST_INFO_OBJECT (pad, "checking what peer %s:%s can do", + GST_DEBUG_PAD_NAME (otherpad)); + GST_DEBUG_OBJECT (pad, "peer caps %" GST_PTR_FORMAT, caps); /* filtered against our padtemplate on the other side */ @@ -1042,8 +1239,10 @@ gst_base_transform_acceptcaps_default (GstBaseTransform * trans, ret = gst_caps_can_intersect (allowed, caps); gst_caps_unref (allowed); - if (!ret) + if (!ret) { + GST_DEBUG_OBJECT (trans, "gst_caps_can_intersect() failed"); goto no_transform_possible; + } } #if 0 else { |