OLD | NEW |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |