summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/filters/adaptive_demuxer.cc100
-rw-r--r--media/filters/adaptive_demuxer.h2
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);