Commit 9055ba2b authored by henrika@chromium.org's avatar henrika@chromium.org

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
parent 9986e3cd
......@@ -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
......
......@@ -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);
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment