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)