mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-30 12:10:37 +00:00
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:
parent
4cecd73c93
commit
574e6ab423
2 changed files with 68 additions and 10 deletions
|
@ -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,15 +1710,51 @@ 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)) {
|
||||||
goto not_supported;
|
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);
|
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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue