playbin2: Send flush events when changing subtitle tracks and use new input-selector...
authorAndre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk>
Thu, 24 May 2012 14:02:59 +0000 (11:02 -0300)
committerThiago Santos <thiago.sousa.santos@collabora.com>
Wed, 6 Jun 2012 19:31:09 +0000 (16:31 -0300)
For audio/video we should flush too for fastest stream switches but this
currently isn't possible because the flushes would need to go to the sink,
which then causes state changes and causes all timing information to be
changed.

Should work out of the box in 0.11 with the flush-stop that doesn't reset
the times.

Conflicts:

gst/playback/gstplaybin2.c
gst/playback/gstplaysink.c
gst/playback/gstsubtitleoverlay.c

gst/playback/gstplaybin2.c
gst/playback/gstplaysink.c
gst/playback/gstsubtitleoverlay.c

index 32b877c..74b53f7 100644 (file)
@@ -410,8 +410,14 @@ struct _GstPlayBin
                                  * input-selector, so that we only post a
                                  * warning once */
 
-  gboolean pending_flush_finish;        /* whether we are pending to send a custom
-                                         * subtitleoverlay-flush-subtitle-finish event
+  gboolean video_pending_flush_finish;  /* whether we are pending to send a custom
+                                         * custom-video-flush-finish event
+                                         * on pad activation */
+  gboolean audio_pending_flush_finish;  /* whether we are pending to send a custom
+                                         * custom-audio-flush-finish event
+                                         * on pad activation */
+  gboolean text_pending_flush_finish;   /* whether we are pending to send a custom
+                                         * custom-subtitle-flush-finish event
                                          * on pad activation */
 
   GstElement *audio_sink;       /* configured audio sink, or NULL      */
@@ -1668,6 +1674,28 @@ get_current_stream_number (GstPlayBin * playbin, GPtrArray * channels)
 }
 
 static gboolean
+gst_playbin2_send_custom_event (GstObject * selector, const gchar * event_name)
+{
+  GstPad *src;
+  GstPad *peer;
+  GstStructure *s;
+  GstEvent *event;
+  gboolean ret = FALSE;
+
+  src = gst_element_get_static_pad (GST_ELEMENT_CAST (selector), "src");
+  peer = gst_pad_get_peer (src);
+  if (peer) {
+    s = gst_structure_new_empty (event_name);
+    event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, s);
+    gst_pad_send_event (peer, event);
+    gst_object_unref (peer);
+    ret = TRUE;
+  }
+  gst_object_unref (src);
+  return ret;
+}
+
+static gboolean
 gst_play_bin_set_current_video_stream (GstPlayBin * playbin, gint stream)
 {
   GstSourceGroup *group;
@@ -1698,8 +1726,19 @@ gst_play_bin_set_current_video_stream (GstPlayBin * playbin, gint stream)
     GstObject *selector;
 
     if ((selector = gst_pad_get_parent (sinkpad))) {
-      /* activate the selected pad */
-      g_object_set (selector, "active-pad", sinkpad, NULL);
+      GstPad *old_sinkpad;
+
+      g_object_get (selector, "active-pad", &old_sinkpad, NULL);
+
+      if (old_sinkpad != sinkpad) {
+        if (gst_playbin2_send_custom_event (selector,
+                "playsink-custom-video-flush"))
+          playbin->video_pending_flush_finish = TRUE;
+
+        /* activate the selected pad */
+        g_object_set (selector, "active-pad", sinkpad, NULL);
+      }
+
       gst_object_unref (selector);
     }
     gst_object_unref (sinkpad);
@@ -1745,8 +1784,18 @@ gst_play_bin_set_current_audio_stream (GstPlayBin * playbin, gint stream)
     GstObject *selector;
 
     if ((selector = gst_pad_get_parent (sinkpad))) {
-      /* activate the selected pad */
-      g_object_set (selector, "active-pad", sinkpad, NULL);
+      GstPad *old_sinkpad;
+
+      g_object_get (selector, "active-pad", &old_sinkpad, NULL);
+
+      if (old_sinkpad != sinkpad) {
+        if (gst_playbin2_send_custom_event (selector,
+                "playsink-custom-audio-flush"))
+          playbin->audio_pending_flush_finish = TRUE;
+
+        /* activate the selected pad */
+        g_object_set (selector, "active-pad", sinkpad, NULL);
+      }
       gst_object_unref (selector);
     }
     gst_object_unref (sinkpad);
@@ -1889,7 +1938,7 @@ gst_play_bin_set_current_text_stream (GstPlayBin * playbin, gint stream)
 
       if (old_sinkpad != sinkpad) {
         gboolean need_unblock, need_block, need_seek;
-        GstPad *src, *peer = NULL, *oldpeer = NULL;
+        GstPad *peer = NULL, *oldpeer = NULL;
         GstElement *parent_element = NULL, *old_parent_element = NULL;
 
         /* Now check if we need to seek the suburidecodebin to the beginning
@@ -1926,22 +1975,9 @@ gst_play_bin_set_current_text_stream (GstPlayBin * playbin, gint stream)
           gst_play_bin_suburidecodebin_block (group, group->suburidecodebin,
               TRUE);
 
-        src = gst_element_get_static_pad (GST_ELEMENT_CAST (selector), "src");
-        peer = gst_pad_get_peer (src);
-        if (peer) {
-          GstStructure *s;
-          GstEvent *event;
-          /* Flush the subtitle renderer to remove any
-           * currently displayed subtitles. This event will
-           * never travel outside subtitleoverlay!
-           */
-          s = gst_structure_new_empty ("subtitleoverlay-flush-subtitle");
-          event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, s);
-          gst_pad_send_event (peer, event);
-          playbin->pending_flush_finish = TRUE;
-          gst_object_unref (peer);
-        }
-        gst_object_unref (src);
+        if (gst_playbin2_send_custom_event (selector,
+                "playsink-custom-subtitle-flush"))
+          playbin->text_pending_flush_finish = TRUE;
 
         /* activate the selected pad */
         g_object_set (selector, "active-pad", sinkpad, NULL);
