Title: [96310] trunk/Source/WebCore
Revision
96310
Author
ph...@webkit.org
Date
2011-09-29 01:03:31 -0700 (Thu, 29 Sep 2011)

Log Message

[GStreamer] fullscreen video pause/play fails
https://bugs.webkit.org/show_bug.cgi?id=66936

Reviewed by Martin Robinson.

Don't use the identity element to avoid painting of the in-window
video. Instead simply make the sink aware of the fullscreen state
and ignore buffers if fullscreen and autovideosink are
active. Also fixed two deadlocks happening when a paused pipeline
is switched to fullscreen and when fullscreen is disabled for a
paused pipeline.

* platform/graphics/gstreamer/GStreamerGWorld.cpp:
(WebCore::GStreamerGWorld::enterFullscreen):
(WebCore::GStreamerGWorld::exitFullscreen):
* platform/graphics/gstreamer/GStreamerGWorld.h:
(WebCore::GStreamerGWorld::isFullscreen):
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
(WebCore::MediaPlayerPrivateGStreamer::createGSTPlayBin):
* platform/graphics/gstreamer/VideoSinkGStreamer.cpp:
(webkit_video_sink_render):
(webkit_video_sink_new):
* platform/graphics/gstreamer/VideoSinkGStreamer.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (96309 => 96310)


--- trunk/Source/WebCore/ChangeLog	2011-09-29 07:52:49 UTC (rev 96309)
+++ trunk/Source/WebCore/ChangeLog	2011-09-29 08:03:31 UTC (rev 96310)
@@ -1,3 +1,29 @@
+2011-09-29  Philippe Normand  <pnorm...@igalia.com>
+
+        [GStreamer] fullscreen video pause/play fails
+        https://bugs.webkit.org/show_bug.cgi?id=66936
+
+        Reviewed by Martin Robinson.
+
+        Don't use the identity element to avoid painting of the in-window
+        video. Instead simply make the sink aware of the fullscreen state
+        and ignore buffers if fullscreen and autovideosink are
+        active. Also fixed two deadlocks happening when a paused pipeline
+        is switched to fullscreen and when fullscreen is disabled for a
+        paused pipeline.
+
+        * platform/graphics/gstreamer/GStreamerGWorld.cpp:
+        (WebCore::GStreamerGWorld::enterFullscreen):
+        (WebCore::GStreamerGWorld::exitFullscreen):
+        * platform/graphics/gstreamer/GStreamerGWorld.h:
+        (WebCore::GStreamerGWorld::isFullscreen):
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
+        (WebCore::MediaPlayerPrivateGStreamer::createGSTPlayBin):
+        * platform/graphics/gstreamer/VideoSinkGStreamer.cpp:
+        (webkit_video_sink_render):
+        (webkit_video_sink_new):
+        * platform/graphics/gstreamer/VideoSinkGStreamer.h:
+
 2011-09-29  Tim Horton  <timothy_hor...@apple.com>
 
         REGRESSION(87010): elements in ECMA-cloud neither filled nor blurred

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp (96309 => 96310)


--- trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp	2011-09-29 07:52:49 UTC (rev 96309)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp	2011-09-29 08:03:31 UTC (rev 96310)
@@ -89,10 +89,7 @@
     GOwnPtr<GstElement> videoSink;
     g_object_get(m_pipeline, "video-sink", &videoSink.outPtr(), NULL);
     GstElement* tee = gst_bin_get_by_name(GST_BIN(videoSink.get()), "videoTee");
-    GstElement* valve = gst_bin_get_by_name(GST_BIN(videoSink.get()), "videoValve");
 
-    g_object_set(valve, "drop-probability", 1.0, NULL);
-
     // Add and link a queue, ffmpegcolorspace, videoscale and sink in the bin.
     gst_bin_add_many(GST_BIN(videoSink.get()), platformVideoSink, videoScale, colorspace, queue, NULL);
 
@@ -109,12 +106,17 @@
 
     m_dynamicPadName = gst_pad_get_name(srcPad);
 
-    // Roll new elements to pipeline state.
-    gst_element_sync_state_with_parent(queue);
-    gst_element_sync_state_with_parent(colorspace);
-    gst_element_sync_state_with_parent(videoScale);
-    gst_element_sync_state_with_parent(platformVideoSink);
+    // Synchronize the new elements with pipeline state. If it's
+    // paused limit the state change to pre-rolling.
+    GstState state;
+    gst_element_get_state(m_pipeline, &state, 0, 0);
+    if (state < GST_STATE_PLAYING)
+        state = GST_STATE_READY;
 
