Title: [280308] trunk
Revision
280308
Author
[email protected]
Date
2021-07-26 12:36:50 -0700 (Mon, 26 Jul 2021)

Log Message

[Cocoa] Playback stalls on bilibili.com
https://bugs.webkit.org/show_bug.cgi?id=228239
<rdar://80419477>

Reviewed by Eric Carlson.

Source/WebCore:

Test: media/media-source/media-source-effectiveplaybackrate.html

bilibili.com will attempt to detect playback stalls by detecting when video.currentTime
returns the same value while video.paused is false. When the GPU process is enabled, we use
a heuristic to provide the answer to currentTime to avoid making synchronous calls to the
GPU process. This heuristic uses the reported playback rate of the MediaPlayerPrivate to
derive the currentTime. However, MediaPlayerPrivateAVFoundationObjC does not override the
default implementation of rate(), and so always returns a reported rate of zero.

To make the call less ambiguous, add a MediaPlayer and MediaPlayerPrivate effectiveRate()
method, which by default will just return rate(), as some ports only report the
requested rate and not the effective rate. Then add overrides for both rate() and
effectiveRate() on both MediaPlayerPrivateAVFoundationObjC and
MediaPlayerPrivateMediaSourceAVFObjC.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::updatePlaybackRate):
(WebCore::HTMLMediaElement::mediaPlayerRateChanged):
* platform/graphics/MediaPlayer.cpp:
(WebCore::MediaPlayer::effectiveRate const):
* platform/graphics/MediaPlayer.h:
* platform/graphics/MediaPlayerPrivate.h:
(WebCore::MediaPlayerPrivateInterface::effectiveRate const):
* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
(WebCore::MediaPlayerPrivateAVFoundationObjC::rate const):
(WebCore::MediaPlayerPrivateAVFoundationObjC::effectiveRate const):
* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::rate const):
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::effectiveRate const):
* testing/Internals.cpp:
(WebCore::Internals::isMediaElementHidden):
(WebCore::Internals::elementEffectivePlaybackRate):
* testing/Internals.h:
* testing/Internals.idl:

Source/WebKit:

Replace rate() -> effectiveRate().

* GPUProcess/media/RemoteMediaPlayerProxy.cpp:
(WebKit::RemoteMediaPlayerProxy::mediaPlayerRateChanged):

LayoutTests:

* media/media-source/media-source-effectiveplaybackrate-expected.txt: Added.
* media/media-source/media-source-effectiveplaybackrate.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (280307 => 280308)


--- trunk/LayoutTests/ChangeLog	2021-07-26 19:22:45 UTC (rev 280307)
+++ trunk/LayoutTests/ChangeLog	2021-07-26 19:36:50 UTC (rev 280308)
@@ -1,3 +1,14 @@
+2021-07-26  Jer Noble  <[email protected]>
+
+        [Cocoa] Playback stalls on bilibili.com
+        https://bugs.webkit.org/show_bug.cgi?id=228239
+        <rdar://80419477>
+
+        Reviewed by Eric Carlson.
+
+        * media/media-source/media-source-effectiveplaybackrate-expected.txt: Added.
+        * media/media-source/media-source-effectiveplaybackrate.html: Added.
+
 2021-07-26  Aditya Keerthi  <[email protected]>
 
         [iOS] Page background color does not update after UIUserInterfaceLevel change

Added: trunk/LayoutTests/media/media-source/media-source-effectiveplaybackrate-expected.txt (0 => 280308)


