diff options
-rw-r--r-- | media/audio/clockless_audio_sink.cc | 3 | ||||
-rw-r--r-- | media/base/audio_renderer.h | 6 | ||||
-rw-r--r-- | media/base/mock_filters.h | 1 | ||||
-rw-r--r-- | media/base/pipeline.cc | 10 | ||||
-rw-r--r-- | media/base/pipeline_unittest.cc | 11 | ||||
-rw-r--r-- | media/filters/audio_renderer_impl.cc | 57 | ||||
-rw-r--r-- | media/filters/audio_renderer_impl.h | 4 | ||||
-rw-r--r-- | media/filters/audio_renderer_impl_unittest.cc | 66 |
8 files changed, 36 insertions, 122 deletions
diff --git a/media/audio/clockless_audio_sink.cc b/media/audio/clockless_audio_sink.cc index 89f43bf..1c98574 100644 --- a/media/audio/clockless_audio_sink.cc +++ b/media/audio/clockless_audio_sink.cc @@ -78,7 +78,8 @@ void ClocklessAudioSink::Start() { } void ClocklessAudioSink::Stop() { - Pause(); + if (initialized_) + Pause(); } void ClocklessAudioSink::Play() { diff --git a/media/base/audio_renderer.h b/media/base/audio_renderer.h index dc202be..3e7131c 100644 --- a/media/base/audio_renderer.h +++ b/media/base/audio_renderer.h @@ -23,6 +23,8 @@ class MEDIA_EXPORT AudioRenderer { typedef base::Callback<void(base::TimeDelta, base::TimeDelta)> TimeCB; AudioRenderer(); + + // Stop all operations and fire all pending callbacks. virtual ~AudioRenderer(); // Initialize an AudioRenderer with |stream|, executing |init_cb| upon @@ -60,10 +62,6 @@ class MEDIA_EXPORT AudioRenderer { // Only valid to call after a successful Initialize() or Flush(). virtual void StartPlaying() = 0; - // Stop all operations in preparation for being deleted, executing |callback| - // when complete. - virtual void Stop(const base::Closure& callback) = 0; - // Sets the output volume. virtual void SetVolume(float volume) = 0; diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h index 06a6c1f..dd66e2f 100644 --- a/media/base/mock_filters.h +++ b/media/base/mock_filters.h @@ -149,7 +149,6 @@ class MockAudioRenderer : public AudioRenderer { const PipelineStatusCB& error_cb)); MOCK_METHOD0(GetTimeSource, TimeSource*()); MOCK_METHOD1(Flush, void(const base::Closure& callback)); - MOCK_METHOD1(Stop, void(const base::Closure& callback)); MOCK_METHOD0(StartPlaying, void()); MOCK_METHOD1(SetVolume, void(float volume)); diff --git a/media/base/pipeline.cc b/media/base/pipeline.cc index efe91f6..f238d66 100644 --- a/media/base/pipeline.cc +++ b/media/base/pipeline.cc @@ -494,6 +494,9 @@ void Pipeline::DoSeek( void Pipeline::DoStop(const PipelineStatusCB& done_cb) { DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(!pending_callbacks_.get()); + + audio_renderer_.reset(); + SerialRunner::Queue bound_fns; if (demuxer_) { @@ -501,11 +504,6 @@ void Pipeline::DoStop(const PipelineStatusCB& done_cb) { &Demuxer::Stop, base::Unretained(demuxer_))); } - if (audio_renderer_) { - bound_fns.Push(base::Bind( - &AudioRenderer::Stop, base::Unretained(audio_renderer_.get()))); - } - if (video_renderer_) { bound_fns.Push(base::Bind( &VideoRenderer::Stop, base::Unretained(video_renderer_.get()))); @@ -522,6 +520,7 @@ void Pipeline::DoStop(const PipelineStatusCB& done_cb) { void Pipeline::OnStopCompleted(PipelineStatus status) { DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK_EQ(state_, kStopping); + DCHECK(!audio_renderer_); { base::AutoLock l(lock_); running_ = false; @@ -530,7 +529,6 @@ void Pipeline::OnStopCompleted(PipelineStatus status) { SetState(kStopped); pending_callbacks_.reset(); filter_collection_.reset(); - audio_renderer_.reset(); video_renderer_.reset(); text_renderer_.reset(); demuxer_ = NULL; diff --git a/media/base/pipeline_unittest.cc b/media/base/pipeline_unittest.cc index 6fdb4b3a..42db189 100644 --- a/media/base/pipeline_unittest.cc +++ b/media/base/pipeline_unittest.cc @@ -312,9 +312,6 @@ class PipelineTest : public ::testing::Test { if (demuxer_) EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>()); - if (audio_stream_) - EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>()); - if (video_stream_) EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>()); } @@ -687,8 +684,6 @@ TEST_F(PipelineTest, ErrorDuringSeek) { .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_, BUFFERING_HAVE_NOTHING), RunClosure<0>())); - EXPECT_CALL(*audio_renderer_, Stop(_)) - .WillOnce(RunClosure<0>()); EXPECT_CALL(*demuxer_, Seek(seek_time, _)) .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ)); @@ -743,8 +738,6 @@ TEST_F(PipelineTest, NoMessageDuringTearDownFromError) { .WillOnce(DoAll(SetBufferingState(&audio_buffering_state_cb_, BUFFERING_HAVE_NOTHING), RunClosure<0>())); - EXPECT_CALL(*audio_renderer_, Stop(_)) - .WillOnce(RunClosure<0>()); EXPECT_CALL(*demuxer_, Seek(seek_time, _)) .WillOnce(RunCallback<1>(PIPELINE_ERROR_READ)); @@ -966,7 +959,6 @@ class PipelineTeardownTest : public PipelineTest { } EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>()); - EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>()); return status; } @@ -987,7 +979,6 @@ class PipelineTeardownTest : public PipelineTest { } EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>()); - EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>()); EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>()); return status; } @@ -1023,7 +1014,6 @@ class PipelineTeardownTest : public PipelineTest { PipelineStatus status = SetSeekExpectations(state, stop_or_error); EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>()); - EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>()); EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>()); EXPECT_CALL(callbacks_, OnSeek(status)); @@ -1094,7 +1084,6 @@ class PipelineTeardownTest : public PipelineTest { InSequence s; EXPECT_CALL(*demuxer_, Stop(_)).WillOnce(RunClosure<0>()); - EXPECT_CALL(*audio_renderer_, Stop(_)).WillOnce(RunClosure<0>()); EXPECT_CALL(*video_renderer_, Stop(_)).WillOnce(RunClosure<0>()); switch (stop_or_error) { diff --git a/media/filters/audio_renderer_impl.cc b/media/filters/audio_renderer_impl.cc index cfdf016..44536de 100644 --- a/media/filters/audio_renderer_impl.cc +++ b/media/filters/audio_renderer_impl.cc @@ -67,9 +67,15 @@ AudioRendererImpl::AudioRendererImpl( } AudioRendererImpl::~AudioRendererImpl() { - // Stop() should have been called and |algorithm_| should have been destroyed. - DCHECK(state_ == kUninitialized || state_ == kStopped); - DCHECK(!algorithm_.get()); + DVLOG(1) << __FUNCTION__; + DCHECK(task_runner_->BelongsToCurrentThread()); + + // If Render() is in progress, this call will wait for Render() to finish. + // After this call, the |sink_| will not call back into |this| anymore. + sink_->Stop(); + + if (!init_cb_.is_null()) + base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); } void AudioRendererImpl::StartTicking() { @@ -189,8 +195,6 @@ void AudioRendererImpl::ResetDecoderDone() { DCHECK(task_runner_->BelongsToCurrentThread()); { base::AutoLock auto_lock(lock_); - if (state_ == kStopped) - return; DCHECK_EQ(state_, kFlushed); DCHECK(!flush_cb_.is_null()); @@ -214,37 +218,6 @@ void AudioRendererImpl::ResetDecoderDone() { task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&flush_cb_)); } -void AudioRendererImpl::Stop(const base::Closure& callback) { - DVLOG(1) << __FUNCTION__; - DCHECK(task_runner_->BelongsToCurrentThread()); - DCHECK(!callback.is_null()); - - // TODO(scherkus): Consider invalidating |weak_factory_| and replacing - // task-running guards that check |state_| with DCHECK(). - - { - base::AutoLock auto_lock(lock_); - - if (state_ == kStopped) { - task_runner_->PostTask(FROM_HERE, callback); - return; - } - - ChangeState_Locked(kStopped); - algorithm_.reset(); - time_cb_.Reset(); - flush_cb_.Reset(); - } - - if (sink_) { - sink_->Stop(); - sink_ = NULL; - } - - audio_buffer_stream_.reset(); - task_runner_->PostTask(FROM_HERE, callback); -} - void AudioRendererImpl::StartPlaying() { DVLOG(1) << __FUNCTION__; DCHECK(task_runner_->BelongsToCurrentThread()); @@ -334,11 +307,6 @@ void AudioRendererImpl::OnAudioBufferStreamInitialized(bool success) { base::AutoLock auto_lock(lock_); - if (state_ == kStopped) { - base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); - return; - } - if (!success) { state_ = kUninitialized; base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); @@ -469,7 +437,7 @@ bool AudioRendererImpl::HandleSplicerBuffer_Locked( return true; } - if (state_ != kUninitialized && state_ != kStopped) + if (state_ != kUninitialized) algorithm_->EnqueueBuffer(buffer); } @@ -491,9 +459,6 @@ bool AudioRendererImpl::HandleSplicerBuffer_Locked( return false; } return true; - - case kStopped: - return false; } return false; } @@ -523,7 +488,6 @@ bool AudioRendererImpl::CanRead_Locked() { case kInitializing: case kFlushing: case kFlushed: - case kStopped: return false; case kPlaying: @@ -690,7 +654,6 @@ void AudioRendererImpl::HandleAbortedReadOrDecodeError(bool is_decode_error) { case kFlushed: case kPlaying: - case kStopped: if (status != PIPELINE_OK) error_cb_.Run(status); return; diff --git a/media/filters/audio_renderer_impl.h b/media/filters/audio_renderer_impl.h index 28d62ab..837dd73 100644 --- a/media/filters/audio_renderer_impl.h +++ b/media/filters/audio_renderer_impl.h @@ -84,7 +84,6 @@ class MEDIA_EXPORT AudioRendererImpl const PipelineStatusCB& error_cb) OVERRIDE; virtual TimeSource* GetTimeSource() OVERRIDE; virtual void Flush(const base::Closure& callback) OVERRIDE; - virtual void Stop(const base::Closure& callback) OVERRIDE; virtual void StartPlaying() OVERRIDE; virtual void SetVolume(float volume) OVERRIDE; @@ -113,8 +112,7 @@ class MEDIA_EXPORT AudioRendererImpl kInitializing, kFlushing, kFlushed, - kPlaying, - kStopped, + kPlaying }; // Callback from the audio decoder delivering decoded audio samples. diff --git a/media/filters/audio_renderer_impl_unittest.cc b/media/filters/audio_renderer_impl_unittest.cc index 5aae0af..54850c8 100644 --- a/media/filters/audio_renderer_impl_unittest.cc +++ b/media/filters/audio_renderer_impl_unittest.cc @@ -59,7 +59,6 @@ class AudioRendererImplTest : public ::testing::Test { // Give the decoder some non-garbage media properties. AudioRendererImplTest() : hardware_config_(AudioParameters(), AudioParameters()), - needs_stop_(true), demuxer_stream_(DemuxerStream::AUDIO), decoder_(new MockAudioDecoder()), last_time_update_(kNoTimestamp()), @@ -103,11 +102,6 @@ class AudioRendererImplTest : public ::testing::Test { virtual ~AudioRendererImplTest() { SCOPED_TRACE("~AudioRendererImplTest()"); - if (needs_stop_) { - WaitableMessageLoopEvent event; - renderer_->Stop(event.GetClosure()); - event.RunAndWait(); - } } void ExpectUnsupportedAudioDecoder() { @@ -161,38 +155,31 @@ class AudioRendererImplTest : public ::testing::Test { EXPECT_TRUE(decode_cb_.is_null()); } - void InitializeAndStop() { + void InitializeAndDestroy() { EXPECT_CALL(*decoder_, Initialize(_, _, _)) - .WillOnce(DoAll(SaveArg<2>(&output_cb_), - RunCallback<1>(PIPELINE_OK))); + .WillOnce(RunCallback<1>(PIPELINE_OK)); WaitableMessageLoopEvent event; InitializeRenderer(event.GetPipelineStatusCB()); - // Stop before we let the MessageLoop run, this simulates an interleaving - // in which we end up calling Stop() while the OnDecoderSelected callback - // is in flight. - renderer_->Stop(NewExpectedClosure()); + // Destroy the |renderer_| before we let the MessageLoop run, this simulates + // an interleaving in which we end up destroying the |renderer_| while the + // OnDecoderSelected callback is in flight. + renderer_.reset(); event.RunAndWaitForStatus(PIPELINE_ERROR_ABORT); - EXPECT_EQ(renderer_->state_, AudioRendererImpl::kStopped); } - void InitializeAndStopDuringDecoderInit() { + void InitializeAndDestroyDuringDecoderInit() { EXPECT_CALL(*decoder_, Initialize(_, _, _)) - .WillOnce(DoAll(SaveArg<2>(&output_cb_), - EnterPendingDecoderInitStateAction(this))); + .WillOnce(EnterPendingDecoderInitStateAction(this)); WaitableMessageLoopEvent event; InitializeRenderer(event.GetPipelineStatusCB()); - base::RunLoop().RunUntilIdle(); DCHECK(!init_decoder_cb_.is_null()); - renderer_->Stop(NewExpectedClosure()); - base::ResetAndReturn(&init_decoder_cb_).Run(PIPELINE_OK); - + renderer_.reset(); event.RunAndWaitForStatus(PIPELINE_ERROR_ABORT); - EXPECT_EQ(renderer_->state_, AudioRendererImpl::kStopped); } void EnterPendingDecoderInitState(PipelineStatusCB cb) { @@ -355,16 +342,9 @@ class AudioRendererImplTest : public ::testing::Test { scoped_refptr<FakeAudioRendererSink> sink_; AudioHardwareConfig hardware_config_; - // Whether or not the test needs the destructor to call Stop() on - // |renderer_| at destruction. - bool needs_stop_; - private: void DecodeDecoder(const scoped_refptr<DecoderBuffer>& buffer, const AudioDecoder::DecodeCB& decode_cb) { - // We shouldn't ever call Read() after Stop(): - EXPECT_TRUE(stop_decoder_cb_.is_null()); - // TODO(scherkus): Make this a DCHECK after threading semantics are fixed. if (base::MessageLoop::current() != &message_loop_) { message_loop_.PostTask(FROM_HERE, base::Bind( @@ -421,7 +401,6 @@ class AudioRendererImplTest : public ::testing::Test { // Run during DecodeDecoder() to unblock WaitForPendingRead(). base::Closure wait_for_pending_decode_cb_; - base::Closure stop_decoder_cb_; PipelineStatusCB init_decoder_cb_; base::TimeDelta last_time_update_; @@ -569,7 +548,7 @@ TEST_F(AudioRendererImplTest, PendingRead_Flush) { Preroll(1000, PIPELINE_OK); } -TEST_F(AudioRendererImplTest, PendingRead_Stop) { +TEST_F(AudioRendererImplTest, PendingRead_Destroy) { Initialize(); Preroll(); @@ -583,18 +562,10 @@ TEST_F(AudioRendererImplTest, PendingRead_Stop) { EXPECT_TRUE(IsReadPending()); - WaitableMessageLoopEvent stop_event; - renderer_->Stop(stop_event.GetClosure()); - needs_stop_ = false; - - SatisfyPendingRead(InputFrames(256)); - - stop_event.RunAndWait(); - - EXPECT_FALSE(IsReadPending()); + renderer_.reset(); } -TEST_F(AudioRendererImplTest, PendingFlush_Stop) { +TEST_F(AudioRendererImplTest, PendingFlush_Destroy) { Initialize(); Preroll(); @@ -615,18 +586,15 @@ TEST_F(AudioRendererImplTest, PendingFlush_Stop) { EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_NOTHING)); SatisfyPendingRead(InputFrames(256)); - WaitableMessageLoopEvent event; - renderer_->Stop(event.GetClosure()); - event.RunAndWait(); - needs_stop_ = false; + renderer_.reset(); } -TEST_F(AudioRendererImplTest, InitializeThenStop) { - InitializeAndStop(); +TEST_F(AudioRendererImplTest, InitializeThenDestroy) { + InitializeAndDestroy(); } -TEST_F(AudioRendererImplTest, InitializeThenStopDuringDecoderInit) { - InitializeAndStopDuringDecoderInit(); +TEST_F(AudioRendererImplTest, InitializeThenDestroyDuringDecoderInit) { + InitializeAndDestroyDuringDecoderInit(); } TEST_F(AudioRendererImplTest, ConfigChangeDrainsConverter) { |