defaultPlaybackRate not respected when set before source is loaded
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 12 Jan 2015 18:15:07 +0000 (18:15 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 12 Jan 2015 18:15:07 +0000 (18:15 +0000)
https://bugs.webkit.org/show_bug.cgi?id=140282

Reviewed by Eric Carlson.

Source/WebCore:

Test: media/video-defaultplaybackrate-before-load.html

When the HTMLMediaElement is notified that the media player's rate has changed, it asks
for the rate from MediaPlayer. However, MediaPlayer never requests the playback rate
from the underlying MediaPlayerPrivate; it just returns the last rate which was set, or
1 if no rate was set. HTMLMediaElement then sets its playbackRate to the returned
value. So the end result is that the value from defaultPlaybackRate is overwritten by
the default value of 1 in MediaPlayer.

Rather than caching the requested rate in MediaPlayer, cache the value reported by
MediaPlayer inside HTMLMediaElement. And instead of returning the reported playback
rate from HTMLMediaElement.playbackRate, just return the last value set. The reported
value is still used for estimating the current time during playback.

Add MediaPlayerPrivate interface method to return the current playback rate.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::HTMLMediaElement): Initialize m_reportedPlaybackRate.
(WebCore::HTMLMediaElement::effectivePlaybackRate): Return m_reportedPlaybackRate.
(WebCore::HTMLMediaElement::requestedPlaybackRate): Return m_playbackRate.
(WebCore::HTMLMediaElement::updatePlaybackRate): Use requestedPlaybackRate() instead
    of effectivePlaybackRate();
(WebCore::HTMLMediaElement::ended): Ditto.
(WebCore::HTMLMediaElement::playbackProgressTimerFired): Ditto.
(WebCore::HTMLMediaElement::endedPlayback): Ditto.
(WebCore::HTMLMediaElement::updatePlayState): Ditto.
(WebCore::HTMLMediaElement::mediaPlayerRateChanged): Set m_reportedPlaybackRate.
(WebCore::HTMLMediaElement::mediaPlayerRequestedPlaybackRate): Return
    requestedPlaybackRate() if playing and 0 if not.
* html/HTMLMediaElement.h:
* platform/graphics/MediaPlayer.cpp:
(WebCore::MediaPlayer::MediaPlayer): Removed m_rate.
(WebCore::MediaPlayer::rate): Pass to MediaPlayerPrivate.
(WebCore::MediaPlayer::setRate): Do not cache the rate.
(WebCore::MediaPlayer::requestedRate): Added; ask HTMLMediaElement.
* platform/graphics/MediaPlayer.h:
(WebCore::MediaPlayerClient::mediaPlayerRequestedPlaybackRate): Added.
* platform/graphics/MediaPlayerPrivate.h:
(WebCore::MediaPlayerPrivateInterface::rate): Added.
* platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp:
(WebCore::MediaPlayerPrivateAVFoundation::MediaPlayerPrivateAVFoundation):
    Do not cache the requested rate.
(WebCore::MediaPlayerPrivateAVFoundation::requestedRate): Pass to MediaPlayer.
(WebCore::MediaPlayerPrivateAVFoundation::setRate): Deleted.
* platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h:
(WebCore::MediaPlayerPrivateAVFoundation::requestedRate): Deleted.
* platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp:
(WebCore::MediaPlayerPrivateAVFoundationCF::setRate): Renamed from updateRate.
(WebCore::MediaPlayerPrivateAVFoundationCF::rate): Fetch the rate from the player.
* platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.h:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
(WebCore::MediaPlayerPrivateAVFoundationObjC::setRateDouble): Renamed from updateRate.
(WebCore::MediaPlayerPrivateAVFoundationObjC::rate): Fetch the rate from the player.
* platform/graphics/mac/MediaPlayerPrivateQTKit.h:
* platform/graphics/mac/MediaPlayerPrivateQTKit.mm:
(WebCore::MediaPlayerPrivateQTKit::rate): Fetch the rate from the QTMovie.

LayoutTests:

* media/video-defaultplaybackrate-before-load-expected.txt: Added.
* media/video-defaultplaybackrate-before-load.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@178281 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
LayoutTests/ChangeLog
LayoutTests/media/video-defaultplaybackrate-before-load-expected.txt [new file with mode: 0644]
LayoutTests/media/video-defaultplaybackrate-before-load.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/HTMLMediaElement.h
Source/WebCore/platform/graphics/MediaPlayer.cpp
Source/WebCore/platform/graphics/MediaPlayer.h
Source/WebCore/platform/graphics/MediaPlayerPrivate.h
Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp
Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h
Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp
Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.h
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm
Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm

index 6edbf09..ebe9876 100644 (file)
@@ -1,3 +1,13 @@
+2015-01-12  Jer Noble  <jer.noble@apple.com>
+
+        defaultPlaybackRate not respected when set before source is loaded
+        https://bugs.webkit.org/show_bug.cgi?id=140282
+
+        Reviewed by Eric Carlson.
+
+        * media/video-defaultplaybackrate-before-load-expected.txt: Added.
+        * media/video-defaultplaybackrate-before-load.html: Added.
+
 2015-01-12  Andrzej Badowski  <a.badowski@samsung.com>
 
         AX: [ATK] Whether to show the title attribute, if there is a label with the attribute for?
