Title: [128320] releases/WebKitGTK/webkit-1.10/Source/WebCore
Revision
128320
Author
carlo...@webkit.org
Date
2012-09-12 09:03:22 -0700 (Wed, 12 Sep 2012)

Log Message

Merge r128298 - [GStreamer] Audio device not closed after playing sound
https://bugs.webkit.org/show_bug.cgi?id=89122

Reviewed by Martin Robinson.

Set the GStreamer pipeline to NULL instead of PAUSED on EOS. This
allows the audio-sink to release its connection to the audio
device. This is done only if the Media element is not
looping. To make the MediaPlayerPrivate layer aware of that
information the MediaPlayerClient interface was updated with a new
method mediaPlayerIsLooping, implemented by the HTMLMediaElement.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::mediaPlayerIsLooping): Implementation of
MediaPlayerClient::mediaPlayerLoop, proxies to ::loop();
* html/HTMLMediaElement.h:
(HTMLMediaElement):
* platform/graphics/MediaPlayer.h:
(WebCore::MediaPlayerClient::mediaPlayerIsLooping): New method allowing
the MediaPlayer and its backend to know if a playback loop is
requested by the client.
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
(WebCore::MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer):
(WebCore::MediaPlayerPrivateGStreamer::playbackPosition): Report
seek time or media duration if EOS was reached. These early
returns are needed because the position query doesn't work on a
NULL pipeline.
(WebCore::MediaPlayerPrivateGStreamer::changePipelineState):
Refactored to use an early return.
(WebCore::MediaPlayerPrivateGStreamer::prepareToPlay): Reset the
seeking flag.
(WebCore::MediaPlayerPrivateGStreamer::play): reset m_isEndReached.
(WebCore::MediaPlayerPrivateGStreamer::pause): Don't pause on EOS.
(WebCore::MediaPlayerPrivateGStreamer::seek): Refactor, call
currentTime() after we're sure playbin is valid and no error occured.
(WebCore::MediaPlayerPrivateGStreamer::paused): Fake paused state
on EOS.

Modified Paths

Diff

Modified: releases/WebKitGTK/webkit-1.10/Source/WebCore/ChangeLog (128319 => 128320)


--- releases/WebKitGTK/webkit-1.10/Source/WebCore/ChangeLog	2012-09-12 16:02:10 UTC (rev 128319)
+++ releases/WebKitGTK/webkit-1.10/Source/WebCore/ChangeLog	2012-09-12 16:03:22 UTC (rev 128320)
@@ -1,3 +1,43 @@
+2012-08-20  Philippe Normand  <pnorm...@igalia.com>
+
+        [GStreamer] Audio device not closed after playing sound
+        https://bugs.webkit.org/show_bug.cgi?id=89122
+
+        Reviewed by Martin Robinson.
+
+        Set the GStreamer pipeline to NULL instead of PAUSED on EOS. This
+        allows the audio-sink to release its connection to the audio
+        device. This is done only if the Media element is not
+        looping. To make the MediaPlayerPrivate layer aware of that
+        information the MediaPlayerClient interface was updated with a new
+        method mediaPlayerIsLooping, implemented by the HTMLMediaElement.
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::mediaPlayerIsLooping): Implementation of
+        MediaPlayerClient::mediaPlayerLoop, proxies to ::loop();
+        * html/HTMLMediaElement.h:
+        (HTMLMediaElement):
+        * platform/graphics/MediaPlayer.h:
+        (WebCore::MediaPlayerClient::mediaPlayerIsLooping): New method allowing
+        the MediaPlayer and its backend to know if a playback loop is
+        requested by the client.
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
+        (WebCore::MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer):
+        (WebCore::MediaPlayerPrivateGStreamer::playbackPosition): Report
+        seek time or media duration if EOS was reached. These early
+        returns are needed because the position query doesn't work on a
+        NULL pipeline.
+        (WebCore::MediaPlayerPrivateGStreamer::changePipelineState):
+        Refactored to use an early return.
+        (WebCore::MediaPlayerPrivateGStreamer::prepareToPlay): Reset the
+        seeking flag.
+        (WebCore::MediaPlayerPrivateGStreamer::play): reset m_isEndReached.
+        (WebCore::MediaPlayerPrivateGStreamer::pause): Don't pause on EOS.
+        (WebCore::MediaPlayerPrivateGStreamer::seek): Refactor, call
+        currentTime() after we're sure playbin is valid and no error occured.
+        (WebCore::MediaPlayerPrivateGStreamer::paused): Fake paused state
+        on EOS.
+
 2012-08-23  John Griggs  <jgri...@rim.com>
 
                 Replace access ot HTMLMediaElement from MediaPlayerPrivateBlackBerry with methods in MediaPlayerClient - updated with notes from initial reviews.  https://bugs.webkit.org/show_bug.cgi?id=84291

