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