diff --git a/LayoutTests/media/video-defaultplaybackrate-before-load-expected.txt b/LayoutTests/media/video-defaultplaybackrate-before-load-expected.txt
new file mode 100644 (file)
index 0000000..31c5fa2
--- /dev/null
@@ -0,0 +1,10 @@
+
+RUN(video.defaultPlaybackRate = 0.5)
+EVENT(canplaythrough)
+EXPECTED (video.playbackRate == '0.5') OK
+EXPECTED (video.defaultPlaybackRate == '0.5') OK
+EVENT(timeupdate)
+EVENT(timeupdate)
+EXPECTED (effectivePlaybackRate < '0.75') OK
+END OF TEST
+
diff --git a/LayoutTests/media/video-defaultplaybackrate-before-load.html b/LayoutTests/media/video-defaultplaybackrate-before-load.html
new file mode 100644 (file)
index 0000000..cb477f4
--- /dev/null
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>test playbackRate and defaultPlaybackRate</title>
+        <script src=media-file.js></script>
+        <script src=video-test.js></script>
+        <script>
+            var wallClockAtFirstTimeUpdate;
+            var mediaTimeAtFirstTimeUpdate;
+            var effectivePlaybackRate;
+
+            function start()
+            {
+                findMediaElement();
+                waitForEvent('canplaythrough', canplaythrough);
+                run('video.defaultPlaybackRate = 0.5');
+                setSrcByTagName('video', findMediaFile('video', 'content/test'));
+            }
+
+            function canplaythrough()
+            {
+                testExpected('video.playbackRate', 0.5);
+                testExpected('video.defaultPlaybackRate', 0.5);
+
+                waitForEvent('timeupdate', timeupdate);
+                video.play();
+            }
+
+            function timeupdate()
+            {
+                var now = Date.now() / 1000;
+                if (!wallClockAtFirstTimeUpdate) {
+                    wallClockAtFirstTimeUpdate = now;
+                    mediaTimeAtFirstTimeUpdate = video.currentTime;
+                    return;
+                }
+
+                if (wallClockAtFirstTimeUpdate == now)
+                    return;
+
+                var wallClockDelta = wallClockAtFirstTimeUpdate - now;
+                var mediaTimeDelta = mediaTimeAtFirstTimeUpdate - video.currentTime;
+                effectivePlaybackRate = mediaTimeDelta / wallClockDelta;
+
+                testExpected('effectivePlaybackRate', .75, '<');
+                endTest();
+            }
+
+        </script>
+    </head>
+
+    <body onload="start()">
+        <video controls></video>
+    </body>
+</html>
index de98757..b6b9ea9 100644 (file)
@@ -1,3 +1,68 @@
+2015-01-12  Jer Noble  <jer.noble@apple.com>
+
+        defaultPlaybackRate not respected when set before source is loaded
+        https://bugs.webkit.org/show_bug.cgi?id=140282
+
+        Reviewed by Eric Carlson.
+
+        Test: media/video-defaultplaybackrate-before-load.html
+
+        When the HTMLMediaElement is notified that the media player's rate has changed, it asks
+        for the rate from MediaPlayer. However, MediaPlayer never requests the playback rate
+        from the underlying MediaPlayerPrivate; it just returns the last rate which was set, or
+        1 if no rate was set. HTMLMediaElement then sets its playbackRate to the returned
+        value. So the end result is that the value from defaultPlaybackRate is overwritten by
+        the default value of 1 in MediaPlayer.
+
+        Rather than caching the requested rate in MediaPlayer, cache the value reported by
+        MediaPlayer inside HTMLMediaElement. And instead of returning the reported playback
+        rate from HTMLMediaElement.playbackRate, just return the last value set. The reported
+        value is still used for estimating the current time during playback.
+
+        Add MediaPlayerPrivate interface method to return the current playback rate.
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::HTMLMediaElement): Initialize m_reportedPlaybackRate.
+        (WebCore::HTMLMediaElement::effectivePlaybackRate): Return m_reportedPlaybackRate.
+        (WebCore::HTMLMediaElement::requestedPlaybackRate): Return m_playbackRate.
+        (WebCore::HTMLMediaElement::updatePlaybackRate): Use requestedPlaybackRate() instead
+            of effectivePlaybackRate();
+        (WebCore::HTMLMediaElement::ended): Ditto.
+        (WebCore::HTMLMediaElement::playbackProgressTimerFired): Ditto.
+        (WebCore::HTMLMediaElement::endedPlayback): Ditto.
+        (WebCore::HTMLMediaElement::updatePlayState): Ditto.
+        (WebCore::HTMLMediaElement::mediaPlayerRateChanged): Set m_reportedPlaybackRate.
+        (WebCore::HTMLMediaElement::mediaPlayerRequestedPlaybackRate): Return
+            requestedPlaybackRate() if playing and 0 if not.
+        * html/HTMLMediaElement.h:
+        * platform/graphics/MediaPlayer.cpp:
+        (WebCore::MediaPlayer::MediaPlayer): Removed m_rate.
+        (WebCore::MediaPlayer::rate): Pass to MediaPlayerPrivate.
+        (WebCore::MediaPlayer::setRate): Do not cache the rate.
+        (WebCore::MediaPlayer::requestedRate): Added; ask HTMLMediaElement.
+        * platform/graphics/MediaPlayer.h:
+        (WebCore::MediaPlayerClient::mediaPlayerRequestedPlaybackRate): Added.
+        * platform/graphics/MediaPlayerPrivate.h:
+        (WebCore::MediaPlayerPrivateInterface::rate): Added.
+        * platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp:
+        (WebCore::MediaPlayerPrivateAVFoundation::MediaPlayerPrivateAVFoundation):
+            Do not cache the requested rate.
+        (WebCore::MediaPlayerPrivateAVFoundation::requestedRate): Pass to MediaPlayer.
+        (WebCore::MediaPlayerPrivateAVFoundation::setRate): Deleted.
+        * platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.h:
+        (WebCore::MediaPlayerPrivateAVFoundation::requestedRate): Deleted.
+        * platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp:
+        (WebCore::MediaPlayerPrivateAVFoundationCF::setRate): Renamed from updateRate.
+        (WebCore::MediaPlayerPrivateAVFoundationCF::rate): Fetch the rate from the player.
+        * platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.h:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::setRateDouble): Renamed from updateRate.
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::rate): Fetch the rate from the player.
+        * platform/graphics/mac/MediaPlayerPrivateQTKit.h:
+        * platform/graphics/mac/MediaPlayerPrivateQTKit.mm:
+        (WebCore::MediaPlayerPrivateQTKit::rate): Fetch the rate from the QTMovie.
+
 2015-01-11  Anders Carlsson  <andersca@apple.com>
 
         Merge DatabaseBase into Database
index 87b3610..a38b447 100644 (file)
@@ -262,8 +262,9 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& docum
     , m_seekTimer(*this, &HTMLMediaElement::seekTimerFired)
     , m_playedTimeRanges()
     , m_asyncEventQueue(*this)
-    , m_playbackRate(1.0f)
-    , m_defaultPlaybackRate(1.0f)
+    , m_requestedPlaybackRate(1)
+    , m_reportedPlaybackRate(1)
+    , m_defaultPlaybackRate(1)
     , m_webkitPreservesPitch(true)
     , m_networkState(NETWORK_EMPTY)
     , m_readyState(HAVE_NOTHING)
