Changeset 201474 in webkit


Ignore:
Timestamp:
May 27, 2016 4:58:28 PM (8 years ago)
Author:
commit-queue@webkit.org
Message:

Decrease flicker when changing video presentation mode.
https://bugs.webkit.org/show_bug.cgi?id=158148
rdar://problem/24476949

Patch by Jeremy Jones <jeremyj@apple.com> on 2016-05-27
Source/WebCore:

Reviewed by Jer Noble.

No new tests because there is no behavior change. This change is about the timing of
moving AVPlayerLayers between layers to prevent flicker.

1) Moving an AVPlayerLayer between CAContexts can flicker. So always keep two
AVPlayerLayers around and add and remove them from the inline and fullscreen contexts.
2) Wait to show the inline placeholder until the fullscreen video layer has been installed.
3) Wait to remove the fullscreen video layer until the placeholder has been removed.

  • Modules/mediacontrols/MediaControlsHost.cpp:

(WebCore::MediaControlsHost::isVideoLayerInline): Expose isVideoLayerInline to the shadow DOM.
(WebCore::MediaControlsHost::setPreparedForInline): Expose setPreparedForInline to the shadow DOM.

  • Modules/mediacontrols/MediaControlsHost.h: Add setPreparedForInline and isVideoLayerInline
  • Modules/mediacontrols/MediaControlsHost.idl: Add setPreparedForInline and isVideoLayerInline
  • Modules/mediacontrols/mediaControlsApple.js:

(Controller.prototype.showInlinePlaybackPlaceholderWhenSafe): Wait to show placeholder when entering fullscreen.
(Controller.prototype.handlePresentationModeChange): Wait to show placeholder, and notify when placeholder is removed.

  • html/HTMLMediaElement.cpp:

(WebCore::HTMLMediaElement::setPreparedForInline):
(WebCore::HTMLMediaElement::waitForPreparedForInlineThen): Used to delay fullscreen cleanup until placeholder is removed.
(WebCore::HTMLMediaElement::setVideoFullscreenLayer): Add a callback so we can wait until this completes before continuing.

  • html/HTMLMediaElement.h:

(WebCore::HTMLMediaElement::isVideoLayerInline):
(WebCore::HTMLMediaElement::waitForPreparedForInlineThen):
(WebCore::HTMLMediaElement::setVideoFullscreenLayer): Add completionHandler.

  • platform/cocoa/WebVideoFullscreenModelVideoElement.h:

(WebCore::WebVideoFullscreenModelVideoElement::setVideoFullscreenLayer): Add completionHandler.
(WebCore::WebVideoFullscreenModelVideoElement::waitForPreparedForInlineThen): Added.

  • platform/cocoa/WebVideoFullscreenModelVideoElement.mm:

(WebVideoFullscreenModelVideoElement::setVideoFullscreenLayer): Add completionHandler.
(WebVideoFullscreenModelVideoElement::waitForPreparedForInlineThen):

  • platform/graphics/MediaPlayer.cpp:

(WebCore::MediaPlayer::setVideoFullscreenLayer): Add completionHandler.

  • platform/graphics/MediaPlayer.h:

(WebCore::MediaPlayer::setVideoFullscreenLayer): Add completionHandler.

  • platform/graphics/MediaPlayerPrivate.h:

(WebCore::MediaPlayerPrivateInterface::setVideoFullscreenLayer): Add completionHandler.

  • platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
  • platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:

(WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayerLayer): Create two video layers.
(WebCore::MediaPlayerPrivateAVFoundationObjC::destroyVideoLayer): Allow two video layers.
(WebCore::MediaPlayerPrivateAVFoundationObjC::setVideoFullscreenLayer): Add completionHandler.
(WebCore::MediaPlayerPrivateAVFoundationObjC::updateVideoLayerGravity): Allow two video layers.

  • platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h:
  • platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:

(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::addDisplayLayer): Allow two video layers.
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::setVideoFullscreenLayer): Add completionHandler.

  • platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h:
  • platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:

(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::createPreviewLayers): Allow two video layers.
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::setVideoFullscreenLayer): Add completionHandler.

  • platform/graphics/avfoundation/objc/VideoFullscreenLayerManager.h:
  • platform/graphics/avfoundation/objc/VideoFullscreenLayerManager.mm:

(WebCore::VideoFullscreenLayerManager::setVideoLayers): Allow two video layers.
(WebCore::VideoFullscreenLayerManager::setVideoFullscreenLayer): Add completionHandler.
(WebCore::VideoFullscreenLayerManager::setVideoFullscreenFrame): Allow two video layers.
(WebCore::VideoFullscreenLayerManager::didDestroyVideoLayer): Allow two video layers.
(WebCore::VideoFullscreenLayerManager::setVideoLayer): Deleted.

  • platform/ios/WebVideoFullscreenControllerAVKit.mm:

(WebVideoFullscreenControllerContext::didSetupFullscreen): Use completionHandler.
(WebVideoFullscreenControllerContext::didExitFullscreen): Use completionHandler.

Source/WebKit2:

Reviewed by Tim Horton.

Prevent flicker by using setVideoFullscreenLayer with a completion handler to delay
enter fullscreen and cleanup fullscreen until the video layer has completely been
installed or removed.

  • WebProcess/cocoa/WebVideoFullscreenManager.mm:

(WebKit::WebVideoFullscreenManager::didSetupFullscreen):
(WebKit::WebVideoFullscreenManager::didExitFullscreen):

