Title: [187092] branches/safari-601.1-branch/Source

Diff

Modified: branches/safari-601.1-branch/Source/WebCore/ChangeLog (187091 => 187092)


--- branches/safari-601.1-branch/Source/WebCore/ChangeLog	2015-07-21 05:27:45 UTC (rev 187091)
+++ branches/safari-601.1-branch/Source/WebCore/ChangeLog	2015-07-21 05:27:51 UTC (rev 187092)
@@ -1,5 +1,123 @@
 2015-07-20  Matthew Hanson  <[email protected]>
 
+        Merge r187044. rdar://problem/21661808
+
+    2015-07-20  Jeremy Jones  <[email protected]>
+
+            Adopt AVPlayerLayerView
+            https://bugs.webkit.org/show_bug.cgi?id=146862
+
+            Reviewed by Jer Noble.
+
+            The CALayerHost is replaced with WebLayerHostView to be compatible with UIView animations.
+            Some animation is improved in the conversion.
+
+            WebAVPlayerLayerView and WebAVPictureInPicturePlayerLayerView derive from AVKit and UIKit respectively.
+            Because these frameworks are loaded at runtime, these classes must be generate using objc/runtime.h to
+            register them from c functions at runtime. The most important part of these UIViews is that their
+            backing layer is a WebAVPlayerLayer.
+
+            WebCALayerHostWrapper and WebAVVideoLayer are combined into WebAVPlayerLayer to simplify the hierarchy.
+            WebAVPlayerLayer is a stand-in for an AVPlayerLayer.
+
+            * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
+            (WebCore::MediaPlayerPrivateAVFoundationObjC::setVideoFullscreenLayer): -removeFromSuperlayer is redundant.
+            (WebCore::MediaPlayerPrivateAVFoundationObjC::setVideoFullscreenGravity): syncTextTrackBounds on change.
+            (WebCore::MediaPlayerPrivateAVFoundationObjC::setVideoFullscreenFrame):
+            We never want animation here, since all animation will happen in UIViews.
+            This is just for going into the final size after a transform based animation.
+
+            * platform/ios/WebVideoFullscreenControllerAVKit.mm:
+            (WebVideoFullscreenControllerContext::didSetupFullscreen): layer -> view
+            (WebVideoFullscreenControllerContext::didCleanupFullscreen): layer -> view
+            (WebVideoFullscreenControllerContext::setUpFullscreen): layer -> view
+
+            (WebVideoFullscreenControllerContext::setVideoLayerFrame): layer -> view
+            Use fence port to synchronize between the UIThread and the WebThread,
+            the same way WebKit2 uses a fence port to synchronize between processes.
+
+            (WebVideoFullscreenControllerContext::setVideoLayerGravity):
+            No longer necessary to cache videoGravity at this level.
+
+            * platform/ios/WebVideoFullscreenInterfaceAVKit.h:
+            * platform/ios/WebVideoFullscreenInterfaceAVKit.mm:
+
+            (-[WebAVPlayerLayer init]):
+            (-[WebAVPlayerLayer dealloc]):
+            (-[WebAVPlayerLayer playerController]):
+            (-[WebAVPlayerLayer setBounds:]):
+            (-[WebAVPlayerLayer resolveBounds]):
+            (-[WebAVPlayerLayer setVideoGravity:]):
+            (-[WebAVPlayerLayer videoGravity]):
+            (-[WebAVPlayerLayer videoRect]):
+            (+[WebAVPlayerLayer keyPathsForValuesAffectingVideoRect]):
+            Added class WebAVPlayerLayer, replacing WebAVVideoLayer and WebCALayerHostWrapper.
+
+            (WebAVPictureInPicturePlayerLayerView_layerClass):
+            (getWebAVPictureInPicturePlayerLayerViewClass):
+            Added runtime class WebAVPictureInPicturePlayerLayerView
+
+            (WebAVPlayerLayerView_layerClass):
+            (WebAVPlayerLayerView_playerController):
+            (WebAVPlayerLayerView_setPlayerController):
+            (WebAVPlayerLayerView_videoView):
+            (WebAVPlayerLayerView_setVideoView):
+            (WebAVPlayerLayerView_startRoutingVideoToPictureInPicturePlayerLayerView):
+            (WebAVPlayerLayerView_stopRoutingVideoToPictureInPicturePlayerLayerView):
+            (WebAVPlayerLayerView_pictureInPicturePlayerLayerView):
+            (getWebAVPlayerLayerViewClass):
+            Added runtime class WebAVPlayerLayerView
+
+            (WebVideoFullscreenInterfaceAVKit::setVideoDimensions):
+            Dimensions are also stored in WebAVPlayerLayer so it can make decisions about
+            animating the video layer.
+
+            (WebVideoFullscreenInterfaceAVKit::setExternalPlayback):
+            (WebVideoFullscreenInterfaceAVKit::enterFullscreen):
+            (WebVideoFullscreenInterfaceAVKit::didStopPictureInPicture):
+            (WebVideoFullscreenInterfaceAVKit::cleanupFullscreen):
+            Straightforward layer to view conversion.
+
+            (WebVideoFullscreenInterfaceAVKit::preparedToReturnToInline):
+            Set view frame using the view hierarchy instead of assuming it is directly in a window.
+
+            (WebVideoFullscreenInterfaceAVKit::exitFullscreen):
+            Set view frame using the view hierarchy instead of assuming it is directly in a window.
+            dispatch_async before calling didExitFullscreen() to allows CATransactions to complete.
+
+            (WebVideoFullscreenInterfaceAVKit::setupFullscreen):
+            Set view frame using the view hierarchy instead of assuming it is directly in a window.
+            dispatch_async before calling didSetupFullscreen() to allows CATransactions to complete.
+
+            (-[WebCALayerHostWrapper dealloc]): Deleted.
+            (-[WebCALayerHostWrapper setVideoSublayer:]): Deleted.
+            (-[WebCALayerHostWrapper videoSublayer]): Deleted.
+            (-[WebCALayerHostWrapper setBounds:]): Deleted.
+            (-[WebCALayerHostWrapper resolveBounds]): Deleted.
+            Class WebCALayerHostWrapper deleted. Functionality rolled into WebAVPlayerLayer.
+
+            (+[WebAVVideoLayer videoLayer]): Deleted.
+            (-[WebAVVideoLayer init]): Deleted.
+            (-[WebAVVideoLayer setPlayerViewController:]): Deleted.
+            (-[WebAVVideoLayer setVideoSublayer:]): Deleted.
+            (-[WebAVVideoLayer setBounds:]): Deleted.
+            (-[WebAVVideoLayer setVideoLayerGravity:]): Deleted.
+            (-[WebAVVideoLayer videoLayerGravity]): Deleted.
+            (-[WebAVVideoLayer enterPIPModeRedirectingVideoToLayer:]): Deleted.
+            (-[WebAVVideoLayer leavePIPMode]): Deleted.
+            Class WebAVVideoLayer deleted. Functionality rolled into WebAVPlayerLayer.
+
+            * platform/ios/WebVideoFullscreenModel.h:
+            * platform/ios/WebVideoFullscreenModelVideoElement.h:
+            * platform/ios/WebVideoFullscreenModelVideoElement.mm:
+            No need to store frame and gravity in the model. It is stored in the UI where it is used.
+
+            (WebVideoFullscreenModelVideoElement::videoLayerFrame): Deleted.
+            (WebVideoFullscreenModelVideoElement::videoLayerGravity): Deleted.
+            * platform/spi/cocoa/AVKitSPI.h: Add AVPlayerLayerView.
+
+2015-07-20  Matthew Hanson  <[email protected]>
+
         Merge r187039. rdar://problem/21474317
 
     2015-07-20  Tim Horton  <[email protected]>

Modified: branches/safari-601.1-branch/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm (187091 => 187092)


--- branches/safari-601.1-branch/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm	2015-07-21 05:27:45 UTC (rev 187091)
+++ branches/safari-601.1-branch/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm	2015-07-21 05:27:51 UTC (rev 187092)
@@ -1124,9 +1124,8 @@
     CAContext *newContext = nil;
     
     if (m_videoFullscreenLayer && m_videoLayer) {
-        [m_videoLayer setFrame:CGRectMake(0, 0, m_videoFullscreenFrame.width(), m_videoFullscreenFrame.height())];
-        [m_videoLayer removeFromSuperlayer];
         [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]];
@@ -1158,11 +1157,7 @@
         return;
 
     if (m_videoLayer) {
-        [m_videoLayer setStyle:nil]; // This enables actions, i.e. implicit animations.
-        [CATransaction begin];
         [m_videoLayer setFrame:CGRectMake(0, 0, frame.width(), frame.height())];
-        [CATransaction commit];
-        [m_videoLayer web_disableAllActions];
     }
     syncTextTrackBounds();
 }
@@ -1182,8 +1177,12 @@
         videoGravity = AVLayerVideoGravityResizeAspectFill;
     else
         ASSERT_NOT_REACHED();
