void MediaPlayerPrivateAVFoundation::play() { LOG(Media, "MediaPlayerPrivateAVFoundation::play(%p)", this); // If the file has video, don't request playback until the first frame of video is ready to display // or the audio may start playing before we can render video. if (!m_cachedHasVideo || hasAvailableVideoFrame()) platformPlay(); else m_playWhenFramesAvailable = true; }
void MediaPlayerPrivateAVFoundation::updateStates() { if (m_ignoreLoadStateChanges) return; MediaPlayer::NetworkState newNetworkState = m_networkState; MediaPlayer::ReadyState newReadyState = m_readyState; if (m_loadingMetadata) newNetworkState = MediaPlayer::Loading; else { // -loadValuesAsynchronouslyForKeys:completionHandler: has invoked its handler; test status of keys and determine state. AssetStatus assetStatus = this->assetStatus(); ItemStatus itemStatus = playerItemStatus(); m_assetIsPlayable = (assetStatus == MediaPlayerAVAssetStatusPlayable); if (m_readyState < MediaPlayer::HaveMetadata && assetStatus > MediaPlayerAVAssetStatusLoading) { if (m_assetIsPlayable) { if (assetStatus >= MediaPlayerAVAssetStatusLoaded) newReadyState = 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. newNetworkState = MediaPlayer::Loading; prepareToPlay(); } else newNetworkState = MediaPlayer::Idle; } } else { // FIX ME: fetch the error associated with the @"playable" key to distinguish between format // and network errors. newNetworkState = MediaPlayer::FormatError; } } if (assetStatus >= MediaPlayerAVAssetStatusLoaded && itemStatus > MediaPlayerAVPlayerItemStatusUnknown) { switch (itemStatus) { case MediaPlayerAVPlayerItemStatusDoesNotExist: case MediaPlayerAVPlayerItemStatusUnknown: case MediaPlayerAVPlayerItemStatusFailed: break; case MediaPlayerAVPlayerItemStatusPlaybackLikelyToKeepUp: case MediaPlayerAVPlayerItemStatusPlaybackBufferFull: // If the status becomes PlaybackBufferFull, loading stops and the status will not // progress to LikelyToKeepUp. Set the readyState to HAVE_ENOUGH_DATA, on the // presumption that if the playback buffer is full, playback will probably not stall. newReadyState = MediaPlayer::HaveEnoughData; break; case MediaPlayerAVPlayerItemStatusReadyToPlay: if (m_readyState != MediaPlayer::HaveEnoughData && maxTimeLoaded() > currentMediaTime()) newReadyState = MediaPlayer::HaveFutureData; break; case MediaPlayerAVPlayerItemStatusPlaybackBufferEmpty: newReadyState = MediaPlayer::HaveCurrentData; break; } if (itemStatus == MediaPlayerAVPlayerItemStatusPlaybackBufferFull) newNetworkState = MediaPlayer::Idle; else if (itemStatus == MediaPlayerAVPlayerItemStatusFailed) newNetworkState = MediaPlayer::DecodeError; else if (itemStatus != MediaPlayerAVPlayerItemStatusPlaybackBufferFull && itemStatus >= MediaPlayerAVPlayerItemStatusReadyToPlay) newNetworkState = (maxTimeLoaded() == durationMediaTime()) ? MediaPlayer::Loaded : MediaPlayer::Loading; } } if (isReadyForVideoSetup() && currentRenderingMode() != preferredRenderingMode()) setUpVideoRendering(); if (!m_haveReportedFirstVideoFrame && m_cachedHasVideo && hasAvailableVideoFrame()) { if (m_readyState < MediaPlayer::HaveCurrentData) newReadyState = MediaPlayer::HaveCurrentData; m_haveReportedFirstVideoFrame = true; m_player->firstVideoFrameAvailable(); } #if !LOG_DISABLED if (m_networkState != newNetworkState || m_readyState != newReadyState) { LOG(Media, "MediaPlayerPrivateAVFoundation::updateStates(%p) - entered with networkState = %i, readyState = %i, exiting with networkState = %i, readyState = %i", this, static_cast<int>(m_networkState), static_cast<int>(m_readyState), static_cast<int>(newNetworkState), static_cast<int>(newReadyState)); } #endif setNetworkState(newNetworkState); setReadyState(newReadyState); if (m_playWhenFramesAvailable && hasAvailableVideoFrame()) { m_playWhenFramesAvailable = false; platformPlay(); } }
void MediaPlayerPrivateAVFoundation::updateStates() { if (m_ignoreLoadStateChanges) return; MediaPlayer::NetworkState oldNetworkState = m_networkState; MediaPlayer::ReadyState oldReadyState = m_readyState; LOG(Media, "MediaPlayerPrivateAVFoundation::updateStates(%p) - entering with networkState = %i, readyState = %i", this, static_cast<int>(m_networkState), static_cast<int>(m_readyState)); if (m_loadingMetadata) m_networkState = MediaPlayer::Loading; else { // -loadValuesAsynchronouslyForKeys:completionHandler: has invoked its handler; test status of keys and determine state. AssetStatus assetStatus = this->assetStatus(); ItemStatus itemStatus = playerItemStatus(); m_assetIsPlayable = (assetStatus == MediaPlayerAVAssetStatusPlayable); if (m_readyState < MediaPlayer::HaveMetadata && assetStatus > MediaPlayerAVAssetStatusLoading) { if (m_assetIsPlayable) { 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; } } else { // FIX ME: fetch the error associated with the @"playable" key to distinguish between format // and network errors. m_networkState = MediaPlayer::FormatError; } } if (assetStatus >= MediaPlayerAVAssetStatusLoaded && itemStatus > MediaPlayerAVPlayerItemStatusUnknown) { switch (itemStatus) { case MediaPlayerAVPlayerItemStatusDoesNotExist: case MediaPlayerAVPlayerItemStatusUnknown: case MediaPlayerAVPlayerItemStatusFailed: break; case MediaPlayerAVPlayerItemStatusPlaybackLikelyToKeepUp: m_readyState = MediaPlayer::HaveEnoughData; break; 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 (maxTimeLoaded() > currentTime()) m_readyState = MediaPlayer::HaveFutureData; else m_readyState = MediaPlayer::HaveCurrentData; break; } 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; } } if (isReadyForVideoSetup() && currentRenderingMode() != preferredRenderingMode()) setUpVideoRendering(); if (!m_haveReportedFirstVideoFrame && m_cachedHasVideo && hasAvailableVideoFrame()) { if (m_readyState < MediaPlayer::HaveCurrentData) m_readyState = MediaPlayer::HaveCurrentData; m_haveReportedFirstVideoFrame = true; m_player->firstVideoFrameAvailable(); } if (m_networkState != oldNetworkState) m_player->networkStateChanged(); if (m_readyState != oldReadyState) m_player->readyStateChanged(); if (m_playWhenFramesAvailable && hasAvailableVideoFrame()) { m_playWhenFramesAvailable = false; platformPlay(); } LOG(Media, "MediaPlayerPrivateAVFoundation::updateStates(%p) - exiting with networkState = %i, readyState = %i", this, static_cast<int>(m_networkState), static_cast<int>(m_readyState)); }