diff options
Diffstat (limited to 'src/3rdparty/webkit/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp')
-rw-r--r-- | src/3rdparty/webkit/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp | 203 |
1 files changed, 93 insertions, 110 deletions
diff --git a/src/3rdparty/webkit/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp b/src/3rdparty/webkit/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp index 096ebb2072..bff20c09c6 100644 --- a/src/3rdparty/webkit/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp +++ b/src/3rdparty/webkit/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp @@ -30,6 +30,7 @@ #include "MediaPlayerPrivateAVFoundation.h" #include "ApplicationCacheHost.h" +#include "ApplicationCacheResource.h" #include "DocumentLoader.h" #include "FrameView.h" #include "GraphicsContext.h" @@ -45,30 +46,25 @@ using namespace std; namespace WebCore { -static const float invalidTime = -1.0f; - MediaPlayerPrivateAVFoundation::MediaPlayerPrivateAVFoundation(MediaPlayer* player) : m_player(player) , m_queuedNotifications() , m_queueMutex() - , m_mainThreadCallPending(false) , m_networkState(MediaPlayer::Empty) , m_readyState(MediaPlayer::HaveNothing) , m_preload(MediaPlayer::Auto) , m_scaleFactor(1, 1) , m_cachedMaxTimeLoaded(0) , m_cachedMaxTimeSeekable(0) - , m_cachedDuration(invalidTime) - , m_reportedDuration(invalidTime) - , m_seekTo(invalidTime) + , m_cachedDuration(invalidTime()) + , m_reportedDuration(invalidTime()) + , m_seekTo(invalidTime()) , m_requestedRate(1) - , m_delayCallbacks(false) - , m_havePreparedToPlay(false) + , m_delayCallbacks(0) + , m_mainThreadCallPending(false) , m_assetIsPlayable(false) , m_visible(false) - , m_videoFrameHasDrawn(false) , m_loadingMetadata(false) - , m_delayingLoad(false) , m_isAllowedToRender(false) , m_cachedHasAudio(false) , m_cachedHasVideo(false) @@ -83,6 +79,7 @@ MediaPlayerPrivateAVFoundation::MediaPlayerPrivateAVFoundation(MediaPlayer* play MediaPlayerPrivateAVFoundation::~MediaPlayerPrivateAVFoundation() { LOG(Media, "MediaPlayerPrivateAVFoundation::~MediaPlayerPrivateAVFoundation(%p)", this); + setIgnoreLoadStateChanges(true); cancelCallOnMainThread(mainThreadCallback, this); } @@ -167,17 +164,6 @@ bool MediaPlayerPrivateAVFoundation::hasSetUpVideoRendering() const return hasLayerRenderer() || hasContextRenderer(); } -void MediaPlayerPrivateAVFoundation::resumeLoad() -{ - LOG(Media, "MediaPlayerPrivateAVFoundation::resumeLoad(%p)", this); - - ASSERT(m_delayingLoad); - m_delayingLoad = false; - - if (m_assetURL.length()) - prepareToPlay(); -} - void MediaPlayerPrivateAVFoundation::load(const String& url) { LOG(Media, "MediaPlayerPrivateAVFoundation::load(%p)", this); @@ -191,27 +177,19 @@ void MediaPlayerPrivateAVFoundation::load(const String& url) m_player->readyStateChanged(); } - m_videoFrameHasDrawn = false; m_assetURL = url; // Don't do any more work if the url is empty. if (!url.length()) return; - if (m_preload == MediaPlayer::None) { - LOG(Media, "MediaPlayerPrivateAVFoundation::load(%p) - preload==none so returning", this); - m_delayingLoad = true; - return; - } - - prepareToPlay(); + setPreload(m_preload); } void MediaPlayerPrivateAVFoundation::playabilityKnown() { LOG(Media, "MediaPlayerPrivateAVFoundation::playabilityKnown(%p)", this); - updateStates(); if (m_assetIsPlayable) return; @@ -232,22 +210,7 @@ void MediaPlayerPrivateAVFoundation::prepareToPlay() { LOG(Media, "MediaPlayerPrivateAVFoundation::prepareToPlay(%p)", this); - m_preload = MediaPlayer::Auto; - if (m_havePreparedToPlay) - return; - m_havePreparedToPlay = true; - - m_delayingLoad = false; -#if ENABLE(OFFLINE_WEB_APPLICATIONS) - Frame* frame = m_player->frameView() ? m_player->frameView()->frame() : 0; - ApplicationCacheHost* cacheHost = frame ? frame->loader()->documentLoader()->applicationCacheHost() : 0; - ApplicationCacheResource* resource = 0; - if (cacheHost && cacheHost->shouldLoadResourceFromApplicationCache(ResourceRequest(m_assetURL), resource) && resource) - createAVPlayerForCacheResource(resource); - else -#endif - createAVPlayerForURL(m_assetURL); - checkPlayability(); + setPreload(MediaPlayer::Auto); } void MediaPlayerPrivateAVFoundation::play() @@ -269,22 +232,17 @@ void MediaPlayerPrivateAVFoundation::pause() platformPause(); } -void MediaPlayerPrivateAVFoundation::paint(GraphicsContext*, const IntRect&) -{ - // This is the base class, only need to remember that a frame has been drawn. - m_videoFrameHasDrawn = true; -} - float MediaPlayerPrivateAVFoundation::duration() const { - if (!metaDataAvailable()) - return 0; + if (m_cachedDuration != invalidTime()) + return m_cachedDuration; - if (m_cachedDuration == invalidTime) { - m_cachedDuration = platformDuration(); - LOG(Media, "MediaPlayerPrivateAVFMac::duration(%p) - caching %f", this, m_cachedDuration); - } + float duration = platformDuration(); + if (!duration || duration == invalidTime()) + return 0; + m_cachedDuration = duration; + LOG(Media, "MediaPlayerPrivateAVFoundation::duration(%p) - caching %f", this, m_cachedDuration); return m_cachedDuration; } @@ -326,7 +284,7 @@ bool MediaPlayerPrivateAVFoundation::seeking() const if (!metaDataAvailable()) return false; - return m_seekTo != invalidTime; + return m_seekTo != invalidTime(); } IntSize MediaPlayerPrivateAVFoundation::naturalSize() const @@ -346,6 +304,8 @@ IntSize MediaPlayerPrivateAVFoundation::naturalSize() const void MediaPlayerPrivateAVFoundation::setNaturalSize(IntSize size) { + LOG(Media, "MediaPlayerPrivateAVFoundation:setNaturalSize(%p) - size = %d x %d", this, size.width(), size.height()); + IntSize oldSize = m_cachedNaturalSize; m_cachedNaturalSize = size; if (oldSize != m_cachedNaturalSize) @@ -422,6 +382,9 @@ bool MediaPlayerPrivateAVFoundation::supportsFullscreen() const void MediaPlayerPrivateAVFoundation::updateStates() { + if (m_ignoreLoadStateChanges) + return; + MediaPlayer::NetworkState oldNetworkState = m_networkState; MediaPlayer::ReadyState oldReadyState = m_readyState; @@ -432,24 +395,23 @@ void MediaPlayerPrivateAVFoundation::updateStates() m_networkState = MediaPlayer::Loading; else { // -loadValuesAsynchronouslyForKeys:completionHandler: has invoked its handler; test status of keys and determine state. - AVAssetStatus avAssetStatus = assetStatus(); + AssetStatus assetStatus = this->assetStatus(); ItemStatus itemStatus = playerItemStatus(); - m_assetIsPlayable = (avAssetStatus == MediaPlayerAVAssetStatusPlayable); - if (m_readyState < MediaPlayer::HaveMetadata && avAssetStatus > MediaPlayerAVAssetStatusLoading) { + m_assetIsPlayable = (assetStatus == MediaPlayerAVAssetStatusPlayable); + if (m_readyState < MediaPlayer::HaveMetadata && assetStatus > MediaPlayerAVAssetStatusLoading) { if (m_assetIsPlayable) { - if (itemStatus == MediaPlayerAVPlayerItemStatusUnknown) { - if (avAssetStatus == MediaPlayerAVAssetStatusFailed || m_preload > MediaPlayer::MetaData) { - // We may have a playable asset that doesn't support inspection prior to playback; go ahead - // and create the AVPlayerItem now. When the AVPlayerItem becomes ready to play, we will - // have access to its metadata. Or we may have been asked to become ready to play immediately. + if (assetStatus >= MediaPlayerAVAssetStatusLoaded) + m_readyState = MediaPlayer::HaveMetadata; + if (itemStatus <= MediaPlayerAVPlayerItemStatusUnknown) { + if (assetStatus == MediaPlayerAVAssetStatusFailed || m_preload > MediaPlayer::MetaData || isLiveStream()) { + // The asset is playable but doesn't support inspection prior to playback (eg. streaming files), + // or we are supposed to prepare for playback immediately, so create the player item now. m_networkState = MediaPlayer::Loading; prepareToPlay(); } else m_networkState = MediaPlayer::Idle; } - if (avAssetStatus == MediaPlayerAVAssetStatusLoaded) - m_readyState = MediaPlayer::HaveMetadata; } else { // FIX ME: fetch the error associated with the @"playable" key to distinguish between format // and network errors. @@ -457,36 +419,40 @@ void MediaPlayerPrivateAVFoundation::updateStates() } } - if (avAssetStatus >= MediaPlayerAVAssetStatusLoaded && itemStatus > MediaPlayerAVPlayerItemStatusUnknown) { + if (assetStatus >= MediaPlayerAVAssetStatusLoaded && itemStatus > MediaPlayerAVPlayerItemStatusUnknown) { if (seeking()) m_readyState = m_readyState >= MediaPlayer::HaveMetadata ? MediaPlayer::HaveMetadata : MediaPlayer::HaveNothing; else { - float maxLoaded = maxTimeLoaded(); switch (itemStatus) { + case MediaPlayerAVPlayerItemStatusDoesNotExist: case MediaPlayerAVPlayerItemStatusUnknown: - break; case MediaPlayerAVPlayerItemStatusFailed: - m_networkState = MediaPlayer::DecodeError; break; + case MediaPlayerAVPlayerItemStatusPlaybackLikelyToKeepUp: m_readyState = MediaPlayer::HaveEnoughData; break; - case MediaPlayerAVPlayerItemStatusReadyToPlay: + case MediaPlayerAVPlayerItemStatusPlaybackBufferFull: + case MediaPlayerAVPlayerItemStatusReadyToPlay: // If the readyState is already HaveEnoughData, don't go lower because of this state change. if (m_readyState == MediaPlayer::HaveEnoughData) break; case MediaPlayerAVPlayerItemStatusPlaybackBufferEmpty: - if (maxLoaded > currentTime()) + if (maxTimeLoaded() > currentTime()) m_readyState = MediaPlayer::HaveFutureData; else m_readyState = MediaPlayer::HaveCurrentData; break; } - if (itemStatus >= MediaPlayerAVPlayerItemStatusReadyToPlay) - m_networkState = (maxLoaded == duration()) ? MediaPlayer::Loaded : MediaPlayer::Loading; + if (itemStatus == MediaPlayerAVPlayerItemStatusPlaybackBufferFull) + m_networkState = MediaPlayer::Idle; + else if (itemStatus == MediaPlayerAVPlayerItemStatusFailed) + m_networkState = MediaPlayer::DecodeError; + else if (itemStatus != MediaPlayerAVPlayerItemStatusPlaybackBufferFull && itemStatus >= MediaPlayerAVPlayerItemStatusReadyToPlay) + m_networkState = (maxTimeLoaded() == duration()) ? MediaPlayer::Loaded : MediaPlayer::Loading; } } } @@ -495,6 +461,8 @@ void MediaPlayerPrivateAVFoundation::updateStates() setUpVideoRendering(); if (!m_haveReportedFirstVideoFrame && m_cachedHasVideo && hasAvailableVideoFrame()) { + if (m_readyState < MediaPlayer::HaveCurrentData) + m_readyState = MediaPlayer::HaveCurrentData; m_haveReportedFirstVideoFrame = true; m_player->firstVideoFrameAvailable(); } @@ -530,16 +498,6 @@ void MediaPlayerPrivateAVFoundation::setVisible(bool visible) platformSetVisible(visible); } -bool MediaPlayerPrivateAVFoundation::hasAvailableVideoFrame() const -{ - if (currentRenderingMode() == MediaRenderingToLayer) - return videoLayerIsReadyToDisplay(); - - // When using the software renderer we hope someone will signal that a frame is available so we might as well - // wait until we know that a frame has been drawn. - return m_videoFrameHasDrawn; -} - void MediaPlayerPrivateAVFoundation::acceleratedRenderingStateChanged() { // Set up or change the rendering path if necessary. @@ -549,19 +507,11 @@ void MediaPlayerPrivateAVFoundation::acceleratedRenderingStateChanged() void MediaPlayerPrivateAVFoundation::metadataLoaded() { m_loadingMetadata = false; - updateStates(); -} - -void MediaPlayerPrivateAVFoundation::loadStateChanged() -{ - if (m_ignoreLoadStateChanges) - return; - updateStates(); + tracksChanged(); } void MediaPlayerPrivateAVFoundation::rateChanged() { - updateStates(); m_player->rateChanged(); } @@ -569,13 +519,12 @@ void MediaPlayerPrivateAVFoundation::loadedTimeRangesChanged() { m_cachedLoadedTimeRanges = 0; m_cachedMaxTimeLoaded = 0; - updateStates(); // For some media files, reported duration is estimated and updated as media is loaded // so report duration changed when the estimate is upated. float dur = duration(); if (dur != m_reportedDuration) { - if (m_reportedDuration != invalidTime) + if (m_reportedDuration != invalidTime()) m_player->durationChanged(); m_reportedDuration = dur; } @@ -590,7 +539,7 @@ void MediaPlayerPrivateAVFoundation::timeChanged(double time) { LOG(Media, "MediaPlayerPrivateAVFoundation::timeChanged(%p) - time = %f", this, time); - if (m_seekTo == invalidTime) + if (m_seekTo == invalidTime()) return; // AVFoundation may call our observer more than once during a seek, and we can't currently tell @@ -600,7 +549,7 @@ void MediaPlayerPrivateAVFoundation::timeChanged(double time) float currentRate = rate(); if ((currentRate > 0 && time >= m_seekTo) || (currentRate < 0 && time <= m_seekTo) || (abs(m_seekTo - time) <= smallSeekDelta)) { - m_seekTo = invalidTime; + m_seekTo = invalidTime(); updateStates(); m_player->timeChanged(); } @@ -611,7 +560,7 @@ void MediaPlayerPrivateAVFoundation::seekCompleted(bool finished) LOG(Media, "MediaPlayerPrivateAVFoundation::seekCompleted(%p) - finished = %d", this, finished); if (finished) - m_seekTo = invalidTime; + m_seekTo = invalidTime(); } void MediaPlayerPrivateAVFoundation::didEnd() @@ -628,7 +577,6 @@ void MediaPlayerPrivateAVFoundation::didEnd() void MediaPlayerPrivateAVFoundation::repaint() { - m_videoFrameHasDrawn = true; m_player->repaint(); } @@ -646,8 +594,38 @@ MediaPlayer::MovieLoadType MediaPlayerPrivateAVFoundation::movieLoadType() const void MediaPlayerPrivateAVFoundation::setPreload(MediaPlayer::Preload preload) { m_preload = preload; - if (m_delayingLoad && m_preload != MediaPlayer::None) - resumeLoad(); + if (!m_assetURL.length()) + return; + + setDelayCallbacks(true); + + if (m_preload >= MediaPlayer::MetaData && assetStatus() == MediaPlayerAVAssetStatusDoesNotExist) { +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + Frame* frame = m_player->frameView() ? m_player->frameView()->frame() : 0; + ApplicationCacheHost* cacheHost = frame ? frame->loader()->documentLoader()->applicationCacheHost() : 0; + ApplicationCacheResource* resource; + if (cacheHost && cacheHost->shouldLoadResourceFromApplicationCache(ResourceRequest(m_assetURL), resource) && resource) { + // AVFoundation can't open arbitrary data pointers, so if this ApplicationCacheResource doesn't + // have a valid local path, just open the resource's original URL. + if (resource->path().isEmpty()) + createAVAssetForURL(resource->url()); + else + createAVAssetForCacheResource(resource); + } else +#endif + createAVAssetForURL(m_assetURL); + + createAVPlayer(); + + checkPlayability(); + } + + // Don't force creation of the player item unless we already know that the asset is playable. If we aren't + // there yet, or if we already know it is not playable, creating it now won't help. + if (m_preload == MediaPlayer::Auto && m_assetIsPlayable) + createAVPlayerItem(); + + setDelayCallbacks(false); } void MediaPlayerPrivateAVFoundation::setDelayCallbacks(bool delay) @@ -742,31 +720,34 @@ void MediaPlayerPrivateAVFoundation::dispatchNotification() break; case Notification::ItemTracksChanged: tracksChanged(); + updateStates(); break; case Notification::ItemStatusChanged: - loadStateChanged(); + updateStates(); break; case Notification::ItemSeekableTimeRangesChanged: seekableTimeRangesChanged(); - loadStateChanged(); + updateStates(); break; case Notification::ItemLoadedTimeRangesChanged: loadedTimeRangesChanged(); - loadStateChanged(); + updateStates(); break; case Notification::ItemPresentationSizeChanged: sizeChanged(); + updateStates(); break; case Notification::ItemIsPlaybackLikelyToKeepUpChanged: - loadStateChanged(); + updateStates(); break; case Notification::ItemIsPlaybackBufferEmptyChanged: - loadStateChanged(); + updateStates(); break; case Notification::ItemIsPlaybackBufferFullChanged: - loadStateChanged(); + updateStates(); break; case Notification::PlayerRateChanged: + updateStates(); rateChanged(); break; case Notification::PlayerTimeChanged: @@ -777,8 +758,10 @@ void MediaPlayerPrivateAVFoundation::dispatchNotification() break; case Notification::AssetMetadataLoaded: metadataLoaded(); + updateStates(); break; case Notification::AssetPlayabilityKnown: + updateStates(); playabilityKnown(); break; case Notification::None: |