mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 00:36:51 +00:00
basetransform: recover from invalid downstream suggestions
When we are handling a buffer and need to allocate an output buffer, handle the case when downstream suggests us a format that we can't convert the input buffer to. In that case, check if there is another format available downstream instead of failing. Fixes #621332 and see also #614296
This commit is contained in:
parent
94a314eaee
commit
f8abf35000
1 changed files with 33 additions and 11 deletions
|
@ -721,7 +721,8 @@ gst_base_transform_configure_caps (GstBaseTransform * trans, GstCaps * in,
|
||||||
|
|
||||||
GST_OBJECT_LOCK (trans);
|
GST_OBJECT_LOCK (trans);
|
||||||
/* make sure we reevaluate how the buffer_alloc works wrt to proxy allocating
|
/* make sure we reevaluate how the buffer_alloc works wrt to proxy allocating
|
||||||
* the buffer. */
|
* the buffer. FIXME, this triggers some quite heavy codepaths that don't need
|
||||||
|
* to be taken.. */
|
||||||
trans->priv->suggest_pending = TRUE;
|
trans->priv->suggest_pending = TRUE;
|
||||||
GST_OBJECT_UNLOCK (trans);
|
GST_OBJECT_UNLOCK (trans);
|
||||||
trans->negotiated = ret;
|
trans->negotiated = ret;
|
||||||
|
@ -1350,17 +1351,36 @@ gst_base_transform_prepare_output_buffer (GstBaseTransform * trans,
|
||||||
|
|
||||||
incaps = GST_PAD_CAPS (trans->sinkpad);
|
incaps = GST_PAD_CAPS (trans->sinkpad);
|
||||||
|
|
||||||
|
/* check if we can convert the current incaps to the new target caps */
|
||||||
|
can_convert =
|
||||||
|
gst_base_transform_can_transform (trans, trans->sinkpad, incaps,
|
||||||
|
newcaps);
|
||||||
|
|
||||||
|
if (!can_convert) {
|
||||||
|
GST_DEBUG_OBJECT (trans, "cannot perform transform on current buffer");
|
||||||
|
/* we got a suggested caps but we can't transform to it. See if there is
|
||||||
|
* another downstream format that we can transform to */
|
||||||
|
othercaps =
|
||||||
|
gst_base_transform_find_transform (trans, trans->sinkpad, incaps);
|
||||||
|
|
||||||
|
if (othercaps && !gst_caps_is_empty (othercaps)) {
|
||||||
|
GST_DEBUG_OBJECT (trans, "we found target caps %" GST_PTR_FORMAT,
|
||||||
|
othercaps);
|
||||||
|
*out_buf = gst_buffer_make_metadata_writable (*out_buf);
|
||||||
|
gst_buffer_set_caps (*out_buf, othercaps);
|
||||||
|
gst_caps_unref (othercaps);
|
||||||
|
newcaps = GST_BUFFER_CAPS (*out_buf);
|
||||||
|
can_convert = TRUE;
|
||||||
|
} else if (othercaps)
|
||||||
|
gst_caps_unref (othercaps);
|
||||||
|
}
|
||||||
|
|
||||||
/* it's possible that the buffer we got is of the wrong size, get the
|
/* it's possible that the buffer we got is of the wrong size, get the
|
||||||
* expected size here, we will check the size if we are going to use the
|
* expected size here, we will check the size if we are going to use the
|
||||||
* buffer later on. */
|
* buffer later on. */
|
||||||
gst_base_transform_transform_size (trans,
|
gst_base_transform_transform_size (trans,
|
||||||
GST_PAD_SINK, incaps, GST_BUFFER_SIZE (in_buf), newcaps, &expsize);
|
GST_PAD_SINK, incaps, GST_BUFFER_SIZE (in_buf), newcaps, &expsize);
|
||||||
|
|
||||||
/* check if we can convert the current incaps to the new target caps */
|
|
||||||
can_convert =
|
|
||||||
gst_base_transform_can_transform (trans, trans->sinkpad, incaps,
|
|
||||||
newcaps);
|
|
||||||
|
|
||||||
if (can_convert) {
|
if (can_convert) {
|
||||||
GST_DEBUG_OBJECT (trans, "reconfigure transform for current buffer");
|
GST_DEBUG_OBJECT (trans, "reconfigure transform for current buffer");
|
||||||
|
|
||||||
|
@ -1401,7 +1421,7 @@ gst_base_transform_prepare_output_buffer (GstBaseTransform * trans,
|
||||||
}
|
}
|
||||||
outsize = expsize;
|
outsize = expsize;
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG_OBJECT (trans, "cannot perform transform on current buffer");
|
GST_DEBUG_OBJECT (trans, "trying to find upstream suggestion");
|
||||||
|
|
||||||
/* we cannot convert the current buffer but we might be able to suggest a
|
/* we cannot convert the current buffer but we might be able to suggest a
|
||||||
* new format upstream, try to find what the best format is. */
|
* new format upstream, try to find what the best format is. */
|
||||||
|
@ -1724,15 +1744,17 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size,
|
||||||
GstCaps *allowed;
|
GstCaps *allowed;
|
||||||
GstCaps *peercaps;
|
GstCaps *peercaps;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (trans,
|
||||||
|
"Requested pad alloc caps are not supported: %" GST_PTR_FORMAT,
|
||||||
|
sink_suggest);
|
||||||
/* the requested pad alloc caps are not supported, so let's try
|
/* the requested pad alloc caps are not supported, so let's try
|
||||||
* picking something allowed between the pads (they are linked,
|
* picking something allowed between the pads (they are linked,
|
||||||
* there must be something) */
|
* there must be something) */
|
||||||
|
|
||||||
allowed = gst_pad_get_allowed_caps (pad);
|
allowed = gst_pad_get_allowed_caps (pad);
|
||||||
if (allowed && !gst_caps_is_empty (allowed)) {
|
if (allowed && !gst_caps_is_empty (allowed)) {
|
||||||
GST_DEBUG_OBJECT (trans, "Requested pad alloc caps is not "
|
GST_DEBUG_OBJECT (trans,
|
||||||
"supported, but pads could agree on one of the following caps: "
|
"pads could agree on one of the following caps: " "%"
|
||||||
"%" GST_PTR_FORMAT, allowed);
|
GST_PTR_FORMAT, allowed);
|
||||||
allowed = gst_caps_make_writable (allowed);
|
allowed = gst_caps_make_writable (allowed);
|
||||||
|
|
||||||
if (klass->fixate_caps) {
|
if (klass->fixate_caps) {
|
||||||
|
|
Loading…
Reference in a new issue