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 "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 "base/win/windows_version.h" | 9 #include "base/win/windows_version.h" |
10 #include "content/renderer/media/audio_hardware.h" | 10 #include "content/renderer/media/audio_hardware.h" |
11 #include "content/renderer/render_thread_impl.h" | 11 #include "content/renderer/render_thread_impl.h" |
12 #include "media/audio/audio_util.h" | 12 #include "media/audio/audio_util.h" |
13 | 13 |
14 static const int64 kMillisecondsBetweenProcessCalls = 5000; | 14 static const int64 kMillisecondsBetweenProcessCalls = 5000; |
| 15 static const double kMaxVolumeLevel = 255.0; |
15 | 16 |
16 // Supported hardware sample rates for input and output sides. | 17 // Supported hardware sample rates for input and output sides. |
17 #if defined(OS_WIN) || defined(OS_MACOSX) | 18 #if defined(OS_WIN) || defined(OS_MACOSX) |
18 // media::GetAudioInput[Output]HardwareSampleRate() asks the audio layer | 19 // media::GetAudioInput[Output]HardwareSampleRate() asks the audio layer |
19 // for its current sample rate (set by the user) on Windows and Mac OS X. | 20 // for its current sample rate (set by the user) on Windows and Mac OS X. |
20 // The listed rates below adds restrictions and WebRtcAudioDeviceImpl::Init() | 21 // The listed rates below adds restrictions and WebRtcAudioDeviceImpl::Init() |
21 // will fail if the user selects any rate outside these ranges. | 22 // will fail if the user selects any rate outside these ranges. |
22 static int kValidInputRates[] = {96000, 48000, 44100, 32000, 16000}; | 23 static int kValidInputRates[] = {96000, 48000, 44100, 32000, 16000}; |
23 static int kValidOutputRates[] = {96000, 48000, 44100}; | 24 static int kValidOutputRates[] = {96000, 48000, 44100}; |
24 #elif defined(OS_LINUX) || defined(OS_OPENBSD) | 25 #elif defined(OS_LINUX) || defined(OS_OPENBSD) |
25 // media::GetAudioInput[Output]HardwareSampleRate() is hardcoded to return | 26 // media::GetAudioInput[Output]HardwareSampleRate() is hardcoded to return |
26 // 48000 in both directions on Linux. | 27 // 48000 in both directions on Linux. |
27 static int kValidInputRates[] = {48000}; | 28 static int kValidInputRates[] = {48000}; |
28 static int kValidOutputRates[] = {48000}; | 29 static int kValidOutputRates[] = {48000}; |
29 #endif | 30 #endif |
30 | 31 |
31 WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl() | 32 WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl() |
32 : ref_count_(0), | 33 : ref_count_(0), |
33 render_loop_(base::MessageLoopProxy::current()), | 34 render_loop_(base::MessageLoopProxy::current()), |
34 audio_transport_callback_(NULL), | 35 audio_transport_callback_(NULL), |
35 input_delay_ms_(0), | 36 input_delay_ms_(0), |
36 output_delay_ms_(0), | 37 output_delay_ms_(0), |
37 last_error_(AudioDeviceModule::kAdmErrNone), | 38 last_error_(AudioDeviceModule::kAdmErrNone), |
38 last_process_time_(base::TimeTicks::Now()), | 39 last_process_time_(base::TimeTicks::Now()), |
39 session_id_(0), | 40 session_id_(0), |
40 bytes_per_sample_(0), | 41 bytes_per_sample_(0), |
41 initialized_(false), | 42 initialized_(false), |
42 playing_(false), | 43 playing_(false), |
43 recording_(false) { | 44 recording_(false), |
| 45 agc_is_enabled_(false) { |
44 DVLOG(1) << "WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()"; | 46 DVLOG(1) << "WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()"; |
45 DCHECK(RenderThreadImpl::current()) << | 47 DCHECK(RenderThreadImpl::current()) << |
46 "WebRtcAudioDeviceImpl must be constructed on the render thread"; | 48 "WebRtcAudioDeviceImpl must be constructed on the render thread"; |
47 } | 49 } |
48 | 50 |
49 WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl() { | 51 WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl() { |
50 DVLOG(1) << "WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl()"; | 52 DVLOG(1) << "WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl()"; |
51 if (playing_) | 53 if (playing_) |
52 StopPlayout(); | 54 StopPlayout(); |
53 if (recording_) | 55 if (recording_) |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 } | 127 } |
126 return number_of_frames; | 128 return number_of_frames; |
127 } | 129 } |
128 | 130 |
129 void WebRtcAudioDeviceImpl::OnRenderError() { | 131 void WebRtcAudioDeviceImpl::OnRenderError() { |
130 DCHECK_EQ(MessageLoop::current(), ChildProcess::current()->io_message_loop()); | 132 DCHECK_EQ(MessageLoop::current(), ChildProcess::current()->io_message_loop()); |
131 // TODO(henrika): Implement error handling. | 133 // TODO(henrika): Implement error handling. |
132 LOG(ERROR) << "OnRenderError()"; | 134 LOG(ERROR) << "OnRenderError()"; |
133 } | 135 } |
134 | 136 |
135 void WebRtcAudioDeviceImpl::Capture( | 137 void WebRtcAudioDeviceImpl::Capture(const std::vector<float*>& audio_data, |
136 const std::vector<float*>& audio_data, | 138 size_t number_of_frames, |
137 size_t number_of_frames, | 139 size_t audio_delay_milliseconds, |
138 size_t audio_delay_milliseconds) { | 140 double volume) { |
139 DCHECK_LE(number_of_frames, input_buffer_size()); | 141 DCHECK_LE(number_of_frames, input_buffer_size()); |
| 142 #if defined(OS_WIN) || defined(OS_MACOSX) |
| 143 DCHECK_LE(volume, 1.0); |
| 144 #elif defined(OS_LINUX) || defined(OS_OPENBSD) |
| 145 // We have a special situation on Linux where the microphone volume can be |
| 146 // "higher than maximum". The input volume slider in the sound preference |
| 147 // allows the user to set a scaling that is higher than 100%. It means that |
| 148 // even if the reported maximum levels is N, the actual microphone level can |
| 149 // go up to 1.5*N and that corresponds to a normalized |volume| of 1.5. |
| 150 DCHECK_LE(volume, 1.5); |
| 151 #endif |
140 | 152 |
141 int output_delay_ms = 0; | 153 int output_delay_ms = 0; |
142 { | 154 { |
143 base::AutoLock auto_lock(lock_); | 155 base::AutoLock auto_lock(lock_); |
144 // Store the reported audio delay locally. | 156 // Store the reported audio delay locally. |
145 input_delay_ms_ = audio_delay_milliseconds; | 157 input_delay_ms_ = audio_delay_milliseconds; |
146 output_delay_ms = output_delay_ms_; | 158 output_delay_ms = output_delay_ms_; |
147 } | 159 } |
148 | 160 |
149 const int channels = audio_data.size(); | 161 const int channels = audio_data.size(); |
150 DCHECK_LE(channels, input_channels()); | 162 DCHECK_LE(channels, input_channels()); |
151 uint32_t new_mic_level = 0; | 163 uint32_t new_mic_level = 0; |
152 | 164 |
153 // Interleave, scale, and clip input to int16 and store result in | 165 // Interleave, scale, and clip input to int16 and store result in |
154 // a local byte buffer. | 166 // a local byte buffer. |
155 media::InterleaveFloatToInt16(audio_data, | 167 media::InterleaveFloatToInt16(audio_data, |
156 input_buffer_.get(), | 168 input_buffer_.get(), |
157 number_of_frames); | 169 number_of_frames); |
158 | 170 |
159 int samples_per_sec = input_sample_rate(); | 171 int samples_per_sec = input_sample_rate(); |
160 if (samples_per_sec == 44100) { | 172 if (samples_per_sec == 44100) { |
161 // Even if the hardware runs at 44.1kHz, we use 44.0 internally. | 173 // Even if the hardware runs at 44.1kHz, we use 44.0 internally. |
162 samples_per_sec = 44000; | 174 samples_per_sec = 44000; |
163 } | 175 } |
164 const int samples_per_10_msec = (samples_per_sec / 100); | 176 const int samples_per_10_msec = (samples_per_sec / 100); |
165 const int bytes_per_10_msec = | 177 const int bytes_per_10_msec = |
166 channels * samples_per_10_msec * bytes_per_sample_; | 178 channels * samples_per_10_msec * bytes_per_sample_; |
167 size_t accumulated_audio_samples = 0; | 179 size_t accumulated_audio_samples = 0; |
| 180 char* audio_byte_buffer = reinterpret_cast<char*>(input_buffer_.get()); |
168 | 181 |
169 char* audio_byte_buffer = reinterpret_cast<char*>(input_buffer_.get()); | 182 // Map internal volume range of [0.0, 1.0] into [0, 255] used by the |
| 183 // webrtc::VoiceEngine. |
| 184 uint32_t current_mic_level = static_cast<uint32_t>(volume * kMaxVolumeLevel); |
170 | 185 |
171 // Write audio samples in blocks of 10 milliseconds to the registered | 186 // Write audio samples in blocks of 10 milliseconds to the registered |
172 // webrtc::AudioTransport sink. Keep writing until our internal byte | 187 // webrtc::AudioTransport sink. Keep writing until our internal byte |
173 // buffer is empty. | 188 // buffer is empty. |
174 while (accumulated_audio_samples < number_of_frames) { | 189 while (accumulated_audio_samples < number_of_frames) { |
175 // Deliver 10ms of recorded PCM audio. | 190 // Deliver 10ms of recorded 16-bit linear PCM audio. |
176 // TODO(henrika): add support for analog AGC? | |
177 audio_transport_callback_->RecordedDataIsAvailable( | 191 audio_transport_callback_->RecordedDataIsAvailable( |
178 audio_byte_buffer, | 192 audio_byte_buffer, |
179 samples_per_10_msec, | 193 samples_per_10_msec, |
180 bytes_per_sample_, | 194 bytes_per_sample_, |
181 channels, | 195 channels, |
182 samples_per_sec, | 196 samples_per_sec, |
183 input_delay_ms_ + output_delay_ms, | 197 input_delay_ms_ + output_delay_ms, |
184 0, // clock_drift | 198 0, // TODO(henrika): |clock_drift| parameter is not utilized today. |
185 0, // current_mic_level | 199 current_mic_level, |
186 new_mic_level); // not used | 200 new_mic_level); |
| 201 |
187 accumulated_audio_samples += samples_per_10_msec; | 202 accumulated_audio_samples += samples_per_10_msec; |
188 audio_byte_buffer += bytes_per_10_msec; | 203 audio_byte_buffer += bytes_per_10_msec; |
189 } | 204 } |
| 205 |
| 206 // The AGC returns a non-zero microphone level if it has been decided |
| 207 // that a new level should be set. |
| 208 if (new_mic_level != 0) { |
| 209 // Use IPC and set the new level. Note that, it will take some time |
| 210 // before the new level is effective due to the IPC scheme. |
| 211 // During this time, |current_mic_level| will contain "non-valid" values |
| 212 // and it might reduce the AGC performance. Measurements on Windows 7 have |
| 213 // shown that we might receive old volume levels for one or two callbacks. |
| 214 SetMicrophoneVolume(new_mic_level); |
| 215 } |
190 } | 216 } |
191 | 217 |
192 void WebRtcAudioDeviceImpl::OnCaptureError() { | 218 void WebRtcAudioDeviceImpl::OnCaptureError() { |
193 DCHECK_EQ(MessageLoop::current(), ChildProcess::current()->io_message_loop()); | 219 DCHECK_EQ(MessageLoop::current(), ChildProcess::current()->io_message_loop()); |
194 // TODO(henrika): Implement error handling. | 220 // TODO(henrika): Implement error handling. |
195 LOG(ERROR) << "OnCaptureError()"; | 221 LOG(ERROR) << "OnCaptureError()"; |
196 } | 222 } |
197 | 223 |
198 void WebRtcAudioDeviceImpl::OnDeviceStarted(const std::string& device_id) { | 224 void WebRtcAudioDeviceImpl::OnDeviceStarted(const std::string& device_id) { |
199 DVLOG(1) << "OnDeviceStarted (device_id=" << device_id << ")"; | 225 DVLOG(1) << "OnDeviceStarted (device_id=" << device_id << ")"; |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 } | 350 } |
325 | 351 |
326 // Ask the browser for the default number of audio input channels. | 352 // Ask the browser for the default number of audio input channels. |
327 // This request is based on a synchronous IPC message. | 353 // This request is based on a synchronous IPC message. |
328 ChannelLayout input_channel_layout = | 354 ChannelLayout input_channel_layout = |
329 audio_hardware::GetInputChannelLayout(); | 355 audio_hardware::GetInputChannelLayout(); |
330 DVLOG(1) << "Audio input hardware channels: " << input_channel_layout; | 356 DVLOG(1) << "Audio input hardware channels: " << input_channel_layout; |
331 | 357 |
332 ChannelLayout out_channel_layout = CHANNEL_LAYOUT_MONO; | 358 ChannelLayout out_channel_layout = CHANNEL_LAYOUT_MONO; |
333 AudioParameters::Format in_format = AudioParameters::AUDIO_PCM_LINEAR; | 359 AudioParameters::Format in_format = AudioParameters::AUDIO_PCM_LINEAR; |
334 size_t in_buffer_size = 0; | 360 int in_buffer_size = 0; |
335 size_t out_buffer_size = 0; | 361 int out_buffer_size = 0; |
336 | 362 |
337 // TODO(henrika): factor out all platform specific parts in separate | 363 // TODO(henrika): factor out all platform specific parts in separate |
338 // functions. Code is a bit messy right now. | 364 // functions. Code is a bit messy right now. |
339 | 365 |
340 // Windows | 366 // Windows |
341 #if defined(OS_WIN) | 367 #if defined(OS_WIN) |
342 // Always use stereo rendering on Windows. | 368 // Always use stereo rendering on Windows. |
343 out_channel_layout = CHANNEL_LAYOUT_STEREO; | 369 out_channel_layout = CHANNEL_LAYOUT_STEREO; |
344 | 370 |
345 DVLOG(1) << "Using AUDIO_PCM_LOW_LATENCY as input mode on Windows."; | 371 DVLOG(1) << "Using AUDIO_PCM_LOW_LATENCY as input mode on Windows."; |
346 in_format = AudioParameters::AUDIO_PCM_LOW_LATENCY; | 372 in_format = AudioParameters::AUDIO_PCM_LOW_LATENCY; |
347 | 373 |
348 // Capture side: AUDIO_PCM_LOW_LATENCY is based on the Core Audio (WASAPI) | 374 // Capture side: AUDIO_PCM_LOW_LATENCY is based on the Core Audio (WASAPI) |
349 // API which was introduced in Windows Vista. For lower Windows versions, | 375 // API which was introduced in Windows Vista. For lower Windows versions, |
350 // a callback-driven Wave implementation is used instead. An input buffer | 376 // a callback-driven Wave implementation is used instead. An input buffer |
351 // size of 10ms works well for both these implementations. | 377 // size of 10ms works well for both these implementations. |
352 | 378 |
353 // Use different buffer sizes depending on the current hardware sample rate. | 379 // Use different buffer sizes depending on the current hardware sample rate. |
354 if (in_sample_rate == 44100) { | 380 if (in_sample_rate == 44100) { |
355 // We do run at 44.1kHz at the actual audio layer, but ask for frames | 381 // We do run at 44.1kHz at the actual audio layer, but ask for frames |
356 // at 44.0kHz to ensure that we can feed them to the webrtc::VoiceEngine. | 382 // at 44.0kHz to ensure that we can feed them to the webrtc::VoiceEngine. |
357 in_buffer_size = 440; | 383 in_buffer_size = 440; |
358 } else { | 384 } else { |
359 in_buffer_size = (in_sample_rate / 100); | 385 in_buffer_size = (in_sample_rate / 100); |
| 386 DCHECK_EQ(in_buffer_size * 100, in_sample_rate) << |
| 387 "Sample rate not supported. Should have been caught in Init()."; |
360 } | 388 } |
361 | 389 |
362 // Render side: AUDIO_PCM_LOW_LATENCY is based on the Core Audio (WASAPI) | 390 // Render side: AUDIO_PCM_LOW_LATENCY is based on the Core Audio (WASAPI) |
363 // API which was introduced in Windows Vista. For lower Windows versions, | 391 // API which was introduced in Windows Vista. For lower Windows versions, |
364 // a callback-driven Wave implementation is used instead. An output buffer | 392 // a callback-driven Wave implementation is used instead. An output buffer |
365 // size of 10ms works well for WASAPI but 30ms is needed for Wave. | 393 // size of 10ms works well for WASAPI but 30ms is needed for Wave. |
366 | 394 |
367 // Use different buffer sizes depending on the current hardware sample rate. | 395 // Use different buffer sizes depending on the current hardware sample rate. |
368 if (out_sample_rate == 96000 || out_sample_rate == 48000) { | 396 if (out_sample_rate == 96000 || out_sample_rate == 48000) { |
369 out_buffer_size = (out_sample_rate / 100); | 397 out_buffer_size = (out_sample_rate / 100); |
(...skipping 24 matching lines...) Expand all Loading... |
394 // driven Core Audio implementation. Tests have shown that 10ms is a suitable | 422 // driven Core Audio implementation. Tests have shown that 10ms is a suitable |
395 // frame size to use, both for 48kHz and 44.1kHz. | 423 // frame size to use, both for 48kHz and 44.1kHz. |
396 | 424 |
397 // Use different buffer sizes depending on the current hardware sample rate. | 425 // Use different buffer sizes depending on the current hardware sample rate. |
398 if (in_sample_rate == 44100) { | 426 if (in_sample_rate == 44100) { |
399 // We do run at 44.1kHz at the actual audio layer, but ask for frames | 427 // We do run at 44.1kHz at the actual audio layer, but ask for frames |
400 // at 44.0kHz to ensure that we can feed them to the webrtc::VoiceEngine. | 428 // at 44.0kHz to ensure that we can feed them to the webrtc::VoiceEngine. |
401 in_buffer_size = 440; | 429 in_buffer_size = 440; |
402 } else { | 430 } else { |
403 in_buffer_size = (in_sample_rate / 100); | 431 in_buffer_size = (in_sample_rate / 100); |
| 432 DCHECK_EQ(in_buffer_size * 100, in_sample_rate) << |
| 433 "Sample rate not supported. Should have been caught in Init()."; |
404 } | 434 } |
405 | 435 |
406 // Render side: AUDIO_PCM_LOW_LATENCY on Mac OS X is based on a callback- | 436 // Render side: AUDIO_PCM_LOW_LATENCY on Mac OS X is based on a callback- |
407 // driven Core Audio implementation. Tests have shown that 10ms is a suitable | 437 // driven Core Audio implementation. Tests have shown that 10ms is a suitable |
408 // frame size to use, both for 48kHz and 44.1kHz. | 438 // frame size to use, both for 48kHz and 44.1kHz. |
409 | 439 |
410 // Use different buffer sizes depending on the current hardware sample rate. | 440 // Use different buffer sizes depending on the current hardware sample rate. |
411 if (out_sample_rate == 48000) { | 441 if (out_sample_rate == 48000) { |
412 out_buffer_size = 480; | 442 out_buffer_size = 480; |
413 } else { | 443 } else { |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 return 0; | 617 return 0; |
588 } | 618 } |
589 | 619 |
590 bool WebRtcAudioDeviceImpl::RecordingIsInitialized() const { | 620 bool WebRtcAudioDeviceImpl::RecordingIsInitialized() const { |
591 DVLOG(1) << "RecordingIsInitialized()"; | 621 DVLOG(1) << "RecordingIsInitialized()"; |
592 return (audio_input_device_ != NULL); | 622 return (audio_input_device_ != NULL); |
593 } | 623 } |
594 | 624 |
595 int32_t WebRtcAudioDeviceImpl::StartPlayout() { | 625 int32_t WebRtcAudioDeviceImpl::StartPlayout() { |
596 DVLOG(1) << "StartPlayout()"; | 626 DVLOG(1) << "StartPlayout()"; |
| 627 LOG_IF(ERROR, !audio_transport_callback_) << "Audio transport is missing"; |
597 if (!audio_transport_callback_) { | 628 if (!audio_transport_callback_) { |
598 LOG(ERROR) << "Audio transport is missing"; | |
599 return -1; | 629 return -1; |
600 } | 630 } |
601 if (playing_) { | 631 if (playing_) { |
602 // webrtc::VoiceEngine assumes that it is OK to call Start() twice and | 632 // webrtc::VoiceEngine assumes that it is OK to call Start() twice and |
603 // that the call is ignored the second time. | 633 // that the call is ignored the second time. |
604 return 0; | 634 return 0; |
605 } | 635 } |
606 audio_output_device_->Start(); | 636 audio_output_device_->Start(); |
607 playing_ = true; | 637 playing_ = true; |
608 return 0; | 638 return 0; |
(...skipping 11 matching lines...) Expand all Loading... |
620 } | 650 } |
621 | 651 |
622 bool WebRtcAudioDeviceImpl::Playing() const { | 652 bool WebRtcAudioDeviceImpl::Playing() const { |
623 return playing_; | 653 return playing_; |
624 } | 654 } |
625 | 655 |
626 int32_t WebRtcAudioDeviceImpl::StartRecording() { | 656 int32_t WebRtcAudioDeviceImpl::StartRecording() { |
627 DVLOG(1) << "StartRecording()"; | 657 DVLOG(1) << "StartRecording()"; |
628 LOG_IF(ERROR, !audio_transport_callback_) << "Audio transport is missing"; | 658 LOG_IF(ERROR, !audio_transport_callback_) << "Audio transport is missing"; |
629 if (!audio_transport_callback_) { | 659 if (!audio_transport_callback_) { |
630 LOG(ERROR) << "Audio transport is missing"; | |
631 return -1; | 660 return -1; |
632 } | 661 } |
633 | 662 |
634 if (session_id_ <= 0) { | 663 if (session_id_ <= 0) { |
635 LOG(WARNING) << session_id_ << " is an invalid session id."; | 664 LOG(WARNING) << session_id_ << " is an invalid session id."; |
636 // TODO(xians): enable the return -1 when MediaStreamManager can handle | 665 // TODO(xians): enable the return -1 when MediaStreamManager can handle |
637 // AudioInputDeviceManager. | 666 // AudioInputDeviceManager. |
638 // return -1; | 667 // return -1; |
639 } | 668 } |
640 | 669 |
(...skipping 27 matching lines...) Expand all Loading... |
668 base::AutoLock auto_lock(lock_); | 697 base::AutoLock auto_lock(lock_); |
669 recording_ = false; | 698 recording_ = false; |
670 return 0; | 699 return 0; |
671 } | 700 } |
672 | 701 |
673 bool WebRtcAudioDeviceImpl::Recording() const { | 702 bool WebRtcAudioDeviceImpl::Recording() const { |
674 return recording_; | 703 return recording_; |
675 } | 704 } |
676 | 705 |
677 int32_t WebRtcAudioDeviceImpl::SetAGC(bool enable) { | 706 int32_t WebRtcAudioDeviceImpl::SetAGC(bool enable) { |
678 DVLOG(2) << "WARNING: WebRtcAudioDeviceImpl::SetAGC() " << "NOT IMPLEMENTED"; | 707 DVLOG(1) << "SetAGC(enable=" << enable << ")"; |
679 return -1; | 708 // The current implementation does not support changing the AGC state while |
| 709 // recording. Using this approach simplifies the design and it is also |
| 710 // inline with the latest WebRTC standard. |
| 711 DCHECK(initialized_); |
| 712 DCHECK(!recording_) << "Unable to set AGC state while recording is active."; |
| 713 if (recording_) { |
| 714 return -1; |
| 715 } |
| 716 |
| 717 audio_input_device_->SetAutomaticGainControl(enable); |
| 718 agc_is_enabled_ = enable; |
| 719 return 0; |
680 } | 720 } |
681 | 721 |
682 bool WebRtcAudioDeviceImpl::AGC() const { | 722 bool WebRtcAudioDeviceImpl::AGC() const { |
683 DVLOG(2) << "WARNING: WebRtcAudioDeviceImpl::AGC() " << "NOT IMPLEMENTED"; | 723 // To reduce the usage of IPC messages, an internal AGC state is used. |
684 return false; | 724 // TODO(henrika): investigate if there is a need for a "deeper" getter. |
| 725 return agc_is_enabled_; |
685 } | 726 } |
686 | 727 |
687 int32_t WebRtcAudioDeviceImpl::SetWaveOutVolume(uint16_t volume_left, | 728 int32_t WebRtcAudioDeviceImpl::SetWaveOutVolume(uint16_t volume_left, |
688 uint16_t volume_right) { | 729 uint16_t volume_right) { |
689 NOTIMPLEMENTED(); | 730 NOTIMPLEMENTED(); |
690 return -1; | 731 return -1; |
691 } | 732 } |
692 int32_t WebRtcAudioDeviceImpl::WaveOutVolume( | 733 int32_t WebRtcAudioDeviceImpl::WaveOutVolume( |
693 uint16_t* volume_left, | 734 uint16_t* volume_left, |
694 uint16_t* volume_right) const { | 735 uint16_t* volume_right) const { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
747 int32_t WebRtcAudioDeviceImpl::SpeakerVolume(uint32_t* volume) const { | 788 int32_t WebRtcAudioDeviceImpl::SpeakerVolume(uint32_t* volume) const { |
748 NOTIMPLEMENTED(); | 789 NOTIMPLEMENTED(); |
749 return -1; | 790 return -1; |
750 } | 791 } |
751 | 792 |
752 int32_t WebRtcAudioDeviceImpl::MaxSpeakerVolume(uint32_t* max_volume) const { | 793 int32_t WebRtcAudioDeviceImpl::MaxSpeakerVolume(uint32_t* max_volume) const { |
753 NOTIMPLEMENTED(); | 794 NOTIMPLEMENTED(); |
754 return -1; | 795 return -1; |
755 } | 796 } |
756 | 797 |
757 int32_t WebRtcAudioDeviceImpl::MinSpeakerVolume( | 798 int32_t WebRtcAudioDeviceImpl::MinSpeakerVolume(uint32_t* min_volume) const { |
758 uint32_t* min_volume) const { | |
759 NOTIMPLEMENTED(); | 799 NOTIMPLEMENTED(); |
760 return -1; | 800 return -1; |
761 } | 801 } |
762 | 802 |
763 int32_t WebRtcAudioDeviceImpl::SpeakerVolumeStepSize( | 803 int32_t WebRtcAudioDeviceImpl::SpeakerVolumeStepSize( |
764 uint16_t* step_size) const { | 804 uint16_t* step_size) const { |
765 NOTIMPLEMENTED(); | 805 NOTIMPLEMENTED(); |
766 return -1; | 806 return -1; |
767 } | 807 } |
768 | 808 |
769 int32_t WebRtcAudioDeviceImpl::MicrophoneVolumeIsAvailable(bool* available) { | 809 int32_t WebRtcAudioDeviceImpl::MicrophoneVolumeIsAvailable(bool* available) { |
770 NOTIMPLEMENTED(); | 810 NOTIMPLEMENTED(); |
771 return -1; | 811 return -1; |
772 } | 812 } |
773 | 813 |
774 int32_t WebRtcAudioDeviceImpl::SetMicrophoneVolume(uint32_t volume) { | 814 int32_t WebRtcAudioDeviceImpl::SetMicrophoneVolume(uint32_t volume) { |
775 NOTIMPLEMENTED(); | 815 DVLOG(1) << "SetMicrophoneVolume(" << volume << ")"; |
| 816 if (volume > kMaxVolumeLevel) |
| 817 return -1; |
| 818 |
| 819 // WebRTC uses a range of [0, 255] to represent the level of the microphone |
| 820 // volume. The IPC channel between the renderer and browser process works |
| 821 // with doubles in the [0.0, 1.0] range and we have to compensate for that. |
| 822 double normalized_volume = static_cast<double>(volume / kMaxVolumeLevel); |
| 823 audio_input_device_->SetVolume(normalized_volume); |
| 824 return 0; |
| 825 } |
| 826 |
| 827 int32_t WebRtcAudioDeviceImpl::MicrophoneVolume(uint32_t* volume) const { |
| 828 // The microphone level is fed to this class using the Capture() callback |
| 829 // and this external API should not be used. Additional IPC messages are |
| 830 // required if support for this API is ever needed. |
| 831 NOTREACHED(); |
776 return -1; | 832 return -1; |
777 } | 833 } |
778 | 834 |
779 int32_t WebRtcAudioDeviceImpl::MicrophoneVolume(uint32_t* volume) const { | 835 int32_t WebRtcAudioDeviceImpl::MaxMicrophoneVolume(uint32_t* max_volume) const { |
780 NOTIMPLEMENTED(); | 836 *max_volume = kMaxVolumeLevel; |
781 return -1; | 837 return 0; |
782 } | 838 } |
783 | 839 |
784 int32_t WebRtcAudioDeviceImpl::MaxMicrophoneVolume( | 840 int32_t WebRtcAudioDeviceImpl::MinMicrophoneVolume(uint32_t* min_volume) const { |
785 uint32_t* max_volume) const { | 841 *min_volume = 0; |
786 DVLOG(2) << "WARNING: WebRtcAudioDeviceImpl::MaxMicrophoneVolume() " | 842 return 0; |
787 << "NOT IMPLEMENTED"; | |
788 return -1; | |
789 } | |
790 | |
791 int32_t WebRtcAudioDeviceImpl::MinMicrophoneVolume( | |
792 uint32_t* min_volume) const { | |
793 DVLOG(2) << "WARNING: WebRtcAudioDeviceImpl::MinMicrophoneVolume() " | |
794 << "NOT IMPLEMENTED"; | |
795 return -1; | |
796 } | 843 } |
797 | 844 |
798 int32_t WebRtcAudioDeviceImpl::MicrophoneVolumeStepSize( | 845 int32_t WebRtcAudioDeviceImpl::MicrophoneVolumeStepSize( |
799 uint16_t* step_size) const { | 846 uint16_t* step_size) const { |
800 NOTIMPLEMENTED(); | 847 NOTREACHED(); |
801 return -1; | 848 return -1; |
802 } | 849 } |
803 | 850 |
804 int32_t WebRtcAudioDeviceImpl::SpeakerMuteIsAvailable(bool* available) { | 851 int32_t WebRtcAudioDeviceImpl::SpeakerMuteIsAvailable(bool* available) { |
805 NOTIMPLEMENTED(); | 852 NOTIMPLEMENTED(); |
806 return -1; | 853 return -1; |
807 } | 854 } |
808 | 855 |
809 int32_t WebRtcAudioDeviceImpl::SetSpeakerMute(bool enable) { | 856 int32_t WebRtcAudioDeviceImpl::SetSpeakerMute(bool enable) { |
810 NOTIMPLEMENTED(); | 857 NOTIMPLEMENTED(); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
988 } | 1035 } |
989 | 1036 |
990 int32_t WebRtcAudioDeviceImpl::GetLoudspeakerStatus(bool* enabled) const { | 1037 int32_t WebRtcAudioDeviceImpl::GetLoudspeakerStatus(bool* enabled) const { |
991 NOTIMPLEMENTED(); | 1038 NOTIMPLEMENTED(); |
992 return -1; | 1039 return -1; |
993 } | 1040 } |
994 | 1041 |
995 void WebRtcAudioDeviceImpl::SetSessionId(int session_id) { | 1042 void WebRtcAudioDeviceImpl::SetSessionId(int session_id) { |
996 session_id_ = session_id; | 1043 session_id_ = session_id; |
997 } | 1044 } |
OLD | NEW |