--- trunk/LayoutTests/media/media-source/media-source-effectiveplaybackrate-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/media/media-source/media-source-effectiveplaybackrate-expected.txt	2021-07-26 19:36:50 UTC (rev 280308)
@@ -0,0 +1,13 @@
+
+RUN(video.src = ""
+EVENT(sourceopen)
+RUN(sourceBuffer = source.addSourceBuffer(loader.type()))
+RUN(sourceBuffer.appendBuffer(loader.initSegment()))
+EVENT(update)
+Append a media segment.
+RUN(sourceBuffer.appendBuffer(loader.mediaSegment(0)))
+EVENT(update)
+RUN(video.play())
+EXPECTED (internals.elementEffectivePlaybackRate(video) != '0') OK
+END OF TEST
+

Added: trunk/LayoutTests/media/media-source/media-source-effectiveplaybackrate.html (0 => 280308)


--- trunk/LayoutTests/media/media-source/media-source-effectiveplaybackrate.html	                        (rev 0)
+++ trunk/LayoutTests/media/media-source/media-source-effectiveplaybackrate.html	2021-07-26 19:36:50 UTC (rev 280308)
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>media-source-resize</title>
+    <script src=""
+    <script src=""
+    <script>
+    var loader;
+    var source;
+    var sourceBuffer;
+
+    function loaderPromise(loader) {
+        return new Promise((resolve, reject) => {
+            loader._onload_ = resolve;
+            loader._onerror_ = reject;
+        });
+    }
+
+    window.addEventListener('load', async event => {
+        findMediaElement();
+
+        loader = new MediaSourceLoader('content/test-fragmented-manifest.json');
+        await loaderPromise(loader);
+
+        source = new MediaSource();
+        run('video.src = ""
+        await waitFor(source, 'sourceopen');
+        waitFor(video, 'error').then(failTest);
+
+        run('sourceBuffer = source.addSourceBuffer(loader.type())');
+        run('sourceBuffer.appendBuffer(loader.initSegment())');
+        await waitFor(sourceBuffer, 'update');
+
+        consoleWrite('Append a media segment.')
+        run('sourceBuffer.appendBuffer(loader.mediaSegment(0))');
+        await waitFor(sourceBuffer, 'update');
+
+        run('video.play()');
+        await testExpectedEventually('internals.elementEffectivePlaybackRate(video)', 0, '!=');
+
+        endTest();
+    });
+
+    </script>
+</head>
+<body>
+    <video controls></video>
+</body>
+</html>
\ No newline at end of file

Modified: trunk/Source/WebCore/ChangeLog (280307 => 280308)


--- trunk/Source/WebCore/ChangeLog	2021-07-26 19:22:45 UTC (rev 280307)
+++ trunk/Source/WebCore/ChangeLog	2021-07-26 19:36:50 UTC (rev 280308)
@@ -1,3 +1,48 @@
+2021-07-26  Jer Noble  <[email protected]>
+
+        [Cocoa] Playback stalls on bilibili.com
+        https://bugs.webkit.org/show_bug.cgi?id=228239
+        <rdar://80419477>
+
+        Reviewed by Eric Carlson.
+
+        Test: media/media-source/media-source-effectiveplaybackrate.html
+
+        bilibili.com will attempt to detect playback stalls by detecting when video.currentTime
+        returns the same value while video.paused is false. When the GPU process is enabled, we use
+        a heuristic to provide the answer to currentTime to avoid making synchronous calls to the
+        GPU process. This heuristic uses the reported playback rate of the MediaPlayerPrivate to
+        derive the currentTime. However, MediaPlayerPrivateAVFoundationObjC does not override the
+        default implementation of rate(), and so always returns a reported rate of zero.
+
+        To make the call less ambiguous, add a MediaPlayer and MediaPlayerPrivate effectiveRate()
+        method, which by default will just return rate(), as some ports only report the
+        requested rate and not the effective rate. Then add overrides for both rate() and
+        effectiveRate() on both MediaPlayerPrivateAVFoundationObjC and
+        MediaPlayerPrivateMediaSourceAVFObjC.
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::updatePlaybackRate):
+        (WebCore::HTMLMediaElement::mediaPlayerRateChanged):
+        * platform/graphics/MediaPlayer.cpp:
+        (WebCore::MediaPlayer::effectiveRate const):
+        * platform/graphics/MediaPlayer.h:
+        * platform/graphics/MediaPlayerPrivate.h:
+        (WebCore::MediaPlayerPrivateInterface::effectiveRate const):
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::rate const):
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::effectiveRate const):
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
+        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::rate const):
+        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::effectiveRate const):
+        * testing/Internals.cpp:
+        (WebCore::Internals::isMediaElementHidden):
+        (WebCore::Internals::elementEffectivePlaybackRate):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
 2021-07-26  Ada Chan  <[email protected]>
 
         [WebXR] WebXRSession::m_visibilityState is uninitialized

Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (280307 => 280308)


--- trunk/Source/WebCore/html/HTMLMediaElement.cpp	2021-07-26 19:22:45 UTC (rev 280307)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp	2021-07-26 19:36:50 UTC (rev 280308)
@@ -3369,7 +3369,7 @@
 void HTMLMediaElement::updatePlaybackRate()
 {
     double requestedRate = requestedPlaybackRate();
-    if (m_player && potentiallyPlaying() && m_player->rate() != requestedRate)
+    if (m_player && potentiallyPlaying() && m_player->effectiveRate() != requestedRate)
         m_player->setRate(requestedRate);
 }
 
