<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[192099] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/192099">192099</a></dd>
<dt>Author</dt> <dd>carlosgc@webkit.org</dd>
<dt>Date</dt> <dd>2015-11-06 04:56:02 -0800 (Fri, 06 Nov 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>[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.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsgstreamerMediaPlayerPrivateGStreamercpp">trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsgstreamerMediaPlayerPrivateGStreamerh">trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsgstreamerMediaPlayerPrivateGStreamerBasecpp">trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsgstreamerMediaPlayerPrivateGStreamerBaseh">trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreplatformgraphicsgstreamerMainThreadNotifierh">trunk/Source/WebCore/platform/graphics/gstreamer/MainThreadNotifier.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (192098 => 192099)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,3 +1,78 @@
</span><ins>+2015-11-06  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
+
+        [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.
+
</ins><span class="cx"> 2015-11-06  Yoav Weiss  &lt;yoav@yoav.ws&gt;
</span><span class="cx"> 
</span><span class="cx">         Expose HTMLImageElement sizes attribute in IDL
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsgstreamerMainThreadNotifierh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/platform/graphics/gstreamer/MainThreadNotifier.h (0 => 192099)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,95 @@
</span><ins>+/*
+ *  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 &lt;wtf/Lock.h&gt;
+#include &lt;wtf/MainThread.h&gt;
+#include &lt;wtf/RunLoop.h&gt;
+#include &lt;wtf/WeakPtr.h&gt;
+
+namespace WebCore {
+
+template &lt;typename T&gt;
+class MainThreadNotifier {
+public:
+    MainThreadNotifier()
+        : m_weakPtrFactory(this)
+    {
+    }
+
+    template&lt;typename F&gt;
+    void notify(T notificationType, const F&amp; callbackFunctor)
+    {
+        if (isMainThread()) {
+            removePendingNotification(notificationType);
+            callbackFunctor();
+            return;
+        }
+
+        if (!addPendingNotification(notificationType))
+            return;
+
+        auto weakThis = m_weakPtrFactory.createWeakPtr();
+        std::function&lt;void ()&gt; callback(callbackFunctor);
+        RunLoop::main().dispatch([weakThis, notificationType, callback] {
+            if (weakThis &amp;&amp; weakThis-&gt;removePendingNotification(notificationType))
+                callback();
+        });
+    }
+
+    void cancelPendingNotifications(unsigned mask = 0)
+    {
+        LockHolder locker(m_pendingNotificationsLock);
+        if (mask)
+            m_pendingNotifications &amp;= ~mask;
+        else
+            m_pendingNotifications = 0;
+    }
+
+private:
+
+    bool addPendingNotification(T notificationType)
+    {
+        LockHolder locker(m_pendingNotificationsLock);
+        if (notificationType &amp; m_pendingNotifications)
+            return false;
+        m_pendingNotifications |= notificationType;
+        return true;
+    }
+
+    bool removePendingNotification(T notificationType)
+    {
+        LockHolder locker(m_pendingNotificationsLock);
+        if (notificationType &amp; m_pendingNotifications) {
+            m_pendingNotifications &amp;= ~notificationType;
+            return true;
+        }
+        return false;
+    }
+
+    WeakPtrFactory&lt;MainThreadNotifier&gt; m_weakPtrFactory;
+    Lock m_pendingNotificationsLock;
+    unsigned m_pendingNotifications { 0 };
+};
+
+
+} // namespace WebCore
+
+#endif // MainThreadNotifier_h
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsgstreamerMediaPlayerPrivateGStreamercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp (192098 => 192099)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -76,45 +76,11 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-static void mediaPlayerPrivateSourceChangedCallback(GObject*, GParamSpec*, MediaPlayerPrivateGStreamer* player)
</del><ins>+void MediaPlayerPrivateGStreamer::setAudioStreamPropertiesCallback(MediaPlayerPrivateGStreamer* player, GObject* object)
</ins><span class="cx"> {
</span><del>-    player-&gt;sourceChanged();
-}
-
-static void mediaPlayerPrivateVideoSinkCapsChangedCallback(GObject*, GParamSpec*, MediaPlayerPrivateGStreamer* player)
-{
-    player-&gt;videoCapsChanged();
-}
-
-static void mediaPlayerPrivateVideoChangedCallback(GObject*, MediaPlayerPrivateGStreamer* player)
-{
-    player-&gt;videoChanged();
-}
-
-static void mediaPlayerPrivateAudioChangedCallback(GObject*, MediaPlayerPrivateGStreamer* player)
-{
-    player-&gt;audioChanged();
-}
-
-static void setAudioStreamPropertiesCallback(GstChildProxy*, GObject* object, gchar*,
-    MediaPlayerPrivateGStreamer* player)
-{
</del><span class="cx">     player-&gt;setAudioStreamProperties(object);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-#if ENABLE(VIDEO_TRACK)
-static void mediaPlayerPrivateTextChangedCallback(GObject*, MediaPlayerPrivateGStreamer* player)
-{
-    player-&gt;textChanged();
-}
-
-static GstFlowReturn mediaPlayerPrivateNewTextSampleCallback(GObject*, MediaPlayerPrivateGStreamer* player)
-{
-    player-&gt;newTextSample();
-    return GST_FLOW_OK;
-}
-#endif
-
</del><span class="cx"> void MediaPlayerPrivateGStreamer::setAudioStreamProperties(GObject* object)
</span><span class="cx"> {
</span><span class="cx">     if (g_strcmp0(G_OBJECT_TYPE_NAME(object), &quot;GstPulseSink&quot;))
</span><span class="lines">@@ -244,21 +210,13 @@
</span><span class="cx">         GRefPtr&lt;GstBus&gt; bus = adoptGRef(gst_pipeline_get_bus(GST_PIPELINE(m_pipeline.get())));
</span><span class="cx">         ASSERT(bus);
</span><span class="cx">         gst_bus_set_sync_handler(bus.get(), nullptr, nullptr, nullptr);
</span><del>-
-        g_signal_handlers_disconnect_by_func(m_pipeline.get(), reinterpret_cast&lt;gpointer&gt;(mediaPlayerPrivateSourceChangedCallback), this);
-        g_signal_handlers_disconnect_by_func(m_pipeline.get(), reinterpret_cast&lt;gpointer&gt;(mediaPlayerPrivateVideoChangedCallback), this);
-        g_signal_handlers_disconnect_by_func(m_pipeline.get(), reinterpret_cast&lt;gpointer&gt;(mediaPlayerPrivateAudioChangedCallback), this);
-#if ENABLE(VIDEO_TRACK)
-        g_signal_handlers_disconnect_by_func(m_pipeline.get(), reinterpret_cast&lt;gpointer&gt;(mediaPlayerPrivateNewTextSampleCallback), this);
-        g_signal_handlers_disconnect_by_func(m_pipeline.get(), reinterpret_cast&lt;gpointer&gt;(mediaPlayerPrivateTextChangedCallback), this);
-#endif
-
</del><ins>+        g_signal_handlers_disconnect_matched(m_pipeline.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this);
</ins><span class="cx">         gst_element_set_state(m_pipeline.get(), GST_STATE_NULL);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (m_videoSink) {
</span><span class="cx">         GRefPtr&lt;GstPad&gt; videoSinkPad = adoptGRef(gst_element_get_static_pad(m_videoSink.get(), &quot;sink&quot;));
</span><del>-        g_signal_handlers_disconnect_by_func(videoSinkPad.get(), reinterpret_cast&lt;gpointer&gt;(mediaPlayerPrivateVideoSinkCapsChangedCallback), this);
</del><ins>+        g_signal_handlers_disconnect_by_func(videoSinkPad.get(), reinterpret_cast&lt;gpointer&gt;(videoSinkCapsChangedCallback), this);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -649,18 +607,11 @@
</span><span class="cx">     return m_seeking;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MediaPlayerPrivateGStreamer::videoChanged()
</del><ins>+void MediaPlayerPrivateGStreamer::videoChangedCallback(MediaPlayerPrivateGStreamer* player)
</ins><span class="cx"> {
</span><del>-    m_videoTimerHandler.schedule(&quot;[WebKit] MediaPlayerPrivateGStreamer::videoChanged&quot;,
-        std::function&lt;void()&gt;([this] { notifyPlayerOfVideo(); }));
</del><ins>+    player-&gt;m_notifier.notify(MainThreadNotification::VideoChanged, [player] { player-&gt;notifyPlayerOfVideo(); });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MediaPlayerPrivateGStreamer::videoCapsChanged()
-{
-    m_videoCapsTimerHandler.schedule(&quot;[WebKit] MediaPlayerPrivateGStreamer::videoCapsChanged&quot;,
-        std::function&lt;void()&gt;([this] { notifyPlayerOfVideoCaps(); }));
-}
-
</del><span class="cx"> void MediaPlayerPrivateGStreamer::notifyPlayerOfVideo()
</span><span class="cx"> {
</span><span class="cx">     gint numTracks = 0;
</span><span class="lines">@@ -698,16 +649,20 @@
</span><span class="cx">     m_player-&gt;client().mediaPlayerEngineUpdated(m_player);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaPlayerPrivateGStreamer::videoSinkCapsChangedCallback(MediaPlayerPrivateGStreamer* player)
+{
+    player-&gt;m_notifier.notify(MainThreadNotification::VideoCapsChanged, [player] { player-&gt;notifyPlayerOfVideoCaps(); });
+}
+
</ins><span class="cx"> void MediaPlayerPrivateGStreamer::notifyPlayerOfVideoCaps()
</span><span class="cx"> {
</span><span class="cx">     m_videoSize = IntSize();
</span><span class="cx">     m_player-&gt;client().mediaPlayerEngineUpdated(m_player);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MediaPlayerPrivateGStreamer::audioChanged()
</del><ins>+void MediaPlayerPrivateGStreamer::audioChangedCallback(MediaPlayerPrivateGStreamer* player)
</ins><span class="cx"> {
</span><del>-    m_audioTimerHandler.schedule(&quot;[WebKit] MediaPlayerPrivateGStreamer::audioChanged&quot;,
-        std::function&lt;void()&gt;([this] { notifyPlayerOfAudio(); }));
</del><ins>+    player-&gt;m_notifier.notify(MainThreadNotification::AudioChanged, [player] { player-&gt;notifyPlayerOfAudio(); });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateGStreamer::notifyPlayerOfAudio()
</span><span class="lines">@@ -748,10 +703,9 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(VIDEO_TRACK)
</span><del>-void MediaPlayerPrivateGStreamer::textChanged()
</del><ins>+void MediaPlayerPrivateGStreamer::textChangedCallback(MediaPlayerPrivateGStreamer* player)
</ins><span class="cx"> {
</span><del>-    m_textTimerHandler.schedule(&quot;[WebKit] MediaPlayerPrivateGStreamer::textChanged&quot;,
-        std::function&lt;void()&gt;([this] { notifyPlayerOfText(); }));
</del><ins>+    player-&gt;m_notifier.notify(MainThreadNotification::TextChanged, [player] { player-&gt;notifyPlayerOfText(); });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateGStreamer::notifyPlayerOfText()
</span><span class="lines">@@ -785,6 +739,12 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+GstFlowReturn MediaPlayerPrivateGStreamer::newTextSampleCallback(MediaPlayerPrivateGStreamer* player)
+{
+    player-&gt;newTextSample();
+    return GST_FLOW_OK;
+}
+
</ins><span class="cx"> void MediaPlayerPrivateGStreamer::newTextSample()
</span><span class="cx"> {
</span><span class="cx">     if (!m_textAppSink)
</span><span class="lines">@@ -1318,6 +1278,11 @@
</span><span class="cx">     return m_totalBytes;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaPlayerPrivateGStreamer::sourceChangedCallback(MediaPlayerPrivateGStreamer* player)
+{
+    player-&gt;sourceChanged();
+}
+
</ins><span class="cx"> void MediaPlayerPrivateGStreamer::sourceChanged()
</span><span class="cx"> {
</span><span class="cx">     m_source.clear();
</span><span class="lines">@@ -1868,7 +1833,7 @@
</span><span class="cx">         return nullptr;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    g_signal_connect(m_autoAudioSink.get(), &quot;child-added&quot;, G_CALLBACK(setAudioStreamPropertiesCallback), this);
</del><ins>+    g_signal_connect_swapped(m_autoAudioSink.get(), &quot;child-added&quot;, G_CALLBACK(setAudioStreamPropertiesCallback), this);
</ins><span class="cx"> 
</span><span class="cx">     GstElement* audioSinkBin;
</span><span class="cx"> 
</span><span class="lines">@@ -1960,12 +1925,12 @@
</span><span class="cx"> 
</span><span class="cx">     g_object_set(m_pipeline.get(), &quot;mute&quot;, m_player-&gt;muted(), nullptr);
</span><span class="cx"> 
</span><del>-    g_signal_connect(m_pipeline.get(), &quot;notify::source&quot;, G_CALLBACK(mediaPlayerPrivateSourceChangedCallback), this);
-    g_signal_connect(m_pipeline.get(), &quot;video-changed&quot;, G_CALLBACK(mediaPlayerPrivateVideoChangedCallback), this);
-    g_signal_connect(m_pipeline.get(), &quot;audio-changed&quot;, G_CALLBACK(mediaPlayerPrivateAudioChangedCallback), this);
</del><ins>+    g_signal_connect_swapped(m_pipeline.get(), &quot;notify::source&quot;, G_CALLBACK(sourceChangedCallback), this);
+    g_signal_connect_swapped(m_pipeline.get(), &quot;video-changed&quot;, G_CALLBACK(videoChangedCallback), this);
+    g_signal_connect_swapped(m_pipeline.get(), &quot;audio-changed&quot;, G_CALLBACK(audioChangedCallback), this);
</ins><span class="cx"> #if ENABLE(VIDEO_TRACK)
</span><span class="cx">     if (webkitGstCheckVersion(1, 1, 2)) {
</span><del>-        g_signal_connect(m_pipeline.get(), &quot;text-changed&quot;, G_CALLBACK(mediaPlayerPrivateTextChangedCallback), this);
</del><ins>+        g_signal_connect_swapped(m_pipeline.get(), &quot;text-changed&quot;, G_CALLBACK(textChangedCallback), this);
</ins><span class="cx"> 
</span><span class="cx">         GstElement* textCombiner = webkitTextCombinerNew();
</span><span class="cx">         ASSERT(textCombiner);
</span><span class="lines">@@ -1978,7 +1943,7 @@
</span><span class="cx">         ASSERT(m_textAppSinkPad);
</span><span class="cx"> 
</span><span class="cx">         g_object_set(m_textAppSink.get(), &quot;emit-signals&quot;, true, &quot;enable-last-sample&quot;, false, &quot;caps&quot;, gst_caps_new_empty_simple(&quot;text/vtt&quot;), NULL);
</span><del>-        g_signal_connect(m_textAppSink.get(), &quot;new-sample&quot;, G_CALLBACK(mediaPlayerPrivateNewTextSampleCallback), this);
</del><ins>+        g_signal_connect_swapped(m_textAppSink.get(), &quot;new-sample&quot;, G_CALLBACK(newTextSampleCallback), this);
</ins><span class="cx"> 
</span><span class="cx">         g_object_set(m_pipeline.get(), &quot;text-sink&quot;, m_textAppSink.get(), NULL);
</span><span class="cx">     }
</span><span class="lines">@@ -2000,7 +1965,7 @@
</span><span class="cx"> 
</span><span class="cx">     GRefPtr&lt;GstPad&gt; videoSinkPad = adoptGRef(gst_element_get_static_pad(m_videoSink.get(), &quot;sink&quot;));
</span><span class="cx">     if (videoSinkPad)
</span><del>-        g_signal_connect(videoSinkPad.get(), &quot;notify::caps&quot;, G_CALLBACK(mediaPlayerPrivateVideoSinkCapsChangedCallback), this);
</del><ins>+        g_signal_connect_swapped(videoSinkPad.get(), &quot;notify::caps&quot;, G_CALLBACK(videoSinkCapsChangedCallback), this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void MediaPlayerPrivateGStreamer::simulateAudioInterruption()
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsgstreamerMediaPlayerPrivateGStreamerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h (192098 => 192099)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -35,7 +35,6 @@
</span><span class="cx"> #include &lt;wtf/Forward.h&gt;
</span><span class="cx"> #include &lt;wtf/RunLoop.h&gt;
</span><span class="cx"> #include &lt;wtf/WeakPtr.h&gt;
</span><del>-#include &lt;wtf/glib/GThreadSafeMainLoopSource.h&gt;
</del><span class="cx"> 
</span><span class="cx"> #if ENABLE(VIDEO_TRACK) &amp;&amp; USE(GSTREAMER_MPEGTS)
</span><span class="cx"> #include &lt;wtf/text/AtomicStringHash.h&gt;
</span><span class="lines">@@ -115,26 +114,9 @@
</span><span class="cx">     void durationChanged();
</span><span class="cx">     void loadingFailed(MediaPlayer::NetworkState);
</span><span class="cx"> 
</span><del>-    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
-
</del><span class="cx">     void sourceChanged();
</span><span class="cx">     GstElement* audioSink() const override;
</span><span class="cx"> 
</span><del>-    void setAudioStreamProperties(GObject*);
-
</del><span class="cx">     void simulateAudioInterruption() override;
</span><span class="cx"> 
</span><span class="cx">     bool changePipelineState(GstState);
</span><span class="lines">@@ -191,6 +173,28 @@
</span><span class="cx"> 
</span><span class="cx">     void readyTimerFired();
</span><span class="cx"> 
</span><ins>+    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
+
</ins><span class="cx">     WeakPtrFactory&lt;MediaPlayerPrivateGStreamer&gt; m_weakPtrFactory;
</span><span class="cx"> 
</span><span class="cx">     GRefPtr&lt;GstElement&gt; m_source;
</span><span class="lines">@@ -228,10 +232,6 @@
</span><span class="cx">     bool m_volumeAndMuteInitialized;
</span><span class="cx">     bool m_hasVideo;
</span><span class="cx">     bool m_hasAudio;
</span><del>-    GThreadSafeMainLoopSource m_audioTimerHandler;
-    GThreadSafeMainLoopSource m_textTimerHandler;
-    GThreadSafeMainLoopSource m_videoTimerHandler;
-    GThreadSafeMainLoopSource m_videoCapsTimerHandler;
</del><span class="cx">     RunLoop::Timer&lt;MediaPlayerPrivateGStreamer&gt; m_readyTimerHandler;
</span><span class="cx">     mutable unsigned long long m_totalBytes;
</span><span class="cx">     URL m_url;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsgstreamerMediaPlayerPrivateGStreamerBasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp (192098 => 192099)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -102,40 +102,11 @@
</span><span class="cx">     return ABS(a);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void mediaPlayerPrivateVolumeChangedCallback(GObject*, GParamSpec*, MediaPlayerPrivateGStreamerBase* player)
-{
-    // This is called when m_volumeElement receives the notify::volume signal.
-    LOG_MEDIA_MESSAGE(&quot;Volume changed to: %f&quot;, player-&gt;volume());
-    player-&gt;volumeChanged();
-}
-
-static void mediaPlayerPrivateMuteChangedCallback(GObject*, GParamSpec*, MediaPlayerPrivateGStreamerBase* player)
-{
-    // This is called when m_volumeElement receives the notify::mute signal.
-    player-&gt;muteChanged();
-}
-
-static void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstSample* sample, MediaPlayerPrivateGStreamerBase* playerPrivate)
-{
-    playerPrivate-&gt;triggerRepaint(sample);
-}
-
-#if USE(GSTREAMER_GL)
-static gboolean mediaPlayerPrivateDrawCallback(GstElement*, GstContext*, GstSample* sample, MediaPlayerPrivateGStreamerBase* playerPrivate)
-{
-    playerPrivate-&gt;triggerRepaint(sample);
-    return TRUE;
-}
-#endif
-
</del><span class="cx"> MediaPlayerPrivateGStreamerBase::MediaPlayerPrivateGStreamerBase(MediaPlayer* player)
</span><span class="cx">     : m_player(player)
</span><span class="cx">     , m_fpsSink(0)
</span><span class="cx">     , m_readyState(MediaPlayer::HaveNothing)
</span><span class="cx">     , m_networkState(MediaPlayer::Empty)
</span><del>-    , m_repaintHandler(0)
-    , m_volumeSignalHandler(0)
-    , m_muteSignalHandler(0)
</del><span class="cx">     , m_usingFallbackVideoSink(false)
</span><span class="cx"> {
</span><span class="cx">     g_mutex_init(&amp;m_sampleMutex);
</span><span class="lines">@@ -147,25 +118,16 @@
</span><span class="cx"> 
</span><span class="cx"> MediaPlayerPrivateGStreamerBase::~MediaPlayerPrivateGStreamerBase()
</span><span class="cx"> {
</span><del>-    if (m_repaintHandler) {
-        g_signal_handler_disconnect(m_videoSink.get(), m_repaintHandler);
-        m_repaintHandler = 0;
-    }
</del><ins>+    m_notifier.cancelPendingNotifications();
</ins><span class="cx"> 
</span><ins>+    g_signal_handlers_disconnect_matched(m_videoSink.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this);
+
</ins><span class="cx">     g_mutex_clear(&amp;m_sampleMutex);
</span><span class="cx"> 
</span><span class="cx">     m_player = 0;
</span><span class="cx"> 
</span><del>-    if (m_volumeSignalHandler) {
-        g_signal_handler_disconnect(m_volumeElement.get(), m_volumeSignalHandler);
-        m_volumeSignalHandler = 0;
-    }
</del><ins>+    g_signal_handlers_disconnect_matched(m_volumeElement.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this);
</ins><span class="cx"> 
</span><del>-    if (m_muteSignalHandler) {
-        g_signal_handler_disconnect(m_volumeElement.get(), m_muteSignalHandler);
-        m_muteSignalHandler = 0;
-    }
-
</del><span class="cx"> #if USE(GSTREAMER_GL)
</span><span class="cx">     g_cond_clear(&amp;m_drawCondition);
</span><span class="cx">     g_mutex_clear(&amp;m_drawMutex);
</span><span class="lines">@@ -353,10 +315,12 @@
</span><span class="cx">     m_player-&gt;volumeChanged(static_cast&lt;float&gt;(volume));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MediaPlayerPrivateGStreamerBase::volumeChanged()
</del><ins>+void MediaPlayerPrivateGStreamerBase::volumeChangedCallback(MediaPlayerPrivateGStreamerBase* player)
</ins><span class="cx"> {
</span><del>-    m_volumeTimerHandler.schedule(&quot;[WebKit] MediaPlayerPrivateGStreamerBase::volumeChanged&quot;,
-        std::function&lt;void()&gt;([this] { notifyPlayerOfVolumeChange(); }));
</del><ins>+    // This is called when m_volumeElement receives the notify::volume signal.
+    LOG_MEDIA_MESSAGE(&quot;Volume changed to: %f&quot;, player-&gt;volume());
+
+    player-&gt;m_notifier.notify(MainThreadNotification::VolumeChanged, [player] { player-&gt;notifyPlayerOfVolumeChange(); });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MediaPlayer::NetworkState MediaPlayerPrivateGStreamerBase::networkState() const
</span><span class="lines">@@ -402,10 +366,10 @@
</span><span class="cx">     m_player-&gt;muteChanged(static_cast&lt;bool&gt;(muted));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MediaPlayerPrivateGStreamerBase::muteChanged()
</del><ins>+void MediaPlayerPrivateGStreamerBase::muteChangedCallback(MediaPlayerPrivateGStreamerBase* player)
</ins><span class="cx"> {
</span><del>-    m_muteTimerHandler.schedule(&quot;[WebKit] MediaPlayerPrivateGStreamerBase::muteChanged&quot;,
-        std::function&lt;void()&gt;([this] { notifyPlayerOfMute(); }));
</del><ins>+    // This is called when m_volumeElement receives the notify::mute signal.
+    player-&gt;m_notifier.notify(MainThreadNotification::MuteChanged, [player] { player-&gt;notifyPlayerOfMute(); });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if USE(TEXTURE_MAPPER_GL) &amp;&amp; !USE(COORDINATED_GRAPHICS)
</span><span class="lines">@@ -493,6 +457,19 @@
</span><span class="cx">     m_player-&gt;repaint();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MediaPlayerPrivateGStreamerBase::repaintCallback(MediaPlayerPrivateGStreamerBase* player, GstSample* sample)
+{
+    player-&gt;triggerRepaint(sample);
+}
+
+#if USE(GSTREAMER_GL)
+gboolean MediaPlayerPrivateGStreamerBase::drawCallback(MediaPlayerPrivateGStreamerBase* player, GstContext*, GstSample* sample)
+{
+    player-&gt;triggerRepaint(sample);
+    return TRUE;
+}
+#endif
+
</ins><span class="cx"> void MediaPlayerPrivateGStreamerBase::setSize(const IntSize&amp; size)
</span><span class="cx"> {
</span><span class="cx">     m_size = size;
</span><span class="lines">@@ -592,7 +569,7 @@
</span><span class="cx">     if (webkitGstCheckVersion(1, 5, 0)) {
</span><span class="cx">         m_videoSink = gst_element_factory_make(&quot;glimagesink&quot;, nullptr);
</span><span class="cx">         if (m_videoSink) {
</span><del>-            m_repaintHandler = g_signal_connect(m_videoSink.get(), &quot;client-draw&quot;, G_CALLBACK(mediaPlayerPrivateDrawCallback), this);
</del><ins>+            g_signal_connect_swapped(m_videoSink.get(), &quot;client-draw&quot;, G_CALLBACK(drawCallback), this);
</ins><span class="cx">             videoSink = m_videoSink.get();
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -601,7 +578,7 @@
</span><span class="cx">     if (!m_videoSink) {
</span><span class="cx">         m_usingFallbackVideoSink = true;
</span><span class="cx">         m_videoSink = webkitVideoSinkNew();
</span><del>-        m_repaintHandler = g_signal_connect(m_videoSink.get(), &quot;repaint-requested&quot;, G_CALLBACK(mediaPlayerPrivateRepaintCallback), this);
</del><ins>+        g_signal_connect_swapped(m_videoSink.get(), &quot;repaint-requested&quot;, G_CALLBACK(repaintCallback), this);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     m_fpsSink = gst_element_factory_make(&quot;fpsdisplaysink&quot;, &quot;sink&quot;);
</span><span class="lines">@@ -647,8 +624,8 @@
</span><span class="cx">     LOG_MEDIA_MESSAGE(&quot;Setting stream muted %d&quot;,  m_player-&gt;muted());
</span><span class="cx">     g_object_set(m_volumeElement.get(), &quot;mute&quot;, m_player-&gt;muted(), NULL);
</span><span class="cx"> 
</span><del>-    m_volumeSignalHandler = g_signal_connect(m_volumeElement.get(), &quot;notify::volume&quot;, G_CALLBACK(mediaPlayerPrivateVolumeChangedCallback), this);
-    m_muteSignalHandler = g_signal_connect(m_volumeElement.get(), &quot;notify::mute&quot;, G_CALLBACK(mediaPlayerPrivateMuteChangedCallback), this);
</del><ins>+    g_signal_connect_swapped(m_volumeElement.get(), &quot;notify::volume&quot;, G_CALLBACK(volumeChangedCallback), this);
+    g_signal_connect_swapped(m_volumeElement.get(), &quot;notify::mute&quot;, G_CALLBACK(muteChangedCallback), this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> unsigned MediaPlayerPrivateGStreamerBase::decodedFrameCount() const
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsgstreamerMediaPlayerPrivateGStreamerBaseh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.h (192098 => 192099)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -25,10 +25,9 @@
</span><span class="cx"> #if ENABLE(VIDEO) &amp;&amp; USE(GSTREAMER)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;GRefPtrGStreamer.h&quot;
</span><ins>+#include &quot;MainThreadNotifier.h&quot;
</ins><span class="cx"> #include &quot;MediaPlayerPrivate.h&quot;
</span><del>-
</del><span class="cx"> #include &lt;glib.h&gt;
</span><del>-
</del><span class="cx"> #include &lt;wtf/Forward.h&gt;
</span><span class="cx"> #include &lt;wtf/glib/GThreadSafeMainLoopSource.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -60,8 +59,6 @@
</span><span class="cx"> 
</span><span class="cx">     void setVolume(float);
</span><span class="cx">     float volume() const;
</span><del>-    void volumeChanged();
-    void notifyPlayerOfVolumeChange();
</del><span class="cx"> 
</span><span class="cx"> #if USE(GSTREAMER_GL)
</span><span class="cx">     bool ensureGstGLContext();
</span><span class="lines">@@ -70,8 +67,6 @@
</span><span class="cx">     bool supportsMuting() const { return true; }
</span><span class="cx">     void setMuted(bool);
</span><span class="cx">     bool muted() const;
</span><del>-    void muteChanged();
-    void notifyPlayerOfMute();
</del><span class="cx"> 
</span><span class="cx">     MediaPlayer::NetworkState networkState() const;
</span><span class="cx">     MediaPlayer::ReadyState readyState() const;
</span><span class="lines">@@ -80,7 +75,6 @@
</span><span class="cx">     void setSize(const IntSize&amp;);
</span><span class="cx">     void sizeChanged();
</span><span class="cx"> 
</span><del>-    void triggerRepaint(GstSample*);
</del><span class="cx">     void paint(GraphicsContext&amp;, const FloatRect&amp;);
</span><span class="cx"> 
</span><span class="cx">     virtual bool hasSingleSecurityOrigin() const { return true; }
</span><span class="lines">@@ -122,6 +116,31 @@
</span><span class="cx"> 
</span><span class="cx">     virtual bool handleSyncMessage(GstMessage*);
</span><span class="cx"> 
</span><ins>+    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 &lt;&lt; 0,
+        VideoCapsChanged = 1 &lt;&lt; 1,
+        AudioChanged = 1 &lt;&lt; 2,
+        VolumeChanged = 1 &lt;&lt; 3,
+        MuteChanged = 1 &lt;&lt; 4,
+#if ENABLE(VIDEO_TRACK)
+        TextChanged = 1 &lt;&lt; 5,
+#endif
+    };
+
+    MainThreadNotifier&lt;MainThreadNotification&gt; m_notifier;
</ins><span class="cx">     MediaPlayer* m_player;
</span><span class="cx">     GRefPtr&lt;GstElement&gt; m_pipeline;
</span><span class="cx">     GRefPtr&lt;GstStreamVolume&gt; m_volumeElement;
</span><span class="lines">@@ -132,16 +151,11 @@
</span><span class="cx">     IntSize m_size;
</span><span class="cx">     mutable GMutex m_sampleMutex;
</span><span class="cx">     GRefPtr&lt;GstSample&gt; m_sample;
</span><del>-    GThreadSafeMainLoopSource m_volumeTimerHandler;
-    GThreadSafeMainLoopSource m_muteTimerHandler;
</del><span class="cx"> #if USE(GSTREAMER_GL)
</span><span class="cx">     GThreadSafeMainLoopSource m_drawTimerHandler;
</span><span class="cx">     GCond m_drawCondition;
</span><span class="cx">     GMutex m_drawMutex;
</span><span class="cx"> #endif
</span><del>-    unsigned long m_repaintHandler;
-    unsigned long m_volumeSignalHandler;
-    unsigned long m_muteSignalHandler;
</del><span class="cx">     mutable FloatSize m_videoSize;
</span><span class="cx">     bool m_usingFallbackVideoSink;
</span><span class="cx"> #if USE(TEXTURE_MAPPER_GL) &amp;&amp; !USE(COORDINATED_GRAPHICS)
</span></span></pre>
</div>
</div>

</body>
</html>