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: |