summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Kost <ensonic@users.sf.net>2010-07-05 14:05:18 +0300
committerStefan Kost <ensonic@users.sf.net>2010-09-14 10:43:40 +0300
commit008f5f632967bd6b807d66f22feff8cce552bfc4 (patch)
treeddc3dc5b3a7126dc8bbfccdf37622202320b9fb8
parent2405c78c1febde4eda8ad214dd5bb165179b93f3 (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.c221
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 {