Diff
Modified: trunk/Source/WebCore/ChangeLog (187043 => 187044)
--- trunk/Source/WebCore/ChangeLog 2015-07-20 23:26:04 UTC (rev 187043)
+++ trunk/Source/WebCore/ChangeLog 2015-07-20 23:27:49 UTC (rev 187044)
@@ -1,3 +1,117 @@
+2015-07-20 Jeremy Jones <jere...@apple.com>
+
+ 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 Anders Carlsson <ander...@apple.com>
Add PLATFORM #ifdefs for Mac SPI headers
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm (187043 => 187044)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm 2015-07-20 23:26:04 UTC (rev 187043)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm 2015-07-20 23:27:49 UTC (rev 187044)
@@ -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: trunk/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm (187043 => 187044)
--- trunk/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm 2015-07-20 23:26:04 UTC (rev 187043)
+++ trunk/Source/WebCore/platform/ios/WebVideoFullscreenControllerAVKit.mm 2015-07-20 23:27:49 UTC (rev 187044)
@@ -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: trunk/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.h (187043 => 187044)
--- trunk/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.h 2015-07-20 23:26:04 UTC (rev 187043)
+++ trunk/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.h 2015-07-20 23:27:49 UTC (rev 187044)
@@ -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: trunk/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.mm (187043 => 187044)
--- trunk/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.mm 2015-07-20 23:26:04 UTC (rev 187043)
+++ trunk/Source/WebCore/platform/ios/WebVideoFullscreenInterfaceAVKit.mm 2015-07-20 23:27:49 UTC (rev 187044)
@@ -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,18 +1015,18 @@
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
@interface UIViewController ()
@property (nonatomic, assign, setter=_setIgnoreAppSupportedOrientations:) BOOL _ignoreAppSupportedOrientations;
@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);
@@ -910,7 +1035,6 @@
[CATransaction begin];
[CATransaction setDisableActions:YES];
- m_videoLayer = &videoLayer;
m_mode = mode;
m_parentView = parentView;
m_parentWindow = parentView.window;
@@ -925,51 +1049,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()
@@ -980,7 +1099,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)
@@ -1024,13 +1143,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)) {
@@ -1049,22 +1167,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()
@@ -1092,16 +1212,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;
@@ -1147,7 +1261,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);
@@ -1218,7 +1332,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: trunk/Source/WebCore/platform/ios/WebVideoFullscreenModel.h (187043 => 187044)
--- trunk/Source/WebCore/platform/ios/WebVideoFullscreenModel.h 2015-07-20 23:26:04 UTC (rev 187043)
+++ trunk/Source/WebCore/platform/ios/WebVideoFullscreenModel.h 2015-07-20 23:27:49 UTC (rev 187044)
@@ -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: trunk/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.h (187043 => 187044)
--- trunk/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.h 2015-07-20 23:26:04 UTC (rev 187043)
+++ trunk/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.h 2015-07-20 23:27:49 UTC (rev 187044)
@@ -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: trunk/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.mm (187043 => 187044)
--- trunk/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.mm 2015-07-20 23:26:04 UTC (rev 187043)
+++ trunk/Source/WebCore/platform/ios/WebVideoFullscreenModelVideoElement.mm 2015-07-20 23:27:49 UTC (rev 187044)
@@ -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: trunk/Source/WebCore/platform/spi/cocoa/AVKitSPI.h (187043 => 187044)
--- trunk/Source/WebCore/platform/spi/cocoa/AVKitSPI.h 2015-07-20 23:26:04 UTC (rev 187043)
+++ trunk/Source/WebCore/platform/spi/cocoa/AVKitSPI.h 2015-07-20 23:27:49 UTC (rev 187044)
@@ -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: trunk/Source/WebCore/platform/spi/cocoa/QuartzCoreSPI.h (187043 => 187044)
--- trunk/Source/WebCore/platform/spi/cocoa/QuartzCoreSPI.h 2015-07-20 23:26:04 UTC (rev 187043)
+++ trunk/Source/WebCore/platform/spi/cocoa/QuartzCoreSPI.h 2015-07-20 23:27:49 UTC (rev 187044)
@@ -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: trunk/Source/WebKit2/ChangeLog (187043 => 187044)
--- trunk/Source/WebKit2/ChangeLog 2015-07-20 23:26:04 UTC (rev 187043)
+++ trunk/Source/WebKit2/ChangeLog 2015-07-20 23:27:49 UTC (rev 187044)
@@ -1,3 +1,40 @@
+2015-07-20 Jeremy Jones <jere...@apple.com>
+
+ 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 Tim Horton <timothy_hor...@apple.com>
REGRESSION (r174287): Flash of black when opening a new web view or navigating to a new page
Modified: trunk/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.h (187043 => 187044)
--- trunk/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.h 2015-07-20 23:26:04 UTC (rev 187043)
+++ trunk/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.h 2015-07-20 23:27:49 UTC (rev 187044)
@@ -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: trunk/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.mm (187043 => 187044)
--- trunk/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.mm 2015-07-20 23:26:04 UTC (rev 187043)
+++ trunk/Source/WebKit2/UIProcess/ios/WebVideoFullscreenManagerProxy.mm 2015-07-20 23:27:49 UTC (rev 187044)
@@ -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: trunk/Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.mm (187043 => 187044)
--- trunk/Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.mm 2015-07-20 23:26:04 UTC (rev 187043)
+++ trunk/Source/WebKit2/WebProcess/ios/WebVideoFullscreenManager.mm 2015-07-20 23:27:49 UTC (rev 187044)
@@ -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)