summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian.droege@collabora.co.uk>2009-11-06 12:51:22 +0100
committerSebastian Dröge <sebastian.droege@collabora.co.uk>2009-11-12 13:20:41 +0100
commitc5d26b23c7a6351c486434bb269d1c9b14c41481 (patch)
tree6e236ad2e7a59da3223d302b854f83be45ad049e
parent16073d1eb7bbd2fa5818d39095e6e6b13eb64771 (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.c132
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);