Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(334)

Side by Side Diff: media/audio/win/wavein_input_win.cc

Issue 12092064: Avoids crash in PCMWaveInAudioInputStream::WaveCallback (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: nit Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/audio/win/wavein_input_win.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/audio/win/wavein_input_win.h" 5 #include "media/audio/win/wavein_input_win.h"
6 6
7 #pragma comment(lib, "winmm.lib") 7 #pragma comment(lib, "winmm.lib")
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "media/audio/audio_io.h" 10 #include "media/audio/audio_io.h"
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 void PCMWaveInAudioInputStream::Stop() { 145 void PCMWaveInAudioInputStream::Stop() {
146 if (state_ != kStateRecording) 146 if (state_ != kStateRecording)
147 return; 147 return;
148 state_ = kStateStopping; 148 state_ = kStateStopping;
149 // Wait for the callback to finish, it will signal us when ready to be reset. 149 // Wait for the callback to finish, it will signal us when ready to be reset.
150 if (WAIT_OBJECT_0 != 150 if (WAIT_OBJECT_0 !=
151 ::WaitForSingleObject(stopped_event_, kStopInputStreamCallbackTimeout)) { 151 ::WaitForSingleObject(stopped_event_, kStopInputStreamCallbackTimeout)) {
152 HandleError(::GetLastError()); 152 HandleError(::GetLastError());
153 return; 153 return;
154 } 154 }
155
155 // Stop is always called before Close. In case of error, this will be 156 // Stop is always called before Close. In case of error, this will be
156 // also called when closing the input controller. 157 // also called when closing the input controller.
157 manager_->DecreaseActiveInputStreamCount(); 158 manager_->DecreaseActiveInputStreamCount();
158 159
159 state_ = kStateStopped; 160 state_ = kStateStopped;
160 MMRESULT res = ::waveInReset(wavein_); 161 MMRESULT res = ::waveInReset(wavein_);
161 if (res != MMSYSERR_NOERROR) { 162 if (res != MMSYSERR_NOERROR) {
162 state_ = kStateRecording; 163 state_ = kStateRecording;
163 HandleError(res); 164 HandleError(res);
164 return; 165 return;
165 } 166 }
167
168 // Wait for lock to ensure all outstanding callbacks have completed.
169 base::AutoLock auto_lock(lock_);
170
171 // Don't use callback after Stop().
172 callback_ = NULL;
173
166 state_ = kStateReady; 174 state_ = kStateReady;
167 } 175 }
168 176
169 // We can Close in any state except that when trying to close a stream that is 177 // We can Close in any state except that when trying to close a stream that is
170 // recording Windows generates an error, which we propagate to the source. 178 // recording Windows generates an error, which we propagate to the source.
171 void PCMWaveInAudioInputStream::Close() { 179 void PCMWaveInAudioInputStream::Close() {
172 if (wavein_) { 180 if (wavein_) {
173 // waveInClose generates a callback with WIM_CLOSE id in the same thread. 181 // waveInClose generates a callback with WIM_CLOSE id in the same thread.
174 MMRESULT res = ::waveInClose(wavein_); 182 MMRESULT res = ::waveInClose(wavein_);
175 if (res != MMSYSERR_NOERROR) { 183 if (res != MMSYSERR_NOERROR) {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 } 266 }
259 267
260 // Windows calls us back in this function when some events happen. Most notably 268 // Windows calls us back in this function when some events happen. Most notably
261 // when it has an audio buffer with recorded data. 269 // when it has an audio buffer with recorded data.
262 void PCMWaveInAudioInputStream::WaveCallback(HWAVEIN hwi, UINT msg, 270 void PCMWaveInAudioInputStream::WaveCallback(HWAVEIN hwi, UINT msg,
263 DWORD_PTR instance, 271 DWORD_PTR instance,
264 DWORD_PTR param1, DWORD_PTR) { 272 DWORD_PTR param1, DWORD_PTR) {
265 PCMWaveInAudioInputStream* obj = 273 PCMWaveInAudioInputStream* obj =
266 reinterpret_cast<PCMWaveInAudioInputStream*>(instance); 274 reinterpret_cast<PCMWaveInAudioInputStream*>(instance);
267 275
276 // The lock ensures that Stop() can't be called during a callback.
277 base::AutoLock auto_lock(obj->lock_);
278
268 if (msg == WIM_DATA) { 279 if (msg == WIM_DATA) {
269 // WIM_DONE indicates that the driver is done with our buffer. We pass it 280 // WIM_DONE indicates that the driver is done with our buffer. We pass it
270 // to the callback and check if we need to stop playing. 281 // to the callback and check if we need to stop playing.
271 // It should be OK to assume the data in the buffer is what has been 282 // It should be OK to assume the data in the buffer is what has been
272 // recorded in the soundcard. 283 // recorded in the soundcard.
273 // TODO(henrika): the |volume| parameter is always set to zero since there 284 // TODO(henrika): the |volume| parameter is always set to zero since there
274 // is currently no support for controlling the microphone volume level. 285 // is currently no support for controlling the microphone volume level.
275 WAVEHDR* buffer = reinterpret_cast<WAVEHDR*>(param1); 286 WAVEHDR* buffer = reinterpret_cast<WAVEHDR*>(param1);
276 obj->callback_->OnData(obj, reinterpret_cast<const uint8*>(buffer->lpData), 287 if (obj->callback_) {
277 buffer->dwBytesRecorded, 288 obj->callback_->OnData(obj,
278 buffer->dwBytesRecorded, 289 reinterpret_cast<const uint8*>(buffer->lpData),
279 0.0); 290 buffer->dwBytesRecorded,
291 buffer->dwBytesRecorded,
292 0.0);
293 }
280 294
281 if (obj->state_ == kStateStopping) { 295 if (obj->state_ == kStateStopping) {
282 // The main thread has called Stop() and is waiting to issue waveOutReset 296 // The main thread has called Stop() and is waiting to issue waveOutReset
283 // which will kill this thread. We should not enter AudioSourceCallback 297 // which will kill this thread. We should not enter AudioSourceCallback
284 // code anymore. 298 // code anymore.
285 ::SetEvent(obj->stopped_event_); 299 ::SetEvent(obj->stopped_event_);
286 } else if (obj->state_ == kStateStopped) { 300 } else if (obj->state_ == kStateStopped) {
287 // Not sure if ever hit this but just in case. 301 // Not sure if ever hit this but just in case.
288 } else { 302 } else {
289 // Queue the finished buffer back with the audio driver. Since we are 303 // Queue the finished buffer back with the audio driver. Since we are
290 // reusing the same buffers we can get away without calling 304 // reusing the same buffers we can get away without calling
291 // waveInPrepareHeader. 305 // waveInPrepareHeader.
292 obj->QueueNextPacket(buffer); 306 obj->QueueNextPacket(buffer);
293 } 307 }
294 } else if (msg == WIM_CLOSE) { 308 } else if (msg == WIM_CLOSE) {
295 // We can be closed before calling Start, so it is possible to have a 309 // We can be closed before calling Start, so it is possible to have a
296 // null callback at this point. 310 // null callback at this point.
297 if (obj->callback_) 311 if (obj->callback_)
298 obj->callback_->OnClose(obj); 312 obj->callback_->OnClose(obj);
299 } 313 }
300 } 314 }
301 315
302 } // namespace media 316 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/win/wavein_input_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698