decodebin: Correctly expose pads from elements that have directly exposable pads

analyze_new_pad() can return a new decode chain, which might have a new
GstDecodePad in the end. We should use those two for expose_pad() and not the
original ones that were passed to analyze_new_pad().

This fails when having a demuxer element that has raw pads immediately or
if a decoder with raw caps is after an adaptive demuxer.

https://bugzilla.gnome.org/show_bug.cgi?id=760949
This commit is contained in:
Sebastian Dröge 2016-01-21 18:30:40 +02:00
parent 3674742957
commit acd08a828d

View file

@ -2067,6 +2067,12 @@ demuxer_source_pad_probe (GstPad * pad, GstPadProbeInfo * info,
return GST_PAD_PROBE_OK;
}
typedef struct
{
GstDecodeChain *chain;
GstPad *pad;
} PadExposeData;
/* connect_pad:
*
* Try to connect the given pad to an element created from one of the factories,
@ -2124,6 +2130,7 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
GParamSpec *pspec;
gboolean subtitle;
GList *to_connect = NULL;
GList *to_expose = NULL;
gboolean is_parser_converter = FALSE;
/* Set dpad target to pad again, it might've been unset
@ -2448,34 +2455,31 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
/* link this element further */
to_connect = connect_element (dbin, delem, chain);
{
GList *l;
for (l = to_connect; l;) {
GstPad *opad = GST_PAD_CAST (l->data);
gboolean to_expose = FALSE;
while (to_connect) {
GstPad *opad = to_connect->data;
gboolean expose_pad = FALSE;
GstDecodeChain *new_chain;
GstCaps *ocaps;
ocaps = get_pad_caps (opad);
to_expose =
analyze_new_pad (dbin, delem->element, opad, ocaps, chain, &chain);
expose_pad =
analyze_new_pad (dbin, delem->element, opad, ocaps, chain,
&new_chain);
if (ocaps)
gst_caps_unref (ocaps);
if (!to_expose) {
GList *l2 = l;
if (expose_pad) {
PadExposeData *expose_data = g_new0 (PadExposeData, 1);
expose_data->chain = new_chain;
expose_data->pad = gst_object_ref (opad);
to_expose = g_list_prepend (to_expose, expose_data);
}
gst_object_unref (opad);
l2 = g_list_next (l);
to_connect = g_list_delete_link (to_connect, l);
l = l2;
} else {
l = g_list_next (l);
}
}
/* any pads left in to_connect are to be exposed */
to_connect = g_list_delete_link (to_connect, to_connect);
}
/* any pads left in to_expose are to be exposed */
/* Bring the element to the state of the parent */
@ -2496,9 +2500,12 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
GST_WARNING_OBJECT (dbin, "Couldn't set %s to PAUSED",
GST_ELEMENT_NAME (element));
g_list_foreach (to_connect, (GFunc) gst_object_unref, NULL);
g_list_free (to_connect);
to_connect = NULL;
while (to_expose) {
PadExposeData *expose_data = to_expose->data;
gst_object_unref (expose_data->pad);
g_free (expose_data);
to_expose = g_list_delete_link (to_expose, to_expose);
}
remove_error_filter (dbin, element, &error_msg);
@ -2586,22 +2593,20 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
SUBTITLE_UNLOCK (dbin);
}
{
GList *l;
for (l = to_connect; l; l = g_list_next (l)) {
GstPad *opad = GST_PAD_CAST (l->data);
while (to_expose) {
PadExposeData *expose_data = to_expose->data;
GstCaps *ocaps;
ocaps = get_pad_caps (opad);
expose_pad (dbin, delem->element, dpad, opad, ocaps, chain, TRUE);
ocaps = get_pad_caps (expose_data->pad);
expose_pad (dbin, delem->element, expose_data->chain->current_pad,
expose_data->pad, ocaps, expose_data->chain, TRUE);
if (ocaps)
gst_caps_unref (ocaps);
gst_object_unref (opad);
}
g_list_free (to_connect);
to_connect = NULL;
gst_object_unref (expose_data->pad);
g_free (expose_data);
to_expose = g_list_delete_link (to_expose, to_expose);
}
res = TRUE;