mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-28 11:55:39 +00:00
basetransform: fix reverse negotiation
When the downstream element suggests a new format, pass the suggestion upstream if we can't convert to it. Fixes #633147
This commit is contained in:
parent
691807d634
commit
ce919c0573
1 changed files with 54 additions and 38 deletions
|
@ -1214,8 +1214,8 @@ gst_base_transform_query (GstPad * pad, GstQuery * query)
|
|||
gst_query_set_position (query, format,
|
||||
gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME,
|
||||
(pad ==
|
||||
trans->sinkpad) ? trans->segment.last_stop : trans->
|
||||
priv->last_stop_out));
|
||||
trans->sinkpad) ? trans->segment.last_stop : trans->priv->
|
||||
last_stop_out));
|
||||
} else {
|
||||
ret = gst_pad_peer_query (otherpad, query);
|
||||
}
|
||||
|
@ -1241,6 +1241,51 @@ gst_base_transform_query_type (GstPad * pad)
|
|||
return types;
|
||||
}
|
||||
|
||||
static void
|
||||
compute_upstream_suggestion (GstBaseTransform * trans, guint expsize,
|
||||
GstCaps * caps)
|
||||
{
|
||||
GstCaps *othercaps;
|
||||
GstBaseTransformPrivate *priv = trans->priv;
|
||||
|
||||
GST_DEBUG_OBJECT (trans, "trying to find upstream suggestion");
|
||||
|
||||
/* 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. */
|
||||
othercaps = gst_base_transform_find_transform (trans, trans->srcpad, caps);
|
||||
|
||||
if (!othercaps) {
|
||||
GST_DEBUG_OBJECT (trans, "incompatible caps, ignoring");
|
||||
/* we received caps that we cannot transform. Upstream is behaving badly
|
||||
* because it should have checked if we could handle these caps. We can
|
||||
* simply ignore these caps and produce a buffer with our original caps. */
|
||||
} else {
|
||||
guint size_suggest;
|
||||
|
||||
GST_DEBUG_OBJECT (trans, "getting size of suggestion");
|
||||
|
||||
/* not a subset, we have a new upstream suggestion, remember it and
|
||||
* allocate a default buffer. First we try to convert the size */
|
||||
if (gst_base_transform_transform_size (trans,
|
||||
GST_PAD_SRC, caps, expsize, othercaps, &size_suggest)) {
|
||||
|
||||
/* ok, remember the suggestions now */
|
||||
GST_DEBUG_OBJECT (trans,
|
||||
"storing new caps and size suggestion of %u and %" GST_PTR_FORMAT,
|
||||
size_suggest, othercaps);
|
||||
|
||||
GST_OBJECT_LOCK (trans->sinkpad);
|
||||
if (priv->sink_suggest)
|
||||
gst_caps_unref (priv->sink_suggest);
|
||||
priv->sink_suggest = gst_caps_ref (othercaps);
|
||||
priv->size_suggest = size_suggest;
|
||||
trans->priv->suggest_pending = TRUE;
|
||||
GST_OBJECT_UNLOCK (trans->sinkpad);
|
||||
}
|
||||
gst_caps_unref (othercaps);
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate a buffer using gst_pad_alloc_buffer
|
||||
*
|
||||
* This function can do renegotiation on the source pad
|
||||
|
@ -1363,6 +1408,12 @@ gst_base_transform_prepare_output_buffer (GstBaseTransform * trans,
|
|||
|
||||
if (!can_convert) {
|
||||
GST_DEBUG_OBJECT (trans, "cannot perform transform on current buffer");
|
||||
|
||||
gst_base_transform_transform_size (trans,
|
||||
GST_PAD_SINK, incaps, GST_BUFFER_SIZE (in_buf), newcaps, &expsize);
|
||||
|
||||
compute_upstream_suggestion (trans, expsize, newcaps);
|
||||
|
||||
/* 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 =
|
||||
|
@ -1426,43 +1477,8 @@ gst_base_transform_prepare_output_buffer (GstBaseTransform * trans,
|
|||
}
|
||||
outsize = expsize;
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (trans, "trying to find upstream suggestion");
|
||||
compute_upstream_suggestion (trans, expsize, newcaps);
|
||||
|
||||
/* 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. */
|
||||
othercaps =
|
||||
gst_base_transform_find_transform (trans, trans->srcpad, newcaps);
|
||||
|
||||
if (!othercaps) {
|
||||
GST_DEBUG_OBJECT (trans, "incompatible caps, ignoring");
|
||||
/* we received caps that we cannot transform. Upstream is behaving badly
|
||||
* because it should have checked if we could handle these caps. We can
|
||||
* simply ignore these caps and produce a buffer with our original caps. */
|
||||
} else {
|
||||
guint size_suggest;
|
||||
|
||||
GST_DEBUG_OBJECT (trans, "getting size of suggestion");
|
||||
|
||||
/* not a subset, we have a new upstream suggestion, remember it and
|
||||
* allocate a default buffer. First we try to convert the size */
|
||||
if (gst_base_transform_transform_size (trans,
|
||||
GST_PAD_SRC, newcaps, expsize, othercaps, &size_suggest)) {
|
||||
|
||||
/* ok, remember the suggestions now */
|
||||
GST_DEBUG_OBJECT (trans,
|
||||
"storing new caps and size suggestion of %u and %" GST_PTR_FORMAT,
|
||||
size_suggest, othercaps);
|
||||
|
||||
GST_OBJECT_LOCK (trans->sinkpad);
|
||||
if (priv->sink_suggest)
|
||||
gst_caps_unref (priv->sink_suggest);
|
||||
priv->sink_suggest = gst_caps_ref (othercaps);
|
||||
priv->size_suggest = size_suggest;
|
||||
trans->priv->suggest_pending = TRUE;
|
||||
GST_OBJECT_UNLOCK (trans->sinkpad);
|
||||
}
|
||||
gst_caps_unref (othercaps);
|
||||
}
|
||||
if (in_buf != *out_buf)
|
||||
gst_buffer_unref (*out_buf);
|
||||
*out_buf = NULL;
|
||||
|
|
Loading…
Reference in a new issue