decodebin: Link Parser/Converter directly and already connect to pad-added and other signals before setting elements to PAUSED

otherwise we're going to
a) start Parser/Converter before they are linked to their capsfilter,
   breaking their negotiation of a proper stream format
b) start demuxers without having connected to their pad-added signals. We
   miss pads and in the worst case don't link any pads at all
This commit is contained in:
Sebastian Dröge 2014-07-10 16:24:36 +02:00
parent 57999c28fd
commit b15a47aa19

View File

@ -1422,7 +1422,7 @@ static gboolean is_adaptive_demuxer_element (GstElement * srcelement);
static gboolean connect_pad (GstDecodeBin * dbin, GstElement * src, static gboolean connect_pad (GstDecodeBin * dbin, GstElement * src,
GstDecodePad * dpad, GstPad * pad, GstCaps * caps, GValueArray * factories, GstDecodePad * dpad, GstPad * pad, GstCaps * caps, GValueArray * factories,
GstDecodeChain * chain); GstDecodeChain * chain);
static gboolean connect_element (GstDecodeBin * dbin, GstDecodeElement * delem, static GList *connect_element (GstDecodeBin * dbin, GstDecodeElement * delem,
GstDecodeChain * chain); GstDecodeChain * chain);
static void expose_pad (GstDecodeBin * dbin, GstElement * src, static void expose_pad (GstDecodeBin * dbin, GstElement * src,
GstDecodePad * dpad, GstPad * pad, GstCaps * caps, GstDecodeChain * chain); GstDecodePad * dpad, GstPad * pad, GstCaps * caps, GstDecodeChain * chain);
@ -1972,6 +1972,8 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
GstPad *sinkpad; GstPad *sinkpad;
GParamSpec *pspec; GParamSpec *pspec;
gboolean subtitle; gboolean subtitle;
GList *to_connect = NULL;
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
* below but we came back here because something failed * below but we came back here because something failed
@ -2068,6 +2070,9 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST (factory))); gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST (factory)));
continue; continue;
} }
is_parser_converter = strstr (gst_element_factory_get_metadata (factory,
GST_ELEMENT_METADATA_KLASS), "Parser") != NULL;
} }
/* emit autoplug-select to see what we should do with it. */ /* emit autoplug-select to see what we should do with it. */
@ -2252,6 +2257,26 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
subtitle = FALSE; subtitle = FALSE;
} }
/* link this element further */
to_connect = connect_element (dbin, delem, chain);
if (is_parser_converter && to_connect) {
GList *l;
for (l = to_connect; l; l = g_list_next (l)) {
GstPad *opad = GST_PAD_CAST (l->data);
GstCaps *ocaps;
ocaps = get_pad_caps (opad);
analyze_new_pad (dbin, delem->element, opad, ocaps, chain);
if (ocaps)
gst_caps_unref (ocaps);
gst_object_unref (opad);
}
g_list_free (to_connect);
to_connect = NULL;
}
/* Bring the element to the state of the parent */ /* Bring the element to the state of the parent */
if ((gst_element_set_state (element, if ((gst_element_set_state (element,
GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE || GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE ||
@ -2262,6 +2287,10 @@ 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);
g_list_free (to_connect);
to_connect = NULL;
remove_error_filter (dbin, element); remove_error_filter (dbin, element);
/* Remove all elements in this chain that were just added. No /* Remove all elements in this chain that were just added. No
@ -2334,8 +2363,22 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
SUBTITLE_UNLOCK (dbin); SUBTITLE_UNLOCK (dbin);
} }
/* link this element further */ if (to_connect) {
connect_element (dbin, delem, chain); GList *l;
for (l = to_connect; l; l = g_list_next (l)) {
GstPad *opad = GST_PAD_CAST (l->data);
GstCaps *ocaps;
ocaps = get_pad_caps (opad);
analyze_new_pad (dbin, delem->element, opad, ocaps, chain);
if (ocaps)
gst_caps_unref (ocaps);
gst_object_unref (opad);
}
g_list_free (to_connect);
to_connect = NULL;
}
res = TRUE; res = TRUE;
break; break;
@ -2366,13 +2409,14 @@ get_pad_caps (GstPad * pad)
return caps; return caps;
} }
static gboolean /* Returns a list of pads that can be connected to already and
* connects to pad-added and related signals */
static GList *
connect_element (GstDecodeBin * dbin, GstDecodeElement * delem, connect_element (GstDecodeBin * dbin, GstDecodeElement * delem,
GstDecodeChain * chain) GstDecodeChain * chain)
{ {
GstElement *element = delem->element; GstElement *element = delem->element;
GList *pads; GList *pads;
gboolean res = TRUE;
gboolean dynamic = FALSE; gboolean dynamic = FALSE;
GList *to_connect = NULL; GList *to_connect = NULL;
@ -2450,21 +2494,9 @@ connect_element (GstDecodeBin * dbin, GstDecodeElement * delem,
G_CALLBACK (no_more_pads_cb), chain); G_CALLBACK (no_more_pads_cb), chain);
} }
/* 3. for every available pad, connect it */ /* 3. return all pads that can be connected to already */
for (pads = to_connect; pads; pads = g_list_next (pads)) {
GstPad *pad = GST_PAD_CAST (pads->data);
GstCaps *caps;
caps = get_pad_caps (pad); return to_connect;
analyze_new_pad (dbin, element, pad, caps, chain);
if (caps)
gst_caps_unref (caps);
gst_object_unref (pad);
}
g_list_free (to_connect);
return res;
} }
/* expose_pad: /* expose_pad: