Changeset 269407 in webkit


Ignore:
Timestamp:
Nov 4, 2020 5:05:14 PM (21 months ago)
Author:
eric.carlson@apple.com
Message:

Transparent video poster image doesn't keep element transparent once first frame is preloaded
https://bugs.webkit.org/show_bug.cgi?id=218391
<rdar://problem/70916944>

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-visible-after-first-video-frame.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::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:

  • TestExpectations: Mark a test that expect video state changes to be visible on the

next rAF to be flaky. HTMLMediaElement uses taskQueues to change properties, and
taskQueue isn't synchronized to rAF, so sometimes the task runs before the next
rAF and sometimes after, making the test flaky.

  • compositing/video/video-poster.html: Don't expect the transition to having layers

to be instantaneous.

  • media/video-poster-visible-after-first-video-frame-expected.txt: Added.
  • media/video-poster-visible-after-first-video-frame.html: Added.
Location:
trunk
Files:
2 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r269405 r269407  
     12020-11-04  Eric Carlson  <eric.carlson@apple.com>
     2
     3        Transparent video poster image doesn't keep element transparent once first frame is preloaded
     4        https://bugs.webkit.org/show_bug.cgi?id=218391
     5        <rdar://problem/70916944>
     6
     7        Reviewed by Jer Noble.
     8
     9        * TestExpectations: Mark a test that expect video state changes to be visible on the
     10        next rAF to be flaky. HTMLMediaElement uses taskQueues to change properties, and
     11        taskQueue isn't synchronized to rAF, so sometimes the task runs before the next
     12        rAF and sometimes after, making the test flaky.
     13
     14        * compositing/video/video-poster.html: Don't expect the transition to having layers
     15        to be instantaneous.
     16
     17        * media/video-poster-visible-after-first-video-frame-expected.txt: Added.
     18        * media/video-poster-visible-after-first-video-frame.html: Added.
     19
    1202020-11-04  Truitt Savell  <tsavell@apple.com>
    221
  • trunk/LayoutTests/TestExpectations

    r269394 r269407  
    30363036
    30373037webkit.org/b/198103 imported/w3c/web-platform-tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/currentTime.html [ Pass Failure ]
     3038
     3039# This tests assumes that changes caused by removing 'video.src' will be visible immediately after the next rAF.
     3040# HTMLMediaElement uses a taskQueue to change video.src, but taskQueue isn't tied to rAF so the task sometimes
     3041# runs before rAF and the test passes, and sometimes run after and the test fails.
     3042imported/w3c/web-platform-tests/html/semantics/embedded-content/the-video-element/intrinsic_sizes.htm [ Pass Failure ]
    30383043
    30393044# Flaky WebSocket tests.
  • trunk/LayoutTests/compositing/video/video-poster.html

    r130689 r269407  
    55        <script>
    66
    7             var count = 0;
    87            function log(str)
    98            {
     
    1514                if (window.testRunner)
    1615                    return window.internals.layerTreeAsText(document) != "";
     16               
    1717                return false;
    1818            }
    1919
    20             function checkLayers(prefix, wantsLayers)
     20            async function checkLayers(prefix, wantsLayers)
    2121            {
    22                 var layers = hasLayers();
    23                 log(prefix + " <br>&nbsp;&nbsp;" + (wantsLayers == layers ? "PASS" : "FAIL") + ": wants layers = " + wantsLayers + ", has layers = " + layers);
    24                 log("");
     22                return new Promise(async resolve => {
     23                    let layers;
     24                    let count = 0;
     25                    while (true) {
     26
     27                        layers = hasLayers();
     28                        if (layers == wantsLayers)
     29                            break;
     30
     31                        await new Promise(resolve => { setTimeout(resolve, 10); });
     32                        if (++count > 10)
     33                            break;
     34                    }
     35
     36                    log(`${prefix} <br>&nbsp;&nbsp;${wantsLayers == layers ? "PASS" : "FAIL"}: wants layers = ${wantsLayers}, has layers = ${layers}<br>`);
     37                    resolve();
     38                });
    2539            }
    2640
    27             function layerTest()
     41            async function layerTest()
    2842            {
    2943                var video = document.getElementsByTagName('video')[0];
     
    3246                {
    3347                    case "load":
    34                         checkLayers("No src, no poster", false);
     48                        await checkLayers("No src, no poster", false);
    3549                        video.src = "../resources/video." + (video.canPlayType("video/ogg") ? "ogv" : "mp4");
    3650                        video.poster = "../resources/apple.jpg";
    3751                        break;
    3852                    case "canplaythrough":
    39                         checkLayers("Displaying poster", false);
     53                        await checkLayers("Displaying poster", false);
    4054                        video.currentTime = 0.5;
    4155                        break;
    4256                    case "seeked":
    43                         checkLayers("Displaying movie", true);
     57                        await checkLayers("Displaying movie", true);
    4458                        if (window.testRunner)
    4559                            testRunner.notifyDone();
  • trunk/Source/WebCore/ChangeLog

    r269402 r269407  
     12020-11-04  Eric Carlson  <eric.carlson@apple.com>
     2
     3        Transparent video poster image doesn't keep element transparent once first frame is preloaded
     4        https://bugs.webkit.org/show_bug.cgi?id=218391
     5        <rdar://problem/70916944>
     6
     7        Reviewed by Jer Noble.
     8       
     9        Redo the poster frame logic to use the `show poster flag` logic from the spec.
     10
     11        Test: media/video-poster-visible-after-first-video-frame.html
     12
     13        * html/HTMLMediaElement.cpp:
     14        (WebCore::HTMLMediaElement::HTMLMediaElement): Initialize m_showPoster.
     15        (WebCore::HTMLMediaElement::prepareForLoad): m_displayMode was removed.
     16        (WebCore::HTMLMediaElement::selectMediaResource): Call setShowPosterFlag.
     17        (WebCore::HTMLMediaElement::loadResource): Remove calls to setDisplayMode and updateDisplayState,
     18        they have been deleted.
     19        (WebCore::HTMLMediaElement::waitForSourceChange): Call setShowPosterFlag. Update spec text.
     20        (WebCore::HTMLMediaElement::noneSupported): Call setShowPosterFlag.
     21        (WebCore::HTMLMediaElement::mediaLoadingFailed): Remove call to updateDisplayState.
     22        (WebCore::HTMLMediaElement::setReadyState): Ditto.
     23        (WebCore::HTMLMediaElement::seekWithTolerance): Call setShowPosterFlag.
     24        (WebCore::HTMLMediaElement::seekTask):  Check m_showPoster, not displayMode.
     25        (WebCore::HTMLMediaElement::playInternal): Call setShowPosterFlag.
     26        (WebCore::HTMLMediaElement::mediaPlayerCharacteristicChanged): Don't check displayMode.
     27        (WebCore::HTMLMediaElement::updatePlayState): No more setDisplayMode.
     28        (WebCore::HTMLMediaElement::userCancelledLoad):  Call setShowPosterFlag.
     29        (WebCore::HTMLMediaElement::setShowPosterFlag):
     30        (WebCore::HTMLMediaElement::mediaPlayerFirstVideoFrameAvailable): Deleted.
     31        * html/HTMLMediaElement.h:
     32        (WebCore::HTMLMediaElement::showPosterFlag const):
     33        (WebCore::HTMLMediaElement::setShowPosterFlag):
     34        (WebCore::HTMLMediaElement::displayMode const): Deleted.
     35        (WebCore::HTMLMediaElement::setDisplayMode): Deleted.
     36        (WebCore::HTMLMediaElement::updateDisplayState): Deleted.
     37
     38        * html/HTMLVideoElement.cpp:
     39        (WebCore::HTMLVideoElement::didAttachRenderers): No more updateDisplayState.
     40        (WebCore::HTMLVideoElement::parseAttribute): Ditto. Call updateFromElement when poster is removed.
     41        (WebCore::HTMLVideoElement::shouldDisplayPosterImage const): New.
     42        (WebCore::HTMLVideoElement::mediaPlayerFirstVideoFrameAvailable): New, update player and
     43        renderer if the poster isn't supposed to be visible.
     44        (WebCore::HTMLVideoElement::setDisplayMode): Deleted.
     45        (WebCore::HTMLVideoElement::updateDisplayState): Deleted.
     46        * html/HTMLVideoElement.h:
     47
     48        * rendering/RenderVideo.cpp:
     49        (WebCore::RenderVideo::failedToLoadPosterImage const): New.
     50        * rendering/RenderVideo.h:
     51
     52        * testing/Internals.cpp:
     53        (WebCore::Internals::elementShouldDisplayPosterImage const):
     54        * testing/Internals.h:
     55        * testing/Internals.idl:
     56
    1572020-11-04  Zalan Bujtas  <zalan@apple.com>
    258
  • trunk/Source/WebCore/html/HTMLMediaElement.cpp

    r269321 r269407  
    415415    , m_isScrubbingRemotely(false)
    416416    , m_waitingToEnterFullscreen(false)
     417    , m_showPoster(true)
    417418    , m_tracksAreReady(true)
    418419    , m_haveVisibleTextTrack(false)
     
    10821083    m_completelyLoaded = false;
    10831084    m_havePreparedToPlay = false;
    1084     m_displayMode = Unknown;
    10851085    m_currentSrc = URL();
    10861086
     
    11861186
    11871187    // 2. Set the element’s show poster flag to true.
    1188     setDisplayMode(Poster);
     1188    setShowPosterFlag(true);
    11891189
    11901190    // 3. Set the media element’s delaying-the-load-event flag to true (this delays the load event).
     
    14321432    m_player->setPrivateBrowsingMode(privateMode);
    14331433
    1434     // Reset display mode to force a recalculation of what to show because we are resetting the player.
    1435     setDisplayMode(Unknown);
    1436 
    14371434    if (!autoplay() && !m_havePreparedToPlay)
    14381435        m_player->setPreload(m_mediaSession->effectivePreloadForElement());
     
    14881485        mediaLoadingFailed(MediaPlayer::NetworkState::FormatError);
    14891486
    1490     // If there is no poster to display, allow the media engine to render video frames as soon as
    1491     // they are available.
    1492     updateDisplayState();
    1493 
    1494     updateRenderer();
     1487    mediaPlayerRenderingModeChanged();
    14951488}
    14961489
     
    19811974    m_networkState = NETWORK_NO_SOURCE;
    19821975
    1983     // 6.18 - Set the element's delaying-the-load-event flag to false. This stops delaying the load event.
     1976    // 6.18 - Set the element's show poster flag to true.
     1977    setShowPosterFlag(true);
     1978
     1979    // 6.19 -  Queue a media element task given the media element given the element to set the
     1980    // element's delaying-the-load-event flag to false. This stops delaying the load event.
     1981    // FIXME: this should be done in a task queue
    19841982    setShouldDelayLoadEvent(false);
    19851983
    1986     updateDisplayState();
    19871984    updateRenderer();
    19881985}
     
    20132010    m_networkState = NETWORK_NO_SOURCE;
    20142011
     2012    // 6.4 - Set the element's show poster flag to true.
     2013    setShowPosterFlag(true);
     2014
    20152015    // 7 - Queue a task to fire a simple event named error at the media element.
    20162016    scheduleEvent(eventNames().errorEvent);
     
    20282028    // the element won't attempt to load another resource.
    20292029
    2030     updateDisplayState();
    20312030    updateRenderer();
    20322031}
     
    21412140    else if ((error == MediaPlayer::NetworkState::FormatError || error == MediaPlayer::NetworkState::NetworkError) && m_loadState == LoadingFromSrcAttr)
    21422141        noneSupported();
    2143 
    2144     updateDisplayState();
    21452142
    21462143    ERROR_LOG(LOGIDENTIFIER, "error = ", static_cast<int>(error));
     
    23442341    }
    23452342
    2346     bool shouldUpdateDisplayState = false;
    2347 
    23482343    if (m_readyState >= HAVE_CURRENT_DATA && oldState < HAVE_CURRENT_DATA) {
    23492344        if (!m_haveFiredLoadedData) {
    23502345            m_haveFiredLoadedData = true;
    23512346            scheduleEvent(eventNames().loadeddataEvent);
    2352             // FIXME: It's not clear that it's correct to skip these two operations just
     2347            // FIXME: It's not clear that it's correct to skip these this operation just
    23532348            // because m_haveFiredLoadedData is already true. At one time we were skipping
    23542349            // the call to setShouldDelayLoadEvent, which was definitely incorrect.
    2355             shouldUpdateDisplayState = true;
    23562350            applyMediaFragmentURI();
    23572351        }
     
    23592353    }
    23602354
    2361     if (m_readyState == HAVE_FUTURE_DATA && oldState <= HAVE_CURRENT_DATA && tracksAreReady) {
     2355    if (m_readyState == HAVE_FUTURE_DATA && oldState <= HAVE_CURRENT_DATA && tracksAreReady)
    23622356        scheduleEvent(eventNames().canplayEvent);
    2363         shouldUpdateDisplayState = true;
    2364     }
    23652357
    23662358    if (m_readyState == HAVE_ENOUGH_DATA && oldState < HAVE_ENOUGH_DATA && tracksAreReady) {
     
    23732365        if (success) {
    23742366            m_paused = false;
     2367            setShowPosterFlag(false);
    23752368            invalidateCachedTime();
    23762369            setAutoplayEventPlaybackState(AutoplayEventPlaybackState::StartedWithoutUserGesture);
     
    23812374            setAutoplayEventPlaybackState(AutoplayEventPlaybackState::PreventedAutoplay);
    23822375        }
    2383 
    2384         shouldUpdateDisplayState = true;
    23852376    }
    23862377
     
    23952386        setAutoplayEventPlaybackState(AutoplayEventPlaybackState::PreventedAutoplay);
    23962387    }
    2397 
    2398     if (shouldUpdateDisplayState)
    2399         updateDisplayState();
    24002388
    24012389    updatePlayState();
     
    28632851
    28642852    // 1 - Set the media element's show poster flag to false.
    2865     setDisplayMode(Video);
     2853    setShowPosterFlag(false);
    28662854
    28672855    // 2 - If the media element's readyState is HAVE_NOTHING, abort these steps.
     
    29622950    // poster display), or 2) if there is a pending fast seek, or 3) if this seek is not an exact seek
    29632951    SeekType thisSeekType = (negativeTolerance == MediaTime::zeroTime() && positiveTolerance == MediaTime::zeroTime()) ? Precise : Fast;
    2964     if (!noSeekRequired && time == now && thisSeekType == Precise && m_pendingSeekType != Fast && displayMode() != Poster)
     2952    if (!noSeekRequired && time == now && thisSeekType == Precise && m_pendingSeekType != Fast && !showPosterFlag())
    29652953        noSeekRequired = true;
    29662954
     
    34433431    if (m_paused) {
    34443432        m_paused = false;
     3433        setShowPosterFlag(false);
    34453434        invalidateCachedTime();
    34463435
     
    48774866{
    48784867    beginProcessingMediaPlayerCallback();
    4879     updateDisplayState();
    48804868    if (auto* renderer = this->renderer())
    48814869        renderer->repaint();
     
    50104998}
    50114999
    5012 void HTMLMediaElement::mediaPlayerFirstVideoFrameAvailable()
    5013 {
    5014     ALWAYS_LOG(LOGIDENTIFIER, "current display mode = ", (int)displayMode());
    5015 
    5016     beginProcessingMediaPlayerCallback();
    5017     if (displayMode() == PosterWaitingForVideo) {
    5018         setDisplayMode(Video);
    5019         mediaPlayerRenderingModeChanged();
    5020     }
    5021     endProcessingMediaPlayerCallback();
    5022 }
    5023 
    50245000void HTMLMediaElement::mediaPlayerCharacteristicChanged()
    50255001{
     
    50315007        markCaptionAndSubtitleTracksAsUnconfigured(AfterDelay);
    50325008
    5033     if (potentiallyPlaying() && displayMode() == PosterWaitingForVideo) {
    5034         setDisplayMode(Video);
     5009    if (potentiallyPlaying())
    50355010        mediaPlayerRenderingModeChanged();
    5036     }
    50375011
    50385012    updateRenderer();
     
    52665240        schedulePlaybackControlsManagerUpdate();
    52675241
    5268         setDisplayMode(Video);
    52695242        invalidateCachedTime();
    52705243
     
    53995372
    54005373    // 4 - If the media element's readyState attribute has a value equal to HAVE_NOTHING, set the
    5401     // element's networkState attribute to the NETWORK_EMPTY value and queue a task to fire a
    5402     // simple event named emptied at the element. Otherwise, set the element's networkState
    5403     // attribute to the NETWORK_IDLE value.
     5374    // element's networkState attribute to the NETWORK_EMPTY value, set the element's show poster
     5375    // flag to true, and fire an event named emptied at the element.
    54045376    if (m_readyState == HAVE_NOTHING) {
    54055377        m_networkState = NETWORK_EMPTY;
     5378        setShowPosterFlag(true);
    54065379        scheduleEvent(eventNames().emptiedEvent);
    54075380    }
     
    79437916}
    79447917
    7945 }
    7946 
    7947 #endif
     7918void HTMLMediaElement::setShowPosterFlag(bool flag)
     7919{
     7920    if (m_showPoster == flag)
     7921        return;
     7922
     7923    ALWAYS_LOG(LOGIDENTIFIER, flag);
     7924
     7925    m_showPoster = flag;
     7926    invalidateStyleAndLayerComposition();
     7927}
     7928
     7929}
     7930
     7931#endif
  • trunk/Source/WebCore/html/HTMLMediaElement.h

    r268865 r269407  
    587587    void didMoveToNewDocument(Document& oldDocument, Document& newDocument) override;
    588588
    589     enum DisplayMode { Unknown, None, Poster, PosterWaitingForVideo, Video };
    590     DisplayMode displayMode() const { return m_displayMode; }
    591     virtual void setDisplayMode(DisplayMode mode) { m_displayMode = mode; }
    592    
    593589    bool isMediaElement() const final { return true; }
    594590
     
    606602    void scheduleEvent(const AtomString&);
    607603
     604    bool showPosterFlag() const { return m_showPoster; }
     605    void setShowPosterFlag(bool);
     606   
    608607    void setChangingVideoFullscreenMode(bool value) { m_changingVideoFullscreenMode = value; }
    609608    bool isChangingVideoFullscreenMode() const { return m_changingVideoFullscreenMode; }
     
    639638    void visibilityStateChanged() final;
    640639
    641     virtual void updateDisplayState() { }
    642    
    643640    void setReadyState(MediaPlayer::ReadyState);
    644641    void setNetworkState(MediaPlayer::NetworkState);
     
    666663    void mediaEngineWasUpdated();
    667664
    668     void mediaPlayerFirstVideoFrameAvailable() final;
    669665    void mediaPlayerCharacteristicChanged() final;
    670666
     
    10241020    MediaPlayer::Preload m_preload { Preload::Auto };
    10251021
    1026     DisplayMode m_displayMode { Unknown };
    1027 
    10281022    // Counter incremented while processing a callback from the media player, so we can avoid
    10291023    // calling the media engine recursively.
     
    10971091    bool m_changingVideoFullscreenMode : 1;
    10981092
     1093    bool m_showPoster : 1;
    10991094    bool m_tracksAreReady : 1;
    11001095    bool m_haveVisibleTextTrack : 1;
  • trunk/Source/WebCore/html/HTMLVideoElement.cpp

    r269323 r269407  
    11/*
    2  * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
     2 * Copyright (C) 2007-2020 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    104104    HTMLMediaElement::didAttachRenderers();
    105105
    106     updateDisplayState();
    107106    if (shouldDisplayPosterImage()) {
    108107        if (!m_imageLoader)
     
    134133{
    135134    if (name == posterAttr) {
    136         if (hasAvailableVideoFrame())
    137             return;
    138 
    139         // Force a poster recalc by setting m_displayMode to Unknown directly before calling updateDisplayState.
    140         HTMLMediaElement::setDisplayMode(Unknown);
    141         updateDisplayState();
    142 
    143135        if (shouldDisplayPosterImage()) {
    144136            if (!m_imageLoader)
     
    146138            m_imageLoader->updateFromElementIgnoringPreviousError();
    147139        } else {
    148             if (auto* renderer = this->renderer())
     140            if (auto* renderer = this->renderer()) {
    149141                renderer->imageResource().setCachedImage(nullptr);
     142                renderer->updateFromElement();
     143            }
    150144        }
    151145    }
     
    259253}
    260254
    261 void HTMLVideoElement::setDisplayMode(DisplayMode mode)
    262 {
    263     DisplayMode oldMode = displayMode();
    264     URL poster = posterImageURL();
    265 
    266     if (!poster.isEmpty()) {
    267         // We have a poster path, but only show it until the user triggers display by playing or seeking and the
    268         // media engine has something to display.
    269         if (mode == Video) {
    270             if (oldMode != Video && player())
    271                 player()->prepareForRendering();
    272             if (!hasAvailableVideoFrame())
    273                 mode = PosterWaitingForVideo;
    274         }
    275     } else if (oldMode != Video && player())
    276         player()->prepareForRendering();
    277 
    278     HTMLMediaElement::setDisplayMode(mode);
    279 
    280     if (auto* renderer = this->renderer()) {
    281         if (displayMode() != oldMode)
    282             renderer->updateFromElement();
    283     }
    284 }
    285 
    286 void HTMLVideoElement::updateDisplayState()
    287 {
    288     if (posterImageURL().isEmpty() || hasAvailableVideoFrame())
    289         setDisplayMode(Video);
    290     else if (displayMode() < Poster)
    291         setDisplayMode(Poster);
     255bool HTMLVideoElement::shouldDisplayPosterImage() const
     256{
     257    if (!showPosterFlag())
     258        return false;
     259
     260    if (posterImageURL().isEmpty())
     261        return false;
     262
     263    auto* renderer = this->renderer();
     264    if (renderer && renderer->failedToLoadPosterImage())
     265        return false;
     266
     267    return true;
     268}
     269
     270void HTMLVideoElement::mediaPlayerFirstVideoFrameAvailable()
     271{
     272    INFO_LOG(LOGIDENTIFIER, "m_showPoster = ", showPosterFlag());
     273
     274    if (showPosterFlag())
     275        return;
     276
     277    invalidateStyleAndLayerComposition();
     278
     279    if (auto player = this->player())
     280        player->prepareForRendering();
     281
     282    if (auto* renderer = this->renderer())
     283        renderer->updateFromElement();
    292284}
    293285
  • trunk/Source/WebCore/html/HTMLVideoElement.h

    r269323 r269407  
    11/*
    2  * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
     2 * Copyright (C) 2007-2020 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    8282    bool copyVideoTextureToPlatformTexture(GraphicsContextGLOpenGL*, PlatformGLObject texture, GCGLenum target, GCGLint level, GCGLenum internalFormat, GCGLenum format, GCGLenum type, bool premultiplyAlpha, bool flipY);
    8383
    84     bool shouldDisplayPosterImage() const { return displayMode() == Poster || displayMode() == PosterWaitingForVideo; }
     84    WEBCORE_EXPORT bool shouldDisplayPosterImage() const;
    8585
    8686    URL posterImageURL() const;
     
    128128    const AtomString& imageSourceURL() const final;
    129129
     130    void didMoveToNewDocument(Document& oldDocument, Document& newDocument) final;
     131
    130132    bool hasAvailableVideoFrame() const;
    131     void updateDisplayState() final;
    132     void didMoveToNewDocument(Document& oldDocument, Document& newDocument) final;
    133     void setDisplayMode(DisplayMode) final;
     133    void mediaPlayerFirstVideoFrameAvailable() final;
    134134
    135135    PlatformMediaSession::MediaType presentationType() const final { return PlatformMediaSession::MediaType::Video; }
  • trunk/Source/WebCore/rendering/RenderVideo.cpp

    r268145 r269407  
    187187}
    188188
     189bool RenderVideo::failedToLoadPosterImage() const
     190{
     191    return imageResource().errorOccurred();
     192}
     193
    189194void RenderVideo::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
    190195{
  • trunk/Source/WebCore/rendering/RenderVideo.h

    r261409 r269407  
    5151
    5252    bool shouldDisplayVideo() const;
     53    bool failedToLoadPosterImage() const;
    5354
    5455    void updateFromElement() final;
Note: See TracChangeset for help on using the changeset viewer.