18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch * Copyright (C) 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "config.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if ENABLE(VIDEO)
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "MediaPlayerPrivateQTKit.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
322bde8e466a4451c7319e3a072d118917957d6554Steve Block#if ENABLE(OFFLINE_WEB_APPLICATIONS)
332bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "ApplicationCacheHost.h"
342bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "ApplicationCacheResource.h"
352bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "DocumentLoader.h"
362bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif
372bde8e466a4451c7319e3a072d118917957d6554Steve Block
38635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#ifdef BUILDING_ON_TIGER
39635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#import "AutodrainedPool.h"
40635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif
41635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "BlockExceptions.h"
432bde8e466a4451c7319e3a072d118917957d6554Steve Block#import "DocumentLoader.h"
44635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#import "FrameView.h"
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "GraphicsContext.h"
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "KURL.h"
475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#import "MIMETypeRegistry.h"
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "SoftLinking.h"
49231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#import "TimeRanges.h"
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "WebCoreSystemInterface.h"
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import <QTKit/QTKit.h>
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import <objc/objc-runtime.h>
53635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#import <wtf/UnusedParam.h>
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if USE(ACCELERATED_COMPOSITING)
560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "GraphicsLayer.h"
570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if DRAW_FRAME_RATE
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "Font.h"
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "Frame.h"
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "Document.h"
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "RenderObject.h"
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#import "RenderStyle.h"
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef BUILDING_ON_TIGER
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic IMP method_setImplementation(Method m, IMP imp)
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    IMP result = m->method_imp;
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m->method_imp = imp;
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result;
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_FRAMEWORK(QTKit)
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK(QTKit, QTMakeTime, QTTime, (long long timeValue, long timeScale), (timeValue, timeScale))
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_CLASS(QTKit, QTMovie)
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_CLASS(QTKit, QTMovieView)
820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochSOFT_LINK_CLASS(QTKit, QTMovieLayer)
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
845f1ab04193ad0130ca8204aadaceae083aca9881Feng QianSOFT_LINK_POINTER(QTKit, QTTrackMediaTypeAttribute, NSString *)
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTMediaTypeAttribute, NSString *)
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTMediaTypeBase, NSString *)
878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianSOFT_LINK_POINTER(QTKit, QTMediaTypeMPEG, NSString *)
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTMediaTypeSound, NSString *)
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTMediaTypeText, NSString *)
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTMediaTypeVideo, NSString *)
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTMovieAskUnresolvedDataRefsAttribute, NSString *)
925ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenSOFT_LINK_POINTER(QTKit, QTMovieLoopsAttribute, NSString *)
932bde8e466a4451c7319e3a072d118917957d6554Steve BlockSOFT_LINK_POINTER(QTKit, QTMovieDataAttribute, NSString *)
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTMovieDataSizeAttribute, NSString *)
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTMovieDidEndNotification, NSString *)
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTMovieHasVideoAttribute, NSString *)
97231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockSOFT_LINK_POINTER(QTKit, QTMovieHasAudioAttribute, NSString *)
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTMovieIsActiveAttribute, NSString *)
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTMovieLoadStateAttribute, NSString *)
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTMovieLoadStateDidChangeNotification, NSString *)
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTMovieNaturalSizeAttribute, NSString *)
1025f1ab04193ad0130ca8204aadaceae083aca9881Feng QianSOFT_LINK_POINTER(QTKit, QTMovieCurrentSizeAttribute, NSString *)
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTMoviePreventExternalURLLinksAttribute, NSString *)
1040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochSOFT_LINK_POINTER(QTKit, QTMovieRateChangesPreservePitchAttribute, NSString *)
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTMovieRateDidChangeNotification, NSString *)
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTMovieSizeDidChangeNotification, NSString *)
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTMovieTimeDidChangeNotification, NSString *)
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTMovieTimeScaleAttribute, NSString *)
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTMovieURLAttribute, NSString *)
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTMovieVolumeDidChangeNotification, NSString *)
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTSecurityPolicyNoCrossSiteAttribute, NSString *)
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSOFT_LINK_POINTER(QTKit, QTVideoRendererWebKitOnlyNewImageAvailableNotification, NSString *)
1135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#ifndef BUILDING_ON_TIGER
1145f1ab04193ad0130ca8204aadaceae083aca9881Feng QianSOFT_LINK_POINTER(QTKit, QTMovieApertureModeClean, NSString *)
1155f1ab04193ad0130ca8204aadaceae083aca9881Feng QianSOFT_LINK_POINTER(QTKit, QTMovieApertureModeAttribute, NSString *)
1165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#endif
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMovie getQTMovieClass()
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMovieView getQTMovieViewClass()
1200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#define QTMovieLayer getQTMovieLayerClass()
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#define QTTrackMediaTypeAttribute getQTTrackMediaTypeAttribute()
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMediaTypeAttribute getQTMediaTypeAttribute()
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMediaTypeBase getQTMediaTypeBase()
1258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#define QTMediaTypeMPEG getQTMediaTypeMPEG()
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMediaTypeSound getQTMediaTypeSound()
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMediaTypeText getQTMediaTypeText()
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMediaTypeVideo getQTMediaTypeVideo()
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMovieAskUnresolvedDataRefsAttribute getQTMovieAskUnresolvedDataRefsAttribute()
1305ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen#define QTMovieLoopsAttribute getQTMovieLoopsAttribute()
1312bde8e466a4451c7319e3a072d118917957d6554Steve Block#define QTMovieDataAttribute getQTMovieDataAttribute()
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMovieDataSizeAttribute getQTMovieDataSizeAttribute()
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMovieDidEndNotification getQTMovieDidEndNotification()
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMovieHasVideoAttribute getQTMovieHasVideoAttribute()
135231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#define QTMovieHasAudioAttribute getQTMovieHasAudioAttribute()
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMovieIsActiveAttribute getQTMovieIsActiveAttribute()
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMovieLoadStateAttribute getQTMovieLoadStateAttribute()
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMovieLoadStateDidChangeNotification getQTMovieLoadStateDidChangeNotification()
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMovieNaturalSizeAttribute getQTMovieNaturalSizeAttribute()
1405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#define QTMovieCurrentSizeAttribute getQTMovieCurrentSizeAttribute()
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMoviePreventExternalURLLinksAttribute getQTMoviePreventExternalURLLinksAttribute()
1420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#define QTMovieRateChangesPreservePitchAttribute getQTMovieRateChangesPreservePitchAttribute()
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMovieRateDidChangeNotification getQTMovieRateDidChangeNotification()
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMovieSizeDidChangeNotification getQTMovieSizeDidChangeNotification()
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMovieTimeDidChangeNotification getQTMovieTimeDidChangeNotification()
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMovieTimeScaleAttribute getQTMovieTimeScaleAttribute()
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMovieURLAttribute getQTMovieURLAttribute()
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTMovieVolumeDidChangeNotification getQTMovieVolumeDidChangeNotification()
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTSecurityPolicyNoCrossSiteAttribute getQTSecurityPolicyNoCrossSiteAttribute()
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define QTVideoRendererWebKitOnlyNewImageAvailableNotification getQTVideoRendererWebKitOnlyNewImageAvailableNotification()
1515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#ifndef BUILDING_ON_TIGER
1525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#define QTMovieApertureModeClean getQTMovieApertureModeClean()
1535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#define QTMovieApertureModeAttribute getQTMovieApertureModeAttribute()
1545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#endif
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Older versions of the QTKit header don't have these constants.
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if !defined QTKIT_VERSION_MAX_ALLOWED || QTKIT_VERSION_MAX_ALLOWED <= QTKIT_VERSION_7_0
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectenum {
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    QTMovieLoadStateError = -1L,
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    QTMovieLoadStateLoaded  = 2000L,
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    QTMovieLoadStatePlayable = 10000L,
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    QTMovieLoadStatePlaythroughOK = 20000L,
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    QTMovieLoadStateComplete = 100000L
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1675ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen@interface FakeQTMovieView : NSObject
1685ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen- (WebCoreMovieObserver *)delegate;
1695ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen@end
1705ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace WebCore;
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace std;
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@interface WebCoreMovieObserver : NSObject
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1766b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    MediaPlayerPrivateQTKit* m_callback;
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSView* m_view;
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    BOOL m_delayCallbacks;
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1806b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner-(id)initWithCallback:(MediaPlayerPrivateQTKit*)callback;
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project-(void)disconnect;
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project-(void)setView:(NSView*)view;
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project-(void)repaint;
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project-(void)setDelayCallbacks:(BOOL)shouldDelay;
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project-(void)loadStateChanged:(NSNotification *)notification;
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project-(void)rateChanged:(NSNotification *)notification;
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project-(void)sizeChanged:(NSNotification *)notification;
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project-(void)timeChanged:(NSNotification *)notification;
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project-(void)didEnd:(NSNotification *)notification;
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@end
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@protocol WebKitVideoRenderingDetails
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project-(void)setMovie:(id)movie;
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project-(void)drawInRect:(NSRect)rect;
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@end
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef BUILDING_ON_TIGER
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic const long minimumQuickTimeVersion = 0x07300000; // 7.3
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2046b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerMediaPlayerPrivateInterface* MediaPlayerPrivateQTKit::create(MediaPlayer* player)
2058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
2066b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return new MediaPlayerPrivateQTKit(player);
2078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
2088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2096b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::registerMediaEngine(MediaEngineRegistrar registrar)
2108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
2118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (isAvailable())
21281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        registrar(create, getSupportedTypes, supportsType, 0, 0, 0);
2138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
2148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2156b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerMediaPlayerPrivateQTKit::MediaPlayerPrivateQTKit(MediaPlayer* player)
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    : m_player(player)
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_objcObserver(AdoptNS, [[WebCoreMovieObserver alloc] initWithCallback:this])
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_seekTo(-1)
2196b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    , m_seekTimer(this, &MediaPlayerPrivateQTKit::seekTimerFired)
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_networkState(MediaPlayer::Empty)
2218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_readyState(MediaPlayer::HaveNothing)
2228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_rect()
2235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    , m_scaleFactor(1, 1)
2248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_enabledTrackCount(0)
2255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    , m_totalTrackCount(0)
226d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_reportedDuration(-1)
227d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_cachedDuration(-1)
228d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_timeToRestore(-1)
229dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    , m_preload(MediaPlayer::Auto)
230d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_startedPlaying(false)
231d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_isStreaming(false)
232d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_visible(false)
2335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    , m_hasUnsupportedTracks(false)
234d0825bca7fe65beaee391d30da42e937db621564Steve Block    , m_videoFrameHasDrawn(false)
235dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    , m_isAllowedToRender(false)
23681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    , m_privateBrowsing(false)
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if DRAW_FRAME_RATE
2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_frameCountWhilePlaying(0)
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_timeStartedPlaying(0)
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_timeStoppedPlaying(0)
2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2456b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerMediaPlayerPrivateQTKit::~MediaPlayerPrivateQTKit()
2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    tearDownVideoRendering();
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [[NSNotificationCenter defaultCenter] removeObserver:m_objcObserver.get()];
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_objcObserver.get() disconnect];
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2532bde8e466a4451c7319e3a072d118917957d6554Steve BlockNSMutableDictionary* MediaPlayerPrivateQTKit::commonMovieAttributes()
2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2552bde8e466a4451c7319e3a072d118917957d6554Steve Block    return [NSMutableDictionary dictionaryWithObjectsAndKeys:
2562bde8e466a4451c7319e3a072d118917957d6554Steve Block            [NSNumber numberWithBool:m_player->preservesPitch()], QTMovieRateChangesPreservePitchAttribute,
2572bde8e466a4451c7319e3a072d118917957d6554Steve Block            [NSNumber numberWithBool:YES], QTMoviePreventExternalURLLinksAttribute,
2582bde8e466a4451c7319e3a072d118917957d6554Steve Block            [NSNumber numberWithBool:YES], QTSecurityPolicyNoCrossSiteAttribute,
2592bde8e466a4451c7319e3a072d118917957d6554Steve Block            [NSNumber numberWithBool:NO], QTMovieAskUnresolvedDataRefsAttribute,
2602bde8e466a4451c7319e3a072d118917957d6554Steve Block            [NSNumber numberWithBool:NO], QTMovieLoopsAttribute,
2612bde8e466a4451c7319e3a072d118917957d6554Steve Block            [NSNumber numberWithBool:!m_privateBrowsing], @"QTMovieAllowPersistentCacheAttribute",
2620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#ifndef BUILDING_ON_TIGER
2632bde8e466a4451c7319e3a072d118917957d6554Steve Block            QTMovieApertureModeClean, QTMovieApertureModeAttribute,
2640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
2652bde8e466a4451c7319e3a072d118917957d6554Steve Block            nil];
2662bde8e466a4451c7319e3a072d118917957d6554Steve Block}
2672bde8e466a4451c7319e3a072d118917957d6554Steve Block
2682bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateQTKit::createQTMovie(const String& url)
2692bde8e466a4451c7319e3a072d118917957d6554Steve Block{
2702bde8e466a4451c7319e3a072d118917957d6554Steve Block    NSURL *cocoaURL = KURL(ParsedURLString, url);
2712bde8e466a4451c7319e3a072d118917957d6554Steve Block    NSMutableDictionary *movieAttributes = commonMovieAttributes();
2722bde8e466a4451c7319e3a072d118917957d6554Steve Block    [movieAttributes setValue:cocoaURL forKey:QTMovieURLAttribute];
2730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
274f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#if !defined(BUILDING_ON_LEOPARD)
2756b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    CFDictionaryRef proxySettings = CFNetworkCopySystemProxySettings();
2766b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    CFArrayRef proxiesForURL = CFNetworkCopyProxiesForURL((CFURLRef)cocoaURL, proxySettings);
2776b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    BOOL willUseProxy = YES;
2786b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2796b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (!proxiesForURL || !CFArrayGetCount(proxiesForURL))
2806b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        willUseProxy = NO;
2816b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2826b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (CFArrayGetCount(proxiesForURL) == 1) {
2836b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        CFDictionaryRef proxy = (CFDictionaryRef)CFArrayGetValueAtIndex(proxiesForURL, 0);
2846b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        ASSERT(CFGetTypeID(proxy) == CFDictionaryGetTypeID());
2856b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2866b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        CFStringRef proxyType = (CFStringRef)CFDictionaryGetValue(proxy, kCFProxyTypeKey);
2876b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        ASSERT(CFGetTypeID(proxyType) == CFStringGetTypeID());
2886b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2896b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        if (CFStringCompare(proxyType, kCFProxyTypeNone, 0) == kCFCompareEqualTo)
2906b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            willUseProxy = NO;
2916b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
2926b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2936b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (!willUseProxy) {
2946b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        // Only pass the QTMovieOpenForPlaybackAttribute flag if there are no proxy servers, due
2956b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        // to rdar://problem/7531776.
2966b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        [movieAttributes setObject:[NSNumber numberWithBool:YES] forKey:@"QTMovieOpenForPlaybackAttribute"];
2976b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
2986b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
2996b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (proxiesForURL)
3006b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        CFRelease(proxiesForURL);
3016b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (proxySettings)
3026b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        CFRelease(proxySettings);
3036b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#endif
3046b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
3050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    createQTMovie(cocoaURL, movieAttributes);
3060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
3070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3082bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid MediaPlayerPrivateQTKit::createQTMovie(ApplicationCacheResource* resource)
3092bde8e466a4451c7319e3a072d118917957d6554Steve Block{
3102bde8e466a4451c7319e3a072d118917957d6554Steve Block#if ENABLE(OFFLINE_WEB_APPLICATIONS)
3112bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(resource);
3122bde8e466a4451c7319e3a072d118917957d6554Steve Block
3132bde8e466a4451c7319e3a072d118917957d6554Steve Block    NSMutableDictionary *movieAttributes = commonMovieAttributes();
3142bde8e466a4451c7319e3a072d118917957d6554Steve Block    [movieAttributes setObject:[NSNumber numberWithBool:YES] forKey:@"QTMovieOpenForPlaybackAttribute"];
3152bde8e466a4451c7319e3a072d118917957d6554Steve Block
3162bde8e466a4451c7319e3a072d118917957d6554Steve Block    // ApplicationCacheResources can supply either a data pointer, or a path to a locally cached
3172bde8e466a4451c7319e3a072d118917957d6554Steve Block    // flat file.  We would prefer the path over the data, but QTKit can handle either:
3182bde8e466a4451c7319e3a072d118917957d6554Steve Block    String localPath = resource->path();
3192bde8e466a4451c7319e3a072d118917957d6554Steve Block    NSURL* cocoaURL = !localPath.isEmpty() ? [NSURL fileURLWithPath:localPath isDirectory:NO] : nil;
3202bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (cocoaURL)
3212bde8e466a4451c7319e3a072d118917957d6554Steve Block        [movieAttributes setValue:cocoaURL forKey:QTMovieURLAttribute];
3222bde8e466a4451c7319e3a072d118917957d6554Steve Block    else {
3232bde8e466a4451c7319e3a072d118917957d6554Steve Block        NSData* movieData = resource->data()->createNSData();
3242bde8e466a4451c7319e3a072d118917957d6554Steve Block        [movieAttributes setValue:movieData forKey:QTMovieDataAttribute];
3252bde8e466a4451c7319e3a072d118917957d6554Steve Block        [movieData release];
3262bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
3272bde8e466a4451c7319e3a072d118917957d6554Steve Block
3282bde8e466a4451c7319e3a072d118917957d6554Steve Block    createQTMovie(cocoaURL, movieAttributes);
3292bde8e466a4451c7319e3a072d118917957d6554Steve Block
3302bde8e466a4451c7319e3a072d118917957d6554Steve Block#else
3312bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT_NOT_REACHED();
3322bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif
3332bde8e466a4451c7319e3a072d118917957d6554Steve Block}
3342bde8e466a4451c7319e3a072d118917957d6554Steve Block
3355ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenstatic void disableComponentsOnce()
3365ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{
3375ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    static bool sComponentsDisabled = false;
3385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (sComponentsDisabled)
3395ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return;
3405ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    sComponentsDisabled = true;
3415ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3425ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // eat/PDF and grip/PDF components must be disabled twice since they are registered twice
3435ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // with different flags.  However, there is currently a bug in 64-bit QTKit (<rdar://problem/8378237>)
3445ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // which causes subsequent disable component requests of exactly the same type to be ignored if
3455ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // QTKitServer has not yet started.  As a result, we must pass in exactly the flags we want to
3465ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // disable per component.  As a failsafe, if in the future these flags change, we will disable the
3475ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    // PDF components for a third time with a wildcard flags field:
3485ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    uint32_t componentsToDisable[11][5] = {
3495ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        {'eat ', 'TEXT', 'text', 0, 0},
3505ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        {'eat ', 'TXT ', 'text', 0, 0},
3515ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        {'eat ', 'utxt', 'text', 0, 0},
3525ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        {'eat ', 'TEXT', 'tx3g', 0, 0},
3535ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        {'eat ', 'PDF ', 'vide', 0x44802, 0},
3545ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        {'eat ', 'PDF ', 'vide', 0x45802, 0},
3555ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        {'eat ', 'PDF ', 'vide', 0, 0},
3565ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        {'grip', 'PDF ', 'appl', 0x844a00, 0},
3575ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        {'grip', 'PDF ', 'appl', 0x845a00, 0},
3585ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        {'grip', 'PDF ', 'appl', 0, 0},
3595ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        {'imdc', 'pdf ', 'appl', 0, 0},
3605ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    };
3615ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3624576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    for (size_t i = 0; i < WTF_ARRAY_LENGTH(componentsToDisable); ++i)
3635ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        wkQTMovieDisableComponent(componentsToDisable[i]);
3645ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
3655ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3666b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::createQTMovie(NSURL *url, NSDictionary *movieAttributes)
3670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
3685ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    disableComponentsOnce();
3695ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [[NSNotificationCenter defaultCenter] removeObserver:m_objcObserver.get()];
3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    bool recreating = false;
3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_qtMovie) {
3740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        recreating = true;
3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        destroyQTVideoRenderer();
3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_qtMovie = 0;
3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Disable rtsp streams for now, <rdar://problem/5693967>
3800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (protocolIs([url scheme], "rtsp"))
3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    NSError *error = nil;
3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_qtMovie.adoptNS([[QTMovie alloc] initWithAttributes:movieAttributes error:&error]);
3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_qtMovie)
3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_qtMovie.get() setVolume:m_player->volume()];
3900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (recreating && hasVideo())
3920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        createQTVideoRenderer(QTVideoRendererModeListensForNewImages);
3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()
3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                             selector:@selector(loadStateChanged:)
3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                                 name:QTMovieLoadStateDidChangeNotification
3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                               object:m_qtMovie.get()];
3985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // In updateState(), we track when maxTimeLoaded() == duration().
4005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // In newer version of QuickTime, a notification is emitted when maxTimeLoaded changes.
4015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // In older version of QuickTime, QTMovieLoadStateDidChangeNotification be fired.
4025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (NSString *maxTimeLoadedChangeNotification = wkQTMovieMaxTimeLoadedChangeNotification()) {
4035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()
4045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                                                 selector:@selector(loadStateChanged:)
4055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                                                     name:maxTimeLoadedChangeNotification
4065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                                                   object:m_qtMovie.get()];
4075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
4085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()
4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                             selector:@selector(rateChanged:)
4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                                 name:QTMovieRateDidChangeNotification
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                               object:m_qtMovie.get()];
4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()
4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                             selector:@selector(sizeChanged:)
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                                 name:QTMovieSizeDidChangeNotification
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                               object:m_qtMovie.get()];
4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                             selector:@selector(timeChanged:)
4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                                 name:QTMovieTimeDidChangeNotification
4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                               object:m_qtMovie.get()];
4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()
4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                             selector:@selector(didEnd:)
4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                                 name:QTMovieDidEndNotification
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                               object:m_qtMovie.get()];
4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
427635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic void mainThreadSetNeedsDisplay(id self, SEL)
4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4295ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    id view = [self superview];
4305ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    ASSERT(!view || [view isKindOfClass:[QTMovieView class]]);
4315ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    if (!view || ![view isKindOfClass:[QTMovieView class]])
4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4345ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    FakeQTMovieView *movieView = static_cast<FakeQTMovieView *>(view);
4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCoreMovieObserver* delegate = [movieView delegate];
4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!delegate || [delegate isKindOfClass:[WebCoreMovieObserver class]]);
4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!delegate || ![delegate isKindOfClass:[WebCoreMovieObserver class]])
4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [delegate repaint];
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic Class QTVideoRendererClass()
4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project     static Class QTVideoRendererWebKitOnlyClass = NSClassFromString(@"QTVideoRendererWebKitOnly");
4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project     return QTVideoRendererWebKitOnlyClass;
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4496b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::createQTMovieView()
4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    detachQTMovieView();
4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static bool addedCustomMethods = false;
4548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!m_player->inMediaDocument() && !addedCustomMethods) {
4558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Class QTMovieContentViewClass = NSClassFromString(@"QTMovieContentView");
4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(QTMovieContentViewClass);
4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Method mainThreadSetNeedsDisplayMethod = class_getInstanceMethod(QTMovieContentViewClass, @selector(_mainThreadSetNeedsDisplay));
4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(mainThreadSetNeedsDisplayMethod);
4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        method_setImplementation(mainThreadSetNeedsDisplayMethod, reinterpret_cast<IMP>(mainThreadSetNeedsDisplay));
4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        addedCustomMethods = true;
4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // delay callbacks as we *will* get notifications during setup
4668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    [m_objcObserver.get() setDelayCallbacks:YES];
4678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_qtMovieView.adoptNS([[QTMovieView alloc] init]);
4698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    setSize(m_player->size());
4708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    NSView* parentView = m_player->frameView()->documentView();
4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [parentView addSubview:m_qtMovieView.get()];
4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef BUILDING_ON_TIGER
4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // setDelegate: isn't a public call in Tiger, so use performSelector to keep the compiler happy
4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_qtMovieView.get() performSelector:@selector(setDelegate:) withObject:m_objcObserver.get()];
4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_qtMovieView.get() setDelegate:m_objcObserver.get()];
4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_objcObserver.get() setView:m_qtMovieView.get()];
4798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_qtMovieView.get() setMovie:m_qtMovie.get()];
4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_qtMovieView.get() setControllerVisible:NO];
4818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_qtMovieView.get() setPreservesAspectRatio:NO];
4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // the area not covered by video should be transparent
4838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_qtMovieView.get() setFillColor:[NSColor clearColor]];
4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // If we're in a media document, allow QTMovieView to render in its default mode;
4868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // otherwise tell it to draw synchronously.
4878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Note that we expect mainThreadSetNeedsDisplay to be invoked only when synchronous drawing is requested.
4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_player->inMediaDocument())
4898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        wkQTMovieViewSetDrawSynchronously(m_qtMovieView.get(), YES);
4908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    [m_objcObserver.get() setDelayCallbacks:NO];
4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4946b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::detachQTMovieView()
4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_qtMovieView) {
4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [m_objcObserver.get() setView:nil];
4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef BUILDING_ON_TIGER
4998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // setDelegate: isn't a public call in Tiger, so use performSelector to keep the compiler happy
5008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [m_qtMovieView.get() performSelector:@selector(setDelegate:) withObject:nil];
5018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
5028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [m_qtMovieView.get() setDelegate:nil];
5038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
5048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [m_qtMovieView.get() removeFromSuperview];
5058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_qtMovieView = nil;
5068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5096b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::createQTVideoRenderer(QTVideoRendererMode rendererMode)
5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    destroyQTVideoRenderer();
5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_qtVideoRenderer.adoptNS([[QTVideoRendererClass() alloc] init]);
5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_qtVideoRenderer)
5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // associate our movie with our instance of QTVideoRendererWebKitOnly
5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [(id<WebKitVideoRenderingDetails>)m_qtVideoRenderer.get() setMovie:m_qtMovie.get()];
5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (rendererMode == QTVideoRendererModeListensForNewImages) {
5210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // listen to QTVideoRendererWebKitOnly's QTVideoRendererWebKitOnlyNewImageDidBecomeAvailableNotification
5220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()
5230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                                                 selector:@selector(newImageAvailable:)
5240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                                                     name:QTVideoRendererWebKitOnlyNewImageAvailableNotification
5250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                                                   object:m_qtVideoRenderer.get()];
5260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5296b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::destroyQTVideoRenderer()
5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_qtVideoRenderer)
5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // stop observing the renderer's notifications before we toss it
5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [[NSNotificationCenter defaultCenter] removeObserver:m_objcObserver.get()
5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                                    name:QTVideoRendererWebKitOnlyNewImageAvailableNotification
5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                                  object:m_qtVideoRenderer.get()];
5388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // disassociate our movie from our instance of QTVideoRendererWebKitOnly
5408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [(id<WebKitVideoRenderingDetails>)m_qtVideoRenderer.get() setMovie:nil];
5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_qtVideoRenderer = nil;
5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5456b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::createQTMovieLayer()
5460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
5470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if USE(ACCELERATED_COMPOSITING)
5480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!m_qtMovie)
5490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return;
5500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
5510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(supportsAcceleratedRendering());
5520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
5530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!m_qtVideoLayer) {
5540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        m_qtVideoLayer.adoptNS([[QTMovieLayer alloc] init]);
5550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (!m_qtVideoLayer)
5560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            return;
5570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
5580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        [m_qtVideoLayer.get() setMovie:m_qtMovie.get()];
5590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#ifndef NDEBUG
5600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        [(CALayer *)m_qtVideoLayer.get() setName:@"Video layer"];
5610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
562692e5dbf12901edacf14812a6fae25462920af42Steve Block        // The layer will get hooked up via RenderLayerBacking::updateGraphicsLayerConfiguration().
5630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
5640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
5650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
5660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
5676b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::destroyQTMovieLayer()
5680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
5690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if USE(ACCELERATED_COMPOSITING)
5700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!m_qtVideoLayer)
5710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return;
5720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
5730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // disassociate our movie from our instance of QTMovieLayer
5740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    [m_qtVideoLayer.get() setMovie:nil];
5750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    m_qtVideoLayer = nil;
5760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
5770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
5780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
5796b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerMediaPlayerPrivateQTKit::MediaRenderingMode MediaPlayerPrivateQTKit::currentRenderingMode() const
5800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
5810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (m_qtMovieView)
5820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return MediaRenderingMovieView;
5830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
5840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (m_qtVideoLayer)
5850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return MediaRenderingMovieLayer;
5860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
5870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (m_qtVideoRenderer)
5880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return MediaRenderingSoftwareRenderer;
5890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
5900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return MediaRenderingNone;
5910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
5920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
5936b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerMediaPlayerPrivateQTKit::MediaRenderingMode MediaPlayerPrivateQTKit::preferredRenderingMode() const
5948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!m_player->frameView() || !m_qtMovie)
5960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return MediaRenderingNone;
5970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
5980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if USE(ACCELERATED_COMPOSITING)
5990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (supportsAcceleratedRendering() && m_player->mediaPlayerClient()->mediaPlayerRenderingCanBeAccelerated(m_player))
6000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return MediaRenderingMovieLayer;
6010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
6020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
60381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!QTVideoRendererClass())
60481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return MediaRenderingMovieView;
60581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
6060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return MediaRenderingSoftwareRenderer;
6070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
6080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6096b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::setUpVideoRendering()
6100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
611dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    if (!isReadyForVideoSetup())
612d0825bca7fe65beaee391d30da42e937db621564Steve Block        return;
613d0825bca7fe65beaee391d30da42e937db621564Steve Block
6140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    MediaRenderingMode currentMode = currentRenderingMode();
6150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    MediaRenderingMode preferredMode = preferredRenderingMode();
6160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (currentMode == preferredMode && currentMode != MediaRenderingNone)
6178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
6188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (currentMode != MediaRenderingNone)
6200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        tearDownVideoRendering();
6210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    switch (preferredMode) {
6230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    case MediaRenderingMovieView:
6248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        createQTMovieView();
6250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        break;
6260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    case MediaRenderingNone:
6270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    case MediaRenderingSoftwareRenderer:
6280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        createQTVideoRenderer(QTVideoRendererModeListensForNewImages);
6290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        break;
6300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    case MediaRenderingMovieLayer:
6310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        createQTMovieLayer();
6320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        break;
6330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
634692e5dbf12901edacf14812a6fae25462920af42Steve Block
635dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    // If using a movie layer, inform the client so the compositing tree is updated.
636692e5dbf12901edacf14812a6fae25462920af42Steve Block    if (currentMode == MediaRenderingMovieLayer || preferredMode == MediaRenderingMovieLayer)
637692e5dbf12901edacf14812a6fae25462920af42Steve Block        m_player->mediaPlayerClient()->mediaPlayerRenderingModeChanged(m_player);
6388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6406b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::tearDownVideoRendering()
6418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_qtMovieView)
6438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        detachQTMovieView();
6440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (m_qtVideoRenderer)
6458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        destroyQTVideoRenderer();
6460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (m_qtVideoLayer)
6470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        destroyQTMovieLayer();
6480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
6490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6506b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerbool MediaPlayerPrivateQTKit::hasSetUpVideoRendering() const
6510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
6520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return m_qtMovieView
6530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        || m_qtVideoLayer
6540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        || m_qtVideoRenderer;
6558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6576b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerQTTime MediaPlayerPrivateQTKit::createQTTime(float time) const
6588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!metaDataAvailable())
6608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return QTMakeTime(0, 600);
6618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    long timeScale = [[m_qtMovie.get() attributeForKey:QTMovieTimeScaleAttribute] longValue];
6622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return QTMakeTime(lroundf(time * timeScale), timeScale);
6638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6656b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::resumeLoad()
666dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
667dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    m_delayingLoad = false;
668dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
669f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!m_movieURL.isNull())
670dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        loadInternal(m_movieURL);
671dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
672dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
6736b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::load(const String& url)
6748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
675dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    m_movieURL = url;
676dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
677dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // If the element is not supposed to load any data return immediately because QTKit
678dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // doesn't have API to throttle loading.
679dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (m_preload == MediaPlayer::None) {
680dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        m_delayingLoad = true;
681dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return;
682dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
683dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
684dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    loadInternal(url);
685dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
686dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
6876b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::loadInternal(const String& url)
688dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
6898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_networkState != MediaPlayer::Loading) {
6908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_networkState = MediaPlayer::Loading;
6918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_player->networkStateChanged();
6928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (m_readyState != MediaPlayer::HaveNothing) {
6948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_readyState = MediaPlayer::HaveNothing;
6958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_player->readyStateChanged();
6968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    cancelSeek();
698d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_videoFrameHasDrawn = false;
6998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_objcObserver.get() setDelayCallbacks:YES];
7018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7022bde8e466a4451c7319e3a072d118917957d6554Steve Block#if ENABLE(OFFLINE_WEB_APPLICATIONS)
7032bde8e466a4451c7319e3a072d118917957d6554Steve Block    Frame* frame = m_player->frameView() ? m_player->frameView()->frame() : NULL;
7042bde8e466a4451c7319e3a072d118917957d6554Steve Block    ApplicationCacheHost* cacheHost = frame ? frame->loader()->documentLoader()->applicationCacheHost() : NULL;
7052bde8e466a4451c7319e3a072d118917957d6554Steve Block    ApplicationCacheResource* resource = NULL;
7062bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (cacheHost && cacheHost->shouldLoadResourceFromApplicationCache(ResourceRequest(url), resource) && resource)
7072bde8e466a4451c7319e3a072d118917957d6554Steve Block        createQTMovie(resource);
7082bde8e466a4451c7319e3a072d118917957d6554Steve Block    else
7092bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif
7108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    createQTMovie(url);
7118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_objcObserver.get() loadStateChanged:nil];
7138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_objcObserver.get() setDelayCallbacks:NO];
7148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7166b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::prepareToPlay()
717dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
718dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!m_qtMovie || m_delayingLoad)
719dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        resumeLoad();
720dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
721dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
7226b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerPlatformMedia MediaPlayerPrivateQTKit::platformMedia() const
723231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
7246c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    PlatformMedia pm;
7256c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    pm.type = PlatformMedia::QTMovieType;
7266c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    pm.media.qtMovie = m_qtMovie.get();
7276c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    return pm;
728231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
729231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
730692e5dbf12901edacf14812a6fae25462920af42Steve Block#if USE(ACCELERATED_COMPOSITING)
7316b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerPlatformLayer* MediaPlayerPrivateQTKit::platformLayer() const
732692e5dbf12901edacf14812a6fae25462920af42Steve Block{
733692e5dbf12901edacf14812a6fae25462920af42Steve Block    return m_qtVideoLayer.get();
734692e5dbf12901edacf14812a6fae25462920af42Steve Block}
735692e5dbf12901edacf14812a6fae25462920af42Steve Block#endif
736692e5dbf12901edacf14812a6fae25462920af42Steve Block
7376b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::play()
7388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!metaDataAvailable())
7408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
7418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_startedPlaying = true;
7428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if DRAW_FRAME_RATE
7438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_frameCountWhilePlaying = 0;
7448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
7458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_objcObserver.get() setDelayCallbacks:YES];
7468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_qtMovie.get() setRate:m_player->rate()];
7478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_objcObserver.get() setDelayCallbacks:NO];
7488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7506b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::pause()
7518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!metaDataAvailable())
7538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
7548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_startedPlaying = false;
7558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if DRAW_FRAME_RATE
7568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_timeStoppedPlaying = [NSDate timeIntervalSinceReferenceDate];
7578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
7588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_objcObserver.get() setDelayCallbacks:YES];
7598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_qtMovie.get() stop];
7608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_objcObserver.get() setDelayCallbacks:NO];
7618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7636b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerfloat MediaPlayerPrivateQTKit::duration() const
7648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!metaDataAvailable())
7668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
7670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
7680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (m_cachedDuration != -1.0f)
7690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return m_cachedDuration;
7700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
7718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    QTTime time = [m_qtMovie.get() duration];
7728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (time.flags == kQTTimeIsIndefinite)
7738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return numeric_limits<float>::infinity();
7748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return static_cast<float>(time.timeValue) / time.timeScale;
7758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7776b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerfloat MediaPlayerPrivateQTKit::currentTime() const
7788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!metaDataAvailable())
7808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
7818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    QTTime time = [m_qtMovie.get() currentTime];
7828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return static_cast<float>(time.timeValue) / time.timeScale;
7838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7856b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::seek(float time)
7868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Nothing to do if we are already in the middle of a seek to the same time.
7880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (time == m_seekTo)
7890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return;
7900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
7918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    cancelSeek();
7928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!metaDataAvailable())
7948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
7958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (time > duration())
7978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        time = duration();
7988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
7998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_seekTo = time;
8000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (maxTimeSeekable() >= m_seekTo)
8018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        doSeek();
8028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else
8038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_seekTimer.start(0, 0.5f);
8048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8066b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::doSeek()
8078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    QTTime qttime = createQTTime(m_seekTo);
8098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // setCurrentTime generates several event callbacks, update afterwards
8108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_objcObserver.get() setDelayCallbacks:YES];
8118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    float oldRate = [m_qtMovie.get() rate];
8120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
8130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (oldRate)
8140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        [m_qtMovie.get() setRate:0];
8158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_qtMovie.get() setCurrentTime:qttime];
8160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
817d0825bca7fe65beaee391d30da42e937db621564Steve Block    // restore playback only if not at end, otherwise QTMovie will loop
8180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    float timeAfterSeek = currentTime();
8198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (oldRate && timeAfterSeek < duration())
8208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [m_qtMovie.get() setRate:oldRate];
8210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
8228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    cancelSeek();
8238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_objcObserver.get() setDelayCallbacks:NO];
8248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8266b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::cancelSeek()
8278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_seekTo = -1;
8298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_seekTimer.stop();
8308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8326b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::seekTimerFired(Timer<MediaPlayerPrivateQTKit>*)
8338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!metaDataAvailable()|| !seeking() || currentTime() == m_seekTo) {
8358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        cancelSeek();
8368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        updateStates();
8378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_player->timeChanged();
8388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
8398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
8410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (maxTimeSeekable() >= m_seekTo)
8428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        doSeek();
8438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else {
8448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        MediaPlayer::NetworkState state = networkState();
8458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (state == MediaPlayer::Empty || state == MediaPlayer::Loaded) {
8468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            cancelSeek();
8478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            updateStates();
8488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_player->timeChanged();
8498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
8508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8536b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerbool MediaPlayerPrivateQTKit::paused() const
8548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!metaDataAvailable())
8568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
8578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return [m_qtMovie.get() rate] == 0;
8588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8606b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerbool MediaPlayerPrivateQTKit::seeking() const
8618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!metaDataAvailable())
8638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
8648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return m_seekTo >= 0;
8658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8676b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerIntSize MediaPlayerPrivateQTKit::naturalSize() const
8688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!metaDataAvailable())
8708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return IntSize();
8715f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
8725f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // In spite of the name of this method, return QTMovieNaturalSizeAttribute transformed by the
8735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // initial movie scale because the spec says intrinsic size is:
8745f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    //
8755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    //    ... the dimensions of the resource in CSS pixels after taking into account the resource's
8765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    //    dimensions, aspect ratio, clean aperture, resolution, and so forth, as defined for the
8775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    //    format used by the resource
8785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
8792bde8e466a4451c7319e3a072d118917957d6554Steve Block    FloatSize naturalSize([[m_qtMovie.get() attributeForKey:QTMovieNaturalSizeAttribute] sizeValue]);
8802bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (naturalSize.isEmpty() && m_isStreaming) {
8812bde8e466a4451c7319e3a072d118917957d6554Steve Block        // HTTP Live Streams will occasionally return {0,0} natural sizes while scrubbing.
8822bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Work around this problem (<rdar://problem/9078563>) by returning the last valid
8832bde8e466a4451c7319e3a072d118917957d6554Steve Block        // cached natural size:
8842bde8e466a4451c7319e3a072d118917957d6554Steve Block        naturalSize = m_cachedNaturalSize;
8852bde8e466a4451c7319e3a072d118917957d6554Steve Block    } else {
8862bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Unfortunately, due to another QTKit bug (<rdar://problem/9082071>) we won't get a sizeChanged
8872bde8e466a4451c7319e3a072d118917957d6554Steve Block        // event when this happens, so we must cache the last valid naturalSize here:
8882bde8e466a4451c7319e3a072d118917957d6554Steve Block        m_cachedNaturalSize = naturalSize;
8892bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
8902bde8e466a4451c7319e3a072d118917957d6554Steve Block
8912bde8e466a4451c7319e3a072d118917957d6554Steve Block    return IntSize(naturalSize.width() * m_scaleFactor.width(), naturalSize.height() * m_scaleFactor.height());
8928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8946b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerbool MediaPlayerPrivateQTKit::hasVideo() const
8958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!metaDataAvailable())
8978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
8988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return [[m_qtMovie.get() attributeForKey:QTMovieHasVideoAttribute] boolValue];
8998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9016b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerbool MediaPlayerPrivateQTKit::hasAudio() const
902231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
903231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!m_qtMovie)
904231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return false;
905231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return [[m_qtMovie.get() attributeForKey:QTMovieHasAudioAttribute] boolValue];
906231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
907231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
9086b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerbool MediaPlayerPrivateQTKit::supportsFullscreen() const
909643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
910643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
911231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return true;
912643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#else
913643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // See <rdar://problem/7389945>
914643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return false;
915643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#endif
916231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
917231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
9186b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::setVolume(float volume)
9198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
920231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_qtMovie)
921231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        [m_qtMovie.get() setVolume:volume];
9228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9246b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerbool MediaPlayerPrivateQTKit::hasClosedCaptions() const
925643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
926643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (!metaDataAvailable())
927643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return false;
928643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return wkQTMovieHasClosedCaptions(m_qtMovie.get());
929643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
930643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
9316b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::setClosedCaptionsVisible(bool closedCaptionsVisible)
932643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{
933643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (metaDataAvailable()) {
934643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        wkQTMovieSetShowClosedCaptions(m_qtMovie.get(), closedCaptionsVisible);
935643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
936643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#if USE(ACCELERATED_COMPOSITING) && (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD))
937643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (closedCaptionsVisible && m_qtVideoLayer) {
938d0825bca7fe65beaee391d30da42e937db621564Steve Block        // Captions will be rendered upside down unless we flag the movie as flipped (again). See <rdar://7408440>.
939643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        [m_qtVideoLayer.get() setGeometryFlipped:YES];
940643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
941643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#endif
942643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
943643ca7872b450ea4efacab6188849e5aac2ba161Steve Block}
944643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
9456b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::setRate(float rate)
9468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
947231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_qtMovie)
948231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        [m_qtMovie.get() setRate:rate];
9490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
9500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
9516b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::setPreservesPitch(bool preservesPitch)
9520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
9530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!m_qtMovie)
9540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return;
9550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
9560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // QTMovieRateChangesPreservePitchAttribute cannot be changed dynamically after QTMovie creation.
9570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // If the passed in value is different than what already exists, we need to recreate the QTMovie for it to take effect.
9580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if ([[m_qtMovie.get() attributeForKey:QTMovieRateChangesPreservePitchAttribute] boolValue] == preservesPitch)
9590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return;
9600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
9614576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    RetainPtr<NSDictionary> movieAttributes(AdoptNS, [[m_qtMovie.get() movieAttributes] mutableCopy]);
9620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(movieAttributes);
9634576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    [movieAttributes.get() setValue:[NSNumber numberWithBool:preservesPitch] forKey:QTMovieRateChangesPreservePitchAttribute];
9640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    m_timeToRestore = currentTime();
9650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
9664576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    createQTMovie([movieAttributes.get() valueForKey:QTMovieURLAttribute], movieAttributes.get());
9678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9696b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerPassRefPtr<TimeRanges> MediaPlayerPrivateQTKit::buffered() const
9708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
971231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    RefPtr<TimeRanges> timeRanges = TimeRanges::create();
972231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    float loaded = maxTimeLoaded();
973231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (loaded > 0)
974231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        timeRanges->add(0, loaded);
975231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return timeRanges.release();
9768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9786b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerfloat MediaPlayerPrivateQTKit::maxTimeSeekable() const
9798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!metaDataAvailable())
9815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return 0;
9825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
9838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // infinite duration means live stream
9845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (isinf(duration()))
9855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return 0;
9865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
9875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return wkQTMovieMaxTimeSeekable(m_qtMovie.get());
9888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9906b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerfloat MediaPlayerPrivateQTKit::maxTimeLoaded() const
9918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!metaDataAvailable())
9938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
9948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return wkQTMovieMaxTimeLoaded(m_qtMovie.get());
9958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9976b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerunsigned MediaPlayerPrivateQTKit::bytesLoaded() const
9988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    float dur = duration();
10008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!dur)
10018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
10028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return totalBytes() * maxTimeLoaded() / dur;
10038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10056b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerunsigned MediaPlayerPrivateQTKit::totalBytes() const
10068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
10078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!metaDataAvailable())
10088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
10098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return [[m_qtMovie.get() attributeForKey:QTMovieDataSizeAttribute] intValue];
10108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10126b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::cancelLoad()
10138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
10148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: Is there a better way to check for this?
10158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_networkState < MediaPlayer::Loading || m_networkState == MediaPlayer::Loaded)
10168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
10178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    tearDownVideoRendering();
10198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_qtMovie = nil;
10208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    updateStates();
10228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10246b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::cacheMovieScale()
10255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
10265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    NSSize initialSize = NSZeroSize;
10275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    NSSize naturalSize = [[m_qtMovie.get() attributeForKey:QTMovieNaturalSizeAttribute] sizeValue];
10285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
10305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // QTMovieCurrentSizeAttribute is not allowed with instances of QTMovie that have been
10315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // opened with QTMovieOpenForPlaybackAttribute, so ask for the display transform attribute instead.
10325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    NSAffineTransform *displayTransform = [m_qtMovie.get() attributeForKey:@"QTMoviePreferredTransformAttribute"];
10335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (displayTransform)
10345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        initialSize = [displayTransform transformSize:naturalSize];
10355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    else {
10365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        initialSize.width = naturalSize.width;
10375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        initialSize.height = naturalSize.height;
10385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
10395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#else
10405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    initialSize = [[m_qtMovie.get() attributeForKey:QTMovieCurrentSizeAttribute] sizeValue];
10415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#endif
10425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (naturalSize.width)
10445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_scaleFactor.setWidth(initialSize.width / naturalSize.width);
10455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (naturalSize.height)
10465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_scaleFactor.setHeight(initialSize.height / naturalSize.height);
10475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
10485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
10496b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerbool MediaPlayerPrivateQTKit::isReadyForVideoSetup() const
10500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
10510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return m_readyState >= MediaPlayer::HaveMetadata && m_player->visible();
10520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
10530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
10546b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::prepareForRendering()
1055dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch{
1056dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    if (m_isAllowedToRender)
1057dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        return;
1058dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    m_isAllowedToRender = true;
1059dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
1060dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    if (!hasSetUpVideoRendering())
1061dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        setUpVideoRendering();
1062dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
1063dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    // If using a movie layer, inform the client so the compositing tree is updated. This is crucial if the movie
1064dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    // has a poster, as it will most likely not have a layer and we will now be rendering frames to the movie layer.
1065dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    if (currentRenderingMode() == MediaRenderingMovieLayer || preferredRenderingMode() == MediaRenderingMovieLayer)
1066dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch        m_player->mediaPlayerClient()->mediaPlayerRenderingModeChanged(m_player);
1067dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch}
1068dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
10696b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::updateStates()
10708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
10718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    MediaPlayer::NetworkState oldNetworkState = m_networkState;
10728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    MediaPlayer::ReadyState oldReadyState = m_readyState;
10738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    long loadState = m_qtMovie ? [[m_qtMovie.get() attributeForKey:QTMovieLoadStateAttribute] longValue] : static_cast<long>(QTMovieLoadStateError);
10758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
10765f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (loadState >= QTMovieLoadStateLoaded && m_readyState < MediaPlayer::HaveMetadata) {
10778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        disableUnsupportedTracks();
10785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (m_player->inMediaDocument()) {
10790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            if (!m_enabledTrackCount || m_hasUnsupportedTracks) {
10800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                // This has a type of media that we do not handle directly with a <video>
10810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                // element, eg. a rtsp track or QuickTime VR. Tell the MediaPlayerClient
10825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                // that we noticed.
10835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                sawUnsupportedTracks();
10845f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                return;
10855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            }
10860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        } else if (!m_enabledTrackCount)
10878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            loadState = QTMovieLoadStateError;
10880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
10890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (loadState != QTMovieLoadStateError) {
1090dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            wkQTMovieSelectPreferredAlternates(m_qtMovie.get());
10915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            cacheMovieScale();
10920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            MediaPlayer::MovieLoadType movieType = movieLoadType();
10930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            m_isStreaming = movieType == MediaPlayer::StoredStream || movieType == MediaPlayer::LiveStream;
10940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
10950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
10960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
10970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // If this movie is reloading and we mean to restore the current time/rate, this might be the right time to do it.
10980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (loadState >= QTMovieLoadStateLoaded && oldNetworkState < MediaPlayer::Loaded && m_timeToRestore != -1.0f) {
10990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        QTTime qttime = createQTTime(m_timeToRestore);
11000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        m_timeToRestore = -1.0f;
11010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
11020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // Disable event callbacks from setCurrentTime for restoring time in a recreated video
11030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        [m_objcObserver.get() setDelayCallbacks:YES];
11040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        [m_qtMovie.get() setCurrentTime:qttime];
11050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        [m_qtMovie.get() setRate:m_player->rate()];
11060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        [m_objcObserver.get() setDelayCallbacks:NO];
11078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
11088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    BOOL completelyLoaded = !m_isStreaming && (loadState >= QTMovieLoadStateComplete);
11105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
11115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Note: QT indicates that we are fully loaded with QTMovieLoadStateComplete.
11125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // However newer versions of QT do not, so we check maxTimeLoaded against duration.
11135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!completelyLoaded && !m_isStreaming && metaDataAvailable())
11145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        completelyLoaded = maxTimeLoaded() == duration();
11155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
11165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (completelyLoaded) {
11178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // "Loaded" is reserved for fully buffered movies, never the case when streaming
11188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_networkState = MediaPlayer::Loaded;
11198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_readyState = MediaPlayer::HaveEnoughData;
11208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else if (loadState >= QTMovieLoadStatePlaythroughOK) {
11215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_readyState = MediaPlayer::HaveEnoughData;
11228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_networkState = MediaPlayer::Loading;
11238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else if (loadState >= QTMovieLoadStatePlayable) {
11248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // FIXME: This might not work correctly in streaming case, <rdar://problem/5693967>
11258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_readyState = currentTime() < maxTimeLoaded() ? MediaPlayer::HaveFutureData : MediaPlayer::HaveCurrentData;
11268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_networkState = MediaPlayer::Loading;
11278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else if (loadState >= QTMovieLoadStateLoaded) {
11288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_readyState = MediaPlayer::HaveMetadata;
11298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_networkState = MediaPlayer::Loading;
11308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else if (loadState > QTMovieLoadStateError) {
11315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_readyState = MediaPlayer::HaveNothing;
11328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_networkState = MediaPlayer::Loading;
11338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
11340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // Loading or decoding failed.
11350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
11365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (m_player->inMediaDocument()) {
11375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            // Something went wrong in the loading of media within a standalone file.
11385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            // This can occur with chained refmovies pointing to streamed media.
11395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            sawUnsupportedTracks();
11405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            return;
11415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
11428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
11435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        float loaded = maxTimeLoaded();
11448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (!loaded)
11458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            m_readyState = MediaPlayer::HaveNothing;
11468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
11478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (!m_enabledTrackCount)
11488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            m_networkState = MediaPlayer::FormatError;
11498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        else {
11508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            // FIXME: We should differentiate between load/network errors and decode errors <rdar://problem/5605692>
11518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            if (loaded > 0)
11528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_networkState = MediaPlayer::DecodeError;
11538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            else
11548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_readyState = MediaPlayer::HaveNothing;
11558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        }
11568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
11578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1158dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    if (isReadyForVideoSetup() && !hasSetUpVideoRendering())
11590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        setUpVideoRendering();
11600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
11618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (seeking())
11620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        m_readyState = m_readyState >= MediaPlayer::HaveMetadata ? MediaPlayer::HaveMetadata : MediaPlayer::HaveNothing;
11630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
11640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Streaming movies don't use the network when paused.
11650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (m_isStreaming && m_readyState >= MediaPlayer::HaveMetadata && m_networkState >= MediaPlayer::Loading && [m_qtMovie.get() rate] == 0)
11660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        m_networkState = MediaPlayer::Idle;
11678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
11688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_networkState != oldNetworkState)
11698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_player->networkStateChanged();
11700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
11718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_readyState != oldReadyState)
11728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_player->readyStateChanged();
11738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (loadState >= QTMovieLoadStateLoaded) {
11758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        float dur = duration();
11760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (dur != m_reportedDuration) {
11770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            if (m_reportedDuration != -1.0f)
11788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                m_player->durationChanged();
11790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            m_reportedDuration = dur;
11808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        }
11818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
11828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
11838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11846b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::loadStateChanged()
11858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
11865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!m_hasUnsupportedTracks)
11875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        updateStates();
11888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
11898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11906b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::rateChanged()
11918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
11925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (m_hasUnsupportedTracks)
11935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return;
11945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
11958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    updateStates();
11968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_player->rateChanged();
11978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
11988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11996b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::sizeChanged()
12008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
12015f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!m_hasUnsupportedTracks)
12025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_player->sizeChanged();
12038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
12048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12056b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::timeChanged()
12068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
12075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (m_hasUnsupportedTracks)
12085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return;
12095f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
12100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // It may not be possible to seek to a specific time in a streamed movie. When seeking in a
12110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // stream QuickTime sets the movie time to closest time possible and posts a timechanged
12120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // notification. Update m_seekTo so we can detect when the seek completes.
12130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (m_seekTo != -1)
12140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        m_seekTo = currentTime();
12150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
12160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    m_timeToRestore = -1.0f;
12178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    updateStates();
12188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_player->timeChanged();
12198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
12208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12216b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::didEnd()
12228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
12235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (m_hasUnsupportedTracks)
12245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return;
12255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
12268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_startedPlaying = false;
12278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if DRAW_FRAME_RATE
12288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_timeStoppedPlaying = [NSDate timeIntervalSinceReferenceDate];
12298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
12300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
12310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Hang onto the current time and use it as duration from now on since QuickTime is telling us we
12320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // are at the end. Do this because QuickTime sometimes reports one time for duration and stops
1233d0825bca7fe65beaee391d30da42e937db621564Steve Block    // playback at another time, which causes problems in HTMLMediaElement. QTKit's 'ended' event
1234d0825bca7fe65beaee391d30da42e937db621564Steve Block    // fires when playing in reverse so don't update duration when at time zero!
1235d0825bca7fe65beaee391d30da42e937db621564Steve Block    float now = currentTime();
1236d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (now > 0)
1237d0825bca7fe65beaee391d30da42e937db621564Steve Block        m_cachedDuration = now;
12380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
12398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    updateStates();
12408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_player->timeChanged();
12418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
12428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12436b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::setSize(const IntSize&)
12448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
12455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Don't resize the view now because [view setFrame] also resizes the movie itself, and because
12465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // the renderer calls this function immediately when we report a size change (QTMovieSizeDidChangeNotification)
12475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // we can get into a feedback loop observing the size change and resetting the size, and this can cause
12485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // QuickTime to miss resetting a movie's size when the media size changes (as happens with an rtsp movie
12495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // once the rtsp server sends the track sizes). Instead we remember the size passed to paint() and resize
12505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // the view when it changes.
12515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // <rdar://problem/6336092> REGRESSION: rtsp movie does not resize correctly
12528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
12538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12546b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::setVisible(bool b)
12558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
12568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_visible != b) {
12578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_visible = b;
1258d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (b)
1259d0825bca7fe65beaee391d30da42e937db621564Steve Block            setUpVideoRendering();
1260d0825bca7fe65beaee391d30da42e937db621564Steve Block        else
12618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            tearDownVideoRendering();
12628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
12638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
12648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12656b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerbool MediaPlayerPrivateQTKit::hasAvailableVideoFrame() const
1266d0825bca7fe65beaee391d30da42e937db621564Steve Block{
1267d0825bca7fe65beaee391d30da42e937db621564Steve Block    // When using a QTMovieLayer return true as soon as the movie reaches QTMovieLoadStatePlayable
1268d0825bca7fe65beaee391d30da42e937db621564Steve Block    // because although we don't *know* when the first frame has decoded, by the time we get and
1269d0825bca7fe65beaee391d30da42e937db621564Steve Block    // process the notification a frame should have propagated the VisualContext and been set on
1270d0825bca7fe65beaee391d30da42e937db621564Steve Block    // the layer.
1271d0825bca7fe65beaee391d30da42e937db621564Steve Block    if (currentRenderingMode() == MediaRenderingMovieLayer)
1272d0825bca7fe65beaee391d30da42e937db621564Steve Block        return m_readyState >= MediaPlayer::HaveCurrentData;
1273d0825bca7fe65beaee391d30da42e937db621564Steve Block
1274d0825bca7fe65beaee391d30da42e937db621564Steve Block    // When using the software renderer QuickTime signals that a frame is available so we might as well
1275d0825bca7fe65beaee391d30da42e937db621564Steve Block    // wait until we know that a frame has been drawn.
1276d0825bca7fe65beaee391d30da42e937db621564Steve Block    return m_videoFrameHasDrawn;
1277d0825bca7fe65beaee391d30da42e937db621564Steve Block}
1278d0825bca7fe65beaee391d30da42e937db621564Steve Block
12796b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::repaint()
12808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
12815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (m_hasUnsupportedTracks)
12825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return;
12835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
12848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if DRAW_FRAME_RATE
12858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_startedPlaying) {
12868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_frameCountWhilePlaying++;
12878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // to eliminate preroll costs from our calculation,
12888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // our frame rate calculation excludes the first frame drawn after playback starts
12898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (1==m_frameCountWhilePlaying)
12908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_timeStartedPlaying = [NSDate timeIntervalSinceReferenceDate];
12918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
12928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
1293d0825bca7fe65beaee391d30da42e937db621564Steve Block    m_videoFrameHasDrawn = true;
12948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_player->repaint();
12958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
12968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
12976b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& r)
12980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
12990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    id qtVideoRenderer = m_qtVideoRenderer.get();
13000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!qtVideoRenderer && currentRenderingMode() == MediaRenderingMovieLayer) {
13010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // We're being told to render into a context, but we already have the
13020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // MovieLayer going. This probably means we've been called from <canvas>.
13030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // Set up a QTVideoRenderer to use, but one that doesn't register for
13040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // update callbacks. That way, it won't bother us asking to repaint.
13050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        createQTVideoRenderer(QTVideoRendererModeDefault);
13060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        qtVideoRenderer = m_qtVideoRenderer.get();
13070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
13080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    paint(context, r);
13090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
13100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
13116b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::paint(GraphicsContext* context, const IntRect& r)
13128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
13135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (context->paintingDisabled() || m_hasUnsupportedTracks)
13148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
13158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSView *view = m_qtMovieView.get();
13168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    id qtVideoRenderer = m_qtVideoRenderer.get();
13178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!view && !qtVideoRenderer)
13188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
13198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
13208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_objcObserver.get() setDelayCallbacks:YES];
13218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    BEGIN_BLOCK_OBJC_EXCEPTIONS;
13228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    context->save();
13238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    context->translate(r.x(), r.y() + r.height());
13248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    context->scale(FloatSize(1.0f, -1.0f));
13258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    context->setImageInterpolationQuality(InterpolationLow);
13268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    IntRect paintRect(IntPoint(0, 0), IntSize(r.width(), r.height()));
1327635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1328635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#ifdef BUILDING_ON_TIGER
1329635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    AutodrainedPool pool;
1330635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif
13318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSGraphicsContext* newContext = [NSGraphicsContext graphicsContextWithGraphicsPort:context->platformContext() flipped:NO];
13328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
13338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // draw the current video frame
13348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (qtVideoRenderer) {
13358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [NSGraphicsContext saveGraphicsState];
13368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [NSGraphicsContext setCurrentContext:newContext];
13378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [(id<WebKitVideoRenderingDetails>)qtVideoRenderer drawInRect:paintRect];
13388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [NSGraphicsContext restoreGraphicsState];
13398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    } else {
13405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (m_rect != r) {
13415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian             m_rect = r;
13425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            if (m_player->inMediaDocument()) {
13435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                // the QTMovieView needs to be placed in the proper location for document mode
13445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                [view setFrame:m_rect];
13455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            }
13465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            else {
13475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                // We don't really need the QTMovieView in any specific location so let's just get it out of the way
13485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                // where it won't intercept events or try to bring up the context menu.
13495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                IntRect farAwayButCorrectSize(m_rect);
13505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                farAwayButCorrectSize.move(-1000000, -1000000);
13515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                [view setFrame:farAwayButCorrectSize];
13525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            }
13538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        }
13545f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
13555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (m_player->inMediaDocument()) {
13565f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            // If we're using a QTMovieView in a media document, the view may get layer-backed. AppKit won't update
13575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            // the layer hosting correctly if we call displayRectIgnoringOpacity:inContext:, so use displayRectIgnoringOpacity:
13585f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            // in this case. See <rdar://problem/6702882>.
13595f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            [view displayRectIgnoringOpacity:paintRect];
13605f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        } else
13615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            [view displayRectIgnoringOpacity:paintRect inContext:newContext];
13628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
13638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
13648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if DRAW_FRAME_RATE
13658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Draw the frame rate only after having played more than 10 frames.
13668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_frameCountWhilePlaying > 10) {
13678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        Frame* frame = m_player->frameView() ? m_player->frameView()->frame() : NULL;
13688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Document* document = frame ? frame->document() : NULL;
13698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        RenderObject* renderer = document ? document->renderer() : NULL;
13708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        RenderStyle* styleToUse = renderer ? renderer->style() : NULL;
13718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (styleToUse) {
13728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            double frameRate = (m_frameCountWhilePlaying - 1) / ( m_startedPlaying ? ([NSDate timeIntervalSinceReferenceDate] - m_timeStartedPlaying) :
13738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                (m_timeStoppedPlaying - m_timeStartedPlaying) );
13748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            String text = String::format("%1.2f", frameRate);
13758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            TextRun textRun(text.characters(), text.length());
13768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            const Color color(255, 0, 0);
13778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            context->scale(FloatSize(1.0f, -1.0f));
1378643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            context->setStrokeColor(color, styleToUse->colorSpace());
13798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            context->setStrokeStyle(SolidStroke);
13808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            context->setStrokeThickness(1.0f);
1381643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            context->setFillColor(color, styleToUse->colorSpace());
13820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            context->drawText(styleToUse->font(), textRun, IntPoint(2, -3));
13838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
13848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
13858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
13868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
13878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    context->restore();
13888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    END_BLOCK_OBJC_EXCEPTIONS;
13898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [m_objcObserver.get() setDelayCallbacks:NO];
13908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
13918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
13925f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic void addFileTypesToCache(NSArray * fileTypes, HashSet<String> &cache)
13935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
13945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    int count = [fileTypes count];
13955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    for (int n = 0; n < count; n++) {
13965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        CFStringRef ext = reinterpret_cast<CFStringRef>([fileTypes objectAtIndex:n]);
13975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        RetainPtr<CFStringRef> uti(AdoptCF, UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, ext, NULL));
13985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!uti)
13995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            continue;
14005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        RetainPtr<CFStringRef> mime(AdoptCF, UTTypeCopyPreferredTagWithClass(uti.get(), kUTTagClassMIMEType));
140106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        if (mime)
140206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            cache.add(mime.get());
140306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen
140406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        // -movieFileTypes: returns both file extensions and OSTypes. The later are surrounded by single
140506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        // quotes, eg. 'MooV', so don't bother looking at those.
140606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        if (CFStringGetCharacterAtIndex(ext, 0) != '\'') {
140706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            // UTI is missing many media related MIME types supported by QTKit (see rdar://6434168), and not all
140806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            // web servers use the MIME type UTI returns for an extension (see rdar://7875393), so even if UTI
140906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            // has a type for this extension add any types in hard coded table in the MIME type regsitry.
141006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            Vector<String> typesForExtension = MIMETypeRegistry::getMediaMIMETypesForExtension(ext);
141106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            unsigned count = typesForExtension.size();
141206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            for (unsigned ndx = 0; ndx < count; ++ndx) {
141306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                if (!cache.contains(typesForExtension[ndx]))
141406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen                    cache.add(typesForExtension[ndx]);
14155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            }
14165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
14175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
14185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
14195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
14205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic HashSet<String> mimeCommonTypesCache()
14218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
14228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    DEFINE_STATIC_LOCAL(HashSet<String>, cache, ());
14238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    static bool typeListInitialized = false;
14248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
14258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!typeListInitialized) {
14265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        typeListInitialized = true;
14278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        NSArray* fileTypes = [QTMovie movieFileTypes:QTIncludeCommonTypes];
14285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        addFileTypesToCache(fileTypes, cache);
14295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
14305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
14315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return cache;
14325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
14335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
14345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic HashSet<String> mimeModernTypesCache()
14355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
14365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    DEFINE_STATIC_LOCAL(HashSet<String>, cache, ());
14375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    static bool typeListInitialized = false;
14385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
14395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!typeListInitialized) {
14408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        typeListInitialized = true;
14415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        NSArray* fileTypes = [QTMovie movieFileTypes:(QTMovieFileTypeOptions)wkQTIncludeOnlyModernMediaFileTypes()];
14425f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        addFileTypesToCache(fileTypes, cache);
14438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
14448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return cache;
14468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
14478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
14486b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::getSupportedTypes(HashSet<String>& supportedTypes)
14498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
1450ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    supportedTypes = mimeModernTypesCache();
1451ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block
14525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Note: this method starts QTKitServer if it isn't already running when in 64-bit because it has to return the list
14535f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // of every MIME type supported by QTKit.
1454ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    HashSet<String> commonTypes = mimeCommonTypesCache();
1455ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    HashSet<String>::const_iterator it = commonTypes.begin();
1456ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    HashSet<String>::const_iterator end = commonTypes.end();
1457ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    for (; it != end; ++it)
1458ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block        supportedTypes.add(*it);
14598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
14608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
14616b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerMediaPlayer::SupportsType MediaPlayerPrivateQTKit::supportsType(const String& type, const String& codecs)
14628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
14635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Only return "IsSupported" if there is no codecs parameter for now as there is no way to ask QT if it supports an
14645f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // extended MIME type yet.
14655f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
14665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // We check the "modern" type cache first, as it doesn't require QTKitServer to start.
14675f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (mimeModernTypesCache().contains(type) || mimeCommonTypesCache().contains(type))
14680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return codecs.isEmpty() ? MediaPlayer::MayBeSupported : MediaPlayer::IsSupported;
14695f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
14705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return MediaPlayer::IsNotSupported;
14718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
14728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
14736b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerbool MediaPlayerPrivateQTKit::isAvailable()
14748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
14758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef BUILDING_ON_TIGER
14768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SInt32 version;
14778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    OSErr result;
14788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    result = Gestalt(gestaltQuickTime, &version);
14798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (result != noErr) {
14808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOG_ERROR("No QuickTime available. Disabling <video> and <audio> support.");
14818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
14828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
14838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (version < minimumQuickTimeVersion) {
14848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOG_ERROR("QuickTime version %x detected, at least %x required. Disabling <video> and <audio> support.", version, minimumQuickTimeVersion);
14858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
14868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
14878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
14888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
14898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // On 10.5 and higher, QuickTime will always be new enough for <video> and <audio> support, so we just check that the framework can be loaded.
14908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return QTKitLibrary();
14918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
14928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
14938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14946b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::disableUnsupportedTracks()
14958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
14968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_qtMovie) {
14978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_enabledTrackCount = 0;
14985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_totalTrackCount = 0;
14998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
15008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
15018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static HashSet<String>* allowedTrackTypes = 0;
15038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!allowedTrackTypes) {
15048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        allowedTrackTypes = new HashSet<String>;
15058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        allowedTrackTypes->add(QTMediaTypeVideo);
15068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        allowedTrackTypes->add(QTMediaTypeSound);
15078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        allowedTrackTypes->add(QTMediaTypeText);
15088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        allowedTrackTypes->add(QTMediaTypeBase);
15098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        allowedTrackTypes->add(QTMediaTypeMPEG);
15105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        allowedTrackTypes->add("clcp"); // Closed caption
15115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        allowedTrackTypes->add("sbtl"); // Subtitle
15125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        allowedTrackTypes->add("odsm"); // MPEG-4 object descriptor stream
15135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        allowedTrackTypes->add("sdsm"); // MPEG-4 scene description stream
15145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        allowedTrackTypes->add("tmcd"); // timecode
15155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        allowedTrackTypes->add("tc64"); // timcode-64
15165ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        allowedTrackTypes->add("tmet"); // timed metadata
15178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
15188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    NSArray *tracks = [m_qtMovie.get() tracks];
15208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    m_totalTrackCount = [tracks count];
15225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    m_enabledTrackCount = m_totalTrackCount;
15235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    for (unsigned trackIndex = 0; trackIndex < m_totalTrackCount; trackIndex++) {
15248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Grab the track at the current index. If there isn't one there, then
15258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // we can move onto the next one.
15268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        QTTrack *track = [tracks objectAtIndex:trackIndex];
15278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!track)
15288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
15298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Check to see if the track is disabled already, we should move along.
15318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // We don't need to re-disable it.
15320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (![track isEnabled]) {
15330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            --m_enabledTrackCount;
15348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
15350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
15368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        // Get the track's media type.
15385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        NSString *mediaType = [track attributeForKey:QTTrackMediaTypeAttribute];
15398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!mediaType)
15408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
15415f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
15428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Test whether the media type is in our white list.
15438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!allowedTrackTypes->contains(mediaType)) {
15448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // If this track type is not allowed, then we need to disable it.
15458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            [track setEnabled:NO];
15468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            --m_enabledTrackCount;
15470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            m_hasUnsupportedTracks = true;
15488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
15495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
15508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Disable chapter tracks. These are most likely to lead to trouble, as
15518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // they will be composited under the video tracks, forcing QT to do extra
15528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // work.
15538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        QTTrack *chapterTrack = [track performSelector:@selector(chapterlist)];
15548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!chapterTrack)
15558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
15568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Try to grab the media for the track.
15588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        QTMedia *chapterMedia = [chapterTrack media];
15598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!chapterMedia)
15608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
15618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Grab the media type for this track.
15638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        id chapterMediaType = [chapterMedia attributeForKey:QTMediaTypeAttribute];
15648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!chapterMediaType)
15658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
15668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Check to see if the track is a video track. We don't care about
15688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // other non-video tracks.
15698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (![chapterMediaType isEqual:QTMediaTypeVideo])
15708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
15718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Check to see if the track is already disabled. If it is, we
15738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // should move along.
15748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (![chapterTrack isEnabled])
15758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
15768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Disable the evil, evil track.
15788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [chapterTrack setEnabled:NO];
15798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        --m_enabledTrackCount;
15800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        m_hasUnsupportedTracks = true;
15818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
15828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
15838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
15846b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::sawUnsupportedTracks()
15855f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
15865f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    m_hasUnsupportedTracks = true;
15875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    m_player->mediaPlayerClient()->mediaPlayerSawUnsupportedTracks(m_player);
15885f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
15895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
15900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if USE(ACCELERATED_COMPOSITING)
15916b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerbool MediaPlayerPrivateQTKit::supportsAcceleratedRendering() const
15920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
159381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return isReadyForVideoSetup() && getQTMovieLayerClass() != Nil;
15940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
15950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
15966b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::acceleratedRenderingStateChanged()
15970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
15980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Set up or change the rendering path if necessary.
15990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    setUpVideoRendering();
16000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
16010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
16020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
16036b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerbool MediaPlayerPrivateQTKit::hasSingleSecurityOrigin() const
16040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
16050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // We tell quicktime to disallow resources that come from different origins
16060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // so we know all media is single origin.
16070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return true;
16080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
16090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
16106b70adc33054f8aee8c54d0f460458a9df11b8a5Russell BrennerMediaPlayer::MovieLoadType MediaPlayerPrivateQTKit::movieLoadType() const
16110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
16120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!m_qtMovie)
16130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return MediaPlayer::Unknown;
16140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
16150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    MediaPlayer::MovieLoadType movieType = (MediaPlayer::MovieLoadType)wkQTMovieGetType(m_qtMovie.get());
16160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
16170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Can't include WebKitSystemInterface from WebCore so we can't get the enum returned
16180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // by wkQTMovieGetType, but at least verify that the value is in the valid range.
16190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(movieType >= MediaPlayer::Unknown && movieType <= MediaPlayer::LiveStream);
16200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
16210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return movieType;
16228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
16238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
16246b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid MediaPlayerPrivateQTKit::setPreload(MediaPlayer::Preload preload)
1625dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1626dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    m_preload = preload;
1627dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (m_delayingLoad && m_preload != MediaPlayer::None)
1628dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        resumeLoad();
1629dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
16300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
16316b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennerfloat MediaPlayerPrivateQTKit::mediaTimeForTimeValue(float timeValue) const
163228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu{
163328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    if (!metaDataAvailable())
163428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        return timeValue;
163528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
163628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    QTTime qttime = createQTTime(timeValue);
163728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    return static_cast<float>(qttime.timeValue) / qttime.timeScale;
163828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu}
163928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
164081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochvoid MediaPlayerPrivateQTKit::setPrivateBrowsingMode(bool privateBrowsing)
164181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
164281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    m_privateBrowsing = privateBrowsing;
164381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!m_qtMovie)
164481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        return;
164581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    [m_qtMovie.get() setAttribute:[NSNumber numberWithBool:!privateBrowsing] forKey:@"QTMovieAllowPersistentCacheAttribute"];
164681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
164781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
164881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
16490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} // namespace WebCore
16500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
16518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@implementation WebCoreMovieObserver
16528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
16536b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner- (id)initWithCallback:(MediaPlayerPrivateQTKit*)callback
16548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
16558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_callback = callback;
16568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return [super init];
16578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
16588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
16598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)disconnect
16608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
16618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [NSObject cancelPreviousPerformRequestsWithTarget:self];
16628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_callback = 0;
16638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
16648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
16658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project-(NSMenu*)menuForEventDelegate:(NSEvent*)theEvent
16668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
16678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Get the contextual menu from the QTMovieView's superview, the frame view
16688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return [[m_view superview] menuForEvent:theEvent];
16698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
16708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
16718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project-(void)setView:(NSView*)view
16728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
16738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_view = view;
16748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
16758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
16768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project-(void)repaint
16778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
16788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_delayCallbacks)
16798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [self performSelector:_cmd withObject:nil afterDelay:0.];
16808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else if (m_callback)
16818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_callback->repaint();
16828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
16838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1684635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project- (void)loadStateChanged:(NSNotification *)unusedNotification
16858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1686635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    UNUSED_PARAM(unusedNotification);
16878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_delayCallbacks)
16888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [self performSelector:_cmd withObject:nil afterDelay:0];
16898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else
16908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_callback->loadStateChanged();
16918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
16928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1693635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project- (void)rateChanged:(NSNotification *)unusedNotification
16948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1695635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    UNUSED_PARAM(unusedNotification);
16968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_delayCallbacks)
16978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [self performSelector:_cmd withObject:nil afterDelay:0];
16988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else
16998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_callback->rateChanged();
17008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
17018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1702635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project- (void)sizeChanged:(NSNotification *)unusedNotification
17038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1704635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    UNUSED_PARAM(unusedNotification);
17058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_delayCallbacks)
17068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [self performSelector:_cmd withObject:nil afterDelay:0];
17078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else
17088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_callback->sizeChanged();
17098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
17108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1711635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project- (void)timeChanged:(NSNotification *)unusedNotification
17128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1713635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    UNUSED_PARAM(unusedNotification);
17148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_delayCallbacks)
17158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [self performSelector:_cmd withObject:nil afterDelay:0];
17168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else
17178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_callback->timeChanged();
17188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
17198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1720635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project- (void)didEnd:(NSNotification *)unusedNotification
17218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1722635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    UNUSED_PARAM(unusedNotification);
17238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_delayCallbacks)
17248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        [self performSelector:_cmd withObject:nil afterDelay:0];
17258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else
17268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_callback->didEnd();
17278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
17288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1729635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project- (void)newImageAvailable:(NSNotification *)unusedNotification
17308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1731635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    UNUSED_PARAM(unusedNotification);
17328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    [self repaint];
17338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
17348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
17358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project- (void)setDelayCallbacks:(BOOL)shouldDelay
17368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
17378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_delayCallbacks = shouldDelay;
17388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
17398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
17408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project@end
17418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
17428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
1743