Title: [261341] trunk
Revision
261341
Author
eric.carl...@apple.com
Date
2020-05-07 16:05:40 -0700 (Thu, 07 May 2020)

Log Message

Poster set after playback begins should be ignored
https://bugs.webkit.org/show_bug.cgi?id=211464

Reviewed by Jer Noble.
Source/WebCore:

Redo the poster frame logic to use the `show poster flag` logic from the spec.

Test: media/video-poster-set-after-playback.html

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::HTMLMediaElement): Initialize m_showPoster.
(WebCore::HTMLMediaElement::prepareForLoad): m_displayMode was removed.
(WebCore::HTMLMediaElement::selectMediaResource): Call setShowPosterFlag.
(WebCore::HTMLMediaElement::loadResource): Remove calls to setDisplayMode and updateDisplayState,
they have been deleted.
(WebCore::HTMLMediaElement::waitForSourceChange): Call setShowPosterFlag. Update spec text.
(WebCore::HTMLMediaElement::noneSupported): Call setShowPosterFlag.
(WebCore::HTMLMediaElement::mediaLoadingFailed): Remove call to updateDisplayState.
(WebCore::HTMLMediaElement::setReadyState): Ditto.
(WebCore::HTMLMediaElement::seekWithTolerance): Call setShowPosterFlag.
(WebCore::HTMLMediaElement::seekTask):  Check m_showPoster, not displayMode.
(WebCore::HTMLMediaElement::playInternal): Call setShowPosterFlag.
(WebCore::HTMLMediaElement::mediaPlayerCharacteristicChanged): Don't check displayMode.
(WebCore::HTMLMediaElement::updatePlayState): No more setDisplayMode.
(WebCore::HTMLMediaElement::userCancelledLoad):  Call setShowPosterFlag.
(WebCore::HTMLMediaElement::mediaPlayerFirstVideoFrameAvailable): Deleted.
* html/HTMLMediaElement.h:
(WebCore::HTMLMediaElement::showPosterFlag const):
(WebCore::HTMLMediaElement::setShowPosterFlag):
(WebCore::HTMLMediaElement::displayMode const): Deleted.
(WebCore::HTMLMediaElement::setDisplayMode): Deleted.
(WebCore::HTMLMediaElement::updateDisplayState): Deleted.

* html/HTMLVideoElement.cpp:
(WebCore::HTMLVideoElement::didAttachRenderers): No more updateDisplayState.
(WebCore::HTMLVideoElement::parseAttribute): Ditto. Call updateFromElement when poster is removed.
(WebCore::HTMLVideoElement::shouldDisplayPosterImage const): New.
(WebCore::HTMLVideoElement::mediaPlayerFirstVideoFrameAvailable): New, update player and
renderer if the poster isn't supposed to be visible.
(WebCore::HTMLVideoElement::setDisplayMode): Deleted.
(WebCore::HTMLVideoElement::updateDisplayState): Deleted.
* html/HTMLVideoElement.h:

* rendering/RenderVideo.cpp:
(WebCore::RenderVideo::failedToLoadPosterImage const): New.
* rendering/RenderVideo.h:

* testing/Internals.cpp:
(WebCore::Internals::elementShouldDisplayPosterImage const):
* testing/Internals.h:
* testing/Internals.idl:

LayoutTests:

* media/video-poster-set-after-playback-expected.txt: Added.
* media/video-poster-set-after-playback.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (261340 => 261341)


--- trunk/LayoutTests/ChangeLog	2020-05-07 23:01:32 UTC (rev 261340)
+++ trunk/LayoutTests/ChangeLog	2020-05-07 23:05:40 UTC (rev 261341)
@@ -1,3 +1,13 @@
+2020-05-07  Eric Carlson  <eric.carl...@apple.com>
+
+        Poster set after playback begins should be ignored
+        https://bugs.webkit.org/show_bug.cgi?id=211464
+
+        Reviewed by Jer Noble.
+
+        * media/video-poster-set-after-playback-expected.txt: Added.
+        * media/video-poster-set-after-playback.html: Added.
+
 2020-05-07  Simon Fraser  <simon.fra...@apple.com>
 
         REGRESSION (r252161): Animation of box-shadow with border-radius set is flashy

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/the-video-element/intrinsic_sizes-expected.txt (261340 => 261341)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/the-video-element/intrinsic_sizes-expected.txt	2020-05-07 23:01:32 UTC (rev 261340)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/the-video-element/intrinsic_sizes-expected.txt	2020-05-07 23:05:40 UTC (rev 261341)
@@ -5,6 +5,6 @@
 PASS default object size is 300x150 
 PASS default height is half the width 
 PASS default width is twice the height 
-FAIL default object size after src is removed assert_equals: expected "320px" but got "300px"
+FAIL default object size after src is removed assert_equals: expected "300px" but got "320px"
 FAIL default object size after poster is removed assert_equals: expected "102px" but got "300px"
 

Added: trunk/LayoutTests/media/video-poster-set-after-playback-expected.txt (0 => 261341)


--- trunk/LayoutTests/media/video-poster-set-after-playback-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/media/video-poster-set-after-playback-expected.txt	2020-05-07 23:05:40 UTC (rev 261341)
@@ -0,0 +1,6 @@
+
+EVENT(playing)
+EVENT(pause)
+EXPECTED (internals.elementShouldDisplayPosterImage(video) == 'false') OK
+END OF TEST
+

Added: trunk/LayoutTests/media/video-poster-set-after-playback.html (0 => 261341)


--- trunk/LayoutTests/media/video-poster-set-after-playback.html	                        (rev 0)
+++ trunk/LayoutTests/media/video-poster-set-after-playback.html	2020-05-07 23:05:40 UTC (rev 261341)
@@ -0,0 +1,38 @@
+
+<html>
+<head>
+    <title>Setting poster after playing</title>
+    <script src=""
+    <script src=""
+    <script>
+
+        window.addEventListener('load', async () => {
+            failTestIn(15000);
+
+            findMediaElement();
+            video.src = "" "content/test");
+
+            video.play();
+            await waitFor(video, 'playing');
+
+            video.pause();
+            await waitFor(video, 'pause');
+            
+            video.poster = 'content/green.png';
+            
+            await sleepFor(1000);
+            
+            if (window.internals)
+                testExpected('internals.elementShouldDisplayPosterImage(video)', false);
+            else
+                consoleWrite("video should not be blank")
+
+            endTest();
+        });
+
+    </script>
+</head>
+<body>
+    <video controls muted></video>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (261340 => 261341)


--- trunk/Source/WebCore/ChangeLog	2020-05-07 23:01:32 UTC (rev 261340)
+++ trunk/Source/WebCore/ChangeLog	2020-05-07 23:05:40 UTC (rev 261341)
@@ -1,3 +1,57 @@
+2020-05-07  Eric Carlson  <eric.carl...@apple.com>
+
+        Poster set after playback begins should be ignored
+        https://bugs.webkit.org/show_bug.cgi?id=211464
+
+        Reviewed by Jer Noble.
+        
+        Redo the poster frame logic to use the `show poster flag` logic from the spec.
+
+        Test: media/video-poster-set-after-playback.html
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::HTMLMediaElement): Initialize m_showPoster.
+        (WebCore::HTMLMediaElement::prepareForLoad): m_displayMode was removed.
+        (WebCore::HTMLMediaElement::selectMediaResource): Call setShowPosterFlag.
+        (WebCore::HTMLMediaElement::loadResource): Remove calls to setDisplayMode and updateDisplayState,
+        they have been deleted.
+        (WebCore::HTMLMediaElement::waitForSourceChange): Call setShowPosterFlag. Update spec text.
+        (WebCore::HTMLMediaElement::noneSupported): Call setShowPosterFlag.
+        (WebCore::HTMLMediaElement::mediaLoadingFailed): Remove call to updateDisplayState.
+        (WebCore::HTMLMediaElement::setReadyState): Ditto.
+        (WebCore::HTMLMediaElement::seekWithTolerance): Call setShowPosterFlag.
+        (WebCore::HTMLMediaElement::seekTask):  Check m_showPoster, not displayMode.
+        (WebCore::HTMLMediaElement::playInternal): Call setShowPosterFlag.
+        (WebCore::HTMLMediaElement::mediaPlayerCharacteristicChanged): Don't check displayMode.
+        (WebCore::HTMLMediaElement::updatePlayState): No more setDisplayMode.
+        (WebCore::HTMLMediaElement::userCancelledLoad):  Call setShowPosterFlag.
+        (WebCore::HTMLMediaElement::mediaPlayerFirstVideoFrameAvailable): Deleted.
+        * html/HTMLMediaElement.h:
+        (WebCore::HTMLMediaElement::showPosterFlag const):
+        (WebCore::HTMLMediaElement::setShowPosterFlag):
+        (WebCore::HTMLMediaElement::displayMode const): Deleted.
+        (WebCore::HTMLMediaElement::setDisplayMode): Deleted.
+        (WebCore::HTMLMediaElement::updateDisplayState): Deleted.
+
+        * html/HTMLVideoElement.cpp:
+        (WebCore::HTMLVideoElement::didAttachRenderers): No more updateDisplayState.
+        (WebCore::HTMLVideoElement::parseAttribute): Ditto. Call updateFromElement when poster is removed.
+        (WebCore::HTMLVideoElement::shouldDisplayPosterImage const): New.
+        (WebCore::HTMLVideoElement::mediaPlayerFirstVideoFrameAvailable): New, update player and 
+        renderer if the poster isn't supposed to be visible.
+        (WebCore::HTMLVideoElement::setDisplayMode): Deleted.
+        (WebCore::HTMLVideoElement::updateDisplayState): Deleted.
+        * html/HTMLVideoElement.h:
+
+        * rendering/RenderVideo.cpp:
+        (WebCore::RenderVideo::failedToLoadPosterImage const): New.
+        * rendering/RenderVideo.h:
+
+        * testing/Internals.cpp:
+        (WebCore::Internals::elementShouldDisplayPosterImage const):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
 2020-05-07  Jack Lee  <shihchieh_...@apple.com>
 
         In Document::willBeRemovedFromFrame, clear FrameSelection before Editor so the selection is removed.

Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (261340 => 261341)


--- trunk/Source/WebCore/html/HTMLMediaElement.cpp	2020-05-07 23:01:32 UTC (rev 261340)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp	2020-05-07 23:05:40 UTC (rev 261341)
@@ -447,6 +447,7 @@
     , m_mediaControlsDependOnPageScaleFactor(false)
     , m_haveSetUpCaptionContainer(false)
     , m_isScrubbingRemotely(false)
+    , m_showPoster(true)
 #if ENABLE(VIDEO_TRACK)
     , m_tracksAreReady(true)
     , m_haveVisibleTextTrack(false)
@@ -1140,7 +1141,6 @@
     m_haveFiredLoadedData = false;
     m_completelyLoaded = false;
     m_havePreparedToPlay = false;
-    m_displayMode = Unknown;
     m_currentSrc = URL();
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
@@ -1246,7 +1246,7 @@
     m_networkState = NETWORK_NO_SOURCE;
 
     // 2. Set the element’s show poster flag to true.
-    setDisplayMode(Poster);
+    setShowPosterFlag(true);
 
     // 3. Set the media element’s delaying-the-load-event flag to true (this delays the load event).
     setShouldDelayLoadEvent(true);
@@ -1494,9 +1494,6 @@
     bool privateMode = document().page() && document().page()->usesEphemeralSession();
     m_player->setPrivateBrowsingMode(privateMode);
 
-    // Reset display mode to force a recalculation of what to show because we are resetting the player.
-    setDisplayMode(Unknown);
-
     if (!autoplay() && !m_havePreparedToPlay)
         m_player->setPreload(m_mediaSession->effectivePreloadForElement());
     m_player->setPreservesPitch(m_webkitPreservesPitch);
