| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "content/renderer/media/webrtc_audio_device_impl.h" | 5 #include "content/renderer/media/webrtc_audio_device_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
| 9 #include "content/common/view_messages.h" |
| 9 #include "content/renderer/render_thread_impl.h" | 10 #include "content/renderer/render_thread_impl.h" |
| 10 #include "media/audio/audio_util.h" | 11 #include "media/audio/audio_util.h" |
| 11 | 12 |
| 12 static const int64 kMillisecondsBetweenProcessCalls = 5000; | 13 static const int64 kMillisecondsBetweenProcessCalls = 5000; |
| 13 static const char kVersion[] = "WebRTC AudioDevice 1.0.0.Chrome"; | 14 static const char kVersion[] = "WebRTC AudioDevice 1.0.0.Chrome"; |
| 14 | 15 |
| 16 static int GetAudioInputHardwareSampleRate() { |
| 17 static double input_sample_rate = 0; |
| 18 if (!input_sample_rate) { |
| 19 RenderThreadImpl::current()->Send( |
| 20 new ViewHostMsg_GetHardwareInputSampleRate(&input_sample_rate)); |
| 21 } |
| 22 return static_cast<int>(input_sample_rate); |
| 23 } |
| 24 |
| 15 WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl() | 25 WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl() |
| 16 : ref_count_(0), | 26 : ref_count_(0), |
| 17 render_loop_(base::MessageLoopProxy::current()), | 27 render_loop_(base::MessageLoopProxy::current()), |
| 18 audio_transport_callback_(NULL), | 28 audio_transport_callback_(NULL), |
| 19 input_buffer_size_(0), | 29 input_buffer_size_(0), |
| 20 output_buffer_size_(0), | 30 output_buffer_size_(0), |
| 21 input_channels_(0), | 31 input_channels_(0), |
| 22 output_channels_(0), | 32 output_channels_(0), |
| 23 input_sample_rate_(0), | 33 input_sample_rate_(0), |
| 24 output_sample_rate_(0), | 34 output_sample_rate_(0), |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 | 75 |
| 66 // Store the reported audio delay locally. | 76 // Store the reported audio delay locally. |
| 67 output_delay_ms_ = audio_delay_milliseconds; | 77 output_delay_ms_ = audio_delay_milliseconds; |
| 68 | 78 |
| 69 const int channels = audio_data.size(); | 79 const int channels = audio_data.size(); |
| 70 DCHECK_LE(channels, output_channels_); | 80 DCHECK_LE(channels, output_channels_); |
| 71 | 81 |
| 72 int samples_per_sec = static_cast<int>(output_sample_rate_); | 82 int samples_per_sec = static_cast<int>(output_sample_rate_); |
| 73 if (samples_per_sec == 44100) { | 83 if (samples_per_sec == 44100) { |
| 74 // Even if the hardware runs at 44.1kHz, we use 44.0 internally. | 84 // Even if the hardware runs at 44.1kHz, we use 44.0 internally. |
| 75 // Can only happen on Mac OS X currently since Windows and Mac | |
| 76 // both uses 48kHz. | |
| 77 samples_per_sec = 44000; | 85 samples_per_sec = 44000; |
| 78 } | 86 } |
| 79 uint32_t samples_per_10_msec = (samples_per_sec / 100); | 87 uint32_t samples_per_10_msec = (samples_per_sec / 100); |
| 80 const int bytes_per_10_msec = | 88 const int bytes_per_10_msec = |
| 81 channels * samples_per_10_msec * bytes_per_sample_; | 89 channels * samples_per_10_msec * bytes_per_sample_; |
| 82 | 90 |
| 83 uint32_t num_audio_samples = 0; | 91 uint32_t num_audio_samples = 0; |
| 84 size_t accumulated_audio_samples = 0; | 92 size_t accumulated_audio_samples = 0; |
| 85 | 93 |
| 86 char* audio_byte_buffer = reinterpret_cast<char*>(output_buffer_.get()); | 94 char* audio_byte_buffer = reinterpret_cast<char*>(output_buffer_.get()); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 const int channels = audio_data.size(); | 133 const int channels = audio_data.size(); |
| 126 DCHECK_LE(channels, input_channels_); | 134 DCHECK_LE(channels, input_channels_); |
| 127 uint32_t new_mic_level = 0; | 135 uint32_t new_mic_level = 0; |
| 128 | 136 |
| 129 // Interleave, scale, and clip input to int16 and store result in | 137 // Interleave, scale, and clip input to int16 and store result in |
| 130 // a local byte buffer. | 138 // a local byte buffer. |
| 131 media::InterleaveFloatToInt16(audio_data, | 139 media::InterleaveFloatToInt16(audio_data, |
| 132 input_buffer_.get(), | 140 input_buffer_.get(), |
| 133 number_of_frames); | 141 number_of_frames); |
| 134 | 142 |
| 135 const int samples_per_sec = static_cast<int>(input_sample_rate_); | 143 int samples_per_sec = static_cast<int>(input_sample_rate_); |
| 144 if (samples_per_sec == 44100) { |
| 145 // Even if the hardware runs at 44.1kHz, we use 44.0 internally. |
| 146 samples_per_sec = 44000; |
| 147 } |
| 136 const int samples_per_10_msec = (samples_per_sec / 100); | 148 const int samples_per_10_msec = (samples_per_sec / 100); |
| 137 const int bytes_per_10_msec = | 149 const int bytes_per_10_msec = |
| 138 channels * samples_per_10_msec * bytes_per_sample_; | 150 channels * samples_per_10_msec * bytes_per_sample_; |
| 139 size_t accumulated_audio_samples = 0; | 151 size_t accumulated_audio_samples = 0; |
| 140 | 152 |
| 141 char* audio_byte_buffer = reinterpret_cast<char*>(input_buffer_.get()); | 153 char* audio_byte_buffer = reinterpret_cast<char*>(input_buffer_.get()); |
| 142 | 154 |
| 143 // Write audio samples in blocks of 10 milliseconds to the registered | 155 // Write audio samples in blocks of 10 milliseconds to the registered |
| 144 // webrtc::AudioTransport sink. Keep writing until our internal byte | 156 // webrtc::AudioTransport sink. Keep writing until our internal byte |
| 145 // buffer is empty. | 157 // buffer is empty. |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 | 279 |
| 268 // Calling Init() multiple times in a row is OK. | 280 // Calling Init() multiple times in a row is OK. |
| 269 if (initialized_) | 281 if (initialized_) |
| 270 return 0; | 282 return 0; |
| 271 | 283 |
| 272 DCHECK(!audio_input_device_); | 284 DCHECK(!audio_input_device_); |
| 273 DCHECK(!audio_output_device_); | 285 DCHECK(!audio_output_device_); |
| 274 DCHECK(!input_buffer_.get()); | 286 DCHECK(!input_buffer_.get()); |
| 275 DCHECK(!output_buffer_.get()); | 287 DCHECK(!output_buffer_.get()); |
| 276 | 288 |
| 277 // TODO(henrika): add AudioInputDevice::GetAudioHardwareSampleRate(). | |
| 278 // Assume that input and output sample rates are identical for now. | |
| 279 | |
| 280 // Ask the browser for the default audio output hardware sample-rate. | 289 // Ask the browser for the default audio output hardware sample-rate. |
| 281 // This request is based on a synchronous IPC message. | 290 // This request is based on a synchronous IPC message. |
| 282 int output_sample_rate = | 291 int output_sample_rate = |
| 283 static_cast<int>(AudioDevice::GetAudioHardwareSampleRate()); | 292 static_cast<int>(AudioDevice::GetAudioHardwareSampleRate()); |
| 284 VLOG(1) << "Audio hardware sample rate: " << output_sample_rate; | 293 VLOG(1) << "Audio output hardware sample rate: " << output_sample_rate; |
| 294 |
| 295 // Ask the browser for the default audio input hardware sample-rate. |
| 296 // This request is based on a synchronous IPC message. |
| 297 int input_sample_rate = GetAudioInputHardwareSampleRate(); |
| 298 VLOG(1) << "Audio input hardware sample rate: " << input_sample_rate; |
| 285 | 299 |
| 286 int input_channels = 0; | 300 int input_channels = 0; |
| 287 int output_channels = 0; | 301 int output_channels = 0; |
| 288 | 302 |
| 289 size_t input_buffer_size = 0; | 303 size_t input_buffer_size = 0; |
| 290 size_t output_buffer_size = 0; | 304 size_t output_buffer_size = 0; |
| 291 | 305 |
| 292 // For real-time audio (in combination with the webrtc::VoiceEngine) it | 306 // For real-time audio (in combination with the webrtc::VoiceEngine) it |
| 293 // is convenient to use audio buffers of size N*10ms. | 307 // is convenient to use audio buffers of size N*10ms. |
| 308 |
| 294 #if defined(OS_WIN) | 309 #if defined(OS_WIN) |
| 295 if (output_sample_rate != 48000) { | 310 if (output_sample_rate != 48000) { |
| 296 DLOG(ERROR) << "Only 48kHz sample rate is supported on Windows."; | 311 DLOG(ERROR) << "Only 48kHz sample rate is supported on Windows."; |
| 297 return -1; | 312 return -1; |
| 298 } | 313 } |
| 299 input_channels = 1; | 314 |
| 315 // Use stereo recording on Windows since low-latency Core Audio (WASAPI) |
| 316 // does not support mono. |
| 317 input_channels = 2; |
| 300 output_channels = 1; | 318 output_channels = 1; |
| 301 // Capture side: AUDIO_PCM_LINEAR on Windows is based on a callback- | 319 |
| 302 // driven Wave implementation where 3 buffers are used for recording audio. | 320 // Capture side: AUDIO_PCM_LOW_LATENCY is based on the Core Audio (WASAPI) |
| 303 // Each buffer is of the size that we specify here and using more than one | 321 // API which was introduced in Windows Vista. For lower Windows versions, |
| 304 // does not increase the delay but only adds robustness against dropping | 322 // a callback-driven Wave implementation is used instead. An input buffer |
| 305 // audio. It might also affect the initial start-up time before callbacks | 323 // size of 10ms works well for both these implementations. |
| 306 // start to pump. Real-time tests have shown that a buffer size of 10ms | 324 |
| 307 // works fine on the capture side. | 325 // Use different buffer sizes depending on the current hardware sample rate. |
| 308 input_buffer_size = 480; | 326 if (input_sample_rate == 48000) { |
| 327 input_buffer_size = 480; |
| 328 } else { |
| 329 // We do run at 44.1kHz at the actual audio layer, but ask for frames |
| 330 // at 44.0kHz to ensure that we can feed them to the webrtc::VoiceEngine. |
| 331 input_buffer_size = 440; |
| 332 } |
| 333 |
| 309 // Rendering side: AUDIO_PCM_LOW_LATENCY on Windows is based on a callback- | 334 // Rendering side: AUDIO_PCM_LOW_LATENCY on Windows is based on a callback- |
| 310 // driven Wave implementation where 2 buffers are fed to the audio driver | 335 // driven Wave implementation where 2 buffers are fed to the audio driver |
| 311 // before actual rendering starts. Initial real-time tests have shown that | 336 // before actual rendering starts. Initial real-time tests have shown that |
| 312 // 20ms buffer size (corresponds to ~40ms total delay) is not enough but | 337 // 20ms buffer size (corresponds to ~40ms total delay) is not enough but |
| 313 // can lead to buffer underruns. The next even multiple of 10ms is 30ms | 338 // can lead to buffer underruns. The next even multiple of 10ms is 30ms |
| 314 // (<=> ~60ms total delay) and it works fine also under high load. | 339 // (<=> ~60ms total delay) and it works fine also under high load. |
| 315 output_buffer_size = 3 * 480; | 340 output_buffer_size = 3 * 480; |
| 316 #elif defined(OS_MACOSX) | 341 #elif defined(OS_MACOSX) |
| 317 if (output_sample_rate != 48000 && output_sample_rate != 44100) { | 342 if (output_sample_rate != 48000 && output_sample_rate != 44100) { |
| 318 DLOG(ERROR) << "Only 48 and 44.1kHz sample rates are supported on Mac OSX."; | 343 DLOG(ERROR) << "Only 48 and 44.1kHz sample rates are supported on Mac OSX."; |
| 319 return -1; | 344 return -1; |
| 320 } | 345 } |
| 321 input_channels = 1; | 346 input_channels = 1; |
| 322 output_channels = 1; | 347 output_channels = 1; |
| 348 |
| 323 // Rendering side: AUDIO_PCM_LOW_LATENCY on Mac OS X is based on a callback- | 349 // Rendering side: AUDIO_PCM_LOW_LATENCY on Mac OS X is based on a callback- |
| 324 // driven Core Audio implementation. Tests have shown that 10ms is a suitable | 350 // driven Core Audio implementation. Tests have shown that 10ms is a suitable |
| 325 // frame size to use, both for 48kHz and 44.1kHz. | 351 // frame size to use, both for 48kHz and 44.1kHz. |
| 326 // Capturing side: AUDIO_PCM_LINEAR on Mac OS X uses the Audio Queue Services | 352 // Capturing side: AUDIO_PCM_LINEAR on Mac OS X uses the Audio Queue Services |
| 327 // API which is not well suited for real-time applications since the delay | 353 // API which is not well suited for real-time applications since the delay |
| 328 // is very high. We set buffer sizes to 10ms for the input side here as well | 354 // is very high. We set buffer sizes to 10ms for the input side here as well |
| 329 // but none of them will work. | 355 // but none of them will work. |
| 330 // TODO(henrika): add support for AUDIO_PCM_LOW_LATENCY on the capture side | 356 // TODO(henrika): add support for AUDIO_PCM_LOW_LATENCY on the capture side |
| 331 // based on the Mac OS X Core Audio API. | 357 // based on the Mac OS X Core Audio API. |
| 332 | 358 |
| 333 // Use different buffer sizes depending on the current hardware sample rate. | 359 // Use different buffer sizes depending on the current hardware sample rate. |
| 334 if (output_sample_rate == 48000) { | 360 if (output_sample_rate == 48000) { |
| 335 input_buffer_size = 480; | 361 input_buffer_size = 480; |
| 336 output_buffer_size = 480; | 362 output_buffer_size = 480; |
| 337 } else { | 363 } else { |
| 338 // We do run at 44.1kHz at the actual audio layer, but ask for frames | 364 // We do run at 44.1kHz at the actual audio layer, but ask for frames |
| 339 // at 44.0kHz to ensure that we can feed them to the webrtc::VoiceEngine. | 365 // at 44.0kHz to ensure that we can feed them to the webrtc::VoiceEngine. |
| 340 input_buffer_size = 440; | 366 input_buffer_size = 440; |
| 341 output_buffer_size = 440; | 367 output_buffer_size = 440; |
| 342 } | 368 } |
| 343 #elif defined(OS_LINUX) | 369 #elif defined(OS_LINUX) |
| 344 if (output_sample_rate != 48000) { | 370 if (output_sample_rate != 48000) { |
| 345 DLOG(ERROR) << "Only 48kHz sample rate is supported on Linux."; | 371 DLOG(ERROR) << "Only 48kHz sample rate is supported on Linux."; |
| 346 return -1; | 372 return -1; |
| 347 } | 373 } |
| 348 input_channels = 1; | 374 input_channels = 1; |
| 349 output_channels = 1; | 375 output_channels = 1; |
| 376 |
| 350 // Based on tests using the current ALSA implementation in Chrome, we have | 377 // Based on tests using the current ALSA implementation in Chrome, we have |
| 351 // found that the best combination is 20ms on the input side and 10ms on the | 378 // found that the best combination is 20ms on the input side and 10ms on the |
| 352 // output side. | 379 // output side. |
| 353 // TODO(henrika): It might be possible to reduce the input buffer | 380 // TODO(henrika): It might be possible to reduce the input buffer |
| 354 // size and reduce the delay even more. | 381 // size and reduce the delay even more. |
| 355 input_buffer_size = 2 * 480; | 382 input_buffer_size = 2 * 480; |
| 356 output_buffer_size = 480; | 383 output_buffer_size = 480; |
| 357 #else | 384 #else |
| 358 DLOG(ERROR) << "Unsupported platform"; | 385 DLOG(ERROR) << "Unsupported platform"; |
| 359 return -1; | 386 return -1; |
| 360 #endif | 387 #endif |
| 361 | 388 |
| 362 // Store utilized parameters to ensure that we can check them | 389 // Store utilized parameters to ensure that we can check them |
| 363 // after a successful initialization. | 390 // after a successful initialization. |
| 364 output_buffer_size_ = output_buffer_size; | 391 output_buffer_size_ = output_buffer_size; |
| 365 output_channels_ = output_channels; | 392 output_channels_ = output_channels; |
| 366 output_sample_rate_ = static_cast<double>(output_sample_rate); | 393 output_sample_rate_ = static_cast<double>(output_sample_rate); |
| 367 | 394 |
| 368 input_buffer_size_ = input_buffer_size; | 395 input_buffer_size_ = input_buffer_size; |
| 369 input_channels_ = input_channels; | 396 input_channels_ = input_channels; |
| 370 // TODO(henrika): we use same rate as on output for now. | 397 input_sample_rate_ = input_sample_rate; |
| 371 input_sample_rate_ = output_sample_rate_; | |
| 372 | 398 |
| 373 // Create and configure the audio capturing client. | 399 // Create and configure the audio capturing client. |
| 374 audio_input_device_ = new AudioInputDevice( | 400 audio_input_device_ = new AudioInputDevice( |
| 375 input_buffer_size, input_channels, output_sample_rate, this, this); | 401 input_buffer_size, input_channels, input_sample_rate, this, this); |
| 376 #if defined(OS_MACOSX) | |
| 377 // We create the input device for Mac as well but the performance | |
| 378 // will be very bad. | |
| 379 DLOG(WARNING) << "Real-time recording is not yet supported on Mac OS X"; | |
| 380 #endif | |
| 381 | 402 |
| 382 // Create and configure the audio rendering client. | 403 // Create and configure the audio rendering client. |
| 383 audio_output_device_ = new AudioDevice( | 404 audio_output_device_ = new AudioDevice( |
| 384 output_buffer_size, output_channels, output_sample_rate, this); | 405 output_buffer_size, output_channels, output_sample_rate, this); |
| 385 | 406 |
| 386 DCHECK(audio_input_device_); | 407 DCHECK(audio_input_device_); |
| 387 DCHECK(audio_output_device_); | 408 DCHECK(audio_output_device_); |
| 388 | 409 |
| 389 // Allocate local audio buffers based on the parameters above. | 410 // Allocate local audio buffers based on the parameters above. |
| 390 // It is assumed that each audio sample contains 16 bits and each | 411 // It is assumed that each audio sample contains 16 bits and each |
| (...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 923 } | 944 } |
| 924 | 945 |
| 925 int32_t WebRtcAudioDeviceImpl::GetLoudspeakerStatus(bool* enabled) const { | 946 int32_t WebRtcAudioDeviceImpl::GetLoudspeakerStatus(bool* enabled) const { |
| 926 NOTIMPLEMENTED(); | 947 NOTIMPLEMENTED(); |
| 927 return -1; | 948 return -1; |
| 928 } | 949 } |
| 929 | 950 |
| 930 void WebRtcAudioDeviceImpl::SetSessionId(int session_id) { | 951 void WebRtcAudioDeviceImpl::SetSessionId(int session_id) { |
| 931 session_id_ = session_id; | 952 session_id_ = session_id; |
| 932 } | 953 } |
| OLD | NEW |