+    gst_element_set_state(platformVideoSink, state);
+    gst_element_set_state(videoScale, state);
+    gst_element_set_state(colorspace, state);
+    gst_element_set_state(queue, state);
     gst_object_unref(tee);
 
     // Query the current media segment informations and send them towards
@@ -160,30 +162,32 @@
     GstElement* colorspace = gst_bin_get_by_name(GST_BIN(videoSink.get()), "colorspace");
     GstElement* videoScale = gst_bin_get_by_name(GST_BIN(videoSink.get()), "videoScale");
 
-    GstElement* valve = gst_bin_get_by_name(GST_BIN(videoSink.get()), "videoValve");
-
-    g_object_set(valve, "drop-probability", 0.0, NULL);
-
     // Get pads to unlink and remove.
     GstPad* srcPad = gst_element_get_static_pad(tee, m_dynamicPadName);
     GstPad* sinkPad = gst_element_get_static_pad(queue, "sink");
 
-    // Block data flow towards the pipeline branch to remove.
-    gst_pad_set_blocked(srcPad, true);
+    // Block data flow towards the pipeline branch to remove. No need
+    // for pad blocking if the pipeline is paused.
+    GstState state;
+    gst_element_get_state(m_pipeline, &state, 0, 0);
+    if (state < GST_STATE_PLAYING || gst_pad_set_blocked(srcPad, true)) {
 
-    // Unlink and release request pad.
-    gst_pad_unlink(srcPad, sinkPad);
-    gst_element_release_request_pad(tee, srcPad);
+        // Unlink and release request pad.
+        gst_pad_unlink(srcPad, sinkPad);
+        gst_element_release_request_pad(tee, srcPad);
+
+        // Unlink, remove and cleanup queue, ffmpegcolorspace, videoScale and sink.
+        gst_element_unlink_many(queue, colorspace, videoScale, platformVideoSink, NULL);
+        gst_bin_remove_many(GST_BIN(videoSink.get()), queue, colorspace, videoScale, platformVideoSink, NULL);
+        gst_element_set_state(platformVideoSink, GST_STATE_NULL);
+        gst_element_set_state(videoScale, GST_STATE_NULL);
+        gst_element_set_state(colorspace, GST_STATE_NULL);
+        gst_element_set_state(queue, GST_STATE_NULL);
+    }
+
     gst_object_unref(GST_OBJECT(srcPad));
     gst_object_unref(GST_OBJECT(sinkPad));
 
-    // Unlink, remove and cleanup queue, ffmpegcolorspace, videoScale and sink.
-    gst_element_unlink_many(queue, colorspace, videoScale, platformVideoSink, NULL);
-    gst_bin_remove_many(GST_BIN(videoSink.get()), queue, colorspace, videoScale, platformVideoSink, NULL);
-    gst_element_set_state(queue, GST_STATE_NULL);
-    gst_element_set_state(colorspace, GST_STATE_NULL);
-    gst_element_set_state(videoScale, GST_STATE_NULL);
-    gst_element_set_state(platformVideoSink, GST_STATE_NULL);
     gst_object_unref(queue);
     gst_object_unref(colorspace);
     gst_object_unref(videoScale);

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerGWorld.h (96309 => 96310)


--- trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerGWorld.h	2011-09-29 07:52:49 UTC (rev 96309)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerGWorld.h	2011-09-29 08:03:31 UTC (rev 96310)
@@ -51,6 +51,8 @@
     bool enterFullscreen();
     void exitFullscreen();
 
+    bool isFullscreen() const { return m_dynamicPadName; }
+
     void setWindowOverlay(GstMessage* message);
     PlatformVideoWindow* platformVideoWindow() const { return m_videoWindow.get(); }
 

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp (96309 => 96310)


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp	2011-09-29 07:52:49 UTC (rev 96309)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp	2011-09-29 08:03:31 UTC (rev 96310)
@@ -1669,14 +1669,13 @@
     g_signal_connect(m_playBin, "video-changed", G_CALLBACK(mediaPlayerPrivateVideoChangedCallback), this);
     g_signal_connect(m_playBin, "audio-changed", G_CALLBACK(mediaPlayerPrivateAudioChangedCallback), this);
 