@@ -1550,11 +1547,7 @@
     if (!loadAttempted && !m_player->load(url, contentType, keySystem))
         mediaLoadingFailed(MediaPlayer::NetworkState::FormatError);
 
-    // If there is no poster to display, allow the media engine to render video frames as soon as
-    // they are available.
-    updateDisplayState();
-
-    updateRenderer();
+    mediaPlayerRenderingModeChanged();
 }
 
 #if ENABLE(VIDEO_TRACK)
@@ -2047,10 +2040,14 @@
     // 6.17 - Waiting: Set the element's networkState attribute to the NETWORK_NO_SOURCE value
     m_networkState = NETWORK_NO_SOURCE;
 
-    // 6.18 - Set the element's delaying-the-load-event flag to false. This stops delaying the load event.
+    // 6.18 - Set the element's show poster flag to true.
+    setShowPosterFlag(true);
+
+    // 6.19 -  Queue a media element task given the media element given the element to set the
+    // element's delaying-the-load-event flag to false. This stops delaying the load event.
+    // FIXME: this should be done in a task queue
     setShouldDelayLoadEvent(false);
 
-    updateDisplayState();
     updateRenderer();
 }
 
@@ -2079,6 +2076,9 @@
     // 6.3 - Set the element's networkState attribute to the NETWORK_NO_SOURCE value.
     m_networkState = NETWORK_NO_SOURCE;
 
+    // 6.4 - Set the element's show poster flag to true.
+    setShowPosterFlag(true);
+
     // 7 - Queue a task to fire a simple event named error at the media element.
     scheduleEvent(eventNames().errorEvent);
 
@@ -2094,7 +2094,6 @@
     // 9 - Abort these steps. Until the load() method is invoked or the src attribute is changed,
     // the element won't attempt to load another resource.
 
-    updateDisplayState();
     updateRenderer();
 }
 
@@ -2208,8 +2207,6 @@
     else if ((error == MediaPlayer::NetworkState::FormatError || error == MediaPlayer::NetworkState::NetworkError) && m_loadState == LoadingFromSrcAttr)
         noneSupported();
 
-    updateDisplayState();
-
     ERROR_LOG(LOGIDENTIFIER, "error = ", static_cast<int>(error));
 
     logMediaLoadRequest(document().page(), String(), convertEnumerationToString(error), false);
@@ -2416,8 +2413,6 @@
         m_mediaSession->clientCharacteristicsChanged();
     }
 
-    bool shouldUpdateDisplayState = false;
-
     if (m_readyState >= HAVE_CURRENT_DATA && oldState < HAVE_CURRENT_DATA) {
         if (!m_haveFiredLoadedData) {
             m_haveFiredLoadedData = true;
@@ -2425,16 +2420,13 @@
             // FIXME: It's not clear that it's correct to skip these two operations just
             // because m_haveFiredLoadedData is already true. At one time we were skipping
             // the call to setShouldDelayLoadEvent, which was definitely incorrect.
-            shouldUpdateDisplayState = true;
             applyMediaFragmentURI();
         }
         setShouldDelayLoadEvent(false);
     }
 
-    if (m_readyState == HAVE_FUTURE_DATA && oldState <= HAVE_CURRENT_DATA && tracksAreReady) {
+    if (m_readyState == HAVE_FUTURE_DATA && oldState <= HAVE_CURRENT_DATA && tracksAreReady)
         scheduleEvent(eventNames().canplayEvent);
-        shouldUpdateDisplayState = true;
-    }
 
     if (m_readyState == HAVE_ENOUGH_DATA && oldState < HAVE_ENOUGH_DATA && tracksAreReady) {
         if (oldState <= HAVE_CURRENT_DATA)
@@ -2445,6 +2437,7 @@
         auto success = canTransitionFromAutoplayToPlay();
         if (success) {
             m_paused = false;
+            setShowPosterFlag(false);
             invalidateCachedTime();
             setAutoplayEventPlaybackState(AutoplayEventPlaybackState::StartedWithoutUserGesture);
             m_playbackStartedTime = currentMediaTime().toDouble();
@@ -2453,8 +2446,6 @@
             ALWAYS_LOG(LOGIDENTIFIER, "Autoplay blocked, user gesture required");
             setAutoplayEventPlaybackState(AutoplayEventPlaybackState::PreventedAutoplay);
         }
-
-        shouldUpdateDisplayState = true;
     }
 
     // If we transition to the Future Data state and we're about to begin playing, ensure playback is actually permitted first,
@@ -2468,9 +2459,6 @@
         setAutoplayEventPlaybackState(AutoplayEventPlaybackState::PreventedAutoplay);
     }
 
-    if (shouldUpdateDisplayState)
-        updateDisplayState();
-
     updatePlayState();
     updateMediaController();
 #if ENABLE(VIDEO_TRACK)
@@ -2894,7 +2882,7 @@
     MediaTime time = inTime;
 
     // 1 - Set the media element's show poster flag to false.
-    setDisplayMode(Video);
+    setShowPosterFlag(false);
 
     // 2 - If the media element's readyState is HAVE_NOTHING, abort these steps.
     if (m_readyState == HAVE_NOTHING || !m_player)
@@ -2993,7 +2981,7 @@
     // Don't skip calling the media engine if 1) we are in poster mode (because a seek should always cancel
     // poster display), or 2) if there is a pending fast seek, or 3) if this seek is not an exact seek
     SeekType thisSeekType = (negativeTolerance == MediaTime::zeroTime() && positiveTolerance == MediaTime::zeroTime()) ? Precise : Fast;
-    if (!noSeekRequired && time == now && thisSeekType == Precise && m_pendingSeekType != Fast && displayMode() != Poster)
+    if (!noSeekRequired && time == now && thisSeekType == Precise && m_pendingSeekType != Fast && !showPosterFlag())
         noSeekRequired = true;
 
 #if ENABLE(MEDIA_SOURCE)
@@ -3474,6 +3462,7 @@
 
     if (m_paused) {
         m_paused = false;
+        setShowPosterFlag(false);
         invalidateCachedTime();
 
         // This avoids the first timeUpdated event after playback starts, when currentTime is still
@@ -4939,7 +4928,6 @@
 void HTMLMediaElement::mediaPlayerRepaint()
 {
     beginProcessingMediaPlayerCallback();
-    updateDisplayState();
     if (auto* renderer = this->renderer())
         renderer->repaint();
     endProcessingMediaPlayerCallback();
@@ -5064,18 +5052,6 @@
     scheduleMediaEngineWasUpdated();
 }
 
-void HTMLMediaElement::mediaPlayerFirstVideoFrameAvailable()
-{
-    INFO_LOG(LOGIDENTIFIER, "current display mode = ", (int)displayMode());
-
-    beginProcessingMediaPlayerCallback();
-    if (displayMode() == PosterWaitingForVideo) {
-        setDisplayMode(Video);
-        mediaPlayerRenderingModeChanged();
-    }
-    endProcessingMediaPlayerCallback();
-}
-
 void HTMLMediaElement::mediaPlayerCharacteristicChanged()
 {
     INFO_LOG(LOGIDENTIFIER);
@@ -5087,10 +5063,8 @@
         markCaptionAndSubtitleTracksAsUnconfigured(AfterDelay);
 #endif
 
-    if (potentiallyPlaying() && displayMode() == PosterWaitingForVideo) {
-        setDisplayMode(Video);
+    if (potentiallyPlaying())
         mediaPlayerRenderingModeChanged();
-    }
 
     updateRenderer();
 
@@ -5331,7 +5305,6 @@
     if (shouldBePlaying) {
         schedulePlaybackControlsManagerUpdate();
 
-        setDisplayMode(Video);
         invalidateCachedTime();
 
         if (playerPaused) {
@@ -5468,11 +5441,11 @@
 #endif
 
     // 4 - If the media element's readyState attribute has a value equal to HAVE_NOTHING, set the
-    // element's networkState attribute to the NETWORK_EMPTY value and queue a task to fire a
-    // simple event named emptied at the element. Otherwise, set the element's networkState
-    // attribute to the NETWORK_IDLE value.
+    // element's networkState attribute to the NETWORK_EMPTY value, set the element's show poster
+    // flag to true, and fire an event named emptied at the element.
     if (m_readyState == HAVE_NOTHING) {
         m_networkState = NETWORK_EMPTY;
+        setShowPosterFlag(true);
         scheduleEvent(eventNames().emptiedEvent);
     }
     else

Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (261340 => 261341)


--- trunk/Source/WebCore/html/HTMLMediaElement.h	2020-05-07 23:01:32 UTC (rev 261340)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h	2020-05-07 23:05:40 UTC (rev 261341)
@@ -599,10 +599,6 @@
 
     void didMoveToNewDocument(Document& oldDocument, Document& newDocument) override;
 
-    enum DisplayMode { Unknown, None, Poster, PosterWaitingForVideo, Video };
-    DisplayMode displayMode() const { return m_displayMode; }
-    virtual void setDisplayMode(DisplayMode mode) { m_displayMode = mode; }
-    
     bool isMediaElement() const final { return true; }
 
     RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) override;
@@ -615,6 +611,9 @@
 
     void scheduleEvent(const AtomString&);
 
+    bool showPosterFlag() const { return m_showPoster; }
+    void setShowPosterFlag(bool flag) { m_showPoster = flag; }
+
 private:
     void createMediaPlayer();
 
@@ -643,8 +642,6 @@
     
     void visibilityStateChanged() final;
 
-    virtual void updateDisplayState() { }
-    
     void setReadyState(MediaPlayer::ReadyState);
     void setNetworkState(MediaPlayer::NetworkState);
 
@@ -670,7 +667,6 @@
     void scheduleMediaEngineWasUpdated();
     void mediaEngineWasUpdated();
 
-    void mediaPlayerFirstVideoFrameAvailable() final;
     void mediaPlayerCharacteristicChanged() final;
 
 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
@@ -1034,8 +1030,6 @@
 
     MediaPlayer::Preload m_preload { Preload::Auto };
 
-    DisplayMode m_displayMode { Unknown };
-
     // Counter incremented while processing a callback from the media player, so we can avoid
     // calling the media engine recursively.
     int m_processingMediaPlayerCallback { 0 };
@@ -1113,6 +1107,8 @@
     bool m_isScrubbingRemotely : 1;
     bool m_waitingToEnterFullscreen : 1;
 
+    bool m_showPoster : 1;
+
 #if ENABLE(VIDEO_TRACK)
     bool m_tracksAreReady : 1;
     bool m_haveVisibleTextTrack : 1;

Modified: trunk/Source/WebCore/html/HTMLVideoElement.cpp (261340 => 261341)


--- trunk/Source/WebCore/html/HTMLVideoElement.cpp	2020-05-07 23:01:32 UTC (rev 261340)
+++ trunk/Source/WebCore/html/HTMLVideoElement.cpp	2020-05-07 23:05:40 UTC (rev 261341)
@@ -102,7 +102,6 @@
 {
     HTMLMediaElement::didAttachRenderers();
 
-    updateDisplayState();
     if (shouldDisplayPosterImage()) {
         if (!m_imageLoader)
             m_imageLoader = makeUnique<HTMLImageLoader>(*this);
@@ -132,17 +131,15 @@
 void HTMLVideoElement::parseAttribute(const QualifiedName& name, const AtomString& value)
 {
     if (name == posterAttr) {
-        // Force a poster recalc by setting m_displayMode to Unknown directly before calling updateDisplayState.
-        HTMLMediaElement::setDisplayMode(Unknown);
-        updateDisplayState();
-
         if (shouldDisplayPosterImage()) {
             if (!m_imageLoader)
                 m_imageLoader = makeUnique<HTMLImageLoader>(*this);
             m_imageLoader->updateFromElementIgnoringPreviousError();
         } else {
-            if (auto* renderer = this->renderer())
+            if (auto* renderer = this->renderer()) {
                 renderer->imageResource().setCachedImage(nullptr);
+                renderer->updateFromElement();
+            }
         }
     }
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
@@ -161,7 +158,6 @@
         }
 #endif
     }
-
 }
 
 bool HTMLVideoElement::supportsFullscreen(HTMLMediaElementEnums::VideoFullscreenMode videoFullscreenMode) const
@@ -251,37 +247,35 @@
     return m_defaultPosterURL;
 }
 
-void HTMLVideoElement::setDisplayMode(DisplayMode mode)
+bool HTMLVideoElement::shouldDisplayPosterImage() const
 {
-    DisplayMode oldMode = displayMode();
-    URL poster = posterImageURL();
+    if (!showPosterFlag())
+        return false;
 
-    if (!poster.isEmpty()) {
-        // We have a poster path, but only show it until the user triggers display by playing or seeking and the
-        // media engine has something to display.
-        if (mode == Video) {
-            if (oldMode != Video && player())
-                player()->prepareForRendering();
-            if (!hasAvailableVideoFrame())
-                mode = PosterWaitingForVideo;
-        }
-    } else if (oldMode != Video && player())
-        player()->prepareForRendering();
+    if (posterImageURL().isEmpty())
+        return false;
 
-    HTMLMediaElement::setDisplayMode(mode);
+    auto* renderer = this->renderer();
+    if (renderer && renderer->failedToLoadPosterImage())
+        return false;
 
-    if (auto* renderer = this->renderer()) {
-        if (displayMode() != oldMode)
-            renderer->updateFromElement();
-    }
+    return true;
 }
 
-void HTMLVideoElement::updateDisplayState()
+void HTMLVideoElement::mediaPlayerFirstVideoFrameAvailable()
 {
-    if (posterImageURL().isEmpty())
-        setDisplayMode(Video);
-    else if (displayMode() < Poster)
-        setDisplayMode(Poster);
+    INFO_LOG(LOGIDENTIFIER, "m_showPoster = ", showPosterFlag());
+
+    if (showPosterFlag())
+        return;
+
+    invalidateStyleAndLayerComposition();
+
+    if (auto player = this->player())
+        player->prepareForRendering();
+
+    if (auto* renderer = this->renderer())
+        renderer->updateFromElement();
 }
 
 void HTMLVideoElement::paintCurrentFrameInContext(GraphicsContext& context, const FloatRect& destRect)

Modified: trunk/Source/WebCore/html/HTMLVideoElement.h (261340 => 261341)


--- trunk/Source/WebCore/html/HTMLVideoElement.h	2020-05-07 23:01:32 UTC (rev 261340)
+++ trunk/Source/WebCore/html/HTMLVideoElement.h	2020-05-07 23:05:40 UTC (rev 261341)
@@ -76,7 +76,7 @@
     // See more details at MediaPlayer::copyVideoTextureToPlatformTexture() defined in Source/WebCore/platform/graphics/MediaPlayer.h.
     bool copyVideoTextureToPlatformTexture(GraphicsContextGLOpenGL*, PlatformGLObject texture, GCGLenum target, GCGLint level, GCGLenum internalFormat, GCGLenum format, GCGLenum type, bool premultiplyAlpha, bool flipY);
 
-    bool shouldDisplayPosterImage() const { return displayMode() == Poster || displayMode() == PosterWaitingForVideo; }
+    WEBCORE_EXPORT bool shouldDisplayPosterImage() const;
 
     URL posterImageURL() const;
     RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) final;
@@ -122,11 +122,11 @@
     bool isURLAttribute(const Attribute&) const final;
     const AtomString& imageSourceURL() const final;
 
-    bool hasAvailableVideoFrame() const;
-    void updateDisplayState() final;
     void didMoveToNewDocument(Document& oldDocument, Document& newDocument) final;
-    void setDisplayMode(DisplayMode) final;
 
+    bool hasAvailableVideoFrame() const;
+    void mediaPlayerFirstVideoFrameAvailable() final;
+
     PlatformMediaSession::MediaType presentationType() const final { return PlatformMediaSession::MediaType::Video; }
 
     std::unique_ptr<HTMLImageLoader> m_imageLoader;

Modified: trunk/Source/WebCore/rendering/RenderVideo.cpp (261340 => 261341)


--- trunk/Source/WebCore/rendering/RenderVideo.cpp	2020-05-07 23:01:32 UTC (rev 261340)
+++ trunk/Source/WebCore/rendering/RenderVideo.cpp	2020-05-07 23:05:40 UTC (rev 261341)
@@ -179,6 +179,11 @@
     return !videoElement().shouldDisplayPosterImage();
 }
 
