diff options
Diffstat (limited to 'media')
-rw-r--r-- | media/filters/adaptive_demuxer.cc | 100 | ||||
-rw-r--r-- | media/filters/adaptive_demuxer.h | 2 |
2 files changed, 73 insertions, 29 deletions
diff --git a/media/filters/adaptive_demuxer.cc b/media/filters/adaptive_demuxer.cc index 09a1e67..7fe2ab7 100644 --- a/media/filters/adaptive_demuxer.cc +++ b/media/filters/adaptive_demuxer.cc @@ -134,7 +134,6 @@ void AdaptiveDemuxer::ChangeCurrentDemuxer(int audio_index, int video_index) { // TODO(fischman): this is currently broken because when a new Demuxer is to // be used we need to set_host(host()) it, and we need to set_host(NULL) the // current Demuxer if it's no longer being used. - // TODO(fischman): remember to Stop active demuxers that are being abandoned. base::AutoLock auto_lock(lock_); current_audio_demuxer_index_ = audio_index; current_video_demuxer_index_ = video_index; @@ -193,14 +192,13 @@ class CountingCallback { }; void AdaptiveDemuxer::Stop(FilterCallback* callback) { - Demuxer* audio = current_demuxer(DemuxerStream::AUDIO); - Demuxer* video = current_demuxer(DemuxerStream::VIDEO); - int count = (audio ? 1 : 0) + (video && audio != video ? 1 : 0); - CountingCallback* wrapper = new CountingCallback(count, callback); - if (audio) - audio->Stop(wrapper->GetACallback()); - if (video && audio != video) - video->Stop(wrapper->GetACallback()); + // Stop() must be called on all of the demuxers even though only one demuxer + // is actively delivering audio and another one is delivering video. This + // just satisfies the contract that all demuxers must have Stop() called on + // them before they are destroyed. + CountingCallback* wrapper = new CountingCallback(demuxers_.size(), callback); + for (size_t i = 0; i < demuxers_.size(); ++i) + demuxers_[i]->Stop(wrapper->GetACallback()); } void AdaptiveDemuxer::Seek(base::TimeDelta time, FilterCallback* callback) { @@ -215,11 +213,8 @@ void AdaptiveDemuxer::Seek(base::TimeDelta time, FilterCallback* callback) { } void AdaptiveDemuxer::OnAudioRendererDisabled() { - Demuxer* audio = current_demuxer(DemuxerStream::AUDIO); - Demuxer* video = current_demuxer(DemuxerStream::VIDEO); - if (audio) audio->OnAudioRendererDisabled(); - if (video && audio != video) video->OnAudioRendererDisabled(); - // TODO(fischman): propagate to other demuxers if/when they're selected. + for (size_t i = 0; i < demuxers_.size(); ++i) + demuxers_[i]->OnAudioRendererDisabled(); } void AdaptiveDemuxer::set_host(FilterHost* filter_host) { @@ -229,7 +224,17 @@ void AdaptiveDemuxer::set_host(FilterHost* filter_host) { if (video && audio != video) video->set_host(filter_host); } -void AdaptiveDemuxer::SetPreload(Preload preload) {} +void AdaptiveDemuxer::SetPlaybackRate(float playback_rate) { + Demuxer* audio = current_demuxer(DemuxerStream::AUDIO); + Demuxer* video = current_demuxer(DemuxerStream::VIDEO); + if (audio) audio->SetPlaybackRate(playback_rate); + if (video && audio != video) video->SetPlaybackRate(playback_rate); +} + +void AdaptiveDemuxer::SetPreload(Preload preload) { + for (size_t i = 0; i < demuxers_.size(); ++i) + demuxers_[i]->SetPreload(preload); +} scoped_refptr<DemuxerStream> AdaptiveDemuxer::GetStream( DemuxerStream::Type type) { @@ -348,26 +353,65 @@ class DemuxerAccumulator { DoneAccumulating(); } + // Called when all of the demuxers have been built. void DoneAccumulating() { - PipelineStatus overall_status = PIPELINE_OK; - for (size_t i = 0; i < statuses_.size(); ++i) { - if (statuses_[i] != PIPELINE_OK) { - overall_status = statuses_[i]; - break; - } - } + PipelineStatus overall_status = GetOverallStatus(); if (overall_status == PIPELINE_OK) { - orig_cb_->Run( - PIPELINE_OK, - new AdaptiveDemuxer(demuxers_, audio_index_, video_index_)); - } else { - orig_cb_->Run(overall_status, static_cast<Demuxer*>(NULL)); + CallOriginalCallback(PIPELINE_OK, + new AdaptiveDemuxer(demuxers_, audio_index_, + video_index_)); + return; } + // An error occurred. Call Stop() on all of the demuxers that were + // successfully built. + AdaptiveDemuxer::DemuxerVector demuxers_to_stop; + + for (size_t i = 0; i < demuxers_.size(); ++i) { + if (demuxers_[i].get()) + demuxers_to_stop.push_back(demuxers_[i]); + } + + if (demuxers_to_stop.empty()) { + CallOriginalCallback(overall_status, NULL); + return; + } + + CountingCallback* wrapper = new CountingCallback( + demuxers_to_stop.size(), + NewCallback(this, &DemuxerAccumulator::StopOnErrorDone)); + for (size_t i = 0; i < demuxers_to_stop.size(); ++i) + demuxers_to_stop[i]->Stop(wrapper->GetACallback()); + } + + // Called after Stop() has been called on all of the demuxers that were + // successfully built. + void StopOnErrorDone() { + CallOriginalCallback(GetOverallStatus(), NULL); + } + + void CallOriginalCallback(PipelineStatus status, Demuxer* demuxer) { + orig_cb_->Run(status, demuxer); + delete this; } - // Self-delete in DoneAccumulating() only. + // Gets the overall status of the demuxer factory builds. If all build + // operations are successful then this will return PIPELINE_OK. If there + // are any errors then this function will return the first error that + // it encounters. Multiple builds may have failed, but we only care about + // the first error since only one error can be reported to the higher level + // code. + PipelineStatus GetOverallStatus() const { + for (size_t i = 0; i < statuses_.size(); ++i) { + if (statuses_[i] != PIPELINE_OK) + return statuses_[i]; + } + + return PIPELINE_OK; + } + + // Self-delete in CallOriginalCallback() only. ~DemuxerAccumulator() {} int audio_index_; diff --git a/media/filters/adaptive_demuxer.h b/media/filters/adaptive_demuxer.h index 937e01c..c38b4e7 100644 --- a/media/filters/adaptive_demuxer.h +++ b/media/filters/adaptive_demuxer.h @@ -82,8 +82,8 @@ class AdaptiveDemuxer : public Demuxer { virtual void Seek(base::TimeDelta time, FilterCallback* callback); virtual void OnAudioRendererDisabled(); virtual void set_host(FilterHost* filter_host); + virtual void SetPlaybackRate(float playback_rate); virtual void SetPreload(Preload preload); - // TODO(fischman): add support for SetPlaybackRate(). // Demuxer implementation. virtual scoped_refptr<DemuxerStream> GetStream(DemuxerStream::Type type); |