mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 11:41:09 +00:00
decodebin3: try candidate decoders to select the first one that works
Send sticky events to the new created decoder after it switches to PAUSED state. It it fails, just skip this decoder and try the next one until finding one that works. Otherwise remove this failing stream after trying all decoders and no one can work. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4677>
This commit is contained in:
parent
6fc6e934aa
commit
887ae4d9e0
1 changed files with 55 additions and 33 deletions
|
@ -2938,35 +2938,29 @@ reconfigure_output_stream (DecodebinOutputStream * output,
|
||||||
GList *factories, *next_factory;
|
GList *factories, *next_factory;
|
||||||
|
|
||||||
factories = next_factory = create_decoder_factory_list (dbin, new_caps);
|
factories = next_factory = create_decoder_factory_list (dbin, new_caps);
|
||||||
while (!output->decoder) {
|
if (!next_factory) {
|
||||||
|
GST_DEBUG ("Could not find an element for caps %" GST_PTR_FORMAT,
|
||||||
|
new_caps);
|
||||||
|
g_assert (output->decoder == NULL);
|
||||||
|
ret = FALSE;
|
||||||
|
goto missing_decoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (next_factory) {
|
||||||
gboolean decoder_failed = FALSE;
|
gboolean decoder_failed = FALSE;
|
||||||
|
|
||||||
/* If we don't have a decoder yet, instantiate one */
|
/* If we don't have a decoder yet, instantiate one */
|
||||||
if (next_factory) {
|
output->decoder = gst_element_factory_create ((GstElementFactory *)
|
||||||
output->decoder = gst_element_factory_create ((GstElementFactory *)
|
next_factory->data, NULL);
|
||||||
next_factory->data, NULL);
|
GST_DEBUG ("Trying decoder %" GST_PTR_FORMAT, output->decoder);
|
||||||
GST_DEBUG ("Created decoder %" GST_PTR_FORMAT, output->decoder);
|
|
||||||
} else {
|
|
||||||
GST_DEBUG ("Could not find an element for caps %" GST_PTR_FORMAT,
|
|
||||||
new_caps);
|
|
||||||
g_assert (output->decoder == NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output->decoder == NULL) {
|
if (output->decoder == NULL)
|
||||||
GstCaps *caps;
|
goto try_next;
|
||||||
|
|
||||||
/* FIXME : Should we be smarter if there's a missing decoder ?
|
|
||||||
* Should we deactivate that stream ? */
|
|
||||||
caps = gst_stream_get_caps (slot->active_stream);
|
|
||||||
*msg = gst_missing_decoder_message_new (GST_ELEMENT_CAST (dbin), caps);
|
|
||||||
gst_caps_unref (caps);
|
|
||||||
ret = FALSE;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (!gst_bin_add ((GstBin *) dbin, output->decoder)) {
|
if (!gst_bin_add ((GstBin *) dbin, output->decoder)) {
|
||||||
GST_ERROR_OBJECT (dbin, "could not add decoder to pipeline");
|
GST_WARNING_OBJECT (dbin, "could not add decoder '%s' to pipeline",
|
||||||
ret = FALSE;
|
GST_ELEMENT_NAME (output->decoder));
|
||||||
goto cleanup;
|
goto try_next;
|
||||||
}
|
}
|
||||||
output->decoder_sink =
|
output->decoder_sink =
|
||||||
gst_element_get_static_pad (output->decoder, "sink");
|
gst_element_get_static_pad (output->decoder, "sink");
|
||||||
|
@ -2977,27 +2971,29 @@ reconfigure_output_stream (DecodebinOutputStream * output,
|
||||||
gst_pad_add_probe (slot->src_pad, GST_PAD_PROBE_TYPE_BUFFER,
|
gst_pad_add_probe (slot->src_pad, GST_PAD_PROBE_TYPE_BUFFER,
|
||||||
(GstPadProbeCallback) keyframe_waiter_probe, output, NULL);
|
(GstPadProbeCallback) keyframe_waiter_probe, output, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gst_pad_link_full (slot->src_pad, output->decoder_sink,
|
if (gst_pad_link_full (slot->src_pad, output->decoder_sink,
|
||||||
GST_PAD_LINK_CHECK_NOTHING) != GST_PAD_LINK_OK) {
|
GST_PAD_LINK_CHECK_NOTHING) != GST_PAD_LINK_OK) {
|
||||||
GST_ERROR_OBJECT (dbin, "could not link to %s:%s",
|
GST_WARNING_OBJECT (dbin, "could not link to %s:%s",
|
||||||
GST_DEBUG_PAD_NAME (output->decoder_sink));
|
GST_DEBUG_PAD_NAME (output->decoder_sink));
|
||||||
ret = FALSE;
|
goto try_next;
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gst_element_set_state (output->decoder,
|
if (gst_element_set_state (output->decoder,
|
||||||
GST_STATE_READY) == GST_STATE_CHANGE_FAILURE) {
|
GST_STATE_READY) == GST_STATE_CHANGE_FAILURE) {
|
||||||
GST_DEBUG_OBJECT (dbin,
|
GST_WARNING_OBJECT (dbin,
|
||||||
"Decoder '%s' failed to reach READY state, trying the next type",
|
"Decoder '%s' failed to reach READY state",
|
||||||
GST_ELEMENT_NAME (output->decoder));
|
GST_ELEMENT_NAME (output->decoder));
|
||||||
decoder_failed = TRUE;
|
decoder_failed = TRUE;
|
||||||
remove_decoder_link (output, slot);
|
goto try_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gst_pad_query_accept_caps (output->decoder_sink, new_caps)) {
|
if (!gst_pad_query_accept_caps (output->decoder_sink, new_caps)) {
|
||||||
GST_DEBUG_OBJECT (dbin,
|
GST_DEBUG_OBJECT (dbin,
|
||||||
"Decoder '%s' did not accept the caps, trying the next type",
|
"Decoder '%s' did not accept the caps, trying the next type",
|
||||||
GST_ELEMENT_NAME (output->decoder));
|
GST_ELEMENT_NAME (output->decoder));
|
||||||
decoder_failed = TRUE;
|
decoder_failed = TRUE;
|
||||||
remove_decoder_link (output, slot);
|
goto try_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First lock element's sinkpad stream lock so no data reaches
|
/* First lock element's sinkpad stream lock so no data reaches
|
||||||
|
@ -3013,13 +3009,32 @@ reconfigure_output_stream (DecodebinOutputStream * output,
|
||||||
GST_WARNING_OBJECT (dbin,
|
GST_WARNING_OBJECT (dbin,
|
||||||
"Decoder '%s' failed to reach PAUSED state",
|
"Decoder '%s' failed to reach PAUSED state",
|
||||||
GST_ELEMENT_NAME (output->decoder));
|
GST_ELEMENT_NAME (output->decoder));
|
||||||
remove_decoder_link (output, slot);
|
decoder_failed = TRUE;
|
||||||
|
goto try_next;
|
||||||
} else {
|
} else {
|
||||||
/* Everything went well */
|
/* Everything went well */
|
||||||
GST_PAD_STREAM_UNLOCK (output->decoder_sink);
|
GST_PAD_STREAM_UNLOCK (output->decoder_sink);
|
||||||
|
output->linked = TRUE;
|
||||||
|
GST_DEBUG ("created decoder %" GST_PTR_FORMAT, output->decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
next_factory = next_factory->next;
|
break;
|
||||||
|
|
||||||
|
try_next:
|
||||||
|
{
|
||||||
|
if (decoder_failed)
|
||||||
|
remove_decoder_link (output, slot);
|
||||||
|
|
||||||
|
if (!next_factory->next) {
|
||||||
|
ret = FALSE;
|
||||||
|
if (!decoder_failed)
|
||||||
|
goto cleanup;
|
||||||
|
if (output->decoder == NULL)
|
||||||
|
goto missing_decoder;
|
||||||
|
} else {
|
||||||
|
next_factory = next_factory->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
gst_plugin_feature_list_free (factories);
|
gst_plugin_feature_list_free (factories);
|
||||||
} else {
|
} else {
|
||||||
|
@ -3028,7 +3043,6 @@ reconfigure_output_stream (DecodebinOutputStream * output,
|
||||||
}
|
}
|
||||||
gst_caps_unref (new_caps);
|
gst_caps_unref (new_caps);
|
||||||
|
|
||||||
output->linked = TRUE;
|
|
||||||
if (!decode_pad_set_target ((GstGhostPad *) output->src_pad,
|
if (!decode_pad_set_target ((GstGhostPad *) output->src_pad,
|
||||||
output->decoder_src)) {
|
output->decoder_src)) {
|
||||||
GST_ERROR_OBJECT (dbin, "Could not expose decoder pad");
|
GST_ERROR_OBJECT (dbin, "Could not expose decoder pad");
|
||||||
|
@ -3060,6 +3074,14 @@ reconfigure_output_stream (DecodebinOutputStream * output,
|
||||||
output->slot = slot;
|
output->slot = slot;
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
missing_decoder:
|
||||||
|
{
|
||||||
|
GstCaps *caps;
|
||||||
|
caps = gst_stream_get_caps (slot->active_stream);
|
||||||
|
*msg = gst_missing_decoder_message_new (GST_ELEMENT_CAST (dbin), caps);
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
{
|
{
|
||||||
GST_DEBUG_OBJECT (dbin, "Cleanup");
|
GST_DEBUG_OBJECT (dbin, "Cleanup");
|
||||||
|
|
Loading…
Reference in a new issue