Log Message
[GStreamer] Live stream support is weak https://bugs.webkit.org/show_bug.cgi?id=90084
Reviewed by Martin Robinson. Make sure on-disk buffering is disabled for live streams. It is enabled initially when loading any remote media file if preload is set to Auto. Later on if the player detects that the media is live it disables on-disk buffering. This patch also adds support for caching the total size of the media. * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp: (WebCore::MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer): (WebCore::MediaPlayerPrivateGStreamer::load): Keep track of the media url as an instance attribute. (WebCore::MediaPlayerPrivateGStreamer::duration): Logging improvement. (WebCore::MediaPlayerPrivateGStreamer::setRate): use the new isLiveStream() method. (WebCore::MediaPlayerPrivateGStreamer::buffered): Ditto. (WebCore::MediaPlayerPrivateGStreamer::handleMessage): Indicate source of duration message. (WebCore::MediaPlayerPrivateGStreamer::fillTimerFired): Perform an anonymous duration change emission, mostly to cache its value. (WebCore::MediaPlayerPrivateGStreamer::totalBytes): Return cached size when available. (WebCore::MediaPlayerPrivateGStreamer::updateStates): Use the new isLiveStream() method and handle state change corner cases for live streams. (WebCore::MediaPlayerPrivateGStreamer::durationChanged): Cache media total size and re-enable on-disk buffering if caching succeeds. (WebCore::MediaPlayerPrivateGStreamer::movieLoadType): New implementation handling on-disk buffered and live streaming cases. (WebCore::MediaPlayerPrivateGStreamer::setPreload): Remember the case where preload is updated from Auto to another value, do on-disk buffering only for Auto preload attribute. * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h: (MediaPlayerPrivateGStreamer): (WebCore::MediaPlayerPrivateGStreamer::isLiveStream): Utility method, a stream is live if it goes to PAUSE without prerolling.
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (124216 => 124217)
--- trunk/Source/WebCore/ChangeLog 2012-07-31 17:02:10 UTC (rev 124216)
+++ trunk/Source/WebCore/ChangeLog 2012-07-31 17:16:24 UTC (rev 124217)
@@ -1,3 +1,44 @@
+2012-07-07 Philippe Normand <[email protected]>
+
+ [GStreamer] Live stream support is weak
+ https://bugs.webkit.org/show_bug.cgi?id=90084
+
+ Reviewed by Martin Robinson.
+
+ Make sure on-disk buffering is disabled for live streams. It is
+ enabled initially when loading any remote media file if preload is
+ set to Auto. Later on if the player detects that the media is live
+ it disables on-disk buffering. This patch also adds support for
+ caching the total size of the media.
+
+ * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
+ (WebCore::MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer):
+ (WebCore::MediaPlayerPrivateGStreamer::load): Keep track of the
+ media url as an instance attribute.
+ (WebCore::MediaPlayerPrivateGStreamer::duration): Logging improvement.
+ (WebCore::MediaPlayerPrivateGStreamer::setRate): use the new
+ isLiveStream() method.
+ (WebCore::MediaPlayerPrivateGStreamer::buffered): Ditto.
+ (WebCore::MediaPlayerPrivateGStreamer::handleMessage): Indicate
+ source of duration message.
+ (WebCore::MediaPlayerPrivateGStreamer::fillTimerFired): Perform an
+ anonymous duration change emission, mostly to cache its value.
+ (WebCore::MediaPlayerPrivateGStreamer::totalBytes): Return
+ cached size when available.
+ (WebCore::MediaPlayerPrivateGStreamer::updateStates): Use the new
+ isLiveStream() method and handle state change corner cases for live streams.
+ (WebCore::MediaPlayerPrivateGStreamer::durationChanged): Cache
+ media total size and re-enable on-disk buffering if caching succeeds.
+ (WebCore::MediaPlayerPrivateGStreamer::movieLoadType): New
+ implementation handling on-disk buffered and live streaming cases.
+ (WebCore::MediaPlayerPrivateGStreamer::setPreload): Remember the
+ case where preload is updated from Auto to another value, do
+ on-disk buffering only for Auto preload attribute.
+ * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h:
+ (MediaPlayerPrivateGStreamer):
+ (WebCore::MediaPlayerPrivateGStreamer::isLiveStream): Utility
+ method, a stream is live if it goes to PAUSE without prerolling.
+
2012-07-17 Antonio Gomes <[email protected]>
[Blackberry][FullScreen] HTML5 <video> controls are scaled differently depending on the current webpage scale
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp (124216 => 124217)
--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp 2012-07-31 17:02:10 UTC (rev 124216)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp 2012-07-31 17:16:24 UTC (rev 124217)
@@ -235,6 +235,8 @@
, m_audioTimerHandler(0)
, m_videoTimerHandler(0)
, m_webkitAudioSink(0)
+ , m_totalBytes(-1)
+ , m_originalPreloadWasAutoAndWasOverridden(false)
{
if (initializeGStreamerAndRegisterWebKitElements())
createGSTPlayBin();
@@ -292,6 +294,7 @@
if (kurl.isLocalFile())
cleanUrl = cleanUrl.substring(0, kurl.pathEnd());
+ m_url = KURL(KURL(), cleanUrl);
g_object_set(m_playBin, "uri", cleanUrl.utf8().data(), NULL);
LOG_VERBOSE(Media, "Load %s", cleanUrl.utf8().data());
@@ -407,7 +410,7 @@
bool failure = !gst_element_query_duration(m_playBin, &timeFormat, &timeLength) || timeFormat != GST_FORMAT_TIME || static_cast<guint64>(timeLength) == GST_CLOCK_TIME_NONE;
#endif
if (failure) {
- LOG_VERBOSE(Media, "Time duration query failed.");
+ LOG_VERBOSE(Media, "Time duration query failed for %s", m_url.string().utf8().data());
return numeric_limits<float>::infinity();
}
@@ -634,7 +637,7 @@
|| (pending == GST_STATE_PAUSED))
return;
- if (m_isStreaming)
+ if (isLiveStream())
return;
m_playbackRate = rate;
@@ -692,7 +695,7 @@
PassRefPtr<TimeRanges> MediaPlayerPrivateGStreamer::buffered() const
{
RefPtr<TimeRanges> timeRanges = TimeRanges::create();
- if (m_errorOccured || m_isStreaming)
+ if (m_errorOccured || isLiveStream())
return timeRanges.release();
#if GST_CHECK_VERSION(0, 10, 31)
@@ -723,7 +726,7 @@
gst_query_unref(query);
#else
float loaded = maxTimeLoaded();
- if (!m_errorOccured && !m_isStreaming && loaded > 0)
+ if (!m_errorOccured && !isLiveStream() && loaded > 0)
timeRanges->add(0, loaded);
#endif
return timeRanges.release();
@@ -749,12 +752,13 @@
}
}
+ LOG_VERBOSE(Media, "Message received from element %s", GST_MESSAGE_SRC_NAME(message));
switch (GST_MESSAGE_TYPE(message)) {
case GST_MESSAGE_ERROR:
if (m_resetPipeline)
break;
gst_message_parse_error(message, &err.outPtr(), &debug.outPtr());
- LOG_VERBOSE(Media, "Error: %d, %s", err->code, err->message);
+ LOG_VERBOSE(Media, "Error %d: %s (url="" err->code, err->message, m_url.string().utf8().data());
GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(m_playBin), GST_DEBUG_GRAPH_SHOW_ALL, "webkit-video.error");
@@ -941,10 +945,13 @@
unsigned MediaPlayerPrivateGStreamer::totalBytes() const
{
- if (!m_source)
+ if (m_errorOccured)
return 0;
- if (m_errorOccured)
+ if (m_totalBytes != -1)
+ return m_totalBytes;
+
+ if (!m_source)
return 0;
GstFormat fmt = GST_FORMAT_BYTES;
@@ -955,7 +962,9 @@
if (gst_element_query_duration(m_source.get(), &fmt, &length)) {
#endif
LOG_VERBOSE(Media, "totalBytes %" G_GINT64_FORMAT, length);
- return static_cast<unsigned>(length);
+ m_totalBytes = static_cast<unsigned>(length);
+ m_isStreaming = !length;
+ return m_totalBytes;
}
// Fall back to querying the source pads manually.
@@ -1003,8 +1012,9 @@
gst_iterator_free(iter);
LOG_VERBOSE(Media, "totalBytes %" G_GINT64_FORMAT, length);
-
- return static_cast<unsigned>(length);
+ m_totalBytes = static_cast<unsigned>(length);
+ m_isStreaming = !length;
+ return m_totalBytes;
}
unsigned MediaPlayerPrivateGStreamer::decodedFrameCount() const
@@ -1150,7 +1160,7 @@
m_readyState = MediaPlayer::HaveEnoughData;
m_paused = false;
- if (m_buffering) {
+ if (m_buffering && !isLiveStream()) {
m_readyState = MediaPlayer::HaveCurrentData;
m_networkState = MediaPlayer::Loading;
@@ -1182,7 +1192,22 @@
gst_element_state_get_name(pending));
// Change in progress
- if (!m_isStreaming && !m_buffering)
+ // On-disk buffering was attempted but the media is live. This
+ // can't work so disable on-disk buffering and reset the
+ // pipeline.
+ if (state == GST_STATE_READY && isLiveStream() && m_preload == MediaPlayer::Auto) {
+ setPreload(MediaPlayer::None);
+ gst_element_set_state(m_playBin, GST_STATE_NULL);
+ gst_element_set_state(m_playBin, GST_STATE_PAUSED);
+ }
+
+ // A live stream was paused, reset the pipeline.
+ if (state == GST_STATE_PAUSED && pending == GST_STATE_PLAYING && isLiveStream()) {
+ gst_element_set_state(m_playBin, GST_STATE_NULL);
+ gst_element_set_state(m_playBin, GST_STATE_PLAYING);
+ }
+
+ if (!isLiveStream() && !m_buffering)
return;
if (m_seeking) {
@@ -1413,6 +1438,15 @@
// HTMLMediaElement.
if (previousDuration && m_mediaDuration != previousDuration)
m_player->durationChanged();
+
+ if (m_preload == MediaPlayer::None && m_originalPreloadWasAutoAndWasOverridden) {
+ m_totalBytes = -1;
+ if (totalBytes() && !isLiveStream()) {
+ setPreload(MediaPlayer::Auto);
+ gst_element_set_state(m_playBin, GST_STATE_NULL);
+ gst_element_set_state(m_playBin, GST_STATE_PAUSED);
+ }
+ }
}
bool MediaPlayerPrivateGStreamer::supportsMuting() const
@@ -1642,18 +1676,34 @@
return p;
}
+MediaPlayer::MovieLoadType MediaPlayerPrivateGStreamer::movieLoadType() const
+{
+ if (m_readyState == MediaPlayer::HaveNothing)
+ return MediaPlayer::Unknown;
+
+ if (isLiveStream())
+ return MediaPlayer::LiveStream;
+
+ return MediaPlayer::Download;
+}
+
void MediaPlayerPrivateGStreamer::setPreload(MediaPlayer::Preload preload)
{
- ASSERT(m_playBin);
+ m_originalPreloadWasAutoAndWasOverridden = m_preload != preload && m_preload == MediaPlayer::Auto;
m_preload = preload;
+ ASSERT(m_playBin);
+
GstPlayFlags flags;
g_object_get(m_playBin, "flags", &flags, NULL);
- if (preload == MediaPlayer::None)
+ if (m_preload == MediaPlayer::Auto) {
+ LOG_VERBOSE(Media, "Enabling on-disk buffering");
+ g_object_set(m_playBin, "flags", flags | GST_PLAY_FLAG_DOWNLOAD, NULL);
+ } else {
+ LOG_VERBOSE(Media, "Disabling on-disk buffering");
g_object_set(m_playBin, "flags", flags & ~GST_PLAY_FLAG_DOWNLOAD, NULL);
- else
- g_object_set(m_playBin, "flags", flags | GST_PLAY_FLAG_DOWNLOAD, NULL);
+ }
if (m_delayingLoad && m_preload != MediaPlayer::None) {
m_delayingLoad = false;
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h (124216 => 124217)
--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h 2012-07-31 17:02:10 UTC (rev 124216)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h 2012-07-31 17:16:24 UTC (rev 124217)
@@ -124,6 +124,8 @@
unsigned audioDecodedByteCount() const;
unsigned videoDecodedByteCount() const;
+ MediaPlayer::MovieLoadType movieLoadType() const;
+
private:
MediaPlayerPrivateGStreamer(MediaPlayer*);
@@ -151,6 +153,7 @@
void processBufferingStats(GstMessage*);
virtual String engineDescription() const { return "GStreamer"; }
+ bool isLiveStream() const { return m_isStreaming; }
private:
MediaPlayer* m_player;
@@ -195,8 +198,11 @@
guint m_audioTimerHandler;
guint m_videoTimerHandler;
GRefPtr<GstElement> m_webkitAudioSink;
+ mutable long m_totalBytes;
GRefPtr<GstPad> m_videoSinkPad;
mutable IntSize m_videoSize;
+ KURL m_url;
+ bool m_originalPreloadWasAutoAndWasOverridden;
};
}
_______________________________________________ webkit-changes mailing list [email protected] http://lists.webkit.org/mailman/listinfo/webkit-changes
