Title: [151728] trunk/Source/WebCore
Revision
151728
Author
[email protected]
Date
2013-06-19 02:14:02 -0700 (Wed, 19 Jun 2013)

Log Message

[GStreamer] Potential race condition when getting the video sink caps.
https://bugs.webkit.org/show_bug.cgi?id=117736

Patch by Víctor Manuel Jáquez Leal <[email protected]> on 2013-06-19
Reviewed by Philippe Normand.

There is a potential race condition with the pad setting caps, as the
buffer and the caps won't match when renegotiation happens, and might
cause a crash.

This patch keeps an instance of the current caps in the video sink,
and it is accessible through a getter method. Hence the player can ask
for the current caps without running into a race condition.

No new tests. No change in behaviour.

* platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:
(WebCore::MediaPlayerPrivateGStreamerBase::naturalSize):
(WebCore::MediaPlayerPrivateGStreamerBase::paint):
(WebCore::MediaPlayerPrivateGStreamerBase::currentVideoSinkCaps):
(WebCore::MediaPlayerPrivateGStreamerBase::createVideoSink):
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h:
* platform/graphics/gstreamer/VideoSinkGStreamer.cpp:
(webkitVideoSinkGetProperty):
(webkitVideoSinkStop):
(webkitVideoSinkSetCaps):
(webkit_video_sink_class_init):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (151727 => 151728)


--- trunk/Source/WebCore/ChangeLog	2013-06-19 08:07:40 UTC (rev 151727)
+++ trunk/Source/WebCore/ChangeLog	2013-06-19 09:14:02 UTC (rev 151728)
@@ -1,3 +1,32 @@
+2013-06-19  Víctor Manuel Jáquez Leal  <[email protected]>
+
+        [GStreamer] Potential race condition when getting the video sink caps.
+        https://bugs.webkit.org/show_bug.cgi?id=117736
+
+        Reviewed by Philippe Normand.
+
+        There is a potential race condition with the pad setting caps, as the
+        buffer and the caps won't match when renegotiation happens, and might
+        cause a crash.
+
+        This patch keeps an instance of the current caps in the video sink,
+        and it is accessible through a getter method. Hence the player can ask
+        for the current caps without running into a race condition.
+
+        No new tests. No change in behaviour.
+
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:
+        (WebCore::MediaPlayerPrivateGStreamerBase::naturalSize):
+        (WebCore::MediaPlayerPrivateGStreamerBase::paint):
+        (WebCore::MediaPlayerPrivateGStreamerBase::currentVideoSinkCaps):
+        (WebCore::MediaPlayerPrivateGStreamerBase::createVideoSink):
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h:
+        * platform/graphics/gstreamer/VideoSinkGStreamer.cpp:
+        (webkitVideoSinkGetProperty):
+        (webkitVideoSinkStop):
+        (webkitVideoSinkSetCaps):
+        (webkit_video_sink_class_init):
+
 2013-06-19  Kihong Kwon  <[email protected]>
 
         Vibration can be canceled even if page visibility status is hidden

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp (151727 => 151728)


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp	2013-06-19 08:07:40 UTC (rev 151727)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp	2013-06-19 09:14:02 UTC (rev 151728)
@@ -176,11 +176,7 @@
         return m_videoSize;
 
 #ifdef GST_API_VERSION_1
-    /* FIXME this has a race with the pad setting caps as the buffer (m_buffer)
-     * and the caps won't match and might cause a crash. (In case a
-     * renegotiation happens)
-     */
-    GRefPtr<GstCaps> caps = webkitGstGetPadCaps(m_videoSinkPad.get());
+    GRefPtr<GstCaps> caps = currentVideoSinkCaps();
 #else
     g_mutex_lock(m_bufferMutex);
     GRefPtr<GstCaps> caps = m_buffer ? GST_BUFFER_CAPS(m_buffer) : 0;
@@ -418,11 +414,7 @@
     }
 
 #ifdef GST_API_VERSION_1
-    /* FIXME this has a race with the pad setting caps as the buffer (m_buffer)
-     * and the caps won't match and might cause a crash. (In case a
-     * renegotiation happens)
-     */
-    GRefPtr<GstCaps> caps = webkitGstGetPadCaps(m_videoSinkPad.get());
+    GRefPtr<GstCaps> caps = currentVideoSinkCaps();
 #else
     GRefPtr<GstCaps> caps = GST_BUFFER_CAPS(m_buffer);
 #endif
@@ -503,6 +495,16 @@
     return MediaPlayer::Download;
 }
 
+GRefPtr<GstCaps> MediaPlayerPrivateGStreamerBase::currentVideoSinkCaps() const
+{
+    if (!m_webkitVideoSink)
+        return 0;
+
+    GstCaps* currentCaps = 0;
+    g_object_get(G_OBJECT(m_webkitVideoSink.get()), "current-caps", &currentCaps, NULL);
+    return adoptGRef(currentCaps);
+}
+
 // This function creates and initializes some internal variables, and returns a
 // pointer to the element that should receive the data flow first
 GstElement* MediaPlayerPrivateGStreamerBase::createVideoSink(GstElement* pipeline)
@@ -517,7 +519,6 @@
     UNUSED_PARAM(pipeline);
     m_webkitVideoSink = webkitVideoSinkNew();
 #endif
-    m_videoSinkPad = adoptGRef(gst_element_get_static_pad(m_webkitVideoSink.get(), "sink"));
 
     m_repaintHandler = g_signal_connect(m_webkitVideoSink.get(), "repaint-requested", G_CALLBACK(mediaPlayerPrivateRepaintCallback), this);
 

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h (151727 => 151728)


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h	2013-06-19 08:07:40 UTC (rev 151727)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h	2013-06-19 09:14:02 UTC (rev 151728)
@@ -114,6 +114,7 @@
     GstElement* createVideoSink(GstElement* pipeline);
     void setStreamVolumeElement(GstStreamVolume*);
     virtual GstElement* audioSink() const { return 0; }
+    GRefPtr<GstCaps> currentVideoSinkCaps() const;
 
     MediaPlayer* m_player;
     GRefPtr<GstStreamVolume> m_volumeElement;
@@ -134,7 +135,6 @@
     unsigned long m_repaintHandler;
     unsigned long m_volumeSignalHandler;
     unsigned long m_muteSignalHandler;
-    GRefPtr<GstPad> m_videoSinkPad;
     mutable IntSize m_videoSize;
 #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER_GL) && !USE(COORDINATED_GRAPHICS)
     void updateTexture(GstBuffer*);

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


--- trunk/Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp	2013-06-19 08:07:40 UTC (rev 151727)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp	2013-06-19 09:14:02 UTC (rev 151728)
@@ -76,7 +76,8 @@
 };
 
 enum {
-    PROP_0
+    PROP_0,
+    PROP_CAPS
 };
 
 static guint webkitVideoSinkSignals[LAST_SIGNAL] = { 0, };
@@ -95,6 +96,8 @@
     WebCore::GStreamerGWorld* gstGWorld;
 #endif
 
+    GstCaps* currentCaps;
+
     // If this is TRUE all processing should finish ASAP
     // This is necessary because there could be a race between
     // unlock() and render(), where unlock() wins, signals the
@@ -296,6 +299,24 @@
     G_OBJECT_CLASS(parent_class)->dispose(object);
 }
 
+static void webkitVideoSinkGetProperty(GObject* object, guint propertyId, GValue* value, GParamSpec* parameterSpec)
+{
+    WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(object);
+    WebKitVideoSinkPrivate* priv = sink->priv;
+
+    switch (propertyId) {
+    case PROP_CAPS: {
+        GstCaps* caps = priv->currentCaps;
+        if (caps)
+            gst_caps_ref(caps);
+        g_value_take_boxed(value, caps);
+        break;
+    }
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyId, parameterSpec);
+    }
+}
+
 static void unlockBufferMutex(WebKitVideoSinkPrivate* priv)
 {
     g_mutex_lock(priv->bufferMutex);
@@ -333,7 +354,15 @@
 
 static gboolean webkitVideoSinkStop(GstBaseSink* baseSink)
 {
-    unlockBufferMutex(WEBKIT_VIDEO_SINK(baseSink)->priv);
+    WebKitVideoSinkPrivate* priv = WEBKIT_VIDEO_SINK(baseSink)->priv;
+
+    unlockBufferMutex(priv);
+
+    if (priv->currentCaps) {
+        gst_caps_unref(priv->currentCaps);
+        priv->currentCaps = 0;
+    }
+
     return TRUE;
 }
 
@@ -347,6 +376,14 @@
     return TRUE;
 }
 
+static gboolean webkitVideoSinkSetCaps(GstBaseSink* baseSink, GstCaps* caps)
+{
+    WebKitVideoSinkPrivate* priv = WEBKIT_VIDEO_SINK(baseSink)->priv;
+
+    gst_caps_replace(&priv->currentCaps, caps);
+    return TRUE;
+}
+
 #ifdef GST_API_VERSION_1
 static gboolean webkitVideoSinkProposeAllocation(GstBaseSink* baseSink, GstQuery* query)
 {
@@ -403,6 +440,7 @@
     g_type_class_add_private(klass, sizeof(WebKitVideoSinkPrivate));
 
     gobjectClass->dispose = webkitVideoSinkDispose;
+    gobjectClass->get_property = webkitVideoSinkGetProperty;
 
     baseSinkClass->unlock = webkitVideoSinkUnlock;
     baseSinkClass->unlock_stop = webkitVideoSinkUnlockStop;
@@ -410,10 +448,14 @@
     baseSinkClass->preroll = webkitVideoSinkRender;
     baseSinkClass->stop = webkitVideoSinkStop;
     baseSinkClass->start = webkitVideoSinkStart;
+    baseSinkClass->set_caps = webkitVideoSinkSetCaps;
 #ifdef GST_API_VERSION_1
     baseSinkClass->propose_allocation = webkitVideoSinkProposeAllocation;
 #endif
 
+    g_object_class_install_property(gobjectClass, PROP_CAPS,
+        g_param_spec_boxed("current-caps", "Current-Caps", "Current caps", GST_TYPE_CAPS, G_PARAM_READABLE));
+
     webkitVideoSinkSignals[REPAINT_REQUESTED] = g_signal_new("repaint-requested",
             G_TYPE_FROM_CLASS(klass),
             static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to