Title: [201474] trunk/Source
Revision
201474
Author
commit-qu...@webkit.org
Date
2016-05-27 16:58:28 -0700 (Fri, 27 May 2016)

Log Message

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

Patch by Jeremy Jones <jere...@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):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (201473 => 201474)


--- trunk/Source/WebCore/ChangeLog	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/ChangeLog	2016-05-27 23:58:28 UTC (rev 201474)
@@ -1,3 +1,72 @@
+2016-05-27  Jeremy Jones  <jere...@apple.com>
+
+        Decrease flicker when changing video presentation mode.
+        https://bugs.webkit.org/show_bug.cgi?id=158148
+        rdar://problem/24476949
+
+        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.
+
 2016-05-26  Ryosuke Niwa  <rn...@webkit.org>
 
         Crash in TreeScope::focusedElement

Modified: trunk/Source/WebCore/Modules/mediacontrols/MediaControlsHost.cpp (201473 => 201474)


--- trunk/Source/WebCore/Modules/mediacontrols/MediaControlsHost.cpp	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/Modules/mediacontrols/MediaControlsHost.cpp	2016-05-27 23:58:28 UTC (rev 201474)
@@ -210,6 +210,16 @@
     return m_mediaElement->supportsFullscreen(HTMLMediaElementEnums::VideoFullscreenModeStandard);
 }
 
+bool MediaControlsHost::isVideoLayerInline()
+{
+    return m_mediaElement->isVideoLayerInline();
+}
+
+void MediaControlsHost::setPreparedForInline(bool value)
+{
+    m_mediaElement->setPreparedForInline(value);
+}
+
 bool MediaControlsHost::userGestureRequired() const
 {
     return !m_mediaElement->mediaSession().playbackPermitted(*m_mediaElement);

Modified: trunk/Source/WebCore/Modules/mediacontrols/MediaControlsHost.h (201473 => 201474)


--- trunk/Source/WebCore/Modules/mediacontrols/MediaControlsHost.h	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/Modules/mediacontrols/MediaControlsHost.h	2016-05-27 23:58:28 UTC (rev 201474)
@@ -64,7 +64,9 @@
     void updateTextTrackContainer();
     bool allowsInlineMediaPlayback() const;
     bool supportsFullscreen();
+    bool isVideoLayerInline();
     bool userGestureRequired() const;
+    void setPreparedForInline(bool);
 
     void updateCaptionDisplaySizes();
     void enteredFullscreen();

Modified: trunk/Source/WebCore/Modules/mediacontrols/MediaControlsHost.idl (201473 => 201474)


--- trunk/Source/WebCore/Modules/mediacontrols/MediaControlsHost.idl	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/Modules/mediacontrols/MediaControlsHost.idl	2016-05-27 23:58:28 UTC (rev 201474)
@@ -42,9 +42,11 @@
     readonly attribute TextTrack captionMenuAutomaticItem;
     readonly attribute DOMString captionDisplayMode;
     void setSelectedTextTrack(TextTrack? track);
+    void setPreparedForInline(boolean prepared);
     readonly attribute HTMLElement textTrackContainer;
     readonly attribute boolean allowsInlineMediaPlayback;
     readonly attribute boolean supportsFullscreen;
+    readonly attribute boolean isVideoLayerInline;
     readonly attribute boolean userGestureRequired;
 
     readonly attribute DOMString externalDeviceDisplayName;

Modified: trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.js (201473 => 201474)


--- trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.js	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/Modules/mediacontrols/mediaControlsApple.js	2016-05-27 23:58:28 UTC (rev 201474)
@@ -82,6 +82,7 @@
         webkitbeginfullscreen: 'handleFullscreenChange',
         webkitendfullscreen: 'handleFullscreenChange',
     },
+    PlaceholderPollingDelay: 33,
     HideControlsDelay: 4 * 1000,
     RewindAmount: 30,
     MaximumSeekRate: 8,
@@ -837,6 +838,16 @@
             this.controls.pictureInPictureButton.classList.add(this.ClassNames.hidden);
     },
 
+    showInlinePlaybackPlaceholderWhenSafe: function() {
+        if (this.presentationMode() != 'picture-in-picture')
+            return;
+
+        if (!this.host.isVideoLayerInline)
+            this.controls.inlinePlaybackPlaceholder.classList.remove(this.ClassNames.hidden);
+        else
+            setTimeout(this.showInlinePlaybackPlaceholderWhenSafe.bind(this), this.PlaceholderPollingDelay);
+    },
+
     handlePresentationModeChange: function(event)
     {
         var presentationMode = this.presentationMode();
@@ -854,7 +865,7 @@
             case 'picture-in-picture':
                 this.controls.panel.classList.add(this.ClassNames.pictureInPicture);
                 this.controls.inlinePlaybackPlaceholder.classList.add(this.ClassNames.pictureInPicture);
-                this.controls.inlinePlaybackPlaceholder.classList.remove(this.ClassNames.hidden);
+                this.showInlinePlaybackPlaceholderWhenSafe();
 
                 this.controls.inlinePlaybackPlaceholderTextTop.innerText = this.UIString('This video is playing in Picture in Picture');
                 this.controls.inlinePlaybackPlaceholderTextTop.classList.add(this.ClassNames.pictureInPicture);
@@ -883,6 +894,7 @@
         this.resetHideControlsTimer();
         if (presentationMode != 'fullscreen' && this.video.paused && this.controlsAreHidden())
             this.showControls();
+        this.host.setPreparedForInline(presentationMode === 'inline')
     },
 
     handleFullscreenChange: function(event)

Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (201473 => 201474)