+    
+    if ([m_videoLayer videoGravity] == videoGravity)
+        return;
 
     [m_videoLayer setVideoGravity:videoGravity];
+    syncTextTrackBounds();
 }
 
 void MediaPlayerPrivateAVFoundationObjC::setVideoFullscreenMode(MediaPlayer::VideoFullscreenMode mode)

Modified: branches/safari-601.1-branch/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm (187091 => 187092)


--- branches/safari-601.1-branch/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm	2015-07-21 05:27:45 UTC (rev 187091)
+++ branches/safari-601.1-branch/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm	2015-07-21 05:27:51 UTC (rev 187092)
@@ -30,6 +30,8 @@
 #import "WebVideoFullscreenControllerAVKit.h"
 
 #import "Logging.h"
+#import "QuartzCoreSPI.h"
+#import "SoftLinking.h"
 #import "TimeRanges.h"
 #import "WebVideoFullscreenInterfaceAVKit.h"
 #import "WebVideoFullscreenModelVideoElement.h"
@@ -37,6 +39,9 @@
 #import <WebCore/HTMLVideoElement.h>
 #import <WebCore/WebCoreThreadRun.h>
 
+SOFT_LINK_FRAMEWORK(UIKit)
+SOFT_LINK_CLASS(UIKit, UIView)
+
 using namespace WebCore;
 
 #if __IPHONE_OS_VERSION_MIN_REQUIRED <= 80200 || !HAVE(AVKIT)
@@ -129,9 +134,7 @@
     virtual void endScanning() override;
     virtual void requestExitFullscreen() override;
     virtual void setVideoLayerFrame(FloatRect) override;
-    virtual FloatRect videoLayerFrame() const override { return m_frame; }
     virtual void setVideoLayerGravity(WebVideoFullscreenModel::VideoGravity) override;
-    virtual VideoGravity videoLayerGravity() const override { return m_gravity; }
     virtual void selectAudioMediaOption(uint64_t index) override;
     virtual void selectLegibleMediaOption(uint64_t index) override;
     virtual void fullscreenModeChanged(HTMLMediaElementEnums::VideoFullscreenMode) override;
@@ -139,10 +142,8 @@
     RefPtr<WebVideoFullscreenInterfaceAVKit> m_interface;
     RefPtr<WebVideoFullscreenModelVideoElement> m_model;
     RefPtr<HTMLVideoElement> m_videoElement;
-    RetainPtr<PlatformLayer> m_videoFullscreenLayer;
+    RetainPtr<UIView> m_videoFullscreenView;
     RetainPtr<WebVideoFullscreenController> m_controller;
-    FloatRect m_frame;
-    VideoGravity m_gravity;
 };
 
 #pragma mark WebVideoFullscreenChangeObserver
@@ -151,8 +152,9 @@
 {
     ASSERT(isUIThread());
     RefPtr<WebVideoFullscreenControllerContext> strongThis(this);
-    WebThreadRun([strongThis, this] {
-        m_model->setVideoFullscreenLayer(m_videoFullscreenLayer.get());
+    RetainPtr<CALayer> videoFullscreenLayer = [m_videoFullscreenView layer];
+    WebThreadRun([strongThis, this, videoFullscreenLayer] {
+        m_model->setVideoFullscreenLayer(videoFullscreenLayer.get());
         dispatch_async(dispatch_get_main_queue(), [strongThis, this] {
             m_interface->enterFullscreen();
         });
@@ -177,6 +179,7 @@
     m_interface->setWebVideoFullscreenModel(nullptr);
     m_interface->setWebVideoFullscreenChangeObserver(nullptr);
     m_interface = nullptr;
+    m_videoFullscreenView = nil;
     
     RefPtr<WebVideoFullscreenControllerContext> strongThis(this);
     WebThreadRun([strongThis, this] {
@@ -185,7 +188,6 @@
         m_model->setVideoElement(nullptr);
         m_model = nullptr;
         m_videoElement = nullptr;
-        m_videoFullscreenLayer = nil;
         
         [m_controller didFinishFullscreen:this];
     });
@@ -450,18 +452,25 @@
 void WebVideoFullscreenControllerContext::setVideoLayerFrame(FloatRect frame)
 {
     ASSERT(isUIThread());
-    m_frame = frame;
     RefPtr<WebVideoFullscreenControllerContext> strongThis(this);
-    WebThreadRun([strongThis, this, frame] {
+    RetainPtr<CALayer> videoFullscreenLayer = [m_videoFullscreenView layer];
+
+    mach_port_name_t fencePort = [[videoFullscreenLayer context] createFencePort];
+    
+    WebThreadRun([strongThis, this, frame, fencePort, videoFullscreenLayer] {
+        [CATransaction begin];
+        [CATransaction setAnimationDuration:0];
         if (m_model)
             m_model->setVideoLayerFrame(frame);
+        [[videoFullscreenLayer context] setFencePort:fencePort];
+        mach_port_deallocate(mach_task_self(), fencePort);
+        [CATransaction commit];
     });
 }
 
 void WebVideoFullscreenControllerContext::setVideoLayerGravity(WebVideoFullscreenModel::VideoGravity videoGravity)
 {
     ASSERT(isUIThread());
-    m_gravity = videoGravity;
     RefPtr<WebVideoFullscreenControllerContext> strongThis(this);
     WebThreadRun([strongThis, this, videoGravity] {
         if (m_model)
@@ -510,19 +519,19 @@
     m_interface = WebVideoFullscreenInterfaceAVKit::create();
     m_interface->setWebVideoFullscreenChangeObserver(this);
     m_interface->setWebVideoFullscreenModel(this);
+    m_videoFullscreenView = adoptNS([[getUIViewClass() alloc] init]);
     
     RefPtr<WebVideoFullscreenControllerContext> strongThis(this);
     WebThreadRun([strongThis, this, viewRef, mode] {
         m_model = WebVideoFullscreenModelVideoElement::create();
         m_model->setWebVideoFullscreenInterface(this);
         m_model->setVideoElement(m_videoElement.get());
-        m_videoFullscreenLayer = [CALayer layer];
         
         bool allowsPictureInPicture = m_videoElement->mediaSession().allowsPictureInPicture(*m_videoElement.get());
         IntRect videoElementClientRect = m_videoElement->clientRect();
         
         dispatch_async(dispatch_get_main_queue(), [strongThis, this, videoElementClientRect, viewRef, mode, allowsPictureInPicture] {
-            m_interface->setupFullscreen(*m_videoFullscreenLayer.get(), videoElementClientRect, viewRef.get(), mode, allowsPictureInPicture);
+            m_interface->setupFullscreen(*m_videoFullscreenView.get(), videoElementClientRect, viewRef.get(), mode, allowsPictureInPicture);
         });
     });
 }

Modified: branches/safari-601.1-branch/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.h (187091 => 187092)


--- branches/safari-601.1-branch/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.h	2015-07-21 05:27:45 UTC (rev 187091)
+++ branches/safari-601.1-branch/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.h	2015-07-21 05:27:51 UTC (rev 187092)
@@ -45,8 +45,8 @@
 OBJC_CLASS UIWindow;
 OBJC_CLASS UIView;
 OBJC_CLASS CALayer;
-OBJC_CLASS WebAVVideoLayer;
-OBJC_CLASS WebCALayerHostWrapper;
+OBJC_CLASS WebAVPlayerLayerView;
+OBJC_CLASS WebAVPlayerLayer;
 
 namespace WTF {
 class String;
@@ -91,7 +91,7 @@
     WEBCORE_EXPORT virtual void setLegibleMediaSelectionOptions(const Vector<WTF::String>& options, uint64_t selectedIndex) override;
     WEBCORE_EXPORT virtual void setExternalPlayback(bool enabled, ExternalPlaybackTargetType, WTF::String localizedDeviceName) override;
     
-    WEBCORE_EXPORT virtual void setupFullscreen(PlatformLayer&, const IntRect& initialRect, UIView *, HTMLMediaElementEnums::VideoFullscreenMode, bool allowsPictureInPicturePlayback);
+    WEBCORE_EXPORT virtual void setupFullscreen(UIView&, const IntRect& initialRect, UIView *, HTMLMediaElementEnums::VideoFullscreenMode, bool allowsPictureInPicturePlayback);
     WEBCORE_EXPORT virtual void enterFullscreen();
     WEBCORE_EXPORT virtual void exitFullscreen(const IntRect& finalRect);
     WEBCORE_EXPORT virtual void cleanupFullscreen();
@@ -133,9 +133,6 @@
 
     RetainPtr<WebAVPlayerController> m_playerController;
     RetainPtr<AVPlayerViewController> m_playerViewController;
-    RetainPtr<CALayer> m_videoLayer;
-    RetainPtr<WebAVVideoLayer> m_videoLayerContainer;
-    RetainPtr<WebCALayerHostWrapper> m_layerHostWrapper;
     WebVideoFullscreenModel* m_videoFullscreenModel { nullptr };
     WebVideoFullscreenChangeObserver* m_fullscreenChangeObserver { nullptr };
 
@@ -144,6 +141,7 @@
     RetainPtr<UIViewController> m_viewController;
     RetainPtr<UIView> m_parentView;
     RetainPtr<UIWindow> m_parentWindow;
+    RetainPtr<WebAVPlayerLayerView> m_playerLayerView;
     HTMLMediaElementEnums::VideoFullscreenMode m_mode { HTMLMediaElementEnums::VideoFullscreenModeNone };
     std::function<void(bool)> m_prepareToInlineCallback;
     bool m_allowsPictureInPicturePlayback { false };

Modified: branches/safari-601.1-branch/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.mm (187091 => 187092)


--- branches/safari-601.1-branch/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.mm	2015-07-21 05:27:45 UTC (rev 187091)
+++ branches/safari-601.1-branch/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.mm	2015-07-21 05:27:51 UTC (rev 187092)
@@ -39,6 +39,8 @@
 #import "WebVideoFullscreenModel.h"
 #import <AVFoundation/AVTime.h>
 #import <UIKit/UIKit.h>
+#import <objc/message.h>
+#import <objc/runtime.h>
 #import <wtf/RetainPtr.h>
 #import <wtf/text/CString.h>
 #import <wtf/text/WTFString.h>
@@ -50,11 +52,16 @@
 
 SOFT_LINK_FRAMEWORK(AVFoundation)
 SOFT_LINK_CLASS(AVFoundation, AVPlayerLayer)
+SOFT_LINK_CONSTANT(AVFoundation, AVLayerVideoGravityResize, NSString *)
+SOFT_LINK_CONSTANT(AVFoundation, AVLayerVideoGravityResizeAspect, NSString *)
+SOFT_LINK_CONSTANT(AVFoundation, AVLayerVideoGravityResizeAspectFill, NSString *)
 
 SOFT_LINK_FRAMEWORK(AVKit)
 SOFT_LINK_CLASS(AVKit, AVPlayerController)
 SOFT_LINK_CLASS(AVKit, AVPlayerViewController)
 SOFT_LINK_CLASS(AVKit, AVValueTiming)
+SOFT_LINK_CLASS(AVKit, AVPlayerLayerView)
+SOFT_LINK_CLASS(AVKit, AVPictureInPicturePlayerLayerView)
 
 SOFT_LINK_FRAMEWORK(UIKit)
 SOFT_LINK_CLASS(UIKit, UIApplication)
@@ -74,13 +81,12 @@
 
 @class WebAVMediaSelectionOption;
 
-@interface WebAVPlayerController : NSObject <AVPlayerViewControllerDelegate>
-{
+@interface WebAVPlayerController : NSObject <AVPlayerViewControllerDelegate> {
     WebAVMediaSelectionOption *_currentAudioMediaSelectionOption;
     WebAVMediaSelectionOption *_currentLegibleMediaSelectionOption;
 }
 
--(void)resetState;
+- (void)resetState;
 
 @property (retain) AVPlayerController* playerControllerProxy;
 @property (assign) WebVideoFullscreenModel* delegate;
@@ -150,7 +156,8 @@
     [super dealloc];
 }
 
--(void)resetState {
+- (void)resetState
+{
     self.contentDuration = 0;
     self.maxTime = 0;
     self.contentDurationWithinEndTimes = 0;
@@ -181,7 +188,8 @@
     self.currentLegibleMediaSelectionOption = nil;
 }
 
-- (AVPlayer*) player {
+- (AVPlayer *) player
+{
     return nil;
 }
 
@@ -568,25 +576,52 @@
 @implementation WebAVMediaSelectionOption
 @end
 
-
-@interface WebCALayerHostWrapper : CALayer
-@property (assign) WebVideoFullscreenModel* model;
+@interface WebAVPlayerLayer : CALayer
+@property (nonatomic, retain) NSString *videoGravity;
+@property (nonatomic, getter=isReadyForDisplay) BOOL readyForDisplay;
+@property (nonatomic, retain) AVPlayerController *playerController;
+@property (nonatomic, retain) CALayer *videoSublayer;
+@property (nonatomic, copy, nullable) NSDictionary *pixelBufferAttributes;
+@property CGSize videoDimensions;
+@property CGRect modelVideoLayerFrame;
 @end
 
-@implementation WebCALayerHostWrapper {
+@implementation WebAVPlayerLayer {
+    RetainPtr<WebAVPlayerController> _avPlayerController;
     RetainPtr<CALayer> _videoSublayer;
+    RetainPtr<NSString> _videoGravity;
 }
 
+- (instancetype)init
+{
+    self = [super init];
+    if (self) {
+        [self setMasksToBounds:YES];
+        _videoGravity = getAVLayerVideoGravityResizeAspect();
+    }
+    return self;
+}
+
 - (void)dealloc
 {
     [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(resolveBounds) object:nil];
     [super dealloc];
 }
 
-- (void)setVideoSublayer:(CALayer*)videoSublayer
+- (AVPlayerController *)playerController
 {
+    return (AVPlayerController *)_avPlayerController.get();
+}
+
+- (void)setPlayerController:(AVPlayerController *)playerController
+{
+    ASSERT(!playerController || [playerController isKindOfClass:[WebAVPlayerController class]]);
+    _avPlayerController = (WebAVPlayerController *)playerController;
+}
+
+- (void)setVideoSublayer:(CALayer *)videoSublayer
+{
     _videoSublayer = videoSublayer;
-    [self addSublayer:videoSublayer];
 }
 
 - (CALayer*)videoSublayer
@@ -598,152 +633,239 @@
 {
     if (CGRectEqualToRect(bounds, self.bounds))
         return;
-
+    
     [super setBounds:bounds];
+    
+    if ([_videoSublayer superlayer] != self)
+        return;
 
     [_videoSublayer setPosition:CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds))];
-
-    if (!self.model)
+    
+    if (![_avPlayerController delegate])
         return;
 
-    FloatRect videoFrame = self.model->videoLayerFrame();
-    FloatRect targetFrame;
-    switch (self.model->videoLayerGravity()) {
-    case WebCore::WebVideoFullscreenModel::VideoGravityResize:
-        targetFrame = bounds;
-        break;
-    case WebCore::WebVideoFullscreenModel::VideoGravityResizeAspect:
-        targetFrame = largestRectWithAspectRatioInsideRect(videoFrame.size().aspectRatio(), bounds);
-        break;
-    case WebCore::WebVideoFullscreenModel::VideoGravityResizeAspectFill:
-        targetFrame = smallestRectWithAspectRatioAroundRect(videoFrame.size().aspectRatio(), bounds);
-        break;
-    }
-    CATransform3D transform = CATransform3DMakeScale(targetFrame.width() / videoFrame.width(), targetFrame.height() / videoFrame.height(), 1);
-    [_videoSublayer setSublayerTransform:transform];
+    FloatRect sourceVideoFrame;
+    FloatRect targetVideoFrame;
+    float videoAspectRatio = self.videoDimensions.width / self.videoDimensions.height;
+    
+    if ([getAVLayerVideoGravityResize() isEqualToString:self.videoGravity]) {
+        sourceVideoFrame = self.modelVideoLayerFrame;
+        targetVideoFrame = self.bounds;
+    } else if ([getAVLayerVideoGravityResizeAspect() isEqualToString:self.videoGravity]) {
+        sourceVideoFrame = largestRectWithAspectRatioInsideRect(videoAspectRatio, self.modelVideoLayerFrame);
+        targetVideoFrame = largestRectWithAspectRatioInsideRect(videoAspectRatio, self.bounds);
+    } else if ([getAVLayerVideoGravityResizeAspectFill() isEqualToString:self.videoGravity]) {
+        sourceVideoFrame = smallestRectWithAspectRatioAroundRect(videoAspectRatio, self.modelVideoLayerFrame);
+        self.modelVideoLayerFrame = CGRectMake(0, 0, sourceVideoFrame.width(), sourceVideoFrame.height());
+        [_avPlayerController delegate]->setVideoLayerFrame(self.modelVideoLayerFrame);
+        targetVideoFrame = smallestRectWithAspectRatioAroundRect(videoAspectRatio, self.bounds);
+    } else
+        ASSERT_NOT_REACHED();
 
+    UIView *view = [_videoSublayer delegate];
+    CGAffineTransform transform = CGAffineTransformMakeScale(targetVideoFrame.width() / sourceVideoFrame.width(), targetVideoFrame.height() / sourceVideoFrame.height());
+    [view setTransform:transform];
+    
     [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(resolveBounds) object:nil];
-    [self performSelector:@selector(resolveBounds) withObject:nil afterDelay:[CATransaction animationDuration] + 0.1];
+    
+    if (!CGAffineTransformEqualToTransform(CGAffineTransformIdentity, transform))
+        [self performSelector:@selector(resolveBounds) withObject:nil afterDelay:[CATransaction animationDuration] + 0.1];
 }
 
 - (void)resolveBounds
 {
     [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(resolveBounds) object:nil];
-    if (!self.model)
+    if (![_avPlayerController delegate])
         return;
-
+    
+    if ([_videoSublayer superlayer] != self)
+        return;
+    
     [CATransaction begin];
     [CATransaction setAnimationDuration:0];
-
-    [_videoSublayer setSublayerTransform:CATransform3DIdentity];
-    self.model->setVideoLayerFrame([self bounds]);
     
+    [(UIView *)[_videoSublayer delegate] setTransform:CGAffineTransformIdentity];
+    self.modelVideoLayerFrame = [self bounds];
+    [_avPlayerController delegate]->setVideoLayerFrame(self.modelVideoLayerFrame);
+    
     [CATransaction commit];
 }
+
+- (void)setVideoGravity:(NSString *)videoGravity
+{
+    _videoGravity = videoGravity;
+    
+    if (![_avPlayerController delegate])
+        return;
+
+    WebCore::WebVideoFullscreenModel::VideoGravity gravity = WebCore::WebVideoFullscreenModel::VideoGravityResizeAspect;
+    if (videoGravity == getAVLayerVideoGravityResize())
+        gravity = WebCore::WebVideoFullscreenModel::VideoGravityResize;
+    if (videoGravity == getAVLayerVideoGravityResizeAspect())
+        gravity = WebCore::WebVideoFullscreenModel::VideoGravityResizeAspect;
+    else if (videoGravity == getAVLayerVideoGravityResizeAspectFill())
+        gravity = WebCore::WebVideoFullscreenModel::VideoGravityResizeAspectFill;
+    else
+        ASSERT_NOT_REACHED();
+    
+    [_avPlayerController delegate]->setVideoLayerGravity(gravity);
+}
+
+- (NSString *)videoGravity
+{
+    return _videoGravity.get();
+}
+
+- (CGRect)videoRect
+{
+    float videoAspectRatio = self.videoDimensions.width / self.videoDimensions.height;
+    
+    if ([getAVLayerVideoGravityResizeAspect() isEqualToString:self.videoGravity])
+        return largestRectWithAspectRatioInsideRect(videoAspectRatio, self.bounds);
+    if ([getAVLayerVideoGravityResizeAspectFill() isEqualToString:self.videoGravity])
+        return smallestRectWithAspectRatioAroundRect(videoAspectRatio, self.bounds);
+
+    return self.bounds;
+}
+
++ (NSSet *)keyPathsForValuesAffectingVideoRect
+{
+    return [NSSet setWithObjects:@"videoDimensions", @"videoGravity", nil];
+}
+
 @end
 
-@interface WebAVVideoLayer : CALayer <AVVideoLayer>
-+(WebAVVideoLayer *)videoLayer;
-@property (nonatomic) AVVideoLayerGravity videoLayerGravity;
-@property (nonatomic, getter = isReadyForDisplay) BOOL readyForDisplay;
-@property (nonatomic) CGRect videoRect;
-- (void)setPlayerViewController:(AVPlayerViewController *)playerViewController;
-- (void)setPlayerController:(AVPlayerController *)playerController;
-@property (nonatomic, retain) CALayer* videoSublayer;
+@interface WebAVPictureInPicturePlayerLayerView : AVPictureInPicturePlayerLayerView
 @end
 
-@implementation WebAVVideoLayer
+static CALayer* WebAVPictureInPicturePlayerLayerView_layerClass(id, SEL)
 {
-    RetainPtr<WebAVPlayerController> _avPlayerController;
-    RetainPtr<AVPlayerViewController> _avPlayerViewController;
-    RetainPtr<CALayer> _videoSublayer;
-    AVVideoLayerGravity _videoLayerGravity;
+    return [WebAVPlayerLayer class];
 }
 
-+(WebAVVideoLayer *)videoLayer
+static Class getWebAVPictureInPicturePlayerLayerViewClass()
 {
-    return [[[WebAVVideoLayer alloc] init] autorelease];
+    static Class theClass = nil;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        theClass = objc_allocateClassPair(getAVPictureInPicturePlayerLayerViewClass(), "WebAVPictureInPicturePlayerLayerView", 0);
+        objc_registerClassPair(theClass);
+        Class metaClass = objc_getMetaClass("WebAVPictureInPicturePlayerLayerView");
+        class_addMethod(metaClass, @selector(layerClass), (IMP)WebAVPictureInPicturePlayerLayerView_layerClass, "@@:");
+    });
+    
+    return theClass;
 }
 
-- (instancetype)init
+@interface WebAVPlayerLayerView : AVPlayerLayerView
+@property (retain) UIView* videoView;
+@end
+
+static CALayer* WebAVPlayerLayerView_layerClass(id, SEL)
 {
-    self = [super init];
-    if (self) {
-        [self setMasksToBounds:YES];
-        [self setVideoLayerGravity:AVVideoLayerGravityResizeAspect];
-    }
-    return self;
+    return [WebAVPlayerLayer class];
 }
 
-- (void)setPlayerController:(AVPlayerController *)playerController
+static AVPlayerController* WebAVPlayerLayerView_playerController(id aSelf, SEL)
 {
-    ASSERT(!playerController || [playerController isKindOfClass:[WebAVPlayerController class]]);
-    _avPlayerController = (WebAVPlayerController *)playerController;
+    AVPlayerLayerView *playerLayer = aSelf;
+    WebAVPlayerLayer *webAVPlayerLayer = (WebAVPlayerLayer *)[playerLayer playerLayer];
+    return [webAVPlayerLayer playerController];
 }
 
-- (void)setPlayerViewController:(AVPlayerViewController *)playerViewController
+static void WebAVPlayerLayerView_setPlayerController(id aSelf, SEL, AVPlayerController *playerController)
 {
-    _avPlayerViewController = playerViewController;
+    AVPlayerLayerView *playerLayerView = aSelf;
+    WebAVPlayerLayer *webAVPlayerLayer = (WebAVPlayerLayer *)[playerLayerView playerLayer];
+    [webAVPlayerLayer setPlayerController: playerController];
 }
 
-- (void)setVideoSublayer:(CALayer *)videoSublayer
+static UIView* WebAVPlayerLayerView_videoView(id aSelf, SEL)
 {
-    _videoSublayer = videoSublayer;
-    [self addSublayer:videoSublayer];
+    AVPlayerLayerView *playerLayer = aSelf;
+    WebAVPlayerLayer *webAVPlayerLayer = (WebAVPlayerLayer *)[playerLayer playerLayer];
+    CALayer* videoLayer = [webAVPlayerLayer videoSublayer];
+    if (!videoLayer)
+        return nil;
+    ASSERT([[videoLayer delegate] isKindOfClass:getUIViewClass()]);
+    return (UIView *)[videoLayer delegate];
 }
 
-- (CALayer*)videoSublayer
+static void WebAVPlayerLayerView_setVideoView(id aSelf, SEL, UIView *videoView)
 {
-    return _videoSublayer.get();
+    AVPlayerLayerView *playerLayerView = aSelf;
+    WebAVPlayerLayer *webAVPlayerLayer = (WebAVPlayerLayer *)[playerLayerView playerLayer];
+    [webAVPlayerLayer setVideoSublayer:[videoView layer]];
 }
 
-- (void)setBounds:(CGRect)bounds
+static void WebAVPlayerLayerView_startRoutingVideoToPictureInPicturePlayerLayerView(id aSelf, SEL)
 {
-    [super setBounds:bounds];
+    WebAVPlayerLayerView *playerLayerView = aSelf;
+    AVPictureInPicturePlayerLayerView *pipView = [playerLayerView pictureInPicturePlayerLayerView];
 
-    if ([_videoSublayer superlayer] == self) {
-        [_videoSublayer setPosition:CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds))];
-        [_videoSublayer setBounds:bounds];
-    }
+    WebAVPlayerLayer *playerLayer = (WebAVPlayerLayer *)[playerLayerView playerLayer];
+    WebAVPlayerLayer *pipPlayerLayer = (WebAVPlayerLayer *)[pipView playerLayer];
+    [playerLayer setVideoGravity:getAVLayerVideoGravityResizeAspect()];
+    [pipPlayerLayer setVideoSublayer:playerLayer.videoSublayer];
+    [pipPlayerLayer setVideoDimensions:playerLayer.videoDimensions];
+    [pipPlayerLayer setVideoGravity:playerLayer.videoGravity];
+    [pipPlayerLayer setModelVideoLayerFrame:playerLayer.modelVideoLayerFrame];
+    [pipPlayerLayer setPlayerController:playerLayer.playerController];
+    [pipView addSubview:playerLayerView.videoView];
 }
 
-- (void)setVideoLayerGravity:(AVVideoLayerGravity)videoLayerGravity
+static void WebAVPlayerLayerView_stopRoutingVideoToPictureInPicturePlayerLayerView(id aSelf, SEL)
 {
-    _videoLayerGravity = videoLayerGravity;
-    
-    if (![_avPlayerController delegate])
-        return;
-
-    WebCore::WebVideoFullscreenModel::VideoGravity gravity = WebCore::WebVideoFullscreenModel::VideoGravityResizeAspect;
-    if (videoLayerGravity == AVVideoLayerGravityResize)
-        gravity = WebCore::WebVideoFullscreenModel::VideoGravityResize;
-    if (videoLayerGravity == AVVideoLayerGravityResizeAspect)
-        gravity = WebCore::WebVideoFullscreenModel::VideoGravityResizeAspect;
-    else if (videoLayerGravity == AVVideoLayerGravityResizeAspectFill)
-        gravity = WebCore::WebVideoFullscreenModel::VideoGravityResizeAspectFill;
-    else
-        ASSERT_NOT_REACHED();
-    
-    [_avPlayerController delegate]->setVideoLayerGravity(gravity);
+    WebAVPlayerLayerView *playerLayerView = aSelf;
+    [playerLayerView addSubview:playerLayerView.videoView];
 }
 
-- (AVVideoLayerGravity)videoLayerGravity
+static AVPictureInPicturePlayerLayerView *WebAVPlayerLayerView_pictureInPicturePlayerLayerView(id aSelf, SEL)
 {
-    return _videoLayerGravity;
+    WebAVPlayerLayerView *playerLayerView = aSelf;
+    WebAVPictureInPicturePlayerLayerView *pipView = [playerLayerView valueForKey:@"_pictureInPicturePlayerLayerView"];
+    if (!pipView) {
+        pipView = [[getWebAVPictureInPicturePlayerLayerViewClass() alloc] initWithFrame:CGRectZero];
+        [playerLayerView setValue:pipView forKey:@"_pictureInPicturePlayerLayerView"];
+    }
+    return pipView;
 }
 
-- (void)enterPIPModeRedirectingVideoToLayer:(CALayer *)layer
+static void WebAVPlayerLayerView_dealloc(id aSelf, SEL)
 {
-    [_videoSublayer removeFromSuperlayer];
-    [layer addSublayer:_videoSublayer.get()];
+    WebAVPlayerLayerView *playerLayerView = aSelf;
+    RetainPtr<WebAVPictureInPicturePlayerLayerView> pipView = adoptNS([playerLayerView valueForKey:@"_pictureInPicturePlayerLayerView"]);
+    [playerLayerView setValue:nil forKey:@"_pictureInPicturePlayerLayerView"];
+    objc_super superClass { playerLayerView, getAVPlayerLayerViewClass() };
+    auto super_dealloc = reinterpret_cast<void(*)(objc_super*, SEL)>(objc_msgSendSuper);
+    super_dealloc(&superClass, @selector(dealloc));
 }
 
-- (void)leavePIPMode
+#pragma mark - Methods
+
+static Class getWebAVPlayerLayerViewClass()
 {
-    [_videoSublayer removeFromSuperlayer];
-    [self addSublayer:_videoSublayer.get()];
+    static Class theClass = nil;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        theClass = objc_allocateClassPair(getAVPlayerLayerViewClass(), "WebAVPlayerLayerView", 0);
+        class_addMethod(theClass, @selector(dealloc), (IMP)WebAVPlayerLayerView_dealloc, "v@:");
+        class_addMethod(theClass, @selector(setPlayerController:), (IMP)WebAVPlayerLayerView_setPlayerController, "v@:@");
+        class_addMethod(theClass, @selector(playerController), (IMP)WebAVPlayerLayerView_playerController, "@@:");
+        class_addMethod(theClass, @selector(setVideoView:), (IMP)WebAVPlayerLayerView_setVideoView, "v@:@");
+        class_addMethod(theClass, @selector(videoView), (IMP)WebAVPlayerLayerView_videoView, "@@:");
+        class_addMethod(theClass, @selector(startRoutingVideoToPictureInPicturePlayerLayerView), (IMP)WebAVPlayerLayerView_startRoutingVideoToPictureInPicturePlayerLayerView, "v@:");
+        class_addMethod(theClass, @selector(stopRoutingVideoToPictureInPicturePlayerLayerView), (IMP)WebAVPlayerLayerView_stopRoutingVideoToPictureInPicturePlayerLayerView, "v@:");
+        class_addMethod(theClass, @selector(pictureInPicturePlayerLayerView), (IMP)WebAVPlayerLayerView_pictureInPicturePlayerLayerView, "@@:");
+        
+        class_addIvar(theClass, "_pictureInPicturePlayerLayerView", sizeof(WebAVPictureInPicturePlayerLayerView *), log2(sizeof(WebAVPictureInPicturePlayerLayerView *)), "@");
+        
+        objc_registerClassPair(theClass);
+        Class metaClass = objc_getMetaClass("WebAVPlayerLayerView");
+        class_addMethod(metaClass, @selector(layerClass), (IMP)WebAVPlayerLayerView_layerClass, "@@:");
+    });
+    return theClass;
 }
-@end
 
 WebVideoFullscreenInterfaceAVKit::WebVideoFullscreenInterfaceAVKit()
     : m_playerController(adoptNS([[WebAVPlayerController alloc] init]))
@@ -826,6 +948,9 @@
 
 void WebVideoFullscreenInterfaceAVKit::setVideoDimensions(bool hasVideo, float width, float height)
 {
+    WebAVPlayerLayer *playerLayer = (WebAVPlayerLayer *)[m_playerLayerView playerLayer];
+
+    [playerLayer setVideoDimensions:CGSizeMake(width, height)];
     [m_playerController setHasEnabledVideo:hasVideo];
     [m_playerController setContentDimensions:CGSizeMake(width, height)];
 }
@@ -890,14 +1015,14 @@
     playerController.externalPlaybackAirPlayDeviceLocalizedName = localizedDeviceName;
     playerController.externalPlaybackType = externalPlaybackType;
     playerController.externalPlaybackActive = enabled;
-    [m_videoLayerContainer.get() setHidden:enabled];
+    [m_playerLayerView setHidden:enabled];
 }
 
 @interface UIWindow ()
--(BOOL)_isHostedInAnotherProcess;
+- (BOOL)_isHostedInAnotherProcess;
 @end
 
-void WebVideoFullscreenInterfaceAVKit::setupFullscreen(PlatformLayer& videoLayer, const WebCore::IntRect& initialRect, UIView* parentView, HTMLMediaElementEnums::VideoFullscreenMode mode, bool allowsPictureInPicturePlayback)
+void WebVideoFullscreenInterfaceAVKit::setupFullscreen(UIView& videoView, const WebCore::IntRect& initialRect, UIView* parentView, HTMLMediaElementEnums::VideoFullscreenMode mode, bool allowsPictureInPicturePlayback)
 {
     ASSERT(mode != HTMLMediaElementEnums::VideoFullscreenModeNone);
     LOG(Fullscreen, "WebVideoFullscreenInterfaceAVKit::setupFullscreen(%p)", this);
@@ -906,7 +1031,6 @@
 
     [CATransaction begin];
     [CATransaction setDisableActions:YES];
-    m_videoLayer = &videoLayer;
     m_mode = mode;
     m_parentView = parentView;
     m_parentWindow = parentView.window;
@@ -920,51 +1044,46 @@
         [m_window makeKeyAndVisible];
     }
 
-    [m_videoLayer removeFromSuperlayer];
+    m_playerLayerView = adoptNS([[getWebAVPlayerLayerViewClass() alloc] init]);
+    [m_playerLayerView setHidden:[m_playerController isExternalPlaybackActive]];
+    [m_playerLayerView setBackgroundColor:[getUIColorClass() clearColor]];
+    
+    [m_playerLayerView setVideoView:&videoView];
+    [m_playerLayerView addSubview:&videoView];
 
-    m_layerHostWrapper = adoptNS([[WebCALayerHostWrapper alloc] init]);
-    [m_layerHostWrapper setModel:m_videoFullscreenModel];
-    [m_layerHostWrapper setVideoSublayer:m_videoLayer.get()];
+    WebAVPlayerLayer *playerLayer = (WebAVPlayerLayer *)[m_playerLayerView playerLayer];
 
-    m_videoLayerContainer = [WebAVVideoLayer videoLayer];
-    [m_videoLayerContainer setHidden:[m_playerController isExternalPlaybackActive]];
-    [m_videoLayerContainer setVideoSublayer:m_layerHostWrapper.get()];
+    [playerLayer setModelVideoLayerFrame:CGRectMake(0, 0, initialRect.width(), initialRect.height())];
+    [playerLayer setVideoDimensions:[m_playerController contentDimensions]];
 
-    CGSize videoSize = [m_playerController contentDimensions];
-    CGRect videoRect = CGRectMake(0, 0, videoSize.width, videoSize.height);
-    [m_videoLayerContainer setVideoRect:videoRect];
-    if (m_videoFullscreenModel)
-        m_videoFullscreenModel->setVideoLayerFrame(videoRect);
+    m_playerViewController = adoptNS([allocAVPlayerViewControllerInstance() initWithPlayerLayerView:m_playerLayerView.get()]);
 
-    // This method has been deprecated so ignore the warning until we port our code to the new API.
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-    m_playerViewController = adoptNS([allocAVPlayerViewControllerInstance() initWithVideoLayer:m_videoLayerContainer.get()]);
-#pragma clang diagnostic pop
-
     [m_playerViewController setShowsPlaybackControls:NO];
     [m_playerViewController setPlayerController:(AVPlayerController *)m_playerController.get()];
     [m_playerViewController setDelegate:m_playerController.get()];
     [m_playerViewController setAllowsPictureInPicturePlayback:m_allowsPictureInPicturePlayback];
 
-    [m_videoLayerContainer setPlayerViewController:m_playerViewController.get()];
-
     if (m_viewController) {
         [m_viewController addChildViewController:m_playerViewController.get()];
         [[m_viewController view] addSubview:[m_playerViewController view]];
     } else
-        [parentView.window addSubview:[m_playerViewController view]];
+        [parentView addSubview:[m_playerViewController view]];
 
-    [m_playerViewController view].frame = [parentView convertRect:initialRect toView:nil];
+    [m_playerViewController view].frame = [parentView convertRect:initialRect toView:[m_playerViewController view].superview];
 
     [[m_playerViewController view] setBackgroundColor:[getUIColorClass() clearColor]];
+    [[m_playerViewController view] setAutoresizingMask:(UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin)];
+
     [[m_playerViewController view] setNeedsLayout];
     [[m_playerViewController view] layoutIfNeeded];
 
     [CATransaction commit];
 
-    if (m_fullscreenChangeObserver)
-        m_fullscreenChangeObserver->didSetupFullscreen();
+    RefPtr<WebVideoFullscreenInterfaceAVKit> strongThis(this);
+    dispatch_async(dispatch_get_main_queue(), [strongThis, this] {
+        if (m_fullscreenChangeObserver)
+            m_fullscreenChangeObserver->didSetupFullscreen();
+    });
 }
 
 void WebVideoFullscreenInterfaceAVKit::enterFullscreen()
@@ -975,7 +1094,7 @@
     m_exitRequested = false;
     m_enterRequested = true;
 
-    [m_videoLayerContainer setBackgroundColor:[[getUIColorClass() blackColor] CGColor]];
+    [m_playerLayerView setBackgroundColor:[getUIColorClass() blackColor]];
     if (mode() == HTMLMediaElementEnums::VideoFullscreenModePictureInPicture)
         enterPictureInPicture();
     else if (mode() == HTMLMediaElementEnums::VideoFullscreenModeStandard)
@@ -1019,13 +1138,12 @@
     
     LOG(Fullscreen, "WebVideoFullscreenInterfaceAVKit::exitFullscreen(%p)", this);
     [m_playerViewController setShowsPlaybackControls:NO];
-    if (m_viewController)
-        [m_playerViewController view].frame = [m_parentView convertRect:finalRect toView:nil];
-    else
-        [m_playerViewController view].frame = finalRect;
+    
+    [m_playerViewController view].frame = [m_parentView convertRect:finalRect toView:[m_playerViewController view].superview];
 
-    if ([m_videoLayerContainer videoLayerGravity] != AVVideoLayerGravityResizeAspect)
-        [m_videoLayerContainer setVideoLayerGravity:AVVideoLayerGravityResizeAspect];
+    WebAVPlayerLayer *playerLayer = (WebAVPlayerLayer *)[m_playerLayerView playerLayer];
+    if ([playerLayer videoGravity] != getAVLayerVideoGravityResizeAspect())
+        [playerLayer setVideoGravity:getAVLayerVideoGravityResizeAspect()];
     [[m_playerViewController view] layoutIfNeeded];
 
     if (isMode(HTMLMediaElementEnums::VideoFullscreenModePictureInPicture)) {
@@ -1044,22 +1162,24 @@
 
             [CATransaction begin];
             [CATransaction setDisableActions:YES];
-            [m_videoLayerContainer setBackgroundColor:[[getUIColorClass() clearColor] CGColor]];
+            [m_playerLayerView setBackgroundColor:[getUIColorClass() clearColor]];
             [[m_playerViewController view] setBackgroundColor:[getUIColorClass() clearColor]];
             [CATransaction commit];
 
-            if (m_fullscreenChangeObserver)
-                m_fullscreenChangeObserver->didExitFullscreen();
+            dispatch_async(dispatch_get_main_queue(), ^{
+                if (m_fullscreenChangeObserver)
+                    m_fullscreenChangeObserver->didExitFullscreen();
+            });
         }];
     };
 }
 
 @interface UIApplication ()