@@ -4922,7 +4922,7 @@
 
     // 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_reportedPlaybackRate = m_player->rate();
+    m_reportedPlaybackRate = m_player->effectiveRate();
 
     ALWAYS_LOG(LOGIDENTIFIER, "rate: ", m_reportedPlaybackRate);
 

Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (280307 => 280308)


--- trunk/Source/WebCore/html/HTMLMediaElement.h	2021-07-26 19:22:45 UTC (rev 280307)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h	2021-07-26 19:36:50 UTC (rev 280308)
@@ -613,6 +613,8 @@
     bool isChangingVideoFullscreenMode() const { return m_changingVideoFullscreenMode; }
 
 private:
+    friend class Internals;
+
     void createMediaPlayer();
 
     bool supportsFocus() const override;
@@ -645,7 +647,7 @@
     void setReadyState(MediaPlayer::ReadyState);
     void setNetworkState(MediaPlayer::NetworkState);
 
-    double effectivePlaybackRate() const;
+    WEBCORE_EXPORT double effectivePlaybackRate() const;
     double requestedPlaybackRate() const;
 
     void mediaPlayerNetworkStateChanged() final;

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp (280307 => 280308)


--- trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp	2021-07-26 19:22:45 UTC (rev 280307)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp	2021-07-26 19:36:50 UTC (rev 280308)
@@ -919,6 +919,11 @@
     m_private->setRateDouble(rate);
 }
 
+double MediaPlayer::effectiveRate() const
+{
+    return m_private->effectiveRate();
+}
+
 double MediaPlayer::requestedRate() const
 {
     return client().mediaPlayerRequestedPlaybackRate();

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.h (280307 => 280308)


--- trunk/Source/WebCore/platform/graphics/MediaPlayer.h	2021-07-26 19:22:45 UTC (rev 280307)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.h	2021-07-26 19:36:50 UTC (rev 280308)
@@ -411,6 +411,8 @@
 
     double rate() const;
     void setRate(double);
+    double effectiveRate() const;
+
     double requestedRate() const;
 
     bool supportsPlayAtHostTime() const;

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h (280307 => 280308)


--- trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h	2021-07-26 19:22:45 UTC (rev 280307)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h	2021-07-26 19:36:50 UTC (rev 280308)
@@ -124,6 +124,7 @@
     virtual void setRate(float) { }
     virtual void setRateDouble(double rate) { setRate(rate); }
     virtual double rate() const { return 0; }
+    virtual double effectiveRate() const { return rate(); }
 
     virtual void setPreservesPitch(bool) { }
     virtual void setPitchCorrectionAlgorithm(MediaPlayer::PitchCorrectionAlgorithm) { }

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h (280307 => 280308)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h	2021-07-26 19:22:45 UTC (rev 280307)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h	2021-07-26 19:36:50 UTC (rev 280308)
@@ -197,6 +197,7 @@
     void checkPlayability();
     void setRateDouble(double) final;
     double rate() const final;
+    double effectiveRate() const final;
     void setPreservesPitch(bool) final;
     void setPitchCorrectionAlgorithm(MediaPlayer::PitchCorrectionAlgorithm) final;
     void seekToTime(const MediaTime&, const MediaTime& negativeTolerance, const MediaTime& positiveTolerance) final;

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm (280307 => 280308)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm	2021-07-26 19:22:45 UTC (rev 280307)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm	2021-07-26 19:36:50 UTC (rev 280308)
@@ -1594,6 +1594,14 @@
     if (!metaDataAvailable())
         return 0;
 
+    return m_requestedRate;
+}
+
+double MediaPlayerPrivateAVFoundationObjC::effectiveRate() const
+{
+    if (!metaDataAvailable())
+        return 0;
+
     return m_cachedRate;
 }
 

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h (280307 => 280308)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h	2021-07-26 19:22:45 UTC (rev 280307)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h	2021-07-26 19:36:50 UTC (rev 280308)
@@ -204,6 +204,8 @@
     void seekWithTolerance(const MediaTime&, const MediaTime& negativeThreshold, const MediaTime& positiveThreshold) override;
     bool seeking() const override;
     void setRateDouble(double) override;
+    double rate() const override;
+    double effectiveRate() const override;
 
     void setPreservesPitch(bool) override;
 

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm (280307 => 280308)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm	2021-07-26 19:22:45 UTC (rev 280307)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm	2021-07-26 19:36:50 UTC (rev 280308)
@@ -592,6 +592,16 @@
         [m_synchronizer setRate:m_rate];
 }
 