--- trunk/Source/WebCore/html/HTMLMediaElement.cpp	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp	2016-05-27 23:58:28 UTC (rev 201474)
@@ -5471,15 +5471,42 @@
     return m_player ? m_player->platformLayer() : nullptr;
 }
 
+void HTMLMediaElement::setPreparedForInline(bool value)
+{
+    m_preparedForInline = value;
+    if (m_preparedForInline && m_preparedForInlineCompletionHandler) {
+        m_preparedForInlineCompletionHandler();
+        m_preparedForInlineCompletionHandler = nullptr;
+    }
+}
+
+void HTMLMediaElement::waitForPreparedForInlineThen(std::function<void()> completionHandler)
+{
+    ASSERT(!m_preparedForInlineCompletionHandler);
+    if (m_preparedForInline)  {
+        completionHandler();
+        return;
+    }
+    
+    m_preparedForInlineCompletionHandler = completionHandler;
+}
+
 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
 
-void HTMLMediaElement::setVideoFullscreenLayer(PlatformLayer* platformLayer)
+bool HTMLMediaElement::isVideoLayerInline()
 {
+    return !m_videoFullscreenLayer;
+};
+    
+void HTMLMediaElement::setVideoFullscreenLayer(PlatformLayer* platformLayer, std::function<void()> completionHandler)
+{
     m_videoFullscreenLayer = platformLayer;
-    if (!m_player)
+    if (!m_player) {
+        completionHandler();
         return;
+    }
     
-    m_player->setVideoFullscreenLayer(platformLayer);
+    m_player->setVideoFullscreenLayer(platformLayer, completionHandler);
     setNeedsStyleRecalc(SyntheticStyleChange);
 #if ENABLE(VIDEO_TRACK)
     updateTextTrackDisplay();
@@ -5499,6 +5526,13 @@
     if (m_player)
         m_player->setVideoFullscreenGravity(gravity);
 }
+    
+#else
+    
+bool HTMLMediaElement::isVideoLayerInline()
+{
+    return true;
+};
 
 #endif
 

Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (201473 => 201474)


--- trunk/Source/WebCore/html/HTMLMediaElement.h	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h	2016-05-27 23:58:28 UTC (rev 201474)
@@ -133,8 +133,11 @@
 
     WEBCORE_EXPORT PlatformMedia platformMedia() const;
     PlatformLayer* platformLayer() const;
+    bool isVideoLayerInline();
+    void setPreparedForInline(bool);
+    void waitForPreparedForInlineThen(std::function<void()> completionHandler = [] { });
 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
-    void setVideoFullscreenLayer(PlatformLayer*);
+    void setVideoFullscreenLayer(PlatformLayer*, std::function<void()> completionHandler = [] { });
     PlatformLayer* videoFullscreenLayer() const { return m_videoFullscreenLayer.get(); }
     void setVideoFullscreenFrame(FloatRect);
     void setVideoFullscreenGravity(MediaPlayerEnums::VideoGravity);
@@ -847,6 +850,8 @@
     RefPtr<Node> m_nextChildNodeToConsider;
 
     VideoFullscreenMode m_videoFullscreenMode;
+    bool m_preparedForInline;
+    std::function<void()> m_preparedForInlineCompletionHandler;
 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
     RetainPtr<PlatformLayer> m_videoFullscreenLayer;
     FloatRect m_videoFullscreenFrame;

Modified: trunk/Source/WebCore/platform/cocoa/WebVideoFullscreenModelVideoElement.h (201473 => 201474)


--- trunk/Source/WebCore/platform/cocoa/WebVideoFullscreenModelVideoElement.h	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/platform/cocoa/WebVideoFullscreenModelVideoElement.h	2016-05-27 23:58:28 UTC (rev 201474)
@@ -34,6 +34,7 @@
 #include "HTMLMediaElementEnums.h"
 #include "PlatformLayer.h"
 #include "WebVideoFullscreenModel.h"
+#include <functional>
 #include <wtf/RefPtr.h>
 #include <wtf/RetainPtr.h>
 #include <wtf/Vector.h>
