webrtc_audio_device_impl.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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" 11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/renderer/media/media_stream_audio_processor.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/renderer/media/webrtc_audio_capturer.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/renderer/media/webrtc_audio_renderer.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/render_thread_impl.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_parameters.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)WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl() 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : ref_count_(0), 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_transport_callback_(NULL), 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_delay_ms_(0), 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_delay_ms_(0), 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized_(false), 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) playing_(false), 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recording_(false), 31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) microphone_volume_(0), 32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) is_audio_track_processing_enabled_( 33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled()) { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()"; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl() { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl()"; 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Terminate(); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::AddRef() { 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::subtle::Barrier_AtomicIncrement(&ref_count_, 1); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::Release() { 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ret = base::subtle::Barrier_AtomicIncrement(&ref_count_, -1); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret == 0) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)int WebRtcAudioDeviceImpl::OnData(const int16* audio_data, 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int sample_rate, 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int number_of_channels, 59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int number_of_frames, 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<int>& channels, 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int audio_delay_milliseconds, 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int current_volume, 63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool need_audio_processing, 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool key_pressed) { 65bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch int total_delay_ms = 0; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 68424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Return immediately when not recording or |channels| is empty. 69424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // See crbug.com/274017: renderer crash dereferencing invalid channels[0]. 70424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!recording_ || channels.empty()) 71bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch return 0; 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Store the reported audio delay locally. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_delay_ms_ = audio_delay_milliseconds; 75bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch total_delay_ms = input_delay_ms_ + output_delay_ms_; 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DVLOG(2) << "total delay: " << input_delay_ms_ + output_delay_ms_; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Write audio frames in blocks of 10 milliseconds to the registered 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // webrtc::AudioTransport sink. Keep writing until our internal byte 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // buffer is empty. 82bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch const int16* audio_buffer = audio_data; 83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const int frames_per_10_ms = (sample_rate / 100); 84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CHECK_EQ(number_of_frames % frames_per_10_ms, 0); 85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int accumulated_audio_frames = 0; 86bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch uint32_t new_volume = 0; 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The lock here is to protect a race in the resampler inside webrtc when 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // there are more than one input stream calling OnData(), which can happen 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // when the users setup two getUserMedia, one for the microphone, another 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // for WebAudio. Currently we don't have a better way to fix it except for 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // adding a lock here to sequence the call. 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(xians): Remove this workaround after we move the 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // webrtc::AudioProcessing module to Chrome. See http://crbug/264611 for 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // details. 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::AutoLock auto_lock(capture_callback_lock_); 97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) while (accumulated_audio_frames < number_of_frames) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Deliver 10ms of recorded 16-bit linear PCM audio. 99bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch int new_mic_level = audio_transport_callback_->OnDataAvailable( 100bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch &channels[0], 101bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch channels.size(), 102bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch audio_buffer, 103bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch sample_rate, 104bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch number_of_channels, 105010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) frames_per_10_ms, 106bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch total_delay_ms, 107bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch current_volume, 108b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) key_pressed, 109bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch need_audio_processing); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) accumulated_audio_frames += frames_per_10_ms; 112010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) audio_buffer += frames_per_10_ms * number_of_channels; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 114bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // The latest non-zero new microphone level will be returned. 115bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch if (new_mic_level) 116bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch new_volume = new_mic_level; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 118bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 119bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch return new_volume; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void WebRtcAudioDeviceImpl::OnSetFormat( 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const media::AudioParameters& params) { 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::OnSetFormat()"; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WebRtcAudioDeviceImpl::RenderData(media::AudioBus* audio_bus, 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int sample_rate, 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int audio_delay_milliseconds) { 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) render_buffer_.resize(audio_bus->frames() * audio_bus->channels()); 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock auto_lock(lock_); 13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(audio_transport_callback_); 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Store the reported audio delay locally. 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_delay_ms_ = audio_delay_milliseconds; 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int frames_per_10_ms = (sample_rate / 100); 140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int bytes_per_sample = sizeof(render_buffer_[0]); 141010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const int bytes_per_10_ms = 142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) audio_bus->channels() * frames_per_10_ms * bytes_per_sample; 143010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_EQ(audio_bus->frames() % frames_per_10_ms, 0); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Get audio frames in blocks of 10 milliseconds from the registered 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // webrtc::AudioTransport source. Keep reading until our internal buffer 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // is full. 148010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) uint32_t num_audio_frames = 0; 149010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int accumulated_audio_frames = 0; 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int16* audio_data = &render_buffer_[0]; 151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) while (accumulated_audio_frames < audio_bus->frames()) { 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Get 10ms and append output to temporary byte buffer. 15346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int64_t elapsed_time_ms = -1; 15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int64_t ntp_time_ms = -1; 155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (is_audio_track_processing_enabled_) { 156010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // When audio processing is enabled in the audio track, we use 157010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // PullRenderData() instead of NeedMorePlayData() to avoid passing the 158010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // render data to the APM in WebRTC as reference signal for echo 159010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // cancellation. 160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) static const int kBitsPerByte = 8; 161010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) audio_transport_callback_->PullRenderData(bytes_per_sample * kBitsPerByte, 162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) sample_rate, 163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) audio_bus->channels(), 164010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) frames_per_10_ms, 165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) audio_data, 16646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) &elapsed_time_ms, 16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) &ntp_time_ms); 168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) accumulated_audio_frames += frames_per_10_ms; 169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } else { 170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // TODO(xians): Remove the following code after the APM in WebRTC is 171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // deprecated. 172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) audio_transport_callback_->NeedMorePlayData(frames_per_10_ms, 173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bytes_per_sample, 174010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) audio_bus->channels(), 175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) sample_rate, 176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) audio_data, 177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) num_audio_frames, 17846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) &elapsed_time_ms, 17946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) &ntp_time_ms); 180010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) accumulated_audio_frames += num_audio_frames; 181010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 183010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) audio_data += bytes_per_10_ms; 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // De-interleave each channel and convert to 32-bit floating-point 187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // with nominal range -1.0 -> +1.0 to match the callback format. 188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_bus->FromInterleaved(&render_buffer_[0], 189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_bus->frames(), 190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bytes_per_sample); 191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Pass the render data to the playout sinks. 193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::AutoLock auto_lock(lock_); 194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (PlayoutDataSinkList::const_iterator it = playout_sinks_.begin(); 195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) it != playout_sinks_.end(); ++it) { 196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (*it)->OnPlayoutData(audio_bus, sample_rate, audio_delay_milliseconds); 197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRtcAudioDeviceImpl::RemoveAudioRenderer(WebRtcAudioRenderer* renderer) { 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(renderer, renderer_); 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock auto_lock(lock_); 204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Notify the playout sink of the change. 205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (PlayoutDataSinkList::const_iterator it = playout_sinks_.begin(); 206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) it != playout_sinks_.end(); ++it) { 207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (*it)->OnPlayoutDataSourceChanged(); 208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) renderer_ = NULL; 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) playing_ = false; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::RegisterAudioCallback( 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) webrtc::AudioTransport* audio_callback) { 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::RegisterAudioCallback()"; 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(audio_transport_callback_ == NULL, audio_callback != NULL); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_transport_callback_ = audio_callback; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::Init() { 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::Init()"; 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We need to return a success to continue the initialization of WebRtc VoE 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // because failure on the capturer_ initialization should not prevent WebRTC 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // from working. See issue http://crbug.com/144421 for details. 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized_ = true; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::Terminate() { 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::Terminate()"; 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Calling Terminate() multiple times in a row is OK. 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!initialized_) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopRecording(); 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StopPlayout(); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(!renderer_.get() || !renderer_->IsStarted()) 24758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) << "The shared audio renderer shouldn't be running"; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DisableAecDump(); 250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 251bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch capturers_.clear(); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized_ = false; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRtcAudioDeviceImpl::Initialized() const { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return initialized_; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::PlayoutIsAvailable(bool* available) { 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *available = initialized_; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRtcAudioDeviceImpl::PlayoutIsInitialized() const { 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return initialized_; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::RecordingIsAvailable(bool* available) { 271bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch *available = (!capturers_.empty()); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRtcAudioDeviceImpl::RecordingIsInitialized() const { 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::RecordingIsInitialized()"; 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 278bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch return (!capturers_.empty()); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::StartPlayout() { 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::StartPlayout()"; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_IF(ERROR, !audio_transport_callback_) << "Audio transport is missing"; 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock auto_lock(lock_); 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!audio_transport_callback_) 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (playing_) { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // webrtc::VoiceEngine assumes that it is OK to call Start() twice and 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that the call is ignored the second time. 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) playing_ = true; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::StopPlayout() { 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::StopPlayout()"; 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!playing_) { 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // webrtc::VoiceEngine assumes that it is OK to call Stop() just in case. 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) playing_ = false; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRtcAudioDeviceImpl::Playing() const { 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return playing_; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::StartRecording() { 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::StartRecording()"; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(initialized_); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_IF(ERROR, !audio_transport_callback_) << "Audio transport is missing"; 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!audio_transport_callback_) { 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) { 3247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::AutoLock auto_lock(lock_); 3257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (recording_) 3267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return 0; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) recording_ = true; 3297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 3307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::StopRecording() { 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::StopRecording()"; 3367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) { 3377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::AutoLock auto_lock(lock_); 3387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!recording_) 3397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return 0; 3407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) recording_ = false; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRtcAudioDeviceImpl::Recording() const { 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock auto_lock(lock_); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return recording_; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::SetMicrophoneVolume(uint32_t volume) { 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::SetMicrophoneVolume(" << volume << ")"; 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(initialized_); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 356bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Only one microphone is supported at the moment, which is represented by 357bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // the default capturer. 358bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer()); 359bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch if (!capturer.get()) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 362bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch capturer->SetVolume(volume); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(henrika): sort out calling thread once we start using this API. 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::MicrophoneVolume(uint32_t* volume) const { 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::MicrophoneVolume()"; 369bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // We only support one microphone now, which is accessed via the default 370bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // capturer. 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(initialized_); 372bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer()); 373bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch if (!capturer.get()) 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return -1; 375bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 376bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch *volume = static_cast<uint32_t>(capturer->Volume()); 3770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::MaxMicrophoneVolume(uint32_t* max_volume) const { 382bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch DCHECK(initialized_); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *max_volume = kMaxVolumeLevel; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::MinMicrophoneVolume(uint32_t* min_volume) const { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *min_volume = 0; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::StereoPlayoutIsAvailable(bool* available) const { 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(initialized_); 394a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *available = renderer_ && renderer_->channels() == 2; 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::StereoRecordingIsAvailable( 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool* available) const { 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(initialized_); 401bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // TODO(xians): These kind of hardware methods do not make much sense since we 402bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // support multiple sources. Remove or figure out new APIs for such methods. 403bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer()); 404bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch if (!capturer.get()) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 406bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *available = (capturer->source_audio_parameters().channels() == 2); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::PlayoutDelay(uint16_t* delay_ms) const { 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *delay_ms = static_cast<uint16_t>(output_delay_ms_); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::RecordingDelay(uint16_t* delay_ms) const { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *delay_ms = static_cast<uint16_t>(input_delay_ms_); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::RecordingSampleRate( 424010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) uint32_t* sample_rate) const { 425bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // We use the default capturer as the recording sample rate. 426bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer()); 427bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch if (!capturer.get()) 428bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch return -1; 429bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 430010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) *sample_rate = static_cast<uint32_t>( 4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) capturer->source_audio_parameters().sample_rate()); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::PlayoutSampleRate( 436010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) uint32_t* sample_rate) const { 437010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) *sample_rate = renderer_ ? renderer_->sample_rate() : 0; 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool WebRtcAudioDeviceImpl::SetAudioRenderer(WebRtcAudioRenderer* renderer) { 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(renderer); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 446868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (renderer_.get()) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!renderer->Initialize(this)) 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) renderer_ = renderer; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 456bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochvoid WebRtcAudioDeviceImpl::AddAudioCapturer( 457bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch const scoped_refptr<WebRtcAudioCapturer>& capturer) { 458bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()"; 459bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 460bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch DCHECK(capturer.get()); 4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!capturer->device_id().empty()); 462a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) { 463a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::AutoLock auto_lock(lock_); 464a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(std::find(capturers_.begin(), capturers_.end(), capturer) == 465a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) capturers_.end()); 466a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) capturers_.push_back(capturer); 467a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 468a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 469a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Start the Aec dump if the Aec dump has been enabled and has not been 470a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // started. 4710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (aec_dump_file_.IsValid()) 472a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MaybeStartAecDump(); 473bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch} 474bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRtcAudioDeviceImpl::RemoveAudioCapturer( 4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<WebRtcAudioCapturer>& capturer) { 4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()"; 4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(capturer.get()); 4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::AutoLock auto_lock(lock_); 4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) capturers_.remove(capturer); 4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 484bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochscoped_refptr<WebRtcAudioCapturer> 485bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben MurdochWebRtcAudioDeviceImpl::GetDefaultCapturer() const { 486bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch base::AutoLock auto_lock(lock_); 4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Use the last |capturer| which is from the latest getUserMedia call as 4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the default capture device. 48923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return capturers_.empty() ? NULL : capturers_.back(); 490bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch} 491bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 492a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WebRtcAudioDeviceImpl::AddPlayoutSink( 493a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) WebRtcPlayoutDataSource::Sink* sink) { 494a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 495a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(sink); 496a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::AutoLock auto_lock(lock_); 497a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(std::find(playout_sinks_.begin(), playout_sinks_.end(), sink) == 498a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) playout_sinks_.end()); 499a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) playout_sinks_.push_back(sink); 500a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 501a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 502a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WebRtcAudioDeviceImpl::RemovePlayoutSink( 503a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) WebRtcPlayoutDataSource::Sink* sink) { 504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(sink); 506a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::AutoLock auto_lock(lock_); 507a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) playout_sinks_.remove(sink); 508a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 509a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool WebRtcAudioDeviceImpl::GetAuthorizedDeviceInfoForAudioRenderer( 5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int* session_id, 5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int* output_sample_rate, 5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int* output_frames_per_buffer) { 5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If there is no capturer or there are more than one open capture devices, 5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // return false. 5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (capturers_.empty() || capturers_.size() > 1) 5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return GetDefaultCapturer()->GetPairedOutputParameters( 5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) session_id, output_sample_rate, output_frames_per_buffer); 5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid WebRtcAudioDeviceImpl::EnableAecDump(base::File aec_dump_file) { 525a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 5260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(aec_dump_file.IsValid()); 52746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 52846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Close the previous AEC dump file description if it has not been consumed. 52946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // This can happen if no getUserMedia has been made yet. 53046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // TODO(xians): DCHECK(!aec_dump_file_.IsValid()) after the browser 53146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // guarantees it won't call EnableAecDump() more than once in a row. 53246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (aec_dump_file_.IsValid()) 53346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) aec_dump_file_.Close(); 53446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 5350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch aec_dump_file_ = aec_dump_file.Pass(); 536a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MaybeStartAecDump(); 537a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 538a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 539a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WebRtcAudioDeviceImpl::DisableAecDump() { 540a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 541a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Simply invalidate the |aec_dump_file_| if we have not pass the ownership 542a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // to WebRtc. 5430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (aec_dump_file_.IsValid()) { 5440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch aec_dump_file_.Close(); 545a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 546a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 547a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 548a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // We might have call StartAecDump() on one of the capturer. Loop 549a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // through all the capturers and call StopAecDump() on each of them. 550a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (CapturerList::const_iterator iter = capturers_.begin(); 551a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) iter != capturers_.end(); ++iter) { 552a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (*iter)->StopAecDump(); 553a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 554a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 555a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 556a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WebRtcAudioDeviceImpl::MaybeStartAecDump() { 557a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 5580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(aec_dump_file_.IsValid()); 559a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 560a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Start the Aec dump on the current default capturer. 561a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<WebRtcAudioCapturer> default_capturer(GetDefaultCapturer()); 562a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!default_capturer) 563a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 564a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 5650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch default_capturer->StartAecDump(aec_dump_file_.Pass()); 566a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 567a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 569