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, 129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int audio_delay_milliseconds, 130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) base::TimeDelta* current_time) { 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) render_buffer_.resize(audio_bus->frames() * audio_bus->channels()); 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock auto_lock(lock_); 13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(audio_transport_callback_); 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Store the reported audio delay locally. 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_delay_ms_ = audio_delay_milliseconds; 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int frames_per_10_ms = (sample_rate / 100); 141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int bytes_per_sample = sizeof(render_buffer_[0]); 142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const int bytes_per_10_ms = 143010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) audio_bus->channels() * frames_per_10_ms * bytes_per_sample; 144010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK_EQ(audio_bus->frames() % frames_per_10_ms, 0); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 146010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Get audio frames in blocks of 10 milliseconds from the registered 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // webrtc::AudioTransport source. Keep reading until our internal buffer 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // is full. 149010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) uint32_t num_audio_frames = 0; 150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) int accumulated_audio_frames = 0; 151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int16* audio_data = &render_buffer_[0]; 152010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) while (accumulated_audio_frames < audio_bus->frames()) { 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Get 10ms and append output to temporary byte buffer. 15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int64_t elapsed_time_ms = -1; 15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int64_t ntp_time_ms = -1; 156010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (is_audio_track_processing_enabled_) { 157010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // When audio processing is enabled in the audio track, we use 158010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // PullRenderData() instead of NeedMorePlayData() to avoid passing the 159010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // render data to the APM in WebRTC as reference signal for echo 160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // cancellation. 161010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) static const int kBitsPerByte = 8; 162010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) audio_transport_callback_->PullRenderData(bytes_per_sample * kBitsPerByte, 163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) sample_rate, 164010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) audio_bus->channels(), 165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) frames_per_10_ms, 166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) audio_data, 16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) &elapsed_time_ms, 16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) &ntp_time_ms); 169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) accumulated_audio_frames += frames_per_10_ms; 170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } else { 171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // TODO(xians): Remove the following code after the APM in WebRTC is 172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // deprecated. 173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) audio_transport_callback_->NeedMorePlayData(frames_per_10_ms, 174010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bytes_per_sample, 175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) audio_bus->channels(), 176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) sample_rate, 177010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) audio_data, 178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) num_audio_frames, 17946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) &elapsed_time_ms, 18046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) &ntp_time_ms); 181010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) accumulated_audio_frames += num_audio_frames; 182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (elapsed_time_ms >= 0) { 184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *current_time = base::TimeDelta::FromMilliseconds(elapsed_time_ms); 185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 186010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) audio_data += bytes_per_10_ms; 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // De-interleave each channel and convert to 32-bit floating-point 190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // with nominal range -1.0 -> +1.0 to match the callback format. 191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_bus->FromInterleaved(&render_buffer_[0], 192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) audio_bus->frames(), 193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bytes_per_sample); 194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Pass the render data to the playout sinks. 196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::AutoLock auto_lock(lock_); 197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (PlayoutDataSinkList::const_iterator it = playout_sinks_.begin(); 198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) it != playout_sinks_.end(); ++it) { 199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (*it)->OnPlayoutData(audio_bus, sample_rate, audio_delay_milliseconds); 200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRtcAudioDeviceImpl::RemoveAudioRenderer(WebRtcAudioRenderer* renderer) { 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(renderer, renderer_.get()); 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock auto_lock(lock_); 207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Notify the playout sink of the change. 208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (PlayoutDataSinkList::const_iterator it = playout_sinks_.begin(); 209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) it != playout_sinks_.end(); ++it) { 210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (*it)->OnPlayoutDataSourceChanged(); 211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) renderer_ = NULL; 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) playing_ = false; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::RegisterAudioCallback( 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) webrtc::AudioTransport* audio_callback) { 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::RegisterAudioCallback()"; 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(audio_transport_callback_ == NULL, audio_callback != NULL); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_transport_callback_ = audio_callback; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::Init() { 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::Init()"; 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We need to return a success to continue the initialization of WebRtc VoE 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // because failure on the capturer_ initialization should not prevent WebRTC 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // from working. See issue http://crbug.com/144421 for details. 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized_ = true; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::Terminate() { 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::Terminate()"; 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Calling Terminate() multiple times in a row is OK. 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!initialized_) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopRecording(); 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StopPlayout(); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DCHECK(!renderer_.get() || !renderer_->IsStarted()) 25058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) << "The shared audio renderer shouldn't be running"; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Stop all the capturers to ensure no further OnData() and 253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // RemoveAudioCapturer() callback. 254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Cache the capturers in a local list since WebRtcAudioCapturer::Stop() 255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // will trigger RemoveAudioCapturer() callback. 256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CapturerList capturers; 257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) capturers.swap(capturers_); 258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (CapturerList::const_iterator iter = capturers.begin(); 259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) iter != capturers.end(); ++iter) { 260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (*iter)->Stop(); 261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized_ = false; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRtcAudioDeviceImpl::Initialized() const { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return initialized_; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::PlayoutIsAvailable(bool* available) { 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *available = initialized_; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRtcAudioDeviceImpl::PlayoutIsInitialized() const { 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return initialized_; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::RecordingIsAvailable(bool* available) { 281bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch *available = (!capturers_.empty()); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRtcAudioDeviceImpl::RecordingIsInitialized() const { 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::RecordingIsInitialized()"; 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 288bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch return (!capturers_.empty()); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::StartPlayout() { 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::StartPlayout()"; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_IF(ERROR, !audio_transport_callback_) << "Audio transport is missing"; 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock auto_lock(lock_); 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!audio_transport_callback_) 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (playing_) { 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // webrtc::VoiceEngine assumes that it is OK to call Start() twice and 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that the call is ignored the second time. 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) playing_ = true; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::StopPlayout() { 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::StopPlayout()"; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!playing_) { 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // webrtc::VoiceEngine assumes that it is OK to call Stop() just in case. 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) playing_ = false; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRtcAudioDeviceImpl::Playing() const { 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return playing_; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::StartRecording() { 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::StartRecording()"; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(initialized_); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_IF(ERROR, !audio_transport_callback_) << "Audio transport is missing"; 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!audio_transport_callback_) { 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) { 3347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::AutoLock auto_lock(lock_); 3357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (recording_) 3367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return 0; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) recording_ = true; 3397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 3407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::StopRecording() { 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::StopRecording()"; 3467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) { 3477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::AutoLock auto_lock(lock_); 3487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!recording_) 3497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return 0; 3507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) recording_ = false; 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WebRtcAudioDeviceImpl::Recording() const { 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoLock auto_lock(lock_); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return recording_; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::SetMicrophoneVolume(uint32_t volume) { 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::SetMicrophoneVolume(" << volume << ")"; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(initialized_); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 366bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Only one microphone is supported at the moment, which is represented by 367bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // the default capturer. 368bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer()); 369bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch if (!capturer.get()) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 372bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch capturer->SetVolume(volume); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(henrika): sort out calling thread once we start using this API. 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::MicrophoneVolume(uint32_t* volume) const { 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::MicrophoneVolume()"; 379bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // We only support one microphone now, which is accessed via the default 380bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // capturer. 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(initialized_); 382bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer()); 383bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch if (!capturer.get()) 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return -1; 385bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 386bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch *volume = static_cast<uint32_t>(capturer->Volume()); 3870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::MaxMicrophoneVolume(uint32_t* max_volume) const { 392bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch DCHECK(initialized_); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *max_volume = kMaxVolumeLevel; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::MinMicrophoneVolume(uint32_t* min_volume) const { 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *min_volume = 0; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::StereoPlayoutIsAvailable(bool* available) const { 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(initialized_); 4041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *available = renderer_.get() && renderer_->channels() == 2; 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::StereoRecordingIsAvailable( 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool* available) const { 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(initialized_); 411bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // TODO(xians): These kind of hardware methods do not make much sense since we 412bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // support multiple sources. Remove or figure out new APIs for such methods. 413bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer()); 414bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch if (!capturer.get()) 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 416bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *available = (capturer->source_audio_parameters().channels() == 2); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::PlayoutDelay(uint16_t* delay_ms) const { 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *delay_ms = static_cast<uint16_t>(output_delay_ms_); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::RecordingDelay(uint16_t* delay_ms) const { 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *delay_ms = static_cast<uint16_t>(input_delay_ms_); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::RecordingSampleRate( 434010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) uint32_t* sample_rate) const { 435bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // We use the default capturer as the recording sample rate. 436bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer()); 437bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch if (!capturer.get()) 438bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch return -1; 439bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 440010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) *sample_rate = static_cast<uint32_t>( 4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) capturer->source_audio_parameters().sample_rate()); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WebRtcAudioDeviceImpl::PlayoutSampleRate( 446010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) uint32_t* sample_rate) const { 4471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *sample_rate = renderer_.get() ? renderer_->sample_rate() : 0; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool WebRtcAudioDeviceImpl::SetAudioRenderer(WebRtcAudioRenderer* renderer) { 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(renderer); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (renderer_.get()) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!renderer->Initialize(this)) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) renderer_ = renderer; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 466bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochvoid WebRtcAudioDeviceImpl::AddAudioCapturer( 467bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch const scoped_refptr<WebRtcAudioCapturer>& capturer) { 468bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()"; 469bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 470bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch DCHECK(capturer.get()); 4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(!capturer->device_id().empty()); 472a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) { 473a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::AutoLock auto_lock(lock_); 474a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(std::find(capturers_.begin(), capturers_.end(), capturer) == 475a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) capturers_.end()); 476a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) capturers_.push_back(capturer); 477a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 478bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch} 479bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRtcAudioDeviceImpl::RemoveAudioCapturer( 4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<WebRtcAudioCapturer>& capturer) { 4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()"; 4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(capturer.get()); 4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::AutoLock auto_lock(lock_); 4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) capturers_.remove(capturer); 4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 489bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochscoped_refptr<WebRtcAudioCapturer> 490bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben MurdochWebRtcAudioDeviceImpl::GetDefaultCapturer() const { 491bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch base::AutoLock auto_lock(lock_); 4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Use the last |capturer| which is from the latest getUserMedia call as 4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the default capture device. 49423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return capturers_.empty() ? NULL : capturers_.back(); 495bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch} 496bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 497a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WebRtcAudioDeviceImpl::AddPlayoutSink( 498a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) WebRtcPlayoutDataSource::Sink* sink) { 499a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 500a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(sink); 501a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::AutoLock auto_lock(lock_); 502a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(std::find(playout_sinks_.begin(), playout_sinks_.end(), sink) == 503a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) playout_sinks_.end()); 504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) playout_sinks_.push_back(sink); 505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 506a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 507a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void WebRtcAudioDeviceImpl::RemovePlayoutSink( 508a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) WebRtcPlayoutDataSource::Sink* sink) { 509a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 510a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(sink); 511a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::AutoLock auto_lock(lock_); 512a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) playout_sinks_.remove(sink); 513a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 514a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool WebRtcAudioDeviceImpl::GetAuthorizedDeviceInfoForAudioRenderer( 5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int* session_id, 5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int* output_sample_rate, 5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int* output_frames_per_buffer) { 5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If there is no capturer or there are more than one open capture devices, 5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // return false. 5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (capturers_.empty() || capturers_.size() > 1) 5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return GetDefaultCapturer()->GetPairedOutputParameters( 5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) session_id, output_sample_rate, output_frames_per_buffer); 5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 530