@@ -55,7 +56,8 @@
     WEBCORE_EXPORT void setWebVideoFullscreenInterface(WebVideoFullscreenInterface*);
     WEBCORE_EXPORT void setVideoElement(HTMLVideoElement*);
     WEBCORE_EXPORT HTMLVideoElement* videoElement() const { return m_videoElement.get(); }
-    WEBCORE_EXPORT void setVideoFullscreenLayer(PlatformLayer*);
+    WEBCORE_EXPORT void setVideoFullscreenLayer(PlatformLayer*, std::function<void()> completionHandler = [] { });
+    WEBCORE_EXPORT void waitForPreparedForInlineThen(std::function<void()> completionHandler = [] { });
     WebPlaybackSessionModelMediaElement& playbackSessionModel() { return m_playbackSessionModel; }
     
     WEBCORE_EXPORT void handleEvent(WebCore::ScriptExecutionContext*, WebCore::Event*) override;

Modified: trunk/Source/WebCore/platform/cocoa/WebVideoFullscreenModelVideoElement.mm (201473 => 201474)


--- trunk/Source/WebCore/platform/cocoa/WebVideoFullscreenModelVideoElement.mm	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/platform/cocoa/WebVideoFullscreenModelVideoElement.mm	2016-05-27 23:58:28 UTC (rev 201474)
@@ -120,10 +120,12 @@
         m_videoFullscreenInterface->setVideoDimensions(true, m_videoElement->videoWidth(), m_videoElement->videoHeight());
 }
 
-void WebVideoFullscreenModelVideoElement::setVideoFullscreenLayer(PlatformLayer* videoLayer)
+void WebVideoFullscreenModelVideoElement::setVideoFullscreenLayer(PlatformLayer* videoLayer, std::function<void()> completionHandler)
 {
-    if (m_videoFullscreenLayer == videoLayer)
+    if (m_videoFullscreenLayer == videoLayer) {
+        completionHandler();
         return;
+    }
     
     m_videoFullscreenLayer = videoLayer;
 #if PLATFORM(MAC)
@@ -133,10 +135,24 @@
 #endif
     [m_videoFullscreenLayer setBounds:m_videoFrame];
     
-    if (m_videoElement)
-        m_videoElement->setVideoFullscreenLayer(m_videoFullscreenLayer.get());
+    if (!m_videoElement) {
+        completionHandler();
+        return;
+    }
+
+    m_videoElement->setVideoFullscreenLayer(m_videoFullscreenLayer.get(), completionHandler);
 }
 
+void WebVideoFullscreenModelVideoElement::waitForPreparedForInlineThen(std::function<void()> completionHandler)
+{
+    if (!m_videoElement) {
+        completionHandler();
+        return;
+    }
+
+    m_videoElement->waitForPreparedForInlineThen(completionHandler);
+}
+
 void WebVideoFullscreenModelVideoElement::requestFullscreenMode(HTMLMediaElementEnums::VideoFullscreenMode mode)
 {
     if (m_videoElement && m_videoElement->fullscreenMode() != mode)

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp (201473 => 201474)


--- trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp	2016-05-27 23:58:28 UTC (rev 201474)
@@ -660,9 +660,9 @@
 }
     
 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
-void MediaPlayer::setVideoFullscreenLayer(PlatformLayer* layer)
+void MediaPlayer::setVideoFullscreenLayer(PlatformLayer* layer, std::function<void()> completionHandler)
 {
-    m_private->setVideoFullscreenLayer(layer);
+    m_private->setVideoFullscreenLayer(layer, completionHandler);
 }
 
 void MediaPlayer::setVideoFullscreenFrame(FloatRect frame)

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.h (201473 => 201474)


--- trunk/Source/WebCore/platform/graphics/MediaPlayer.h	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.h	2016-05-27 23:58:28 UTC (rev 201474)
@@ -308,7 +308,7 @@
     PlatformLayer* platformLayer() const;
 
 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
-    void setVideoFullscreenLayer(PlatformLayer*);
+    void setVideoFullscreenLayer(PlatformLayer*, std::function<void()> completionHandler = [] { });
     void setVideoFullscreenFrame(FloatRect);
     using MediaPlayerEnums::VideoGravity;
     void setVideoFullscreenGravity(VideoGravity);

Modified: trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h (201473 => 201474)


--- trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayerPrivate.h	2016-05-27 23:58:28 UTC (rev 201474)
@@ -59,7 +59,7 @@
     virtual PlatformLayer* platformLayer() const { return 0; }
 
 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
-    virtual void setVideoFullscreenLayer(PlatformLayer*) { }
+    virtual void setVideoFullscreenLayer(PlatformLayer*, std::function<void()> completionHandler) { completionHandler(); }
     virtual void setVideoFullscreenFrame(FloatRect) { }
     virtual void setVideoFullscreenGravity(MediaPlayer::VideoGravity) { }
     virtual void setVideoFullscreenMode(MediaPlayer::VideoFullscreenMode) { }

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


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h	2016-05-27 23:58:28 UTC (rev 201474)
@@ -172,7 +172,7 @@
     void paintCurrentFrameInContext(GraphicsContext&, const FloatRect&) override;
     PlatformLayer* platformLayer() const override;
 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
