diff options
author | dalecurtis@chromium.org <dalecurtis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-07 19:09:24 +0000 |
---|---|---|
committer | dalecurtis@chromium.org <dalecurtis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-07 19:09:24 +0000 |
commit | 49cdfd863b19e9a6c6fc524b76c5a11422d2ae9f (patch) | |
tree | c6c01bbeaf203df2aa3fb1d596e882d62d81d88a /media | |
parent | 9fe89eaf1fbb8b1383c7f94817de2604032b2843 (diff) | |
download | chromium_src-49cdfd863b19e9a6c6fc524b76c5a11422d2ae9f.zip chromium_src-49cdfd863b19e9a6c6fc524b76c5a11422d2ae9f.tar.gz chromium_src-49cdfd863b19e9a6c6fc524b76c5a11422d2ae9f.tar.bz2 |
Fix double StopStream() calls during wedge fix.
Whoops. The wedge fix ignored start / stop status when stopping
streams which leads to heap corruption when the underlying dispatcher
tries to stop a stream it can't find in the audio stream map.
BUG=326656
TEST=new unittest
NOTRY=true
Review URL: https://codereview.chromium.org/109113002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@239342 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/audio/audio_output_proxy_unittest.cc | 16 | ||||
-rw-r--r-- | media/audio/audio_output_resampler.cc | 13 |
2 files changed, 24 insertions, 5 deletions
diff --git a/media/audio/audio_output_proxy_unittest.cc b/media/audio/audio_output_proxy_unittest.cc index 1c4029b..de690d9 100644 --- a/media/audio/audio_output_proxy_unittest.cc +++ b/media/audio/audio_output_proxy_unittest.cc @@ -771,6 +771,7 @@ TEST_F(AudioOutputResamplerTest, WedgeFix) { EXPECT_CALL(stream1, SetVolume(_)); EXPECT_CALL(stream2, Open()) .WillOnce(Return(true)); + EXPECT_CALL(stream2, SetVolume(_)); EXPECT_CALL(stream2, Close()); // Open and start the first proxy and stream. @@ -783,12 +784,20 @@ TEST_F(AudioOutputResamplerTest, WedgeFix) { AudioOutputProxy* proxy2 = new AudioOutputProxy(resampler_.get()); EXPECT_TRUE(proxy2->Open()); + // Open, start and then stop the third proxy. + AudioOutputProxy* proxy3 = new AudioOutputProxy(resampler_.get()); + EXPECT_TRUE(proxy3->Open()); + proxy3->Start(&callback_); + OnStart(); + proxy3->Stop(); + // Wait for stream to timeout and shutdown. WaitForCloseTimer(kTestCloseDelayMs); resampler_->CloseStreamsForWedgeFix(); - // Stream3 should take Stream1's place after RestartStreamsForWedgeFix(). + // Stream3 should take Stream1's place after RestartStreamsForWedgeFix(). No + // additional streams should be opened for proxy2 and proxy3. EXPECT_CALL(stream3, Open()) .WillOnce(Return(true)); EXPECT_CALL(stream3, Close()); @@ -798,6 +807,7 @@ TEST_F(AudioOutputResamplerTest, WedgeFix) { OnStart(); // Perform the required Stop()/Close() shutdown dance for each proxy. + proxy3->Close(); proxy2->Close(); proxy1->Stop(); proxy1->Close(); @@ -806,8 +816,8 @@ TEST_F(AudioOutputResamplerTest, WedgeFix) { WaitForCloseTimer(kTestCloseDelayMs); EXPECT_TRUE(stream1.stop_called()); EXPECT_TRUE(stream1.start_called()); - EXPECT_FALSE(stream2.stop_called()); - EXPECT_FALSE(stream2.start_called()); + EXPECT_TRUE(stream2.stop_called()); + EXPECT_TRUE(stream2.start_called()); EXPECT_TRUE(stream3.stop_called()); EXPECT_TRUE(stream3.start_called()); } diff --git a/media/audio/audio_output_resampler.cc b/media/audio/audio_output_resampler.cc index 3179ddb..c53f3e0 100644 --- a/media/audio/audio_output_resampler.cc +++ b/media/audio/audio_output_resampler.cc @@ -43,6 +43,8 @@ class OnMoreDataConverter // Clears |source_callback_| and flushes the resampler. void Stop(); + bool started() { return source_callback_ != NULL; } + private: // AudioConverter::InputCallback implementation. virtual double ProvideInput(AudioBus* audio_bus, @@ -298,7 +300,8 @@ void AudioOutputResampler::CloseStreamsForWedgeFix() { // have been closed the AudioManager will call RestartStreamsForWedgeFix(). for (CallbackMap::iterator it = callbacks_.begin(); it != callbacks_.end(); ++it) { - dispatcher_->StopStream(it->first); + if (it->second->started()) + dispatcher_->StopStream(it->first); dispatcher_->CloseStream(it->first); } @@ -308,10 +311,16 @@ void AudioOutputResampler::CloseStreamsForWedgeFix() { void AudioOutputResampler::RestartStreamsForWedgeFix() { DCHECK(message_loop_->BelongsToCurrentThread()); + // By opening all streams first and then starting them one by one we ensure + // the dispatcher only opens streams for those which will actually be used. for (CallbackMap::iterator it = callbacks_.begin(); it != callbacks_.end(); ++it) { dispatcher_->OpenStream(); - dispatcher_->StartStream(it->second, it->first); + } + for (CallbackMap::iterator it = callbacks_.begin(); it != callbacks_.end(); + ++it) { + if (it->second->started()) + dispatcher_->StartStream(it->second, it->first); } } |