+double MediaPlayerPrivateMediaSourceAVFObjC::rate() const
+{
+    return m_rate;
+}
+
+double MediaPlayerPrivateMediaSourceAVFObjC::effectiveRate() const
+{
+    return PAL::CMTimebaseGetRate([m_synchronizer timebase]);
+}
+
 void MediaPlayerPrivateMediaSourceAVFObjC::setPreservesPitch(bool preservesPitch)
 {
     ALWAYS_LOG(LOGIDENTIFIER, preservesPitch);

Modified: trunk/Source/WebCore/testing/Internals.cpp (280307 => 280308)


--- trunk/Source/WebCore/testing/Internals.cpp	2021-07-26 19:22:45 UTC (rev 280307)
+++ trunk/Source/WebCore/testing/Internals.cpp	2021-07-26 19:36:50 UTC (rev 280308)
@@ -5032,6 +5032,11 @@
 {
     return media.elementIsHidden();
 }
+
+double Internals::elementEffectivePlaybackRate(const HTMLMediaElement& media)
+{
+    return media.effectivePlaybackRate();
+}
 #endif
 
 ExceptionOr<void> Internals::setIsPlayingToBluetoothOverride(std::optional<bool> isPlaying)

Modified: trunk/Source/WebCore/testing/Internals.h (280307 => 280308)


--- trunk/Source/WebCore/testing/Internals.h	2021-07-26 19:22:45 UTC (rev 280307)
+++ trunk/Source/WebCore/testing/Internals.h	2021-07-26 19:36:50 UTC (rev 280308)
@@ -661,6 +661,7 @@
     double privatePlayerVolume(const HTMLMediaElement&);
     bool privatePlayerMuted(const HTMLMediaElement&);
     bool isMediaElementHidden(const HTMLMediaElement&);
+    double elementEffectivePlaybackRate(const HTMLMediaElement&);
 
     ExceptionOr<void> setOverridePreferredDynamicRangeMode(HTMLMediaElement&, const String&);
 #endif

Modified: trunk/Source/WebCore/testing/Internals.idl (280307 => 280308)


--- trunk/Source/WebCore/testing/Internals.idl	2021-07-26 19:22:45 UTC (rev 280307)
+++ trunk/Source/WebCore/testing/Internals.idl	2021-07-26 19:36:50 UTC (rev 280308)
@@ -701,6 +701,7 @@
     [Conditional=VIDEO] boolean privatePlayerMuted(HTMLMediaElement media);
     [Conditional=VIDEO] boolean isMediaElementHidden(HTMLMediaElement media);
     [Conditional=VIDEO] undefined setOverridePreferredDynamicRangeMode(HTMLMediaElement media, DOMString mode);
+    [Conditional=VIDEO] double elementEffectivePlaybackRate(HTMLMediaElement media);
 
     undefined setIsPlayingToBluetoothOverride(optional boolean? isPlaying = null);
 

Modified: trunk/Source/WebKit/ChangeLog (280307 => 280308)


--- trunk/Source/WebKit/ChangeLog	2021-07-26 19:22:45 UTC (rev 280307)
+++ trunk/Source/WebKit/ChangeLog	2021-07-26 19:36:50 UTC (rev 280308)
@@ -1,3 +1,16 @@
+2021-07-26  Jer Noble  <[email protected]>
+
+        [Cocoa] Playback stalls on bilibili.com
+        https://bugs.webkit.org/show_bug.cgi?id=228239
+        <rdar://80419477>
+
+        Reviewed by Eric Carlson.
+
+        Replace rate() -> effectiveRate().
+
+        * GPUProcess/media/RemoteMediaPlayerProxy.cpp:
+        (WebKit::RemoteMediaPlayerProxy::mediaPlayerRateChanged):
+
 2021-07-26  Chris Dumez  <[email protected]>
 
         Make sure the ProcessAssertion gets destroyed on the main thread

Modified: trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.cpp (280307 => 280308)


--- trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.cpp	2021-07-26 19:22:45 UTC (rev 280307)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.cpp	2021-07-26 19:36:50 UTC (rev 280308)
@@ -404,7 +404,7 @@
 {
     updateCachedVideoMetrics();
     sendCachedState();
-    m_webProcessConnection->send(Messages::MediaPlayerPrivateRemote::RateChanged(m_player->rate()), m_id);
+    m_webProcessConnection->send(Messages::MediaPlayerPrivateRemote::RateChanged(m_player->effectiveRate()), m_id);
 }
 
 void RemoteMediaPlayerProxy::mediaPlayerEngineFailedToLoad() const
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to