@@ -2653,12 +2654,17 @@ void HTMLMediaElement::setDefaultPlaybackRate(double rate)
 
 double HTMLMediaElement::effectivePlaybackRate() const
 {
-    return m_mediaController ? m_mediaController->playbackRate() : m_playbackRate;
+    return m_mediaController ? m_mediaController->playbackRate() : m_reportedPlaybackRate;
+}
+
+double HTMLMediaElement::requestedPlaybackRate() const
+{
+    return m_mediaController ? m_mediaController->playbackRate() : m_requestedPlaybackRate;
 }
 
 double HTMLMediaElement::playbackRate() const
 {
-    return m_playbackRate;
+    return m_requestedPlaybackRate;
 }
 
 void HTMLMediaElement::setPlaybackRate(double rate)
@@ -2668,8 +2674,8 @@ void HTMLMediaElement::setPlaybackRate(double rate)
     if (m_player && potentiallyPlaying() && m_player->rate() != rate && !m_mediaController)
         m_player->setRate(rate);
 
-    if (m_playbackRate != rate) {
-        m_playbackRate = rate;
+    if (m_requestedPlaybackRate != rate) {
+        m_reportedPlaybackRate = m_requestedPlaybackRate = rate;
         invalidateCachedTime();
         scheduleEvent(eventNames().ratechangeEvent);
     }
@@ -2677,9 +2683,9 @@ void HTMLMediaElement::setPlaybackRate(double rate)
 
 void HTMLMediaElement::updatePlaybackRate()
 {
-    double effectiveRate = effectivePlaybackRate();
-    if (m_player && potentiallyPlaying() && m_player->rate() != effectiveRate)
-        m_player->setRate(effectiveRate);
+    double requestedRate = requestedPlaybackRate();
+    if (m_player && potentiallyPlaying() && m_player->rate() != requestedRate)
+        m_player->setRate(requestedRate);
 }
 
 bool HTMLMediaElement::webkitPreservesPitch() const
@@ -2704,7 +2710,7 @@ bool HTMLMediaElement::ended() const
     // 4.8.10.8 Playing the media resource
     // The ended attribute must return true if the media element has ended 
     // playback and the direction of playback is forwards, and false otherwise.
-    return endedPlayback() && effectivePlaybackRate() > 0;
+    return endedPlayback() && requestedPlaybackRate() > 0;
 }
 
 bool HTMLMediaElement::autoplay() const