--(void)_setStatusBarOrientation:(UIInterfaceOrientation)o;
+- (void)_setStatusBarOrientation:(UIInterfaceOrientation)o;
 @end
 
 @interface UIWindow ()
--(UIInterfaceOrientation)interfaceOrientation;
+- (UIInterfaceOrientation)interfaceOrientation;
 @end
 
 void WebVideoFullscreenInterfaceAVKit::cleanupFullscreen()
@@ -1087,16 +1207,10 @@
     if (m_viewController)
         [m_playerViewController removeFromParentViewController];
     
-    [m_videoLayer removeFromSuperlayer];
-    [m_videoLayerContainer removeFromSuperlayer];
-    [m_videoLayerContainer setPlayerViewController:nil];
+    [m_playerLayerView removeFromSuperview];
     [[m_viewController view] removeFromSuperview];
 
-    [m_layerHostWrapper setModel:nullptr];
-
-    m_layerHostWrapper = nil;
-    m_videoLayer = nil;
-    m_videoLayerContainer = nil;
+    m_playerLayerView = nil;
     m_playerViewController = nil;
     m_playerController = nil;
     m_viewController = nil;
@@ -1142,7 +1256,7 @@
     LOG(Fullscreen, "WebVideoFullscreenInterfaceAVKit::preparedToReturnToInline(%p) - visible(%s)", this, boolString(visible));
     if (m_prepareToInlineCallback) {
         
-        [m_playerViewController view].frame = [m_parentView convertRect:inlineRect toView:nil];
+        [m_playerViewController view].frame = [m_parentView convertRect:inlineRect toView:[m_playerViewController view].superview];
 
         std::function<void(bool)> callback = WTF::move(m_prepareToInlineCallback);
         callback(visible);
@@ -1213,7 +1327,7 @@
 
     m_exitCompleted = true;
 
-    [m_videoLayerContainer setBackgroundColor:[[getUIColorClass() clearColor] CGColor]];
+    [m_playerLayerView setBackgroundColor:[getUIColorClass() clearColor]];
     [[m_playerViewController view] setBackgroundColor:[getUIColorClass() clearColor]];
 
     clearMode(HTMLMediaElementEnums::VideoFullscreenModePictureInPicture);

Modified: branches/safari-601.1-branch/Source/WebCore/platform/ios/WebVideoFullscreenModel.h (187091 => 187092)


--- branches/safari-601.1-branch/Source/WebCore/platform/ios/WebVideoFullscreenModel.h	2015-07-21 05:27:45 UTC (rev 187091)
+++ branches/safari-601.1-branch/Source/WebCore/platform/ios/WebVideoFullscreenModel.h	2015-07-21 05:27:51 UTC (rev 187092)
@@ -48,10 +48,8 @@
     virtual void endScanning() = 0;
     virtual void requestExitFullscreen() = 0;
     virtual void setVideoLayerFrame(FloatRect) = 0;
-    virtual FloatRect videoLayerFrame() const = 0;
     enum VideoGravity { VideoGravityResize, VideoGravityResizeAspect, VideoGravityResizeAspectFill };
     virtual void setVideoLayerGravity(VideoGravity) = 0;
-    virtual VideoGravity videoLayerGravity() const = 0;
     virtual void selectAudioMediaOption(uint64_t index) = 0;
     virtual void selectLegibleMediaOption(uint64_t index) = 0;
     virtual void fullscreenModeChanged(HTMLMediaElementEnums::VideoFullscreenMode) = 0;

Modified: branches/safari-601.1-branch/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.h (187091 => 187092)


--- branches/safari-601.1-branch/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.h	2015-07-21 05:27:45 UTC (rev 187091)
+++ branches/safari-601.1-branch/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.h	2015-07-21 05:27:51 UTC (rev 187092)
@@ -72,9 +72,7 @@
     WEBCORE_EXPORT virtual void endScanning() override;
     WEBCORE_EXPORT virtual void requestExitFullscreen() override;
     WEBCORE_EXPORT virtual void setVideoLayerFrame(FloatRect) override;
-    WEBCORE_EXPORT virtual FloatRect videoLayerFrame() const override;
     WEBCORE_EXPORT virtual void setVideoLayerGravity(VideoGravity) override;
-    WEBCORE_EXPORT virtual VideoGravity videoLayerGravity() const override;
     WEBCORE_EXPORT virtual void selectAudioMediaOption(uint64_t index) override;
     WEBCORE_EXPORT virtual void selectLegibleMediaOption(uint64_t index) override;
     WEBCORE_EXPORT virtual void fullscreenModeChanged(HTMLMediaElementEnums::VideoFullscreenMode) override;

Modified: branches/safari-601.1-branch/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.mm (187091 => 187092)


--- branches/safari-601.1-branch/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.mm	2015-07-21 05:27:45 UTC (rev 187091)
+++ branches/safari-601.1-branch/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.mm	2015-07-21 05:27:51 UTC (rev 187092)
@@ -254,11 +254,6 @@
         m_videoElement->setVideoFullscreenFrame(rect);
 }
 
