From 574e6ab423f0bba58c3bc88085d6c406677f76e4 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 29 Mar 2010 18:05:40 -0300 Subject: [PATCH] basetransform: Try suggesting caps on bad caps pad_alloc When basetransform received an unsupported caps on pad_alloc it just returned not-negotiated. This patch makes it query the allowed caps between his sinkpad and upstream's srcpad to find a caps to suggest. This happens when dinamically switching pipeline elements and upstream pad_allocs with the previous caps that was being used. Fixes #614296 --- libs/gst/base/gstbasetransform.c | 48 ++++++++++++++++++++++++++++++++++++---- tests/check/libs/transform1.c | 30 ++++++++++++++++++++----- 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/libs/gst/base/gstbasetransform.c b/libs/gst/base/gstbasetransform.c index f6f7ab8..8f49737 100644 --- a/libs/gst/base/gstbasetransform.c +++ b/libs/gst/base/gstbasetransform.c @@ -1341,6 +1341,7 @@ gst_base_transform_prepare_output_buffer (GstBaseTransform * trans, /* check if we got different caps on this new output buffer */ newcaps = GST_BUFFER_CAPS (*out_buf); newsize = GST_BUFFER_SIZE (*out_buf); + if (newcaps && !gst_caps_is_equal (newcaps, oldcaps)) { GstCaps *othercaps; gboolean can_convert; @@ -1619,6 +1620,7 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf) { GstBaseTransform *trans; + GstBaseTransformClass *klass; GstBaseTransformPrivate *priv; GstFlowReturn res; gboolean proxy, suggest, same_caps; @@ -1626,6 +1628,7 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size, guint size_suggest; trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad)); + klass = GST_BASE_TRANSFORM_GET_CLASS (trans); priv = trans->priv; GST_DEBUG_OBJECT (pad, "alloc with caps %p %" GST_PTR_FORMAT ", size %u", @@ -1707,15 +1710,51 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size, sink_suggest = NULL; } - GST_DEBUG_OBJECT (trans, "Caps fixated to now: %" GST_PTR_FORMAT, + GST_DEBUG_OBJECT (trans, "Caps fixed to: %" GST_PTR_FORMAT, sink_suggest); } if (sink_suggest) { templ = gst_pad_get_pad_template_caps (pad); - if (!gst_caps_can_intersect (sink_suggest, templ)) - goto not_supported; + if (!gst_caps_can_intersect (sink_suggest, templ)) { + GstCaps *allowed; + GstCaps *peercaps; + + /* the requested pad alloc caps are not supported, so let's try + * picking something allowed between the pads (they are linked, + * there must be something) */ + + allowed = gst_pad_get_allowed_caps (pad); + if (allowed && !gst_caps_is_empty (allowed)) { + GST_DEBUG_OBJECT (trans, "Requested pad alloc caps is not " + "supported, but pads could agree on one of the following caps: " + "%" GST_PTR_FORMAT, allowed); + allowed = gst_caps_make_writable (allowed); + + if (klass->fixate_caps) { + peercaps = + gst_pad_get_allowed_caps (GST_BASE_TRANSFORM_SRC_PAD (trans)); + klass->fixate_caps (trans, GST_PAD_SRC, peercaps, allowed); + gst_caps_unref (peercaps); + } + + /* Fixate them to be safe if the subclass didn't do it */ + gst_caps_truncate (allowed); + gst_pad_fixate_caps (pad, allowed); + gst_caps_replace (&sink_suggest, allowed); + gst_caps_unref (allowed); + + suggest = TRUE; + + GST_DEBUG_OBJECT (trans, "Fixated suggestion caps to %" + GST_PTR_FORMAT, sink_suggest); + } else { + if (allowed) + gst_caps_unref (allowed); + goto not_supported; + } + } } } @@ -1757,7 +1796,8 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size, GST_OBJECT_UNLOCK (pad); proxy = priv->proxy_alloc; - GST_DEBUG_OBJECT (trans, "doing default alloc, proxy %d", proxy); + GST_DEBUG_OBJECT (trans, "doing default alloc, proxy %d, suggest %d", proxy, + suggest); /* we only want to proxy if we have no suggestion pending, FIXME */ if (proxy && !suggest) { diff --git a/tests/check/libs/transform1.c b/tests/check/libs/transform1.c index afd09a7..55b316c 100644 --- a/tests/check/libs/transform1.c +++ b/tests/check/libs/transform1.c @@ -642,7 +642,10 @@ GST_START_TEST (basetransform_chain_ct1) buffer_alloc_ct1_called = FALSE; res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, outcaps, &buffer); - fail_unless (res == GST_FLOW_NOT_NEGOTIATED); + fail_unless (res == GST_FLOW_OK); + fail_if (buffer == NULL); + fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps)); + gst_buffer_unref (buffer); /* FIXME, why would this call the alloc function? we try to alloc something * with caps that are not supported on the sinkpad */ fail_unless (buffer_alloc_ct1_called == FALSE); @@ -743,7 +746,10 @@ GST_START_TEST (basetransform_chain_ct1) buffer_alloc_ct1_called = FALSE; res = gst_pad_alloc_buffer (trans->srcpad, 0, 10, outcaps, &buffer); - fail_unless (res == GST_FLOW_NOT_NEGOTIATED); + fail_unless (res == GST_FLOW_OK); + fail_if (buffer == NULL); + fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps)); + gst_buffer_unref (buffer); /* should not call the pad-alloc function */ fail_unless (buffer_alloc_ct1_called == FALSE); @@ -933,7 +939,10 @@ GST_START_TEST (basetransform_chain_ct2) buffer_alloc_ct2_case = 2; buffer_alloc_ct2_called = FALSE; res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, outcaps, &buffer); - fail_unless (res == GST_FLOW_NOT_NEGOTIATED); + fail_unless (res == GST_FLOW_OK); + fail_if (buffer == NULL); + fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps)); + gst_buffer_unref (buffer); /* should not call pad-alloc because the caps and sizes are different */ fail_unless (buffer_alloc_ct2_called == FALSE); @@ -1024,7 +1033,10 @@ GST_START_TEST (basetransform_chain_ct2) buffer_alloc_ct2_case = 2; buffer_alloc_ct2_called = FALSE; res = gst_pad_alloc_buffer (trans->srcpad, 0, 10, outcaps, &buffer); - fail_unless (res == GST_FLOW_NOT_NEGOTIATED); + fail_unless (res == GST_FLOW_OK); + fail_if (buffer == NULL); + fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps)); + gst_buffer_unref (buffer); /* should not call the pad-alloc function */ fail_unless (buffer_alloc_ct2_called == FALSE); @@ -1086,7 +1098,10 @@ GST_START_TEST (basetransform_chain_ct3) buffer_alloc_ct2_case = 2; buffer_alloc_ct2_called = FALSE; res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, outcaps, &buffer); - fail_unless (res == GST_FLOW_NOT_NEGOTIATED); + fail_unless (res == GST_FLOW_OK); + fail_if (buffer == NULL); + fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps)); + gst_buffer_unref (buffer); /* should not call pad-alloc because the caps and sizes are different */ fail_unless (buffer_alloc_ct2_called == FALSE); @@ -1173,7 +1188,10 @@ GST_START_TEST (basetransform_chain_ct3) buffer_alloc_ct2_case = 2; buffer_alloc_ct2_called = FALSE; res = gst_pad_alloc_buffer (trans->srcpad, 0, 10, outcaps, &buffer); - fail_unless (res == GST_FLOW_NOT_NEGOTIATED); + fail_unless (res == GST_FLOW_OK); + fail_if (buffer == NULL); + fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), incaps)); + gst_buffer_unref (buffer); /* FIXME should not call the pad-alloc function but it currently does */ fail_unless (buffer_alloc_ct2_called == FALSE); -- 2.7.4