diff options
author | henrika@chromium.org <henrika@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-01 11:14:50 +0000 |
---|---|---|
committer | henrika@chromium.org <henrika@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-01 11:14:50 +0000 |
commit | 9055ba2bd5d4da411438f36dd49617bd4edd0ac8 (patch) | |
tree | f9ad17f4befd6ab9fe7485d4b61d4c88569556be | |
parent | 9986e3cd61a6bb80fc9e770cd6e8507177a27a12 (diff) | |
download | chromium_src-9055ba2bd5d4da411438f36dd49617bd4edd0ac8.zip chromium_src-9055ba2bd5d4da411438f36dd49617bd4edd0ac8.tar.gz chromium_src-9055ba2bd5d4da411438f36dd49617bd4edd0ac8.tar.bz2 |
Avoids crash in PCMWaveInAudioInputStream::WaveCallback
BUG=12092064
TEST=
Review URL: https://codereview.chromium.org/12092064
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@180125 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | media/audio/win/wavein_input_win.cc | 22 | ||||
-rw-r--r-- | media/audio/win/wavein_input_win.h | 4 |
2 files changed, 22 insertions, 4 deletions
diff --git a/media/audio/win/wavein_input_win.cc b/media/audio/win/wavein_input_win.cc index a625707..68d5265 100644 --- a/media/audio/win/wavein_input_win.cc +++ b/media/audio/win/wavein_input_win.cc @@ -152,6 +152,7 @@ void PCMWaveInAudioInputStream::Stop() { HandleError(::GetLastError()); return; } + // Stop is always called before Close. In case of error, this will be // also called when closing the input controller. manager_->DecreaseActiveInputStreamCount(); @@ -163,6 +164,13 @@ void PCMWaveInAudioInputStream::Stop() { HandleError(res); return; } + + // Wait for lock to ensure all outstanding callbacks have completed. + base::AutoLock auto_lock(lock_); + + // Don't use callback after Stop(). + callback_ = NULL; + state_ = kStateReady; } @@ -265,6 +273,9 @@ void PCMWaveInAudioInputStream::WaveCallback(HWAVEIN hwi, UINT msg, PCMWaveInAudioInputStream* obj = reinterpret_cast<PCMWaveInAudioInputStream*>(instance); + // The lock ensures that Stop() can't be called during a callback. + base::AutoLock auto_lock(obj->lock_); + if (msg == WIM_DATA) { // WIM_DONE indicates that the driver is done with our buffer. We pass it // to the callback and check if we need to stop playing. @@ -273,10 +284,13 @@ void PCMWaveInAudioInputStream::WaveCallback(HWAVEIN hwi, UINT msg, // TODO(henrika): the |volume| parameter is always set to zero since there // is currently no support for controlling the microphone volume level. WAVEHDR* buffer = reinterpret_cast<WAVEHDR*>(param1); - obj->callback_->OnData(obj, reinterpret_cast<const uint8*>(buffer->lpData), - buffer->dwBytesRecorded, - buffer->dwBytesRecorded, - 0.0); + if (obj->callback_) { + obj->callback_->OnData(obj, + reinterpret_cast<const uint8*>(buffer->lpData), + buffer->dwBytesRecorded, + buffer->dwBytesRecorded, + 0.0); + } if (obj->state_ == kStateStopping) { // The main thread has called Stop() and is waiting to issue waveOutReset diff --git a/media/audio/win/wavein_input_win.h b/media/audio/win/wavein_input_win.h index 82f1f55..076b099 100644 --- a/media/audio/win/wavein_input_win.h +++ b/media/audio/win/wavein_input_win.h @@ -12,6 +12,7 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/synchronization/lock.h" #include "base/win/scoped_handle.h" #include "media/audio/audio_io.h" #include "media/audio/audio_parameters.h" @@ -116,6 +117,9 @@ class PCMWaveInAudioInputStream : public AudioInputStream { // An event that is signaled when the callback thread is ready to stop. base::win::ScopedHandle stopped_event_; + // Lock used to avoid conflicts when Stop() is called during a callback. + base::Lock lock_; + DISALLOW_COPY_AND_ASSIGN(PCMWaveInAudioInputStream); }; |