-FloatRect WebVideoFullscreenModelVideoElement::videoLayerFrame() const
-{
-    return m_videoFrame;
-}
-
 void WebVideoFullscreenModelVideoElement::setVideoLayerGravity(WebVideoFullscreenModel::VideoGravity gravity)
 {
     MediaPlayer::VideoGravity videoGravity = MediaPlayer::VideoGravityResizeAspect;
@@ -274,21 +269,6 @@
     m_videoElement->setVideoFullscreenGravity(videoGravity);
 }
 
-WebVideoFullscreenModel::VideoGravity WebVideoFullscreenModelVideoElement::videoLayerGravity() const
-{
-    switch (m_videoElement->videoFullscreenGravity()) {
-    case MediaPlayer::VideoGravityResize:
-        return VideoGravityResize;
-    case MediaPlayer::VideoGravityResizeAspect:
-        return VideoGravityResizeAspect;
-    case MediaPlayer::VideoGravityResizeAspectFill:
-        return VideoGravityResizeAspectFill;
-    }
-
-    ASSERT_NOT_REACHED();
-    return VideoGravityResize;
-}
-
 void WebVideoFullscreenModelVideoElement::selectAudioMediaOption(uint64_t selectedAudioIndex)
 {
     AudioTrack* selectedAudioTrack = nullptr;

Modified: branches/safari-601.1-branch/Source/WebCore/platform/spi/cocoa/AVKitSPI.h (187091 => 187092)


--- branches/safari-601.1-branch/Source/WebCore/platform/spi/cocoa/AVKitSPI.h	2015-07-21 05:27:45 UTC (rev 187091)
+++ branches/safari-601.1-branch/Source/WebCore/platform/spi/cocoa/AVKitSPI.h	2015-07-21 05:27:51 UTC (rev 187092)
@@ -34,9 +34,12 @@
 #if USE(APPLE_INTERNAL_SDK)
 
 #import <AVKit/AVPlayerController.h>
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wobjc-property-no-attribute"
+#import <AVKit/AVPlayerLayerView.h>
+#pragma clang diagnostic pop
 #import <AVKit/AVPlayerViewController_Private.h>
 #import <AVKit/AVPlayerViewController_WebKitOnly.h>
-#import <AVKit/AVVideoLayer.h>
 
 #else
 
@@ -58,19 +61,19 @@
 @property (NS_NONATOMIC_IOSONLY, readonly) AVPlayerControllerStatus status;
 @end
 
-@protocol AVVideoLayer
-typedef NS_ENUM(NSInteger, AVVideoLayerGravity) {
-    AVVideoLayerGravityInvalid = 0,
-    AVVideoLayerGravityResizeAspect = 1,
-    AVVideoLayerGravityResizeAspectFill = 2,
-    AVVideoLayerGravityResize = 3,
-};
-- (void)setPlayerController:(AVPlayerController *)playerController;
-@property (nonatomic) AVVideoLayerGravity videoLayerGravity;
-@property (nonatomic) CGRect videoRect;
-@property (nonatomic, readonly, getter=isReadyForDisplay) BOOL readyForDisplay;
+@class AVPlayerLayer;
+
+@interface AVPictureInPicturePlayerLayerView : UIView
+@property (nonatomic, readonly) AVPlayerLayer *playerLayer;
 @end
 
+@interface AVPlayerLayerView : UIView
+@property (nonatomic, readonly) AVPlayerLayer *playerLayer;
+@property (nonatomic, readonly) AVPictureInPicturePlayerLayerView *pictureInPicturePlayerLayerView;
+- (void)startRoutingVideoToPictureInPicturePlayerLayerView;
+- (void)stopRoutingVideoToPictureInPicturePlayerLayerView;
+@end
+
 @protocol AVPlayerViewControllerDelegate <NSObject>
 @optional
 typedef NS_ENUM(NSInteger, AVPlayerViewControllerExitFullScreenReason) {
@@ -85,15 +88,15 @@
 @end
 
 @interface AVPlayerViewController (Details)
-- (instancetype)initWithVideoLayer:(CALayer <AVVideoLayer> *)videoLayer;
+- (instancetype)initWithPlayerLayerView:(AVPlayerLayerView *)playerLayerView;
 - (void)enterFullScreenAnimated:(BOOL)animated completionHandler:(void (^)(BOOL success, NSError *))completionHandler;
 - (void)exitFullScreenAnimated:(BOOL)animated completionHandler:(void (^)(BOOL success, NSError *))completionHandler;
 
 - (BOOL)isPictureInPicturePossible;
 - (void)startPictureInPicture;
 - (void)stopPictureInPicture;
-- (void)setAllowsPictureInPicturePlayback:(BOOL)allow;
 
+@property (nonatomic) BOOL allowsPictureInPicturePlayback;
 @property (nonatomic, strong) AVPlayerController *playerController;
 @property (nonatomic, weak) id <AVPlayerViewControllerDelegate> delegate;
 @end

Modified: branches/safari-601.1-branch/Source/WebCore/platform/spi/cocoa/QuartzCoreSPI.h (187091 => 187092)


--- branches/safari-601.1-branch/Source/WebCore/platform/spi/cocoa/QuartzCoreSPI.h	2015-07-21 05:27:45 UTC (rev 187091)
+++ branches/safari-601.1-branch/Source/WebCore/platform/spi/cocoa/QuartzCoreSPI.h	2015-07-21 05:27:51 UTC (rev 187092)
@@ -32,6 +32,7 @@
 #include <QuartzCore/CARenderServer.h>
 
 #ifdef __OBJC__
+#import <QuartzCore/CALayerHost.h>
 #import <QuartzCore/CALayerPrivate.h>
 
 // FIXME: As a workaround for <rdar://problem/18985152>, we conditionally enclose the following
@@ -134,6 +135,12 @@
 + (void)addCommitHandler:(void(^)(void))block forPhase:(CATransactionPhase)phase;
 @end
 #endif
+
+@interface CALayerHost : CALayer
+@property uint32_t contextId;
+@property BOOL inheritsSecurity;
+@end
+
 #endif // __OBJC__
 
 #endif

Modified: branches/safari-601.1-branch/Source/WebKit2/ChangeLog (187091 => 187092)


--- branches/safari-601.1-branch/Source/WebKit2/ChangeLog	2015-07-21 05:27:45 UTC (rev 187091)
+++ branches/safari-601.1-branch/Source/WebKit2/ChangeLog	2015-07-21 05:27:51 UTC (rev 187092)
@@ -1,5 +1,46 @@
 2015-07-20  Matthew Hanson  <[email protected]>
 
+        Merge r187044. rdar://problem/21661808
+
+    2015-07-20  Jeremy Jones  <[email protected]>
+
+            Adopt AVPlayerLayerView
+            https://bugs.webkit.org/show_bug.cgi?id=146862
+
+            Reviewed by Simon Fraser.
+
+            The CALayerHost is replaced with WebLayerHostView to be compatible with UIView animations.
+            videoLayerFrame and videoLayerGravity no longer need to be stored because they are stored
+            where they are used in the interface. Some animation is improved in the conversion.
+
+            * UIProcess/ios/WebVideoFullscreenManagerProxy.h:
+            * UIProcess/ios/WebVideoFullscreenManagerProxy.mm:
+            (+[WebLayerHostView layerClass]): Add class WebLayerHostView.
+            (-[WebLayerHostView contextID]):
+            (-[WebLayerHostView setContextID:]):
+            (-[WebLayerHostView layerHost]):
+            (WebKit::WebVideoFullscreenManagerProxy::invalidate): layer -> view
+            (WebKit::WebVideoFullscreenManagerProxy::setupFullscreenWithID):
+            Apply the hostingDeviceScaleFactor transform to -sublayerTransform instead of to
+            -transform. This more directly inverts the tranform WebProcess and allows -transform
+            to be used for animation in the UIProcess. This is important because UIView's actions
+            animate -transform, but not -sublayerTrasform.
+
+            (WebKit::WebVideoFullscreenManagerProxy::didCleanupFullscreen): layer -> view
+            (WebKit::WebVideoFullscreenModelContext::setVideoLayerFrame): Deleted.
+            (WebKit::WebVideoFullscreenModelContext::videoLayerFrame): Deleted.
+            (WebKit::WebVideoFullscreenModelContext::setVideoLayerGravity): Deleted.
+            (WebKit::WebVideoFullscreenModelContext::videoLayerGravity): Deleted.
+            * WebProcess/ios/WebVideoFullscreenManager.mm:
+            (WebKit::WebVideoFullscreenManager::enterVideoFullscreenForVideoElement):
+            Set initial video layer frame to fix start point of animation.
+
+            (WebKit::WebVideoFullscreenManager::didSetupFullscreen):
+            dispatch_async allows the CATransaction to complete before continuing with the animation.
+            This prevents a flash during animation.
+
+2015-07-20  Matthew Hanson  <[email protected]>
+
         Merge r187039. rdar://problem/21474317
 
     2015-07-20  Tim Horton  <[email protected]>

Modified: branches/safari-601.1-branch/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.h (187091 => 187092)


--- branches/safari-601.1-branch/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.h	2015-07-21 05:27:45 UTC (rev 187091)
+++ branches/safari-601.1-branch/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.h	2015-07-21 05:27:51 UTC (rev 187092)
@@ -53,11 +53,9 @@
 
     void invalidate() { m_manager = nullptr; }
 
-    PlatformLayer* layerHost() const { return m_layerHost.get(); }
-    void setLayerHost(RetainPtr<PlatformLayer>&& layerHost) { m_layerHost = WTF::move(layerHost); }
+    UIView *layerHostView() const { return m_layerHostView.get(); }
+    void setLayerHostView(RetainPtr<UIView>&& layerHostView) { m_layerHostView = WTF::move(layerHostView); }
 
-    void setInitialVideoLayerFrame(WebCore::FloatRect frame) { m_videoLayerFrame = frame; }
-
 private:
     WebVideoFullscreenModelContext(WebVideoFullscreenManagerProxy& manager, uint64_t contextId)
         : m_manager(&manager)
@@ -78,9 +76,7 @@
     virtual void endScanning() override;
     virtual void requestExitFullscreen() override;
     virtual void setVideoLayerFrame(WebCore::FloatRect) override;
-    virtual WebCore::FloatRect videoLayerFrame() const override;
     virtual void setVideoLayerGravity(VideoGravity) override;
-    virtual VideoGravity videoLayerGravity() const override;
     virtual void selectAudioMediaOption(uint64_t) override;
     virtual void selectLegibleMediaOption(uint64_t) override;
     virtual void fullscreenModeChanged(WebCore::HTMLMediaElementEnums::VideoFullscreenMode) override;
@@ -94,9 +90,7 @@
 
     WebVideoFullscreenManagerProxy* m_manager;
     uint64_t m_contextId;
-    RetainPtr<PlatformLayer> m_layerHost;
-    WebCore::FloatRect m_videoLayerFrame;
-    VideoGravity m_videoLayerGravity { VideoGravityResize };
+    RetainPtr<UIView *> m_layerHostView;
 };
 
 class WebVideoFullscreenManagerProxy : public RefCounted<WebVideoFullscreenManagerProxy>, private IPC::MessageReceiver {

Modified: branches/safari-601.1-branch/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.mm (187091 => 187092)


--- branches/safari-601.1-branch/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.mm	2015-07-21 05:27:45 UTC (rev 187091)
+++ branches/safari-601.1-branch/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.mm	2015-07-21 05:27:51 UTC (rev 187092)
@@ -35,9 +35,34 @@
 #import "WebVideoFullscreenManagerMessages.h"
 #import "WebVideoFullscreenManagerProxyMessages.h"
 #import <QuartzCore/CoreAnimation.h>
+#import <WebCore/QuartzCoreSPI.h>
 #import <WebCore/TimeRanges.h>
 #import <WebKitSystemInterface.h>
 
+@interface WebLayerHostView : UIView
+@property (nonatomic, assign) uint32_t contextID;
+@end
+
+@implementation WebLayerHostView
+
++ (Class)layerClass {
+    return [CALayerHost class];
+}
+
+- (uint32_t)contextID {
+    return [[self layerHost] contextId];
+}
+
+- (void)setContextID:(uint32_t)contextID {
+    [[self layerHost] setContextId:contextID];
+}
+
+- (CALayerHost *)layerHost {
+    return (CALayerHost *)[self layer];
+}
+
+@end
+
 using namespace WebCore;
 
 namespace WebKit {
@@ -139,28 +164,16 @@
 
 void WebVideoFullscreenModelContext::setVideoLayerFrame(WebCore::FloatRect frame)
 {
-    m_videoLayerFrame = frame;
     if (m_manager)
         m_manager->setVideoLayerFrame(m_contextId, frame);
 }
 
-WebCore::FloatRect WebVideoFullscreenModelContext::videoLayerFrame() const
-{
-    return m_videoLayerFrame;
-}
-
 void WebVideoFullscreenModelContext::setVideoLayerGravity(WebCore::WebVideoFullscreenModel::VideoGravity gravity)
 {
-    m_videoLayerGravity = gravity;
     if (m_manager)
         m_manager->setVideoLayerGravity(m_contextId, gravity);
 }
 
-WebCore::WebVideoFullscreenModel::VideoGravity WebVideoFullscreenModelContext::videoLayerGravity() const
-{
-    return m_videoLayerGravity;
-}
-
 void WebVideoFullscreenModelContext::selectAudioMediaOption(uint64_t optionId)
 {
     if (m_manager)
@@ -240,8 +253,8 @@
         std::tie(model, interface) = tuple;
 
         interface->invalidate();
-        [model->layerHost() removeFromSuperlayer];
-        model->setLayerHost(nullptr);
+        [model->layerHostView() removeFromSuperview];
+        model->setLayerHostView(nullptr);
     }
 
     m_contextMap.clear();
@@ -310,16 +323,17 @@
 
     std::tie(model, interface) = ensureModelAndInterface(contextId);
 
-    model->setInitialVideoLayerFrame(initialRect);
-    model->setLayerHost(WKMakeRenderLayer(videoLayerID));
+    RetainPtr<WebLayerHostView> view = adoptNS([[WebLayerHostView alloc] init]);
+    [view setContextID:videoLayerID];
+    model->setLayerHostView(view);
     if (hostingDeviceScaleFactor != 1) {
         // Invert the scale transform added in the WebProcess to fix <rdar://problem/18316542>.
         float inverseScale = 1 / hostingDeviceScaleFactor;
-        [model->layerHost() setTransform:CATransform3DMakeScale(inverseScale, inverseScale, 1)];
+        [[model->layerHostView() layer] setSublayerTransform:CATransform3DMakeScale(inverseScale, inverseScale, 1)];
     }
 
     UIView *parentView = downcast<RemoteLayerTreeDrawingAreaProxy>(*m_page->drawingArea()).remoteLayerTreeHost().rootLayer();
-    interface->setupFullscreen(*model->layerHost(), initialRect, parentView, videoFullscreenMode, allowsPictureInPicture);
+    interface->setupFullscreen(*model->layerHostView(), initialRect, parentView, videoFullscreenMode, allowsPictureInPicture);
 }
 
 void WebVideoFullscreenManagerProxy::resetMediaState(uint64_t contextId)
@@ -502,8 +516,8 @@
     auto& model = ensureModel(contextId);
 
     [CATransaction flush];
-    [model.layerHost() removeFromSuperlayer];
-    model.setLayerHost(nullptr);
+    [model.layerHostView() removeFromSuperview];
+    model.setLayerHostView(nullptr);
     m_page->send(Messages::WebVideoFullscreenManager::DidCleanupFullscreen(contextId), m_page->pageID());
 
     m_contextMap.remove(contextId);

Modified: branches/safari-601.1-branch/Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.mm (187091 => 187092)


--- branches/safari-601.1-branch/Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.mm	2015-07-21 05:27:45 UTC (rev 187091)
+++ branches/safari-601.1-branch/Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.mm	2015-07-21 05:27:51 UTC (rev 187092)
@@ -232,9 +232,13 @@
     RefPtr<WebVideoFullscreenInterfaceContext> interface;
     std::tie(model, interface) = ensureModelAndInterface(contextId);
 
+    FloatRect clientRect = clientRectForElement(&videoElement);
+    FloatRect videoLayerFrame = FloatRect(0, 0, clientRect.width(), clientRect.height());
+    
     interface->setTargetIsFullscreen(true);
     interface->setFullscreenMode(mode);
     model->setVideoElement(&videoElement);
+    model->setVideoLayerFrame(videoLayerFrame);
 
     if (interface->isAnimating())
         return;
@@ -428,7 +432,10 @@
 
     [CATransaction commit];
 
-    m_page->send(Messages::WebVideoFullscreenManagerProxy::EnterFullscreen(contextId), m_page->pageID());
+    RefPtr<WebVideoFullscreenManager> strongThis(this);
+    dispatch_async(dispatch_get_main_queue(), [strongThis, this, contextId] {
+        m_page->send(Messages::WebVideoFullscreenManagerProxy::EnterFullscreen(contextId), m_page->pageID());
+    });
 }
     
 void WebVideoFullscreenManager::didEnterFullscreen(uint64_t contextId)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to