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