Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp (154987 => 154988)
--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp 2013-09-03 16:51:03 UTC (rev 154987)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp 2013-09-03 16:51:19 UTC (rev 154988)
@@ -81,6 +81,9 @@
static const char* gPlaybinName = "playbin2";
static const gint64 gPercentMax = 100;
#endif
+// Max interval in seconds to stay in the READY state on manual
+// state change requests.
+static const guint gReadyStateTimerInterval = 60;
GST_DEBUG_CATEGORY_EXTERN(webkit_media_player_debug);
#define GST_CAT_DEFAULT webkit_media_player_debug
@@ -158,6 +161,14 @@
}
#endif
+static gboolean mediaPlayerPrivateReadyStateTimeoutCallback(MediaPlayerPrivateGStreamer* player)
+{
+ // This is the callback of the timeout source created in ::changePipelineState.
+ // Reset pipeline if we are sitting on READY state when timeout is reached
+ player->changePipelineState(GST_STATE_NULL);
+ return FALSE;
+}
+
static void mediaPlayerPrivatePluginInstallerResultFunction(GstInstallPluginsReturn result, gpointer userData)
{
MediaPlayerPrivateGStreamer* player = reinterpret_cast<MediaPlayerPrivateGStreamer*>(userData);
@@ -257,6 +268,7 @@
, m_audioTimerHandler(0)
, m_textTimerHandler(0)
, m_videoTimerHandler(0)
+ , m_readyTimerHandler(0)
, m_webkitAudioSink(0)
, m_totalBytes(-1)
, m_preservesPitch(false)
@@ -283,6 +295,9 @@
g_signal_handlers_disconnect_by_func(G_OBJECT(m_autoAudioSink.get()),
reinterpret_cast<gpointer>(setAudioStreamPropertiesCallback), this);
+ if (m_readyTimerHandler)
+ g_source_remove(m_readyTimerHandler);
+
if (m_playBin) {
GRefPtr<GstBus> bus = webkitGstPipelineGetBus(GST_PIPELINE(m_playBin.get()));
ASSERT(bus);
@@ -367,7 +382,7 @@
// GStreamer needs to have the pipeline set to a paused state to
// start providing anything useful.
- gst_element_set_state(m_playBin.get(), GST_STATE_PAUSED);
+ changePipelineState(GST_STATE_PAUSED);
setDownloadBuffering();
updateStates();
@@ -408,7 +423,7 @@
bool MediaPlayerPrivateGStreamer::changePipelineState(GstState newState)
{
- ASSERT(newState == GST_STATE_PLAYING || newState == GST_STATE_PAUSED);
+ ASSERT(m_playBin);
GstState currentState;
GstState pending;
@@ -429,6 +444,18 @@
loadingFailed(MediaPlayer::Empty);
return false;
}
+
+ // Create a timer when entering the READY state so that we can free resources
+ // if we stay for too long on READY.
+ // Also lets remove the timer if we request a state change for any state other than READY.
+ // See also https://bugs.webkit.org/show_bug.cgi?id=117354
+ if (newState == GST_STATE_READY && !m_readyTimerHandler) {
+ m_readyTimerHandler = g_timeout_add_seconds(gReadyStateTimerInterval, reinterpret_cast<GSourceFunc>(mediaPlayerPrivateReadyStateTimeoutCallback), this);
+ } else if (newState != GST_STATE_READY && m_readyTimerHandler) {
+ g_source_remove(m_readyTimerHandler);
+ m_readyTimerHandler = 0;
+ }
+
return true;
}
@@ -728,7 +755,7 @@
m_changingRate = true;
if (!rate) {
- gst_element_set_state(m_playBin.get(), GST_STATE_PAUSED);
+ changePipelineState(GST_STATE_PAUSED);
return;
}
@@ -938,8 +965,8 @@
{
m_missingPlugins = false;
if (result == GST_INSTALL_PLUGINS_SUCCESS) {
- gst_element_set_state(m_playBin.get(), GST_STATE_READY);
- gst_element_set_state(m_playBin.get(), GST_STATE_PAUSED);
+ changePipelineState(GST_STATE_READY);
+ changePipelineState(GST_STATE_PAUSED);
}
}
@@ -1144,7 +1171,7 @@
return;
if (m_playBin)
- gst_element_set_state(m_playBin.get(), GST_STATE_NULL);
+ changePipelineState(GST_STATE_READY);
}
void MediaPlayerPrivateGStreamer::asyncStateChangeDone()
@@ -1211,8 +1238,12 @@
m_networkState = MediaPlayer::Empty;
break;
case GST_STATE_READY:
- m_readyState = MediaPlayer::HaveMetadata;
- m_networkState = MediaPlayer::Empty;
+ // Do not change network/ready states if on EOS and state changed to READY to avoid
+ // recreating the player on HTMLMediaElement.
+ if (!m_isEndReached) {
+ m_readyState = MediaPlayer::HaveMetadata;
+ m_networkState = MediaPlayer::Empty;
+ }
break;
case GST_STATE_PAUSED:
case GST_STATE_PLAYING:
@@ -1253,14 +1284,14 @@
if (didBuffering && !m_buffering && !m_paused) {
LOG_MEDIA_MESSAGE("[Buffering] Restarting playback.");
- gst_element_set_state(m_playBin.get(), GST_STATE_PLAYING);
+ changePipelineState(GST_STATE_PLAYING);
}
} else if (state == GST_STATE_PLAYING) {
m_paused = false;
if (m_buffering && !isLiveStream()) {
LOG_MEDIA_MESSAGE("[Buffering] Pausing stream for buffering.");
- gst_element_set_state(m_playBin.get(), GST_STATE_PAUSED);
+ changePipelineState(GST_STATE_PAUSED);
}
} else
m_paused = true;
@@ -1283,8 +1314,8 @@
// A live stream was paused, reset the pipeline.
if (state == GST_STATE_PAUSED && pending == GST_STATE_PLAYING && isLiveStream()) {
- gst_element_set_state(m_playBin.get(), GST_STATE_NULL);
- gst_element_set_state(m_playBin.get(), GST_STATE_PLAYING);
+ changePipelineState(GST_STATE_READY);
+ changePipelineState(GST_STATE_PLAYING);
}
break;
@@ -1308,7 +1339,7 @@
m_paused = false;
if (!m_paused)
- gst_element_set_state(m_playBin.get(), GST_STATE_PLAYING);
+ changePipelineState(GST_STATE_PLAYING);
m_networkState = MediaPlayer::Loading;
break;
@@ -1413,7 +1444,7 @@
// Reset pipeline state.
m_resetPipeline = true;
- gst_element_set_state(m_playBin.get(), GST_STATE_READY);
+ changePipelineState(GST_STATE_READY);
GstState state;
gst_element_get_state(m_playBin.get(), &state, 0, 0);
@@ -1421,7 +1452,7 @@
// Set the new uri and start playing.
g_object_set(m_playBin.get(), "uri", newUrl.string().utf8().data(), NULL);
m_url = newUrl;
- gst_element_set_state(m_playBin.get(), GST_STATE_PLAYING);
+ changePipelineState(GST_STATE_PLAYING);
return true;
}
} else
@@ -1459,7 +1490,7 @@
if (!m_player->mediaPlayerClient()->mediaPlayerIsLooping()) {
m_paused = true;
- gst_element_set_state(m_playBin.get(), GST_STATE_NULL);
+ changePipelineState(GST_STATE_READY);
m_downloadFinished = false;
}
}
@@ -1504,6 +1535,13 @@
m_readyState = MediaPlayer::HaveNothing;
m_player->readyStateChanged();
}
+
+ // Loading failed, force reset pipeline and remove ready timer.
+ gst_element_set_state(m_playBin.get(), GST_STATE_NULL);
+ if (m_readyTimerHandler) {
+ g_source_remove(m_readyTimerHandler);
+ m_readyTimerHandler = 0;
+ }
}
static HashSet<String> mimeTypeCache()
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h (154987 => 154988)
--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h 2013-09-03 16:51:03 UTC (rev 154987)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h 2013-09-03 16:51:19 UTC (rev 154988)
@@ -107,6 +107,8 @@
void simulateAudioInterruption();
+ bool changePipelineState(GstState);
+
private:
MediaPlayerPrivateGStreamer(MediaPlayer*);
@@ -127,7 +129,6 @@
void asyncStateChangeDone();
void createGSTPlayBin();
- bool changePipelineState(GstState);
bool loadNextLocation();
void mediaLocationChanged(GstMessage*);
@@ -176,6 +177,7 @@
guint m_audioTimerHandler;
guint m_textTimerHandler;
guint m_videoTimerHandler;
+ guint m_readyTimerHandler;
GRefPtr<GstElement> m_webkitAudioSink;
mutable long m_totalBytes;
KURL m_url;