Chromium Code Reviews| Index: media/filters/audio_renderer_impl.cc |
| diff --git a/media/filters/audio_renderer_impl.cc b/media/filters/audio_renderer_impl.cc |
| index 9ade30dc0dc6fdbba1dae9d7e8cbd041aee6638e..af507d0cbf80aa13db72d82a45a26550f5edfcc3 100644 |
| --- a/media/filters/audio_renderer_impl.cc |
| +++ b/media/filters/audio_renderer_impl.cc |
| @@ -147,8 +147,8 @@ void AudioRendererImpl::DoFlush_Locked() { |
| DCHECK_EQ(state_, kPaused); |
| if (decrypting_demuxer_stream_) { |
| - decrypting_demuxer_stream_->Reset(BindToCurrentLoop( |
| - base::Bind(&AudioRendererImpl::ResetDecoder, weak_this_))); |
| + decrypting_demuxer_stream_->Reset( |
| + base::Bind(&AudioRendererImpl::ResetDecoder, weak_this_)); |
| return; |
| } |
| @@ -157,54 +157,72 @@ void AudioRendererImpl::DoFlush_Locked() { |
| void AudioRendererImpl::ResetDecoder() { |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| - decoder_->Reset(BindToCurrentLoop( |
| - base::Bind(&AudioRendererImpl::ResetDecoderDone, weak_this_))); |
| + decoder_->Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone, weak_this_)); |
| } |
| void AudioRendererImpl::ResetDecoderDone() { |
| - base::AutoLock auto_lock(lock_); |
| - if (state_ == kStopped) |
| - return; |
| + DCHECK(task_runner_->BelongsToCurrentThread()); |
| + { |
| + base::AutoLock auto_lock(lock_); |
| + if (state_ == kStopped) |
| + return; |
| - DCHECK_EQ(state_, kPaused); |
| - DCHECK(!flush_cb_.is_null()); |
| + DCHECK_EQ(state_, kPaused); |
| + DCHECK(!flush_cb_.is_null()); |
| - audio_time_buffered_ = kNoTimestamp(); |
| - current_time_ = kNoTimestamp(); |
| - received_end_of_stream_ = false; |
| - rendered_end_of_stream_ = false; |
| - preroll_aborted_ = false; |
| - |
| - earliest_end_time_ = now_cb_.Run(); |
| - splicer_->Reset(); |
| - algorithm_->FlushBuffers(); |
| + audio_time_buffered_ = kNoTimestamp(); |
| + current_time_ = kNoTimestamp(); |
| + received_end_of_stream_ = false; |
| + rendered_end_of_stream_ = false; |
| + preroll_aborted_ = false; |
| + earliest_end_time_ = now_cb_.Run(); |
| + splicer_->Reset(); |
| + algorithm_->FlushBuffers(); |
| + } |
| base::ResetAndReturn(&flush_cb_).Run(); |
| } |
| void AudioRendererImpl::Stop(const base::Closure& callback) { |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| DCHECK(!callback.is_null()); |
| + DCHECK(stop_cb_.is_null()); |
| + |
| + stop_cb_ = callback; |
| // TODO(scherkus): Consider invalidating |weak_factory_| and replacing |
| // task-running guards that check |state_| with DCHECK(). |
| - if (sink_) { |
| - sink_->Stop(); |
| - sink_ = NULL; |
| - } |
| - |
| { |
| base::AutoLock auto_lock(lock_); |
| + if (state_ == kInitializing) { |
| + decoder_selector_->Abort(); |
| + return; |
| + } |
| + |
| + if (state_ == kStopped) { |
| + task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); |
| + return; |
| + } |
| + |
| ChangeState_Locked(kStopped); |
| - algorithm_.reset(NULL); |
| - init_cb_.Reset(); |
| + algorithm_.reset(); |
| underflow_cb_.Reset(); |
| time_cb_.Reset(); |
| flush_cb_.Reset(); |
| } |
| - callback.Run(); |
| + if (sink_) { |
| + sink_->Stop(); |
| + sink_ = NULL; |
| + } |
| + |
| + if (decoder_) { |
| + decoder_->Stop(base::ResetAndReturn(&stop_cb_)); |
| + return; |
| + } |
| + |
| + task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_)); |
| } |
| void AudioRendererImpl::Preroll(base::TimeDelta time, |
| @@ -245,6 +263,8 @@ void AudioRendererImpl::Initialize(DemuxerStream* stream, |
| DCHECK_EQ(kUninitialized, state_); |
| DCHECK(sink_); |
| + state_ = kInitializing; |
| + |
| weak_this_ = weak_factory_.GetWeakPtr(); |
| init_cb_ = init_cb; |
| statistics_cb_ = statistics_cb; |
| @@ -265,58 +285,65 @@ void AudioRendererImpl::OnDecoderSelected( |
| scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| - base::AutoLock auto_lock(lock_); |
| scoped_ptr<AudioDecoderSelector> deleter(decoder_selector_.Pass()); |
| - if (state_ == kStopped) { |
| - DCHECK(!sink_); |
| - return; |
| - } |
| - |
| if (!decoder) { |
| - base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
| + { |
| + base::AutoLock auto_lock(lock_); |
| + ChangeState_Locked(kUninitialized); |
| + } |
| + // Stop() called during initialization. |
| + if (!stop_cb_.is_null()) { |
| + base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); |
| + Stop(base::ResetAndReturn(&stop_cb_)); |
| + } else { |
| + base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
| + } |
| return; |
| } |
| + { |
|
DaleCurtis
2014/01/22 19:06:17
No need to scope since you're holding it for the r
rileya (GONE FROM CHROMIUM)
2014/01/22 19:18:59
Right, makes sense, for some reason I was thinking
|
| + base::AutoLock auto_lock(lock_); |
| + decoder_ = decoder.Pass(); |
| + decrypting_demuxer_stream_ = decrypting_demuxer_stream.Pass(); |
| + |
| + int sample_rate = decoder_->samples_per_second(); |
| + |
| + // The actual buffer size is controlled via the size of the AudioBus |
| + // provided to Render(), so just choose something reasonable here for looks. |
| + int buffer_size = decoder_->samples_per_second() / 100; |
| + audio_parameters_ = AudioParameters( |
| + AudioParameters::AUDIO_PCM_LOW_LATENCY, decoder_->channel_layout(), |
| + sample_rate, decoder_->bits_per_channel(), buffer_size); |
| + if (!audio_parameters_.IsValid()) { |
| + ChangeState_Locked(kUninitialized); |
| + base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); |
| + return; |
| + } |
| - decoder_ = decoder.Pass(); |
| - decrypting_demuxer_stream_ = decrypting_demuxer_stream.Pass(); |
| - |
| - int sample_rate = decoder_->samples_per_second(); |
| + splicer_.reset(new AudioSplicer(sample_rate)); |
| - // The actual buffer size is controlled via the size of the AudioBus provided |
| - // to Render(), so just choose something reasonable here for looks. |
| - int buffer_size = decoder_->samples_per_second() / 100; |
| - audio_parameters_ = AudioParameters( |
| - AudioParameters::AUDIO_PCM_LOW_LATENCY, decoder_->channel_layout(), |
| - sample_rate, decoder_->bits_per_channel(), buffer_size); |
| - if (!audio_parameters_.IsValid()) { |
| - base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); |
| - return; |
| - } |
| + // We're all good! Continue initializing the rest of the audio renderer |
| + // based on the decoder format. |
| + algorithm_.reset(new AudioRendererAlgorithm()); |
| + algorithm_->Initialize(0, audio_parameters_); |
| - splicer_.reset(new AudioSplicer(sample_rate)); |
| + ChangeState_Locked(kPaused); |
| - // We're all good! Continue initializing the rest of the audio renderer based |
| - // on the decoder format. |
| - algorithm_.reset(new AudioRendererAlgorithm()); |
| - algorithm_->Initialize(0, audio_parameters_); |
| + HistogramRendererEvent(INITIALIZED); |
| - ChangeState_Locked(kPaused); |
| + { |
| + base::AutoUnlock auto_unlock(lock_); |
| + sink_->Initialize(audio_parameters_, weak_this_.get()); |
| + sink_->Start(); |
| - HistogramRendererEvent(INITIALIZED); |
| + // Some sinks play on start... |
| + sink_->Pause(); |
| + } |
| - { |
| - base::AutoUnlock auto_unlock(lock_); |
| - sink_->Initialize(audio_parameters_, weak_this_.get()); |
| - sink_->Start(); |
| + DCHECK(!sink_playing_); |
| - // Some sinks play on start... |
| - sink_->Pause(); |
| + base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
| } |
| - |
| - DCHECK(!sink_playing_); |
| - |
| - base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
| } |
| void AudioRendererImpl::ResumeAfterUnderflow() { |
| @@ -426,6 +453,7 @@ bool AudioRendererImpl::HandleSplicerBuffer( |
| switch (state_) { |
| case kUninitialized: |
| + case kInitializing: |
| case kFlushing: |
| NOTREACHED(); |
| return false; |
| @@ -478,6 +506,7 @@ bool AudioRendererImpl::CanRead_Locked() { |
| switch (state_) { |
| case kUninitialized: |
| + case kInitializing: |
| case kPaused: |
| case kFlushing: |
| case kStopped: |
| @@ -667,6 +696,7 @@ void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error) { |
| PipelineStatus status = is_decode_error ? PIPELINE_ERROR_DECODE : PIPELINE_OK; |
| switch (state_) { |
| case kUninitialized: |
| + case kInitializing: |
| NOTREACHED(); |
| return; |
| case kPaused: |