Title: [192099] trunk/Source/WebCore
Revision
192099
Author
[email protected]
Date
2015-11-06 04:56:02 -0800 (Fri, 06 Nov 2015)

Log Message

[GStreamer] Do not use GThreadSafeMainLoopSource to send notifications to the main thread in MediaPlayerPrivateGStreamer
https://bugs.webkit.org/show_bug.cgi?id=150888

Reviewed by Žan Doberšek.

Analyzing how the main loop sources were used in GST code I've
noticed that in most of the cases they are used to send
notifications to the main thread. The way it works in those cases
is that some state is updated in whatever thread and we notify the
main thread to use the new state. There's no data passed to the
main thread, they are just notifications. I've also noticed that
we are not doing this exactly as expected in several of those
cases. GThreadSafeMainLoopSource cancels the current source when a
new one is scheduled, and that was done this way because previous
code in GST using GSources directly did it that way. But that's
not what we want, if there's a notification pending, since the
state is updated, we can just wait for it to happen instead of
cancelling and scheduling a new one. I've also noticed that in
most of the cases where we schedule notifications to the main
thread, we can be already in the main thread, so we could avoid
the schedule entirely.
We can use RunLoop::dispatch() to send notifications to the main
thread, but there's no way to cancel those tasks. This patch adds
a new helper class MainThreadNotifier that uses an enum of flags to
handle different kind of notifications. It uses
RunLoop::dispatch() to send notifications to the main thread, but
only if there isn't one pending for the given type.
This patch also makes signal callbacks static members to be able
to make the private methods actually private.

* platform/graphics/gstreamer/MainThreadNotifier.h: Added.
(WebCore::MainThreadNotifier::MainThreadNotifier):
(WebCore::MainThreadNotifier::notify):
(WebCore::MainThreadNotifier::cancelPendingNotifications):
(WebCore::MainThreadNotifier::addPendingNotification):
(WebCore::MainThreadNotifier::removePendingNotification):
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
(WebCore::MediaPlayerPrivateGStreamer::setAudioStreamPropertiesCallback):
(WebCore::MediaPlayerPrivateGStreamer::~MediaPlayerPrivateGStreamer):
(WebCore::MediaPlayerPrivateGStreamer::videoChangedCallback):
(WebCore::MediaPlayerPrivateGStreamer::videoSinkCapsChangedCallback):
(WebCore::MediaPlayerPrivateGStreamer::audioChangedCallback):
(WebCore::MediaPlayerPrivateGStreamer::textChangedCallback):
(WebCore::MediaPlayerPrivateGStreamer::newTextSampleCallback):
(WebCore::MediaPlayerPrivateGStreamer::sourceChangedCallback):
(WebCore::MediaPlayerPrivateGStreamer::createAudioSink):
(WebCore::MediaPlayerPrivateGStreamer::createGSTPlayBin):
(WebCore::MediaPlayerPrivateGStreamer::setAudioStreamProperties): Deleted.
(WebCore::MediaPlayerPrivateGStreamer::registerMediaEngine): Deleted.
(WebCore::initializeGStreamerAndRegisterWebKitElements): Deleted.
(WebCore::MediaPlayerPrivateGStreamer::load): Deleted.
(WebCore::MediaPlayerPrivateGStreamer::notifyPlayerOfVideo): Deleted.
(WebCore::MediaPlayerPrivateGStreamer::notifyPlayerOfAudio): Deleted.
(WebCore::MediaPlayerPrivateGStreamer::notifyPlayerOfText): Deleted.
(WebCore::MediaPlayerPrivateGStreamer::canSaveMediaData): Deleted.
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h:
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:
(WebCore::MediaPlayerPrivateGStreamerBase::~MediaPlayerPrivateGStreamerBase):
(WebCore::MediaPlayerPrivateGStreamerBase::volumeChangedCallback):
(WebCore::MediaPlayerPrivateGStreamerBase::muteChangedCallback):
(WebCore::MediaPlayerPrivateGStreamerBase::repaintCallback):
(WebCore::MediaPlayerPrivateGStreamerBase::drawCallback):
(WebCore::MediaPlayerPrivateGStreamerBase::createVideoSink):
(WebCore::MediaPlayerPrivateGStreamerBase::setStreamVolumeElement):
(WebCore::MediaPlayerPrivateGStreamerBase::MediaPlayerPrivateGStreamerBase): Deleted.
(WebCore::MediaPlayerPrivateGStreamerBase::setPipeline): Deleted.
(WebCore::MediaPlayerPrivateGStreamerBase::handleSyncMessage): Deleted.
(WebCore::MediaPlayerPrivateGStreamerBase::muted): Deleted.
(WebCore::MediaPlayerPrivateGStreamerBase::updateTexture): Deleted.
(WebCore::MediaPlayerPrivateGStreamerBase::droppedFrameCount): Deleted.
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h:
(WebCore::MediaPlayerPrivateGStreamerBase::setVisible): Deleted.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (192098 => 192099)


