Index: media/filters/audio_renderer_impl.cc |
diff --git a/media/filters/audio_renderer_impl.cc b/media/filters/audio_renderer_impl.cc |
index 820cf6ee58e0a3036ffbbb479926d844becb9124..20dffd6143bf4a6fe53acc5ab32a74a5e0280b68 100644 |
--- a/media/filters/audio_renderer_impl.cc |
+++ b/media/filters/audio_renderer_impl.cc |
@@ -6,11 +6,14 @@ |
#include <math.h> |
+#include <algorithm> |
+ |
#include "base/bind.h" |
#include "base/callback.h" |
#include "base/callback_helpers.h" |
#include "base/logging.h" |
#include "media/audio/audio_util.h" |
+#include "media/base/demuxer_stream.h" |
namespace media { |
@@ -83,6 +86,8 @@ void AudioRendererImpl::Flush(const base::Closure& callback) { |
} |
void AudioRendererImpl::Stop(const base::Closure& callback) { |
+ DCHECK(!callback.is_null()); |
+ |
if (!stopped_) { |
DCHECK(sink_.get()); |
sink_->Stop(); |
@@ -93,12 +98,12 @@ void AudioRendererImpl::Stop(const base::Closure& callback) { |
base::AutoLock auto_lock(lock_); |
state_ = kStopped; |
algorithm_.reset(NULL); |
- time_cb_.Reset(); |
+ init_cb_.Reset(); |
underflow_cb_.Reset(); |
+ time_cb_.Reset(); |
} |
- if (!callback.is_null()) { |
- callback.Run(); |
- } |
+ |
+ callback.Run(); |
} |
void AudioRendererImpl::Preroll(base::TimeDelta time, |
@@ -130,14 +135,19 @@ void AudioRendererImpl::Preroll(base::TimeDelta time, |
sink_->Pause(true); |
} |
-void AudioRendererImpl::Initialize(const scoped_refptr<AudioDecoder>& decoder, |
+void AudioRendererImpl::Initialize(const scoped_refptr<DemuxerStream>& stream, |
+ const AudioDecoderList& decoders, |
const PipelineStatusCB& init_cb, |
+ const StatisticsCB& statistics_cb, |
const base::Closure& underflow_cb, |
const TimeCB& time_cb, |
const base::Closure& ended_cb, |
const base::Closure& disabled_cb, |
const PipelineStatusCB& error_cb) { |
- DCHECK(decoder); |
+ base::AutoLock auto_lock(lock_); |
+ DCHECK(stream); |
+ DCHECK(!decoders.empty()); |
+ DCHECK_EQ(stream->type(), DemuxerStream::AUDIO); |
DCHECK(!init_cb.is_null()); |
DCHECK(!underflow_cb.is_null()); |
DCHECK(!time_cb.is_null()); |
@@ -145,13 +155,61 @@ void AudioRendererImpl::Initialize(const scoped_refptr<AudioDecoder>& decoder, |
DCHECK(!disabled_cb.is_null()); |
DCHECK(!error_cb.is_null()); |
DCHECK_EQ(kUninitialized, state_); |
- decoder_ = decoder; |
+ |
+ init_cb_ = init_cb; |
+ statistics_cb_ = statistics_cb; |
underflow_cb_ = underflow_cb; |
time_cb_ = time_cb; |
ended_cb_ = ended_cb; |
disabled_cb_ = disabled_cb; |
error_cb_ = error_cb; |
+ scoped_ptr<AudioDecoderList> decoder_list(new AudioDecoderList(decoders)); |
+ InitializeNextDecoder(stream, decoder_list.Pass()); |
+} |
+ |
+void AudioRendererImpl::InitializeNextDecoder( |
+ const scoped_refptr<DemuxerStream>& demuxer_stream, |
+ scoped_ptr<AudioDecoderList> decoders) { |
+ lock_.AssertAcquired(); |
+ DCHECK(!decoders->empty()); |
+ |
+ scoped_refptr<AudioDecoder> decoder = decoders->front(); |
+ decoders->pop_front(); |
+ |
+ DCHECK(decoder); |
+ decoder_ = decoder; |
+ |
+ base::AutoUnlock auto_unlock(lock_); |
+ decoder->Initialize( |
+ demuxer_stream, |
+ base::Bind(&AudioRendererImpl::OnDecoderInitDone, this, |
+ demuxer_stream, |
+ base::Passed(&decoders)), |
+ statistics_cb_); |
+} |
+ |
+void AudioRendererImpl::OnDecoderInitDone( |
+ const scoped_refptr<DemuxerStream>& demuxer_stream, |
+ scoped_ptr<AudioDecoderList> decoders, |
+ PipelineStatus status) { |
+ base::AutoLock auto_lock(lock_); |
+ |
+ if (state_ == kStopped) { |
+ DCHECK(stopped_); |
+ return; |
+ } |
+ |
+ if (!decoders->empty() && status == DECODER_ERROR_NOT_SUPPORTED) { |
+ InitializeNextDecoder(demuxer_stream, decoders.Pass()); |
+ return; |
+ } |
+ |
+ if (status != PIPELINE_OK) { |
+ base::ResetAndReturn(&init_cb_).Run(status); |
+ return; |
+ } |
+ |
// Create a callback so our algorithm can request more reads. |
base::Closure cb = base::Bind(&AudioRendererImpl::ScheduleRead_Locked, this); |
@@ -170,7 +228,7 @@ void AudioRendererImpl::Initialize(const scoped_refptr<AudioDecoder>& decoder, |
bool config_ok = algorithm_->ValidateConfig(channels, sample_rate, |
bits_per_channel); |
if (!config_ok || is_initialized_) { |
- init_cb.Run(PIPELINE_ERROR_INITIALIZATION_FAILED); |
+ base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); |
return; |
} |
@@ -197,7 +255,7 @@ void AudioRendererImpl::Initialize(const scoped_refptr<AudioDecoder>& decoder, |
// Finally, execute the start callback. |
state_ = kPaused; |
- init_cb.Run(PIPELINE_OK); |
+ base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
} |
void AudioRendererImpl::ResumeAfterUnderflow(bool buffer_more_audio) { |