-    void setVideoFullscreenLayer(PlatformLayer*) override;
+    void setVideoFullscreenLayer(PlatformLayer*, std::function<void()> completionHandler) override;
     void setVideoFullscreenFrame(FloatRect) override;
     void setVideoFullscreenGravity(MediaPlayer::VideoGravity) override;
     void setVideoFullscreenMode(MediaPlayer::VideoFullscreenMode) override;
@@ -329,6 +329,7 @@
     RetainPtr<AVPlayer> m_avPlayer;
     RetainPtr<AVPlayerItem> m_avPlayerItem;
     RetainPtr<AVPlayerLayer> m_videoLayer;
+    RetainPtr<AVPlayerLayer> m_secondaryVideoLayer;
 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
     std::unique_ptr<VideoFullscreenLayerManager> m_videoFullscreenLayerManager;
     MediaPlayer::VideoGravity m_videoFullscreenGravity;

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


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm	2016-05-27 23:58:28 UTC (rev 201474)
@@ -730,17 +730,24 @@
     m_videoLayer = adoptNS([allocAVPlayerLayerInstance() init]);
     [m_videoLayer setPlayer:m_avPlayer.get()];
     [m_videoLayer setBackgroundColor:cachedCGColor(Color::black)];
+
+    m_secondaryVideoLayer = adoptNS([allocAVPlayerLayerInstance() init]);
+    [m_secondaryVideoLayer setPlayer:m_avPlayer.get()];
+    [m_secondaryVideoLayer setBackgroundColor:cachedCGColor(Color::black)];
+
 #ifndef NDEBUG
     [m_videoLayer setName:@"MediaPlayerPrivate AVPlayerLayer"];
+    [m_secondaryVideoLayer setName:@"MediaPlayerPrivate AVPlayerLayer secondary"];
 #endif
     [m_videoLayer addObserver:m_objcObserver.get() forKeyPath:@"readyForDisplay" options:NSKeyValueObservingOptionNew context:(void *)MediaPlayerAVFoundationObservationContextAVPlayerLayer];
     updateVideoLayerGravity();
     [m_videoLayer setContentsScale:player()->client().mediaPlayerContentsScale()];
+    [m_secondaryVideoLayer setContentsScale:player()->client().mediaPlayerContentsScale()];
     IntSize defaultSize = snappedIntRect(player()->client().mediaPlayerContentBoxRect()).size();
     LOG(Media, "MediaPlayerPrivateAVFoundationObjC::createVideoLayer(%p) - returning %p", this, m_videoLayer.get());
 
 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
-    m_videoFullscreenLayerManager->setVideoLayer(m_videoLayer.get(), defaultSize);
+    m_videoFullscreenLayerManager->setVideoLayers(m_videoLayer.get(), m_secondaryVideoLayer.get(), defaultSize);
 
 #if PLATFORM(IOS)
     if ([m_videoLayer respondsToSelector:@selector(setPIPModeEnabled:)])
@@ -748,6 +755,7 @@
 #endif
 #else
     [m_videoLayer setFrame:CGRectMake(0, 0, defaultSize.width(), defaultSize.height())];
+    [m_secondaryVideoLayer setFrame:CGRectMake(0, 0, defaultSize.width(), defaultSize.height())];
 #endif
 }
 
@@ -758,14 +766,16 @@
 
     LOG(Media, "MediaPlayerPrivateAVFoundationObjC::destroyVideoLayer(%p) - destroying %p", this, m_videoLayer.get());
 
-    [m_videoLayer.get() removeObserver:m_objcObserver.get() forKeyPath:@"readyForDisplay"];
-    [m_videoLayer.get() setPlayer:nil];
+    [m_videoLayer removeObserver:m_objcObserver.get() forKeyPath:@"readyForDisplay"];
+    [m_videoLayer setPlayer:nil];
+    [m_secondaryVideoLayer setPlayer:nil];
 
 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
     m_videoFullscreenLayerManager->didDestroyVideoLayer();
 #endif
 
     m_videoLayer = nil;
+    m_secondaryVideoLayer = nil;
 }
 
 MediaTime MediaPlayerPrivateAVFoundationObjC::getStartDate() const
@@ -1183,12 +1193,14 @@
 }
 
 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