@@ -2568,38 +2604,39 @@ selector_active_pad_changed (GObject * selector, GParamSpec * pspec,
       property = "current-video";
       playbin->current_video = get_current_stream_number (playbin,
           group->video_channels);
+
+      if (playbin->video_pending_flush_finish) {
+        playbin->video_pending_flush_finish = FALSE;
+        GST_PLAY_BIN_UNLOCK (playbin);
+        gst_playbin2_send_custom_event (GST_OBJECT (selector),
+            "playsink-custom-video-flush-finish");
+        goto notify;
+      }
       break;
     case GST_PLAY_SINK_TYPE_AUDIO:
     case GST_PLAY_SINK_TYPE_AUDIO_RAW:
       property = "current-audio";
       playbin->current_audio = get_current_stream_number (playbin,
           group->audio_channels);
+
+      if (playbin->audio_pending_flush_finish) {
+        playbin->audio_pending_flush_finish = FALSE;
+        GST_PLAY_BIN_UNLOCK (playbin);
+        gst_playbin2_send_custom_event (GST_OBJECT (selector),
+            "playsink-custom-audio-flush-finish");
+        goto notify;
+      }
       break;
     case GST_PLAY_SINK_TYPE_TEXT:
       property = "current-text";
       playbin->current_text = get_current_stream_number (playbin,
           group->text_channels);
 
-      if (playbin->pending_flush_finish) {
-        GstEvent *ev;
-        GstStructure *s;
-        GstPad *src, *peer;
-
-        playbin->pending_flush_finish = FALSE;
+      if (playbin->text_pending_flush_finish) {
+        playbin->text_pending_flush_finish = FALSE;
         GST_PLAY_BIN_UNLOCK (playbin);
-
-        /* Flush the subtitle renderer to remove any
-         * currently displayed subtitles. This event will
-         * never travel outside subtitleoverlay!
-         */
-        src = gst_element_get_static_pad (GST_ELEMENT_CAST (selector), "src");
-        peer = gst_pad_get_peer (src);
-        s = gst_structure_new_empty ("subtitleoverlay-flush-subtitle-finish");
-        ev = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, s);
-        gst_pad_send_event (peer, ev);
-        gst_object_unref (peer);
-        gst_object_unref (src);
-
+        gst_playbin2_send_custom_event (GST_OBJECT (selector),
+            "playsink-custom-subtitle-flush-finish");
         goto notify;
       }
       break;
@@ -2796,7 +2833,12 @@ pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
           (_("Missing element '%s' - check your GStreamer installation."),
               "input-selector"), (NULL));
     } else {
-      g_object_set (select->selector, "sync-streams", TRUE, NULL);
+      /* sync-mode=1, use clock */
+      if (select->type == GST_PLAY_SINK_TYPE_TEXT)
+        g_object_set (select->selector, "sync-streams", TRUE,
+            "sync-mode", 1, "cache-buffers", TRUE, NULL);
+      else
+        g_object_set (select->selector, "sync-streams", TRUE, NULL);
 
       g_signal_connect (select->selector, "notify::active-pad",
           G_CALLBACK (selector_active_pad_changed), playbin);
index 583b6fa..63b482e 100644 (file)
@@ -257,10 +257,24 @@ struct _GstPlaySink
   GList *colorbalance_channels; /* CONTRAST, BRIGHTNESS, HUE, SATURATION */
   gint colorbalance_values[4];
 
+  /* sending audio/video flushes break stream changes when the pipeline
+   * is paused and played again in 0.10 */
+#if 0
+  GstSegment video_segment;
+  gboolean video_custom_flush_finished;
+  gboolean video_ignore_wrong_state;
+  gboolean video_pending_flush;
+
+  GstSegment audio_segment;
+  gboolean audio_custom_flush_finished;
+  gboolean audio_ignore_wrong_state;
+  gboolean audio_pending_flush;
+#endif
+
   GstSegment text_segment;
-  gboolean custom_flush_finished;
-  gboolean ignore_wrong_state;
-  gboolean pending_flush_stop;
+  gboolean text_custom_flush_finished;
+  gboolean text_ignore_wrong_state;
+  gboolean text_pending_flush;
 };
 
 struct _GstPlaySinkClass
