| 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 |