playbin2: Properly change subtitles
authorAndre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk>
Sun, 20 May 2012 15:51:17 +0000 (12:51 -0300)
committerThiago Santos <thiago.sousa.santos@collabora.com>
Wed, 6 Jun 2012 19:31:08 +0000 (16:31 -0300)
Conflicts:

gst/playback/gstplaysink.c

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

index 85425d0..32b877c 100644 (file)
@@ -410,6 +410,10 @@ 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
+                                         * on pad activation */
+
   GstElement *audio_sink;       /* configured audio sink, or NULL      */
   GstElement *video_sink;       /* configured video sink, or NULL      */
   GstElement *text_sink;        /* configured text sink, or NULL       */
@@ -1922,9 +1926,6 @@ gst_play_bin_set_current_text_stream (GstPlayBin * playbin, gint stream)
           gst_play_bin_suburidecodebin_block (group, group->suburidecodebin,
               TRUE);
 
-        /* activate the selected pad */
-        g_object_set (selector, "active-pad", sinkpad, NULL);
-
         src = gst_element_get_static_pad (GST_ELEMENT_CAST (selector), "src");
         peer = gst_pad_get_peer (src);
         if (peer) {
@@ -1937,10 +1938,14 @@ gst_play_bin_set_current_text_stream (GstPlayBin * playbin, gint stream)
           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);
 
+        /* activate the selected pad */
+        g_object_set (selector, "active-pad", sinkpad, NULL);
+
         /* Unblock pads if necessary */
         if (need_unblock)
           gst_play_bin_suburidecodebin_block (group, group->suburidecodebin,
@@ -2574,12 +2579,36 @@ selector_active_pad_changed (GObject * selector, GParamSpec * pspec,
       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;
+        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);
+
+        goto notify;
+      }
       break;
     default:
       property = NULL;
   }
   GST_PLAY_BIN_UNLOCK (playbin);
 
+notify:
   if (property)
     g_object_notify (G_OBJECT (playbin), property);
 }
index 19bce39..eda375f 100644 (file)
@@ -258,7 +258,9 @@ struct _GstPlaySink
   gint colorbalance_values[4];
 
   GstSegment text_segment;
-  gboolean text_flush;
+  gboolean custom_flush_finished;
+  gboolean ignore_wrong_state;
+  gboolean pending_flush_stop;
 };
 
 struct _GstPlaySinkClass
@@ -1870,7 +1872,16 @@ gst_play_sink_text_sink_event (GstPad * pad, GstObject * parent,
     GST_DEBUG_OBJECT (pad,
         "Custom subtitle flush event received, marking to flush text");
     GST_PLAY_SINK_LOCK (playsink);
-    playsink->text_flush = TRUE;
+    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");
+    GST_PLAY_SINK_LOCK (playsink);
+    playsink->pending_flush_stop = TRUE;
+    playsink->custom_flush_finished = TRUE;
     GST_PLAY_SINK_UNLOCK (playsink);
   } else if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
     GST_DEBUG_OBJECT (pad,
@@ -1910,20 +1921,17 @@ gst_play_sink_text_sink_chain (GstPad * pad, GstObject * parent,
 {
   GstBin *tbin = GST_BIN_CAST (gst_pad_get_parent (pad));
   GstPlaySink *playsink = GST_PLAY_SINK_CAST (gst_pad_get_parent (tbin));
+  GstFlowReturn ret;
 
-  GstFlowReturn ret = gst_proxy_pad_chain_default (pad, parent, buffer);
+  GST_PLAY_SINK_LOCK (playsink);
 
-  if (ret == GST_FLOW_FLUSHING && playsink->text_flush) {
-    GstEvent *event;
+  if (playsink->pending_flush_stop) {
     GstSegment *text_segment;
+    GstEvent *event;
     GstStructure *structure;
 
-    GST_DEBUG_OBJECT (pad,
-        "Ignoring wrong state due to flush text being marked");
-    GST_PLAY_SINK_LOCK (playsink);
-    playsink->text_flush = FALSE;
+    // it will be replaced in flush_stop
     text_segment = gst_segment_copy (&playsink->text_segment);
-    GST_PLAY_SINK_UNLOCK (playsink);
 
     /* make queue drop all cached data.
      * This event will be dropped on the src pad. */
@@ -1931,9 +1939,10 @@ gst_play_sink_text_sink_chain (GstPad * pad, GstObject * parent,
     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 (playsink,
+
+    GST_DEBUG_OBJECT (pad,
         "Pushing flush-stop event with reset segment marker set: %"
-        GST_PTR_FORMAT, structure);
+        GST_PTR_FORMAT, event);
     gst_pad_send_event (pad, event);
 
     /* Re-sync queue segment info after flush-stop.
@@ -1947,11 +1956,26 @@ gst_play_sink_text_sink_chain (GstPad * pad, GstObject * parent,
           "segment marker set: %" GST_PTR_FORMAT, event1);
       gst_pad_send_event (pad, event1);
     }
-
     gst_segment_free (text_segment);
 
+    playsink->pending_flush_stop = FALSE;
+  }
+  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;
+    }
+
     ret = GST_FLOW_OK;
   }
+  GST_PLAY_SINK_UNLOCK (playsink);
 
   gst_object_unref (playsink);
   gst_object_unref (tbin);
@@ -2526,7 +2550,7 @@ setup_audio_chain (GstPlaySink * playsink, gboolean raw)
   } else if (conv) {
     /* no volume, we need to add a volume element when we can */
     g_object_set (chain->conv, "use-volume",
-        ! !(playsink->flags & GST_PLAY_FLAG_SOFT_VOLUME), NULL);
+        !!(playsink->flags & GST_PLAY_FLAG_SOFT_VOLUME), NULL);
     GST_DEBUG_OBJECT (playsink, "the sink has no volume property");
 
     /* Disconnect signals */
@@ -3647,14 +3671,14 @@ caps_notify_cb (GstPad * pad, GParamSpec * unused, GstPlaySink * playsink)
 
   if (pad == playsink->audio_pad) {
     raw = is_raw_pad (pad);
-    reconfigure = (! !playsink->audio_pad_raw != ! !raw)
+    reconfigure = (!!playsink->audio_pad_raw != !!raw)
         && playsink->audiochain;
     GST_DEBUG_OBJECT (pad,
         "Audio caps changed: raw %d reconfigure %d caps %" GST_PTR_FORMAT, raw,
         reconfigure, caps);
   } else if (pad == playsink->video_pad) {
     raw = is_raw_pad (pad);
-    reconfigure = (! !playsink->video_pad_raw != ! !raw)
+    reconfigure = (!!playsink->video_pad_raw != !!raw)
         && playsink->videochain;
     GST_DEBUG_OBJECT (pad,
         "Video caps changed: raw %d reconfigure %d caps %" GST_PTR_FORMAT, raw,