@@ -344,6 +358,21 @@ static GstStateChangeReturn gst_play_sink_change_state (GstElement * element,
 
 static void gst_play_sink_handle_message (GstBin * bin, GstMessage * message);
 
+/* sending audio/video flushes break stream changes when the pipeline
+ * is paused and played again in 0.10 */
+#if 0
+static gboolean gst_play_sink_video_sink_event (GstPad * pad, GstEvent * event);
+static GstFlowReturn gst_play_sink_video_sink_chain (GstPad * pad,
+    GstBuffer * buffer);
+static gboolean gst_play_sink_audio_sink_event (GstPad * pad, GstEvent * event);
+static GstFlowReturn gst_play_sink_audio_sink_chain (GstPad * pad,
+    GstBuffer * buffer);
+#endif
+static gboolean gst_play_sink_text_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
+static GstFlowReturn gst_play_sink_text_sink_chain (GstPad * pad,
+    GstObject * parent, GstBuffer * buffer);
+
 static void notify_volume_cb (GObject * object, GParamSpec * pspec,
     GstPlaySink * playsink);
 static void notify_mute_cb (GObject * object, GParamSpec * pspec,
@@ -1690,8 +1719,17 @@ gen_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async)
 
   pad = gst_element_get_static_pad (head, "sink");
   chain->sinkpad = gst_ghost_pad_new ("sink", pad);
-  gst_object_unref (pad);
 
+  /* sending audio/video flushes break stream changes when the pipeline
+   * is paused and played again in 0.10 */
+#if 0
+  gst_pad_set_event_function (chain->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_play_sink_video_sink_event));
+  gst_pad_set_chain_function (chain->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_play_sink_video_sink_chain));
+#endif
+
+  gst_object_unref (pad);
   gst_element_add_pad (chain->chain.bin, chain->sinkpad);
 
   return chain;
