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