summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authordalecurtis@chromium.org <dalecurtis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-07 19:09:24 +0000
committerdalecurtis@chromium.org <dalecurtis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-07 19:09:24 +0000
commit49cdfd863b19e9a6c6fc524b76c5a11422d2ae9f (patch)
treec6c01bbeaf203df2aa3fb1d596e882d62d81d88a /media
parent9fe89eaf1fbb8b1383c7f94817de2604032b2843 (diff)
downloadchromium_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.cc16
-rw-r--r--media/audio/audio_output_resampler.cc13
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);
}
}