+bool RenderVideo::failedToLoadPosterImage() const
+{
+    return imageResource().errorOccurred();
+}
+
 void RenderVideo::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
 {
     auto mediaPlayer = videoElement().player();

Modified: trunk/Source/WebCore/rendering/RenderVideo.h (261340 => 261341)


--- trunk/Source/WebCore/rendering/RenderVideo.h	2020-05-07 23:01:32 UTC (rev 261340)
+++ trunk/Source/WebCore/rendering/RenderVideo.h	2020-05-07 23:05:40 UTC (rev 261341)
@@ -50,6 +50,7 @@
     bool requiresImmediateCompositing() const;
 
     bool shouldDisplayVideo() const;
+    bool failedToLoadPosterImage() const;
 
     void updateFromElement() final;
 

Modified: trunk/Source/WebCore/testing/Internals.cpp (261340 => 261341)


--- trunk/Source/WebCore/testing/Internals.cpp	2020-05-07 23:01:32 UTC (rev 261340)
+++ trunk/Source/WebCore/testing/Internals.cpp	2020-05-07 23:05:40 UTC (rev 261341)
@@ -4333,6 +4333,15 @@
 #endif
 }
 
+ExceptionOr<bool> Internals::elementShouldDisplayPosterImage(HTMLVideoElement& element) const
+{
+#if ENABLE(VIDEO)
+    return element.shouldDisplayPosterImage();
+#else
+    UNUSED_PARAM(element);
+    return Exception { InvalidAccessError };
+#endif
+}
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
 

