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; return GST_PAD_PROBE_OK;
} }
typedef struct
{
GstDecodeChain *chain;
GstPad *pad;
} PadExposeData;
/* connect_pad: /* connect_pad:
* *
* Try to connect the given pad to an element created from one of the factories, * 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; GParamSpec *pspec;
gboolean subtitle; gboolean subtitle;
GList *to_connect = NULL; GList *to_connect = NULL;
GList *to_expose = NULL;
gboolean is_parser_converter = FALSE; gboolean is_parser_converter = FALSE;
/* Set dpad target to pad again, it might've been unset /* 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 */ /* link this element further */
to_connect = connect_element (dbin, delem, chain); to_connect = connect_element (dbin, delem, chain);
{ while (to_connect) {
GList *l; GstPad *opad = to_connect->data;
for (l = to_connect; l;) { gboolean expose_pad = FALSE;
GstPad *opad = GST_PAD_CAST (l->data); GstDecodeChain *new_chain;
gboolean to_expose = FALSE; GstCaps *ocaps;
GstCaps *ocaps;
ocaps = get_pad_caps (opad); ocaps = get_pad_caps (opad);
to_expose = expose_pad =
analyze_new_pad (dbin, delem->element, opad, ocaps, chain, &chain); analyze_new_pad (dbin, delem->element, opad, ocaps, chain,
&new_chain);
if (ocaps) if (ocaps)
gst_caps_unref (ocaps); gst_caps_unref (ocaps);
if (!to_expose) { if (expose_pad) {
GList *l2 = l; PadExposeData *expose_data = g_new0 (PadExposeData, 1);
expose_data->chain = new_chain;
gst_object_unref (opad); expose_data->pad = gst_object_ref (opad);
to_expose = g_list_prepend (to_expose, expose_data);
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 */
gst_object_unref (opad);
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 */ /* 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_WARNING_OBJECT (dbin, "Couldn't set %s to PAUSED",
GST_ELEMENT_NAME (element)); GST_ELEMENT_NAME (element));
g_list_foreach (to_connect, (GFunc) gst_object_unref, NULL); while (to_expose) {
g_list_free (to_connect); PadExposeData *expose_data = to_expose->data;
to_connect = NULL; 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); remove_error_filter (dbin, element, &error_msg);
@ -2586,22 +2593,20 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
SUBTITLE_UNLOCK (dbin); SUBTITLE_UNLOCK (dbin);
} }
{ while (to_expose) {
GList *l; PadExposeData *expose_data = to_expose->data;
for (l = to_connect; l; l = g_list_next (l)) { GstCaps *ocaps;
GstPad *opad = GST_PAD_CAST (l->data);
GstCaps *ocaps;
ocaps = get_pad_caps (opad); ocaps = get_pad_caps (expose_data->pad);
expose_pad (dbin, delem->element, dpad, opad, ocaps, chain, TRUE); expose_pad (dbin, delem->element, expose_data->chain->current_pad,
expose_data->pad, ocaps, expose_data->chain, TRUE);
if (ocaps) if (ocaps)
gst_caps_unref (ocaps); gst_caps_unref (ocaps);
gst_object_unref (opad); gst_object_unref (expose_data->pad);
} g_free (expose_data);
g_list_free (to_connect); to_expose = g_list_delete_link (to_expose, to_expose);
to_connect = NULL;
} }
res = TRUE; res = TRUE;