--- trunk/Source/WebCore/ChangeLog	2015-11-06 11:05:55 UTC (rev 192098)
+++ trunk/Source/WebCore/ChangeLog	2015-11-06 12:56:02 UTC (rev 192099)
@@ -1,3 +1,78 @@
+2015-11-06  Carlos Garcia Campos  <[email protected]>
+
+        [GStreamer] Do not use GThreadSafeMainLoopSource to send notifications to the main thread in MediaPlayerPrivateGStreamer
+        https://bugs.webkit.org/show_bug.cgi?id=150888
+
+        Reviewed by Žan Doberšek.
+
+        Analyzing how the main loop sources were used in GST code I've
+        noticed that in most of the cases they are used to send
+        notifications to the main thread. The way it works in those cases
+        is that some state is updated in whatever thread and we notify the
+        main thread to use the new state. There's no data passed to the
+        main thread, they are just notifications. I've also noticed that
+        we are not doing this exactly as expected in several of those
+        cases. GThreadSafeMainLoopSource cancels the current source when a
+        new one is scheduled, and that was done this way because previous
+        code in GST using GSources directly did it that way. But that's
+        not what we want, if there's a notification pending, since the
+        state is updated, we can just wait for it to happen instead of
+        cancelling and scheduling a new one. I've also noticed that in
+        most of the cases where we schedule notifications to the main
+        thread, we can be already in the main thread, so we could avoid
+        the schedule entirely.
+        We can use RunLoop::dispatch() to send notifications to the main
+        thread, but there's no way to cancel those tasks. This patch adds
+        a new helper class MainThreadNotifier that uses an enum of flags to
+        handle different kind of notifications. It uses
+        RunLoop::dispatch() to send notifications to the main thread, but
+        only if there isn't one pending for the given type.
+        This patch also makes signal callbacks static members to be able
+        to make the private methods actually private.
+
+        * platform/graphics/gstreamer/MainThreadNotifier.h: Added.
+        (WebCore::MainThreadNotifier::MainThreadNotifier):
+        (WebCore::MainThreadNotifier::notify):
+        (WebCore::MainThreadNotifier::cancelPendingNotifications):
+        (WebCore::MainThreadNotifier::addPendingNotification):
+        (WebCore::MainThreadNotifier::removePendingNotification):
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
+        (WebCore::MediaPlayerPrivateGStreamer::setAudioStreamPropertiesCallback):
+        (WebCore::MediaPlayerPrivateGStreamer::~MediaPlayerPrivateGStreamer):
+        (WebCore::MediaPlayerPrivateGStreamer::videoChangedCallback):
+        (WebCore::MediaPlayerPrivateGStreamer::videoSinkCapsChangedCallback):
+        (WebCore::MediaPlayerPrivateGStreamer::audioChangedCallback):
+        (WebCore::MediaPlayerPrivateGStreamer::textChangedCallback):
+        (WebCore::MediaPlayerPrivateGStreamer::newTextSampleCallback):
+        (WebCore::MediaPlayerPrivateGStreamer::sourceChangedCallback):
+        (WebCore::MediaPlayerPrivateGStreamer::createAudioSink):
+        (WebCore::MediaPlayerPrivateGStreamer::createGSTPlayBin):
+        (WebCore::MediaPlayerPrivateGStreamer::setAudioStreamProperties): Deleted.
+        (WebCore::MediaPlayerPrivateGStreamer::registerMediaEngine): Deleted.
+        (WebCore::initializeGStreamerAndRegisterWebKitElements): Deleted.
+        (WebCore::MediaPlayerPrivateGStreamer::load): Deleted.
+        (WebCore::MediaPlayerPrivateGStreamer::notifyPlayerOfVideo): Deleted.
+        (WebCore::MediaPlayerPrivateGStreamer::notifyPlayerOfAudio): Deleted.
+        (WebCore::MediaPlayerPrivateGStreamer::notifyPlayerOfText): Deleted.
+        (WebCore::MediaPlayerPrivateGStreamer::canSaveMediaData): Deleted.
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h:
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:
+        (WebCore::MediaPlayerPrivateGStreamerBase::~MediaPlayerPrivateGStreamerBase):
+        (WebCore::MediaPlayerPrivateGStreamerBase::volumeChangedCallback):
+        (WebCore::MediaPlayerPrivateGStreamerBase::muteChangedCallback):
+        (WebCore::MediaPlayerPrivateGStreamerBase::repaintCallback):
+        (WebCore::MediaPlayerPrivateGStreamerBase::drawCallback):
+        (WebCore::MediaPlayerPrivateGStreamerBase::createVideoSink):
+        (WebCore::MediaPlayerPrivateGStreamerBase::setStreamVolumeElement):
+        (WebCore::MediaPlayerPrivateGStreamerBase::MediaPlayerPrivateGStreamerBase): Deleted.
+        (WebCore::MediaPlayerPrivateGStreamerBase::setPipeline): Deleted.
+        (WebCore::MediaPlayerPrivateGStreamerBase::handleSyncMessage): Deleted.
+        (WebCore::MediaPlayerPrivateGStreamerBase::muted): Deleted.
+        (WebCore::MediaPlayerPrivateGStreamerBase::updateTexture): Deleted.
+        (WebCore::MediaPlayerPrivateGStreamerBase::droppedFrameCount): Deleted.
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h:
+        (WebCore::MediaPlayerPrivateGStreamerBase::setVisible): Deleted.
+
 2015-11-06  Yoav Weiss  <[email protected]>
 
         Expose HTMLImageElement sizes attribute in IDL