Modified: trunk/Source/WebCore/testing/Internals.h (261340 => 261341)


--- trunk/Source/WebCore/testing/Internals.h	2020-05-07 23:01:32 UTC (rev 261340)
+++ trunk/Source/WebCore/testing/Internals.h	2020-05-07 23:05:40 UTC (rev 261341)
@@ -864,6 +864,8 @@
     };
     ExceptionOr<MediaUsageState> mediaUsageState(HTMLMediaElement&) const;
 
+    ExceptionOr<bool> elementShouldDisplayPosterImage(HTMLVideoElement&) const;
+
 #if ENABLE(VIDEO)
     using PlaybackControlsPurpose = MediaElementSession::PlaybackControlsPurpose;
     RefPtr<HTMLMediaElement> bestMediaElementForShowingPlaybackControlsManager(PlaybackControlsPurpose);

Modified: trunk/Source/WebCore/testing/Internals.idl (261340 => 261341)


--- trunk/Source/WebCore/testing/Internals.idl	2020-05-07 23:01:32 UTC (rev 261340)
+++ trunk/Source/WebCore/testing/Internals.idl	2020-05-07 23:05:40 UTC (rev 261341)
@@ -840,6 +840,7 @@
     [Conditional=VIDEO] MediaSessionState mediaSessionState(HTMLMediaElement element);
 
     [Conditional=VIDEO, MayThrowException] MediaUsageState mediaUsageState(HTMLMediaElement element);
+    [Conditional=VIDEO, MayThrowException] boolean elementShouldDisplayPosterImage(HTMLVideoElement element);
 
     DOMString ongoingLoadsDescriptions();
     void setCaptureExtraNetworkLoadMetricsEnabled(boolean value);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to