Modified: releases/WebKitGTK/webkit-1.10/Source/WebCore/html/HTMLMediaElement.cpp (128319 => 128320)


--- releases/WebKitGTK/webkit-1.10/Source/WebCore/html/HTMLMediaElement.cpp	2012-09-12 16:02:10 UTC (rev 128319)
+++ releases/WebKitGTK/webkit-1.10/Source/WebCore/html/HTMLMediaElement.cpp	2012-09-12 16:03:22 UTC (rev 128320)
@@ -4415,6 +4415,11 @@
     return paused();
 }
 
+bool HTMLMediaElement::mediaPlayerIsLooping() const
+{
+    return loop();
+}
+
 HostWindow* HTMLMediaElement::mediaPlayerHostWindow()
 {
     return mediaPlayerOwningDocument()->view()->hostWindow();

Modified: releases/WebKitGTK/webkit-1.10/Source/WebCore/html/HTMLMediaElement.h (128319 => 128320)


--- releases/WebKitGTK/webkit-1.10/Source/WebCore/html/HTMLMediaElement.h	2012-09-12 16:02:10 UTC (rev 128319)
+++ releases/WebKitGTK/webkit-1.10/Source/WebCore/html/HTMLMediaElement.h	2012-09-12 16:03:22 UTC (rev 128320)
@@ -429,6 +429,7 @@
     virtual void mediaPlayerPause() OVERRIDE;
     virtual void mediaPlayerPlay() OVERRIDE;
     virtual bool mediaPlayerIsPaused() const OVERRIDE;
+    virtual bool mediaPlayerIsLooping() const OVERRIDE;
     virtual HostWindow* mediaPlayerHostWindow() OVERRIDE;
     virtual IntRect mediaPlayerWindowClipRect() OVERRIDE;
 

Modified: releases/WebKitGTK/webkit-1.10/Source/WebCore/platform/graphics/MediaPlayer.h (128319 => 128320)


--- releases/WebKitGTK/webkit-1.10/Source/WebCore/platform/graphics/MediaPlayer.h	2012-09-12 16:02:10 UTC (rev 128319)
+++ releases/WebKitGTK/webkit-1.10/Source/WebCore/platform/graphics/MediaPlayer.h	2012-09-12 16:03:22 UTC (rev 128320)
@@ -197,6 +197,7 @@
     virtual void mediaPlayerPause() { }
     virtual void mediaPlayerPlay() { }
     virtual bool mediaPlayerIsPaused() const { return true; }
+    virtual bool mediaPlayerIsLooping() const { return false; }
     virtual HostWindow* mediaPlayerHostWindow() { return 0; }
     virtual IntRect mediaPlayerWindowClipRect() { return IntRect(); }
 };

Modified: releases/WebKitGTK/webkit-1.10/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp (128319 => 128320)


--- releases/WebKitGTK/webkit-1.10/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp	2012-09-12 16:02:10 UTC (rev 128319)
+++ releases/WebKitGTK/webkit-1.10/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp	2012-09-12 16:03:22 UTC (rev 128320)
@@ -211,6 +211,7 @@
     , m_seekTime(0)
     , m_changingRate(false)
     , m_endTime(numeric_limits<float>::infinity())
+    , m_isEndReached(false)
     , m_networkState(MediaPlayer::Empty)
     , m_readyState(MediaPlayer::HaveNothing)
     , m_isStreaming(false)