-void MediaPlayerPrivateAVFoundationObjC::setVideoFullscreenLayer(PlatformLayer* videoFullscreenLayer)
+void MediaPlayerPrivateAVFoundationObjC::setVideoFullscreenLayer(PlatformLayer* videoFullscreenLayer, std::function<void()> completionHandler)
 {
-    if (m_videoFullscreenLayerManager->videoFullscreenLayer() == videoFullscreenLayer)
+    if (m_videoFullscreenLayerManager->videoFullscreenLayer() == videoFullscreenLayer) {
+        completionHandler();
         return;
+    }
 
-    m_videoFullscreenLayerManager->setVideoFullscreenLayer(videoFullscreenLayer);
+    m_videoFullscreenLayerManager->setVideoFullscreenLayer(videoFullscreenLayer, completionHandler);
 
     if (m_videoFullscreenLayerManager->videoFullscreenLayer() && m_textTrackRepresentationLayer) {
         syncTextTrackBounds();
@@ -1872,6 +1884,7 @@
     [CATransaction setDisableActions:YES];    
     NSString* gravity = shouldMaintainAspectRatio() ? AVLayerVideoGravityResizeAspect : AVLayerVideoGravityResize;
     [m_videoLayer.get() setVideoGravity:gravity];
+    [m_secondaryVideoLayer.get() setVideoGravity:gravity];
     [CATransaction commit];
 }
 

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


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h	2016-05-27 23:58:28 UTC (rev 201474)
@@ -87,7 +87,7 @@
     void characteristicsChanged();
 
 #if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
-    void setVideoFullscreenLayer(PlatformLayer*) override;
+    void setVideoFullscreenLayer(PlatformLayer*, std::function<void()> completionHandler) override;
     void setVideoFullscreenFrame(FloatRect) override;
 #endif
 

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


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm	2016-05-27 23:58:28 UTC (rev 201474)
@@ -770,7 +770,7 @@
     m_player->firstVideoFrameAvailable();
 
 #if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
-    m_videoFullscreenLayerManager->setVideoLayer(m_sampleBufferDisplayLayer.get(), snappedIntRect(m_player->client().mediaPlayerContentBoxRect()).size());
+    m_videoFullscreenLayerManager->setVideoLayers(m_sampleBufferDisplayLayer.get(), nil, snappedIntRect(m_player->client().mediaPlayerContentBoxRect()).size());
 #endif
 }
 
@@ -828,9 +828,9 @@
 }
 
 #if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
-void MediaPlayerPrivateMediaSourceAVFObjC::setVideoFullscreenLayer(PlatformLayer *videoFullscreenLayer)
+void MediaPlayerPrivateMediaSourceAVFObjC::setVideoFullscreenLayer(PlatformLayer *videoFullscreenLayer, std::function<void()> completionHandler)
 {
-    m_videoFullscreenLayerManager->setVideoFullscreenLayer(videoFullscreenLayer);
+    m_videoFullscreenLayerManager->setVideoFullscreenLayer(videoFullscreenLayer, completionHandler);
 }
 
 void MediaPlayerPrivateMediaSourceAVFObjC::setVideoFullscreenFrame(FloatRect frame)

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h (201473 => 201474)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h	2016-05-27 23:58:28 UTC (rev 201474)
@@ -160,7 +160,7 @@
     void didRemoveTrack(MediaStreamTrackPrivate&) override;
 
 #if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
-    void setVideoFullscreenLayer(PlatformLayer*) override;
+    void setVideoFullscreenLayer(PlatformLayer*, std::function<void()> completionHandler) override;
     void setVideoFullscreenFrame(FloatRect) override;
 #endif
 

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm (201473 => 201474)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm	2016-05-27 23:58:28 UTC (rev 201474)
@@ -404,7 +404,7 @@
         m_videoBackgroundLayer.get().name = @"MediaPlayerPrivateMediaStreamAVFObjC preview background layer";
 
 #if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
-        m_videoFullscreenLayerManager->setVideoLayer(m_videoBackgroundLayer.get(), snappedIntRect(m_player->client().mediaPlayerContentBoxRect()).size());
+        m_videoFullscreenLayerManager->setVideoLayers(m_videoBackgroundLayer.get(), nil, snappedIntRect(m_player->client().mediaPlayerContentBoxRect()).size());
 #endif
     }
 
@@ -474,9 +474,9 @@
 }
 
 #if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
-void MediaPlayerPrivateMediaStreamAVFObjC::setVideoFullscreenLayer(PlatformLayer *videoFullscreenLayer)
+void MediaPlayerPrivateMediaStreamAVFObjC::setVideoFullscreenLayer(PlatformLayer *videoFullscreenLayer, std::function<void()> completionHandler)
 {
-    m_videoFullscreenLayerManager->setVideoFullscreenLayer(videoFullscreenLayer);
+    m_videoFullscreenLayerManager->setVideoFullscreenLayer(videoFullscreenLayer, completionHandler);
 }
 
 void MediaPlayerPrivateMediaStreamAVFObjC::setVideoFullscreenFrame(FloatRect frame)

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/VideoFullscreenLayerManager.h (201473 => 201474)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/VideoFullscreenLayerManager.h	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/VideoFullscreenLayerManager.h	2016-05-27 23:58:28 UTC (rev 201474)
@@ -31,6 +31,7 @@
 #include "FloatRect.h"
 #include "IntSize.h"
 #include "PlatformLayer.h"