@@ -1858,37 +1896,52 @@ _generate_update_newsegment_event (GstPad * pad, GstSegment * segment,
 }
 
 static gboolean
-gst_play_sink_text_sink_event (GstPad * pad, GstObject * parent,
-    GstEvent * event)
+gst_play_sink_sink_event (GstPad * pad, GstObject * parent, GstEvent * event,
+    const gchar * sink_type,
+    gboolean * sink_ignore_wrong_state,
+    gboolean * sink_custom_flush_finished,
+    gboolean * sink_pending_flush, GstSegment * sink_segment)
 {
   GstPlaySink *playsink = GST_PLAY_SINK_CAST (gst_object_get_parent (parent));
   gboolean ret;
   const GstStructure *structure = gst_event_get_structure (event);
 
-  if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM_OOB &&
-      structure
-      && strcmp (gst_structure_get_name (structure),
-          "subtitleoverlay-flush-subtitle") == 0) {
-    GST_DEBUG_OBJECT (pad,
-        "Custom subtitle flush event received, marking to flush text");
-    GST_PLAY_SINK_LOCK (playsink);
-    playsink->ignore_wrong_state = TRUE;
-    playsink->custom_flush_finished = FALSE;
-    GST_PLAY_SINK_UNLOCK (playsink);
-  } else if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM_OOB &&
-      structure && strcmp (gst_structure_get_name (structure),
-          "subtitleoverlay-flush-subtitle-finish") == 0) {
-    GST_DEBUG_OBJECT (pad, "Custom subtitle flush finish event received");
+  if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM_OOB && structure) {
+    gchar *custom_flush;
+    gchar *custom_flush_finish;
+
+    custom_flush = g_strdup_printf ("playsink-custom-%s-flush", sink_type);
+    custom_flush_finish =
+        g_strdup_printf ("playsink-custom-%s-flush-finish", sink_type);
+    if (strcmp (gst_structure_get_name (structure), custom_flush) == 0) {
+      GST_DEBUG_OBJECT (pad,
+          "Custom %s flush event received, marking to flush %s", sink_type,
+          sink_type);
+      GST_PLAY_SINK_LOCK (playsink);
+      *sink_ignore_wrong_state = TRUE;
+      *sink_custom_flush_finished = FALSE;
+      GST_PLAY_SINK_UNLOCK (playsink);
+    } else if (strcmp (gst_structure_get_name (structure),
+            custom_flush_finish) == 0) {
+      GST_DEBUG_OBJECT (pad, "Custom %s flush finish event received",
+          sink_type);
+      GST_PLAY_SINK_LOCK (playsink);
+      *sink_pending_flush = TRUE;
+      *sink_custom_flush_finished = TRUE;
+      GST_PLAY_SINK_UNLOCK (playsink);
+    }
+
+    g_free (custom_flush);
+    g_free (custom_flush_finish);
+  } else if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
     GST_PLAY_SINK_LOCK (playsink);
-    playsink->pending_flush_stop = TRUE;
-    playsink->custom_flush_finished = TRUE;
+    GST_DEBUG_OBJECT (pad, "Resetting %s segment because of flush-stop event",
+        sink_type);
+    gst_segment_init (sink_segment, GST_FORMAT_UNDEFINED);
     GST_PLAY_SINK_UNLOCK (playsink);
-  } else if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
-    GST_DEBUG_OBJECT (pad,
-        "Resetting text segment because of flush-stop event");
-    gst_segment_init (&playsink->text_segment, GST_FORMAT_UNDEFINED);
   }
 
+  GST_DEBUG_OBJECT (pad, "Forwarding event %" GST_PTR_FORMAT, event);
   ret = gst_proxy_pad_event_default (pad, parent, gst_event_ref (event));
 
   if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
