12bde8e466a4451c7319e3a072d118917957d6554Steve Block/* 22bde8e466a4451c7319e3a072d118917957d6554Steve Block * Copyright (C) 2011 Apple Inc. All rights reserved. 32bde8e466a4451c7319e3a072d118917957d6554Steve Block * 42bde8e466a4451c7319e3a072d118917957d6554Steve Block * Redistribution and use in source and binary forms, with or without 52bde8e466a4451c7319e3a072d118917957d6554Steve Block * modification, are permitted provided that the following conditions 62bde8e466a4451c7319e3a072d118917957d6554Steve Block * are met: 72bde8e466a4451c7319e3a072d118917957d6554Steve Block * 1. Redistributions of source code must retain the above copyright 82bde8e466a4451c7319e3a072d118917957d6554Steve Block * notice, this list of conditions and the following disclaimer. 92bde8e466a4451c7319e3a072d118917957d6554Steve Block * 2. Redistributions in binary form must reproduce the above copyright 102bde8e466a4451c7319e3a072d118917957d6554Steve Block * notice, this list of conditions and the following disclaimer in the 112bde8e466a4451c7319e3a072d118917957d6554Steve Block * documentation and/or other materials provided with the distribution. 122bde8e466a4451c7319e3a072d118917957d6554Steve Block * 132bde8e466a4451c7319e3a072d118917957d6554Steve Block * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 142bde8e466a4451c7319e3a072d118917957d6554Steve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 152bde8e466a4451c7319e3a072d118917957d6554Steve Block * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 162bde8e466a4451c7319e3a072d118917957d6554Steve Block * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 172bde8e466a4451c7319e3a072d118917957d6554Steve Block * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 182bde8e466a4451c7319e3a072d118917957d6554Steve Block * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 192bde8e466a4451c7319e3a072d118917957d6554Steve Block * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 202bde8e466a4451c7319e3a072d118917957d6554Steve Block * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 212bde8e466a4451c7319e3a072d118917957d6554Steve Block * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 222bde8e466a4451c7319e3a072d118917957d6554Steve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 232bde8e466a4451c7319e3a072d118917957d6554Steve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 242bde8e466a4451c7319e3a072d118917957d6554Steve Block */ 252bde8e466a4451c7319e3a072d118917957d6554Steve Block 262bde8e466a4451c7319e3a072d118917957d6554Steve Block#import "config.h" 272bde8e466a4451c7319e3a072d118917957d6554Steve Block 282bde8e466a4451c7319e3a072d118917957d6554Steve Block#if ENABLE(VIDEO) && USE(AVFOUNDATION) 292bde8e466a4451c7319e3a072d118917957d6554Steve Block 302bde8e466a4451c7319e3a072d118917957d6554Steve Block#import "MediaPlayerPrivateAVFoundationObjC.h" 312bde8e466a4451c7319e3a072d118917957d6554Steve Block 322bde8e466a4451c7319e3a072d118917957d6554Steve Block#import "ApplicationCacheResource.h" 332bde8e466a4451c7319e3a072d118917957d6554Steve Block#import "BlockExceptions.h" 342bde8e466a4451c7319e3a072d118917957d6554Steve Block#import "FloatConversion.h" 352bde8e466a4451c7319e3a072d118917957d6554Steve Block#import "FrameView.h" 362bde8e466a4451c7319e3a072d118917957d6554Steve Block#import "FloatConversion.h" 372bde8e466a4451c7319e3a072d118917957d6554Steve Block#import "GraphicsContext.h" 382bde8e466a4451c7319e3a072d118917957d6554Steve Block#import "KURL.h" 392bde8e466a4451c7319e3a072d118917957d6554Steve Block#import "Logging.h" 402bde8e466a4451c7319e3a072d118917957d6554Steve Block#import "SoftLinking.h" 412bde8e466a4451c7319e3a072d118917957d6554Steve Block#import "TimeRanges.h" 422bde8e466a4451c7319e3a072d118917957d6554Steve Block#import "WebCoreSystemInterface.h" 432bde8e466a4451c7319e3a072d118917957d6554Steve Block#import <objc/objc-runtime.h> 442bde8e466a4451c7319e3a072d118917957d6554Steve Block#import <wtf/UnusedParam.h> 452bde8e466a4451c7319e3a072d118917957d6554Steve Block 462bde8e466a4451c7319e3a072d118917957d6554Steve Block#import <CoreMedia/CoreMedia.h> 472bde8e466a4451c7319e3a072d118917957d6554Steve Block#import <AVFoundation/AVFoundation.h> 482bde8e466a4451c7319e3a072d118917957d6554Steve Block 492bde8e466a4451c7319e3a072d118917957d6554Steve BlockSOFT_LINK_FRAMEWORK(AVFoundation) 502bde8e466a4451c7319e3a072d118917957d6554Steve BlockSOFT_LINK_FRAMEWORK(CoreMedia) 512bde8e466a4451c7319e3a072d118917957d6554Steve Block 522bde8e466a4451c7319e3a072d118917957d6554Steve BlockSOFT_LINK(CoreMedia, CMTimeCompare, int32_t, (CMTime time1, CMTime time2), (time1, time2)) 532bde8e466a4451c7319e3a072d118917957d6554Steve BlockSOFT_LINK(CoreMedia, CMTimeMakeWithSeconds, CMTime, (Float64 seconds, int32_t preferredTimeScale), (seconds, preferredTimeScale)) 542bde8e466a4451c7319e3a072d118917957d6554Steve BlockSOFT_LINK(CoreMedia, CMTimeGetSeconds, Float64, (CMTime time), (time)) 552bde8e466a4451c7319e3a072d118917957d6554Steve BlockSOFT_LINK(CoreMedia, CMTimeRangeGetEnd, CMTime, (CMTimeRange range), (range)) 562bde8e466a4451c7319e3a072d118917957d6554Steve Block 572bde8e466a4451c7319e3a072d118917957d6554Steve BlockSOFT_LINK_CLASS(AVFoundation, AVPlayer) 582bde8e466a4451c7319e3a072d118917957d6554Steve BlockSOFT_LINK_CLASS(AVFoundation, AVPlayerItem) 592bde8e466a4451c7319e3a072d118917957d6554Steve BlockSOFT_LINK_CLASS(AVFoundation, AVPlayerLayer) 602bde8e466a4451c7319e3a072d118917957d6554Steve BlockSOFT_LINK_CLASS(AVFoundation, AVURLAsset) 612bde8e466a4451c7319e3a072d118917957d6554Steve BlockSOFT_LINK_CLASS(AVFoundation, AVAssetImageGenerator) 622bde8e466a4451c7319e3a072d118917957d6554Steve Block 632bde8e466a4451c7319e3a072d118917957d6554Steve BlockSOFT_LINK_POINTER(AVFoundation, AVMediaCharacteristicVisual, NSString *) 642bde8e466a4451c7319e3a072d118917957d6554Steve BlockSOFT_LINK_POINTER(AVFoundation, AVMediaCharacteristicAudible, NSString *) 652bde8e466a4451c7319e3a072d118917957d6554Steve BlockSOFT_LINK_POINTER(AVFoundation, AVMediaTypeClosedCaption, NSString *) 662bde8e466a4451c7319e3a072d118917957d6554Steve BlockSOFT_LINK_POINTER(AVFoundation, AVPlayerItemDidPlayToEndTimeNotification, NSString *) 672bde8e466a4451c7319e3a072d118917957d6554Steve BlockSOFT_LINK_POINTER(AVFoundation, AVAssetImageGeneratorApertureModeCleanAperture, NSString *) 682bde8e466a4451c7319e3a072d118917957d6554Steve Block 692bde8e466a4451c7319e3a072d118917957d6554Steve BlockSOFT_LINK_CONSTANT(CoreMedia, kCMTimeZero, CMTime) 702bde8e466a4451c7319e3a072d118917957d6554Steve Block 712bde8e466a4451c7319e3a072d118917957d6554Steve Block#define AVPlayer getAVPlayerClass() 722bde8e466a4451c7319e3a072d118917957d6554Steve Block#define AVPlayerItem getAVPlayerItemClass() 732bde8e466a4451c7319e3a072d118917957d6554Steve Block#define AVPlayerLayer getAVPlayerLayerClass() 742bde8e466a4451c7319e3a072d118917957d6554Steve Block#define AVURLAsset getAVURLAssetClass() 752bde8e466a4451c7319e3a072d118917957d6554Steve Block#define AVAssetImageGenerator getAVAssetImageGeneratorClass() 762bde8e466a4451c7319e3a072d118917957d6554Steve Block 772bde8e466a4451c7319e3a072d118917957d6554Steve Block#define AVMediaCharacteristicVisual getAVMediaCharacteristicVisual() 782bde8e466a4451c7319e3a072d118917957d6554Steve Block#define AVMediaCharacteristicAudible getAVMediaCharacteristicAudible() 792bde8e466a4451c7319e3a072d118917957d6554Steve Block#define AVMediaTypeClosedCaption getAVMediaTypeClosedCaption() 802bde8e466a4451c7319e3a072d118917957d6554Steve Block#define AVPlayerItemDidPlayToEndTimeNotification getAVPlayerItemDidPlayToEndTimeNotification() 812bde8e466a4451c7319e3a072d118917957d6554Steve Block#define AVAssetImageGeneratorApertureModeCleanAperture getAVAssetImageGeneratorApertureModeCleanAperture() 822bde8e466a4451c7319e3a072d118917957d6554Steve Block 832bde8e466a4451c7319e3a072d118917957d6554Steve Block#define kCMTimeZero getkCMTimeZero() 842bde8e466a4451c7319e3a072d118917957d6554Steve Block 852bde8e466a4451c7319e3a072d118917957d6554Steve Blockusing namespace WebCore; 862bde8e466a4451c7319e3a072d118917957d6554Steve Blockusing namespace std; 872bde8e466a4451c7319e3a072d118917957d6554Steve Block 882bde8e466a4451c7319e3a072d118917957d6554Steve Blockenum MediaPlayerAVFoundationObservationContext { 892bde8e466a4451c7319e3a072d118917957d6554Steve Block MediaPlayerAVFoundationObservationContextPlayerItem, 902bde8e466a4451c7319e3a072d118917957d6554Steve Block MediaPlayerAVFoundationObservationContextPlayer 912bde8e466a4451c7319e3a072d118917957d6554Steve Block}; 922bde8e466a4451c7319e3a072d118917957d6554Steve Block 932bde8e466a4451c7319e3a072d118917957d6554Steve Block@interface WebCoreAVFMovieObserver : NSObject 942bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 952bde8e466a4451c7319e3a072d118917957d6554Steve Block MediaPlayerPrivateAVFoundationObjC* m_callback; 962bde8e466a4451c7319e3a072d118917957d6554Steve Block int m_delayCallbacks; 972bde8e466a4451c7319e3a072d118917957d6554Steve Block} 982bde8e466a4451c7319e3a072d118917957d6554Steve Block-(id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC*)callback; 992bde8e466a4451c7319e3a072d118917957d6554Steve Block-(void)disconnect; 1002bde8e466a4451c7319e3a072d118917957d6554Steve Block-(void)playableKnown; 1012bde8e466a4451c7319e3a072d118917957d6554Steve Block-(void)metadataLoaded; 1022bde8e466a4451c7319e3a072d118917957d6554Steve Block-(void)timeChanged:(double)time; 1032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch-(void)seekCompleted:(BOOL)finished; 1042bde8e466a4451c7319e3a072d118917957d6554Steve Block-(void)didEnd:(NSNotification *)notification; 1052bde8e466a4451c7319e3a072d118917957d6554Steve Block-(void)observeValueForKeyPath:keyPath ofObject:(id)object change:(NSDictionary *)change context:(MediaPlayerAVFoundationObservationContext)context; 1062bde8e466a4451c7319e3a072d118917957d6554Steve Block@end 1072bde8e466a4451c7319e3a072d118917957d6554Steve Block 1082bde8e466a4451c7319e3a072d118917957d6554Steve Blocknamespace WebCore { 1092bde8e466a4451c7319e3a072d118917957d6554Steve Block 1102bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic NSArray *assetMetadataKeyNames(); 1112bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic NSArray *itemKVOProperties(); 1122bde8e466a4451c7319e3a072d118917957d6554Steve Block 1132bde8e466a4451c7319e3a072d118917957d6554Steve Block#if !LOG_DISABLED 1142bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic const char *boolString(bool val) 1152bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 1162bde8e466a4451c7319e3a072d118917957d6554Steve Block return val ? "true" : "false"; 1172bde8e466a4451c7319e3a072d118917957d6554Steve Block} 1182bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif 1192bde8e466a4451c7319e3a072d118917957d6554Steve Block 1202bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic const float invalidTime = -1.0f; 1212bde8e466a4451c7319e3a072d118917957d6554Steve Block 1222bde8e466a4451c7319e3a072d118917957d6554Steve BlockMediaPlayerPrivateInterface* MediaPlayerPrivateAVFoundationObjC::create(MediaPlayer* player) 1232bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 1242bde8e466a4451c7319e3a072d118917957d6554Steve Block return new MediaPlayerPrivateAVFoundationObjC(player); 1252bde8e466a4451c7319e3a072d118917957d6554Steve Block} 1262bde8e466a4451c7319e3a072d118917957d6554Steve Block 1272bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateAVFoundationObjC::registerMediaEngine(MediaEngineRegistrar registrar) 1282bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 1292bde8e466a4451c7319e3a072d118917957d6554Steve Block if (isAvailable()) 1302bde8e466a4451c7319e3a072d118917957d6554Steve Block registrar(create, getSupportedTypes, supportsType, 0, 0, 0); 1312bde8e466a4451c7319e3a072d118917957d6554Steve Block} 1322bde8e466a4451c7319e3a072d118917957d6554Steve Block 1332bde8e466a4451c7319e3a072d118917957d6554Steve BlockMediaPlayerPrivateAVFoundationObjC::MediaPlayerPrivateAVFoundationObjC(MediaPlayer* player) 1342bde8e466a4451c7319e3a072d118917957d6554Steve Block : MediaPlayerPrivateAVFoundation(player) 1352bde8e466a4451c7319e3a072d118917957d6554Steve Block , m_objcObserver(AdoptNS, [[WebCoreAVFMovieObserver alloc] initWithCallback:this]) 1362bde8e466a4451c7319e3a072d118917957d6554Steve Block , m_timeObserver(0) 1372bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 1382bde8e466a4451c7319e3a072d118917957d6554Steve Block} 1392bde8e466a4451c7319e3a072d118917957d6554Steve Block 1402bde8e466a4451c7319e3a072d118917957d6554Steve BlockMediaPlayerPrivateAVFoundationObjC::~MediaPlayerPrivateAVFoundationObjC() 1412bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 1422bde8e466a4451c7319e3a072d118917957d6554Steve Block cancelLoad(); 1432bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_objcObserver.get() disconnect]; 1442bde8e466a4451c7319e3a072d118917957d6554Steve Block} 1452bde8e466a4451c7319e3a072d118917957d6554Steve Block 1462bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateAVFoundationObjC::cancelLoad() 1472bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 1482bde8e466a4451c7319e3a072d118917957d6554Steve Block LOG(Media, "MediaPlayerPrivateAVFoundationObjC::cancelLoad(%p)", this); 1492bde8e466a4451c7319e3a072d118917957d6554Steve Block tearDownVideoRendering(); 1502bde8e466a4451c7319e3a072d118917957d6554Steve Block 1512bde8e466a4451c7319e3a072d118917957d6554Steve Block [[NSNotificationCenter defaultCenter] removeObserver:m_objcObserver.get()]; 1522bde8e466a4451c7319e3a072d118917957d6554Steve Block 1532bde8e466a4451c7319e3a072d118917957d6554Steve Block // Tell our observer to do nothing when our cancellation of pending loading calls its completion handler. 1542bde8e466a4451c7319e3a072d118917957d6554Steve Block setIgnoreLoadStateChanges(true); 1552bde8e466a4451c7319e3a072d118917957d6554Steve Block if (m_avAsset) { 1562bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_avAsset.get() cancelLoading]; 1572bde8e466a4451c7319e3a072d118917957d6554Steve Block m_avAsset = nil; 1582bde8e466a4451c7319e3a072d118917957d6554Steve Block } 1592bde8e466a4451c7319e3a072d118917957d6554Steve Block if (m_avPlayerItem) { 1602bde8e466a4451c7319e3a072d118917957d6554Steve Block for (NSString *keyName in itemKVOProperties()) 1612bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_avPlayerItem.get() removeObserver:m_objcObserver.get() forKeyPath:keyName]; 1622bde8e466a4451c7319e3a072d118917957d6554Steve Block 1632bde8e466a4451c7319e3a072d118917957d6554Steve Block m_avPlayerItem = nil; 1642bde8e466a4451c7319e3a072d118917957d6554Steve Block } 1652bde8e466a4451c7319e3a072d118917957d6554Steve Block if (m_avPlayer) { 1662bde8e466a4451c7319e3a072d118917957d6554Steve Block if (m_timeObserver) 1672bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_avPlayer.get() removeTimeObserver:m_timeObserver]; 1682bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_avPlayer.get() removeObserver:m_objcObserver.get() forKeyPath:@"rate"]; 1692bde8e466a4451c7319e3a072d118917957d6554Steve Block m_avPlayer = nil; 1702bde8e466a4451c7319e3a072d118917957d6554Steve Block } 1712bde8e466a4451c7319e3a072d118917957d6554Steve Block setIgnoreLoadStateChanges(false); 1722bde8e466a4451c7319e3a072d118917957d6554Steve Block} 1732bde8e466a4451c7319e3a072d118917957d6554Steve Block 1742bde8e466a4451c7319e3a072d118917957d6554Steve Blockbool MediaPlayerPrivateAVFoundationObjC::hasLayerRenderer() const 1752bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 1762bde8e466a4451c7319e3a072d118917957d6554Steve Block return m_videoLayer; 1772bde8e466a4451c7319e3a072d118917957d6554Steve Block} 1782bde8e466a4451c7319e3a072d118917957d6554Steve Block 1792bde8e466a4451c7319e3a072d118917957d6554Steve Blockbool MediaPlayerPrivateAVFoundationObjC::hasContextRenderer() const 1802bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 1812bde8e466a4451c7319e3a072d118917957d6554Steve Block return m_imageGenerator; 1822bde8e466a4451c7319e3a072d118917957d6554Steve Block} 1832bde8e466a4451c7319e3a072d118917957d6554Steve Block 1842bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateAVFoundationObjC::createContextVideoRenderer() 1852bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 1862bde8e466a4451c7319e3a072d118917957d6554Steve Block LOG(Media, "MediaPlayerPrivateAVFoundationObjC::createContextVideoRenderer(%p)", this); 1872bde8e466a4451c7319e3a072d118917957d6554Steve Block 1882bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!m_avAsset || m_imageGenerator) 1892bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 1902bde8e466a4451c7319e3a072d118917957d6554Steve Block 1912bde8e466a4451c7319e3a072d118917957d6554Steve Block m_imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:m_avAsset.get()]; 1922bde8e466a4451c7319e3a072d118917957d6554Steve Block 1932bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_imageGenerator.get() setApertureMode:AVAssetImageGeneratorApertureModeCleanAperture]; 1942bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_imageGenerator.get() setAppliesPreferredTrackTransform:YES]; 1952bde8e466a4451c7319e3a072d118917957d6554Steve Block 1962bde8e466a4451c7319e3a072d118917957d6554Steve Block LOG(Media, "MediaPlayerPrivateAVFoundationObjC::createImageGenerator(%p) - returning %p", this, m_imageGenerator.get()); 1972bde8e466a4451c7319e3a072d118917957d6554Steve Block} 1982bde8e466a4451c7319e3a072d118917957d6554Steve Block 1992bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateAVFoundationObjC::destroyContextVideoRenderer() 2002bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 2012bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!m_imageGenerator) 2022bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 2032bde8e466a4451c7319e3a072d118917957d6554Steve Block 2042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch LOG(Media, "MediaPlayerPrivateAVFoundationObjC::destroyContextVideoRenderer(%p) - destroying %p", this, m_imageGenerator.get()); 2052bde8e466a4451c7319e3a072d118917957d6554Steve Block 2062bde8e466a4451c7319e3a072d118917957d6554Steve Block m_imageGenerator = 0; 2072bde8e466a4451c7319e3a072d118917957d6554Steve Block} 2082bde8e466a4451c7319e3a072d118917957d6554Steve Block 2092bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateAVFoundationObjC::createVideoLayer() 2102bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 2112bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!m_avPlayer) 2122bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 2132bde8e466a4451c7319e3a072d118917957d6554Steve Block 2142bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!m_videoLayer) { 2152bde8e466a4451c7319e3a072d118917957d6554Steve Block m_videoLayer.adoptNS([[AVPlayerLayer alloc] init]); 2162bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_videoLayer.get() setPlayer:m_avPlayer.get()]; 2172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch LOG(Media, "MediaPlayerPrivateAVFoundationObjC::createVideoLayer(%p) - returning %p", this, m_videoLayer.get()); 2182bde8e466a4451c7319e3a072d118917957d6554Steve Block } 2192bde8e466a4451c7319e3a072d118917957d6554Steve Block} 2202bde8e466a4451c7319e3a072d118917957d6554Steve Block 2212bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateAVFoundationObjC::destroyVideoLayer() 2222bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 2232bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!m_videoLayer) 2242bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 2252bde8e466a4451c7319e3a072d118917957d6554Steve Block 2262bde8e466a4451c7319e3a072d118917957d6554Steve Block LOG(Media, "MediaPlayerPrivateAVFoundationObjC::destroyVideoLayer(%p) - destroying", this, m_videoLayer.get()); 2272bde8e466a4451c7319e3a072d118917957d6554Steve Block 2282bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_videoLayer.get() setPlayer:nil]; 2292bde8e466a4451c7319e3a072d118917957d6554Steve Block 2302bde8e466a4451c7319e3a072d118917957d6554Steve Block m_videoLayer = 0; 2312bde8e466a4451c7319e3a072d118917957d6554Steve Block} 2322bde8e466a4451c7319e3a072d118917957d6554Steve Block 2332bde8e466a4451c7319e3a072d118917957d6554Steve Blockbool MediaPlayerPrivateAVFoundationObjC::videoLayerIsReadyToDisplay() const 2342bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 2352bde8e466a4451c7319e3a072d118917957d6554Steve Block return (m_videoLayer && [m_videoLayer.get() isReadyForDisplay]); 2362bde8e466a4451c7319e3a072d118917957d6554Steve Block} 2372bde8e466a4451c7319e3a072d118917957d6554Steve Block 2382bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateAVFoundationObjC::createAVPlayerForURL(const String& url) 2392bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 2402bde8e466a4451c7319e3a072d118917957d6554Steve Block setDelayCallbacks(true); 2412bde8e466a4451c7319e3a072d118917957d6554Steve Block 2422bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!m_avAsset) { 2432bde8e466a4451c7319e3a072d118917957d6554Steve Block NSURL *cocoaURL = KURL(ParsedURLString, url); 2442bde8e466a4451c7319e3a072d118917957d6554Steve Block m_avAsset.adoptNS([[AVURLAsset alloc] initWithURL:cocoaURL options:nil]); 2452bde8e466a4451c7319e3a072d118917957d6554Steve Block } 2462bde8e466a4451c7319e3a072d118917957d6554Steve Block 2472bde8e466a4451c7319e3a072d118917957d6554Steve Block createAVPlayer(); 2482bde8e466a4451c7319e3a072d118917957d6554Steve Block} 2492bde8e466a4451c7319e3a072d118917957d6554Steve Block 2502bde8e466a4451c7319e3a072d118917957d6554Steve Block#if ENABLE(OFFLINE_WEB_APPLICATIONS) 2512bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateAVFoundationObjC::createAVPlayerForCacheResource(ApplicationCacheResource* resource) 2522bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 2532bde8e466a4451c7319e3a072d118917957d6554Steve Block // AVFoundation can't open arbitrary data pointers, so if this ApplicationCacheResource doesn't 2542bde8e466a4451c7319e3a072d118917957d6554Steve Block // have a valid local path, just open the resource's original URL. 2552bde8e466a4451c7319e3a072d118917957d6554Steve Block if (resource->path().isEmpty()) { 2562bde8e466a4451c7319e3a072d118917957d6554Steve Block createAVPlayerForURL(resource->url()); 2572bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 2582bde8e466a4451c7319e3a072d118917957d6554Steve Block } 2592bde8e466a4451c7319e3a072d118917957d6554Steve Block 2602bde8e466a4451c7319e3a072d118917957d6554Steve Block setDelayCallbacks(true); 2612bde8e466a4451c7319e3a072d118917957d6554Steve Block 2622bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!m_avAsset) { 2632bde8e466a4451c7319e3a072d118917957d6554Steve Block NSURL* localURL = [NSURL fileURLWithPath:resource->path()]; 2642bde8e466a4451c7319e3a072d118917957d6554Steve Block m_avAsset.adoptNS([[AVURLAsset alloc] initWithURL:localURL options:nil]); 2652bde8e466a4451c7319e3a072d118917957d6554Steve Block } 2662bde8e466a4451c7319e3a072d118917957d6554Steve Block 2672bde8e466a4451c7319e3a072d118917957d6554Steve Block createAVPlayer(); 2682bde8e466a4451c7319e3a072d118917957d6554Steve Block} 2692bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif 2702bde8e466a4451c7319e3a072d118917957d6554Steve Block 2712bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateAVFoundationObjC::createAVPlayer() 2722bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 2732bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!m_avPlayer) { 2742bde8e466a4451c7319e3a072d118917957d6554Steve Block m_avPlayer.adoptNS([[AVPlayer alloc] init]); 2752bde8e466a4451c7319e3a072d118917957d6554Steve Block 2762bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_avPlayer.get() addObserver:m_objcObserver.get() forKeyPath:@"rate" options:nil context:(void *)MediaPlayerAVFoundationObservationContextPlayer]; 2772bde8e466a4451c7319e3a072d118917957d6554Steve Block 2782bde8e466a4451c7319e3a072d118917957d6554Steve Block // Add a time observer, ask to be called infrequently because we don't really want periodic callbacks but 2792bde8e466a4451c7319e3a072d118917957d6554Steve Block // our observer will also be called whenever a seek happens. 2802bde8e466a4451c7319e3a072d118917957d6554Steve Block const double veryLongInterval = 60*60*60*24*30; 2812bde8e466a4451c7319e3a072d118917957d6554Steve Block WebCoreAVFMovieObserver *observer = m_objcObserver.get(); 2822bde8e466a4451c7319e3a072d118917957d6554Steve Block m_timeObserver = [m_avPlayer.get() addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(veryLongInterval, 10) queue:nil usingBlock:^(CMTime time){ 2832bde8e466a4451c7319e3a072d118917957d6554Steve Block [observer timeChanged:CMTimeGetSeconds(time)]; 2842bde8e466a4451c7319e3a072d118917957d6554Steve Block }]; 2852bde8e466a4451c7319e3a072d118917957d6554Steve Block } 2862bde8e466a4451c7319e3a072d118917957d6554Steve Block 2872bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!m_avPlayerItem) { 2882bde8e466a4451c7319e3a072d118917957d6554Steve Block // Create the player item so we can media data. 2892bde8e466a4451c7319e3a072d118917957d6554Steve Block m_avPlayerItem.adoptNS([[AVPlayerItem alloc] initWithAsset:m_avAsset.get()]); 2902bde8e466a4451c7319e3a072d118917957d6554Steve Block 2912bde8e466a4451c7319e3a072d118917957d6554Steve Block [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()selector:@selector(didEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:m_avPlayerItem.get()]; 2922bde8e466a4451c7319e3a072d118917957d6554Steve Block 2932bde8e466a4451c7319e3a072d118917957d6554Steve Block for (NSString *keyName in itemKVOProperties()) 2942bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_avPlayerItem.get() addObserver:m_objcObserver.get() forKeyPath:keyName options:nil context:(void *)MediaPlayerAVFoundationObservationContextPlayerItem]; 2952bde8e466a4451c7319e3a072d118917957d6554Steve Block 2962bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_avPlayer.get() replaceCurrentItemWithPlayerItem:m_avPlayerItem.get()]; 2972bde8e466a4451c7319e3a072d118917957d6554Steve Block } 2982bde8e466a4451c7319e3a072d118917957d6554Steve Block 2992bde8e466a4451c7319e3a072d118917957d6554Steve Block setDelayCallbacks(false); 3002bde8e466a4451c7319e3a072d118917957d6554Steve Block} 3012bde8e466a4451c7319e3a072d118917957d6554Steve Block 3022bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateAVFoundationObjC::checkPlayability() 3032bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 3042bde8e466a4451c7319e3a072d118917957d6554Steve Block LOG(Media, "MediaPlayerPrivateAVFoundationObjC::checkPlayability(%p)", this); 3052bde8e466a4451c7319e3a072d118917957d6554Steve Block 3062bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_avAsset.get() loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:@"playable"] completionHandler:^{ 3072bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_objcObserver.get() playableKnown]; 3082bde8e466a4451c7319e3a072d118917957d6554Steve Block }]; 3092bde8e466a4451c7319e3a072d118917957d6554Steve Block} 3102bde8e466a4451c7319e3a072d118917957d6554Steve Block 3112bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateAVFoundationObjC::beginLoadingMetadata() 3122bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 3132bde8e466a4451c7319e3a072d118917957d6554Steve Block LOG(Media, "MediaPlayerPrivateAVFoundationObjC::playabilityKnown(%p) - requesting metadata loading", this); 3142bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_avAsset.get() loadValuesAsynchronouslyForKeys:[assetMetadataKeyNames() retain] completionHandler:^{ 3152bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_objcObserver.get() metadataLoaded]; 3162bde8e466a4451c7319e3a072d118917957d6554Steve Block }]; 3172bde8e466a4451c7319e3a072d118917957d6554Steve Block} 3182bde8e466a4451c7319e3a072d118917957d6554Steve Block 3192bde8e466a4451c7319e3a072d118917957d6554Steve BlockMediaPlayerPrivateAVFoundation::ItemStatus MediaPlayerPrivateAVFoundationObjC::playerItemStatus() const 3202bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 3212bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!m_avPlayerItem) 3222bde8e466a4451c7319e3a072d118917957d6554Steve Block return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusUnknown; 3232bde8e466a4451c7319e3a072d118917957d6554Steve Block 3242bde8e466a4451c7319e3a072d118917957d6554Steve Block AVPlayerItemStatus status = [m_avPlayerItem.get() status]; 3252bde8e466a4451c7319e3a072d118917957d6554Steve Block if (status == AVPlayerItemStatusUnknown) 3262bde8e466a4451c7319e3a072d118917957d6554Steve Block return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusUnknown; 3272bde8e466a4451c7319e3a072d118917957d6554Steve Block if (status == AVPlayerItemStatusFailed) 3282bde8e466a4451c7319e3a072d118917957d6554Steve Block return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusFailed; 3292bde8e466a4451c7319e3a072d118917957d6554Steve Block if ([m_avPlayerItem.get() isPlaybackLikelyToKeepUp]) 3302bde8e466a4451c7319e3a072d118917957d6554Steve Block return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusPlaybackLikelyToKeepUp; 3312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (buffered()->contain(duration())) 3322bde8e466a4451c7319e3a072d118917957d6554Steve Block return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusPlaybackBufferFull; 3332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (buffered()->contain(currentTime())) 3342bde8e466a4451c7319e3a072d118917957d6554Steve Block return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusPlaybackBufferEmpty; 3352bde8e466a4451c7319e3a072d118917957d6554Steve Block 3362bde8e466a4451c7319e3a072d118917957d6554Steve Block return MediaPlayerPrivateAVFoundation::MediaPlayerAVPlayerItemStatusReadyToPlay; 3372bde8e466a4451c7319e3a072d118917957d6554Steve Block} 3382bde8e466a4451c7319e3a072d118917957d6554Steve Block 3392bde8e466a4451c7319e3a072d118917957d6554Steve BlockPlatformMedia MediaPlayerPrivateAVFoundationObjC::platformMedia() const 3402bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 3412bde8e466a4451c7319e3a072d118917957d6554Steve Block LOG(Media, "MediaPlayerPrivateAVFoundationObjC::platformMedia(%p)", this); 3422bde8e466a4451c7319e3a072d118917957d6554Steve Block PlatformMedia pm; 3432bde8e466a4451c7319e3a072d118917957d6554Steve Block pm.type = PlatformMedia::AVFoundationMediaPlayerType; 3442bde8e466a4451c7319e3a072d118917957d6554Steve Block pm.media.avfMediaPlayer = m_avPlayer.get(); 3452bde8e466a4451c7319e3a072d118917957d6554Steve Block return pm; 3462bde8e466a4451c7319e3a072d118917957d6554Steve Block} 3472bde8e466a4451c7319e3a072d118917957d6554Steve Block 3482bde8e466a4451c7319e3a072d118917957d6554Steve BlockPlatformLayer* MediaPlayerPrivateAVFoundationObjC::platformLayer() const 3492bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 3502bde8e466a4451c7319e3a072d118917957d6554Steve Block LOG(Media, "MediaPlayerPrivateAVFoundationObjC::platformLayer(%p)", this); 3512bde8e466a4451c7319e3a072d118917957d6554Steve Block return m_videoLayer.get(); 3522bde8e466a4451c7319e3a072d118917957d6554Steve Block} 3532bde8e466a4451c7319e3a072d118917957d6554Steve Block 3542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid MediaPlayerPrivateAVFoundationObjC::platformPlay() 3552bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 3562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch LOG(Media, "MediaPlayerPrivateAVFoundationObjC::platformPlay(%p)", this); 3572bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!metaDataAvailable()) 3582bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 3592bde8e466a4451c7319e3a072d118917957d6554Steve Block 3602bde8e466a4451c7319e3a072d118917957d6554Steve Block setDelayCallbacks(true); 3612bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_avPlayer.get() setRate:requestedRate()]; 3622bde8e466a4451c7319e3a072d118917957d6554Steve Block setDelayCallbacks(false); 3632bde8e466a4451c7319e3a072d118917957d6554Steve Block} 3642bde8e466a4451c7319e3a072d118917957d6554Steve Block 3652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid MediaPlayerPrivateAVFoundationObjC::platformPause() 3662bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 3672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch LOG(Media, "MediaPlayerPrivateAVFoundationObjC::platformPause(%p)", this); 3682bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!metaDataAvailable()) 3692bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 3702bde8e466a4451c7319e3a072d118917957d6554Steve Block 3712bde8e466a4451c7319e3a072d118917957d6554Steve Block setDelayCallbacks(true); 3722bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_avPlayer.get() setRate:nil]; 3732bde8e466a4451c7319e3a072d118917957d6554Steve Block setDelayCallbacks(false); 3742bde8e466a4451c7319e3a072d118917957d6554Steve Block} 3752bde8e466a4451c7319e3a072d118917957d6554Steve Block 3762bde8e466a4451c7319e3a072d118917957d6554Steve Blockfloat MediaPlayerPrivateAVFoundationObjC::platformDuration() const 3772bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 3782bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!metaDataAvailable() || !m_avPlayerItem) 3792bde8e466a4451c7319e3a072d118917957d6554Steve Block return 0; 3802bde8e466a4451c7319e3a072d118917957d6554Steve Block 3812bde8e466a4451c7319e3a072d118917957d6554Steve Block float duration; 3822bde8e466a4451c7319e3a072d118917957d6554Steve Block CMTime cmDuration = [m_avPlayerItem.get() duration]; 3832bde8e466a4451c7319e3a072d118917957d6554Steve Block if (CMTIME_IS_NUMERIC(cmDuration)) 3842bde8e466a4451c7319e3a072d118917957d6554Steve Block duration = narrowPrecisionToFloat(CMTimeGetSeconds(cmDuration)); 3852bde8e466a4451c7319e3a072d118917957d6554Steve Block else if (CMTIME_IS_INDEFINITE(cmDuration)) 3862bde8e466a4451c7319e3a072d118917957d6554Steve Block duration = numeric_limits<float>::infinity(); 3872bde8e466a4451c7319e3a072d118917957d6554Steve Block else { 3882bde8e466a4451c7319e3a072d118917957d6554Steve Block LOG(Media, "MediaPlayerPrivateAVFoundationObjC::duration(%p) - invalid duration, returning 0", this); 3892bde8e466a4451c7319e3a072d118917957d6554Steve Block return 0; 3902bde8e466a4451c7319e3a072d118917957d6554Steve Block } 3912bde8e466a4451c7319e3a072d118917957d6554Steve Block 3922bde8e466a4451c7319e3a072d118917957d6554Steve Block return duration; 3932bde8e466a4451c7319e3a072d118917957d6554Steve Block} 3942bde8e466a4451c7319e3a072d118917957d6554Steve Block 3952bde8e466a4451c7319e3a072d118917957d6554Steve Blockfloat MediaPlayerPrivateAVFoundationObjC::currentTime() const 3962bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 3972bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!metaDataAvailable() || !m_avPlayerItem) 3982bde8e466a4451c7319e3a072d118917957d6554Steve Block return 0; 3992bde8e466a4451c7319e3a072d118917957d6554Steve Block 4002bde8e466a4451c7319e3a072d118917957d6554Steve Block CMTime itemTime = [m_avPlayerItem.get() currentTime]; 4012bde8e466a4451c7319e3a072d118917957d6554Steve Block if (CMTIME_IS_NUMERIC(itemTime)) 4022bde8e466a4451c7319e3a072d118917957d6554Steve Block return narrowPrecisionToFloat(CMTimeGetSeconds(itemTime)); 4032bde8e466a4451c7319e3a072d118917957d6554Steve Block 4042bde8e466a4451c7319e3a072d118917957d6554Steve Block return 0; 4052bde8e466a4451c7319e3a072d118917957d6554Steve Block} 4062bde8e466a4451c7319e3a072d118917957d6554Steve Block 4072bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateAVFoundationObjC::seekToTime(float time) 4082bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 4092bde8e466a4451c7319e3a072d118917957d6554Steve Block // setCurrentTime generates several event callbacks, update afterwards. 4102bde8e466a4451c7319e3a072d118917957d6554Steve Block setDelayCallbacks(true); 4112bde8e466a4451c7319e3a072d118917957d6554Steve Block 4122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch WebCoreAVFMovieObserver *observer = m_objcObserver.get(); 4132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch [m_avPlayerItem.get() seekToTime:CMTimeMakeWithSeconds(time, 600) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:^(BOOL finished) { 4142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch [observer seekCompleted:finished]; 4152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch }]; 4162bde8e466a4451c7319e3a072d118917957d6554Steve Block 4172bde8e466a4451c7319e3a072d118917957d6554Steve Block setDelayCallbacks(false); 4182bde8e466a4451c7319e3a072d118917957d6554Steve Block} 4192bde8e466a4451c7319e3a072d118917957d6554Steve Block 4202bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateAVFoundationObjC::setVolume(float volume) 4212bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 4222bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!metaDataAvailable()) 4232bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 4242bde8e466a4451c7319e3a072d118917957d6554Steve Block 4252bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_avPlayer.get() setVolume:volume]; 4262bde8e466a4451c7319e3a072d118917957d6554Steve Block} 4272bde8e466a4451c7319e3a072d118917957d6554Steve Block 4282bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateAVFoundationObjC::setClosedCaptionsVisible(bool closedCaptionsVisible) 4292bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 4302bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!metaDataAvailable()) 4312bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 4322bde8e466a4451c7319e3a072d118917957d6554Steve Block 4332bde8e466a4451c7319e3a072d118917957d6554Steve Block LOG(Media, "MediaPlayerPrivateAVFoundationObjC::setClosedCaptionsVisible(%p) - setting to %s", this, boolString(closedCaptionsVisible)); 4342bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_avPlayer.get() setClosedCaptionDisplayEnabled:closedCaptionsVisible]; 4352bde8e466a4451c7319e3a072d118917957d6554Steve Block} 4362bde8e466a4451c7319e3a072d118917957d6554Steve Block 4372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid MediaPlayerPrivateAVFoundationObjC::updateRate() 4382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{ 4392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch setDelayCallbacks(true); 4402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch [m_avPlayer.get() setRate:requestedRate()]; 4412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch setDelayCallbacks(false); 4422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch} 4432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 4442bde8e466a4451c7319e3a072d118917957d6554Steve Blockfloat MediaPlayerPrivateAVFoundationObjC::rate() const 4452bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 4462bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!metaDataAvailable()) 4472bde8e466a4451c7319e3a072d118917957d6554Steve Block return 0; 4482bde8e466a4451c7319e3a072d118917957d6554Steve Block 4492bde8e466a4451c7319e3a072d118917957d6554Steve Block return [m_avPlayer.get() rate]; 4502bde8e466a4451c7319e3a072d118917957d6554Steve Block} 4512bde8e466a4451c7319e3a072d118917957d6554Steve Block 4522bde8e466a4451c7319e3a072d118917957d6554Steve BlockPassRefPtr<TimeRanges> MediaPlayerPrivateAVFoundationObjC::platformBufferedTimeRanges() const 4532bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 4542bde8e466a4451c7319e3a072d118917957d6554Steve Block RefPtr<TimeRanges> timeRanges = TimeRanges::create(); 4552bde8e466a4451c7319e3a072d118917957d6554Steve Block 4562bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!m_avPlayerItem) 4572bde8e466a4451c7319e3a072d118917957d6554Steve Block return timeRanges.release(); 4582bde8e466a4451c7319e3a072d118917957d6554Steve Block 4592bde8e466a4451c7319e3a072d118917957d6554Steve Block NSArray *loadedRanges = [m_avPlayerItem.get() loadedTimeRanges]; 4602bde8e466a4451c7319e3a072d118917957d6554Steve Block for (NSValue *thisRangeValue in loadedRanges) { 4612bde8e466a4451c7319e3a072d118917957d6554Steve Block CMTimeRange timeRange = [thisRangeValue CMTimeRangeValue]; 4622bde8e466a4451c7319e3a072d118917957d6554Steve Block if (CMTIMERANGE_IS_VALID(timeRange) && !CMTIMERANGE_IS_EMPTY(timeRange)) { 4632bde8e466a4451c7319e3a072d118917957d6554Steve Block float rangeStart = narrowPrecisionToFloat(CMTimeGetSeconds(timeRange.start)); 4642bde8e466a4451c7319e3a072d118917957d6554Steve Block float rangeEnd = narrowPrecisionToFloat(CMTimeGetSeconds(CMTimeRangeGetEnd(timeRange))); 4652bde8e466a4451c7319e3a072d118917957d6554Steve Block timeRanges->add(rangeStart, rangeEnd); 4662bde8e466a4451c7319e3a072d118917957d6554Steve Block } 4672bde8e466a4451c7319e3a072d118917957d6554Steve Block } 4682bde8e466a4451c7319e3a072d118917957d6554Steve Block return timeRanges.release(); 4692bde8e466a4451c7319e3a072d118917957d6554Steve Block} 4702bde8e466a4451c7319e3a072d118917957d6554Steve Block 4712bde8e466a4451c7319e3a072d118917957d6554Steve Blockfloat MediaPlayerPrivateAVFoundationObjC::platformMaxTimeSeekable() const 4722bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 4732bde8e466a4451c7319e3a072d118917957d6554Steve Block NSArray *seekableRanges = [m_avPlayerItem.get() seekableTimeRanges]; 4742bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!seekableRanges) 4752bde8e466a4451c7319e3a072d118917957d6554Steve Block return 0; 4762bde8e466a4451c7319e3a072d118917957d6554Steve Block 4772bde8e466a4451c7319e3a072d118917957d6554Steve Block float maxTimeSeekable = 0; 4782bde8e466a4451c7319e3a072d118917957d6554Steve Block for (NSValue *thisRangeValue in seekableRanges) { 4792bde8e466a4451c7319e3a072d118917957d6554Steve Block CMTimeRange timeRange = [thisRangeValue CMTimeRangeValue]; 4802bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!CMTIMERANGE_IS_VALID(timeRange) || CMTIMERANGE_IS_EMPTY(timeRange)) 4812bde8e466a4451c7319e3a072d118917957d6554Steve Block continue; 4822bde8e466a4451c7319e3a072d118917957d6554Steve Block 4832bde8e466a4451c7319e3a072d118917957d6554Steve Block float endOfRange = narrowPrecisionToFloat(CMTimeGetSeconds(CMTimeRangeGetEnd(timeRange))); 4842bde8e466a4451c7319e3a072d118917957d6554Steve Block if (maxTimeSeekable < endOfRange) 4852bde8e466a4451c7319e3a072d118917957d6554Steve Block maxTimeSeekable = endOfRange; 4862bde8e466a4451c7319e3a072d118917957d6554Steve Block } 4872bde8e466a4451c7319e3a072d118917957d6554Steve Block return maxTimeSeekable; 4882bde8e466a4451c7319e3a072d118917957d6554Steve Block} 4892bde8e466a4451c7319e3a072d118917957d6554Steve Block 4902bde8e466a4451c7319e3a072d118917957d6554Steve Blockfloat MediaPlayerPrivateAVFoundationObjC::platformMaxTimeLoaded() const 4912bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 4922bde8e466a4451c7319e3a072d118917957d6554Steve Block NSArray *loadedRanges = [m_avPlayerItem.get() loadedTimeRanges]; 4932bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!loadedRanges) 4942bde8e466a4451c7319e3a072d118917957d6554Steve Block return 0; 4952bde8e466a4451c7319e3a072d118917957d6554Steve Block 4962bde8e466a4451c7319e3a072d118917957d6554Steve Block float maxTimeLoaded = 0; 4972bde8e466a4451c7319e3a072d118917957d6554Steve Block for (NSValue *thisRangeValue in loadedRanges) { 4982bde8e466a4451c7319e3a072d118917957d6554Steve Block CMTimeRange timeRange = [thisRangeValue CMTimeRangeValue]; 4992bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!CMTIMERANGE_IS_VALID(timeRange) || CMTIMERANGE_IS_EMPTY(timeRange)) 5002bde8e466a4451c7319e3a072d118917957d6554Steve Block continue; 5012bde8e466a4451c7319e3a072d118917957d6554Steve Block 5022bde8e466a4451c7319e3a072d118917957d6554Steve Block float endOfRange = narrowPrecisionToFloat(CMTimeGetSeconds(CMTimeRangeGetEnd(timeRange))); 5032bde8e466a4451c7319e3a072d118917957d6554Steve Block if (maxTimeLoaded < endOfRange) 5042bde8e466a4451c7319e3a072d118917957d6554Steve Block maxTimeLoaded = endOfRange; 5052bde8e466a4451c7319e3a072d118917957d6554Steve Block } 5062bde8e466a4451c7319e3a072d118917957d6554Steve Block 5072bde8e466a4451c7319e3a072d118917957d6554Steve Block return maxTimeLoaded; 5082bde8e466a4451c7319e3a072d118917957d6554Steve Block} 5092bde8e466a4451c7319e3a072d118917957d6554Steve Block 5102bde8e466a4451c7319e3a072d118917957d6554Steve Blockunsigned MediaPlayerPrivateAVFoundationObjC::totalBytes() const 5112bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 5122bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!metaDataAvailable()) 5132bde8e466a4451c7319e3a072d118917957d6554Steve Block return 0; 5142bde8e466a4451c7319e3a072d118917957d6554Steve Block 5152bde8e466a4451c7319e3a072d118917957d6554Steve Block long long totalMediaSize = 0; 5162bde8e466a4451c7319e3a072d118917957d6554Steve Block NSArray *tracks = [m_avAsset.get() tracks]; 5172bde8e466a4451c7319e3a072d118917957d6554Steve Block for (AVAssetTrack *thisTrack in tracks) 5182bde8e466a4451c7319e3a072d118917957d6554Steve Block totalMediaSize += [thisTrack totalSampleDataLength]; 5192bde8e466a4451c7319e3a072d118917957d6554Steve Block 5202bde8e466a4451c7319e3a072d118917957d6554Steve Block return static_cast<unsigned>(totalMediaSize); 5212bde8e466a4451c7319e3a072d118917957d6554Steve Block} 5222bde8e466a4451c7319e3a072d118917957d6554Steve Block 5232bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateAVFoundationObjC::setAsset(id asset) 5242bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 5252bde8e466a4451c7319e3a072d118917957d6554Steve Block m_avAsset = asset; 5262bde8e466a4451c7319e3a072d118917957d6554Steve Block} 5272bde8e466a4451c7319e3a072d118917957d6554Steve Block 5282bde8e466a4451c7319e3a072d118917957d6554Steve BlockMediaPlayerPrivateAVFoundation::AVAssetStatus MediaPlayerPrivateAVFoundationObjC::assetStatus() const 5292bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 5302bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!m_avAsset) 5312bde8e466a4451c7319e3a072d118917957d6554Steve Block return MediaPlayerAVAssetStatusUnknown; 5322bde8e466a4451c7319e3a072d118917957d6554Steve Block 5332bde8e466a4451c7319e3a072d118917957d6554Steve Block for (NSString *keyName in assetMetadataKeyNames()) { 5342bde8e466a4451c7319e3a072d118917957d6554Steve Block AVKeyValueStatus keyStatus = [m_avAsset.get() statusOfValueForKey:keyName error:nil]; 5352bde8e466a4451c7319e3a072d118917957d6554Steve Block if (keyStatus < AVKeyValueStatusLoaded) 5362bde8e466a4451c7319e3a072d118917957d6554Steve Block return MediaPlayerAVAssetStatusLoading;// At least one key is not loaded yet. 5372bde8e466a4451c7319e3a072d118917957d6554Steve Block 5382bde8e466a4451c7319e3a072d118917957d6554Steve Block if (keyStatus == AVKeyValueStatusFailed) 5392bde8e466a4451c7319e3a072d118917957d6554Steve Block return MediaPlayerAVAssetStatusFailed; // At least one key could not be loaded. 5402bde8e466a4451c7319e3a072d118917957d6554Steve Block if (keyStatus == AVKeyValueStatusCancelled) 5412bde8e466a4451c7319e3a072d118917957d6554Steve Block return MediaPlayerAVAssetStatusCancelled; // Loading of at least one key was cancelled. 5422bde8e466a4451c7319e3a072d118917957d6554Steve Block } 5432bde8e466a4451c7319e3a072d118917957d6554Steve Block 5442bde8e466a4451c7319e3a072d118917957d6554Steve Block if ([[m_avAsset.get() valueForKey:@"playable"] boolValue]) 5452bde8e466a4451c7319e3a072d118917957d6554Steve Block return MediaPlayerAVAssetStatusPlayable; 5462bde8e466a4451c7319e3a072d118917957d6554Steve Block 5472bde8e466a4451c7319e3a072d118917957d6554Steve Block return MediaPlayerAVAssetStatusLoaded; 5482bde8e466a4451c7319e3a072d118917957d6554Steve Block} 5492bde8e466a4451c7319e3a072d118917957d6554Steve Block 5502bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateAVFoundationObjC::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& rect) 5512bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 5522bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!metaDataAvailable() || context->paintingDisabled()) 5532bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 5542bde8e466a4451c7319e3a072d118917957d6554Steve Block 5552bde8e466a4451c7319e3a072d118917957d6554Steve Block paint(context, rect); 5562bde8e466a4451c7319e3a072d118917957d6554Steve Block} 5572bde8e466a4451c7319e3a072d118917957d6554Steve Block 5582bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateAVFoundationObjC::paint(GraphicsContext* context, const IntRect& rect) 5592bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 5602bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!metaDataAvailable() || context->paintingDisabled()) 5612bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 5622bde8e466a4451c7319e3a072d118917957d6554Steve Block 5632bde8e466a4451c7319e3a072d118917957d6554Steve Block setDelayCallbacks(true); 5642bde8e466a4451c7319e3a072d118917957d6554Steve Block BEGIN_BLOCK_OBJC_EXCEPTIONS; 5652bde8e466a4451c7319e3a072d118917957d6554Steve Block 5662bde8e466a4451c7319e3a072d118917957d6554Steve Block RetainPtr<CGImageRef> image = createImageForTimeInRect(currentTime(), rect); 5672bde8e466a4451c7319e3a072d118917957d6554Steve Block if (image) { 5682bde8e466a4451c7319e3a072d118917957d6554Steve Block context->save(); 5692bde8e466a4451c7319e3a072d118917957d6554Steve Block context->translate(rect.x(), rect.y() + rect.height()); 5702bde8e466a4451c7319e3a072d118917957d6554Steve Block context->scale(FloatSize(1.0f, -1.0f)); 5712bde8e466a4451c7319e3a072d118917957d6554Steve Block context->setImageInterpolationQuality(InterpolationLow); 5722bde8e466a4451c7319e3a072d118917957d6554Steve Block IntRect paintRect(IntPoint(0, 0), IntSize(rect.width(), rect.height())); 5732bde8e466a4451c7319e3a072d118917957d6554Steve Block CGContextDrawImage(context->platformContext(), CGRectMake(0, 0, paintRect.width(), paintRect.height()), image.get()); 5742bde8e466a4451c7319e3a072d118917957d6554Steve Block context->restore(); 5752bde8e466a4451c7319e3a072d118917957d6554Steve Block image = 0; 5762bde8e466a4451c7319e3a072d118917957d6554Steve Block } 5772bde8e466a4451c7319e3a072d118917957d6554Steve Block 5782bde8e466a4451c7319e3a072d118917957d6554Steve Block END_BLOCK_OBJC_EXCEPTIONS; 5792bde8e466a4451c7319e3a072d118917957d6554Steve Block setDelayCallbacks(false); 5802bde8e466a4451c7319e3a072d118917957d6554Steve Block 5812bde8e466a4451c7319e3a072d118917957d6554Steve Block MediaPlayerPrivateAVFoundation::paint(context, rect); 5822bde8e466a4451c7319e3a072d118917957d6554Steve Block} 5832bde8e466a4451c7319e3a072d118917957d6554Steve Block 5842bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic HashSet<String> mimeTypeCache() 5852bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 5862bde8e466a4451c7319e3a072d118917957d6554Steve Block DEFINE_STATIC_LOCAL(HashSet<String>, cache, ()); 5872bde8e466a4451c7319e3a072d118917957d6554Steve Block static bool typeListInitialized = false; 5882bde8e466a4451c7319e3a072d118917957d6554Steve Block 5892bde8e466a4451c7319e3a072d118917957d6554Steve Block if (typeListInitialized) 5902bde8e466a4451c7319e3a072d118917957d6554Steve Block return cache; 5912bde8e466a4451c7319e3a072d118917957d6554Steve Block typeListInitialized = true; 5922bde8e466a4451c7319e3a072d118917957d6554Steve Block 5932bde8e466a4451c7319e3a072d118917957d6554Steve Block NSArray *types = [AVURLAsset audiovisualMIMETypes]; 5942bde8e466a4451c7319e3a072d118917957d6554Steve Block for (NSString *mimeType in types) 5952bde8e466a4451c7319e3a072d118917957d6554Steve Block cache.add(mimeType); 5962bde8e466a4451c7319e3a072d118917957d6554Steve Block 5972bde8e466a4451c7319e3a072d118917957d6554Steve Block return cache; 5982bde8e466a4451c7319e3a072d118917957d6554Steve Block} 5992bde8e466a4451c7319e3a072d118917957d6554Steve Block 6002bde8e466a4451c7319e3a072d118917957d6554Steve BlockRetainPtr<CGImageRef> MediaPlayerPrivateAVFoundationObjC::createImageForTimeInRect(float time, const IntRect& rect) 6012bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 6022bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!m_imageGenerator) 6032bde8e466a4451c7319e3a072d118917957d6554Steve Block createContextVideoRenderer(); 6042bde8e466a4451c7319e3a072d118917957d6554Steve Block ASSERT(m_imageGenerator); 6052bde8e466a4451c7319e3a072d118917957d6554Steve Block 6062bde8e466a4451c7319e3a072d118917957d6554Steve Block#if !LOG_DISABLED 6072bde8e466a4451c7319e3a072d118917957d6554Steve Block double start = WTF::currentTime(); 6082bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif 6092bde8e466a4451c7319e3a072d118917957d6554Steve Block 6102bde8e466a4451c7319e3a072d118917957d6554Steve Block [m_imageGenerator.get() setMaximumSize:CGSize(rect.size())]; 6112bde8e466a4451c7319e3a072d118917957d6554Steve Block CGImageRef image = [m_imageGenerator.get() copyCGImageAtTime:CMTimeMakeWithSeconds(time, 600) actualTime:nil error:nil]; 6122bde8e466a4451c7319e3a072d118917957d6554Steve Block 6132bde8e466a4451c7319e3a072d118917957d6554Steve Block#if !LOG_DISABLED 6142bde8e466a4451c7319e3a072d118917957d6554Steve Block double duration = WTF::currentTime() - start; 6152bde8e466a4451c7319e3a072d118917957d6554Steve Block LOG(Media, "MediaPlayerPrivateAVFoundationObjC::createImageForTimeInRect(%p) - creating image took %.4f", this, narrowPrecisionToFloat(duration)); 6162bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif 6172bde8e466a4451c7319e3a072d118917957d6554Steve Block 6182bde8e466a4451c7319e3a072d118917957d6554Steve Block return image; 6192bde8e466a4451c7319e3a072d118917957d6554Steve Block} 6202bde8e466a4451c7319e3a072d118917957d6554Steve Block 6212bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateAVFoundationObjC::getSupportedTypes(HashSet<String>& supportedTypes) 6222bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 6232bde8e466a4451c7319e3a072d118917957d6554Steve Block supportedTypes = mimeTypeCache(); 6242bde8e466a4451c7319e3a072d118917957d6554Steve Block} 6252bde8e466a4451c7319e3a072d118917957d6554Steve Block 6262bde8e466a4451c7319e3a072d118917957d6554Steve BlockMediaPlayer::SupportsType MediaPlayerPrivateAVFoundationObjC::supportsType(const String& type, const String& codecs) 6272bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 6282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (!mimeTypeCache().contains(type)) 6292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return MediaPlayer::IsNotSupported; 6302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 6312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // The spec says: 6322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // "Implementors are encouraged to return "maybe" unless the type can be confidently established as being supported or not." 6332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (codecs.isEmpty()) 6342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return MediaPlayer::MayBeSupported; 6352bde8e466a4451c7319e3a072d118917957d6554Steve Block 6362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch NSString *typeString = [NSString stringWithFormat:@"%@; codecs=\"%@\"", (NSString *)type, (NSString *)codecs]; 6372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return [AVURLAsset isPlayableExtendedMIMEType:typeString] ? MediaPlayer::IsSupported : MediaPlayer::MayBeSupported;; 6382bde8e466a4451c7319e3a072d118917957d6554Steve Block} 6392bde8e466a4451c7319e3a072d118917957d6554Steve Block 6402bde8e466a4451c7319e3a072d118917957d6554Steve Blockbool MediaPlayerPrivateAVFoundationObjC::isAvailable() 6412bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 6422bde8e466a4451c7319e3a072d118917957d6554Steve Block return true; 6432bde8e466a4451c7319e3a072d118917957d6554Steve Block} 6442bde8e466a4451c7319e3a072d118917957d6554Steve Block 6452bde8e466a4451c7319e3a072d118917957d6554Steve Blockfloat MediaPlayerPrivateAVFoundationObjC::mediaTimeForTimeValue(float timeValue) const 6462bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 6472bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!metaDataAvailable()) 6482bde8e466a4451c7319e3a072d118917957d6554Steve Block return timeValue; 6492bde8e466a4451c7319e3a072d118917957d6554Steve Block 6502bde8e466a4451c7319e3a072d118917957d6554Steve Block // FIXME - impossible to implement until rdar://8721510 is fixed. 6512bde8e466a4451c7319e3a072d118917957d6554Steve Block return timeValue; 6522bde8e466a4451c7319e3a072d118917957d6554Steve Block} 6532bde8e466a4451c7319e3a072d118917957d6554Steve Block 6542bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateAVFoundationObjC::tracksChanged() 6552bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 6562bde8e466a4451c7319e3a072d118917957d6554Steve Block // This is called whenever the tracks collection changes so cache hasVideo and hasAudio since we get 6572bde8e466a4451c7319e3a072d118917957d6554Steve Block // asked about those fairly fequently. 6582bde8e466a4451c7319e3a072d118917957d6554Steve Block setHasVideo([[m_avAsset.get() tracksWithMediaCharacteristic:AVMediaCharacteristicVisual] count]); 6592bde8e466a4451c7319e3a072d118917957d6554Steve Block setHasAudio([[m_avAsset.get() tracksWithMediaCharacteristic:AVMediaCharacteristicAudible] count]); 6602bde8e466a4451c7319e3a072d118917957d6554Steve Block setHasClosedCaptions([[m_avAsset.get() tracksWithMediaType:AVMediaTypeClosedCaption] count]); 6612bde8e466a4451c7319e3a072d118917957d6554Steve Block 6622bde8e466a4451c7319e3a072d118917957d6554Steve Block sizeChanged(); 6632bde8e466a4451c7319e3a072d118917957d6554Steve Block} 6642bde8e466a4451c7319e3a072d118917957d6554Steve Block 6652bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateAVFoundationObjC::sizeChanged() 6662bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 6672bde8e466a4451c7319e3a072d118917957d6554Steve Block NSArray *tracks = [m_avAsset.get() tracks]; 6682bde8e466a4451c7319e3a072d118917957d6554Steve Block 6692bde8e466a4451c7319e3a072d118917957d6554Steve Block // Some assets don't report track properties until they are completely ready to play, but we 6702bde8e466a4451c7319e3a072d118917957d6554Steve Block // want to report a size as early as possible so use presentationSize when an asset has no tracks. 6712bde8e466a4451c7319e3a072d118917957d6554Steve Block if (![tracks count]) { 6722bde8e466a4451c7319e3a072d118917957d6554Steve Block setNaturalSize(IntSize([m_avPlayerItem.get() presentationSize])); 6732bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 6742bde8e466a4451c7319e3a072d118917957d6554Steve Block } 6752bde8e466a4451c7319e3a072d118917957d6554Steve Block 6762bde8e466a4451c7319e3a072d118917957d6554Steve Block // AVAsset's 'naturalSize' property only considers the movie's first video track, so we need to compute 6772bde8e466a4451c7319e3a072d118917957d6554Steve Block // the union of all visual track rects. 6782bde8e466a4451c7319e3a072d118917957d6554Steve Block CGRect trackUnionRect = CGRectZero; 6792bde8e466a4451c7319e3a072d118917957d6554Steve Block for (AVAssetTrack *track in tracks) { 6802bde8e466a4451c7319e3a072d118917957d6554Steve Block CGSize trackSize = [track naturalSize]; 6812bde8e466a4451c7319e3a072d118917957d6554Steve Block CGRect trackRect = CGRectMake(0, 0, trackSize.width, trackSize.height); 6822bde8e466a4451c7319e3a072d118917957d6554Steve Block trackUnionRect = CGRectUnion(trackUnionRect, CGRectApplyAffineTransform(trackRect, [track preferredTransform])); 6832bde8e466a4451c7319e3a072d118917957d6554Steve Block } 6842bde8e466a4451c7319e3a072d118917957d6554Steve Block 6852bde8e466a4451c7319e3a072d118917957d6554Steve Block // The movie is always displayed at 0,0 so move the track rect to the origin before using width and height. 6862bde8e466a4451c7319e3a072d118917957d6554Steve Block trackUnionRect = CGRectOffset(trackUnionRect, trackUnionRect.origin.x, trackUnionRect.origin.y); 6872bde8e466a4451c7319e3a072d118917957d6554Steve Block 6882bde8e466a4451c7319e3a072d118917957d6554Steve Block // Also look at the asset's preferred transform so we account for a movie matrix. 6892bde8e466a4451c7319e3a072d118917957d6554Steve Block CGSize naturalSize = CGSizeApplyAffineTransform(trackUnionRect.size, [m_avAsset.get() preferredTransform]); 6902bde8e466a4451c7319e3a072d118917957d6554Steve Block 6912bde8e466a4451c7319e3a072d118917957d6554Steve Block // Cache the natural size (setNaturalSize will notify the player if it has changed). 6922bde8e466a4451c7319e3a072d118917957d6554Steve Block setNaturalSize(IntSize(naturalSize)); 6932bde8e466a4451c7319e3a072d118917957d6554Steve Block} 6942bde8e466a4451c7319e3a072d118917957d6554Steve Block 6952bde8e466a4451c7319e3a072d118917957d6554Steve BlockNSArray* assetMetadataKeyNames() 6962bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 6972bde8e466a4451c7319e3a072d118917957d6554Steve Block static NSArray* keys; 6982bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!keys) { 6992bde8e466a4451c7319e3a072d118917957d6554Steve Block keys = [[NSArray alloc] initWithObjects:@"duration", 7002bde8e466a4451c7319e3a072d118917957d6554Steve Block @"naturalSize", 7012bde8e466a4451c7319e3a072d118917957d6554Steve Block @"preferredTransform", 7022bde8e466a4451c7319e3a072d118917957d6554Steve Block @"preferredVolume", 7032bde8e466a4451c7319e3a072d118917957d6554Steve Block @"preferredRate", 7042bde8e466a4451c7319e3a072d118917957d6554Steve Block @"playable", 7052bde8e466a4451c7319e3a072d118917957d6554Steve Block @"tracks", 7062bde8e466a4451c7319e3a072d118917957d6554Steve Block nil]; 7072bde8e466a4451c7319e3a072d118917957d6554Steve Block } 7082bde8e466a4451c7319e3a072d118917957d6554Steve Block return keys; 7092bde8e466a4451c7319e3a072d118917957d6554Steve Block} 7102bde8e466a4451c7319e3a072d118917957d6554Steve Block 7112bde8e466a4451c7319e3a072d118917957d6554Steve BlockNSArray* itemKVOProperties() 7122bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 7132bde8e466a4451c7319e3a072d118917957d6554Steve Block static NSArray* keys; 7142bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!keys) { 7152bde8e466a4451c7319e3a072d118917957d6554Steve Block keys = [[NSArray alloc] initWithObjects:@"presentationSize", 7162bde8e466a4451c7319e3a072d118917957d6554Steve Block @"status", 7172bde8e466a4451c7319e3a072d118917957d6554Steve Block @"asset", 7182bde8e466a4451c7319e3a072d118917957d6554Steve Block @"tracks", 7192bde8e466a4451c7319e3a072d118917957d6554Steve Block @"seekableTimeRanges", 7202bde8e466a4451c7319e3a072d118917957d6554Steve Block @"loadedTimeRanges", 7212bde8e466a4451c7319e3a072d118917957d6554Steve Block @"playbackLikelyToKeepUp", 7222bde8e466a4451c7319e3a072d118917957d6554Steve Block @"playbackBufferFull", 7232bde8e466a4451c7319e3a072d118917957d6554Steve Block @"playbackBufferEmpty", 7242bde8e466a4451c7319e3a072d118917957d6554Steve Block nil]; 7252bde8e466a4451c7319e3a072d118917957d6554Steve Block } 7262bde8e466a4451c7319e3a072d118917957d6554Steve Block return keys; 7272bde8e466a4451c7319e3a072d118917957d6554Steve Block} 7282bde8e466a4451c7319e3a072d118917957d6554Steve Block 7292bde8e466a4451c7319e3a072d118917957d6554Steve Block} // namespace WebCore 7302bde8e466a4451c7319e3a072d118917957d6554Steve Block 7312bde8e466a4451c7319e3a072d118917957d6554Steve Block@implementation WebCoreAVFMovieObserver 7322bde8e466a4451c7319e3a072d118917957d6554Steve Block 7332bde8e466a4451c7319e3a072d118917957d6554Steve Block- (id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC*)callback 7342bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 7352bde8e466a4451c7319e3a072d118917957d6554Steve Block m_callback = callback; 7362bde8e466a4451c7319e3a072d118917957d6554Steve Block return [super init]; 7372bde8e466a4451c7319e3a072d118917957d6554Steve Block} 7382bde8e466a4451c7319e3a072d118917957d6554Steve Block 7392bde8e466a4451c7319e3a072d118917957d6554Steve Block- (void)disconnect 7402bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 7412bde8e466a4451c7319e3a072d118917957d6554Steve Block [NSObject cancelPreviousPerformRequestsWithTarget:self]; 7422bde8e466a4451c7319e3a072d118917957d6554Steve Block m_callback = 0; 7432bde8e466a4451c7319e3a072d118917957d6554Steve Block} 7442bde8e466a4451c7319e3a072d118917957d6554Steve Block 7452bde8e466a4451c7319e3a072d118917957d6554Steve Block- (void)metadataLoaded 7462bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 7472bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!m_callback) 7482bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 7492bde8e466a4451c7319e3a072d118917957d6554Steve Block 7502bde8e466a4451c7319e3a072d118917957d6554Steve Block m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::AssetMetadataLoaded); 7512bde8e466a4451c7319e3a072d118917957d6554Steve Block} 7522bde8e466a4451c7319e3a072d118917957d6554Steve Block 7532bde8e466a4451c7319e3a072d118917957d6554Steve Block- (void)playableKnown 7542bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 7552bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!m_callback) 7562bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 7572bde8e466a4451c7319e3a072d118917957d6554Steve Block 7582bde8e466a4451c7319e3a072d118917957d6554Steve Block m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::AssetPlayabilityKnown); 7592bde8e466a4451c7319e3a072d118917957d6554Steve Block} 7602bde8e466a4451c7319e3a072d118917957d6554Steve Block 7612bde8e466a4451c7319e3a072d118917957d6554Steve Block- (void)timeChanged:(double)time 7622bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 7632bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!m_callback) 7642bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 7652bde8e466a4451c7319e3a072d118917957d6554Steve Block 7662bde8e466a4451c7319e3a072d118917957d6554Steve Block m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::PlayerTimeChanged, time); 7672bde8e466a4451c7319e3a072d118917957d6554Steve Block} 7682bde8e466a4451c7319e3a072d118917957d6554Steve Block 7692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch- (void)seekCompleted:(BOOL)finished 7702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{ 7712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (!m_callback) 7722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return; 7732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 7742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::SeekCompleted, static_cast<bool>(finished)); 7752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch} 7762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 7772bde8e466a4451c7319e3a072d118917957d6554Steve Block- (void)didEnd:(NSNotification *)unusedNotification 7782bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 7792bde8e466a4451c7319e3a072d118917957d6554Steve Block UNUSED_PARAM(unusedNotification); 7802bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!m_callback) 7812bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 7822bde8e466a4451c7319e3a072d118917957d6554Steve Block m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemDidPlayToEndTime); 7832bde8e466a4451c7319e3a072d118917957d6554Steve Block} 7842bde8e466a4451c7319e3a072d118917957d6554Steve Block 7852bde8e466a4451c7319e3a072d118917957d6554Steve Block- (void)observeValueForKeyPath:keyPath ofObject:(id)object change:(NSDictionary *)change context:(MediaPlayerAVFoundationObservationContext)context 7862bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 7872bde8e466a4451c7319e3a072d118917957d6554Steve Block UNUSED_PARAM(change); 7882bde8e466a4451c7319e3a072d118917957d6554Steve Block 7892bde8e466a4451c7319e3a072d118917957d6554Steve Block LOG(Media, "WebCoreAVFMovieObserver:observeValueForKeyPath(%p) - keyPath = %s", self, [keyPath UTF8String]); 7902bde8e466a4451c7319e3a072d118917957d6554Steve Block 7912bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!m_callback) 7922bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 7932bde8e466a4451c7319e3a072d118917957d6554Steve Block 7942bde8e466a4451c7319e3a072d118917957d6554Steve Block if (context == MediaPlayerAVFoundationObservationContextPlayerItem) { 7952bde8e466a4451c7319e3a072d118917957d6554Steve Block // A value changed for an AVPlayerItem 7962bde8e466a4451c7319e3a072d118917957d6554Steve Block if ([keyPath isEqualToString:@"status"]) 7972bde8e466a4451c7319e3a072d118917957d6554Steve Block m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemStatusChanged); 7982bde8e466a4451c7319e3a072d118917957d6554Steve Block else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"]) 7992bde8e466a4451c7319e3a072d118917957d6554Steve Block m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemIsPlaybackLikelyToKeepUpChanged); 8002bde8e466a4451c7319e3a072d118917957d6554Steve Block else if ([keyPath isEqualToString:@"playbackBufferEmpty"]) 8012bde8e466a4451c7319e3a072d118917957d6554Steve Block m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemIsPlaybackBufferEmptyChanged); 8022bde8e466a4451c7319e3a072d118917957d6554Steve Block else if ([keyPath isEqualToString:@"playbackBufferFull"]) 8032bde8e466a4451c7319e3a072d118917957d6554Steve Block m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemIsPlaybackBufferFullChanged); 8042bde8e466a4451c7319e3a072d118917957d6554Steve Block else if ([keyPath isEqualToString:@"asset"]) 8052bde8e466a4451c7319e3a072d118917957d6554Steve Block m_callback->setAsset([object asset]); 8062bde8e466a4451c7319e3a072d118917957d6554Steve Block else if ([keyPath isEqualToString:@"loadedTimeRanges"]) 8072bde8e466a4451c7319e3a072d118917957d6554Steve Block m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemLoadedTimeRangesChanged); 8082bde8e466a4451c7319e3a072d118917957d6554Steve Block else if ([keyPath isEqualToString:@"seekableTimeRanges"]) 8092bde8e466a4451c7319e3a072d118917957d6554Steve Block m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemSeekableTimeRangesChanged); 8102bde8e466a4451c7319e3a072d118917957d6554Steve Block else if ([keyPath isEqualToString:@"tracks"]) 8112bde8e466a4451c7319e3a072d118917957d6554Steve Block m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemTracksChanged); 8122bde8e466a4451c7319e3a072d118917957d6554Steve Block else if ([keyPath isEqualToString:@"presentationSize"]) 8132bde8e466a4451c7319e3a072d118917957d6554Steve Block m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::ItemPresentationSizeChanged); 8142bde8e466a4451c7319e3a072d118917957d6554Steve Block 8152bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 8162bde8e466a4451c7319e3a072d118917957d6554Steve Block } 8172bde8e466a4451c7319e3a072d118917957d6554Steve Block 8182bde8e466a4451c7319e3a072d118917957d6554Steve Block if (context == MediaPlayerAVFoundationObservationContextPlayer) { 8192bde8e466a4451c7319e3a072d118917957d6554Steve Block // A value changed for an AVPlayer. 8202bde8e466a4451c7319e3a072d118917957d6554Steve Block if ([keyPath isEqualToString:@"rate"]) 8212bde8e466a4451c7319e3a072d118917957d6554Steve Block m_callback->scheduleMainThreadNotification(MediaPlayerPrivateAVFoundation::Notification::PlayerRateChanged); 8222bde8e466a4451c7319e3a072d118917957d6554Steve Block} 8232bde8e466a4451c7319e3a072d118917957d6554Steve Block} 8242bde8e466a4451c7319e3a072d118917957d6554Steve Block 8252bde8e466a4451c7319e3a072d118917957d6554Steve Block@end 8262bde8e466a4451c7319e3a072d118917957d6554Steve Block 8272bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif 828