webrtc_audio_device_impl.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/media/webrtc_audio_device_impl.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/renderer/media/webrtc_audio_capturer.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/renderer/media/webrtc_audio_renderer.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/render_thread_impl.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_parameters.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_util.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/sample_rates.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using media::AudioParameters; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using media::ChannelLayout; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const double kMaxVolumeLevel = 255.0; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl() 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : ref_count_(0), 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_transport_callback_(NULL), 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_delay_ms_(0), 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_delay_ms_(0), 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized_(false), 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) playing_(false), 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recording_(false), 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) agc_is_enabled_(false), 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) microphone_volume_(0) { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()"; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl() { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl()"; 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Terminate(); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::AddRef() { 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::subtle::Barrier_AtomicIncrement(&ref_count_, 1); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::Release() { 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ret = base::subtle::Barrier_AtomicIncrement(&ref_count_, -1); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret == 0) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRtcAudioDeviceImpl::CaptureData(const int16* audio_data, 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int number_of_channels, 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int number_of_frames, 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int audio_delay_milliseconds, 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) double volume) { 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_LE(number_of_frames, input_buffer_size()); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) || defined(OS_MACOSX) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(volume, 1.0); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_LINUX) || defined(OS_OPENBSD) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have a special situation on Linux where the microphone volume can be 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "higher than maximum". The input volume slider in the sound preference 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // allows the user to set a scaling that is higher than 100%. It means that 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // even if the reported maximum levels is N, the actual microphone level can 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // go up to 1.5x*N and that corresponds to a normalized |volume| of 1.5x. 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_LE(volume, 1.6); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) media::AudioParameters input_audio_parameters; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int output_delay_ms = 0; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!recording_) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Take a copy of the input parameters while we are under a lock. 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_audio_parameters = input_audio_parameters_; 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Store the reported audio delay locally. 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_delay_ms_ = audio_delay_milliseconds; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_delay_ms = output_delay_ms_; 9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DVLOG(2) << "total delay: " << input_delay_ms_ + output_delay_ms_; 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Map internal volume range of [0.0, 1.0] into [0, 255] used by the 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // webrtc::VoiceEngine. 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) microphone_volume_ = static_cast<uint32_t>(volume * kMaxVolumeLevel); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int channels = number_of_channels; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(channels, input_channels()); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t new_mic_level = 0; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int samples_per_sec = input_sample_rate(); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int samples_per_10_msec = (samples_per_sec / 100); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int bytes_per_sample = input_audio_parameters.bits_per_sample() / 8; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int bytes_per_10_msec = 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) channels * samples_per_10_msec * bytes_per_sample; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int accumulated_audio_samples = 0; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const uint8* audio_byte_buffer = reinterpret_cast<const uint8*>(audio_data); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write audio samples in blocks of 10 milliseconds to the registered 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // webrtc::AudioTransport sink. Keep writing until our internal byte 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // buffer is empty. 115b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // TODO(niklase): Wire up the key press detection. 116b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) bool key_pressed = false; 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (accumulated_audio_samples < number_of_frames) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Deliver 10ms of recorded 16-bit linear PCM audio. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_transport_callback_->RecordedDataIsAvailable( 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_byte_buffer, 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) samples_per_10_msec, 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bytes_per_sample, 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channels, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) samples_per_sec, 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_delay_ms_ + output_delay_ms, 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, // TODO(henrika): |clock_drift| parameter is not utilized today. 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) microphone_volume_, 128b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) key_pressed, 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_mic_level); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accumulated_audio_samples += samples_per_10_msec; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_byte_buffer += bytes_per_10_msec; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The AGC returns a non-zero microphone level if it has been decided 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that a new level should be set. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_mic_level != 0) { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use IPC and set the new level. Note that, it will take some time 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // before the new level is effective due to the IPC scheme. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // During this time, |current_mic_level| will contain "non-valid" values 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and it might reduce the AGC performance. Measurements on Windows 7 have 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // shown that we might receive old volume levels for one or two callbacks. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetMicrophoneVolume(new_mic_level); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRtcAudioDeviceImpl::SetCaptureFormat( 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const media::AudioParameters& params) { 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::SetCaptureFormat()"; 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) input_audio_parameters_ = params; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRtcAudioDeviceImpl::RenderData(uint8* audio_data, 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int number_of_channels, 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int number_of_frames, 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int audio_delay_milliseconds) { 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_LE(number_of_frames, output_buffer_size()); 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock auto_lock(lock_); 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Store the reported audio delay locally. 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_delay_ms_ = audio_delay_milliseconds; 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int channels = number_of_channels; 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_LE(channels, output_channels()); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int samples_per_sec = output_sample_rate(); 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int samples_per_10_msec = (samples_per_sec / 100); 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int bytes_per_sample = output_audio_parameters_.bits_per_sample() / 8; 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int bytes_per_10_msec = 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) channels * samples_per_10_msec * bytes_per_sample; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t num_audio_samples = 0; 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int accumulated_audio_samples = 0; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Get audio samples in blocks of 10 milliseconds from the registered 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // webrtc::AudioTransport source. Keep reading until our internal buffer 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // is full. 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (accumulated_audio_samples < number_of_frames) { 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Get 10ms and append output to temporary byte buffer. 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_transport_callback_->NeedMorePlayData(samples_per_10_msec, 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bytes_per_sample, 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) channels, 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) samples_per_sec, 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_data, 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) num_audio_samples); 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) accumulated_audio_samples += num_audio_samples; 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_data += bytes_per_10_msec; 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRtcAudioDeviceImpl::SetRenderFormat(const AudioParameters& params) { 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_audio_parameters_ = params; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRtcAudioDeviceImpl::RemoveAudioRenderer(WebRtcAudioRenderer* renderer) { 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(renderer, renderer_); 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock auto_lock(lock_); 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) renderer_ = NULL; 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) playing_ = false; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::RegisterAudioCallback( 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) webrtc::AudioTransport* audio_callback) { 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::RegisterAudioCallback()"; 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(audio_transport_callback_ == NULL, audio_callback != NULL); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_transport_callback_ = audio_callback; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::Init() { 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::Init()"; 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (initialized_) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!capturer_.get()); 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) capturer_ = WebRtcAudioCapturer::CreateCapturer(); 2257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Add itself as an audio track to the |capturer_|. This is because WebRTC 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // supports only one ADM but multiple audio tracks, so the ADM can't be the 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // sink of certain audio track now. 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // TODO(xians): Register the ADM as the sink of the audio track if WebRTC 2307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // supports one ADM for each audio track. See http://crbug/247027. 2317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) capturer_->SetDefaultSink(this); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We need to return a success to continue the initialization of WebRtc VoE 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // because failure on the capturer_ initialization should not prevent WebRTC 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // from working. See issue http://crbug.com/144421 for details. 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized_ = true; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::Terminate() { 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::Terminate()"; 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Calling Terminate() multiple times in a row is OK. 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!initialized_) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopRecording(); 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StopPlayout(); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // It is necessary to stop the |renderer_| before going away. 253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (renderer_.get()) { 25490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Grab a local reference while we call Stop(), which will trigger a call to 25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // RemoveAudioRenderer that clears our reference to the audio renderer. 25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_refptr<WebRtcAudioRenderer> local_renderer(renderer_); 25790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) local_renderer->Stop(); 258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!renderer_.get()); 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (capturer_.get()) { 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |capturer_| is stopped by the media stream, so do not need to 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // call Stop() here. 2647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) capturer_->SetDefaultSink(NULL); 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) capturer_ = NULL; 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized_ = false; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRtcAudioDeviceImpl::Initialized() const { 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return initialized_; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::PlayoutIsAvailable(bool* available) { 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *available = initialized_; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRtcAudioDeviceImpl::PlayoutIsInitialized() const { 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return initialized_; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::RecordingIsAvailable(bool* available) { 286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *available = (capturer_.get() != NULL); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRtcAudioDeviceImpl::RecordingIsInitialized() const { 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::RecordingIsInitialized()"; 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return (capturer_.get() != NULL); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::StartPlayout() { 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::StartPlayout()"; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_IF(ERROR, !audio_transport_callback_) << "Audio transport is missing"; 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock auto_lock(lock_); 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!audio_transport_callback_) 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (playing_) { 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // webrtc::VoiceEngine assumes that it is OK to call Start() twice and 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that the call is ignored the second time. 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) playing_ = true; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_render_time_ = base::Time::Now(); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::StopPlayout() { 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::StopPlayout()"; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!playing_) { 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // webrtc::VoiceEngine assumes that it is OK to call Stop() just in case. 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add histogram data to be uploaded as part of an UMA logging event. 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This histogram keeps track of total playout times. 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!start_render_time_.is_null()) { 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta render_time = base::Time::Now() - start_render_time_; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_LONG_TIMES("WebRTC.AudioRenderTime", render_time); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) playing_ = false; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRtcAudioDeviceImpl::Playing() const { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return playing_; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::StartRecording() { 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::StartRecording()"; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(initialized_); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_IF(ERROR, !audio_transport_callback_) << "Audio transport is missing"; 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!audio_transport_callback_) { 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) { 3477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::AutoLock auto_lock(lock_); 3487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (recording_) 3497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return 0; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) recording_ = true; 3527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 3537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) start_capture_time_ = base::Time::Now(); 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::StopRecording() { 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::StopRecording()"; 3617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) { 3627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::AutoLock auto_lock(lock_); 3637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!recording_) 3647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return 0; 3657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) recording_ = false; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add histogram data to be uploaded as part of an UMA logging event. 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This histogram keeps track of total recording times. 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!start_capture_time_.is_null()) { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta capture_time = base::Time::Now() - start_capture_time_; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_LONG_TIMES("WebRTC.AudioCaptureTime", capture_time); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRtcAudioDeviceImpl::Recording() const { 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock auto_lock(lock_); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return recording_; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::SetAGC(bool enable) { 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::SetAGC(enable=" << enable << ")"; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(initialized_); 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Return early if we are not changing the AGC state. 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (enable == agc_is_enabled_) 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The current implementation does not support changing the AGC state while 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // recording. Using this approach simplifies the design and it is also 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // inline with the latest WebRTC standard. 395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!capturer_.get() || capturer_->is_recording()) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) capturer_->SetAutomaticGainControl(enable); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) agc_is_enabled_ = enable; 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRtcAudioDeviceImpl::AGC() const { 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::AGC()"; 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To reduce the usage of IPC messages, an internal AGC state is used. 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(henrika): investigate if there is a need for a "deeper" getter. 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return agc_is_enabled_; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::SetMicrophoneVolume(uint32_t volume) { 4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::SetMicrophoneVolume(" << volume << ")"; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(initialized_); 414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!capturer_.get()) 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (volume > kMaxVolumeLevel) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // WebRTC uses a range of [0, 255] to represent the level of the microphone 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // volume. The IPC channel between the renderer and browser process works 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with doubles in the [0.0, 1.0] range and we have to compensate for that. 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) double normalized_volume = static_cast<double>(volume) / kMaxVolumeLevel; 4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) capturer_->SetVolume(normalized_volume); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(henrika): sort out calling thread once we start using this API. 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::MicrophoneVolume(uint32_t* volume) const { 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::MicrophoneVolume()"; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The microphone level is fed to this class using the Capture() callback 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and cached in the same method, i.e. we don't ask the native audio layer 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // for the actual micropone level here. 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(initialized_); 435868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!capturer_.get()) 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return -1; 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock auto_lock(lock_); 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *volume = microphone_volume_; 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::MaxMicrophoneVolume(uint32_t* max_volume) const { 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *max_volume = kMaxVolumeLevel; 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::MinMicrophoneVolume(uint32_t* min_volume) const { 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *min_volume = 0; 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::StereoPlayoutIsAvailable(bool* available) const { 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(initialized_); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *available = (output_channels() == 2); 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::StereoRecordingIsAvailable( 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool* available) const { 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(initialized_); 461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!capturer_.get()) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *available = (input_channels() == 2); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::PlayoutDelay(uint16_t* delay_ms) const { 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *delay_ms = static_cast<uint16_t>(output_delay_ms_); 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::RecordingDelay(uint16_t* delay_ms) const { 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *delay_ms = static_cast<uint16_t>(input_delay_ms_); 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::RecordingSampleRate( 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t* samples_per_sec) const { 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *samples_per_sec = static_cast<uint32_t>(input_sample_rate()); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::PlayoutSampleRate( 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t* samples_per_sec) const { 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *samples_per_sec = static_cast<uint32_t>(output_sample_rate()); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool WebRtcAudioDeviceImpl::SetAudioRenderer(WebRtcAudioRenderer* renderer) { 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(renderer); 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (renderer_.get()) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!renderer->Initialize(this)) 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) renderer_ = renderer; 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 507