@@ -3141,7 +3147,7 @@ void HTMLMediaElement::playbackProgressTimerFired()
 {
     ASSERT(m_player);
 
-    if (m_fragmentEndTime.isValid() && currentMediaTime() >= m_fragmentEndTime && effectivePlaybackRate() > 0) {
+    if (m_fragmentEndTime.isValid() && currentMediaTime() >= m_fragmentEndTime && requestedPlaybackRate() > 0) {
         m_fragmentEndTime = MediaTime::invalidTime();
         if (!m_mediaController && !m_paused) {
             // changes paused to true and fires a simple event named pause at the media element.
@@ -4195,13 +4201,14 @@ void HTMLMediaElement::mediaPlayerDurationChanged(MediaPlayer* player)
 
 void HTMLMediaElement::mediaPlayerRateChanged(MediaPlayer*)
 {
-    LOG(Media, "HTMLMediaElement::mediaPlayerRateChanged(%p)", this);
-
     beginProcessingMediaPlayerCallback();
 
     // Stash the rate in case the one we tried to set isn't what the engine is
     // using (eg. it can't handle the rate we set)
-    m_playbackRate = m_player->rate();
+    m_reportedPlaybackRate = m_player->rate();
+
+    LOG(Media, "HTMLMediaElement::mediaPlayerRateChanged(%p) - rate: %lf", this, m_reportedPlaybackRate);
+
     if (m_playing)
         invalidateCachedTime();
 
@@ -4433,12 +4440,12 @@ bool HTMLMediaElement::endedPlayback() const
     // of playback is forwards, Either the media element does not have a loop attribute specified,
     // or the media element has a current media controller.
     MediaTime now = currentMediaTime();
-    if (effectivePlaybackRate() > 0)
+    if (requestedPlaybackRate() > 0)
         return dur > MediaTime::zeroTime() && now >= dur && (!loop() || m_mediaController);
 
     // or the current playback position is the earliest possible position and the direction 
     // of playback is backwards
-    if (effectivePlaybackRate() < 0)
+    if (requestedPlaybackRate() < 0)
         return now <= MediaTime::zeroTime();
 
     return false;
@@ -4539,7 +4546,7 @@ void HTMLMediaElement::updatePlayState()
 
             // Set rate, muted before calling play in case they were set before the media engine was setup.
             // The media engine should just stash the rate and muted values since it isn't already playing.
-            m_player->setRate(effectivePlaybackRate());
+            m_player->setRate(requestedPlaybackRate());
             m_player->setMuted(effectiveMuted());
 
             if (m_firstTimePlaying) {
@@ -5790,6 +5797,11 @@ void HTMLMediaElement::mediaPlayerEngineFailedToLoad() const
     diagnosticLoggingClient->logDiagnosticMessageWithValue(DiagnosticLoggingKeys::engineFailedToLoadKey(), engine, String::number(m_player->platformErrorCode()));
 }
 
+double HTMLMediaElement::mediaPlayerRequestedPlaybackRate() const
+{
+    return potentiallyPlaying() ? requestedPlaybackRate() : 0;
+}
+
 void HTMLMediaElement::removeBehaviorsRestrictionsAfterFirstUserGesture()
 {
     m_mediaSession->removeBehaviorRestriction(HTMLMediaSession::RequireUserGestureForLoad);
index b19f0cb..43b3582 100644 (file)
@@ -532,6 +532,7 @@ private:
     void setNetworkState(MediaPlayer::NetworkState);
 
     double effectivePlaybackRate() const;
+    double requestedPlaybackRate() const;
 
     virtual void mediaPlayerNetworkStateChanged(MediaPlayer*) override;
     virtual void mediaPlayerReadyStateChanged(MediaPlayer*) override;
@@ -606,6 +607,8 @@ private:
     virtual bool mediaPlayerIsInMediaDocument() const override final;
     virtual void mediaPlayerEngineFailedToLoad() const override final;
 
+    virtual double mediaPlayerRequestedPlaybackRate() const override final;
+
     void loadTimerFired();
     void progressEventTimerFired();
     void playbackProgressTimerFired();
@@ -745,7 +748,8 @@ private:
     RefPtr<TimeRanges> m_playedTimeRanges;
     GenericEventQueue m_asyncEventQueue;
 
-    double m_playbackRate;
+    double m_requestedPlaybackRate;
+    double m_reportedPlaybackRate;
     double m_defaultPlaybackRate;
     bool m_webkitPreservesPitch;
     NetworkState m_networkState;
index f11365e..c14472e 100644 (file)
@@ -312,7 +312,6 @@ MediaPlayer::MediaPlayer(MediaPlayerClient& client)
     , m_currentMediaEngine(0)
     , m_preload(Auto)
     , m_visible(false)
-    , m_rate(1.0f)
     , m_volume(1.0f)
     , m_muted(false)
     , m_preservesPitch(true)
@@ -679,15 +678,19 @@ void MediaPlayer::setClosedCaptionsVisible(bool closedCaptionsVisible)
 
 double MediaPlayer::rate() const
 {
-    return m_rate;
+    return m_private->rate();
 }
 
 void MediaPlayer::setRate(double rate)
 {
-    m_rate = rate;
     m_private->setRateDouble(rate);
 }
 
+double MediaPlayer::requestedRate() const
+{
+    return m_client.mediaPlayerRequestedPlaybackRate();
+}
+
 bool MediaPlayer::preservesPitch() const
 {
     return m_preservesPitch;
index 43d9653..3b9463e 100644 (file)
@@ -262,6 +262,8 @@ public:
 
     virtual bool mediaPlayerIsInMediaDocument() const { return false; }
     virtual void mediaPlayerEngineFailedToLoad() const { }
+
+    virtual double mediaPlayerRequestedPlaybackRate() const { return 0; }
 };
 
 class MediaPlayerSupportsTypeClient {
@@ -364,6 +366,7 @@ public:
 
     double rate() const;
     void setRate(double);
+    double requestedRate() const;
 
     bool preservesPitch() const;
     void setPreservesPitch(bool);
@@ -595,7 +598,6 @@ private:
     IntSize m_size;
     Preload m_preload;
     bool m_visible;
-    double m_rate;
     double m_volume;
     bool m_muted;
     bool m_preservesPitch;
index 16361e8..44f8f6c 100644 (file)
@@ -102,6 +102,7 @@ public:
 
     virtual void setRate(float) { }
     virtual void setRateDouble(double rate) { setRate(rate); }
+    virtual double rate() const { return 0; }
 
     virtual void setPreservesPitch(bool) { }
 
index f8c5518..4d96886 100644 (file)
@@ -60,7 +60,6 @@ MediaPlayerPrivateAVFoundation::MediaPlayerPrivateAVFoundation(MediaPlayer* play
     , m_cachedDuration(MediaTime::invalidTime())
     , m_reportedDuration(MediaTime::invalidTime())
     , m_maxTimeLoadedAtLastDidLoadingProgress(MediaTime::invalidTime())
-    , m_requestedRate(1)
     , m_delayCallbacks(0)
     , m_delayCharacteristicsChangedNotification(0)
     , m_mainThreadCallPending(false)
@@ -290,14 +289,6 @@ void MediaPlayerPrivateAVFoundation::seekWithTolerance(const MediaTime& mediaTim
     seekToTime(time, negativeTolerance, positiveTolerance);
 }
 
-void MediaPlayerPrivateAVFoundation::setRate(float rate)
-{
-    LOG(Media, "MediaPlayerPrivateAVFoundation::setRate(%p) - seting to %f", this, rate);
-    m_requestedRate = rate;
-
-    updateRate();
-}
-
 bool MediaPlayerPrivateAVFoundation::paused() const
 {
     if (!metaDataAvailable())
@@ -419,6 +410,11 @@ MediaTime MediaPlayerPrivateAVFoundation::minMediaTimeSeekable() const
     return m_cachedMinTimeSeekable;
 }
 
+double MediaPlayerPrivateAVFoundation::requestedRate() const
+{
+    return m_player->requestedRate();
+}
+
 MediaTime MediaPlayerPrivateAVFoundation::maxTimeLoaded() const
 {
     if (!metaDataAvailable())
index 80e1467..7b55846 100644 (file)
@@ -171,7 +171,6 @@ protected:
     virtual void seek(const MediaTime&) override;
     virtual void seekWithTolerance(const MediaTime&, const MediaTime&, const MediaTime&) override;
     virtual bool seeking() const override;
-    virtual void setRate(float) override;
     virtual bool paused() const override;
     virtual void setVolume(float) = 0;
     virtual bool hasClosedCaptions() const override { return m_cachedHasCaptions; }
@@ -232,8 +231,6 @@ protected:
     virtual void platformPlay() = 0;
     virtual void platformPause() = 0;
     virtual void checkPlayability() = 0;
-    virtual void updateRate() = 0;
-    virtual float rate() const = 0;
     virtual void seekToTime(const MediaTime&, const MediaTime& negativeTolerance, const MediaTime& positiveTolerance) = 0;
     virtual unsigned long long totalBytes() const = 0;
     virtual std::unique_ptr<PlatformTimeRanges> platformBufferedTimeRanges() const = 0;
@@ -277,7 +274,7 @@ protected:
     MediaRenderingMode preferredRenderingMode() const;
 
     bool metaDataAvailable() const { return m_readyState >= MediaPlayer::HaveMetadata; }
-    float requestedRate() const { return m_requestedRate; }
+    double requestedRate() const;
     MediaTime maxTimeLoaded() const;
     bool isReadyForVideoSetup() const;
     virtual void setUpVideoRendering();
@@ -331,7 +328,6 @@ private:
     mutable MediaTime m_cachedDuration;
     MediaTime m_reportedDuration;
     mutable MediaTime m_maxTimeLoadedAtLastDidLoadingProgress;
-    float m_requestedRate;
     mutable int m_delayCallbacks;
     int m_delayCharacteristicsChangedNotification;
     bool m_mainThreadCallPending;
index 593e382..a34f0d4 100644 (file)
@@ -643,24 +643,24 @@ void MediaPlayerPrivateAVFoundationCF::setClosedCaptionsVisible(bool closedCapti
     AVCFPlayerSetClosedCaptionDisplayEnabled(avPlayer(m_avfWrapper), closedCaptionsVisible);
 }
 
-void MediaPlayerPrivateAVFoundationCF::updateRate()
+void MediaPlayerPrivateAVFoundationCF::setRate(float rate)
 {
-    LOG(Media, "MediaPlayerPrivateAVFoundationCF::updateRate(%p)", this);
+    LOG(Media, "MediaPlayerPrivateAVFoundationCF::setRate(%p) - rate: %f", this, rate);
     if (!metaDataAvailable() || !avPlayer(m_avfWrapper))
         return;
 
     setDelayCallbacks(true);
-    AVCFPlayerSetRate(avPlayer(m_avfWrapper), requestedRate());
+    AVCFPlayerSetRate(avPlayer(m_avfWrapper), rate);
     setDelayCallbacks(false);
 }
 
-float MediaPlayerPrivateAVFoundationCF::rate() const
+double MediaPlayerPrivateAVFoundationCF::rate() const
 {
     if (!metaDataAvailable() || !avPlayer(m_avfWrapper))
         return 0;
 
     setDelayCallbacks(true);
-    float currentRate = AVCFPlayerGetRate(avPlayer(m_avfWrapper));
+    double currentRate = AVCFPlayerGetRate(avPlayer(m_avfWrapper));
     setDelayCallbacks(false);
 
     return currentRate;
index 3be45ee..b1cdcd0 100644 (file)
@@ -90,8 +90,8 @@ private:
     virtual MediaPlayerPrivateAVFoundation::AssetStatus assetStatus() const;
 
     virtual void checkPlayability();
-    virtual void updateRate();
-    virtual float rate() const;
+    virtual void setRate(float) override;
+    virtual double rate() const override;
     virtual void seekToTime(const MediaTime&, const MediaTime& negativeTolerance, const MediaTime& positiveTolerance);
     virtual unsigned long long totalBytes() const;
     virtual std::unique_ptr<PlatformTimeRanges> platformBufferedTimeRanges() const;
index b861638..7049ccc 100644 (file)
@@ -177,8 +177,8 @@ private:
     virtual long assetErrorCode() const;
 
     virtual void checkPlayability();
-    virtual void updateRate();
-    virtual float rate() const;
+    virtual void setRateDouble(double) override;
+    virtual double rate() const;
     virtual void seekToTime(const MediaTime&, const MediaTime& negativeTolerance, const MediaTime& positiveTolerance);
     virtual unsigned long long totalBytes() const;
     virtual std::unique_ptr<PlatformTimeRanges> platformBufferedTimeRanges() const;
index d3d2218..f7700f6 100644 (file)
@@ -1253,15 +1253,16 @@ void MediaPlayerPrivateAVFoundationObjC::setClosedCaptionsVisible(bool closedCap
     LOG(Media, "MediaPlayerPrivateAVFoundationObjC::setClosedCaptionsVisible(%p) - set to %s", this, boolString(closedCaptionsVisible));
 }
 
-void MediaPlayerPrivateAVFoundationObjC::updateRate()
+void MediaPlayerPrivateAVFoundationObjC::setRateDouble(double rate)
+
 {
     setDelayCallbacks(true);
-    m_cachedRate = requestedRate();
-    [m_avPlayer.get() setRate:requestedRate()];
+    m_cachedRate = rate;
+    [m_avPlayer.get() setRate:rate];
     setDelayCallbacks(false);
 }
 
-float MediaPlayerPrivateAVFoundationObjC::rate() const
+double MediaPlayerPrivateAVFoundationObjC::rate() const
 {
     if (!metaDataAvailable())
         return 0;
index 11b6a06..e767045 100644 (file)
@@ -104,6 +104,7 @@ private:
     virtual void seek(const MediaTime&) override;
     
     void setRate(float);
+    virtual double rate() const override;
     void setVolume(float);
     void setPreservesPitch(bool);
 
index 3691206..6b2ba48 100644 (file)
@@ -792,6 +792,11 @@ void MediaPlayerPrivateQTKit::setRate(float rate)
         [m_qtMovie.get() setRate:rate];
 }
 
+double MediaPlayerPrivateQTKit::rate() const
+{
+    return m_qtMovie ? [m_qtMovie rate] : 0;
+}
+
 void MediaPlayerPrivateQTKit::setPreservesPitch(bool preservesPitch)
 {
     LOG(Media, "MediaPlayerPrivateQTKit::setPreservesPitch(%p) - preservesPitch %d", this, (int)preservesPitch);