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 */ /* check if we got different caps on this new output buffer */
newcaps = GST_BUFFER_CAPS (*out_buf); newcaps = GST_BUFFER_CAPS (*out_buf);
newsize = GST_BUFFER_SIZE (*out_buf); newsize = GST_BUFFER_SIZE (*out_buf);
if (newcaps && !gst_caps_is_equal (newcaps, oldcaps)) { if (newcaps && !gst_caps_is_equal (newcaps, oldcaps)) {
GstCaps *othercaps; GstCaps *othercaps;
gboolean can_convert; gboolean can_convert;
@ -1619,6 +1620,7 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size,
GstCaps * caps, GstBuffer ** buf) GstCaps * caps, GstBuffer ** buf)
{ {
GstBaseTransform *trans; GstBaseTransform *trans;
GstBaseTransformClass *klass;
GstBaseTransformPrivate *priv; GstBaseTransformPrivate *priv;
GstFlowReturn res; GstFlowReturn res;
gboolean proxy, suggest, same_caps; gboolean proxy, suggest, same_caps;
@ -1626,6 +1628,7 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size,
guint size_suggest; guint size_suggest;
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad)); trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
priv = trans->priv; priv = trans->priv;
GST_DEBUG_OBJECT (pad, "alloc with caps %p %" GST_PTR_FORMAT ", size %u", GST_DEBUG_OBJECT (pad, "alloc with caps %p %" GST_PTR_FORMAT ", size %u",
@ -1707,17 +1710,53 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size,
sink_suggest = NULL; 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); sink_suggest);
} }
if (sink_suggest) { if (sink_suggest) {
templ = gst_pad_get_pad_template_caps (pad); templ = gst_pad_get_pad_template_caps (pad);
if (!gst_caps_can_intersect (sink_suggest, templ)) 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; goto not_supported;
} }
} }
}
}
/* find the best format for the other side here we decide if we will proxy /* find the best format for the other side here we decide if we will proxy
* the caps or not. */ * the caps or not. */
@ -1757,7 +1796,8 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size,
GST_OBJECT_UNLOCK (pad); GST_OBJECT_UNLOCK (pad);
proxy = priv->proxy_alloc; 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 */ /* we only want to proxy if we have no suggestion pending, FIXME */
if (proxy && !suggest) { if (proxy && !suggest) {

View file

@ -642,7 +642,10 @@ GST_START_TEST (basetransform_chain_ct1)
buffer_alloc_ct1_called = FALSE; buffer_alloc_ct1_called = FALSE;
res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, outcaps, &buffer); 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 /* FIXME, why would this call the alloc function? we try to alloc something
* with caps that are not supported on the sinkpad */ * with caps that are not supported on the sinkpad */
fail_unless (buffer_alloc_ct1_called == FALSE); fail_unless (buffer_alloc_ct1_called == FALSE);
@ -743,7 +746,10 @@ GST_START_TEST (basetransform_chain_ct1)
buffer_alloc_ct1_called = FALSE; buffer_alloc_ct1_called = FALSE;
res = gst_pad_alloc_buffer (trans->srcpad, 0, 10, outcaps, &buffer); 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 */ /* should not call the pad-alloc function */
fail_unless (buffer_alloc_ct1_called == FALSE); 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_case = 2;
buffer_alloc_ct2_called = FALSE; buffer_alloc_ct2_called = FALSE;
res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, outcaps, &buffer); 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 */ /* should not call pad-alloc because the caps and sizes are different */
fail_unless (buffer_alloc_ct2_called == FALSE); 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_case = 2;
buffer_alloc_ct2_called = FALSE; buffer_alloc_ct2_called = FALSE;
res = gst_pad_alloc_buffer (trans->srcpad, 0, 10, outcaps, &buffer); 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 */ /* should not call the pad-alloc function */
fail_unless (buffer_alloc_ct2_called == FALSE); 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_case = 2;
buffer_alloc_ct2_called = FALSE; buffer_alloc_ct2_called = FALSE;
res = gst_pad_alloc_buffer (trans->srcpad, 0, 20, outcaps, &buffer); 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 */ /* should not call pad-alloc because the caps and sizes are different */
fail_unless (buffer_alloc_ct2_called == FALSE); 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_case = 2;
buffer_alloc_ct2_called = FALSE; buffer_alloc_ct2_called = FALSE;
res = gst_pad_alloc_buffer (trans->srcpad, 0, 10, outcaps, &buffer); 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 */ /* FIXME should not call the pad-alloc function but it currently does */
fail_unless (buffer_alloc_ct2_called == FALSE); fail_unless (buffer_alloc_ct2_called == FALSE);