+#include <functional>
 #include <wtf/RetainPtr.h>
 
 namespace WebCore {
@@ -43,8 +44,8 @@
     PlatformLayer *videoInlineLayer() const { return m_videoInlineLayer.get(); }
     PlatformLayer *videoFullscreenLayer() const { return m_videoFullscreenLayer.get(); }
     FloatRect videoFullscreenFrame() const { return m_videoFullscreenFrame; }
-    void setVideoLayer(PlatformLayer *, IntSize contentSize);
-    void setVideoFullscreenLayer(PlatformLayer *);
+    void setVideoLayers(PlatformLayer *, PlatformLayer *, IntSize contentSize);
+    void setVideoFullscreenLayer(PlatformLayer *, std::function<void()> completionHandler);
     void setVideoFullscreenFrame(FloatRect);
     void didDestroyVideoLayer();
 
@@ -54,6 +55,7 @@
     RetainPtr<PlatformLayer> m_videoInlineLayer;
     RetainPtr<PlatformLayer> m_videoFullscreenLayer;
     RetainPtr<PlatformLayer> m_videoLayer;
+    RetainPtr<PlatformLayer> m_secondaryVideoLayer;
     FloatRect m_videoFullscreenFrame;
 };
 

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/VideoFullscreenLayerManager.mm (201473 => 201474)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/VideoFullscreenLayerManager.mm	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/VideoFullscreenLayerManager.mm	2016-05-27 23:58:28 UTC (rev 201474)
@@ -66,55 +66,97 @@
 {
 }
 
-void VideoFullscreenLayerManager::setVideoLayer(PlatformLayer *videoLayer, IntSize contentSize)
+void VideoFullscreenLayerManager::setVideoLayers(PlatformLayer *videoLayer, PlatformLayer *secondaryVideoLayer, IntSize contentSize)
 {
     m_videoLayer = videoLayer;
+    m_secondaryVideoLayer = secondaryVideoLayer;
 
     [m_videoLayer web_disableAllActions];
+    [m_secondaryVideoLayer web_disableAllActions];
     m_videoInlineLayer = adoptNS([[WebVideoContainerLayer alloc] init]);
 #ifndef NDEBUG
     [m_videoInlineLayer setName:@"WebVideoContainerLayer"];
 #endif
     [m_videoInlineLayer setFrame:CGRectMake(0, 0, contentSize.width(), contentSize.height())];
     if (m_videoFullscreenLayer) {
-        [m_videoLayer setFrame:CGRectMake(0, 0, m_videoFullscreenFrame.width(), m_videoFullscreenFrame.height())];
-        [m_videoFullscreenLayer insertSublayer:m_videoLayer.get() atIndex:0];
+        [m_videoLayer removeFromSuperlayer];
+        PlatformLayer *activeLayer = secondaryVideoLayer ? secondaryVideoLayer : videoLayer;
+        [activeLayer setFrame:CGRectMake(0, 0, m_videoFullscreenFrame.width(), m_videoFullscreenFrame.height())];
+        [m_videoFullscreenLayer insertSublayer:activeLayer atIndex:0];
     } else {
         [m_videoInlineLayer insertSublayer:m_videoLayer.get() atIndex:0];
         [m_videoLayer setFrame:m_videoInlineLayer.get().bounds];
+        [m_secondaryVideoLayer removeFromSuperlayer];
     }
 }
 
-void VideoFullscreenLayerManager::setVideoFullscreenLayer(PlatformLayer *videoFullscreenLayer)
+void VideoFullscreenLayerManager::setVideoFullscreenLayer(PlatformLayer *videoFullscreenLayer, std::function<void()> completionHandler)
 {
-    if (m_videoFullscreenLayer == videoFullscreenLayer)
+    if (m_videoFullscreenLayer == videoFullscreenLayer) {
+        completionHandler();
         return;
+    }
 
     m_videoFullscreenLayer = videoFullscreenLayer;
 
     [CATransaction begin];
     [CATransaction setDisableActions:YES];
 
-    CAContext *oldContext = [m_videoLayer context];
-    CAContext *newContext = nil;
+    if (m_secondaryVideoLayer && m_videoLayer) {
+        if (m_videoFullscreenLayer) {
+            [m_videoFullscreenLayer insertSublayer:m_secondaryVideoLayer.get() atIndex:0];
+            [m_secondaryVideoLayer setFrame:CGRectMake(0, 0, m_videoFullscreenFrame.width(), m_videoFullscreenFrame.height())];
+        } else if (m_videoInlineLayer) {
+            [m_videoLayer setFrame:[m_videoInlineLayer bounds]];
+            [m_videoInlineLayer insertSublayer:m_videoLayer.get() atIndex:0];
+        }
 
-    if (m_videoFullscreenLayer && m_videoLayer) {
-        [m_videoFullscreenLayer insertSublayer:m_videoLayer.get() atIndex:0];
-        [m_videoLayer setFrame:CGRectMake(0, 0, m_videoFullscreenFrame.width(), m_videoFullscreenFrame.height())];
-        newContext = [m_videoFullscreenLayer context];
-    } else if (m_videoInlineLayer && m_videoLayer) {
-        [m_videoLayer setFrame:[m_videoInlineLayer bounds]];
-        [m_videoLayer removeFromSuperlayer];
-        [m_videoInlineLayer insertSublayer:m_videoLayer.get() atIndex:0];
-        newContext = [m_videoInlineLayer context];
-    } else if (m_videoLayer)
-        [m_videoLayer removeFromSuperlayer];
+        RetainPtr<PlatformLayer> fullscreenLayer = m_videoFullscreenLayer;
+        RetainPtr<PlatformLayer> videoLayer = m_videoLayer;
+        RetainPtr<PlatformLayer> secondaryVideoLayer = m_secondaryVideoLayer;
 
-    if (oldContext && newContext && oldContext != newContext) {
-        mach_port_t fencePort = [oldContext createFencePort];
-        [newContext setFencePort:fencePort];
-        mach_port_deallocate(mach_task_self(), fencePort);
+        [CATransaction setCompletionBlock:[completionHandler, fullscreenLayer, videoLayer, secondaryVideoLayer] {
+            [CATransaction begin];
+            [CATransaction setDisableActions:YES];
+            
+            if (fullscreenLayer)
+                [videoLayer removeFromSuperlayer];
+            else
+                [secondaryVideoLayer removeFromSuperlayer];
+
+            [CATransaction setCompletionBlock:[completionHandler] {
+                completionHandler();
+            }];
+            [CATransaction commit];
+        }];
+    } else if (m_videoLayer) {
+        if (m_videoFullscreenLayer) {
+            [m_videoFullscreenLayer insertSublayer:m_videoLayer.get() atIndex:0];
+            [m_videoLayer setFrame:CGRectMake(0, 0, m_videoFullscreenFrame.width(), m_videoFullscreenFrame.height())];
+        } else if (m_videoInlineLayer) {
+            [m_videoLayer setFrame:[m_videoInlineLayer bounds]];
+            [m_videoLayer removeFromSuperlayer];
+            [m_videoInlineLayer insertSublayer:m_videoLayer.get() atIndex:0];
+        } else
+            [m_videoLayer removeFromSuperlayer];
+
+        CAContext *oldContext = [m_videoFullscreenLayer context];
+        CAContext *newContext = [m_videoInlineLayer context];
+        if (oldContext && newContext && oldContext != newContext) {
+            mach_port_t fencePort = [oldContext createFencePort];
+            [newContext setFencePort:fencePort];
+            mach_port_deallocate(mach_task_self(), fencePort);
+        }
+
+        [CATransaction setCompletionBlock:[completionHandler] {
+            completionHandler();
+        }];
+    } else {
+        [CATransaction setCompletionBlock:[completionHandler] {
+            completionHandler();
+        }];
     }
+
     [CATransaction commit];
 }
 
@@ -124,17 +166,18 @@
     if (!m_videoFullscreenLayer)
         return;
 
-    if (m_videoLayer)
-        [m_videoLayer setFrame:CGRectMake(0, 0, videoFullscreenFrame.width(), videoFullscreenFrame.height())];
+    PlatformLayer *activeLayer = m_secondaryVideoLayer.get() ? m_secondaryVideoLayer.get() : m_videoLayer.get();
+    [activeLayer setFrame:CGRectMake(0, 0, videoFullscreenFrame.width(), videoFullscreenFrame.height())];
 }
 
 void VideoFullscreenLayerManager::didDestroyVideoLayer()
 {
-    if (m_videoFullscreenLayer)
-        [m_videoLayer removeFromSuperlayer];
+    [m_videoLayer removeFromSuperlayer];
+    [m_secondaryVideoLayer removeFromSuperlayer];
 
     m_videoInlineLayer = nil;
     m_videoLayer = nil;
+    m_secondaryVideoLayer = nil;
 }
 
 }

Modified: trunk/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm (201473 => 201474)


