📄 mediaplayerprivateqtkit.mm
字号:
/* * Copyright (C) 2007, 2008, 2009 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 COMPUTER, 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 COMPUTER, 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"#if ENABLE(VIDEO)#import "MediaPlayerPrivateQTKit.h"#ifdef BUILDING_ON_TIGER#import "AutodrainedPool.h"#endif#import "BlockExceptions.h"#import "FrameView.h"#import "GraphicsContext.h"#import "KURL.h"#import "SoftLinking.h"#import "WebCoreSystemInterface.h"#import <QTKit/QTKit.h>#import <objc/objc-runtime.h>#import <wtf/UnusedParam.h>#if DRAW_FRAME_RATE#import "Font.h"#import "Frame.h"#import "Document.h"#import "RenderObject.h"#import "RenderStyle.h"#endif#ifdef BUILDING_ON_TIGERstatic IMP method_setImplementation(Method m, IMP imp){ IMP result = m->method_imp; m->method_imp = imp; return result;}#endifSOFT_LINK_FRAMEWORK(QTKit)SOFT_LINK(QTKit, QTMakeTime, QTTime, (long long timeValue, long timeScale), (timeValue, timeScale))SOFT_LINK_CLASS(QTKit, QTMovie)SOFT_LINK_CLASS(QTKit, QTMovieView)SOFT_LINK_POINTER(QTKit, QTMediaTypeAttribute, NSString *)SOFT_LINK_POINTER(QTKit, QTMediaTypeBase, NSString *)SOFT_LINK_POINTER(QTKit, QTMediaTypeMPEG, NSString *)SOFT_LINK_POINTER(QTKit, QTMediaTypeSound, NSString *)SOFT_LINK_POINTER(QTKit, QTMediaTypeText, NSString *)SOFT_LINK_POINTER(QTKit, QTMediaTypeVideo, NSString *)SOFT_LINK_POINTER(QTKit, QTMovieAskUnresolvedDataRefsAttribute, NSString *)SOFT_LINK_POINTER(QTKit, QTMovieDataSizeAttribute, NSString *)SOFT_LINK_POINTER(QTKit, QTMovieDidEndNotification, NSString *)SOFT_LINK_POINTER(QTKit, QTMovieHasVideoAttribute, NSString *)SOFT_LINK_POINTER(QTKit, QTMovieIsActiveAttribute, NSString *)SOFT_LINK_POINTER(QTKit, QTMovieLoadStateAttribute, NSString *)SOFT_LINK_POINTER(QTKit, QTMovieLoadStateDidChangeNotification, NSString *)SOFT_LINK_POINTER(QTKit, QTMovieNaturalSizeAttribute, NSString *)SOFT_LINK_POINTER(QTKit, QTMoviePreventExternalURLLinksAttribute, NSString *)SOFT_LINK_POINTER(QTKit, QTMovieRateDidChangeNotification, NSString *)SOFT_LINK_POINTER(QTKit, QTMovieSizeDidChangeNotification, NSString *)SOFT_LINK_POINTER(QTKit, QTMovieTimeDidChangeNotification, NSString *)SOFT_LINK_POINTER(QTKit, QTMovieTimeScaleAttribute, NSString *)SOFT_LINK_POINTER(QTKit, QTMovieURLAttribute, NSString *)SOFT_LINK_POINTER(QTKit, QTMovieVolumeDidChangeNotification, NSString *)SOFT_LINK_POINTER(QTKit, QTSecurityPolicyNoCrossSiteAttribute, NSString *)SOFT_LINK_POINTER(QTKit, QTVideoRendererWebKitOnlyNewImageAvailableNotification, NSString *)#define QTMovie getQTMovieClass()#define QTMovieView getQTMovieViewClass()#define QTMediaTypeAttribute getQTMediaTypeAttribute()#define QTMediaTypeBase getQTMediaTypeBase()#define QTMediaTypeMPEG getQTMediaTypeMPEG()#define QTMediaTypeSound getQTMediaTypeSound()#define QTMediaTypeText getQTMediaTypeText()#define QTMediaTypeVideo getQTMediaTypeVideo()#define QTMovieAskUnresolvedDataRefsAttribute getQTMovieAskUnresolvedDataRefsAttribute()#define QTMovieDataSizeAttribute getQTMovieDataSizeAttribute()#define QTMovieDidEndNotification getQTMovieDidEndNotification()#define QTMovieHasVideoAttribute getQTMovieHasVideoAttribute()#define QTMovieIsActiveAttribute getQTMovieIsActiveAttribute()#define QTMovieLoadStateAttribute getQTMovieLoadStateAttribute()#define QTMovieLoadStateDidChangeNotification getQTMovieLoadStateDidChangeNotification()#define QTMovieNaturalSizeAttribute getQTMovieNaturalSizeAttribute()#define QTMoviePreventExternalURLLinksAttribute getQTMoviePreventExternalURLLinksAttribute()#define QTMovieRateDidChangeNotification getQTMovieRateDidChangeNotification()#define QTMovieSizeDidChangeNotification getQTMovieSizeDidChangeNotification()#define QTMovieTimeDidChangeNotification getQTMovieTimeDidChangeNotification()#define QTMovieTimeScaleAttribute getQTMovieTimeScaleAttribute()#define QTMovieURLAttribute getQTMovieURLAttribute()#define QTMovieVolumeDidChangeNotification getQTMovieVolumeDidChangeNotification()#define QTSecurityPolicyNoCrossSiteAttribute getQTSecurityPolicyNoCrossSiteAttribute()#define QTVideoRendererWebKitOnlyNewImageAvailableNotification getQTVideoRendererWebKitOnlyNewImageAvailableNotification()// Older versions of the QTKit header don't have these constants.#if !defined QTKIT_VERSION_MAX_ALLOWED || QTKIT_VERSION_MAX_ALLOWED <= QTKIT_VERSION_7_0enum { QTMovieLoadStateError = -1L, QTMovieLoadStateLoaded = 2000L, QTMovieLoadStatePlayable = 10000L, QTMovieLoadStatePlaythroughOK = 20000L, QTMovieLoadStateComplete = 100000L};#endifusing namespace WebCore;using namespace std;@interface WebCoreMovieObserver : NSObject{ MediaPlayerPrivate* m_callback; NSView* m_view; BOOL m_delayCallbacks;}-(id)initWithCallback:(MediaPlayerPrivate*)callback;-(void)disconnect;-(void)setView:(NSView*)view;-(void)repaint;-(void)setDelayCallbacks:(BOOL)shouldDelay;-(void)loadStateChanged:(NSNotification *)notification;-(void)rateChanged:(NSNotification *)notification;-(void)sizeChanged:(NSNotification *)notification;-(void)timeChanged:(NSNotification *)notification;-(void)didEnd:(NSNotification *)notification;@end@protocol WebKitVideoRenderingDetails-(void)setMovie:(id)movie;-(void)drawInRect:(NSRect)rect;@endnamespace WebCore {static const float endPointTimerInterval = 0.020f;#ifdef BUILDING_ON_TIGERstatic const long minimumQuickTimeVersion = 0x07300000; // 7.3#endifMediaPlayerPrivateInterface* MediaPlayerPrivate::create(MediaPlayer* player) { return new MediaPlayerPrivate(player);}void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar){ if (isAvailable()) registrar(create, getSupportedTypes, supportsType);}MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) : m_player(player) , m_objcObserver(AdoptNS, [[WebCoreMovieObserver alloc] initWithCallback:this]) , m_seekTo(-1) , m_endTime(numeric_limits<float>::infinity()) , m_seekTimer(this, &MediaPlayerPrivate::seekTimerFired) , m_endPointTimer(this, &MediaPlayerPrivate::endPointTimerFired) , m_networkState(MediaPlayer::Empty) , m_readyState(MediaPlayer::DataUnavailable) , m_startedPlaying(false) , m_isStreaming(false) , m_visible(false) , m_rect()#if DRAW_FRAME_RATE , m_frameCountWhilePlaying(0) , m_timeStartedPlaying(0) , m_timeStoppedPlaying(0)#endif{}MediaPlayerPrivate::~MediaPlayerPrivate(){ tearDownVideoRendering(); [[NSNotificationCenter defaultCenter] removeObserver:m_objcObserver.get()]; [m_objcObserver.get() disconnect];}void MediaPlayerPrivate::createQTMovie(const String& url){ [[NSNotificationCenter defaultCenter] removeObserver:m_objcObserver.get()]; if (m_qtMovie) { destroyQTVideoRenderer(); m_qtMovie = 0; } // Disable streaming support for now, <rdar://problem/5693967> if (protocolIs(url, "rtsp")) return; NSURL *cocoaURL = KURL(url); NSDictionary *movieAttributes = [NSDictionary dictionaryWithObjectsAndKeys: cocoaURL, QTMovieURLAttribute, [NSNumber numberWithBool:YES], QTMoviePreventExternalURLLinksAttribute, [NSNumber numberWithBool:YES], QTSecurityPolicyNoCrossSiteAttribute, [NSNumber numberWithBool:NO], QTMovieAskUnresolvedDataRefsAttribute, [NSNumber numberWithBool:YES], @"QTMovieOpenForPlaybackAttribute", // FIXME: Use defined attribute when required version of QT supports this attribute nil]; NSError* error = nil; m_qtMovie.adoptNS([[QTMovie alloc] initWithAttributes:movieAttributes error:&error]); // FIXME: Find a proper way to detect streaming content. m_isStreaming = protocolIs(url, "rtsp"); if (!m_qtMovie) return; [m_qtMovie.get() setVolume:m_player->volume()]; [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get() selector:@selector(loadStateChanged:) name:QTMovieLoadStateDidChangeNotification object:m_qtMovie.get()]; [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get() selector:@selector(rateChanged:) name:QTMovieRateDidChangeNotification object:m_qtMovie.get()]; [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get() selector:@selector(sizeChanged:) name:QTMovieSizeDidChangeNotification object:m_qtMovie.get()]; [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get() selector:@selector(timeChanged:) name:QTMovieTimeDidChangeNotification object:m_qtMovie.get()]; [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get() selector:@selector(didEnd:) name:QTMovieDidEndNotification object:m_qtMovie.get()];}static void mainThreadSetNeedsDisplay(id self, SEL){ id movieView = [self superview]; ASSERT(!movieView || [movieView isKindOfClass:[QTMovieView class]]); if (!movieView || ![movieView isKindOfClass:[QTMovieView class]]) return; WebCoreMovieObserver* delegate = [movieView delegate]; ASSERT(!delegate || [delegate isKindOfClass:[WebCoreMovieObserver class]]); if (!delegate || ![delegate isKindOfClass:[WebCoreMovieObserver class]]) return; [delegate repaint];}static Class QTVideoRendererClass(){ static Class QTVideoRendererWebKitOnlyClass = NSClassFromString(@"QTVideoRendererWebKitOnly"); return QTVideoRendererWebKitOnlyClass;}void MediaPlayerPrivate::createQTMovieView(){ detachQTMovieView(); static bool addedCustomMethods = false; if (!addedCustomMethods) { Class QTMovieContentViewClass = NSClassFromString(@"QTMovieContentView"); ASSERT(QTMovieContentViewClass); Method mainThreadSetNeedsDisplayMethod = class_getInstanceMethod(QTMovieContentViewClass, @selector(_mainThreadSetNeedsDisplay)); ASSERT(mainThreadSetNeedsDisplayMethod); method_setImplementation(mainThreadSetNeedsDisplayMethod, reinterpret_cast<IMP>(mainThreadSetNeedsDisplay)); addedCustomMethods = true; } // delay callbacks as we *will* get notifications during setup [m_objcObserver.get() setDelayCallbacks:YES]; m_qtMovieView.adoptNS([[QTMovieView alloc] init]); setSize(m_player->size()); NSView* parentView = m_player->frameView()->documentView(); [parentView addSubview:m_qtMovieView.get()];#ifdef BUILDING_ON_TIGER // setDelegate: isn't a public call in Tiger, so use performSelector to keep the compiler happy [m_qtMovieView.get() performSelector:@selector(setDelegate:) withObject:m_objcObserver.get()]; #else [m_qtMovieView.get() setDelegate:m_objcObserver.get()];#endif [m_objcObserver.get() setView:m_qtMovieView.get()]; [m_qtMovieView.get() setMovie:m_qtMovie.get()]; [m_qtMovieView.get() setControllerVisible:NO]; [m_qtMovieView.get() setPreservesAspectRatio:NO]; // the area not covered by video should be transparent [m_qtMovieView.get() setFillColor:[NSColor clearColor]]; // If we're in a media document, allow QTMovieView to render in its default mode; // otherwise tell it to draw synchronously. // Note that we expect mainThreadSetNeedsDisplay to be invoked only when synchronous drawing is requested. if (!m_player->inMediaDocument()) wkQTMovieViewSetDrawSynchronously(m_qtMovieView.get(), YES); [m_objcObserver.get() setDelayCallbacks:NO];}void MediaPlayerPrivate::detachQTMovieView(){ if (m_qtMovieView) { [m_objcObserver.get() setView:nil];#ifdef BUILDING_ON_TIGER // setDelegate: isn't a public call in Tiger, so use performSelector to keep the compiler happy [m_qtMovieView.get() performSelector:@selector(setDelegate:) withObject:nil]; #else [m_qtMovieView.get() setDelegate:nil];#endif [m_qtMovieView.get() removeFromSuperview]; m_qtMovieView = nil; }}void MediaPlayerPrivate::createQTVideoRenderer(){ destroyQTVideoRenderer(); m_qtVideoRenderer.adoptNS([[QTVideoRendererClass() alloc] init]); if (!m_qtVideoRenderer) return; // associate our movie with our instance of QTVideoRendererWebKitOnly [(id<WebKitVideoRenderingDetails>)m_qtVideoRenderer.get() setMovie:m_qtMovie.get()]; // listen to QTVideoRendererWebKitOnly's QTVideoRendererWebKitOnlyNewImageDidBecomeAvailableNotification [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get() selector:@selector(newImageAvailable:) name:QTVideoRendererWebKitOnlyNewImageAvailableNotification object:m_qtVideoRenderer.get()];}void MediaPlayerPrivate::destroyQTVideoRenderer(){ if (!m_qtVideoRenderer)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -