📄 mediaplayerprivateqtkit.mm
字号:
return; // stop observing the renderer's notifications before we toss it [[NSNotificationCenter defaultCenter] removeObserver:m_objcObserver.get() name:QTVideoRendererWebKitOnlyNewImageAvailableNotification object:m_qtVideoRenderer.get()]; // disassociate our movie from our instance of QTVideoRendererWebKitOnly [(id<WebKitVideoRenderingDetails>)m_qtVideoRenderer.get() setMovie:nil]; m_qtVideoRenderer = nil;}void MediaPlayerPrivate::setUpVideoRendering(){ if (!m_player->frameView() || !m_qtMovie) return; if (m_player->inMediaDocument() || !QTVideoRendererClass() ) createQTMovieView(); else createQTVideoRenderer();}void MediaPlayerPrivate::tearDownVideoRendering(){ if (m_qtMovieView) detachQTMovieView(); else destroyQTVideoRenderer();}QTTime MediaPlayerPrivate::createQTTime(float time) const{ if (!metaDataAvailable()) return QTMakeTime(0, 600); long timeScale = [[m_qtMovie.get() attributeForKey:QTMovieTimeScaleAttribute] longValue]; return QTMakeTime(time * timeScale, timeScale);}void MediaPlayerPrivate::load(const String& url){ if (m_networkState != MediaPlayer::Loading) { m_networkState = MediaPlayer::Loading; m_player->networkStateChanged(); } if (m_readyState != MediaPlayer::DataUnavailable) { m_readyState = MediaPlayer::DataUnavailable; m_player->readyStateChanged(); } cancelSeek(); m_endPointTimer.stop(); [m_objcObserver.get() setDelayCallbacks:YES]; createQTMovie(url); [m_objcObserver.get() loadStateChanged:nil]; [m_objcObserver.get() setDelayCallbacks:NO];}void MediaPlayerPrivate::play(){ if (!metaDataAvailable()) return; m_startedPlaying = true;#if DRAW_FRAME_RATE m_frameCountWhilePlaying = 0;#endif [m_objcObserver.get() setDelayCallbacks:YES]; [m_qtMovie.get() setRate:m_player->rate()]; [m_objcObserver.get() setDelayCallbacks:NO]; startEndPointTimerIfNeeded();}void MediaPlayerPrivate::pause(){ if (!metaDataAvailable()) return; m_startedPlaying = false;#if DRAW_FRAME_RATE m_timeStoppedPlaying = [NSDate timeIntervalSinceReferenceDate];#endif [m_objcObserver.get() setDelayCallbacks:YES]; [m_qtMovie.get() stop]; [m_objcObserver.get() setDelayCallbacks:NO]; m_endPointTimer.stop();}float MediaPlayerPrivate::duration() const{ if (!metaDataAvailable()) return 0; QTTime time = [m_qtMovie.get() duration]; if (time.flags == kQTTimeIsIndefinite) return numeric_limits<float>::infinity(); return static_cast<float>(time.timeValue) / time.timeScale;}float MediaPlayerPrivate::currentTime() const{ if (!metaDataAvailable()) return 0; QTTime time = [m_qtMovie.get() currentTime]; return min(static_cast<float>(time.timeValue) / time.timeScale, m_endTime);}void MediaPlayerPrivate::seek(float time){ cancelSeek(); if (!metaDataAvailable()) return; if (time > duration()) time = duration(); m_seekTo = time; if (maxTimeLoaded() >= m_seekTo) doSeek(); else m_seekTimer.start(0, 0.5f);}void MediaPlayerPrivate::doSeek() { QTTime qttime = createQTTime(m_seekTo); // setCurrentTime generates several event callbacks, update afterwards [m_objcObserver.get() setDelayCallbacks:YES]; float oldRate = [m_qtMovie.get() rate]; [m_qtMovie.get() setRate:0]; [m_qtMovie.get() setCurrentTime:qttime]; float timeAfterSeek = currentTime(); // restore playback only if not at end, othewise QTMovie will loop if (timeAfterSeek < duration() && timeAfterSeek < m_endTime) [m_qtMovie.get() setRate:oldRate]; cancelSeek(); [m_objcObserver.get() setDelayCallbacks:NO];}void MediaPlayerPrivate::cancelSeek(){ m_seekTo = -1; m_seekTimer.stop();}void MediaPlayerPrivate::seekTimerFired(Timer<MediaPlayerPrivate>*){ if (!metaDataAvailable()|| !seeking() || currentTime() == m_seekTo) { cancelSeek(); updateStates(); m_player->timeChanged(); return; } if (maxTimeLoaded() >= m_seekTo) doSeek(); else { MediaPlayer::NetworkState state = networkState(); if (state == MediaPlayer::Empty || state == MediaPlayer::Loaded) { cancelSeek(); updateStates(); m_player->timeChanged(); } }}void MediaPlayerPrivate::setEndTime(float time){ m_endTime = time; startEndPointTimerIfNeeded();}void MediaPlayerPrivate::startEndPointTimerIfNeeded(){ if (m_endTime < duration() && m_startedPlaying && !m_endPointTimer.isActive()) m_endPointTimer.startRepeating(endPointTimerInterval);}void MediaPlayerPrivate::endPointTimerFired(Timer<MediaPlayerPrivate>*){ float time = currentTime(); // just do end for now if (time >= m_endTime) { pause(); didEnd(); }}bool MediaPlayerPrivate::paused() const{ if (!metaDataAvailable()) return true; return [m_qtMovie.get() rate] == 0;}bool MediaPlayerPrivate::seeking() const{ if (!metaDataAvailable()) return false; return m_seekTo >= 0;}IntSize MediaPlayerPrivate::naturalSize() const{ if (!metaDataAvailable()) return IntSize(); return IntSize([[m_qtMovie.get() attributeForKey:QTMovieNaturalSizeAttribute] sizeValue]);}bool MediaPlayerPrivate::hasVideo() const{ if (!metaDataAvailable()) return false; return [[m_qtMovie.get() attributeForKey:QTMovieHasVideoAttribute] boolValue];}void MediaPlayerPrivate::setVolume(float volume){ if (!metaDataAvailable()) return; [m_qtMovie.get() setVolume:volume]; }void MediaPlayerPrivate::setRate(float rate){ if (!metaDataAvailable()) return; if (!paused()) [m_qtMovie.get() setRate:rate];}int MediaPlayerPrivate::dataRate() const{ if (!metaDataAvailable()) return 0; return wkQTMovieDataRate(m_qtMovie.get()); }float MediaPlayerPrivate::maxTimeBuffered() const{ // rtsp streams are not buffered return m_isStreaming ? 0 : maxTimeLoaded();}float MediaPlayerPrivate::maxTimeSeekable() const{ // infinite duration means live stream return isinf(duration()) ? 0 : maxTimeLoaded();}float MediaPlayerPrivate::maxTimeLoaded() const{ if (!metaDataAvailable()) return 0; return wkQTMovieMaxTimeLoaded(m_qtMovie.get()); }unsigned MediaPlayerPrivate::bytesLoaded() const{ float dur = duration(); if (!dur) return 0; return totalBytes() * maxTimeLoaded() / dur;}bool MediaPlayerPrivate::totalBytesKnown() const{ return totalBytes() > 0;}unsigned MediaPlayerPrivate::totalBytes() const{ if (!metaDataAvailable()) return 0; return [[m_qtMovie.get() attributeForKey:QTMovieDataSizeAttribute] intValue];}void MediaPlayerPrivate::cancelLoad(){ // FIXME: Is there a better way to check for this? if (m_networkState < MediaPlayer::Loading || m_networkState == MediaPlayer::Loaded) return; tearDownVideoRendering(); m_qtMovie = nil; updateStates();}void MediaPlayerPrivate::updateStates(){ MediaPlayer::NetworkState oldNetworkState = m_networkState; MediaPlayer::ReadyState oldReadyState = m_readyState; long loadState = m_qtMovie ? [[m_qtMovie.get() attributeForKey:QTMovieLoadStateAttribute] longValue] : static_cast<long>(QTMovieLoadStateError); if (loadState >= QTMovieLoadStateLoaded && m_networkState < MediaPlayer::LoadedMetaData && !m_player->inMediaDocument()) { unsigned enabledTrackCount; disableUnsupportedTracks(enabledTrackCount); // FIXME: We should differentiate between load errors and decode errors <rdar://problem/5605692> if (!enabledTrackCount) loadState = QTMovieLoadStateError; } // "Loaded" is reserved for fully buffered movies, never the case when streaming if (loadState >= QTMovieLoadStateComplete && !m_isStreaming) { if (m_networkState < MediaPlayer::Loaded) m_networkState = MediaPlayer::Loaded; m_readyState = MediaPlayer::CanPlayThrough; } else if (loadState >= QTMovieLoadStatePlaythroughOK) { if (m_networkState < MediaPlayer::LoadedFirstFrame && !seeking()) m_networkState = MediaPlayer::LoadedFirstFrame; m_readyState = MediaPlayer::CanPlayThrough; } else if (loadState >= QTMovieLoadStatePlayable) { if (m_networkState < MediaPlayer::LoadedFirstFrame && !seeking()) m_networkState = MediaPlayer::LoadedFirstFrame; // FIXME: This might not work correctly in streaming case, <rdar://problem/5693967> m_readyState = currentTime() < maxTimeLoaded() ? MediaPlayer::CanPlay : MediaPlayer::DataUnavailable; } else if (loadState >= QTMovieLoadStateLoaded) { if (m_networkState < MediaPlayer::LoadedMetaData) m_networkState = MediaPlayer::LoadedMetaData; m_readyState = MediaPlayer::DataUnavailable; } else if (loadState > QTMovieLoadStateError) { if (m_networkState < MediaPlayer::Loading) m_networkState = MediaPlayer::Loading; m_readyState = MediaPlayer::DataUnavailable; } else { m_networkState = MediaPlayer::LoadFailed; m_readyState = MediaPlayer::DataUnavailable; } if (seeking()) m_readyState = MediaPlayer::DataUnavailable; if (m_networkState != oldNetworkState) m_player->networkStateChanged(); if (m_readyState != oldReadyState) m_player->readyStateChanged(); if (loadState >= QTMovieLoadStateLoaded && oldNetworkState < MediaPlayer::LoadedMetaData && m_player->visible()) setUpVideoRendering();}void MediaPlayerPrivate::loadStateChanged(){ updateStates();}void MediaPlayerPrivate::rateChanged(){ updateStates();}void MediaPlayerPrivate::sizeChanged(){}void MediaPlayerPrivate::timeChanged(){ updateStates();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -