| Index: media/filters/audio_renderer_impl.cc
|
| diff --git a/media/filters/audio_renderer_impl.cc b/media/filters/audio_renderer_impl.cc
|
| index e189c6134ceabe703aa4617bfbacdbdfb01fe4c7..48da818bc748cf89376396d292bdf78b6173f31c 100644
|
| --- a/media/filters/audio_renderer_impl.cc
|
| +++ b/media/filters/audio_renderer_impl.cc
|
| @@ -54,6 +54,7 @@ AudioRendererImpl::AudioRendererImpl(
|
| hardware_config_(hardware_config),
|
| now_cb_(base::Bind(&base::TimeTicks::Now)),
|
| state_(kUninitialized),
|
| + rendering_(false),
|
| sink_playing_(false),
|
| pending_read_(false),
|
| received_end_of_stream_(false),
|
| @@ -73,65 +74,72 @@ AudioRendererImpl::~AudioRendererImpl() {
|
| DCHECK(!algorithm_.get());
|
| }
|
|
|
| -void AudioRendererImpl::Play() {
|
| +void AudioRendererImpl::StartRendering() {
|
| + DVLOG(1) << __FUNCTION__;
|
| DCHECK(task_runner_->BelongsToCurrentThread());
|
| + DCHECK(!rendering_);
|
| + rendering_ = true;
|
|
|
| base::AutoLock auto_lock(lock_);
|
| - DCHECK_EQ(state_, kPaused);
|
| - ChangeState_Locked(kPlaying);
|
| - earliest_end_time_ = now_cb_.Run();
|
| -
|
| - if (algorithm_->playback_rate() != 0)
|
| - DoPlay_Locked();
|
| - else
|
| + // Wait for an eventual call to SetPlaybackRate() to start rendering.
|
| + if (algorithm_->playback_rate() == 0) {
|
| DCHECK(!sink_playing_);
|
| + return;
|
| + }
|
| +
|
| + StartRendering_Locked();
|
| }
|
|
|
| -void AudioRendererImpl::DoPlay_Locked() {
|
| +void AudioRendererImpl::StartRendering_Locked() {
|
| + DVLOG(1) << __FUNCTION__;
|
| DCHECK(task_runner_->BelongsToCurrentThread());
|
| + DCHECK(state_ == kPlaying || state_ == kRebuffering || state_ == kUnderflow)
|
| + << "state_=" << state_;
|
| + DCHECK(!sink_playing_);
|
| + DCHECK_NE(algorithm_->playback_rate(), 0);
|
| lock_.AssertAcquired();
|
| - earliest_end_time_ = now_cb_.Run();
|
|
|
| - if ((state_ == kPlaying || state_ == kRebuffering || state_ == kUnderflow) &&
|
| - !sink_playing_) {
|
| - {
|
| - base::AutoUnlock auto_unlock(lock_);
|
| - sink_->Play();
|
| - }
|
| + earliest_end_time_ = now_cb_.Run();
|
| + sink_playing_ = true;
|
|
|
| - sink_playing_ = true;
|
| - }
|
| + base::AutoUnlock auto_unlock(lock_);
|
| + sink_->Play();
|
| }
|
|
|
| -void AudioRendererImpl::Pause() {
|
| +void AudioRendererImpl::StopRendering() {
|
| + DVLOG(1) << __FUNCTION__;
|
| DCHECK(task_runner_->BelongsToCurrentThread());
|
| + DCHECK(rendering_);
|
| + rendering_ = false;
|
|
|
| base::AutoLock auto_lock(lock_);
|
| - DCHECK(state_ == kPlaying || state_ == kUnderflow ||
|
| - state_ == kRebuffering) << "state_ == " << state_;
|
| - ChangeState_Locked(kPaused);
|
| + // Rendering should have already been stopped with a zero playback rate.
|
| + if (algorithm_->playback_rate() == 0) {
|
| + DCHECK(!sink_playing_);
|
| + return;
|
| + }
|
|
|
| - DoPause_Locked();
|
| + StopRendering_Locked();
|
| }
|
|
|
| -void AudioRendererImpl::DoPause_Locked() {
|
| +void AudioRendererImpl::StopRendering_Locked() {
|
| DCHECK(task_runner_->BelongsToCurrentThread());
|
| + DCHECK(state_ == kPlaying || state_ == kRebuffering || state_ == kUnderflow)
|
| + << "state_=" << state_;
|
| + DCHECK(sink_playing_);
|
| lock_.AssertAcquired();
|
|
|
| - if (sink_playing_) {
|
| - {
|
| - base::AutoUnlock auto_unlock(lock_);
|
| - sink_->Pause();
|
| - }
|
| - sink_playing_ = false;
|
| - }
|
| + sink_playing_ = false;
|
| +
|
| + base::AutoUnlock auto_unlock(lock_);
|
| + sink_->Pause();
|
| }
|
|
|
| void AudioRendererImpl::Flush(const base::Closure& callback) {
|
| DCHECK(task_runner_->BelongsToCurrentThread());
|
|
|
| base::AutoLock auto_lock(lock_);
|
| - DCHECK_EQ(state_, kPaused);
|
| + DCHECK_EQ(state_, kPlaying);
|
| DCHECK(flush_cb_.is_null());
|
|
|
| flush_cb_ = callback;
|
| @@ -141,6 +149,7 @@ void AudioRendererImpl::Flush(const base::Closure& callback) {
|
| return;
|
| }
|
|
|
| + ChangeState_Locked(kFlushed);
|
| DoFlush_Locked();
|
| }
|
|
|
| @@ -149,7 +158,7 @@ void AudioRendererImpl::DoFlush_Locked() {
|
| lock_.AssertAcquired();
|
|
|
| DCHECK(!pending_read_);
|
| - DCHECK_EQ(state_, kPaused);
|
| + DCHECK_EQ(state_, kFlushed);
|
|
|
| audio_buffer_stream_.Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone,
|
| weak_factory_.GetWeakPtr()));
|
| @@ -162,7 +171,7 @@ void AudioRendererImpl::ResetDecoderDone() {
|
| if (state_ == kStopped)
|
| return;
|
|
|
| - DCHECK_EQ(state_, kPaused);
|
| + DCHECK_EQ(state_, kFlushed);
|
| DCHECK(!flush_cb_.is_null());
|
|
|
| audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate()));
|
| @@ -215,7 +224,7 @@ void AudioRendererImpl::Preroll(base::TimeDelta time,
|
|
|
| base::AutoLock auto_lock(lock_);
|
| DCHECK(!sink_playing_);
|
| - DCHECK_EQ(state_, kPaused);
|
| + DCHECK_EQ(state_, kFlushed);
|
| DCHECK(!pending_read_) << "Pending read must complete before seeking";
|
| DCHECK(preroll_cb_.is_null());
|
|
|
| @@ -321,7 +330,7 @@ void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) {
|
| algorithm_.reset(new AudioRendererAlgorithm());
|
| algorithm_->Initialize(0, audio_parameters_);
|
|
|
| - ChangeState_Locked(kPaused);
|
| + ChangeState_Locked(kFlushed);
|
|
|
| HistogramRendererEvent(INITIALIZED);
|
|
|
| @@ -365,7 +374,7 @@ void AudioRendererImpl::SetVolume(float volume) {
|
| void AudioRendererImpl::DecodedAudioReady(
|
| AudioBufferStream::Status status,
|
| const scoped_refptr<AudioBuffer>& buffer) {
|
| - DVLOG(1) << __FUNCTION__ << "(" << status << ")";
|
| + DVLOG(2) << __FUNCTION__ << "(" << status << ")";
|
| DCHECK(task_runner_->BelongsToCurrentThread());
|
|
|
| base::AutoLock auto_lock(lock_);
|
| @@ -389,7 +398,7 @@ void AudioRendererImpl::DecodedAudioReady(
|
| DCHECK(buffer.get());
|
|
|
| if (state_ == kFlushing) {
|
| - ChangeState_Locked(kPaused);
|
| + ChangeState_Locked(kFlushed);
|
| DoFlush_Locked();
|
| return;
|
| }
|
| @@ -463,14 +472,14 @@ bool AudioRendererImpl::HandleSplicerBuffer(
|
| NOTREACHED();
|
| return false;
|
|
|
| - case kPaused:
|
| + case kFlushed:
|
| DCHECK(!pending_read_);
|
| return false;
|
|
|
| case kPrerolling:
|
| if (!buffer->end_of_stream() && !algorithm_->IsQueueFull())
|
| return true;
|
| - ChangeState_Locked(kPaused);
|
| + ChangeState_Locked(kPlaying);
|
| base::ResetAndReturn(&preroll_cb_).Run(PIPELINE_OK);
|
| return false;
|
|
|
| @@ -513,7 +522,7 @@ bool AudioRendererImpl::CanRead_Locked() {
|
| switch (state_) {
|
| case kUninitialized:
|
| case kInitializing:
|
| - case kPaused:
|
| + case kFlushed:
|
| case kFlushing:
|
| case kStopped:
|
| return false;
|
| @@ -541,12 +550,20 @@ void AudioRendererImpl::SetPlaybackRate(float playback_rate) {
|
| // Play: current_playback_rate == 0 && playback_rate != 0
|
| // Pause: current_playback_rate != 0 && playback_rate == 0
|
| float current_playback_rate = algorithm_->playback_rate();
|
| - if (current_playback_rate == 0 && playback_rate != 0)
|
| - DoPlay_Locked();
|
| - else if (current_playback_rate != 0 && playback_rate == 0)
|
| - DoPause_Locked();
|
| -
|
| algorithm_->SetPlaybackRate(playback_rate);
|
| +
|
| + if (!rendering_)
|
| + return;
|
| +
|
| + if (current_playback_rate == 0 && playback_rate != 0) {
|
| + StartRendering_Locked();
|
| + return;
|
| + }
|
| +
|
| + if (current_playback_rate != 0 && playback_rate == 0) {
|
| + StopRendering_Locked();
|
| + return;
|
| + }
|
| }
|
|
|
| bool AudioRendererImpl::IsBeforePrerollTime(
|
| @@ -697,12 +714,8 @@ void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error) {
|
| case kInitializing:
|
| NOTREACHED();
|
| return;
|
| - case kPaused:
|
| - if (status != PIPELINE_OK)
|
| - error_cb_.Run(status);
|
| - return;
|
| case kFlushing:
|
| - ChangeState_Locked(kPaused);
|
| + ChangeState_Locked(kFlushed);
|
|
|
| if (status == PIPELINE_OK) {
|
| DoFlush_Locked();
|
| @@ -715,9 +728,10 @@ void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error) {
|
| case kPrerolling:
|
| // This is a signal for abort if it's not an error.
|
| preroll_aborted_ = !is_decode_error;
|
| - ChangeState_Locked(kPaused);
|
| + ChangeState_Locked(kPlaying);
|
| base::ResetAndReturn(&preroll_cb_).Run(status);
|
| return;
|
| + case kFlushed:
|
| case kPlaying:
|
| case kUnderflow:
|
| case kRebuffering:
|
|
|