-    m_webkitVideoSink = webkit_video_sink_new();
+    m_webkitVideoSink = webkit_video_sink_new(m_gstGWorld.get());
 
     g_signal_connect(m_webkitVideoSink, "repaint-requested", G_CALLBACK(mediaPlayerPrivateRepaintCallback), this);
 
     m_videoSinkBin = gst_bin_new("sink");
     GstElement* videoTee = gst_element_factory_make("tee", "videoTee");
     GstElement* queue = gst_element_factory_make("queue", 0);
-    GstElement* identity = gst_element_factory_make("identity", "videoValve");
 
     // Take ownership.
     gst_object_ref_sink(m_videoSinkBin);
@@ -1686,7 +1685,7 @@
     // internal video sink. For fullscreen we create an autovideosink
     // and initially block the data flow towards it and configure it
 
-    gst_bin_add_many(GST_BIN(m_videoSinkBin), videoTee, queue, identity, NULL);
+    gst_bin_add_many(GST_BIN(m_videoSinkBin), videoTee, queue, NULL);
 
     // Link a new src pad from tee to queue1.
     GstPad* srcPad = gst_element_get_request_pad(videoTee, "src%d");
@@ -1728,8 +1727,7 @@
     ASSERT(actualVideoSink);
 
     // Faster elements linking.
-    gst_element_link_pads_full(queue, "src", identity, "sink", GST_PAD_LINK_CHECK_NOTHING);
-    gst_element_link_pads_full(identity, "src", actualVideoSink, "sink", GST_PAD_LINK_CHECK_NOTHING);
+    gst_element_link_pads_full(queue, "src", actualVideoSink, "sink", GST_PAD_LINK_CHECK_NOTHING);
 
     // Add a ghostpad to the bin so it can proxy to tee.
     GstPad* pad = gst_element_get_static_pad(videoTee, "sink");

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp (96309 => 96310)


--- trunk/Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp	2011-09-29 07:52:49 UTC (rev 96309)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp	2011-09-29 08:03:31 UTC (rev 96310)
@@ -63,6 +63,7 @@
     guint timeout_id;
     GMutex* buffer_mutex;
     GCond* data_cond;
+    WebCore::GStreamerGWorld* gstGWorld;
 
     // If this is TRUE all processing should finish ASAP
     // This is necessary because there could be a race between
@@ -147,6 +148,13 @@
         return GST_FLOW_OK;
     }
 
+    // Ignore buffers if the video is already in fullscreen using
+    // another sink.
+    if (priv->gstGWorld->isFullscreen()) {
+        g_mutex_unlock(priv->buffer_mutex);
+        return GST_FLOW_OK;
+    }
+
     priv->buffer = gst_buffer_ref(buffer);
 
     // For the unlikely case where the buffer has no caps, the caps
@@ -365,10 +373,11 @@
  *
  * Return value: a #GstElement for the newly created video sink
  */
-GstElement*
-webkit_video_sink_new(void)
+GstElement* webkit_video_sink_new(WebCore::GStreamerGWorld* gstGWorld)
 {
-    return (GstElement*)g_object_new(WEBKIT_TYPE_VIDEO_SINK, 0);
+    GstElement* element = GST_ELEMENT(g_object_new(WEBKIT_TYPE_VIDEO_SINK, 0));
+    WEBKIT_VIDEO_SINK(element)->priv->gstGWorld = gstGWorld;
+    return element;
 }
 
 #endif // USE(GSTREAMER)

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h (96309 => 96310)


--- trunk/Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h	2011-09-29 07:52:49 UTC (rev 96309)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h	2011-09-29 08:03:31 UTC (rev 96310)
@@ -22,6 +22,7 @@
 
 #if ENABLE(VIDEO) && USE(GSTREAMER)
 
+#include "GStreamerGWorld.h"
 #include <glib-object.h>
 #include <gst/video/gstvideosink.h>
 
@@ -72,8 +73,9 @@
     void (* _webkit_reserved6)(void);
 };
 
+
 GType       webkit_video_sink_get_type(void) G_GNUC_CONST;
-GstElement *webkit_video_sink_new(void);
+GstElement *webkit_video_sink_new(WebCore::GStreamerGWorld*);
 
 G_END_DECLS
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to