--- trunk/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm	2016-05-27 23:58:28 UTC (rev 201474)
@@ -247,9 +247,10 @@
     RetainPtr<CALayer> videoFullscreenLayer = [m_videoFullscreenView layer];
     WebThreadRun([protectedThis, this, videoFullscreenLayer] {
         [videoFullscreenLayer setBackgroundColor:cachedCGColor(WebCore::Color::transparent)];
-        m_model->setVideoFullscreenLayer(videoFullscreenLayer.get());
-        dispatch_async(dispatch_get_main_queue(), [protectedThis, this] {
-            m_interface->enterFullscreen();
+        m_model->setVideoFullscreenLayer(videoFullscreenLayer.get(), [protectedThis, this] {
+            dispatch_async(dispatch_get_main_queue(), [protectedThis, this] {
+                m_interface->enterFullscreen();
+            });
         });
     });
 }
@@ -259,9 +260,10 @@
     ASSERT(isUIThread());
     RefPtr<WebVideoFullscreenControllerContext> protectedThis(this);
     WebThreadRun([protectedThis, this] {
-        m_model->setVideoFullscreenLayer(nil);
-        dispatch_async(dispatch_get_main_queue(), [protectedThis, this] {
-            m_interface->cleanupFullscreen();
+        m_model->setVideoFullscreenLayer(nil, [protectedThis, this] {
+            dispatch_async(dispatch_get_main_queue(), [protectedThis, this] {
+                m_interface->cleanupFullscreen();
+            });
         });
     });
 }

Modified: trunk/Source/WebKit2/ChangeLog (201473 => 201474)


--- trunk/Source/WebKit2/ChangeLog	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebKit2/ChangeLog	2016-05-27 23:58:28 UTC (rev 201474)
@@ -1,3 +1,19 @@
+2016-05-27  Jeremy Jones  <jere...@apple.com>
+
+        Decrease flicker when changing video presentation mode.
+        https://bugs.webkit.org/show_bug.cgi?id=158148
+        rdar://problem/24476949
+
+        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):
+
 2016-05-27  Chris Dumez  <cdu...@apple.com>
 
         WorkQueue::dispatch() / RunLoop::dispatch() should not copy captured lambda variables

Modified: trunk/Source/WebKit2/WebProcess/cocoa/WebVideoFullscreenManager.mm (201473 => 201474)


--- trunk/Source/WebKit2/WebProcess/cocoa/WebVideoFullscreenManager.mm	2016-05-27 23:42:08 UTC (rev 201473)
+++ trunk/Source/WebKit2/WebProcess/cocoa/WebVideoFullscreenManager.mm	2016-05-27 23:58:28 UTC (rev 201474)
@@ -369,14 +369,16 @@
     std::tie(model, interface) = ensureModelAndInterface(contextId);
 
     interface->layerHostingContext()->setRootLayer(videoLayer);
-    model->setVideoFullscreenLayer(videoLayer);
 
-    [CATransaction commit];
-
     RefPtr<WebVideoFullscreenManager> strongThis(this);
-    dispatch_async(dispatch_get_main_queue(), [strongThis, this, contextId] {
-        m_page->send(Messages::WebVideoFullscreenManagerProxy::EnterFullscreen(contextId), m_page->pageID());
+    
+    model->setVideoFullscreenLayer(videoLayer, [strongThis, this, contextId] {
+        dispatch_async(dispatch_get_main_queue(), [strongThis, this, contextId] {
+            m_page->send(Messages::WebVideoFullscreenManagerProxy::EnterFullscreen(contextId), m_page->pageID());
+        });
     });
+    
+    [CATransaction commit];
 }
     
 void WebVideoFullscreenManager::didEnterFullscreen(uint64_t contextId)
@@ -407,17 +409,21 @@
     RefPtr<WebVideoFullscreenModelVideoElement> model;
     RefPtr<WebVideoFullscreenInterfaceContext> interface;
     std::tie(model, interface) = ensureModelAndInterface(contextId);
-
-    model->setVideoFullscreenLayer(nil);
-
     RefPtr<WebVideoFullscreenManager> strongThis(this);
-    dispatch_async(dispatch_get_main_queue(), [strongThis, contextId, interface] {
-        if (interface->layerHostingContext()) {
-            interface->layerHostingContext()->setRootLayer(nullptr);
-            interface->setLayerHostingContext(nullptr);
-        }
-        if (strongThis->m_page)
-            strongThis->m_page->send(Messages::WebVideoFullscreenManagerProxy::CleanupFullscreen(contextId), strongThis->m_page->pageID());
+    
+    model->waitForPreparedForInlineThen([strongThis, this, contextId, interface, model] {
+        dispatch_async(dispatch_get_main_queue(), [strongThis, this, contextId, interface, model] {
+            model->setVideoFullscreenLayer(nil, [strongThis, this, contextId, interface] {
+                dispatch_async(dispatch_get_main_queue(), [strongThis, this, contextId, interface] {
+                    if (interface->layerHostingContext()) {
+                        interface->layerHostingContext()->setRootLayer(nullptr);
+                        interface->setLayerHostingContext(nullptr);
+                    }
+                    if (strongThis->m_page)
+                        strongThis->m_page->send(Messages::WebVideoFullscreenManagerProxy::CleanupFullscreen(contextId), strongThis->m_page->pageID());
+                });
+            });
+        });
     });
 }
     
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to