Added: trunk/Source/WebCore/platform/graphics/gstreamer/MainThreadNotifier.h (0 => 192099)


--- trunk/Source/WebCore/platform/graphics/gstreamer/MainThreadNotifier.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MainThreadNotifier.h	2015-11-06 12:56:02 UTC (rev 192099)
@@ -0,0 +1,95 @@
+/*
+ *  Copyright (C) 2015 Igalia S.L
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef MainThreadNotifier_h
+#define MainThreadNotifier_h
+
+#include <wtf/Lock.h>
+#include <wtf/MainThread.h>
+#include <wtf/RunLoop.h>
+#include <wtf/WeakPtr.h>
+
+namespace WebCore {
+
+template <typename T>
+class MainThreadNotifier {
+public:
+    MainThreadNotifier()
+        : m_weakPtrFactory(this)
+    {
+    }
+
+    template<typename F>
+    void notify(T notificationType, const F& callbackFunctor)
+    {
+        if (isMainThread()) {
+            removePendingNotification(notificationType);
+            callbackFunctor();
+            return;
+        }
+
+        if (!addPendingNotification(notificationType))
+            return;
+
+        auto weakThis = m_weakPtrFactory.createWeakPtr();
+        std::function<void ()> callback(callbackFunctor);
+        RunLoop::main().dispatch([weakThis, notificationType, callback] {
+            if (weakThis && weakThis->removePendingNotification(notificationType))
+                callback();
+        });
+    }
+
+    void cancelPendingNotifications(unsigned mask = 0)
+    {
+        LockHolder locker(m_pendingNotificationsLock);
+        if (mask)
+            m_pendingNotifications &= ~mask;
+        else
+            m_pendingNotifications = 0;
+    }
+
+private:
+
+    bool addPendingNotification(T notificationType)
+    {
+        LockHolder locker(m_pendingNotificationsLock);
+        if (notificationType & m_pendingNotifications)
+            return false;
+        m_pendingNotifications |= notificationType;
+        return true;
+    }
+
+    bool removePendingNotification(T notificationType)
+    {
+        LockHolder locker(m_pendingNotificationsLock);
+        if (notificationType & m_pendingNotifications) {
+            m_pendingNotifications &= ~notificationType;
+            return true;
+        }
+        return false;
+    }
+
+    WeakPtrFactory<MainThreadNotifier> m_weakPtrFactory;
+    Lock m_pendingNotificationsLock;
+    unsigned m_pendingNotifications { 0 };
+};
+
+
+} // namespace WebCore
+
+#endif // MainThreadNotifier_h

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


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp	2015-11-06 11:05:55 UTC (rev 192098)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp	2015-11-06 12:56:02 UTC (rev 192099)
@@ -76,45 +76,11 @@
 
 namespace WebCore {
 
-static void mediaPlayerPrivateSourceChangedCallback(GObject*, GParamSpec*, MediaPlayerPrivateGStreamer* player)
+void MediaPlayerPrivateGStreamer::setAudioStreamPropertiesCallback(MediaPlayerPrivateGStreamer* player, GObject* object)
 {
-    player->sourceChanged();
-}
-
-static void mediaPlayerPrivateVideoSinkCapsChangedCallback(GObject*, GParamSpec*, MediaPlayerPrivateGStreamer* player)
-{
-    player->videoCapsChanged();
-}
-
-static void mediaPlayerPrivateVideoChangedCallback(GObject*, MediaPlayerPrivateGStreamer* player)
-{
-    player->videoChanged();
-}
-
-static void mediaPlayerPrivateAudioChangedCallback(GObject*, MediaPlayerPrivateGStreamer* player)
-{
-    player->audioChanged();
-}
-
-static void setAudioStreamPropertiesCallback(GstChildProxy*, GObject* object, gchar*,
-    MediaPlayerPrivateGStreamer* player)
-{
     player->setAudioStreamProperties(object);
 }
 
-#if ENABLE(VIDEO_TRACK)
-static void mediaPlayerPrivateTextChangedCallback(GObject*, MediaPlayerPrivateGStreamer* player)
-{
-    player->textChanged();
-}
-
-static GstFlowReturn mediaPlayerPrivateNewTextSampleCallback(GObject*, MediaPlayerPrivateGStreamer* player)
-{
-    player->newTextSample();
-    return GST_FLOW_OK;
-}
-#endif
-
 void MediaPlayerPrivateGStreamer::setAudioStreamProperties(GObject* object)
 {
     if (g_strcmp0(G_OBJECT_TYPE_NAME(object), "GstPulseSink"))
@@ -244,21 +210,13 @@
         GRefPtr<GstBus> bus = adoptGRef(gst_pipeline_get_bus(GST_PIPELINE(m_pipeline.get())));
         ASSERT(bus);
         gst_bus_set_sync_handler(bus.get(), nullptr, nullptr, nullptr);
-
-        g_signal_handlers_disconnect_by_func(m_pipeline.get(), reinterpret_cast<gpointer>(mediaPlayerPrivateSourceChangedCallback), this);
-        g_signal_handlers_disconnect_by_func(m_pipeline.get(), reinterpret_cast<gpointer>(mediaPlayerPrivateVideoChangedCallback), this);
-        g_signal_handlers_disconnect_by_func(m_pipeline.get(), reinterpret_cast<gpointer>(mediaPlayerPrivateAudioChangedCallback), this);
-#if ENABLE(VIDEO_TRACK)
-        g_signal_handlers_disconnect_by_func(m_pipeline.get(), reinterpret_cast<gpointer>(mediaPlayerPrivateNewTextSampleCallback), this);
-        g_signal_handlers_disconnect_by_func(m_pipeline.get(), reinterpret_cast<gpointer>(mediaPlayerPrivateTextChangedCallback), this);
-#endif
-
+        g_signal_handlers_disconnect_matched(m_pipeline.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this);
         gst_element_set_state(m_pipeline.get(), GST_STATE_NULL);
     }
 
     if (m_videoSink) {
         GRefPtr<GstPad> videoSinkPad = adoptGRef(gst_element_get_static_pad(m_videoSink.get(), "sink"));
-        g_signal_handlers_disconnect_by_func(videoSinkPad.get(), reinterpret_cast<gpointer>(mediaPlayerPrivateVideoSinkCapsChangedCallback), this);
+        g_signal_handlers_disconnect_by_func(videoSinkPad.get(), reinterpret_cast<gpointer>(videoSinkCapsChangedCallback), this);
     }
 }
 
@@ -649,18 +607,11 @@
     return m_seeking;
 }
 
-void MediaPlayerPrivateGStreamer::videoChanged()
+void MediaPlayerPrivateGStreamer::videoChangedCallback(MediaPlayerPrivateGStreamer* player)
 {
-    m_videoTimerHandler.schedule("[WebKit] MediaPlayerPrivateGStreamer::videoChanged",
-        std::function<void()>([this] { notifyPlayerOfVideo(); }));
+    player->m_notifier.notify(MainThreadNotification::VideoChanged, [player] { player->notifyPlayerOfVideo(); });
 }
 
-void MediaPlayerPrivateGStreamer::videoCapsChanged()
-{
-    m_videoCapsTimerHandler.schedule("[WebKit] MediaPlayerPrivateGStreamer::videoCapsChanged",
-        std::function<void()>([this] { notifyPlayerOfVideoCaps(); }));
-}
-
 void MediaPlayerPrivateGStreamer::notifyPlayerOfVideo()
 {
     gint numTracks = 0;
@@ -698,16 +649,20 @@
     m_player->client().mediaPlayerEngineUpdated(m_player);
 }
 
+void MediaPlayerPrivateGStreamer::videoSinkCapsChangedCallback(MediaPlayerPrivateGStreamer* player)
+{
+    player->m_notifier.notify(MainThreadNotification::VideoCapsChanged, [player] { player->notifyPlayerOfVideoCaps(); });
+}
+
 void MediaPlayerPrivateGStreamer::notifyPlayerOfVideoCaps()
 {
     m_videoSize = IntSize();
     m_player->client().mediaPlayerEngineUpdated(m_player);
 }
 
-void MediaPlayerPrivateGStreamer::audioChanged()
+void MediaPlayerPrivateGStreamer::audioChangedCallback(MediaPlayerPrivateGStreamer* player)
 {
-    m_audioTimerHandler.schedule("[WebKit] MediaPlayerPrivateGStreamer::audioChanged",
-        std::function<void()>([this] { notifyPlayerOfAudio(); }));
+    player->m_notifier.notify(MainThreadNotification::AudioChanged, [player] { player->notifyPlayerOfAudio(); });
 }
 
 void MediaPlayerPrivateGStreamer::notifyPlayerOfAudio()
@@ -748,10 +703,9 @@
 }
 
 #if ENABLE(VIDEO_TRACK)
-void MediaPlayerPrivateGStreamer::textChanged()
+void MediaPlayerPrivateGStreamer::textChangedCallback(MediaPlayerPrivateGStreamer* player)
 {
-    m_textTimerHandler.schedule("[WebKit] MediaPlayerPrivateGStreamer::textChanged",
-        std::function<void()>([this] { notifyPlayerOfText(); }));
+    player->m_notifier.notify(MainThreadNotification::TextChanged, [player] { player->notifyPlayerOfText(); });
 }
 
 void MediaPlayerPrivateGStreamer::notifyPlayerOfText()
@@ -785,6 +739,12 @@
     }
 }
 
+GstFlowReturn MediaPlayerPrivateGStreamer::newTextSampleCallback(MediaPlayerPrivateGStreamer* player)
+{
+    player->newTextSample();
+    return GST_FLOW_OK;
+}
+
 void MediaPlayerPrivateGStreamer::newTextSample()
 {
     if (!m_textAppSink)
@@ -1318,6 +1278,11 @@
     return m_totalBytes;
 }
 
+void MediaPlayerPrivateGStreamer::sourceChangedCallback(MediaPlayerPrivateGStreamer* player)
+{
+    player->sourceChanged();
+}
+
 void MediaPlayerPrivateGStreamer::sourceChanged()
 {
     m_source.clear();
@@ -1868,7 +1833,7 @@
         return nullptr;
     }
 
-    g_signal_connect(m_autoAudioSink.get(), "child-added", G_CALLBACK(setAudioStreamPropertiesCallback), this);
+    g_signal_connect_swapped(m_autoAudioSink.get(), "child-added", G_CALLBACK(setAudioStreamPropertiesCallback), this);
 
     GstElement* audioSinkBin;
 
@@ -1960,12 +1925,12 @@
 
     g_object_set(m_pipeline.get(), "mute", m_player->muted(), nullptr);
 
-    g_signal_connect(m_pipeline.get(), "notify::source", G_CALLBACK(mediaPlayerPrivateSourceChangedCallback), this);
-    g_signal_connect(m_pipeline.get(), "video-changed", G_CALLBACK(mediaPlayerPrivateVideoChangedCallback), this);
-    g_signal_connect(m_pipeline.get(), "audio-changed", G_CALLBACK(mediaPlayerPrivateAudioChangedCallback), this);
+    g_signal_connect_swapped(m_pipeline.get(), "notify::source", G_CALLBACK(sourceChangedCallback), this);
+    g_signal_connect_swapped(m_pipeline.get(), "video-changed", G_CALLBACK(videoChangedCallback), this);
+    g_signal_connect_swapped(m_pipeline.get(), "audio-changed", G_CALLBACK(audioChangedCallback), this);
 #if ENABLE(VIDEO_TRACK)
     if (webkitGstCheckVersion(1, 1, 2)) {
-        g_signal_connect(m_pipeline.get(), "text-changed", G_CALLBACK(mediaPlayerPrivateTextChangedCallback), this);
+        g_signal_connect_swapped(m_pipeline.get(), "text-changed", G_CALLBACK(textChangedCallback), this);
 
         GstElement* textCombiner = webkitTextCombinerNew();
         ASSERT(textCombiner);
@@ -1978,7 +1943,7 @@
         ASSERT(m_textAppSinkPad);
 
         g_object_set(m_textAppSink.get(), "emit-signals", true, "enable-last-sample", false, "caps", gst_caps_new_empty_simple("text/vtt"), NULL);
-        g_signal_connect(m_textAppSink.get(), "new-sample", G_CALLBACK(mediaPlayerPrivateNewTextSampleCallback), this);
+        g_signal_connect_swapped(m_textAppSink.get(), "new-sample", G_CALLBACK(newTextSampleCallback), this);
 
         g_object_set(m_pipeline.get(), "text-sink", m_textAppSink.get(), NULL);
     }
@@ -2000,7 +1965,7 @@
 
     GRefPtr<GstPad> videoSinkPad = adoptGRef(gst_element_get_static_pad(m_videoSink.get(), "sink"));
     if (videoSinkPad)
-        g_signal_connect(videoSinkPad.get(), "notify::caps", G_CALLBACK(mediaPlayerPrivateVideoSinkCapsChangedCallback), this);
+        g_signal_connect_swapped(videoSinkPad.get(), "notify::caps", G_CALLBACK(videoSinkCapsChangedCallback), this);
 }
 
 void MediaPlayerPrivateGStreamer::simulateAudioInterruption()

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h (192098 => 192099)


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h	2015-11-06 11:05:55 UTC (rev 192098)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h	2015-11-06 12:56:02 UTC (rev 192099)
@@ -35,7 +35,6 @@
 #include <wtf/Forward.h>
 #include <wtf/RunLoop.h>
 #include <wtf/WeakPtr.h>
-#include <wtf/glib/GThreadSafeMainLoopSource.h>
 
 #if ENABLE(VIDEO_TRACK) && USE(GSTREAMER_MPEGTS)
 #include <wtf/text/AtomicStringHash.h>
@@ -115,26 +114,9 @@
     void durationChanged();
     void loadingFailed(MediaPlayer::NetworkState);
 
-    void videoChanged();
-    void videoCapsChanged();
-    void audioChanged();
-    void notifyPlayerOfVideo();
-    void notifyPlayerOfVideoCaps();
-    void notifyPlayerOfAudio();
-
-#if ENABLE(VIDEO_TRACK)
-    void textChanged();
-    void notifyPlayerOfText();
-
-    void newTextSample();
-    void notifyPlayerOfNewTextSample();
-#endif
-
     void sourceChanged();
     GstElement* audioSink() const override;
 
-    void setAudioStreamProperties(GObject*);
-
     void simulateAudioInterruption() override;
 
     bool changePipelineState(GstState);
@@ -191,6 +173,28 @@
 
     void readyTimerFired();
 
+    void notifyPlayerOfVideo();
+    void notifyPlayerOfVideoCaps();
+    void notifyPlayerOfAudio();
+
+#if ENABLE(VIDEO_TRACK)
+    void notifyPlayerOfText();
+    void newTextSample();
+#endif
+
+    void setAudioStreamProperties(GObject*);
+
+    static void setAudioStreamPropertiesCallback(MediaPlayerPrivateGStreamer*, GObject*);
+
+    static void sourceChangedCallback(MediaPlayerPrivateGStreamer*);
+    static void videoChangedCallback(MediaPlayerPrivateGStreamer*);
+    static void videoSinkCapsChangedCallback(MediaPlayerPrivateGStreamer*);
+    static void audioChangedCallback(MediaPlayerPrivateGStreamer*);
+#if ENABLE(VIDEO_TRACK)
+    static void textChangedCallback(MediaPlayerPrivateGStreamer*);
+    static GstFlowReturn newTextSampleCallback(MediaPlayerPrivateGStreamer*);
+#endif
+
     WeakPtrFactory<MediaPlayerPrivateGStreamer> m_weakPtrFactory;
 
     GRefPtr<GstElement> m_source;
@@ -228,10 +232,6 @@
     bool m_volumeAndMuteInitialized;
     bool m_hasVideo;
     bool m_hasAudio;
-    GThreadSafeMainLoopSource m_audioTimerHandler;
-    GThreadSafeMainLoopSource m_textTimerHandler;
-    GThreadSafeMainLoopSource m_videoTimerHandler;
-    GThreadSafeMainLoopSource m_videoCapsTimerHandler;
     RunLoop::Timer<MediaPlayerPrivateGStreamer> m_readyTimerHandler;
     mutable unsigned long long m_totalBytes;
     URL m_url;

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


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp	2015-11-06 11:05:55 UTC (rev 192098)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp	2015-11-06 12:56:02 UTC (rev 192099)
@@ -102,40 +102,11 @@
     return ABS(a);
 }
 
-static void mediaPlayerPrivateVolumeChangedCallback(GObject*, GParamSpec*, MediaPlayerPrivateGStreamerBase* player)
-{
-    // This is called when m_volumeElement receives the notify::volume signal.
-    LOG_MEDIA_MESSAGE("Volume changed to: %f", player->volume());
-    player->volumeChanged();
-}
-
-static void mediaPlayerPrivateMuteChangedCallback(GObject*, GParamSpec*, MediaPlayerPrivateGStreamerBase* player)
-{
-    // This is called when m_volumeElement receives the notify::mute signal.
-    player->muteChanged();
-}
-
-static void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstSample* sample, MediaPlayerPrivateGStreamerBase* playerPrivate)
-{
-    playerPrivate->triggerRepaint(sample);
-}
-
-#if USE(GSTREAMER_GL)
-static gboolean mediaPlayerPrivateDrawCallback(GstElement*, GstContext*, GstSample* sample, MediaPlayerPrivateGStreamerBase* playerPrivate)
-{
-    playerPrivate->triggerRepaint(sample);
-    return TRUE;
-}
-#endif
-
 MediaPlayerPrivateGStreamerBase::MediaPlayerPrivateGStreamerBase(MediaPlayer* player)
     : m_player(player)
     , m_fpsSink(0)
     , m_readyState(MediaPlayer::HaveNothing)
     , m_networkState(MediaPlayer::Empty)
-    , m_repaintHandler(0)
-    , m_volumeSignalHandler(0)
-    , m_muteSignalHandler(0)
     , m_usingFallbackVideoSink(false)
 {
     g_mutex_init(&m_sampleMutex);
@@ -147,25 +118,16 @@
 
 MediaPlayerPrivateGStreamerBase::~MediaPlayerPrivateGStreamerBase()
 {
-    if (m_repaintHandler) {
-        g_signal_handler_disconnect(m_videoSink.get(), m_repaintHandler);
-        m_repaintHandler = 0;
-    }
+    m_notifier.cancelPendingNotifications();
 
+    g_signal_handlers_disconnect_matched(m_videoSink.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this);
+
     g_mutex_clear(&m_sampleMutex);
 
     m_player = 0;
 
-    if (m_volumeSignalHandler) {
-        g_signal_handler_disconnect(m_volumeElement.get(), m_volumeSignalHandler);
-        m_volumeSignalHandler = 0;
-    }
+    g_signal_handlers_disconnect_matched(m_volumeElement.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this);
 
-    if (m_muteSignalHandler) {
-        g_signal_handler_disconnect(m_volumeElement.get(), m_muteSignalHandler);
-        m_muteSignalHandler = 0;
-    }
-
 #if USE(GSTREAMER_GL)
     g_cond_clear(&m_drawCondition);
     g_mutex_clear(&m_drawMutex);
@@ -353,10 +315,12 @@
     m_player->volumeChanged(static_cast<float>(volume));
 }
 
-void MediaPlayerPrivateGStreamerBase::volumeChanged()
+void MediaPlayerPrivateGStreamerBase::volumeChangedCallback(MediaPlayerPrivateGStreamerBase* player)
 {
-    m_volumeTimerHandler.schedule("[WebKit] MediaPlayerPrivateGStreamerBase::volumeChanged",
-        std::function<void()>([this] { notifyPlayerOfVolumeChange(); }));
+    // This is called when m_volumeElement receives the notify::volume signal.
+    LOG_MEDIA_MESSAGE("Volume changed to: %f", player->volume());
+
+    player->m_notifier.notify(MainThreadNotification::VolumeChanged, [player] { player->notifyPlayerOfVolumeChange(); });
 }
 
 MediaPlayer::NetworkState MediaPlayerPrivateGStreamerBase::networkState() const
@@ -402,10 +366,10 @@
     m_player->muteChanged(static_cast<bool>(muted));
 }
 
-void MediaPlayerPrivateGStreamerBase::muteChanged()
+void MediaPlayerPrivateGStreamerBase::muteChangedCallback(MediaPlayerPrivateGStreamerBase* player)
 {
-    m_muteTimerHandler.schedule("[WebKit] MediaPlayerPrivateGStreamerBase::muteChanged",
-        std::function<void()>([this] { notifyPlayerOfMute(); }));
+    // This is called when m_volumeElement receives the notify::mute signal.
+    player->m_notifier.notify(MainThreadNotification::MuteChanged, [player] { player->notifyPlayerOfMute(); });
 }
 
 #if USE(TEXTURE_MAPPER_GL) && !USE(COORDINATED_GRAPHICS)
@@ -493,6 +457,19 @@
     m_player->repaint();
 }
 
+void MediaPlayerPrivateGStreamerBase::repaintCallback(MediaPlayerPrivateGStreamerBase* player, GstSample* sample)
+{
+    player->triggerRepaint(sample);
+}
+
+#if USE(GSTREAMER_GL)
+gboolean MediaPlayerPrivateGStreamerBase::drawCallback(MediaPlayerPrivateGStreamerBase* player, GstContext*, GstSample* sample)
+{
+    player->triggerRepaint(sample);
+    return TRUE;
+}
+#endif
+
 void MediaPlayerPrivateGStreamerBase::setSize(const IntSize& size)
 {
     m_size = size;
@@ -592,7 +569,7 @@
     if (webkitGstCheckVersion(1, 5, 0)) {
         m_videoSink = gst_element_factory_make("glimagesink", nullptr);
         if (m_videoSink) {
-            m_repaintHandler = g_signal_connect(m_videoSink.get(), "client-draw", G_CALLBACK(mediaPlayerPrivateDrawCallback), this);
+            g_signal_connect_swapped(m_videoSink.get(), "client-draw", G_CALLBACK(drawCallback), this);
             videoSink = m_videoSink.get();
         }
     }
@@ -601,7 +578,7 @@
     if (!m_videoSink) {
         m_usingFallbackVideoSink = true;
         m_videoSink = webkitVideoSinkNew();
-        m_repaintHandler = g_signal_connect(m_videoSink.get(), "repaint-requested", G_CALLBACK(mediaPlayerPrivateRepaintCallback), this);
+        g_signal_connect_swapped(m_videoSink.get(), "repaint-requested", G_CALLBACK(repaintCallback), this);
     }
 
     m_fpsSink = gst_element_factory_make("fpsdisplaysink", "sink");
@@ -647,8 +624,8 @@
     LOG_MEDIA_MESSAGE("Setting stream muted %d",  m_player->muted());
     g_object_set(m_volumeElement.get(), "mute", m_player->muted(), NULL);
 
-    m_volumeSignalHandler = g_signal_connect(m_volumeElement.get(), "notify::volume", G_CALLBACK(mediaPlayerPrivateVolumeChangedCallback), this);
-    m_muteSignalHandler = g_signal_connect(m_volumeElement.get(), "notify::mute", G_CALLBACK(mediaPlayerPrivateMuteChangedCallback), this);
+    g_signal_connect_swapped(m_volumeElement.get(), "notify::volume", G_CALLBACK(volumeChangedCallback), this);
+    g_signal_connect_swapped(m_volumeElement.get(), "notify::mute", G_CALLBACK(muteChangedCallback), this);
 }
 
 unsigned MediaPlayerPrivateGStreamerBase::decodedFrameCount() const

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


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h	2015-11-06 11:05:55 UTC (rev 192098)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h	2015-11-06 12:56:02 UTC (rev 192099)
@@ -25,10 +25,9 @@
 #if ENABLE(VIDEO) && USE(GSTREAMER)
 
 #include "GRefPtrGStreamer.h"
+#include "MainThreadNotifier.h"
 #include "MediaPlayerPrivate.h"
-
 #include <glib.h>
-
 #include <wtf/Forward.h>
 #include <wtf/glib/GThreadSafeMainLoopSource.h>
 
@@ -60,8 +59,6 @@
 
     void setVolume(float);
     float volume() const;
-    void volumeChanged();
-    void notifyPlayerOfVolumeChange();
 
 #if USE(GSTREAMER_GL)
     bool ensureGstGLContext();
@@ -70,8 +67,6 @@
     bool supportsMuting() const { return true; }
     void setMuted(bool);
     bool muted() const;
-    void muteChanged();
-    void notifyPlayerOfMute();
 
     MediaPlayer::NetworkState networkState() const;
     MediaPlayer::ReadyState readyState() const;
@@ -80,7 +75,6 @@
     void setSize(const IntSize&);
     void sizeChanged();
 
-    void triggerRepaint(GstSample*);
     void paint(GraphicsContext&, const FloatRect&);
 
     virtual bool hasSingleSecurityOrigin() const { return true; }
@@ -122,6 +116,31 @@
 
     virtual bool handleSyncMessage(GstMessage*);
 
+    void triggerRepaint(GstSample*);
+
+    static void repaintCallback(MediaPlayerPrivateGStreamerBase*, GstSample*);
+#if USE(GSTREAMER_GL)
+    static gboolean drawCallback(MediaPlayerPrivateGStreamerBase*, GstContext*, GstSample*);
+#endif
+
+    void notifyPlayerOfVolumeChange();
+    void notifyPlayerOfMute();
+
+    static void volumeChangedCallback(MediaPlayerPrivateGStreamerBase*);
+    static void muteChangedCallback(MediaPlayerPrivateGStreamerBase*);
+
+    enum MainThreadNotification {
+        VideoChanged = 1 << 0,
+        VideoCapsChanged = 1 << 1,
+        AudioChanged = 1 << 2,
+        VolumeChanged = 1 << 3,
+        MuteChanged = 1 << 4,
+#if ENABLE(VIDEO_TRACK)
+        TextChanged = 1 << 5,
+#endif
+    };
+
+    MainThreadNotifier<MainThreadNotification> m_notifier;
     MediaPlayer* m_player;
     GRefPtr<GstElement> m_pipeline;
     GRefPtr<GstStreamVolume> m_volumeElement;
@@ -132,16 +151,11 @@
     IntSize m_size;
     mutable GMutex m_sampleMutex;
     GRefPtr<GstSample> m_sample;
-    GThreadSafeMainLoopSource m_volumeTimerHandler;
-    GThreadSafeMainLoopSource m_muteTimerHandler;
 #if USE(GSTREAMER_GL)
     GThreadSafeMainLoopSource m_drawTimerHandler;
     GCond m_drawCondition;
     GMutex m_drawMutex;
 #endif
-    unsigned long m_repaintHandler;
-    unsigned long m_volumeSignalHandler;
-    unsigned long m_muteSignalHandler;
     mutable FloatSize m_videoSize;
     bool m_usingFallbackVideoSink;
 #if USE(TEXTURE_MAPPER_GL) && !USE(COORDINATED_GRAPHICS)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to