diff options
author | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2009-11-06 12:51:22 +0100 |
---|---|---|
committer | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2009-11-12 13:20:41 +0100 |
commit | c5d26b23c7a6351c486434bb269d1c9b14c41481 (patch) | |
tree | 6e236ad2e7a59da3223d302b854f83be45ad049e | |
parent | 16073d1eb7bbd2fa5818d39095e6e6b13eb64771 (diff) |
playbin2: Handle external subtitles better
First of all, make sure that suburidecodebin never
errors out because of not-linked in case external subtitles
are used but then subtitles are disabled.
And then make sure that external subtitles always start from
the correct position and are not racing until EOS if they
get unselected and selected again.
-rw-r--r-- | gst/playback/gstplaybin2.c | 132 |
1 files changed, 131 insertions, 1 deletions
diff --git a/gst/playback/gstplaybin2.c b/gst/playback/gstplaybin2.c index c2dfeeb9b..273aacfc5 100644 --- a/gst/playback/gstplaybin2.c +++ b/gst/playback/gstplaybin2.c @@ -526,6 +526,11 @@ static void no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group); static void pad_removed_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group); +static void gst_play_bin_suburidecodebin_block (GstElement * suburidecodebin, + gboolean block); +static void gst_play_bin_suburidecodebin_seek_to_start (GstElement * + suburidecodebin); + static GstElementClass *parent_class; static guint gst_play_bin_signals[LAST_SIGNAL] = { 0 }; @@ -1233,8 +1238,24 @@ gst_play_bin_set_suburi (GstPlayBin * playbin, const gchar * suburi) static void gst_play_bin_set_flags (GstPlayBin * playbin, GstPlayFlags flags) { + GstPlayFlags oldflags = gst_play_sink_get_flags (playbin->playsink); + GstSourceGroup *group = playbin->curr_group; + gboolean unblock = FALSE; + + if (group && group->suburidecodebin) { + if ((oldflags & GST_PLAY_FLAG_TEXT) && !(flags & GST_PLAY_FLAG_TEXT)) { + gst_play_bin_suburidecodebin_block (group->suburidecodebin, TRUE); + } else if (!(oldflags & GST_PLAY_FLAG_TEXT) && (flags & GST_PLAY_FLAG_TEXT)) { + gst_play_bin_suburidecodebin_seek_to_start (group->suburidecodebin); + unblock = TRUE; + } + } + gst_play_sink_set_flags (playbin->playsink, flags); gst_play_sink_reconfigure (playbin->playsink); + + if (unblock) + gst_play_bin_suburidecodebin_block (group->suburidecodebin, FALSE); } static GstPlayFlags @@ -1499,6 +1520,72 @@ no_channels: } } +static void +_suburidecodebin_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data) +{ + GST_DEBUG_OBJECT (pad, "Pad blocked: %d", blocked); +} + +static void +gst_play_bin_suburidecodebin_seek_to_start (GstElement * suburidecodebin) +{ + GstIterator *it = gst_element_iterate_src_pads (suburidecodebin); + GstPad *sinkpad; + + if (it && gst_iterator_next (it, (gpointer) & sinkpad) == GST_ITERATOR_OK + && sinkpad) { + GstEvent *event; + + event = + gst_event_new_seek (1.0, GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, -1); + if (!gst_pad_send_event (sinkpad, event)) { + event = + gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, -1); + if (!gst_pad_send_event (sinkpad, event)) + GST_DEBUG_OBJECT (suburidecodebin, "Seeking to the beginning failed!"); + } + } + + if (it) + gst_iterator_free (it); +} + +static void +gst_play_bin_suburidecodebin_block (GstElement * suburidecodebin, + gboolean block) +{ + GstIterator *it = gst_element_iterate_src_pads (suburidecodebin); + gboolean done = FALSE; + + GST_DEBUG_OBJECT (suburidecodebin, "Blocking suburidecodebin: %d", block); + + if (!it) + return; + while (!done) { + GstPad *sinkpad; + + switch (gst_iterator_next (it, (gpointer) & sinkpad)) { + case GST_ITERATOR_OK: + gst_pad_set_blocked_async (sinkpad, block, _suburidecodebin_blocked_cb, + NULL); + gst_object_unref (sinkpad); + break; + case GST_ITERATOR_DONE: + done = TRUE; + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (it); + break; + case GST_ITERATOR_ERROR: + done = TRUE; + break; + } + } + gst_iterator_free (it); +} + static gboolean gst_play_bin_set_current_text_stream (GstPlayBin * playbin, gint stream) { @@ -1531,7 +1618,42 @@ gst_play_bin_set_current_text_stream (GstPlayBin * playbin, gint stream) g_object_get (selector, "active-pad", &old_sinkpad, NULL); if (old_sinkpad != sinkpad) { - GstPad *src, *peer; + gboolean need_unblock, need_block, need_seek; + GstPad *src, *peer = NULL, *oldpeer = NULL; + GstElement *parent_element = NULL, *old_parent_element = NULL; + + /* Now check if we need to seek the suburidecodebin to the beginning + * or if we need to block all suburidecodebin sinkpads or if we need + * to unblock all suburidecodebin sinkpads + */ + if (sinkpad) + peer = gst_pad_get_peer (sinkpad); + if (old_sinkpad) + oldpeer = gst_pad_get_peer (old_sinkpad); + + if (peer) + parent_element = gst_pad_get_parent_element (peer); + if (oldpeer) + old_parent_element = gst_pad_get_parent_element (oldpeer); + + need_block = (old_parent_element == group->suburidecodebin + && parent_element != old_parent_element); + need_unblock = (parent_element == group->suburidecodebin + && parent_element != old_parent_element); + need_seek = (parent_element == group->suburidecodebin); + + if (peer) + gst_object_unref (peer); + if (oldpeer) + gst_object_unref (oldpeer); + if (parent_element) + gst_object_unref (parent_element); + if (old_parent_element) + gst_object_unref (old_parent_element); + + /* Block all suburidecodebin sinkpads */ + if (need_block) + gst_play_bin_suburidecodebin_block (group->suburidecodebin, TRUE); /* activate the selected pad */ g_object_set (selector, "active-pad", sinkpad, NULL); @@ -1551,6 +1673,14 @@ gst_play_bin_set_current_text_stream (GstPlayBin * playbin, gint stream) gst_object_unref (peer); } gst_object_unref (src); + + /* Unblock pads if necessary */ + if (need_unblock) + gst_play_bin_suburidecodebin_block (group->suburidecodebin, FALSE); + + /* seek to the beginning */ + if (need_seek) + gst_play_bin_suburidecodebin_seek_to_start (group->suburidecodebin); } gst_object_unref (selector); |