mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-30 12:10:37 +00:00
playbin2: handle missing input-selector
Gracefully degrade and disable stream selection when input-selector is missing.
This commit is contained in:
parent
ee03bf5379
commit
f25e4e4743
1 changed files with 82 additions and 65 deletions
|
@ -369,6 +369,10 @@ struct _GstPlayBin
|
||||||
gint shutdown;
|
gint shutdown;
|
||||||
|
|
||||||
GValueArray *elements; /* factories we can use for selecting elements */
|
GValueArray *elements; /* factories we can use for selecting elements */
|
||||||
|
|
||||||
|
gboolean have_selector; /* set to FALSE when we fail to create an
|
||||||
|
* input-selector, so that we only post a
|
||||||
|
* warning once */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstPlayBinClass
|
struct _GstPlayBinClass
|
||||||
|
@ -989,6 +993,9 @@ gst_play_bin_init (GstPlayBin * playbin)
|
||||||
playbin->lock = g_mutex_new ();
|
playbin->lock = g_mutex_new ();
|
||||||
playbin->dyn_lock = g_mutex_new ();
|
playbin->dyn_lock = g_mutex_new ();
|
||||||
|
|
||||||
|
/* assume we can create a selector */
|
||||||
|
playbin->have_selector = TRUE;
|
||||||
|
|
||||||
/* init groups */
|
/* init groups */
|
||||||
playbin->curr_group = &playbin->groups[0];
|
playbin->curr_group = &playbin->groups[0];
|
||||||
playbin->next_group = &playbin->groups[1];
|
playbin->next_group = &playbin->groups[1];
|
||||||
|
@ -1736,22 +1743,37 @@ pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
|
||||||
goto unknown_type;
|
goto unknown_type;
|
||||||
|
|
||||||
GST_SOURCE_GROUP_LOCK (group);
|
GST_SOURCE_GROUP_LOCK (group);
|
||||||
if (select->selector == NULL) {
|
if (select->selector == NULL && playbin->have_selector) {
|
||||||
/* no selector, create one */
|
/* no selector, create one */
|
||||||
GST_DEBUG_OBJECT (playbin, "creating new selector");
|
GST_DEBUG_OBJECT (playbin, "creating new selector");
|
||||||
select->selector = gst_element_factory_make ("input-selector", NULL);
|
select->selector = gst_element_factory_make ("input-selector", NULL);
|
||||||
if (select->selector == NULL)
|
if (select->selector == NULL) {
|
||||||
goto no_selector;
|
/* post the missing selector message only once */
|
||||||
|
playbin->have_selector = FALSE;
|
||||||
|
gst_element_post_message (GST_ELEMENT_CAST (playbin),
|
||||||
|
gst_missing_element_message_new (GST_ELEMENT_CAST (playbin),
|
||||||
|
"input-selector"));
|
||||||
|
GST_ELEMENT_WARNING (playbin, CORE, MISSING_PLUGIN,
|
||||||
|
(_("Missing element '%s' - check your GStreamer installation."),
|
||||||
|
"input-selector"), (NULL));
|
||||||
|
} else {
|
||||||
g_signal_connect (select->selector, "notify::active-pad",
|
g_signal_connect (select->selector, "notify::active-pad",
|
||||||
G_CALLBACK (selector_active_pad_changed), playbin);
|
G_CALLBACK (selector_active_pad_changed), playbin);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (playbin, "adding new selector %p", select->selector);
|
GST_DEBUG_OBJECT (playbin, "adding new selector %p", select->selector);
|
||||||
gst_bin_add (GST_BIN_CAST (playbin), select->selector);
|
gst_bin_add (GST_BIN_CAST (playbin), select->selector);
|
||||||
gst_element_set_state (select->selector, GST_STATE_PAUSED);
|
gst_element_set_state (select->selector, GST_STATE_PAUSED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* save source pad */
|
if (select->srcpad == NULL) {
|
||||||
|
if (select->selector) {
|
||||||
|
/* save source pad of the selector */
|
||||||
select->srcpad = gst_element_get_static_pad (select->selector, "src");
|
select->srcpad = gst_element_get_static_pad (select->selector, "src");
|
||||||
|
} else {
|
||||||
|
/* no selector, use the pad as the source pad then */
|
||||||
|
select->srcpad = gst_object_ref (pad);
|
||||||
|
}
|
||||||
/* block the selector srcpad. It's possible that multiple decodebins start
|
/* block the selector srcpad. It's possible that multiple decodebins start
|
||||||
* pushing data into the selectors before we have a chance to collect all
|
* pushing data into the selectors before we have a chance to collect all
|
||||||
* streams and connect the sinks, resulting in not-linked errors. After we
|
* streams and connect the sinks, resulting in not-linked errors. After we
|
||||||
|
@ -1760,6 +1782,7 @@ pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get sinkpad for the new stream */
|
/* get sinkpad for the new stream */
|
||||||
|
if (select->selector) {
|
||||||
if ((sinkpad = gst_element_get_request_pad (select->selector, "sink%d"))) {
|
if ((sinkpad = gst_element_get_request_pad (select->selector, "sink%d"))) {
|
||||||
GST_DEBUG_OBJECT (playbin, "got pad %s:%s from selector",
|
GST_DEBUG_OBJECT (playbin, "got pad %s:%s from selector",
|
||||||
GST_DEBUG_PAD_NAME (sinkpad));
|
GST_DEBUG_PAD_NAME (sinkpad));
|
||||||
|
@ -1779,9 +1802,15 @@ pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
|
||||||
g_object_set_data (G_OBJECT (pad), "playbin2.sinkpad", sinkpad);
|
g_object_set_data (G_OBJECT (pad), "playbin2.sinkpad", sinkpad);
|
||||||
|
|
||||||
changed = TRUE;
|
changed = TRUE;
|
||||||
}
|
|
||||||
GST_DEBUG_OBJECT (playbin, "linked pad %s:%s to selector %p",
|
GST_DEBUG_OBJECT (playbin, "linked pad %s:%s to selector %p",
|
||||||
GST_DEBUG_PAD_NAME (pad), select->selector);
|
GST_DEBUG_PAD_NAME (pad), select->selector);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* no selector, don't configure anything, we'll link the new pad directly to
|
||||||
|
* the sink. */
|
||||||
|
changed = FALSE;
|
||||||
|
sinkpad = NULL;
|
||||||
|
}
|
||||||
GST_SOURCE_GROUP_UNLOCK (group);
|
GST_SOURCE_GROUP_UNLOCK (group);
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
|
@ -1822,18 +1851,6 @@ unknown_type:
|
||||||
name, GST_DEBUG_PAD_NAME (pad));
|
name, GST_DEBUG_PAD_NAME (pad));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
no_selector:
|
|
||||||
{
|
|
||||||
GST_SOURCE_GROUP_UNLOCK (group);
|
|
||||||
|
|
||||||
gst_element_post_message (GST_ELEMENT_CAST (playbin),
|
|
||||||
gst_missing_element_message_new (GST_ELEMENT_CAST (playbin),
|
|
||||||
"input-selector"));
|
|
||||||
GST_ELEMENT_ERROR (playbin, CORE, MISSING_PLUGIN,
|
|
||||||
(_("Missing element '%s' - check your GStreamer installation."),
|
|
||||||
"input-selector"), (NULL));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
link_failed:
|
link_failed:
|
||||||
{
|
{
|
||||||
GST_ERROR_OBJECT (playbin,
|
GST_ERROR_OBJECT (playbin,
|
||||||
|
@ -1937,7 +1954,7 @@ no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group)
|
||||||
* created for it. If there is the media type, get a sinkpad from the sink
|
* created for it. If there is the media type, get a sinkpad from the sink
|
||||||
* and link it. We only do this if we have not yet requested the sinkpad
|
* and link it. We only do this if we have not yet requested the sinkpad
|
||||||
* before. */
|
* before. */
|
||||||
if (select->selector && select->sinkpad == NULL) {
|
if (select->srcpad && select->sinkpad == NULL) {
|
||||||
GST_DEBUG_OBJECT (playbin, "requesting new sink pad %d", select->type);
|
GST_DEBUG_OBJECT (playbin, "requesting new sink pad %d", select->type);
|
||||||
select->sinkpad =
|
select->sinkpad =
|
||||||
gst_play_sink_request_pad (playbin->playsink, select->type);
|
gst_play_sink_request_pad (playbin->playsink, select->type);
|
||||||
|
@ -1979,7 +1996,7 @@ no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group)
|
||||||
for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
|
for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
|
||||||
GstSourceSelect *select = &group->selector[i];
|
GstSourceSelect *select = &group->selector[i];
|
||||||
|
|
||||||
if (select->selector) {
|
if (select->srcpad) {
|
||||||
GST_DEBUG_OBJECT (playbin, "unblocking %" GST_PTR_FORMAT,
|
GST_DEBUG_OBJECT (playbin, "unblocking %" GST_PTR_FORMAT,
|
||||||
select->srcpad);
|
select->srcpad);
|
||||||
gst_pad_set_blocked_async (select->srcpad, FALSE, selector_blocked,
|
gst_pad_set_blocked_async (select->srcpad, FALSE, selector_blocked,
|
||||||
|
@ -2004,7 +2021,8 @@ shutdown:
|
||||||
for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
|
for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
|
||||||
GstSourceSelect *select = &group->selector[i];
|
GstSourceSelect *select = &group->selector[i];
|
||||||
|
|
||||||
if (select->selector && select->sinkpad == NULL) {
|
if (select->srcpad) {
|
||||||
|
if (select->sinkpad == NULL) {
|
||||||
GST_DEBUG_OBJECT (playbin, "requesting new flushing sink pad");
|
GST_DEBUG_OBJECT (playbin, "requesting new flushing sink pad");
|
||||||
select->sinkpad =
|
select->sinkpad =
|
||||||
gst_play_sink_request_pad (playbin->playsink,
|
gst_play_sink_request_pad (playbin->playsink,
|
||||||
|
@ -2012,7 +2030,6 @@ shutdown:
|
||||||
res = gst_pad_link (select->srcpad, select->sinkpad);
|
res = gst_pad_link (select->srcpad, select->sinkpad);
|
||||||
GST_DEBUG_OBJECT (playbin, "linked flushing, result: %d", res);
|
GST_DEBUG_OBJECT (playbin, "linked flushing, result: %d", res);
|
||||||
}
|
}
|
||||||
if (select->srcpad) {
|
|
||||||
GST_DEBUG_OBJECT (playbin, "unblocking %" GST_PTR_FORMAT,
|
GST_DEBUG_OBJECT (playbin, "unblocking %" GST_PTR_FORMAT,
|
||||||
select->srcpad);
|
select->srcpad);
|
||||||
gst_pad_set_blocked_async (select->srcpad, FALSE, selector_blocked,
|
gst_pad_set_blocked_async (select->srcpad, FALSE, selector_blocked,
|
||||||
|
@ -2350,11 +2367,9 @@ deactivate_group (GstPlayBin * playbin, GstSourceGroup * group)
|
||||||
for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
|
for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
|
||||||
GstSourceSelect *select = &group->selector[i];
|
GstSourceSelect *select = &group->selector[i];
|
||||||
|
|
||||||
if (!select->selector)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (playbin, "unlinking selector %s", select->media);
|
GST_DEBUG_OBJECT (playbin, "unlinking selector %s", select->media);
|
||||||
|
|
||||||
|
if (select->srcpad) {
|
||||||
if (select->sinkpad) {
|
if (select->sinkpad) {
|
||||||
GST_LOG_OBJECT (playbin, "unlinking from sink");
|
GST_LOG_OBJECT (playbin, "unlinking from sink");
|
||||||
gst_pad_unlink (select->srcpad, select->sinkpad);
|
gst_pad_unlink (select->srcpad, select->sinkpad);
|
||||||
|
@ -2364,14 +2379,16 @@ deactivate_group (GstPlayBin * playbin, GstSourceGroup * group)
|
||||||
gst_play_sink_release_pad (playbin->playsink, select->sinkpad);
|
gst_play_sink_release_pad (playbin->playsink, select->sinkpad);
|
||||||
select->sinkpad = NULL;
|
select->sinkpad = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_object_unref (select->srcpad);
|
gst_object_unref (select->srcpad);
|
||||||
select->srcpad = NULL;
|
select->srcpad = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (select->selector) {
|
||||||
gst_element_set_state (select->selector, GST_STATE_NULL);
|
gst_element_set_state (select->selector, GST_STATE_NULL);
|
||||||
gst_bin_remove (GST_BIN_CAST (playbin), select->selector);
|
gst_bin_remove (GST_BIN_CAST (playbin), select->selector);
|
||||||
select->selector = NULL;
|
select->selector = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/* we still have the decodebins added to the playbin2 but we can't remove them
|
/* we still have the decodebins added to the playbin2 but we can't remove them
|
||||||
* yet or change their state because this function might be called from the
|
* yet or change their state because this function might be called from the
|
||||||
* streaming threads, instead block the state so that state changes on the
|
* streaming threads, instead block the state so that state changes on the
|
||||||
|
|
Loading…
Reference in a new issue