@@ -1897,17 +1950,21 @@ gst_play_sink_text_sink_event (GstPad * pad, GstObject * parent,
     gst_event_parse_segment (event, &segment);
     GST_DEBUG_OBJECT (pad, "Segment event: %" GST_SEGMENT_FORMAT, segment);
 
-    if (playsink->text_segment.format != segment->format) {
-      GST_DEBUG_OBJECT (pad, "Text segment format changed: %s -> %s",
-          gst_format_get_name (playsink->text_segment.format),
+    GST_PLAY_SINK_LOCK (playsink);
+    if (sink_segment->format != segment->format) {
+      GST_DEBUG_OBJECT (pad, "%s segment format changed: %s -> %s",
+          sink_type,
+          gst_format_get_name (sink_segment->format),
           gst_format_get_name (segment->format));
+      gst_segment_init (sink_segment, segment->format);
     }
 
-    GST_DEBUG_OBJECT (pad, "Old text segment: %" GST_SEGMENT_FORMAT,
-        &playsink->text_segment);
-    gst_segment_copy_into (segment, &playsink->text_segment);
-    GST_DEBUG_OBJECT (pad, "New text segment: %" GST_SEGMENT_FORMAT,
-        &playsink->text_segment);
+    GST_DEBUG_OBJECT (pad, "Old %s segment: %" GST_SEGMENT_FORMAT,
+        sink_type, sink_segment);
+    gst_segment_copy_into (&playsink->text_segment, sink_segment);
+    GST_DEBUG_OBJECT (pad, "New %s segment: %" GST_SEGMENT_FORMAT,
+        sink_type, sink_segment);
+    GST_PLAY_SINK_UNLOCK (playsink);
   }
 
   gst_event_unref (event);
@@ -1916,8 +1973,11 @@ gst_play_sink_text_sink_event (GstPad * pad, GstObject * parent,
 }
 
 static GstFlowReturn
-gst_play_sink_text_sink_chain (GstPad * pad, GstObject * parent,
-    GstBuffer * buffer)
+gst_play_sink_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer,
+    const gchar * sink_type,
+    gboolean * sink_ignore_wrong_state,
+    gboolean * sink_custom_flush_finished,
+    gboolean * sink_pending_flush, GstSegment * sink_segment)
 {
   GstBin *tbin = GST_BIN_CAST (gst_pad_get_parent (pad));
   GstPlaySink *playsink = GST_PLAY_SINK_CAST (gst_pad_get_parent (tbin));
@@ -1925,13 +1985,29 @@ gst_play_sink_text_sink_chain (GstPad * pad, GstObject * parent,
 
   GST_PLAY_SINK_LOCK (playsink);
 
-  if (playsink->pending_flush_stop) {
-    GstSegment text_segment;
+  if (*sink_pending_flush) {
+    GstSegment segment_copy;
     GstEvent *event;
     GstStructure *structure;
 
-    /* it will be replaced in flush_stop */
-    text_segment = playsink->text_segment;
+    *sink_pending_flush = FALSE;
+
+    /* sink_segment will be updated in flush */
+    segment_copy = *sink_segment;
+
+    GST_PLAY_SINK_UNLOCK (playsink);
+
+    /* make the bin drop all cached data.
+     * This event will be dropped on the src pad, if any. */
+    event = gst_event_new_flush_start ();
+    structure = gst_event_writable_structure (event);
+    gst_structure_id_set (structure,
+        _playsink_reset_segment_event_marker_id, G_TYPE_BOOLEAN, TRUE, NULL);
+
+    GST_DEBUG_OBJECT (pad,
+        "Pushing %s flush-start event with reset segment marker set: %"
+        GST_PTR_FORMAT, sink_type, event);
+    gst_pad_send_event (pad, event);
 
     /* make queue drop all cached data.
      * This event will be dropped on the src pad. */
@@ -1941,35 +2017,35 @@ gst_play_sink_text_sink_chain (GstPad * pad, GstObject * parent,
         _playsink_reset_segment_event_marker_id, G_TYPE_BOOLEAN, TRUE, NULL);
 
     GST_DEBUG_OBJECT (pad,
-        "Pushing flush-stop event with reset segment marker set: %"
-        GST_PTR_FORMAT, event);
+        "Pushing %s flush-stop event with reset segment marker set: %"
+        GST_PTR_FORMAT, sink_type, event);
     gst_pad_send_event (pad, event);
 
     /* Re-sync queue segment info after flush-stop.
      * This event will be dropped on the src pad. */
-    if (text_segment.format != GST_FORMAT_UNDEFINED) {
+    if (sink_segment->format != GST_FORMAT_UNDEFINED) {
       GstEvent *event1;
 
-      _generate_update_newsegment_event (pad, &text_segment, &event1);
+      _generate_update_newsegment_event (pad, sink_segment, &event1);
       GST_DEBUG_OBJECT (playsink,
           "Pushing segment event with reset "
           "segment marker set: %" GST_PTR_FORMAT, event1);
       gst_pad_send_event (pad, event1);
     }
-
-    playsink->pending_flush_stop = FALSE;
+  } else {
+    GST_PLAY_SINK_UNLOCK (playsink);
   }
-  GST_PLAY_SINK_UNLOCK (playsink);
 
   ret = gst_proxy_pad_chain_default (pad, parent, buffer);
 
   GST_PLAY_SINK_LOCK (playsink);
-  if (ret == GST_FLOW_FLUSHING && playsink->ignore_wrong_state) {
-    GST_DEBUG_OBJECT (pad, "Ignoring wrong state during flush");
-    if (playsink->custom_flush_finished) {
-      GST_DEBUG_OBJECT (pad,
-          "custom flush finished, stop ignoring wrong state");
-      playsink->ignore_wrong_state = FALSE;
+  if (ret == GST_FLOW_FLUSHING && *sink_ignore_wrong_state) {
+    GST_DEBUG_OBJECT (pad, "Ignoring wrong state for %s during flush",
+        sink_type);
+    if (*sink_custom_flush_finished) {
+      GST_DEBUG_OBJECT (pad, "Custom flush finished, stop ignoring "
+          "wrong state for %s", sink_type);
+      *sink_ignore_wrong_state = FALSE;
     }
 
     ret = GST_FLOW_OK;
@@ -1981,6 +2057,111 @@ gst_play_sink_text_sink_chain (GstPad * pad, GstObject * parent,
   return ret;
 }
 
+/* sending audio/video flushes break stream changes when the pipeline
+ * is paused and played again in 0.10 */
+#if 0
+static gboolean
+gst_play_sink_video_sink_event (GstPad * pad, GstEvent * event)
+{
+  GstBin *tbin = GST_BIN_CAST (gst_pad_get_parent (pad));
+  GstPlaySink *playsink = GST_PLAY_SINK_CAST (gst_pad_get_parent (tbin));
+  gboolean ret;
+
+  ret = gst_play_sink_sink_event (pad, event, "video",
+      &playsink->video_ignore_wrong_state,
+      &playsink->video_custom_flush_finished,
+      &playsink->video_pending_flush, &playsink->video_segment);
+
+  gst_object_unref (playsink);
+  gst_object_unref (tbin);
+  return ret;
+}
+
+static GstFlowReturn
+gst_play_sink_video_sink_chain (GstPad * pad, GstBuffer * buffer)
+{
+  GstBin *tbin = GST_BIN_CAST (gst_pad_get_parent (pad));
+  GstPlaySink *playsink = GST_PLAY_SINK_CAST (gst_pad_get_parent (tbin));
+  gboolean ret;
+
+  ret = gst_play_sink_sink_chain (pad, buffer, "video",
+      &playsink->video_ignore_wrong_state,
+      &playsink->video_custom_flush_finished,
+      &playsink->video_pending_flush, &playsink->video_segment);
+
+  gst_object_unref (playsink);
+  gst_object_unref (tbin);
+  return ret;
+}
+
+static gboolean
+gst_play_sink_audio_sink_event (GstPad * pad, GstEvent * event)
+{
+  GstBin *tbin = GST_BIN_CAST (gst_pad_get_parent (pad));
+  GstPlaySink *playsink = GST_PLAY_SINK_CAST (gst_pad_get_parent (tbin));
+  gboolean ret;
+
+  ret = gst_play_sink_sink_event (pad, event, "audio",
+      &playsink->audio_ignore_wrong_state,
+      &playsink->audio_custom_flush_finished,
+      &playsink->audio_pending_flush, &playsink->audio_segment);
+
+  gst_object_unref (playsink);
+  gst_object_unref (tbin);
+  return ret;
+}
+
+static GstFlowReturn
+gst_play_sink_audio_sink_chain (GstPad * pad, GstBuffer * buffer)
+{
+  GstBin *tbin = GST_BIN_CAST (gst_pad_get_parent (pad));
+  GstPlaySink *playsink = GST_PLAY_SINK_CAST (gst_pad_get_parent (tbin));
+  gboolean ret;
+
+  ret = gst_play_sink_sink_chain (pad, buffer, "audio",
+      &playsink->audio_ignore_wrong_state,
+      &playsink->audio_custom_flush_finished,
+      &playsink->audio_pending_flush, &playsink->audio_segment);
+
+  gst_object_unref (playsink);
+  gst_object_unref (tbin);
+  return ret;
+}
+#endif
+
+static gboolean
+gst_play_sink_text_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event)
+{
+  GstPlaySink *playsink = GST_PLAY_SINK_CAST (gst_object_get_parent (parent));
+  gboolean ret;
+
+  ret = gst_play_sink_sink_event (pad, parent, event, "subtitle",
+      &playsink->text_ignore_wrong_state,
+      &playsink->text_custom_flush_finished,
+      &playsink->text_pending_flush, &playsink->text_segment);
+
+  gst_object_unref (playsink);
+
+  return ret;
+}
+
+static GstFlowReturn
+gst_play_sink_text_sink_chain (GstPad * pad, GstObject * parent,
+    GstBuffer * buffer)
+{
+  gboolean ret;
+  GstPlaySink *playsink = GST_PLAY_SINK_CAST (gst_object_get_parent (parent));
+
+  ret = gst_play_sink_sink_chain (pad, parent, buffer, "subtitle",
+      &playsink->text_ignore_wrong_state,
+      &playsink->text_custom_flush_finished,
+      &playsink->text_pending_flush, &playsink->text_segment);
+
+  gst_object_unref (playsink);
+  return ret;
+}
+
 static gboolean
 gst_play_sink_text_src_event (GstPad * pad, GstObject * parent,
     GstEvent * event)
@@ -2439,6 +2620,16 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw)
   GST_DEBUG_OBJECT (playsink, "ghosting sink pad");
   pad = gst_element_get_static_pad (head, "sink");
   chain->sinkpad = gst_ghost_pad_new ("sink", pad);
+
+  /* sending audio/video flushes break stream changes when the pipeline
+   * is paused and played again in 0.10 */
+#if 0
+  gst_pad_set_event_function (chain->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_play_sink_audio_sink_event));
+  gst_pad_set_chain_function (chain->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_play_sink_audio_sink_chain));
+#endif
+
   gst_object_unref (pad);
   gst_element_add_pad (chain->chain.bin, chain->sinkpad);
 
index a3bbd1a..e88d345 100644 (file)
@@ -2066,7 +2066,7 @@ gst_subtitle_overlay_subtitle_sink_event (GstPad * pad, GstObject * parent,
   GST_DEBUG_OBJECT (pad, "Got event %" GST_PTR_FORMAT, event);
 
   if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM_OOB &&
-      gst_event_has_name (event, "subtitleoverlay-flush-subtitle")) {
+      gst_event_has_name (event, "playsink-custom-subtitle-flush")) {
     GST_DEBUG_OBJECT (pad, "Custom subtitle flush event");
     GST_SUBTITLE_OVERLAY_LOCK (self);
     self->subtitle_flush = TRUE;