| Index: media/filters/audio_renderer_impl.cc
|
| diff --git a/media/filters/audio_renderer_impl.cc b/media/filters/audio_renderer_impl.cc
|
| index 2805ed05837293fa6ea1c6f245393f8f8a35bf8f..003881b88aa00b20d380490da6ed816c867c4870 100644
|
| --- a/media/filters/audio_renderer_impl.cc
|
| +++ b/media/filters/audio_renderer_impl.cc
|
| @@ -13,7 +13,9 @@
|
| #include "base/callback_helpers.h"
|
| #include "base/command_line.h"
|
| #include "base/logging.h"
|
| +#include "base/message_loop_proxy.h"
|
| #include "media/audio/audio_util.h"
|
| +#include "media/base/bind_to_loop.h"
|
| #include "media/base/demuxer_stream.h"
|
| #include "media/base/media_switches.h"
|
|
|
| @@ -31,9 +33,12 @@ AudioRendererImpl::AudioRendererImpl(media::AudioRendererSink* sink)
|
| sink_(sink),
|
| underflow_disabled_(false),
|
| preroll_aborted_(false) {
|
| + // We're created on the render thread, but this thread checker is for another.
|
| + pipeline_thread_checker_.DetachFromThread();
|
| }
|
|
|
| void AudioRendererImpl::Play(const base::Closure& callback) {
|
| + DCHECK(pipeline_thread_checker_.CalledOnValidThread());
|
| {
|
| base::AutoLock auto_lock(lock_);
|
| DCHECK_EQ(kPaused, state_);
|
| @@ -52,11 +57,13 @@ void AudioRendererImpl::Play(const base::Closure& callback) {
|
| }
|
|
|
| void AudioRendererImpl::DoPlay() {
|
| + DCHECK(pipeline_thread_checker_.CalledOnValidThread());
|
| earliest_end_time_ = base::Time::Now();
|
| sink_->Play();
|
| }
|
|
|
| void AudioRendererImpl::Pause(const base::Closure& callback) {
|
| + DCHECK(pipeline_thread_checker_.CalledOnValidThread());
|
| {
|
| base::AutoLock auto_lock(lock_);
|
| DCHECK(state_ == kPlaying || state_ == kUnderflow ||
|
| @@ -76,23 +83,26 @@ void AudioRendererImpl::Pause(const base::Closure& callback) {
|
| }
|
|
|
| void AudioRendererImpl::DoPause() {
|
| + DCHECK(pipeline_thread_checker_.CalledOnValidThread());
|
| sink_->Pause(false);
|
| }
|
|
|
| void AudioRendererImpl::Flush(const base::Closure& callback) {
|
| + DCHECK(pipeline_thread_checker_.CalledOnValidThread());
|
| decoder_->Reset(callback);
|
| }
|
|
|
| void AudioRendererImpl::Stop(const base::Closure& callback) {
|
| + DCHECK(pipeline_thread_checker_.CalledOnValidThread());
|
| DCHECK(!callback.is_null());
|
|
|
| + if (!stopped_) {
|
| + sink_->Stop();
|
| + stopped_ = true;
|
| + }
|
| +
|
| {
|
| base::AutoLock auto_lock(lock_);
|
| - if (!stopped_) {
|
| - sink_->Stop();
|
| - stopped_ = true;
|
| - }
|
| -
|
| state_ = kStopped;
|
| algorithm_.reset(NULL);
|
| init_cb_.Reset();
|
| @@ -105,28 +115,31 @@ void AudioRendererImpl::Stop(const base::Closure& callback) {
|
|
|
| void AudioRendererImpl::Preroll(base::TimeDelta time,
|
| const PipelineStatusCB& cb) {
|
| - base::AutoLock auto_lock(lock_);
|
| - DCHECK_EQ(kPaused, state_);
|
| - DCHECK(!pending_read_) << "Pending read must complete before seeking";
|
| - DCHECK(pause_cb_.is_null());
|
| - DCHECK(preroll_cb_.is_null());
|
| - state_ = kPrerolling;
|
| - preroll_cb_ = cb;
|
| - preroll_timestamp_ = time;
|
| -
|
| - // Throw away everything and schedule our reads.
|
| - audio_time_buffered_ = kNoTimestamp();
|
| - current_time_ = kNoTimestamp();
|
| - received_end_of_stream_ = false;
|
| - rendered_end_of_stream_ = false;
|
| - preroll_aborted_ = false;
|
| -
|
| - // |algorithm_| will request more reads.
|
| - algorithm_->FlushBuffers();
|
| -
|
| + DCHECK(pipeline_thread_checker_.CalledOnValidThread());
|
| if (stopped_)
|
| return;
|
|
|
| + {
|
| + base::AutoLock auto_lock(lock_);
|
| + DCHECK_EQ(kPaused, state_);
|
| + DCHECK(!pending_read_) << "Pending read must complete before seeking";
|
| + DCHECK(pause_cb_.is_null());
|
| + DCHECK(preroll_cb_.is_null());
|
| + state_ = kPrerolling;
|
| + preroll_cb_ = cb;
|
| + preroll_timestamp_ = time;
|
| +
|
| + // Throw away everything and schedule our reads.
|
| + audio_time_buffered_ = kNoTimestamp();
|
| + current_time_ = kNoTimestamp();
|
| + received_end_of_stream_ = false;
|
| + rendered_end_of_stream_ = false;
|
| + preroll_aborted_ = false;
|
| +
|
| + // |algorithm_| will request more reads.
|
| + algorithm_->FlushBuffers();
|
| + }
|
| +
|
| // Pause and flush the stream when we preroll to a new location.
|
| earliest_end_time_ = base::Time::Now();
|
| sink_->Pause(true);
|
| @@ -141,7 +154,7 @@ void AudioRendererImpl::Initialize(const scoped_refptr<DemuxerStream>& stream,
|
| const base::Closure& ended_cb,
|
| const base::Closure& disabled_cb,
|
| const PipelineStatusCB& error_cb) {
|
| - base::AutoLock auto_lock(lock_);
|
| + DCHECK(pipeline_thread_checker_.CalledOnValidThread());
|
| DCHECK(stream);
|
| DCHECK(!decoders.empty());
|
| DCHECK_EQ(stream->type(), DemuxerStream::AUDIO);
|
| @@ -169,7 +182,7 @@ void AudioRendererImpl::Initialize(const scoped_refptr<DemuxerStream>& stream,
|
| void AudioRendererImpl::InitializeNextDecoder(
|
| const scoped_refptr<DemuxerStream>& demuxer_stream,
|
| scoped_ptr<AudioDecoderList> decoders) {
|
| - lock_.AssertAcquired();
|
| + DCHECK(pipeline_thread_checker_.CalledOnValidThread());
|
| DCHECK(!decoders->empty());
|
|
|
| scoped_refptr<AudioDecoder> decoder = decoders->front();
|
| @@ -177,13 +190,10 @@ void AudioRendererImpl::InitializeNextDecoder(
|
|
|
| DCHECK(decoder);
|
| decoder_ = decoder;
|
| -
|
| - base::AutoUnlock auto_unlock(lock_);
|
| decoder->Initialize(
|
| - demuxer_stream,
|
| - base::Bind(&AudioRendererImpl::OnDecoderInitDone, this,
|
| - demuxer_stream,
|
| - base::Passed(&decoders)),
|
| + demuxer_stream, BindToLoop(base::MessageLoopProxy::current(), base::Bind(
|
| + &AudioRendererImpl::OnDecoderInitDone, this, demuxer_stream,
|
| + base::Passed(&decoders))),
|
| statistics_cb_);
|
| }
|
|
|
| @@ -191,7 +201,7 @@ void AudioRendererImpl::OnDecoderInitDone(
|
| const scoped_refptr<DemuxerStream>& demuxer_stream,
|
| scoped_ptr<AudioDecoderList> decoders,
|
| PipelineStatus status) {
|
| - base::AutoLock auto_lock(lock_);
|
| + DCHECK(pipeline_thread_checker_.CalledOnValidThread());
|
|
|
| if (state_ == kStopped) {
|
| DCHECK(stopped_);
|
| @@ -267,14 +277,16 @@ void AudioRendererImpl::OnDecoderInitDone(
|
| audio_parameters_ = AudioParameters(
|
| format, channel_layout, sample_rate, bits_per_channel, buffer_size);
|
|
|
| + state_ = kPaused;
|
| +
|
| sink_->Initialize(audio_parameters_, this);
|
| sink_->Start();
|
|
|
| - state_ = kPaused;
|
| base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
|
| }
|
|
|
| void AudioRendererImpl::ResumeAfterUnderflow(bool buffer_more_audio) {
|
| + DCHECK(pipeline_thread_checker_.CalledOnValidThread());
|
| base::AutoLock auto_lock(lock_);
|
| if (state_ == kUnderflow) {
|
| // The "&& preroll_aborted_" is a hack. If preroll is aborted, then we
|
| @@ -291,6 +303,7 @@ void AudioRendererImpl::ResumeAfterUnderflow(bool buffer_more_audio) {
|
| }
|
|
|
| void AudioRendererImpl::SetVolume(float volume) {
|
| + DCHECK(pipeline_thread_checker_.CalledOnValidThread());
|
| if (stopped_)
|
| return;
|
| sink_->SetVolume(volume);
|
| @@ -376,6 +389,7 @@ void AudioRendererImpl::ScheduleRead_Locked() {
|
| }
|
|
|
| void AudioRendererImpl::SetPlaybackRate(float playback_rate) {
|
| + DCHECK(pipeline_thread_checker_.CalledOnValidThread());
|
| DCHECK_LE(0.0f, playback_rate);
|
|
|
| if (!stopped_) {
|
|
|