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
This commit is contained in:
Thiago Santos 2010-03-29 18:05:40 -03:00
parent 4cecd73c93
commit 574e6ab423
2 changed files with 68 additions and 10 deletions

View file

@ -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) {

View file

@ -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);