Location:
trunk/Source
Files:
23 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r201471 r201474  
     12016-05-27  Jeremy Jones  <jeremyj@apple.com>
     2
     3        Decrease flicker when changing video presentation mode.
     4        https://bugs.webkit.org/show_bug.cgi?id=158148
     5        rdar://problem/24476949
     6
     7        Reviewed by Jer Noble.
     8
     9        No new tests because there is no behavior change. This change is about the timing of
     10        moving AVPlayerLayers between layers to prevent flicker.
     11
     12        1) Moving an AVPlayerLayer between CAContexts can flicker. So always keep two
     13        AVPlayerLayers around and add and remove them from the inline and fullscreen contexts.
     14        2) Wait to show the inline placeholder until the fullscreen video layer has been installed.
     15        3) Wait to remove the fullscreen video layer until the placeholder has been removed.
     16
     17        * Modules/mediacontrols/MediaControlsHost.cpp:
     18        (WebCore::MediaControlsHost::isVideoLayerInline): Expose isVideoLayerInline to the shadow DOM.
     19        (WebCore::MediaControlsHost::setPreparedForInline): Expose setPreparedForInline to the shadow DOM.
     20        * Modules/mediacontrols/MediaControlsHost.h: Add setPreparedForInline and isVideoLayerInline
     21        * Modules/mediacontrols/MediaControlsHost.idl: Add setPreparedForInline and isVideoLayerInline
     22        * Modules/mediacontrols/mediaControlsApple.js:
     23        (Controller.prototype.showInlinePlaybackPlaceholderWhenSafe): Wait to show placeholder when entering fullscreen.
     24        (Controller.prototype.handlePresentationModeChange): Wait to show placeholder, and notify when placeholder is removed.
     25        * html/HTMLMediaElement.cpp:
     26        (WebCore::HTMLMediaElement::setPreparedForInline):
     27        (WebCore::HTMLMediaElement::waitForPreparedForInlineThen): Used to delay fullscreen cleanup until placeholder is removed.
     28        (WebCore::HTMLMediaElement::setVideoFullscreenLayer): Add a callback so we can wait until this completes before continuing.
     29        * html/HTMLMediaElement.h:
     30        (WebCore::HTMLMediaElement::isVideoLayerInline):
     31        (WebCore::HTMLMediaElement::waitForPreparedForInlineThen):
     32        (WebCore::HTMLMediaElement::setVideoFullscreenLayer): Add completionHandler.
     33        * platform/cocoa/WebVideoFullscreenModelVideoElement.h:
     34        (WebCore::WebVideoFullscreenModelVideoElement::setVideoFullscreenLayer): Add completionHandler.
     35        (WebCore::WebVideoFullscreenModelVideoElement::waitForPreparedForInlineThen): Added.
     36        * platform/cocoa/WebVideoFullscreenModelVideoElement.mm:
     37        (WebVideoFullscreenModelVideoElement::setVideoFullscreenLayer): Add completionHandler.
     38        (WebVideoFullscreenModelVideoElement::waitForPreparedForInlineThen):
     39        * platform/graphics/MediaPlayer.cpp:
     40        (WebCore::MediaPlayer::setVideoFullscreenLayer): Add completionHandler.
     41        * platform/graphics/MediaPlayer.h:
     42        (WebCore::MediaPlayer::setVideoFullscreenLayer): Add completionHandler.
     43        * platform/graphics/MediaPlayerPrivate.h:
     44        (WebCore::MediaPlayerPrivateInterface::setVideoFullscreenLayer): Add completionHandler.
     45        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
     46        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
     47        (WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayerLayer): Create two video layers.
     48        (WebCore::MediaPlayerPrivateAVFoundationObjC::destroyVideoLayer): Allow two video layers.
     49        (WebCore::MediaPlayerPrivateAVFoundationObjC::setVideoFullscreenLayer): Add completionHandler.
     50        (WebCore::MediaPlayerPrivateAVFoundationObjC::updateVideoLayerGravity): Allow two video layers.
     51        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h:
     52        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
     53        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::addDisplayLayer): Allow two video layers.
     54        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::setVideoFullscreenLayer): Add completionHandler.
     55        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h:
     56        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
     57        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::createPreviewLayers): Allow two video layers.
     58        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::setVideoFullscreenLayer): Add completionHandler.
     59        * platform/graphics/avfoundation/objc/VideoFullscreenLayerManager.h:
     60        * platform/graphics/avfoundation/objc/VideoFullscreenLayerManager.mm:
     61        (WebCore::VideoFullscreenLayerManager::setVideoLayers): Allow two video layers.
     62        (WebCore::VideoFullscreenLayerManager::setVideoFullscreenLayer): Add completionHandler.
     63        (WebCore::VideoFullscreenLayerManager::setVideoFullscreenFrame): Allow two video layers.
     64        (WebCore::VideoFullscreenLayerManager::didDestroyVideoLayer): Allow two video layers.
     65        (WebCore::VideoFullscreenLayerManager::setVideoLayer): Deleted.
     66        * platform/ios/WebVideoFullscreenControllerAVKit.mm:
     67        (WebVideoFullscreenControllerContext::didSetupFullscreen): Use completionHandler.
     68        (WebVideoFullscreenControllerContext::didExitFullscreen): Use completionHandler.
     69
    1702016-05-26  Ryosuke Niwa  <rniwa@webkit.org>
    271
  • trunk/Source/WebCore/Modules/mediacontrols/MediaControlsHost.cpp

    r200361 r201474  
    211211}
    212212
     213bool MediaControlsHost::isVideoLayerInline()
     214{
     215    return m_mediaElement->isVideoLayerInline();
     216}
     217
     218void MediaControlsHost::setPreparedForInline(bool value)
     219{
     220    m_mediaElement->setPreparedForInline(value);
     221}
     222
    213223bool MediaControlsHost::userGestureRequired() const
    214224{
  • trunk/Source/WebCore/Modules/mediacontrols/MediaControlsHost.h

    r200361 r201474  
    6565    bool allowsInlineMediaPlayback() const;
    6666    bool supportsFullscreen();
     67    bool isVideoLayerInline();
    6768    bool userGestureRequired() const;
     69    void setPreparedForInline(bool);
    6870
    6971    void updateCaptionDisplaySizes();
  • trunk/Source/WebCore/Modules/mediacontrols/MediaControlsHost.idl

    r199963 r201474  
    4343    readonly attribute DOMString captionDisplayMode;
    4444    void setSelectedTextTrack(TextTrack? track);
     45    void setPreparedForInline(boolean prepared);
    4546    readonly attribute HTMLElement textTrackContainer;
    4647    readonly attribute boolean allowsInlineMediaPlayback;
    4748    readonly attribute boolean supportsFullscreen;
     49    readonly attribute boolean isVideoLayerInline;
    4850    readonly attribute boolean userGestureRequired;
    4951
  • trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.js

    r201355 r201474  
    8383        webkitendfullscreen: 'handleFullscreenChange',
    8484    },
     85    PlaceholderPollingDelay: 33,
    8586    HideControlsDelay: 4 * 1000,
    8687    RewindAmount: 30,
     
    838839    },
    839840
     841    showInlinePlaybackPlaceholderWhenSafe: function() {
     842        if (this.presentationMode() != 'picture-in-picture')
     843            return;
     844
     845        if (!this.host.isVideoLayerInline)
     846            this.controls.inlinePlaybackPlaceholder.classList.remove(this.ClassNames.hidden);
     847        else
     848            setTimeout(this.showInlinePlaybackPlaceholderWhenSafe.bind(this), this.PlaceholderPollingDelay);
     849    },
     850
    840851    handlePresentationModeChange: function(event)
    841852    {
     
    855866                this.controls.panel.classList.add(this.ClassNames.pictureInPicture);
    856867                this.controls.inlinePlaybackPlaceholder.classList.add(this.ClassNames.pictureInPicture);
    857                 this.controls.inlinePlaybackPlaceholder.classList.remove(this.ClassNames.hidden);
     868                this.showInlinePlaybackPlaceholderWhenSafe();
    858869
    859870                this.controls.inlinePlaybackPlaceholderTextTop.innerText = this.UIString('This video is playing in Picture in Picture');
     
    884895        if (presentationMode != 'fullscreen' && this.video.paused && this.controlsAreHidden())
    885896            this.showControls();
     897        this.host.setPreparedForInline(presentationMode === 'inline')
    886898    },
    887899
  • trunk/Source/WebCore/html/HTMLMediaElement.cpp

    r201441 r201474  
    54725472}
    54735473
     5474void HTMLMediaElement::setPreparedForInline(bool value)
     5475{
     5476    m_preparedForInline = value;
     5477    if (m_preparedForInline && m_preparedForInlineCompletionHandler) {
     5478        m_preparedForInlineCompletionHandler();
     5479        m_preparedForInlineCompletionHandler = nullptr;
     5480    }
     5481}
     5482
     5483void HTMLMediaElement::waitForPreparedForInlineThen(std::function<void()> completionHandler)
     5484{
     5485    ASSERT(!m_preparedForInlineCompletionHandler);
     5486    if (m_preparedForInline)  {
     5487        completionHandler();
     5488        return;
     5489    }
     5490   
     5491    m_preparedForInlineCompletionHandler = completionHandler;
     5492}
     5493
    54745494#if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
    54755495
    5476 void HTMLMediaElement::setVideoFullscreenLayer(PlatformLayer* platformLayer)
     5496bool HTMLMediaElement::isVideoLayerInline()
     5497{
     5498    return !m_videoFullscreenLayer;
     5499};
     5500   
     5501void HTMLMediaElement::setVideoFullscreenLayer(PlatformLayer* platformLayer, std::function<void()> completionHandler)
    54775502{
    54785503    m_videoFullscreenLayer = platformLayer;
    5479     if (!m_player)
    5480         return;
     5504    if (!m_player) {
     5505        completionHandler();
     5506        return;
     5507    }
    54815508   
    5482     m_player->setVideoFullscreenLayer(platformLayer);
     5509    m_player->setVideoFullscreenLayer(platformLayer, completionHandler);
    54835510    setNeedsStyleRecalc(SyntheticStyleChange);
    54845511#if ENABLE(VIDEO_TRACK)
     
    55005527        m_player->setVideoFullscreenGravity(gravity);
    55015528}
     5529   
     5530#else
     5531   
     5532bool HTMLMediaElement::isVideoLayerInline()
     5533{
     5534    return true;
     5535};
    55025536
    55035537#endif
  • trunk/Source/WebCore/html/HTMLMediaElement.h

    r201435 r201474  
    134134    WEBCORE_EXPORT PlatformMedia platformMedia() const;
    135135    PlatformLayer* platformLayer() const;
     136    bool isVideoLayerInline();
     137    void setPreparedForInline(bool);
     138    void waitForPreparedForInlineThen(std::function<void()> completionHandler = [] { });
    136139#if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
    137     void setVideoFullscreenLayer(PlatformLayer*);
     140    void setVideoFullscreenLayer(PlatformLayer*, std::function<void()> completionHandler = [] { });
    138141    PlatformLayer* videoFullscreenLayer() const { return m_videoFullscreenLayer.get(); }
    139142    void setVideoFullscreenFrame(FloatRect);
     
    848851
    849852    VideoFullscreenMode m_videoFullscreenMode;
     853    bool m_preparedForInline;
     854    std::function<void()> m_preparedForInlineCompletionHandler;
    850855#if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
    851856    RetainPtr<PlatformLayer> m_videoFullscreenLayer;
  • trunk/Source/WebCore/platform/cocoa/WebVideoFullscreenModelVideoElement.h

    r201305 r201474  
    3535#include "PlatformLayer.h"
    3636#include "WebVideoFullscreenModel.h"
     37#include <functional>
    3738#include <wtf/RefPtr.h>
    3839#include <wtf/RetainPtr.h>
     
    5657    WEBCORE_EXPORT void setVideoElement(HTMLVideoElement*);
    5758    WEBCORE_EXPORT HTMLVideoElement* videoElement() const { return m_videoElement.get(); }
    58     WEBCORE_EXPORT void setVideoFullscreenLayer(PlatformLayer*);
     59    WEBCORE_EXPORT void setVideoFullscreenLayer(PlatformLayer*, std::function<void()> completionHandler = [] { });
     60    WEBCORE_EXPORT void waitForPreparedForInlineThen(std::function<void()> completionHandler = [] { });
    5961    WebPlaybackSessionModelMediaElement& playbackSessionModel() { return m_playbackSessionModel; }
    6062   
  • trunk/Source/WebCore/platform/cocoa/WebVideoFullscreenModelVideoElement.mm

    r201305 r201474  
    121121}
    122122
    123 void WebVideoFullscreenModelVideoElement::setVideoFullscreenLayer(PlatformLayer* videoLayer)
    124 {
    125     if (m_videoFullscreenLayer == videoLayer)
    126         return;
     123void WebVideoFullscreenModelVideoElement::setVideoFullscreenLayer(PlatformLayer* videoLayer, std::function<void()> completionHandler)
     124{
     125    if (m_videoFullscreenLayer == videoLayer) {
     126        completionHandler();
     127        return;
     128    }
    127129   
    128130    m_videoFullscreenLayer = videoLayer;
     
    134136    [m_videoFullscreenLayer setBounds:m_videoFrame];
    135137   
    136     if (m_videoElement)
    137         m_videoElement->setVideoFullscreenLayer(m_videoFullscreenLayer.get());
     138    if (!m_videoElement) {
     139        completionHandler();
     140        return;
     141    }
     142
     143    m_videoElement->setVideoFullscreenLayer(m_videoFullscreenLayer.get(), completionHandler);
     144}
     145
     146void WebVideoFullscreenModelVideoElement::waitForPreparedForInlineThen(std::function<void()> completionHandler)
     147{
     148    if (!m_videoElement) {
     149        completionHandler();
     150        return;
     151    }
     152
     153    m_videoElement->waitForPreparedForInlineThen(completionHandler);
    138154}
    139155
  • trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp

    r199326 r201474  
    661661   
    662662#if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
    663 void MediaPlayer::setVideoFullscreenLayer(PlatformLayer* layer)
    664 {
    665     m_private->setVideoFullscreenLayer(layer);
     663void MediaPlayer::setVideoFullscreenLayer(PlatformLayer* layer, std::function<void()> completionHandler)
     664{
     665    m_private->setVideoFullscreenLayer(layer, completionHandler);
    666666}
    667667
  • trunk/Source/WebCore/platform/graphics/MediaPlayer.h

    r199326 r201474  
    309309
    310310#if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
    311     void setVideoFullscreenLayer(PlatformLayer*);
     311    void setVideoFullscreenLayer(PlatformLayer*, std::function<void()> completionHandler = [] { });
    312312    void setVideoFullscreenFrame(FloatRect);
    313313    using MediaPlayerEnums::VideoGravity;
  • trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h

    r199326 r201474  
    6060
    6161#if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
    62     virtual void setVideoFullscreenLayer(PlatformLayer*) { }
     62    virtual void setVideoFullscreenLayer(PlatformLayer*, std::function<void()> completionHandler) { completionHandler(); }
    6363    virtual void setVideoFullscreenFrame(FloatRect) { }
    6464    virtual void setVideoFullscreenGravity(MediaPlayer::VideoGravity) { }
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h

    r199672 r201474  
    173173    PlatformLayer* platformLayer() const override;
    174174#if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
    175     void setVideoFullscreenLayer(PlatformLayer*) override;
     175    void setVideoFullscreenLayer(PlatformLayer*, std::function<void()> completionHandler) override;
    176176    void setVideoFullscreenFrame(FloatRect) override;
    177177    void setVideoFullscreenGravity(MediaPlayer::VideoGravity) override;
     
    330330    RetainPtr<AVPlayerItem> m_avPlayerItem;
    331331    RetainPtr<AVPlayerLayer> m_videoLayer;
     332    RetainPtr<AVPlayerLayer> m_secondaryVideoLayer;
    332333#if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
    333334    std::unique_ptr<VideoFullscreenLayerManager> m_videoFullscreenLayerManager;
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm

    r201038 r201474  
    731731    [m_videoLayer setPlayer:m_avPlayer.get()];
    732732    [m_videoLayer setBackgroundColor:cachedCGColor(Color::black)];
     733
     734    m_secondaryVideoLayer = adoptNS([allocAVPlayerLayerInstance() init]);
     735    [m_secondaryVideoLayer setPlayer:m_avPlayer.get()];
     736    [m_secondaryVideoLayer setBackgroundColor:cachedCGColor(Color::black)];
     737
    733738#ifndef NDEBUG
    734739    [m_videoLayer setName:@"MediaPlayerPrivate AVPlayerLayer"];
     740    [m_secondaryVideoLayer setName:@"MediaPlayerPrivate AVPlayerLayer secondary"];
    735741#endif
    736742    [m_videoLayer addObserver:m_objcObserver.get() forKeyPath:@"readyForDisplay" options:NSKeyValueObservingOptionNew context:(void *)MediaPlayerAVFoundationObservationContextAVPlayerLayer];
    737743    updateVideoLayerGravity();
    738744    [m_videoLayer setContentsScale:player()->client().mediaPlayerContentsScale()];
     745    [m_secondaryVideoLayer setContentsScale:player()->client().mediaPlayerContentsScale()];
    739746    IntSize defaultSize = snappedIntRect(player()->client().mediaPlayerContentBoxRect()).size();
    740747    LOG(Media, "MediaPlayerPrivateAVFoundationObjC::createVideoLayer(%p) - returning %p", this, m_videoLayer.get());
    741748
    742749#if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
    743     m_videoFullscreenLayerManager->setVideoLayer(m_videoLayer.get(), defaultSize);
     750    m_videoFullscreenLayerManager->setVideoLayers(m_videoLayer.get(), m_secondaryVideoLayer.get(), defaultSize);
    744751
    745752#if PLATFORM(IOS)
     
    749756#else
    750757    [m_videoLayer setFrame:CGRectMake(0, 0, defaultSize.width(), defaultSize.height())];
     758    [m_secondaryVideoLayer setFrame:CGRectMake(0, 0, defaultSize.width(), defaultSize.height())];
    751759#endif
    752760}
     
    759767    LOG(Media, "MediaPlayerPrivateAVFoundationObjC::destroyVideoLayer(%p) - destroying %p", this, m_videoLayer.get());
    760768
    761     [m_videoLayer.get() removeObserver:m_objcObserver.get() forKeyPath:@"readyForDisplay"];
    762     [m_videoLayer.get() setPlayer:nil];
     769    [m_videoLayer removeObserver:m_objcObserver.get() forKeyPath:@"readyForDisplay"];
     770    [m_videoLayer setPlayer:nil];
     771    [m_secondaryVideoLayer setPlayer:nil];
    763772
    764773#if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
     
    767776
    768777    m_videoLayer = nil;
     778    m_secondaryVideoLayer = nil;
    769779}
    770780
     
    11841194
    11851195#if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
    1186 void MediaPlayerPrivateAVFoundationObjC::setVideoFullscreenLayer(PlatformLayer* videoFullscreenLayer)
    1187 {
    1188     if (m_videoFullscreenLayerManager->videoFullscreenLayer() == videoFullscreenLayer)
    1189         return;
    1190 
    1191     m_videoFullscreenLayerManager->setVideoFullscreenLayer(videoFullscreenLayer);
     1196void MediaPlayerPrivateAVFoundationObjC::setVideoFullscreenLayer(PlatformLayer* videoFullscreenLayer, std::function<void()> completionHandler)
     1197{
     1198    if (m_videoFullscreenLayerManager->videoFullscreenLayer() == videoFullscreenLayer) {
     1199        completionHandler();
     1200        return;
     1201    }
     1202
     1203    m_videoFullscreenLayerManager->setVideoFullscreenLayer(videoFullscreenLayer, completionHandler);
    11921204
    11931205    if (m_videoFullscreenLayerManager->videoFullscreenLayer() && m_textTrackRepresentationLayer) {
     
    18731885    NSString* gravity = shouldMaintainAspectRatio() ? AVLayerVideoGravityResizeAspect : AVLayerVideoGravityResize;
    18741886    [m_videoLayer.get() setVideoGravity:gravity];
     1887    [m_secondaryVideoLayer.get() setVideoGravity:gravity];
    18751888    [CATransaction commit];
    18761889}
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h

    r197563 r201474  
    8888
    8989#if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
    90     void setVideoFullscreenLayer(PlatformLayer*) override;
     90    void setVideoFullscreenLayer(PlatformLayer*, std::function<void()> completionHandler) override;
    9191    void setVideoFullscreenFrame(FloatRect) override;
    9292#endif
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm

    r200315 r201474  
    771771
    772772#if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
    773     m_videoFullscreenLayerManager->setVideoLayer(m_sampleBufferDisplayLayer.get(), snappedIntRect(m_player->client().mediaPlayerContentBoxRect()).size());
     773    m_videoFullscreenLayerManager->setVideoLayers(m_sampleBufferDisplayLayer.get(), nil, snappedIntRect(m_player->client().mediaPlayerContentBoxRect()).size());
    774774#endif
    775775}
     
    829829
    830830#if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
    831 void MediaPlayerPrivateMediaSourceAVFObjC::setVideoFullscreenLayer(PlatformLayer *videoFullscreenLayer)
    832 {
    833     m_videoFullscreenLayerManager->setVideoFullscreenLayer(videoFullscreenLayer);
     831void MediaPlayerPrivateMediaSourceAVFObjC::setVideoFullscreenLayer(PlatformLayer *videoFullscreenLayer, std::function<void()> completionHandler)
     832{
     833    m_videoFullscreenLayerManager->setVideoFullscreenLayer(videoFullscreenLayer, completionHandler);
    834834}
    835835
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h

    r197807 r201474  
    161161
    162162#if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
    163     void setVideoFullscreenLayer(PlatformLayer*) override;
     163    void setVideoFullscreenLayer(PlatformLayer*, std::function<void()> completionHandler) override;
    164164    void setVideoFullscreenFrame(FloatRect) override;
    165165#endif
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm

    r201333 r201474  
    405405
    406406#if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
    407         m_videoFullscreenLayerManager->setVideoLayer(m_videoBackgroundLayer.get(), snappedIntRect(m_player->client().mediaPlayerContentBoxRect()).size());
     407        m_videoFullscreenLayerManager->setVideoLayers(m_videoBackgroundLayer.get(), nil, snappedIntRect(m_player->client().mediaPlayerContentBoxRect()).size());
    408408#endif
    409409    }
     
    475475
    476476#if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
    477 void MediaPlayerPrivateMediaStreamAVFObjC::setVideoFullscreenLayer(PlatformLayer *videoFullscreenLayer)
    478 {
    479     m_videoFullscreenLayerManager->setVideoFullscreenLayer(videoFullscreenLayer);
     477void MediaPlayerPrivateMediaStreamAVFObjC::setVideoFullscreenLayer(PlatformLayer *videoFullscreenLayer, std::function<void()> completionHandler)
     478{
     479    m_videoFullscreenLayerManager->setVideoFullscreenLayer(videoFullscreenLayer, completionHandler);
    480480}
    481481
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/VideoFullscreenLayerManager.h

    r195595 r201474  
    3232#include "IntSize.h"
    3333#include "PlatformLayer.h"
     34#include <functional>
    3435#include <wtf/RetainPtr.h>
    3536
     
    4445    PlatformLayer *videoFullscreenLayer() const { return m_videoFullscreenLayer.get(); }
    4546    FloatRect videoFullscreenFrame() const { return m_videoFullscreenFrame; }
    46     void setVideoLayer(PlatformLayer *, IntSize contentSize);
    47     void setVideoFullscreenLayer(PlatformLayer *);
     47    void setVideoLayers(PlatformLayer *, PlatformLayer *, IntSize contentSize);
     48    void setVideoFullscreenLayer(PlatformLayer *, std::function<void()> completionHandler);
    4849    void setVideoFullscreenFrame(FloatRect);
    4950    void didDestroyVideoLayer();
     
    5556    RetainPtr<PlatformLayer> m_videoFullscreenLayer;
    5657    RetainPtr<PlatformLayer> m_videoLayer;
     58    RetainPtr<PlatformLayer> m_secondaryVideoLayer;
    5759    FloatRect m_videoFullscreenFrame;
    5860};
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/VideoFullscreenLayerManager.mm

    r195595 r201474  
    6767}
    6868
    69 void VideoFullscreenLayerManager::setVideoLayer(PlatformLayer *videoLayer, IntSize contentSize)
     69void VideoFullscreenLayerManager::setVideoLayers(PlatformLayer *videoLayer, PlatformLayer *secondaryVideoLayer, IntSize contentSize)
    7070{
    7171    m_videoLayer = videoLayer;
     72    m_secondaryVideoLayer = secondaryVideoLayer;
    7273
    7374    [m_videoLayer web_disableAllActions];
     75    [m_secondaryVideoLayer web_disableAllActions];
    7476    m_videoInlineLayer = adoptNS([[WebVideoContainerLayer alloc] init]);
    7577#ifndef NDEBUG
     
    7880    [m_videoInlineLayer setFrame:CGRectMake(0, 0, contentSize.width(), contentSize.height())];
    7981    if (m_videoFullscreenLayer) {
    80         [m_videoLayer setFrame:CGRectMake(0, 0, m_videoFullscreenFrame.width(), m_videoFullscreenFrame.height())];
    81         [m_videoFullscreenLayer insertSublayer:m_videoLayer.get() atIndex:0];
     82        [m_videoLayer removeFromSuperlayer];
     83        PlatformLayer *activeLayer = secondaryVideoLayer ? secondaryVideoLayer : videoLayer;
     84        [activeLayer setFrame:CGRectMake(0, 0, m_videoFullscreenFrame.width(), m_videoFullscreenFrame.height())];
     85        [m_videoFullscreenLayer insertSublayer:activeLayer atIndex:0];
    8286    } else {
    8387        [m_videoInlineLayer insertSublayer:m_videoLayer.get() atIndex:0];
    8488        [m_videoLayer setFrame:m_videoInlineLayer.get().bounds];
     89        [m_secondaryVideoLayer removeFromSuperlayer];
    8590    }
    8691}
    8792
    88 void VideoFullscreenLayerManager::setVideoFullscreenLayer(PlatformLayer *videoFullscreenLayer)
     93void VideoFullscreenLayerManager::setVideoFullscreenLayer(PlatformLayer *videoFullscreenLayer, std::function<void()> completionHandler)
    8994{
    90     if (m_videoFullscreenLayer == videoFullscreenLayer)
     95    if (m_videoFullscreenLayer == videoFullscreenLayer) {
     96        completionHandler();
    9197        return;
     98    }
    9299
    93100    m_videoFullscreenLayer = videoFullscreenLayer;
     
    96103    [CATransaction setDisableActions:YES];
    97104
    98     CAContext *oldContext = [m_videoLayer context];
    99     CAContext *newContext = nil;
     105    if (m_secondaryVideoLayer && m_videoLayer) {
     106        if (m_videoFullscreenLayer) {
     107            [m_videoFullscreenLayer insertSublayer:m_secondaryVideoLayer.get() atIndex:0];
     108            [m_secondaryVideoLayer setFrame:CGRectMake(0, 0, m_videoFullscreenFrame.width(), m_videoFullscreenFrame.height())];
     109        } else if (m_videoInlineLayer) {
     110            [m_videoLayer setFrame:[m_videoInlineLayer bounds]];
     111            [m_videoInlineLayer insertSublayer:m_videoLayer.get() atIndex:0];
     112        }
    100113
    101     if (m_videoFullscreenLayer && m_videoLayer) {
    102         [m_videoFullscreenLayer insertSublayer:m_videoLayer.get() atIndex:0];
    103         [m_videoLayer setFrame:CGRectMake(0, 0, m_videoFullscreenFrame.width(), m_videoFullscreenFrame.height())];
    104         newContext = [m_videoFullscreenLayer context];
    105     } else if (m_videoInlineLayer && m_videoLayer) {
    106         [m_videoLayer setFrame:[m_videoInlineLayer bounds]];
    107         [m_videoLayer removeFromSuperlayer];
    108         [m_videoInlineLayer insertSublayer:m_videoLayer.get() atIndex:0];
    109         newContext = [m_videoInlineLayer context];
    110     } else if (m_videoLayer)
    111         [m_videoLayer removeFromSuperlayer];
     114        RetainPtr<PlatformLayer> fullscreenLayer = m_videoFullscreenLayer;
     115        RetainPtr<PlatformLayer> videoLayer = m_videoLayer;
     116        RetainPtr<PlatformLayer> secondaryVideoLayer = m_secondaryVideoLayer;
    112117
    113     if (oldContext && newContext && oldContext != newContext) {
    114         mach_port_t fencePort = [oldContext createFencePort];
    115         [newContext setFencePort:fencePort];
    116         mach_port_deallocate(mach_task_self(), fencePort);
     118        [CATransaction setCompletionBlock:[completionHandler, fullscreenLayer, videoLayer, secondaryVideoLayer] {
     119            [CATransaction begin];
     120            [CATransaction setDisableActions:YES];
     121           
     122            if (fullscreenLayer)
     123                [videoLayer removeFromSuperlayer];
     124            else
     125                [secondaryVideoLayer removeFromSuperlayer];
     126
     127            [CATransaction setCompletionBlock:[completionHandler] {
     128                completionHandler();
     129            }];
     130            [CATransaction commit];
     131        }];
     132    } else if (m_videoLayer) {
     133        if (m_videoFullscreenLayer) {
     134            [m_videoFullscreenLayer insertSublayer:m_videoLayer.get() atIndex:0];
     135            [m_videoLayer setFrame:CGRectMake(0, 0, m_videoFullscreenFrame.width(), m_videoFullscreenFrame.height())];
     136        } else if (m_videoInlineLayer) {
     137            [m_videoLayer setFrame:[m_videoInlineLayer bounds]];
     138            [m_videoLayer removeFromSuperlayer];
     139            [m_videoInlineLayer insertSublayer:m_videoLayer.get() atIndex:0];
     140        } else
     141            [m_videoLayer removeFromSuperlayer];
     142
     143        CAContext *oldContext = [m_videoFullscreenLayer context];
     144        CAContext *newContext = [m_videoInlineLayer context];
     145        if (oldContext && newContext && oldContext != newContext) {
     146            mach_port_t fencePort = [oldContext createFencePort];
     147            [newContext setFencePort:fencePort];
     148            mach_port_deallocate(mach_task_self(), fencePort);
     149        }
     150
     151        [CATransaction setCompletionBlock:[completionHandler] {
     152            completionHandler();
     153        }];
     154    } else {
     155        [CATransaction setCompletionBlock:[completionHandler] {
     156            completionHandler();
     157        }];
    117158    }
     159
    118160    [CATransaction commit];
    119161}
     
    125167        return;
    126168
    127     if (m_videoLayer)
    128         [m_videoLayer setFrame:CGRectMake(0, 0, videoFullscreenFrame.width(), videoFullscreenFrame.height())];
     169    PlatformLayer *activeLayer = m_secondaryVideoLayer.get() ? m_secondaryVideoLayer.get() : m_videoLayer.get();
     170    [activeLayer setFrame:CGRectMake(0, 0, videoFullscreenFrame.width(), videoFullscreenFrame.height())];
    129171}
    130172
    131173void VideoFullscreenLayerManager::didDestroyVideoLayer()
    132174{
    133     if (m_videoFullscreenLayer)
    134         [m_videoLayer removeFromSuperlayer];
     175    [m_videoLayer removeFromSuperlayer];
     176    [m_secondaryVideoLayer removeFromSuperlayer];
    135177
    136178    m_videoInlineLayer = nil;
    137179    m_videoLayer = nil;
     180    m_secondaryVideoLayer = nil;
    138181}
    139182
  • trunk/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm

    r201354 r201474  
    248248    WebThreadRun([protectedThis, this, videoFullscreenLayer] {
    249249        [videoFullscreenLayer setBackgroundColor:cachedCGColor(WebCore::Color::transparent)];
    250         m_model->setVideoFullscreenLayer(videoFullscreenLayer.get());
    251         dispatch_async(dispatch_get_main_queue(), [protectedThis, this] {
    252             m_interface->enterFullscreen();
     250        m_model->setVideoFullscreenLayer(videoFullscreenLayer.get(), [protectedThis, this] {
     251            dispatch_async(dispatch_get_main_queue(), [protectedThis, this] {
     252                m_interface->enterFullscreen();
     253            });
    253254        });
    254255    });
     
    260261    RefPtr<WebVideoFullscreenControllerContext> protectedThis(this);
    261262    WebThreadRun([protectedThis, this] {
    262         m_model->setVideoFullscreenLayer(nil);
    263         dispatch_async(dispatch_get_main_queue(), [protectedThis, this] {
    264             m_interface->cleanupFullscreen();
     263        m_model->setVideoFullscreenLayer(nil, [protectedThis, this] {
     264            dispatch_async(dispatch_get_main_queue(), [protectedThis, this] {
     265                m_interface->cleanupFullscreen();
     266            });
    265267        });
    266268    });
  • trunk/Source/WebKit2/ChangeLog

    r201464 r201474  
     12016-05-27  Jeremy Jones  <jeremyj@apple.com>
     2
     3        Decrease flicker when changing video presentation mode.
     4        https://bugs.webkit.org/show_bug.cgi?id=158148
     5        rdar://problem/24476949
     6
     7        Reviewed by Tim Horton.
     8
     9        Prevent flicker by using setVideoFullscreenLayer with a completion handler to delay
     10        enter fullscreen and cleanup fullscreen until the video layer has completely been
     11        installed or removed.
     12
     13        * WebProcess/cocoa/WebVideoFullscreenManager.mm:
     14        (WebKit::WebVideoFullscreenManager::didSetupFullscreen):
     15        (WebKit::WebVideoFullscreenManager::didExitFullscreen):
     16
    1172016-05-27  Chris Dumez  <cdumez@apple.com>
    218
  • trunk/Source/WebKit2/WebProcess/cocoa/WebVideoFullscreenManager.mm

    r200157 r201474  
    370370
    371371    interface->layerHostingContext()->setRootLayer(videoLayer);
    372     model->setVideoFullscreenLayer(videoLayer);
    373 
     372
     373    RefPtr<WebVideoFullscreenManager> strongThis(this);
     374   
     375    model->setVideoFullscreenLayer(videoLayer, [strongThis, this, contextId] {
     376        dispatch_async(dispatch_get_main_queue(), [strongThis, this, contextId] {
     377            m_page->send(Messages::WebVideoFullscreenManagerProxy::EnterFullscreen(contextId), m_page->pageID());
     378        });
     379    });
     380   
    374381    [CATransaction commit];
    375 
    376     RefPtr<WebVideoFullscreenManager> strongThis(this);
    377     dispatch_async(dispatch_get_main_queue(), [strongThis, this, contextId] {
    378         m_page->send(Messages::WebVideoFullscreenManagerProxy::EnterFullscreen(contextId), m_page->pageID());
    379     });
    380382}
    381383   
     
    408410    RefPtr<WebVideoFullscreenInterfaceContext> interface;
    409411    std::tie(model, interface) = ensureModelAndInterface(contextId);
    410 
    411     model->setVideoFullscreenLayer(nil);
    412 
    413412    RefPtr<WebVideoFullscreenManager> strongThis(this);
    414     dispatch_async(dispatch_get_main_queue(), [strongThis, contextId, interface] {
    415         if (interface->layerHostingContext()) {
    416             interface->layerHostingContext()->setRootLayer(nullptr);
    417             interface->setLayerHostingContext(nullptr);
    418         }
    419         if (strongThis->m_page)
    420             strongThis->m_page->send(Messages::WebVideoFullscreenManagerProxy::CleanupFullscreen(contextId), strongThis->m_page->pageID());
     413   
     414    model->waitForPreparedForInlineThen([strongThis, this, contextId, interface, model] {
     415        dispatch_async(dispatch_get_main_queue(), [strongThis, this, contextId, interface, model] {
     416            model->setVideoFullscreenLayer(nil, [strongThis, this, contextId, interface] {
     417                dispatch_async(dispatch_get_main_queue(), [strongThis, this, contextId, interface] {
     418                    if (interface->layerHostingContext()) {
     419                        interface->layerHostingContext()->setRootLayer(nullptr);
     420                        interface->setLayerHostingContext(nullptr);
     421                    }
     422                    if (strongThis->m_page)
     423                        strongThis->m_page->send(Messages::WebVideoFullscreenManagerProxy::CleanupFullscreen(contextId), strongThis->m_page->pageID());
     424                });
     425            });
     426        });
    421427    });
    422428}
Note: See TracChangeset for help on using the changeset viewer.