/* * Copyright (C) 2016-2018 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "config.h" #import "VideoLayerManagerObjC.h" #import "Color.h" #import "Logging.h" #import "TextTrackRepresentation.h" #import "WebCoreCALayerExtras.h" #import "WebVideoContainerLayer.h" #import #import #import #import #import #import #import OBJC_CLASS AVPlayerLayer; namespace WebCore { #if !RELEASE_LOG_DISABLED VideoLayerManagerObjC::VideoLayerManagerObjC(const Logger& logger, const void* logIdentifier) : m_logger(logger) , m_logIdentifier(logIdentifier) { } #endif VideoLayerManagerObjC::~VideoLayerManagerObjC() { } PlatformLayer* VideoLayerManagerObjC::videoInlineLayer() const { return m_videoInlineLayer.get(); } void VideoLayerManagerObjC::setVideoLayer(PlatformLayer *videoLayer, IntSize contentSize) { ALWAYS_LOG(LOGIDENTIFIER, contentSize.width(), ", ", contentSize.height()); m_videoLayer = videoLayer; [m_videoLayer web_disableAllActions]; m_videoInlineLayer = adoptNS([[WebVideoContainerLayer alloc] init]); [m_videoInlineLayer setName:@"WebVideoContainerLayer"]; [m_videoInlineLayer setFrame:CGRectMake(0, 0, contentSize.width(), contentSize.height())]; [m_videoInlineLayer setContentsGravity:kCAGravityResizeAspect]; if (PAL::isAVFoundationFrameworkAvailable() && [videoLayer isKindOfClass:PAL::getAVPlayerLayerClass()]) [m_videoInlineLayer setPlayerLayer:(AVPlayerLayer *)videoLayer]; #if ENABLE(VIDEO_PRESENTATION_MODE) if (m_videoFullscreenLayer) { [m_videoLayer setFrame:m_videoFullscreenFrame]; [m_videoFullscreenLayer insertSublayer:m_videoLayer.get() atIndex:0]; } else #endif { [m_videoLayer setFrame:m_videoInlineLayer.get().bounds]; [m_videoInlineLayer insertSublayer:m_videoLayer.get() atIndex:0]; } } void VideoLayerManagerObjC::didDestroyVideoLayer() { ALWAYS_LOG(LOGIDENTIFIER); #if ENABLE(VIDEO_PRESENTATION_MODE) setTextTrackRepresentationLayer(nil); #endif [m_videoLayer removeFromSuperlayer]; m_videoInlineLayer = nil; m_videoLayer = nil; } #if ENABLE(VIDEO_PRESENTATION_MODE) PlatformLayer* VideoLayerManagerObjC::videoFullscreenLayer() const { return m_videoFullscreenLayer.get(); } void VideoLayerManagerObjC::setVideoFullscreenLayer(PlatformLayer *videoFullscreenLayer, WTF::Function&& completionHandler, PlatformImagePtr currentImage) { if (m_videoFullscreenLayer == videoFullscreenLayer) { completionHandler(); return; } ALWAYS_LOG(LOGIDENTIFIER); m_videoFullscreenLayer = videoFullscreenLayer; [CATransaction begin]; [CATransaction setDisableActions:YES]; if (m_videoLayer) { CAContext *oldContext = [m_videoLayer context]; if (m_videoInlineLayer && currentImage) [m_videoInlineLayer setContents:(__bridge id)currentImage.get()]; if (m_videoFullscreenLayer) { [m_videoLayer setFrame:m_videoFullscreenFrame]; [m_videoFullscreenLayer insertSublayer:m_videoLayer.get() atIndex:0]; } else if (m_videoInlineLayer) { [m_videoLayer setFrame:[m_videoInlineLayer bounds]]; [m_videoInlineLayer insertSublayer:m_videoLayer.get() atIndex:0]; } else [m_videoLayer removeFromSuperlayer]; CAContext *newContext = [m_videoLayer context]; if (oldContext && newContext && oldContext != newContext) { #if PLATFORM(MAC) oldContext.commitPriority = 0; newContext.commitPriority = 1; #endif auto fencePort = MachSendRight::adopt([oldContext createFencePort]); [newContext setFencePort:fencePort.sendRight()]; } } [CATransaction setCompletionBlock:makeBlockPtr([completionHandler = WTFMove(completionHandler)] { completionHandler(); }).get()]; [CATransaction commit]; } FloatRect VideoLayerManagerObjC::videoFullscreenFrame() const { return m_videoFullscreenFrame; } void VideoLayerManagerObjC::setVideoFullscreenFrame(FloatRect videoFullscreenFrame) { ALWAYS_LOG(LOGIDENTIFIER, videoFullscreenFrame.x(), ", ", videoFullscreenFrame.y(), ", ", videoFullscreenFrame.width(), ", ", videoFullscreenFrame.height()); m_videoFullscreenFrame = videoFullscreenFrame; if (!m_videoFullscreenLayer) return; [m_videoLayer setFrame:m_videoFullscreenFrame]; syncTextTrackBounds(); } void VideoLayerManagerObjC::updateVideoFullscreenInlineImage(PlatformImagePtr image) { if (m_videoInlineLayer) [m_videoInlineLayer setContents:(__bridge id)image.get()]; } #endif bool VideoLayerManagerObjC::requiresTextTrackRepresentation() const { #if ENABLE(VIDEO_PRESENTATION_MODE) return m_videoFullscreenLayer; #else return false; #endif } void VideoLayerManagerObjC::syncTextTrackBounds() { #if ENABLE(VIDEO_PRESENTATION_MODE) if (!m_videoFullscreenLayer || !m_textTrackRepresentationLayer) return; if (m_textTrackRepresentationLayer.get().bounds == m_videoFullscreenFrame) return; [CATransaction begin]; [CATransaction setDisableActions:YES]; [m_textTrackRepresentationLayer setFrame:m_videoFullscreenFrame]; [CATransaction commit]; #endif } void VideoLayerManagerObjC::setTextTrackRepresentationLayer(PlatformLayer* representationLayer) { #if !ENABLE(VIDEO_PRESENTATION_MODE) UNUSED_PARAM(representationLayer); #else ALWAYS_LOG(LOGIDENTIFIER); if (representationLayer == m_textTrackRepresentationLayer) { syncTextTrackBounds(); return; } [CATransaction begin]; [CATransaction setDisableActions:YES]; if (m_textTrackRepresentationLayer) [m_textTrackRepresentationLayer removeFromSuperlayer]; m_textTrackRepresentationLayer = representationLayer; if (m_videoFullscreenLayer && m_textTrackRepresentationLayer) { syncTextTrackBounds(); [m_videoFullscreenLayer addSublayer:m_textTrackRepresentationLayer.get()]; } [CATransaction commit]; #endif } WTFLogChannel& VideoLayerManagerObjC::logChannel() const { return LogMedia; } }