@@ -333,6 +334,17 @@
 
 float MediaPlayerPrivateGStreamer::playbackPosition() const
 {
+    if (m_isEndReached) {
+        // Position queries on a null pipeline return 0. If we're at
+        // the end of the stream the pipeline is null but we want to
+        // report either the seek time or the duration because this is
+        // what the Media element spec expects us to do.
+        if (m_seeking)
+            return m_seekTime;
+        if (m_mediaDuration)
+            return m_mediaDuration;
+    }
+
     float ret = 0.0f;
 
     GstQuery* query = gst_query_new_position(GST_FORMAT_TIME);
@@ -365,13 +377,15 @@
     GstState pending;
 
     gst_element_get_state(m_playBin, &currentState, &pending, 0);
-    if (currentState != newState && pending != newState) {
-        GstStateChangeReturn ret = gst_element_set_state(m_playBin, newState);
-        GstState pausedOrPlaying = newState == GST_STATE_PLAYING ? GST_STATE_PAUSED : GST_STATE_PLAYING;
-        if (currentState != pausedOrPlaying && ret == GST_STATE_CHANGE_FAILURE) {
-            loadingFailed(MediaPlayer::Empty);
-            return false;
-        }
+    LOG_MEDIA_MESSAGE("Current state: %s, pending: %s", gst_element_state_get_name(currentState), gst_element_state_get_name(pending));
+    if (currentState == newState || pending == newState)
+        return true;
+
+    GstStateChangeReturn setStateResult = gst_element_set_state(m_playBin, newState);
+    GstState pausedOrPlaying = newState == GST_STATE_PLAYING ? GST_STATE_PAUSED : GST_STATE_PLAYING;
+    if (currentState != pausedOrPlaying && setStateResult == GST_STATE_CHANGE_FAILURE) {
+        loadingFailed(MediaPlayer::Empty);
+        return false;
     }
     return true;
 }
@@ -379,6 +393,7 @@
 void MediaPlayerPrivateGStreamer::prepareToPlay()
 {
     m_isEndReached = false;
+    m_seeking = false;
 
     if (m_delayingLoad) {
         m_delayingLoad = false;
@@ -388,12 +403,17 @@
 
 void MediaPlayerPrivateGStreamer::play()
 {
-    if (changePipelineState(GST_STATE_PLAYING))
+    if (changePipelineState(GST_STATE_PLAYING)) {
+        m_isEndReached = false;
         LOG_MEDIA_MESSAGE("Play");
+    }
 }
 
 void MediaPlayerPrivateGStreamer::pause()
 {
+    if (m_isEndReached)
+        return;
+
     if (changePipelineState(GST_STATE_PAUSED))
         LOG_MEDIA_MESSAGE("Pause");
 }
@@ -457,16 +477,18 @@
 
 void MediaPlayerPrivateGStreamer::seek(float time)
 {
-    // Avoid useless seeking.
-    if (time == playbackPosition())
-        return;
-
     if (!m_playBin)
         return;
 
     if (m_errorOccured)
         return;
 
+    LOG_MEDIA_MESSAGE("Seek attempt to %f secs", time);
+
+    // Avoid useless seeking.
+    if (time == currentTime())
+        return;
+
     // Extract the integer part of the time (seconds) and the
     // fractional part (microseconds). Attempt to round the
     // microseconds so no floating point precision is lost and we can
@@ -494,6 +516,11 @@
 
 bool MediaPlayerPrivateGStreamer::paused() const
 {
+    if (m_isEndReached) {
+        LOG_MEDIA_MESSAGE("Ignoring pause at EOS");
+        return true;
+    }
+
     GstState state;
     gst_element_get_state(m_playBin, &state, 0, 0);
     return state == GST_STATE_PAUSED;
@@ -1134,8 +1161,9 @@
             // Cache the duration without emiting the durationchange
             // event because it's taken care of by the media element
             // in this precise case.
-            cacheDuration();
-        } else if (maxTimeLoaded() == duration()) {
+            if (!m_isEndReached)
+                cacheDuration();
+        } else if ((state == GST_STATE_NULL) || (maxTimeLoaded() == duration())) {
             m_networkState = MediaPlayer::Loaded;
             m_readyState = MediaPlayer::HaveEnoughData;
         } else {
@@ -1399,19 +1427,23 @@
 
 void MediaPlayerPrivateGStreamer::didEnd()
 {
-    // EOS was reached but the position is not always 0 in case of
-    // reverse playback. So to not confuse the HTMLMediaElement, we
-    // synchronize position and duration values.
+    // Synchronize position and duration values to not confuse the
+    // HTMLMediaElement. In some cases like reverse playback the
+    // position is not always reported as 0 for instance.
     float now = currentTime();
-    if (now > 0 && m_playbackRate < 0) {
+    if (now > 0 && now <= duration() && m_mediaDuration != now) {
+        m_mediaDurationKnown = true;
         m_mediaDuration = now;
-        m_mediaDurationKnown = true;
         m_player->durationChanged();
     }
 
     m_isEndReached = true;
+    timeChanged();
 
-    timeChanged();
+    if (!m_player->mediaPlayerClient()->mediaPlayerIsLooping()) {
+        m_paused = true;
+        gst_element_set_state(m_playBin, GST_STATE_NULL);
+    }
 }
 
 void MediaPlayerPrivateGStreamer::cacheDuration()
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to