2011-04-06 Philippe Normand <pnormand@igalia.com>
Reviewed by Martin Robinson.
[GStreamer] RTSP playback broken
https://bugs.webkit.org/show_bug.cgi?id=56930
Rely on {audio,video}-changed playbin2 signals instead of the
-tags-changed signals because some media don't provide tags and
then can trick the media-player to not paint video, for instance.
Also trigger a video size calculation after the video sink
negotiated its caps. This is useful in the cases where
audio-changed signal is emitted but the video sink takes more time
to negociate caps with its peer.
This patch also fixes the rtsp manual-test with a new stream url
which seems to be more permanent than the previous WWDC keynote
stream.
* manual-tests/video-rtsp.html:
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
(WebCore::mediaPlayerPrivateVideoChangedCallback):
(WebCore::mediaPlayerPrivateAudioChangedCallback):
(WebCore::mediaPlayerPrivateAudioChangeTimeoutCallback):
(WebCore::mediaPlayerPrivateVideoChangeTimeoutCallback):
(WebCore::MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer):
(WebCore::MediaPlayerPrivateGStreamer::~MediaPlayerPrivateGStreamer):
(WebCore::MediaPlayerPrivateGStreamer::naturalSize):
(WebCore::MediaPlayerPrivateGStreamer::videoChanged):
(WebCore::MediaPlayerPrivateGStreamer::notifyPlayerOfVideo):
(WebCore::MediaPlayerPrivateGStreamer::audioChanged):
(WebCore::MediaPlayerPrivateGStreamer::notifyPlayerOfAudio):
(WebCore::MediaPlayerPrivateGStreamer::paint):
(WebCore::MediaPlayerPrivateGStreamer::createGSTPlayBin):
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@83566 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index c06b7de..b5f66de 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,40 @@
+2011-04-06 Philippe Normand <pnormand@igalia.com>
+
+ Reviewed by Martin Robinson.
+
+ [GStreamer] RTSP playback broken
+ https://bugs.webkit.org/show_bug.cgi?id=56930
+
+ Rely on {audio,video}-changed playbin2 signals instead of the
+ -tags-changed signals because some media don't provide tags and
+ then can trick the media-player to not paint video, for instance.
+
+ Also trigger a video size calculation after the video sink
+ negotiated its caps. This is useful in the cases where
+ audio-changed signal is emitted but the video sink takes more time
+ to negociate caps with its peer.
+
+ This patch also fixes the rtsp manual-test with a new stream url
+ which seems to be more permanent than the previous WWDC keynote
+ stream.
+
+ * manual-tests/video-rtsp.html:
+ * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
+ (WebCore::mediaPlayerPrivateVideoChangedCallback):
+ (WebCore::mediaPlayerPrivateAudioChangedCallback):
+ (WebCore::mediaPlayerPrivateAudioChangeTimeoutCallback):
+ (WebCore::mediaPlayerPrivateVideoChangeTimeoutCallback):
+ (WebCore::MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer):
+ (WebCore::MediaPlayerPrivateGStreamer::~MediaPlayerPrivateGStreamer):
+ (WebCore::MediaPlayerPrivateGStreamer::naturalSize):
+ (WebCore::MediaPlayerPrivateGStreamer::videoChanged):
+ (WebCore::MediaPlayerPrivateGStreamer::notifyPlayerOfVideo):
+ (WebCore::MediaPlayerPrivateGStreamer::audioChanged):
+ (WebCore::MediaPlayerPrivateGStreamer::notifyPlayerOfAudio):
+ (WebCore::MediaPlayerPrivateGStreamer::paint):
+ (WebCore::MediaPlayerPrivateGStreamer::createGSTPlayBin):
+ * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h:
+
2011-04-12 Vsevolod Vlasov <vsevik@chromium.org>
Reviewed by Pavel Feldman.
diff --git a/Source/WebCore/manual-tests/video-rtsp.html b/Source/WebCore/manual-tests/video-rtsp.html
index 4fff987..f500f69 100644
--- a/Source/WebCore/manual-tests/video-rtsp.html
+++ b/Source/WebCore/manual-tests/video-rtsp.html
@@ -3,9 +3,7 @@
<title>RTSP playback test</title>
</head>
<body>
-<video with=640 height=352 autoplay controls src="rtsp://a2047.v1411b.c1411.g.vq.akamaistream.net/5/2047/1411/2_h264_650/1a1a1ae454c430950065de4cbb2f94c226950c7ae655b61a48a91475e243acda3dac194879adde0f/wwdc_2006_2_650.mov"></video>
-<p>Test that QuickTime file with RTSP URL loads.<p>
-<script>start()</script>
-<pre id="console"></pre>
+<video width=400 height=300 preload=none autoplay src="rtsp://dmzosx001.dpa.act.gov.au/medium"></video>
+<p>Test that RTSP URL loads.<p>
</body>
</html>
diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
index 85787c7..ee3d473 100644
--- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
+++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
@@ -184,55 +184,60 @@
}
}
-void mediaPlayerPrivateVolumeChangedCallback(GObject *element, GParamSpec *pspec, gpointer data)
+static void mediaPlayerPrivateVolumeChangedCallback(GObject*, GParamSpec*, gpointer data)
{
// This is called when playbin receives the notify::volume signal.
MediaPlayerPrivateGStreamer* mp = reinterpret_cast<MediaPlayerPrivateGStreamer*>(data);
mp->volumeChanged();
}
-gboolean mediaPlayerPrivateVolumeChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
+static gboolean mediaPlayerPrivateVolumeChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
{
// This is the callback of the timeout source created in ::volumeChanged.
player->notifyPlayerOfVolumeChange();
return FALSE;
}
-void mediaPlayerPrivateMuteChangedCallback(GObject *element, GParamSpec *pspec, gpointer data)
+static void mediaPlayerPrivateMuteChangedCallback(GObject*, GParamSpec*, gpointer data)
{
// This is called when playbin receives the notify::mute signal.
MediaPlayerPrivateGStreamer* mp = reinterpret_cast<MediaPlayerPrivateGStreamer*>(data);
mp->muteChanged();
}
-gboolean mediaPlayerPrivateMuteChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
+static gboolean mediaPlayerPrivateMuteChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
{
// This is the callback of the timeout source created in ::muteChanged.
player->notifyPlayerOfMute();
return FALSE;
}
-void mediaPlayerPrivateVideoTagsChangedCallback(GObject* element, gint streamId, MediaPlayerPrivateGStreamer* player)
+static void mediaPlayerPrivateVideoSinkCapsChangedCallback(GObject*, GParamSpec*, MediaPlayerPrivateGStreamer* player)
{
- player->videoTagsChanged(streamId);
+ player->videoChanged();
}
-void mediaPlayerPrivateAudioTagsChangedCallback(GObject* element, gint streamId, MediaPlayerPrivateGStreamer* player)
+static void mediaPlayerPrivateVideoChangedCallback(GObject*, MediaPlayerPrivateGStreamer* player)
{
- player->audioTagsChanged(streamId);
+ player->videoChanged();
}
-gboolean mediaPlayerPrivateAudioTagsChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
+static void mediaPlayerPrivateAudioChangedCallback(GObject*, MediaPlayerPrivateGStreamer* player)
{
- // This is the callback of the timeout source created in ::audioTagsChanged.
- player->notifyPlayerOfAudioTags();
+ player->audioChanged();
+}
+
+static gboolean mediaPlayerPrivateAudioChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
+{
+ // This is the callback of the timeout source created in ::audioChanged.
+ player->notifyPlayerOfAudio();
return FALSE;
}
-gboolean mediaPlayerPrivateVideoTagsChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
+static gboolean mediaPlayerPrivateVideoChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
{
- // This is the callback of the timeout source created in ::videoTagsChanged.
- player->notifyPlayerOfVideoTags();
+ // This is the callback of the timeout source created in ::videoChanged.
+ player->notifyPlayerOfVideo();
return FALSE;
}
@@ -347,8 +352,8 @@
, m_muteTimerHandler(0)
, m_hasVideo(false)
, m_hasAudio(false)
- , m_audioTagsTimerHandler(0)
- , m_videoTagsTimerHandler(0)
+ , m_audioTimerHandler(0)
+ , m_videoTimerHandler(0)
, m_webkitAudioSink(0)
{
if (doGstInit())
@@ -393,11 +398,11 @@
if (m_volumeTimerHandler)
g_source_remove(m_volumeTimerHandler);
- if (m_videoTagsTimerHandler)
- g_source_remove(m_videoTagsTimerHandler);
+ if (m_videoTimerHandler)
+ g_source_remove(m_videoTimerHandler);
- if (m_audioTagsTimerHandler)
- g_source_remove(m_audioTagsTimerHandler);
+ if (m_audioTimerHandler)
+ g_source_remove(m_audioTimerHandler);
}
void MediaPlayerPrivateGStreamer::load(const String& url)
@@ -583,6 +588,7 @@
|| !gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator,
&pixelAspectRatioDenominator)) {
gst_object_unref(GST_OBJECT(pad));
+ // The video-sink has likely not yet negotiated its caps.
return IntSize();
}
@@ -619,39 +625,40 @@
return IntSize(static_cast<int>(width), static_cast<int>(height));
}
-void MediaPlayerPrivateGStreamer::videoTagsChanged(gint streamId)
+void MediaPlayerPrivateGStreamer::videoChanged()
{
- if (m_videoTagsTimerHandler)
- g_source_remove(m_videoTagsTimerHandler);
- m_videoTagsTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(mediaPlayerPrivateVideoTagsChangeTimeoutCallback), this);
+ if (m_videoTimerHandler)
+ g_source_remove(m_videoTimerHandler);
+ m_videoTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(mediaPlayerPrivateVideoChangeTimeoutCallback), this);
}
-void MediaPlayerPrivateGStreamer::notifyPlayerOfVideoTags()
+void MediaPlayerPrivateGStreamer::notifyPlayerOfVideo()
{
- m_videoTagsTimerHandler = 0;
+ m_videoTimerHandler = 0;
- gint currentVideo = -1;
+ gint videoTracks = 0;
if (m_playBin)
- g_object_get(m_playBin, "current-video", ¤tVideo, NULL);
- m_hasVideo = currentVideo > -1;
+ g_object_get(m_playBin, "n-video", &videoTracks, NULL);
+
+ m_hasVideo = videoTracks > 0;
m_player->mediaPlayerClient()->mediaPlayerEngineUpdated(m_player);
}
-void MediaPlayerPrivateGStreamer::audioTagsChanged(gint streamId)
+void MediaPlayerPrivateGStreamer::audioChanged()
{
- if (m_audioTagsTimerHandler)
- g_source_remove(m_audioTagsTimerHandler);
- m_audioTagsTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(mediaPlayerPrivateAudioTagsChangeTimeoutCallback), this);
+ if (m_audioTimerHandler)
+ g_source_remove(m_audioTimerHandler);
+ m_audioTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(mediaPlayerPrivateAudioChangeTimeoutCallback), this);
}
-void MediaPlayerPrivateGStreamer::notifyPlayerOfAudioTags()
+void MediaPlayerPrivateGStreamer::notifyPlayerOfAudio()
{
- m_audioTagsTimerHandler = 0;
+ m_audioTimerHandler = 0;
- gint currentAudio = -1;
+ gint audioTracks = 0;
if (m_playBin)
- g_object_get(m_playBin, "current-audio", ¤tAudio, NULL);
- m_hasAudio = currentAudio > -1;
+ g_object_get(m_playBin, "n-audio", &audioTracks, NULL);
+ m_hasAudio = audioTracks > 0;
m_player->mediaPlayerClient()->mediaPlayerEngineUpdated(m_player);
}
@@ -1420,6 +1427,7 @@
if (!m_player->visible())
return;
+
if (!m_buffer)
return;
@@ -1645,8 +1653,8 @@
g_signal_connect(m_playBin, "notify::volume", G_CALLBACK(mediaPlayerPrivateVolumeChangedCallback), this);
g_signal_connect(m_playBin, "notify::source", G_CALLBACK(mediaPlayerPrivateSourceChangedCallback), this);
g_signal_connect(m_playBin, "notify::mute", G_CALLBACK(mediaPlayerPrivateMuteChangedCallback), this);
- g_signal_connect(m_playBin, "video-tags-changed", G_CALLBACK(mediaPlayerPrivateVideoTagsChangedCallback), this);
- g_signal_connect(m_playBin, "audio-tags-changed", G_CALLBACK(mediaPlayerPrivateAudioTagsChangedCallback), this);
+ g_signal_connect(m_playBin, "video-changed", G_CALLBACK(mediaPlayerPrivateVideoChangedCallback), this);
+ g_signal_connect(m_playBin, "audio-changed", G_CALLBACK(mediaPlayerPrivateAudioChangedCallback), this);
m_webkitVideoSink = webkit_video_sink_new();
@@ -1722,6 +1730,14 @@
// Set the bin as video sink of playbin.
g_object_set(m_playBin, "video-sink", m_videoSinkBin, NULL);
+
+
+ pad = gst_element_get_static_pad(m_webkitVideoSink, "sink");
+ if (pad) {
+ g_signal_connect(pad, "notify::caps", G_CALLBACK(mediaPlayerPrivateVideoSinkCapsChangedCallback), this);
+ gst_object_unref(GST_OBJECT(pad));
+ }
+
}
}
diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
index 680e815..7a9ca7f 100644
--- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
+++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
@@ -46,16 +46,7 @@
class MediaPlayerPrivateGStreamer;
gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data);
-void mediaPlayerPrivateVolumeChangedCallback(GObject* element, GParamSpec* pspec, gpointer data);
-void mediaPlayerPrivateMuteChangedCallback(GObject* element, GParamSpec* pspec, gpointer data);
void mediaPlayerPrivateSourceChangedCallback(GObject* element, GParamSpec* pspec, gpointer data);
-void mediaPlayerPrivateVideoTagsChangedCallback(GObject* element, gint, MediaPlayerPrivateGStreamer*);
-void mediaPlayerPrivateAudioTagsChangedCallback(GObject* element, gint, MediaPlayerPrivateGStreamer*);
-gboolean mediaPlayerPrivateAudioTagsChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player);
-gboolean mediaPlayerPrivateVideoTagsChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player);
-
-gboolean mediaPlayerPrivateVolumeChangeTimeoutCallback(MediaPlayerPrivateGStreamer*);
-gboolean mediaPlayerPrivateMuteChangeTimeoutCallback(MediaPlayerPrivateGStreamer*);
class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
friend gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data);
@@ -130,10 +121,10 @@
GstElement* pipeline() const { return m_playBin; }
bool pipelineReset() const { return m_resetPipeline; }
- void videoTagsChanged(gint);
- void audioTagsChanged(gint);
- void notifyPlayerOfVideoTags();
- void notifyPlayerOfAudioTags();
+ void videoChanged();
+ void audioChanged();
+ void notifyPlayerOfVideo();
+ void notifyPlayerOfAudio();
unsigned decodedFrameCount() const;
unsigned droppedFrameCount() const;
@@ -198,8 +189,8 @@
guint m_muteTimerHandler;
bool m_hasVideo;
bool m_hasAudio;
- guint m_audioTagsTimerHandler;
- guint m_videoTagsTimerHandler;
+ guint m_audioTimerHandler;
+ guint m_videoTimerHandler;
GstElement* m_webkitAudioSink;
};
}