Changeset 187044 in webkit


Ignore:
Timestamp:
Jul 20, 2015, 4:27:49 PM (10 years ago)
Author:
commit-queue@webkit.org
Message:

Adopt AVPlayerLayerView
https://bugs.webkit.org/show_bug.cgi?id=146862

Patch by Jeremy Jones <jeremyj@apple.com> on 2015-07-20
Source/WebCore:

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.

Source/WebKit2:

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.

Location:
trunk/Source
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified trunk/Source/WebCore/ChangeLog

    r187043 r187044  
     12015-07-20  Jeremy Jones  <jeremyj@apple.com>
     2
     3        Adopt AVPlayerLayerView
     4        https://bugs.webkit.org/show_bug.cgi?id=146862
     5
     6        Reviewed by Jer Noble.
     7
     8        The CALayerHost is replaced with WebLayerHostView to be compatible with UIView animations.
     9        Some animation is improved in the conversion.
     10
     11        WebAVPlayerLayerView and WebAVPictureInPicturePlayerLayerView derive from AVKit and UIKit respectively.
     12        Because these frameworks are loaded at runtime, these classes must be generate using objc/runtime.h to
     13        register them from c functions at runtime. The most important part of these UIViews is that their
     14        backing layer is a WebAVPlayerLayer.
     15
     16        WebCALayerHostWrapper and WebAVVideoLayer are combined into WebAVPlayerLayer to simplify the hierarchy.
     17        WebAVPlayerLayer is a stand-in for an AVPlayerLayer.
     18
     19        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
     20        (WebCore::MediaPlayerPrivateAVFoundationObjC::setVideoFullscreenLayer): -removeFromSuperlayer is redundant.
     21        (WebCore::MediaPlayerPrivateAVFoundationObjC::setVideoFullscreenGravity): syncTextTrackBounds on change.
     22        (WebCore::MediaPlayerPrivateAVFoundationObjC::setVideoFullscreenFrame):
     23        We never want animation here, since all animation will happen in UIViews.
     24        This is just for going into the final size after a transform based animation.
     25
     26        * platform/ios/WebVideoFullscreenControllerAVKit.mm:
     27        (WebVideoFullscreenControllerContext::didSetupFullscreen): layer -> view
     28        (WebVideoFullscreenControllerContext::didCleanupFullscreen): layer -> view
     29        (WebVideoFullscreenControllerContext::setUpFullscreen): layer -> view
     30
     31        (WebVideoFullscreenControllerContext::setVideoLayerFrame): layer -> view
     32        Use fence port to synchronize between the UIThread and the WebThread,
     33        the same way WebKit2 uses a fence port to synchronize between processes.
     34
     35        (WebVideoFullscreenControllerContext::setVideoLayerGravity):
     36        No longer necessary to cache videoGravity at this level.
     37
     38        * platform/ios/WebVideoFullscreenInterfaceAVKit.h:
     39        * platform/ios/WebVideoFullscreenInterfaceAVKit.mm:
     40
     41        (-[WebAVPlayerLayer init]):
     42        (-[WebAVPlayerLayer dealloc]):
     43        (-[WebAVPlayerLayer playerController]):
     44        (-[WebAVPlayerLayer setBounds:]):
     45        (-[WebAVPlayerLayer resolveBounds]):
     46        (-[WebAVPlayerLayer setVideoGravity:]):
     47        (-[WebAVPlayerLayer videoGravity]):
     48        (-[WebAVPlayerLayer videoRect]):
     49        (+[WebAVPlayerLayer keyPathsForValuesAffectingVideoRect]):
     50        Added class WebAVPlayerLayer, replacing WebAVVideoLayer and WebCALayerHostWrapper.
     51
     52        (WebAVPictureInPicturePlayerLayerView_layerClass):
     53        (getWebAVPictureInPicturePlayerLayerViewClass):
     54        Added runtime class WebAVPictureInPicturePlayerLayerView
     55
     56        (WebAVPlayerLayerView_layerClass):
     57        (WebAVPlayerLayerView_playerController):
     58        (WebAVPlayerLayerView_setPlayerController):
     59        (WebAVPlayerLayerView_videoView):
     60        (WebAVPlayerLayerView_setVideoView):
     61        (WebAVPlayerLayerView_startRoutingVideoToPictureInPicturePlayerLayerView):
     62        (WebAVPlayerLayerView_stopRoutingVideoToPictureInPicturePlayerLayerView):
     63        (WebAVPlayerLayerView_pictureInPicturePlayerLayerView):
     64        (getWebAVPlayerLayerViewClass):
     65        Added runtime class WebAVPlayerLayerView
     66
     67        (WebVideoFullscreenInterfaceAVKit::setVideoDimensions):
     68        Dimensions are also stored in WebAVPlayerLayer so it can make decisions about
     69        animating the video layer.
     70
     71        (WebVideoFullscreenInterfaceAVKit::setExternalPlayback):
     72        (WebVideoFullscreenInterfaceAVKit::enterFullscreen):
     73        (WebVideoFullscreenInterfaceAVKit::didStopPictureInPicture):
     74        (WebVideoFullscreenInterfaceAVKit::cleanupFullscreen):
     75        Straightforward layer to view conversion.
     76
     77        (WebVideoFullscreenInterfaceAVKit::preparedToReturnToInline):
     78        Set view frame using the view hierarchy instead of assuming it is directly in a window.
     79
     80        (WebVideoFullscreenInterfaceAVKit::exitFullscreen):
     81        Set view frame using the view hierarchy instead of assuming it is directly in a window.
     82        dispatch_async before calling didExitFullscreen() to allows CATransactions to complete.
     83
     84        (WebVideoFullscreenInterfaceAVKit::setupFullscreen):
     85        Set view frame using the view hierarchy instead of assuming it is directly in a window.
     86        dispatch_async before calling didSetupFullscreen() to allows CATransactions to complete.
     87
     88        (-[WebCALayerHostWrapper dealloc]): Deleted.
     89        (-[WebCALayerHostWrapper setVideoSublayer:]): Deleted.
     90        (-[WebCALayerHostWrapper videoSublayer]): Deleted.
     91        (-[WebCALayerHostWrapper setBounds:]): Deleted.
     92        (-[WebCALayerHostWrapper resolveBounds]): Deleted.
     93        Class WebCALayerHostWrapper deleted. Functionality rolled into WebAVPlayerLayer.
     94
     95        (+[WebAVVideoLayer videoLayer]): Deleted.
     96        (-[WebAVVideoLayer init]): Deleted.
     97        (-[WebAVVideoLayer setPlayerViewController:]): Deleted.
     98        (-[WebAVVideoLayer setVideoSublayer:]): Deleted.
     99        (-[WebAVVideoLayer setBounds:]): Deleted.
     100        (-[WebAVVideoLayer setVideoLayerGravity:]): Deleted.
     101        (-[WebAVVideoLayer videoLayerGravity]): Deleted.
     102        (-[WebAVVideoLayer enterPIPModeRedirectingVideoToLayer:]): Deleted.
     103        (-[WebAVVideoLayer leavePIPMode]): Deleted.
     104        Class WebAVVideoLayer deleted. Functionality rolled into WebAVPlayerLayer.
     105
     106        * platform/ios/WebVideoFullscreenModel.h:
     107        * platform/ios/WebVideoFullscreenModelVideoElement.h:
     108        * platform/ios/WebVideoFullscreenModelVideoElement.mm:
     109        No need to store frame and gravity in the model. It is stored in the UI where it is used.
     110
     111        (WebVideoFullscreenModelVideoElement::videoLayerFrame): Deleted.
     112        (WebVideoFullscreenModelVideoElement::videoLayerGravity): Deleted.
     113        * platform/spi/cocoa/AVKitSPI.h: Add AVPlayerLayerView.
     114
    11152015-07-20  Anders Carlsson  <andersca@apple.com>
    2116
  • TabularUnified trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm

    r186563 r187044  
    11251125   
    11261126    if (m_videoFullscreenLayer && m_videoLayer) {
     1127        [m_videoFullscreenLayer insertSublayer:m_videoLayer.get() atIndex:0];
    11271128        [m_videoLayer setFrame:CGRectMake(0, 0, m_videoFullscreenFrame.width(), m_videoFullscreenFrame.height())];
    1128         [m_videoLayer removeFromSuperlayer];
    1129         [m_videoFullscreenLayer insertSublayer:m_videoLayer.get() atIndex:0];
    11301129        newContext = [m_videoFullscreenLayer context];
    11311130    } else if (m_videoInlineLayer && m_videoLayer) {
     
    11591158
    11601159    if (m_videoLayer) {
    1161         [m_videoLayer setStyle:nil]; // This enables actions, i.e. implicit animations.
    1162         [CATransaction begin];
    11631160        [m_videoLayer setFrame:CGRectMake(0, 0, frame.width(), frame.height())];
    1164         [CATransaction commit];
    1165         [m_videoLayer web_disableAllActions];
    11661161    }
    11671162    syncTextTrackBounds();
     
    11831178    else
    11841179        ASSERT_NOT_REACHED();
     1180   
     1181    if ([m_videoLayer videoGravity] == videoGravity)
     1182        return;
    11851183
    11861184    [m_videoLayer setVideoGravity:videoGravity];
     1185    syncTextTrackBounds();
    11871186}
    11881187
  • TabularUnified trunk/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm

    r185727 r187044  
    3131
    3232#import "Logging.h"
     33#import "QuartzCoreSPI.h"
     34#import "SoftLinking.h"
    3335#import "TimeRanges.h"
    3436#import "WebVideoFullscreenInterfaceAVKit.h"
     
    3739#import <WebCore/HTMLVideoElement.h>
    3840#import <WebCore/WebCoreThreadRun.h>
     41
     42SOFT_LINK_FRAMEWORK(UIKit)
     43SOFT_LINK_CLASS(UIKit, UIView)
    3944
    4045using namespace WebCore;
     
    130135    virtual void requestExitFullscreen() override;
    131136    virtual void setVideoLayerFrame(FloatRect) override;
    132     virtual FloatRect videoLayerFrame() const override { return m_frame; }
    133137    virtual void setVideoLayerGravity(WebVideoFullscreenModel::VideoGravity) override;
    134     virtual VideoGravity videoLayerGravity() const override { return m_gravity; }
    135138    virtual void selectAudioMediaOption(uint64_t index) override;
    136139    virtual void selectLegibleMediaOption(uint64_t index) override;
     
    140143    RefPtr<WebVideoFullscreenModelVideoElement> m_model;
    141144    RefPtr<HTMLVideoElement> m_videoElement;
    142     RetainPtr<PlatformLayer> m_videoFullscreenLayer;
     145    RetainPtr<UIView> m_videoFullscreenView;
    143146    RetainPtr<WebVideoFullscreenController> m_controller;
    144     FloatRect m_frame;
    145     VideoGravity m_gravity;
    146147};
    147148
     
    152153    ASSERT(isUIThread());
    153154    RefPtr<WebVideoFullscreenControllerContext> strongThis(this);
    154     WebThreadRun([strongThis, this] {
    155         m_model->setVideoFullscreenLayer(m_videoFullscreenLayer.get());
     155    RetainPtr<CALayer> videoFullscreenLayer = [m_videoFullscreenView layer];
     156    WebThreadRun([strongThis, this, videoFullscreenLayer] {
     157        m_model->setVideoFullscreenLayer(videoFullscreenLayer.get());
    156158        dispatch_async(dispatch_get_main_queue(), [strongThis, this] {
    157159            m_interface->enterFullscreen();
     
    178180    m_interface->setWebVideoFullscreenChangeObserver(nullptr);
    179181    m_interface = nullptr;
     182    m_videoFullscreenView = nil;
    180183   
    181184    RefPtr<WebVideoFullscreenControllerContext> strongThis(this);
     
    186189        m_model = nullptr;
    187190        m_videoElement = nullptr;
    188         m_videoFullscreenLayer = nil;
    189191       
    190192        [m_controller didFinishFullscreen:this];
     
    451453{
    452454    ASSERT(isUIThread());
    453     m_frame = frame;
    454     RefPtr<WebVideoFullscreenControllerContext> strongThis(this);
    455     WebThreadRun([strongThis, this, frame] {
     455    RefPtr<WebVideoFullscreenControllerContext> strongThis(this);
     456    RetainPtr<CALayer> videoFullscreenLayer = [m_videoFullscreenView layer];
     457
     458    mach_port_name_t fencePort = [[videoFullscreenLayer context] createFencePort];
     459   
     460    WebThreadRun([strongThis, this, frame, fencePort, videoFullscreenLayer] {
     461        [CATransaction begin];
     462        [CATransaction setAnimationDuration:0];
    456463        if (m_model)
    457464            m_model->setVideoLayerFrame(frame);
     465        [[videoFullscreenLayer context] setFencePort:fencePort];
     466        mach_port_deallocate(mach_task_self(), fencePort);
     467        [CATransaction commit];
    458468    });
    459469}
     
    462472{
    463473    ASSERT(isUIThread());
    464     m_gravity = videoGravity;
    465474    RefPtr<WebVideoFullscreenControllerContext> strongThis(this);
    466475    WebThreadRun([strongThis, this, videoGravity] {
     
    511520    m_interface->setWebVideoFullscreenChangeObserver(this);
    512521    m_interface->setWebVideoFullscreenModel(this);
     522    m_videoFullscreenView = adoptNS([[getUIViewClass() alloc] init]);
    513523   
    514524    RefPtr<WebVideoFullscreenControllerContext> strongThis(this);
     
    517527        m_model->setWebVideoFullscreenInterface(this);
    518528        m_model->setVideoElement(m_videoElement.get());
    519         m_videoFullscreenLayer = [CALayer layer];
    520529       
    521530        bool allowsPictureInPicture = m_videoElement->mediaSession().allowsPictureInPicture(*m_videoElement.get());
     
    523532       
    524533        dispatch_async(dispatch_get_main_queue(), [strongThis, this, videoElementClientRect, viewRef, mode, allowsPictureInPicture] {
    525             m_interface->setupFullscreen(*m_videoFullscreenLayer.get(), videoElementClientRect, viewRef.get(), mode, allowsPictureInPicture);
     534            m_interface->setupFullscreen(*m_videoFullscreenView.get(), videoElementClientRect, viewRef.get(), mode, allowsPictureInPicture);
    526535        });
    527536    });
  • TabularUnified trunk/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.h

    r186764 r187044  
    4646OBJC_CLASS UIView;
    4747OBJC_CLASS CALayer;
    48 OBJC_CLASS WebAVVideoLayer;
    49 OBJC_CLASS WebCALayerHostWrapper;
     48OBJC_CLASS WebAVPlayerLayerView;
     49OBJC_CLASS WebAVPlayerLayer;
    5050
    5151namespace WTF {
     
    9292    WEBCORE_EXPORT virtual void setExternalPlayback(bool enabled, ExternalPlaybackTargetType, WTF::String localizedDeviceName) override;
    9393   
    94     WEBCORE_EXPORT virtual void setupFullscreen(PlatformLayer&, const IntRect& initialRect, UIView *, HTMLMediaElementEnums::VideoFullscreenMode, bool allowsPictureInPicturePlayback);
     94    WEBCORE_EXPORT virtual void setupFullscreen(UIView&, const IntRect& initialRect, UIView *, HTMLMediaElementEnums::VideoFullscreenMode, bool allowsPictureInPicturePlayback);
    9595    WEBCORE_EXPORT virtual void enterFullscreen();
    9696    WEBCORE_EXPORT virtual void exitFullscreen(const IntRect& finalRect);
     
    134134    RetainPtr<WebAVPlayerController> m_playerController;
    135135    RetainPtr<AVPlayerViewController> m_playerViewController;
    136     RetainPtr<CALayer> m_videoLayer;
    137     RetainPtr<WebAVVideoLayer> m_videoLayerContainer;
    138     RetainPtr<WebCALayerHostWrapper> m_layerHostWrapper;
    139136    WebVideoFullscreenModel* m_videoFullscreenModel { nullptr };
    140137    WebVideoFullscreenChangeObserver* m_fullscreenChangeObserver { nullptr };
     
    145142    RetainPtr<UIView> m_parentView;
    146143    RetainPtr<UIWindow> m_parentWindow;
     144    RetainPtr<WebAVPlayerLayerView> m_playerLayerView;
    147145    HTMLMediaElementEnums::VideoFullscreenMode m_mode { HTMLMediaElementEnums::VideoFullscreenModeNone };
    148146    std::function<void(bool)> m_prepareToInlineCallback;
  • TabularUnified trunk/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.mm

    r187036 r187044  
    4040#import <AVFoundation/AVTime.h>
    4141#import <UIKit/UIKit.h>
     42#import <objc/message.h>
     43#import <objc/runtime.h>
    4244#import <wtf/RetainPtr.h>
    4345#import <wtf/text/CString.h>
     
    5153SOFT_LINK_FRAMEWORK(AVFoundation)
    5254SOFT_LINK_CLASS(AVFoundation, AVPlayerLayer)
     55SOFT_LINK_CONSTANT(AVFoundation, AVLayerVideoGravityResize, NSString *)
     56SOFT_LINK_CONSTANT(AVFoundation, AVLayerVideoGravityResizeAspect, NSString *)
     57SOFT_LINK_CONSTANT(AVFoundation, AVLayerVideoGravityResizeAspectFill, NSString *)
    5358
    5459SOFT_LINK_FRAMEWORK(AVKit)
     
    5661SOFT_LINK_CLASS(AVKit, AVPlayerViewController)
    5762SOFT_LINK_CLASS(AVKit, AVValueTiming)
     63SOFT_LINK_CLASS(AVKit, AVPlayerLayerView)
     64SOFT_LINK_CLASS(AVKit, AVPictureInPicturePlayerLayerView)
    5865
    5966SOFT_LINK_FRAMEWORK(UIKit)
     
    7582@class WebAVMediaSelectionOption;
    7683
    77 @interface WebAVPlayerController : NSObject <AVPlayerViewControllerDelegate>
    78 {
     84@interface WebAVPlayerController : NSObject <AVPlayerViewControllerDelegate> {
    7985    WebAVMediaSelectionOption *_currentAudioMediaSelectionOption;
    8086    WebAVMediaSelectionOption *_currentLegibleMediaSelectionOption;
    8187}
    8288
    83 -(void)resetState;
     89- (void)resetState;
    8490
    8591@property (retain) AVPlayerController* playerControllerProxy;
     
    151157}
    152158
    153 -(void)resetState {
     159- (void)resetState
     160{
    154161    self.contentDuration = 0;
    155162    self.maxTime = 0;
     
    182189}
    183190
    184 - (AVPlayer*) player {
     191- (AVPlayer *) player
     192{
    185193    return nil;
    186194}
     
    569577@end
    570578
    571 
    572 @interface WebCALayerHostWrapper : CALayer
    573 @property (assign) WebVideoFullscreenModel* model;
     579@interface WebAVPlayerLayer : CALayer
     580@property (nonatomic, retain) NSString *videoGravity;
     581@property (nonatomic, getter=isReadyForDisplay) BOOL readyForDisplay;
     582@property (nonatomic, retain) AVPlayerController *playerController;
     583@property (nonatomic, retain) CALayer *videoSublayer;
     584@property (nonatomic, copy, nullable) NSDictionary *pixelBufferAttributes;
     585@property CGSize videoDimensions;
     586@property CGRect modelVideoLayerFrame;
    574587@end
    575588
    576 @implementation WebCALayerHostWrapper {
     589@implementation WebAVPlayerLayer {
     590    RetainPtr<WebAVPlayerController> _avPlayerController;
    577591    RetainPtr<CALayer> _videoSublayer;
    578 }
    579 
    580 - (void)dealloc
    581 {
    582     [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(resolveBounds) object:nil];
    583     [super dealloc];
    584 }
    585 
    586 - (void)setVideoSublayer:(CALayer*)videoSublayer
    587 {
    588     _videoSublayer = videoSublayer;
    589     [self addSublayer:videoSublayer];
    590 }
    591 
    592 - (CALayer*)videoSublayer
    593 {
    594     return _videoSublayer.get();
    595 }
    596 
    597 - (void)setBounds:(CGRect)bounds
    598 {
    599     if (CGRectEqualToRect(bounds, self.bounds))
    600         return;
    601 
    602     [super setBounds:bounds];
    603 
    604     [_videoSublayer setPosition:CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds))];
    605 
    606     if (!self.model)
    607         return;
    608 
    609     FloatRect videoFrame = self.model->videoLayerFrame();
    610     FloatRect targetFrame;
    611     switch (self.model->videoLayerGravity()) {
    612     case WebCore::WebVideoFullscreenModel::VideoGravityResize:
    613         targetFrame = bounds;
    614         break;
    615     case WebCore::WebVideoFullscreenModel::VideoGravityResizeAspect:
    616         targetFrame = largestRectWithAspectRatioInsideRect(videoFrame.size().aspectRatio(), bounds);
    617         break;
    618     case WebCore::WebVideoFullscreenModel::VideoGravityResizeAspectFill:
    619         targetFrame = smallestRectWithAspectRatioAroundRect(videoFrame.size().aspectRatio(), bounds);
    620         break;
    621     }
    622     CATransform3D transform = CATransform3DMakeScale(targetFrame.width() / videoFrame.width(), targetFrame.height() / videoFrame.height(), 1);
    623     [_videoSublayer setSublayerTransform:transform];
    624 
    625     [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(resolveBounds) object:nil];
    626     [self performSelector:@selector(resolveBounds) withObject:nil afterDelay:[CATransaction animationDuration] + 0.1];
    627 }
    628 
    629 - (void)resolveBounds
    630 {
    631     [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(resolveBounds) object:nil];
    632     if (!self.model)
    633         return;
    634 
    635     [CATransaction begin];
    636     [CATransaction setAnimationDuration:0];
    637 
    638     [_videoSublayer setSublayerTransform:CATransform3DIdentity];
    639     self.model->setVideoLayerFrame([self bounds]);
    640    
    641     [CATransaction commit];
    642 }
    643 @end
    644 
    645 @interface WebAVVideoLayer : CALayer <AVVideoLayer>
    646 +(WebAVVideoLayer *)videoLayer;
    647 @property (nonatomic) AVVideoLayerGravity videoLayerGravity;
    648 @property (nonatomic, getter = isReadyForDisplay) BOOL readyForDisplay;
    649 @property (nonatomic) CGRect videoRect;
    650 - (void)setPlayerViewController:(AVPlayerViewController *)playerViewController;
    651 - (void)setPlayerController:(AVPlayerController *)playerController;
    652 @property (nonatomic, retain) CALayer* videoSublayer;
    653 @end
    654 
    655 @implementation WebAVVideoLayer
    656 {
    657     RetainPtr<WebAVPlayerController> _avPlayerController;
    658     RetainPtr<AVPlayerViewController> _avPlayerViewController;
    659     RetainPtr<CALayer> _videoSublayer;
    660     AVVideoLayerGravity _videoLayerGravity;
    661 }
    662 
    663 +(WebAVVideoLayer *)videoLayer
    664 {
    665     return [[[WebAVVideoLayer alloc] init] autorelease];
     592    RetainPtr<NSString> _videoGravity;
    666593}
    667594
     
    671598    if (self) {
    672599        [self setMasksToBounds:YES];
    673         [self setVideoLayerGravity:AVVideoLayerGravityResizeAspect];
     600        _videoGravity = getAVLayerVideoGravityResizeAspect();
    674601    }
    675602    return self;
    676603}
    677604
     605- (void)dealloc
     606{
     607    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(resolveBounds) object:nil];
     608    [super dealloc];
     609}
     610
     611- (AVPlayerController *)playerController
     612{
     613    return (AVPlayerController *)_avPlayerController.get();
     614}
     615
    678616- (void)setPlayerController:(AVPlayerController *)playerController
    679617{
     
    682620}
    683621
    684 - (void)setPlayerViewController:(AVPlayerViewController *)playerViewController
    685 {
    686     _avPlayerViewController = playerViewController;
    687 }
    688 
    689622- (void)setVideoSublayer:(CALayer *)videoSublayer
    690623{
    691624    _videoSublayer = videoSublayer;
    692     [self addSublayer:videoSublayer];
    693625}
    694626
     
    700632- (void)setBounds:(CGRect)bounds
    701633{
     634    if (CGRectEqualToRect(bounds, self.bounds))
     635        return;
     636   
    702637    [super setBounds:bounds];
    703 
    704     if ([_videoSublayer superlayer] == self) {
    705         [_videoSublayer setPosition:CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds))];
    706         [_videoSublayer setBounds:bounds];
    707     }
    708 }
    709 
    710 - (void)setVideoLayerGravity:(AVVideoLayerGravity)videoLayerGravity
    711 {
    712     _videoLayerGravity = videoLayerGravity;
     638   
     639    if ([_videoSublayer superlayer] != self)
     640        return;
     641
     642    [_videoSublayer setPosition:CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds))];
    713643   
    714644    if (![_avPlayerController delegate])
    715645        return;
    716646
     647    FloatRect sourceVideoFrame;
     648    FloatRect targetVideoFrame;
     649    float videoAspectRatio = self.videoDimensions.width / self.videoDimensions.height;
     650   
     651    if ([getAVLayerVideoGravityResize() isEqualToString:self.videoGravity]) {
     652        sourceVideoFrame = self.modelVideoLayerFrame;
     653        targetVideoFrame = self.bounds;
     654    } else if ([getAVLayerVideoGravityResizeAspect() isEqualToString:self.videoGravity]) {
     655        sourceVideoFrame = largestRectWithAspectRatioInsideRect(videoAspectRatio, self.modelVideoLayerFrame);
     656        targetVideoFrame = largestRectWithAspectRatioInsideRect(videoAspectRatio, self.bounds);
     657    } else if ([getAVLayerVideoGravityResizeAspectFill() isEqualToString:self.videoGravity]) {
     658        sourceVideoFrame = smallestRectWithAspectRatioAroundRect(videoAspectRatio, self.modelVideoLayerFrame);
     659        self.modelVideoLayerFrame = CGRectMake(0, 0, sourceVideoFrame.width(), sourceVideoFrame.height());
     660        [_avPlayerController delegate]->setVideoLayerFrame(self.modelVideoLayerFrame);
     661        targetVideoFrame = smallestRectWithAspectRatioAroundRect(videoAspectRatio, self.bounds);
     662    } else
     663        ASSERT_NOT_REACHED();
     664
     665    UIView *view = [_videoSublayer delegate];
     666    CGAffineTransform transform = CGAffineTransformMakeScale(targetVideoFrame.width() / sourceVideoFrame.width(), targetVideoFrame.height() / sourceVideoFrame.height());
     667    [view setTransform:transform];
     668   
     669    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(resolveBounds) object:nil];
     670   
     671    if (!CGAffineTransformEqualToTransform(CGAffineTransformIdentity, transform))
     672        [self performSelector:@selector(resolveBounds) withObject:nil afterDelay:[CATransaction animationDuration] + 0.1];
     673}
     674
     675- (void)resolveBounds
     676{
     677    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(resolveBounds) object:nil];
     678    if (![_avPlayerController delegate])
     679        return;
     680   
     681    if ([_videoSublayer superlayer] != self)
     682        return;
     683   
     684    [CATransaction begin];
     685    [CATransaction setAnimationDuration:0];
     686   
     687    [(UIView *)[_videoSublayer delegate] setTransform:CGAffineTransformIdentity];
     688    self.modelVideoLayerFrame = [self bounds];
     689    [_avPlayerController delegate]->setVideoLayerFrame(self.modelVideoLayerFrame);
     690   
     691    [CATransaction commit];
     692}
     693
     694- (void)setVideoGravity:(NSString *)videoGravity
     695{
     696    _videoGravity = videoGravity;
     697   
     698    if (![_avPlayerController delegate])
     699        return;
     700
    717701    WebCore::WebVideoFullscreenModel::VideoGravity gravity = WebCore::WebVideoFullscreenModel::VideoGravityResizeAspect;
    718     if (videoLayerGravity == AVVideoLayerGravityResize)
     702    if (videoGravity == getAVLayerVideoGravityResize())
    719703        gravity = WebCore::WebVideoFullscreenModel::VideoGravityResize;
    720     if (videoLayerGravity == AVVideoLayerGravityResizeAspect)
     704    if (videoGravity == getAVLayerVideoGravityResizeAspect())
    721705        gravity = WebCore::WebVideoFullscreenModel::VideoGravityResizeAspect;
    722     else if (videoLayerGravity == AVVideoLayerGravityResizeAspectFill)
     706    else if (videoGravity == getAVLayerVideoGravityResizeAspectFill())
    723707        gravity = WebCore::WebVideoFullscreenModel::VideoGravityResizeAspectFill;
    724708    else
     
    728712}
    729713
    730 - (AVVideoLayerGravity)videoLayerGravity
    731 {
    732     return _videoLayerGravity;
    733 }
    734 
    735 - (void)enterPIPModeRedirectingVideoToLayer:(CALayer *)layer
    736 {
    737     [_videoSublayer removeFromSuperlayer];
    738     [layer addSublayer:_videoSublayer.get()];
    739 }
    740 
    741 - (void)leavePIPMode
    742 {
    743     [_videoSublayer removeFromSuperlayer];
    744     [self addSublayer:_videoSublayer.get()];
    745 }
     714- (NSString *)videoGravity
     715{
     716    return _videoGravity.get();
     717}
     718
     719- (CGRect)videoRect
     720{
     721    float videoAspectRatio = self.videoDimensions.width / self.videoDimensions.height;
     722   
     723    if ([getAVLayerVideoGravityResizeAspect() isEqualToString:self.videoGravity])
     724        return largestRectWithAspectRatioInsideRect(videoAspectRatio, self.bounds);
     725    if ([getAVLayerVideoGravityResizeAspectFill() isEqualToString:self.videoGravity])
     726        return smallestRectWithAspectRatioAroundRect(videoAspectRatio, self.bounds);
     727
     728    return self.bounds;
     729}
     730
     731+ (NSSet *)keyPathsForValuesAffectingVideoRect
     732{
     733    return [NSSet setWithObjects:@"videoDimensions", @"videoGravity", nil];
     734}
     735
    746736@end
     737
     738@interface WebAVPictureInPicturePlayerLayerView : AVPictureInPicturePlayerLayerView
     739@end
     740
     741static CALayer* WebAVPictureInPicturePlayerLayerView_layerClass(id, SEL)
     742{
     743    return [WebAVPlayerLayer class];
     744}
     745
     746static Class getWebAVPictureInPicturePlayerLayerViewClass()
     747{
     748    static Class theClass = nil;
     749    static dispatch_once_t onceToken;
     750    dispatch_once(&onceToken, ^{
     751        theClass = objc_allocateClassPair(getAVPictureInPicturePlayerLayerViewClass(), "WebAVPictureInPicturePlayerLayerView", 0);
     752        objc_registerClassPair(theClass);
     753        Class metaClass = objc_getMetaClass("WebAVPictureInPicturePlayerLayerView");
     754        class_addMethod(metaClass, @selector(layerClass), (IMP)WebAVPictureInPicturePlayerLayerView_layerClass, "@@:");
     755    });
     756   
     757    return theClass;
     758}
     759
     760@interface WebAVPlayerLayerView : AVPlayerLayerView
     761@property (retain) UIView* videoView;
     762@end
     763
     764static CALayer* WebAVPlayerLayerView_layerClass(id, SEL)
     765{
     766    return [WebAVPlayerLayer class];
     767}
     768
     769static AVPlayerController* WebAVPlayerLayerView_playerController(id aSelf, SEL)
     770{
     771    AVPlayerLayerView *playerLayer = aSelf;
     772    WebAVPlayerLayer *webAVPlayerLayer = (WebAVPlayerLayer *)[playerLayer playerLayer];
     773    return [webAVPlayerLayer playerController];
     774}
     775
     776static void WebAVPlayerLayerView_setPlayerController(id aSelf, SEL, AVPlayerController *playerController)
     777{
     778    AVPlayerLayerView *playerLayerView = aSelf;
     779    WebAVPlayerLayer *webAVPlayerLayer = (WebAVPlayerLayer *)[playerLayerView playerLayer];
     780    [webAVPlayerLayer setPlayerController: playerController];
     781}
     782
     783static UIView* WebAVPlayerLayerView_videoView(id aSelf, SEL)
     784{
     785    AVPlayerLayerView *playerLayer = aSelf;
     786    WebAVPlayerLayer *webAVPlayerLayer = (WebAVPlayerLayer *)[playerLayer playerLayer];
     787    CALayer* videoLayer = [webAVPlayerLayer videoSublayer];
     788    if (!videoLayer)
     789        return nil;
     790    ASSERT([[videoLayer delegate] isKindOfClass:getUIViewClass()]);
     791    return (UIView *)[videoLayer delegate];
     792}
     793
     794static void WebAVPlayerLayerView_setVideoView(id aSelf, SEL, UIView *videoView)
     795{
     796    AVPlayerLayerView *playerLayerView = aSelf;
     797    WebAVPlayerLayer *webAVPlayerLayer = (WebAVPlayerLayer *)[playerLayerView playerLayer];
     798    [webAVPlayerLayer setVideoSublayer:[videoView layer]];
     799}
     800
     801static void WebAVPlayerLayerView_startRoutingVideoToPictureInPicturePlayerLayerView(id aSelf, SEL)
     802{
     803    WebAVPlayerLayerView *playerLayerView = aSelf;
     804    AVPictureInPicturePlayerLayerView *pipView = [playerLayerView pictureInPicturePlayerLayerView];
     805
     806    WebAVPlayerLayer *playerLayer = (WebAVPlayerLayer *)[playerLayerView playerLayer];
     807    WebAVPlayerLayer *pipPlayerLayer = (WebAVPlayerLayer *)[pipView playerLayer];
     808    [playerLayer setVideoGravity:getAVLayerVideoGravityResizeAspect()];
     809    [pipPlayerLayer setVideoSublayer:playerLayer.videoSublayer];
     810    [pipPlayerLayer setVideoDimensions:playerLayer.videoDimensions];
     811    [pipPlayerLayer setVideoGravity:playerLayer.videoGravity];
     812    [pipPlayerLayer setModelVideoLayerFrame:playerLayer.modelVideoLayerFrame];
     813    [pipPlayerLayer setPlayerController:playerLayer.playerController];
     814    [pipView addSubview:playerLayerView.videoView];
     815}
     816
     817static void WebAVPlayerLayerView_stopRoutingVideoToPictureInPicturePlayerLayerView(id aSelf, SEL)
     818{
     819    WebAVPlayerLayerView *playerLayerView = aSelf;
     820    [playerLayerView addSubview:playerLayerView.videoView];
     821}
     822
     823static AVPictureInPicturePlayerLayerView *WebAVPlayerLayerView_pictureInPicturePlayerLayerView(id aSelf, SEL)
     824{
     825    WebAVPlayerLayerView *playerLayerView = aSelf;
     826    WebAVPictureInPicturePlayerLayerView *pipView = [playerLayerView valueForKey:@"_pictureInPicturePlayerLayerView"];
     827    if (!pipView) {
     828        pipView = [[getWebAVPictureInPicturePlayerLayerViewClass() alloc] initWithFrame:CGRectZero];
     829        [playerLayerView setValue:pipView forKey:@"_pictureInPicturePlayerLayerView"];
     830    }
     831    return pipView;
     832}
     833
     834static void WebAVPlayerLayerView_dealloc(id aSelf, SEL)
     835{
     836    WebAVPlayerLayerView *playerLayerView = aSelf;
     837    RetainPtr<WebAVPictureInPicturePlayerLayerView> pipView = adoptNS([playerLayerView valueForKey:@"_pictureInPicturePlayerLayerView"]);
     838    [playerLayerView setValue:nil forKey:@"_pictureInPicturePlayerLayerView"];
     839    objc_super superClass { playerLayerView, getAVPlayerLayerViewClass() };
     840    auto super_dealloc = reinterpret_cast<void(*)(objc_super*, SEL)>(objc_msgSendSuper);
     841    super_dealloc(&superClass, @selector(dealloc));
     842}
     843
     844#pragma mark - Methods
     845
     846static Class getWebAVPlayerLayerViewClass()
     847{
     848    static Class theClass = nil;
     849    static dispatch_once_t onceToken;
     850    dispatch_once(&onceToken, ^{
     851        theClass = objc_allocateClassPair(getAVPlayerLayerViewClass(), "WebAVPlayerLayerView", 0);
     852        class_addMethod(theClass, @selector(dealloc), (IMP)WebAVPlayerLayerView_dealloc, "v@:");
     853        class_addMethod(theClass, @selector(setPlayerController:), (IMP)WebAVPlayerLayerView_setPlayerController, "v@:@");
     854        class_addMethod(theClass, @selector(playerController), (IMP)WebAVPlayerLayerView_playerController, "@@:");
     855        class_addMethod(theClass, @selector(setVideoView:), (IMP)WebAVPlayerLayerView_setVideoView, "v@:@");
     856        class_addMethod(theClass, @selector(videoView), (IMP)WebAVPlayerLayerView_videoView, "@@:");
     857        class_addMethod(theClass, @selector(startRoutingVideoToPictureInPicturePlayerLayerView), (IMP)WebAVPlayerLayerView_startRoutingVideoToPictureInPicturePlayerLayerView, "v@:");
     858        class_addMethod(theClass, @selector(stopRoutingVideoToPictureInPicturePlayerLayerView), (IMP)WebAVPlayerLayerView_stopRoutingVideoToPictureInPicturePlayerLayerView, "v@:");
     859        class_addMethod(theClass, @selector(pictureInPicturePlayerLayerView), (IMP)WebAVPlayerLayerView_pictureInPicturePlayerLayerView, "@@:");
     860       
     861        class_addIvar(theClass, "_pictureInPicturePlayerLayerView", sizeof(WebAVPictureInPicturePlayerLayerView *), log2(sizeof(WebAVPictureInPicturePlayerLayerView *)), "@");
     862       
     863        objc_registerClassPair(theClass);
     864        Class metaClass = objc_getMetaClass("WebAVPlayerLayerView");
     865        class_addMethod(metaClass, @selector(layerClass), (IMP)WebAVPlayerLayerView_layerClass, "@@:");
     866    });
     867    return theClass;
     868}
    747869
    748870WebVideoFullscreenInterfaceAVKit::WebVideoFullscreenInterfaceAVKit()
     
    827949void WebVideoFullscreenInterfaceAVKit::setVideoDimensions(bool hasVideo, float width, float height)
    828950{
     951    WebAVPlayerLayer *playerLayer = (WebAVPlayerLayer *)[m_playerLayerView playerLayer];
     952
     953    [playerLayer setVideoDimensions:CGSizeMake(width, height)];
    829954    [m_playerController setHasEnabledVideo:hasVideo];
    830955    [m_playerController setContentDimensions:CGSizeMake(width, height)];
     
    8911016    playerController.externalPlaybackType = externalPlaybackType;
    8921017    playerController.externalPlaybackActive = enabled;
    893     [m_videoLayerContainer.get() setHidden:enabled];
     1018    [m_playerLayerView setHidden:enabled];
    8941019}
    8951020
    8961021@interface UIWindow ()
    897 -(BOOL)_isHostedInAnotherProcess;
     1022- (BOOL)_isHostedInAnotherProcess;
    8981023@end
    8991024
     
    9021027@end
    9031028
    904 void WebVideoFullscreenInterfaceAVKit::setupFullscreen(PlatformLayer& videoLayer, const WebCore::IntRect& initialRect, UIView* parentView, HTMLMediaElementEnums::VideoFullscreenMode mode, bool allowsPictureInPicturePlayback)
     1029void WebVideoFullscreenInterfaceAVKit::setupFullscreen(UIView& videoView, const WebCore::IntRect& initialRect, UIView* parentView, HTMLMediaElementEnums::VideoFullscreenMode mode, bool allowsPictureInPicturePlayback)
    9051030{
    9061031    ASSERT(mode != HTMLMediaElementEnums::VideoFullscreenModeNone);
     
    9111036    [CATransaction begin];
    9121037    [CATransaction setDisableActions:YES];
    913     m_videoLayer = &videoLayer;
    9141038    m_mode = mode;
    9151039    m_parentView = parentView;
     
    9261050    }
    9271051
    928     [m_videoLayer removeFromSuperlayer];
    929 
    930     m_layerHostWrapper = adoptNS([[WebCALayerHostWrapper alloc] init]);
    931     [m_layerHostWrapper setModel:m_videoFullscreenModel];
    932     [m_layerHostWrapper setVideoSublayer:m_videoLayer.get()];
    933 
    934     m_videoLayerContainer = [WebAVVideoLayer videoLayer];
    935     [m_videoLayerContainer setHidden:[m_playerController isExternalPlaybackActive]];
    936     [m_videoLayerContainer setVideoSublayer:m_layerHostWrapper.get()];
    937 
    938     CGSize videoSize = [m_playerController contentDimensions];
    939     CGRect videoRect = CGRectMake(0, 0, videoSize.width, videoSize.height);
    940     [m_videoLayerContainer setVideoRect:videoRect];
    941     if (m_videoFullscreenModel)
    942         m_videoFullscreenModel->setVideoLayerFrame(videoRect);
    943 
    944     // This method has been deprecated so ignore the warning until we port our code to the new API.
    945 #pragma clang diagnostic push
    946 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
    947     m_playerViewController = adoptNS([allocAVPlayerViewControllerInstance() initWithVideoLayer:m_videoLayerContainer.get()]);
    948 #pragma clang diagnostic pop
     1052    m_playerLayerView = adoptNS([[getWebAVPlayerLayerViewClass() alloc] init]);
     1053    [m_playerLayerView setHidden:[m_playerController isExternalPlaybackActive]];
     1054    [m_playerLayerView setBackgroundColor:[getUIColorClass() clearColor]];
     1055   
     1056    [m_playerLayerView setVideoView:&videoView];
     1057    [m_playerLayerView addSubview:&videoView];
     1058
     1059    WebAVPlayerLayer *playerLayer = (WebAVPlayerLayer *)[m_playerLayerView playerLayer];
     1060
     1061    [playerLayer setModelVideoLayerFrame:CGRectMake(0, 0, initialRect.width(), initialRect.height())];
     1062    [playerLayer setVideoDimensions:[m_playerController contentDimensions]];
     1063
     1064    m_playerViewController = adoptNS([allocAVPlayerViewControllerInstance() initWithPlayerLayerView:m_playerLayerView.get()]);
    9491065
    9501066    [m_playerViewController setShowsPlaybackControls:NO];
     
    9531069    [m_playerViewController setAllowsPictureInPicturePlayback:m_allowsPictureInPicturePlayback];
    9541070
    955     [m_videoLayerContainer setPlayerViewController:m_playerViewController.get()];
    956 
    9571071    if (m_viewController) {
    9581072        [m_viewController addChildViewController:m_playerViewController.get()];
    9591073        [[m_viewController view] addSubview:[m_playerViewController view]];
    9601074    } else
    961         [parentView.window addSubview:[m_playerViewController view]];
    962 
    963     [m_playerViewController view].frame = [parentView convertRect:initialRect toView:nil];
     1075        [parentView addSubview:[m_playerViewController view]];
     1076
     1077    [m_playerViewController view].frame = [parentView convertRect:initialRect toView:[m_playerViewController view].superview];
    9641078
    9651079    [[m_playerViewController view] setBackgroundColor:[getUIColorClass() clearColor]];
     1080    [[m_playerViewController view] setAutoresizingMask:(UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin)];
     1081
    9661082    [[m_playerViewController view] setNeedsLayout];
    9671083    [[m_playerViewController view] layoutIfNeeded];
     
    9691085    [CATransaction commit];
    9701086
    971     if (m_fullscreenChangeObserver)
    972         m_fullscreenChangeObserver->didSetupFullscreen();
     1087    RefPtr<WebVideoFullscreenInterfaceAVKit> strongThis(this);
     1088    dispatch_async(dispatch_get_main_queue(), [strongThis, this] {
     1089        if (m_fullscreenChangeObserver)
     1090            m_fullscreenChangeObserver->didSetupFullscreen();
     1091    });
    9731092}
    9741093
     
    9811100    m_enterRequested = true;
    9821101
    983     [m_videoLayerContainer setBackgroundColor:[[getUIColorClass() blackColor] CGColor]];
     1102    [m_playerLayerView setBackgroundColor:[getUIColorClass() blackColor]];
    9841103    if (mode() == HTMLMediaElementEnums::VideoFullscreenModePictureInPicture)
    9851104        enterPictureInPicture();
     
    10251144    LOG(Fullscreen, "WebVideoFullscreenInterfaceAVKit::exitFullscreen(%p)", this);
    10261145    [m_playerViewController setShowsPlaybackControls:NO];
    1027     if (m_viewController)
    1028         [m_playerViewController view].frame = [m_parentView convertRect:finalRect toView:nil];
    1029     else
    1030         [m_playerViewController view].frame = finalRect;
    1031 
    1032     if ([m_videoLayerContainer videoLayerGravity] != AVVideoLayerGravityResizeAspect)
    1033         [m_videoLayerContainer setVideoLayerGravity:AVVideoLayerGravityResizeAspect];
     1146   
     1147    [m_playerViewController view].frame = [m_parentView convertRect:finalRect toView:[m_playerViewController view].superview];
     1148
     1149    WebAVPlayerLayer *playerLayer = (WebAVPlayerLayer *)[m_playerLayerView playerLayer];
     1150    if ([playerLayer videoGravity] != getAVLayerVideoGravityResizeAspect())
     1151        [playerLayer setVideoGravity:getAVLayerVideoGravityResizeAspect()];
    10341152    [[m_playerViewController view] layoutIfNeeded];
    10351153
     
    10501168            [CATransaction begin];
    10511169            [CATransaction setDisableActions:YES];
    1052             [m_videoLayerContainer setBackgroundColor:[[getUIColorClass() clearColor] CGColor]];
     1170            [m_playerLayerView setBackgroundColor:[getUIColorClass() clearColor]];
    10531171            [[m_playerViewController view] setBackgroundColor:[getUIColorClass() clearColor]];
    10541172            [CATransaction commit];
    10551173
    1056             if (m_fullscreenChangeObserver)
    1057                 m_fullscreenChangeObserver->didExitFullscreen();
     1174            dispatch_async(dispatch_get_main_queue(), ^{
     1175                if (m_fullscreenChangeObserver)
     1176                    m_fullscreenChangeObserver->didExitFullscreen();
     1177            });
    10581178        }];
    10591179    };
     
    10611181
    10621182@interface UIApplication ()
    1063 -(void)_setStatusBarOrientation:(UIInterfaceOrientation)o;
     1183- (void)_setStatusBarOrientation:(UIInterfaceOrientation)o;
    10641184@end
    10651185
    10661186@interface UIWindow ()
    1067 -(UIInterfaceOrientation)interfaceOrientation;
     1187- (UIInterfaceOrientation)interfaceOrientation;
    10681188@end
    10691189
     
    10931213        [m_playerViewController removeFromParentViewController];
    10941214   
    1095     [m_videoLayer removeFromSuperlayer];
    1096     [m_videoLayerContainer removeFromSuperlayer];
    1097     [m_videoLayerContainer setPlayerViewController:nil];
     1215    [m_playerLayerView removeFromSuperview];
    10981216    [[m_viewController view] removeFromSuperview];
    10991217
    1100     [m_layerHostWrapper setModel:nullptr];
    1101 
    1102     m_layerHostWrapper = nil;
    1103     m_videoLayer = nil;
    1104     m_videoLayerContainer = nil;
     1218    m_playerLayerView = nil;
    11051219    m_playerViewController = nil;
    11061220    m_playerController = nil;
     
    11481262    if (m_prepareToInlineCallback) {
    11491263       
    1150         [m_playerViewController view].frame = [m_parentView convertRect:inlineRect toView:nil];
     1264        [m_playerViewController view].frame = [m_parentView convertRect:inlineRect toView:[m_playerViewController view].superview];
    11511265
    11521266        std::function<void(bool)> callback = WTF::move(m_prepareToInlineCallback);
     
    12191333    m_exitCompleted = true;
    12201334
    1221     [m_videoLayerContainer setBackgroundColor:[[getUIColorClass() clearColor] CGColor]];
     1335    [m_playerLayerView setBackgroundColor:[getUIColorClass() clearColor]];
    12221336    [[m_playerViewController view] setBackgroundColor:[getUIColorClass() clearColor]];
    12231337
  • TabularUnified trunk/Source/WebCore/platform/ios/WebVideoFullscreenModel.h

    r184670 r187044  
    4949    virtual void requestExitFullscreen() = 0;
    5050    virtual void setVideoLayerFrame(FloatRect) = 0;
    51     virtual FloatRect videoLayerFrame() const = 0;
    5251    enum VideoGravity { VideoGravityResize, VideoGravityResizeAspect, VideoGravityResizeAspectFill };
    5352    virtual void setVideoLayerGravity(VideoGravity) = 0;
    54     virtual VideoGravity videoLayerGravity() const = 0;
    5553    virtual void selectAudioMediaOption(uint64_t index) = 0;
    5654    virtual void selectLegibleMediaOption(uint64_t index) = 0;
  • TabularUnified trunk/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.h

    r184670 r187044  
    7373    WEBCORE_EXPORT virtual void requestExitFullscreen() override;
    7474    WEBCORE_EXPORT virtual void setVideoLayerFrame(FloatRect) override;
    75     WEBCORE_EXPORT virtual FloatRect videoLayerFrame() const override;
    7675    WEBCORE_EXPORT virtual void setVideoLayerGravity(VideoGravity) override;
    77     WEBCORE_EXPORT virtual VideoGravity videoLayerGravity() const override;
    7876    WEBCORE_EXPORT virtual void selectAudioMediaOption(uint64_t index) override;
    7977    WEBCORE_EXPORT virtual void selectLegibleMediaOption(uint64_t index) override;
  • TabularUnified trunk/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.mm

    r185726 r187044  
    255255}
    256256
    257 FloatRect WebVideoFullscreenModelVideoElement::videoLayerFrame() const
    258 {
    259     return m_videoFrame;
    260 }
    261 
    262257void WebVideoFullscreenModelVideoElement::setVideoLayerGravity(WebVideoFullscreenModel::VideoGravity gravity)
    263258{
     
    273268   
    274269    m_videoElement->setVideoFullscreenGravity(videoGravity);
    275 }
    276 
    277 WebVideoFullscreenModel::VideoGravity WebVideoFullscreenModelVideoElement::videoLayerGravity() const
    278 {
    279     switch (m_videoElement->videoFullscreenGravity()) {
    280     case MediaPlayer::VideoGravityResize:
    281         return VideoGravityResize;
    282     case MediaPlayer::VideoGravityResizeAspect:
    283         return VideoGravityResizeAspect;
    284     case MediaPlayer::VideoGravityResizeAspectFill:
    285         return VideoGravityResizeAspectFill;
    286     }
    287 
    288     ASSERT_NOT_REACHED();
    289     return VideoGravityResize;
    290270}
    291271
  • TabularUnified trunk/Source/WebCore/platform/spi/cocoa/AVKitSPI.h

    r185834 r187044  
    3535
    3636#import <AVKit/AVPlayerController.h>
     37#pragma clang diagnostic push
     38#pragma clang diagnostic ignored "-Wobjc-property-no-attribute"
     39#import <AVKit/AVPlayerLayerView.h>
     40#pragma clang diagnostic pop
    3741#import <AVKit/AVPlayerViewController_Private.h>
    3842#import <AVKit/AVPlayerViewController_WebKitOnly.h>
    39 #import <AVKit/AVVideoLayer.h>
    4043
    4144#else
     
    5962@end
    6063
    61 @protocol AVVideoLayer
    62 typedef NS_ENUM(NSInteger, AVVideoLayerGravity) {
    63     AVVideoLayerGravityInvalid = 0,
    64     AVVideoLayerGravityResizeAspect = 1,
    65     AVVideoLayerGravityResizeAspectFill = 2,
    66     AVVideoLayerGravityResize = 3,
    67 };
    68 - (void)setPlayerController:(AVPlayerController *)playerController;
    69 @property (nonatomic) AVVideoLayerGravity videoLayerGravity;
    70 @property (nonatomic) CGRect videoRect;
    71 @property (nonatomic, readonly, getter=isReadyForDisplay) BOOL readyForDisplay;
     64@class AVPlayerLayer;
     65
     66@interface AVPictureInPicturePlayerLayerView : UIView
     67@property (nonatomic, readonly) AVPlayerLayer *playerLayer;
     68@end
     69
     70@interface AVPlayerLayerView : UIView
     71@property (nonatomic, readonly) AVPlayerLayer *playerLayer;
     72@property (nonatomic, readonly) AVPictureInPicturePlayerLayerView *pictureInPicturePlayerLayerView;
     73- (void)startRoutingVideoToPictureInPicturePlayerLayerView;
     74- (void)stopRoutingVideoToPictureInPicturePlayerLayerView;
    7275@end
    7376
     
    8689
    8790@interface AVPlayerViewController (Details)
    88 - (instancetype)initWithVideoLayer:(CALayer <AVVideoLayer> *)videoLayer;
     91- (instancetype)initWithPlayerLayerView:(AVPlayerLayerView *)playerLayerView;
    8992- (void)enterFullScreenAnimated:(BOOL)animated completionHandler:(void (^)(BOOL success, NSError *))completionHandler;
    9093- (void)exitFullScreenAnimated:(BOOL)animated completionHandler:(void (^)(BOOL success, NSError *))completionHandler;
     
    9396- (void)startPictureInPicture;
    9497- (void)stopPictureInPicture;
    95 - (void)setAllowsPictureInPicturePlayback:(BOOL)allow;
    9698
     99@property (nonatomic) BOOL allowsPictureInPicturePlayback;
    97100@property (nonatomic, strong) AVPlayerController *playerController;
    98101@property (nonatomic, weak) id <AVPlayerViewControllerDelegate> delegate;
  • TabularUnified trunk/Source/WebCore/platform/spi/cocoa/QuartzCoreSPI.h

    r186879 r187044  
    3333
    3434#ifdef __OBJC__
     35#import <QuartzCore/CALayerHost.h>
    3536#import <QuartzCore/CALayerPrivate.h>
    3637
     
    135136@end
    136137#endif
     138
     139@interface CALayerHost : CALayer
     140@property uint32_t contextId;
     141@property BOOL inheritsSecurity;
     142@end
     143
    137144#endif // __OBJC__
    138145
  • TabularUnified trunk/Source/WebKit2/ChangeLog

    r187039 r187044  
     12015-07-20  Jeremy Jones  <jeremyj@apple.com>
     2
     3        Adopt AVPlayerLayerView
     4        https://bugs.webkit.org/show_bug.cgi?id=146862
     5
     6        Reviewed by Simon Fraser.
     7
     8        The CALayerHost is replaced with WebLayerHostView to be compatible with UIView animations.
     9        videoLayerFrame and videoLayerGravity no longer need to be stored because they are stored
     10        where they are used in the interface. Some animation is improved in the conversion.
     11
     12        * UIProcess/ios/WebVideoFullscreenManagerProxy.h:
     13        * UIProcess/ios/WebVideoFullscreenManagerProxy.mm:
     14        (+[WebLayerHostView layerClass]): Add class WebLayerHostView.
     15        (-[WebLayerHostView contextID]):
     16        (-[WebLayerHostView setContextID:]):
     17        (-[WebLayerHostView layerHost]):
     18        (WebKit::WebVideoFullscreenManagerProxy::invalidate): layer -> view
     19        (WebKit::WebVideoFullscreenManagerProxy::setupFullscreenWithID):
     20        Apply the hostingDeviceScaleFactor transform to -sublayerTransform instead of to
     21        -transform. This more directly inverts the tranform WebProcess and allows -transform
     22        to be used for animation in the UIProcess. This is important because UIView's actions
     23        animate -transform, but not -sublayerTrasform.
     24
     25        (WebKit::WebVideoFullscreenManagerProxy::didCleanupFullscreen): layer -> view
     26        (WebKit::WebVideoFullscreenModelContext::setVideoLayerFrame): Deleted.
     27        (WebKit::WebVideoFullscreenModelContext::videoLayerFrame): Deleted.
     28        (WebKit::WebVideoFullscreenModelContext::setVideoLayerGravity): Deleted.
     29        (WebKit::WebVideoFullscreenModelContext::videoLayerGravity): Deleted.
     30        * WebProcess/ios/WebVideoFullscreenManager.mm:
     31        (WebKit::WebVideoFullscreenManager::enterVideoFullscreenForVideoElement):
     32        Set initial video layer frame to fix start point of animation.
     33
     34        (WebKit::WebVideoFullscreenManager::didSetupFullscreen):
     35        dispatch_async allows the CATransaction to complete before continuing with the animation.
     36        This prevents a flash during animation.
     37
    1382015-07-20  Tim Horton  <timothy_horton@apple.com>
    239
  • TabularUnified trunk/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.h

    r186067 r187044  
    5454    void invalidate() { m_manager = nullptr; }
    5555
    56     PlatformLayer* layerHost() const { return m_layerHost.get(); }
    57     void setLayerHost(RetainPtr<PlatformLayer>&& layerHost) { m_layerHost = WTF::move(layerHost); }
    58 
    59     void setInitialVideoLayerFrame(WebCore::FloatRect frame) { m_videoLayerFrame = frame; }
     56    UIView *layerHostView() const { return m_layerHostView.get(); }
     57    void setLayerHostView(RetainPtr<UIView>&& layerHostView) { m_layerHostView = WTF::move(layerHostView); }
    6058
    6159private:
     
    7977    virtual void requestExitFullscreen() override;
    8078    virtual void setVideoLayerFrame(WebCore::FloatRect) override;
    81     virtual WebCore::FloatRect videoLayerFrame() const override;
    8279    virtual void setVideoLayerGravity(VideoGravity) override;
    83     virtual VideoGravity videoLayerGravity() const override;
    8480    virtual void selectAudioMediaOption(uint64_t) override;
    8581    virtual void selectLegibleMediaOption(uint64_t) override;
     
    9591    WebVideoFullscreenManagerProxy* m_manager;
    9692    uint64_t m_contextId;
    97     RetainPtr<PlatformLayer> m_layerHost;
    98     WebCore::FloatRect m_videoLayerFrame;
    99     VideoGravity m_videoLayerGravity { VideoGravityResize };
     93    RetainPtr<UIView *> m_layerHostView;
    10094};
    10195
  • TabularUnified trunk/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.mm

    r186067 r187044  
    3636#import "WebVideoFullscreenManagerProxyMessages.h"
    3737#import <QuartzCore/CoreAnimation.h>
     38#import <WebCore/QuartzCoreSPI.h>
    3839#import <WebCore/TimeRanges.h>
    3940#import <WebKitSystemInterface.h>
    4041
     42@interface WebLayerHostView : UIView
     43@property (nonatomic, assign) uint32_t contextID;
     44@end
     45
     46@implementation WebLayerHostView
     47
     48+ (Class)layerClass {
     49    return [CALayerHost class];
     50}
     51
     52- (uint32_t)contextID {
     53    return [[self layerHost] contextId];
     54}
     55
     56- (void)setContextID:(uint32_t)contextID {
     57    [[self layerHost] setContextId:contextID];
     58}
     59
     60- (CALayerHost *)layerHost {
     61    return (CALayerHost *)[self layer];
     62}
     63
     64@end
     65
    4166using namespace WebCore;
    4267
     
    140165void WebVideoFullscreenModelContext::setVideoLayerFrame(WebCore::FloatRect frame)
    141166{
    142     m_videoLayerFrame = frame;
    143167    if (m_manager)
    144168        m_manager->setVideoLayerFrame(m_contextId, frame);
    145169}
    146170
    147 WebCore::FloatRect WebVideoFullscreenModelContext::videoLayerFrame() const
    148 {
    149     return m_videoLayerFrame;
    150 }
    151 
    152171void WebVideoFullscreenModelContext::setVideoLayerGravity(WebCore::WebVideoFullscreenModel::VideoGravity gravity)
    153172{
    154     m_videoLayerGravity = gravity;
    155173    if (m_manager)
    156174        m_manager->setVideoLayerGravity(m_contextId, gravity);
    157 }
    158 
    159 WebCore::WebVideoFullscreenModel::VideoGravity WebVideoFullscreenModelContext::videoLayerGravity() const
    160 {
    161     return m_videoLayerGravity;
    162175}
    163176
     
    241254
    242255        interface->invalidate();
    243         [model->layerHost() removeFromSuperlayer];
    244         model->setLayerHost(nullptr);
     256        [model->layerHostView() removeFromSuperview];
     257        model->setLayerHostView(nullptr);
    245258    }
    246259
     
    311324    std::tie(model, interface) = ensureModelAndInterface(contextId);
    312325
    313     model->setInitialVideoLayerFrame(initialRect);
    314     model->setLayerHost(WKMakeRenderLayer(videoLayerID));
     326    RetainPtr<WebLayerHostView> view = adoptNS([[WebLayerHostView alloc] init]);
     327    [view setContextID:videoLayerID];
     328    model->setLayerHostView(view);
    315329    if (hostingDeviceScaleFactor != 1) {
    316330        // Invert the scale transform added in the WebProcess to fix <rdar://problem/18316542>.
    317331        float inverseScale = 1 / hostingDeviceScaleFactor;
    318         [model->layerHost() setTransform:CATransform3DMakeScale(inverseScale, inverseScale, 1)];
     332        [[model->layerHostView() layer] setSublayerTransform:CATransform3DMakeScale(inverseScale, inverseScale, 1)];
    319333    }
    320334
    321335    UIView *parentView = downcast<RemoteLayerTreeDrawingAreaProxy>(*m_page->drawingArea()).remoteLayerTreeHost().rootLayer();
    322     interface->setupFullscreen(*model->layerHost(), initialRect, parentView, videoFullscreenMode, allowsPictureInPicture);
     336    interface->setupFullscreen(*model->layerHostView(), initialRect, parentView, videoFullscreenMode, allowsPictureInPicture);
    323337}
    324338
     
    503517
    504518    [CATransaction flush];
    505     [model.layerHost() removeFromSuperlayer];
    506     model.setLayerHost(nullptr);
     519    [model.layerHostView() removeFromSuperview];
     520    model.setLayerHostView(nullptr);
    507521    m_page->send(Messages::WebVideoFullscreenManager::DidCleanupFullscreen(contextId), m_page->pageID());
    508522
  • TabularUnified trunk/Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.mm

    r186566 r187044  
    233233    std::tie(model, interface) = ensureModelAndInterface(contextId);
    234234
     235    FloatRect clientRect = clientRectForElement(&videoElement);
     236    FloatRect videoLayerFrame = FloatRect(0, 0, clientRect.width(), clientRect.height());
     237   
    235238    interface->setTargetIsFullscreen(true);
    236239    interface->setFullscreenMode(mode);
    237240    model->setVideoElement(&videoElement);
     241    model->setVideoLayerFrame(videoLayerFrame);
    238242
    239243    if (interface->isAnimating())
     
    429433    [CATransaction commit];
    430434
    431     m_page->send(Messages::WebVideoFullscreenManagerProxy::EnterFullscreen(contextId), m_page->pageID());
     435    RefPtr<WebVideoFullscreenManager> strongThis(this);
     436    dispatch_async(dispatch_get_main_queue(), [strongThis, this, contextId] {
     437        m_page->send(Messages::WebVideoFullscreenManagerProxy::EnterFullscreen(contextId), m_page->pageID());
     438    });
    432439}
    433440   
Note: See TracChangeset for help on using the changeset viewer.