12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/renderer/media/webrtc_audio_capturer.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/strings/stringprintf.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/child/child_process.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/renderer/media/audio_device_factory.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/renderer/media/media_stream_audio_processor.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/renderer/media/media_stream_audio_processor_options.h"
160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "content/renderer/media/media_stream_audio_source.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/renderer/media/webrtc_audio_device_impl.h"
18bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "content/renderer/media/webrtc_local_audio_track.h"
19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/renderer/media/webrtc_logging.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/sample_rates.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace content {
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochnamespace {
25bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
26a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Time constant for AudioPowerMonitor.  See AudioPowerMonitor ctor comments
27a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// for semantics.  This value was arbitrarily chosen, but seems to work well.
28a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochconst int kPowerMonitorTimeConstantMs = 10;
29a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
30a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// The time between two audio power level samples.
31a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochconst int kPowerMonitorLogIntervalSeconds = 10;
32a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
33ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch// Method to check if any of the data in |audio_source| has energy.
34ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdochbool HasDataEnergy(const media::AudioBus& audio_source) {
35ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch  for (int ch = 0; ch < audio_source.channels(); ++ch) {
36ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch    const float* channel_ptr = audio_source.channel(ch);
37ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch    for (int frame = 0; frame < audio_source.frames(); ++frame) {
38ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch      if (channel_ptr[frame] != 0)
39ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch        return true;
40ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch    }
41ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch  }
42ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch
43ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch  // All the data is zero.
44ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch  return false;
45ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch}
46ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch
47bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}  // namespace
48bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
49bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Reference counted container of WebRtcLocalAudioTrack delegate.
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// TODO(xians): Switch to MediaStreamAudioSinkOwner.
51bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochclass WebRtcAudioCapturer::TrackOwner
52bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    : public base::RefCountedThreadSafe<WebRtcAudioCapturer::TrackOwner> {
53bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch public:
54bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  explicit TrackOwner(WebRtcLocalAudioTrack* track)
55bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      : delegate_(track) {}
56bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void Capture(const int16* audio_data,
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               base::TimeDelta delay,
59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)               double volume,
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               bool key_pressed,
61ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch               bool need_audio_processing,
62ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch               bool force_report_nonzero_energy) {
63bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    base::AutoLock lock(lock_);
64bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    if (delegate_) {
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      delegate_->Capture(audio_data,
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         delay,
67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                         volume,
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         key_pressed,
69ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch                         need_audio_processing,
70ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch                         force_report_nonzero_energy);
71bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    }
72bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
73bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void OnSetFormat(const media::AudioParameters& params) {
75bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    base::AutoLock lock(lock_);
76bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    if (delegate_)
77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      delegate_->OnSetFormat(params);
78bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
79bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void SetAudioProcessor(
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const scoped_refptr<MediaStreamAudioProcessor>& processor) {
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::AutoLock lock(lock_);
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (delegate_)
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      delegate_->SetAudioProcessor(processor);
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
87bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  void Reset() {
88bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    base::AutoLock lock(lock_);
89bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    delegate_ = NULL;
90bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
91bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void Stop() {
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::AutoLock lock(lock_);
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(delegate_);
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // This can be reentrant so reset |delegate_| before calling out.
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WebRtcLocalAudioTrack* temp = delegate_;
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    delegate_ = NULL;
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    temp->Stop();
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
102bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Wrapper which allows to use std::find_if() when adding and removing
103bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // sinks to/from the list.
104bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  struct TrackWrapper {
105bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    TrackWrapper(WebRtcLocalAudioTrack* track) : track_(track) {}
106bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    bool operator()(
107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        const scoped_refptr<WebRtcAudioCapturer::TrackOwner>& owner) const {
108bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      return owner->IsEqual(track_);
109bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    }
110bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    WebRtcLocalAudioTrack* track_;
111bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  };
112bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
113bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch protected:
114bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  virtual ~TrackOwner() {}
115bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
116bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch private:
117bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  friend class base::RefCountedThreadSafe<WebRtcAudioCapturer::TrackOwner>;
118bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
119bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  bool IsEqual(const WebRtcLocalAudioTrack* other) const {
120bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    base::AutoLock lock(lock_);
121bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return (other == delegate_);
122bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
123bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
124bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Do NOT reference count the |delegate_| to avoid cyclic reference counting.
125bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  WebRtcLocalAudioTrack* delegate_;
126bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  mutable base::Lock lock_;
127bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
128bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(TrackOwner);
129bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch};
130bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_refptr<WebRtcAudioCapturer> WebRtcAudioCapturer::CreateCapturer(
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int render_view_id, const StreamDeviceInfo& device_info,
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const blink::WebMediaConstraints& constraints,
1350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    WebRtcAudioDeviceImpl* audio_device,
1360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    MediaStreamAudioSource* audio_source) {
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<WebRtcAudioCapturer> capturer = new WebRtcAudioCapturer(
1380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      render_view_id, device_info, constraints, audio_device, audio_source);
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (capturer->Initialize())
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return capturer;
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return NULL;
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool WebRtcAudioCapturer::Initialize() {
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "WebRtcAudioCapturer::Initialize()";
148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  WebRtcLogMessage(base::StringPrintf(
149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "WAC::Initialize. render_view_id=%d"
150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ", channel_layout=%d, sample_rate=%d, buffer_size=%d"
151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ", session_id=%d, paired_output_sample_rate=%d"
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ", paired_output_frames_per_buffer=%d, effects=%d. ",
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      render_view_id_,
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      device_info_.device.input.channel_layout,
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      device_info_.device.input.sample_rate,
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      device_info_.device.input.frames_per_buffer,
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      device_info_.session_id,
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      device_info_.device.matched_output.sample_rate,
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      device_info_.device.matched_output.frames_per_buffer,
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      device_info_.device.input.effects));
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (render_view_id_ == -1) {
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Return true here to allow injecting a new source via
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // SetCapturerSourceForTesting() at a later state.
165bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return true;
166bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MediaAudioConstraints audio_constraints(constraints_,
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                          device_info_.device.input.effects);
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!audio_constraints.IsValid())
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  media::ChannelLayout channel_layout = static_cast<media::ChannelLayout>(
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      device_info_.device.input.channel_layout);
1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // If KEYBOARD_MIC effect is set, change the layout to the corresponding
1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // layout that includes the keyboard mic.
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if ((device_info_.device.input.effects &
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          media::AudioParameters::KEYBOARD_MIC) &&
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled() &&
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      audio_constraints.GetProperty(
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          MediaAudioConstraints::kGoogExperimentalNoiseSuppression)) {
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (channel_layout == media::CHANNEL_LAYOUT_STEREO) {
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      channel_layout = media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC;
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      DVLOG(1) << "Changed stereo layout to stereo + keyboard mic layout due "
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci               << "to KEYBOARD_MIC effect.";
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    } else {
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      DVLOG(1) << "KEYBOARD_MIC effect ignored, not compatible with layout "
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci               << channel_layout;
1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DVLOG(1) << "Audio input hardware channel layout: " << channel_layout;
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputChannelLayout",
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            channel_layout, media::CHANNEL_LAYOUT_MAX + 1);
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify that the reported input channel configuration is supported.
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (channel_layout != media::CHANNEL_LAYOUT_MONO &&
1995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      channel_layout != media::CHANNEL_LAYOUT_STEREO &&
2005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      channel_layout != media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) {
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DLOG(ERROR) << channel_layout
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                << " is not a supported input channel configuration.";
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DVLOG(1) << "Audio input hardware sample rate: "
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << device_info_.device.input.sample_rate;
208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  media::AudioSampleRate asr;
209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (media::ToAudioSampleRate(device_info_.device.input.sample_rate, &asr)) {
210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    UMA_HISTOGRAM_ENUMERATION(
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        "WebRTC.AudioInputSampleRate", asr, media::kAudioSampleRateMax + 1);
212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } else {
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    UMA_HISTOGRAM_COUNTS("WebRTC.AudioInputSampleRateUnexpected",
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         device_info_.device.input.sample_rate);
215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Create and configure the default audio capturing source.
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id_),
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    channel_layout,
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    static_cast<float>(device_info_.device.input.sample_rate));
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Add the capturer to the WebRtcAudioDeviceImpl since it needs some hardware
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // information from the capturer.
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (audio_device_)
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    audio_device_->AddAudioCapturer(this);
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WebRtcAudioCapturer::WebRtcAudioCapturer(
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int render_view_id,
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const StreamDeviceInfo& device_info,
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const blink::WebMediaConstraints& constraints,
2340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    WebRtcAudioDeviceImpl* audio_device,
2350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    MediaStreamAudioSource* audio_source)
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : constraints_(constraints),
237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      audio_processor_(
2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          new rtc::RefCountedObject<MediaStreamAudioProcessor>(
239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              constraints, device_info.device.input.effects, audio_device)),
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      running_(false),
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      render_view_id_(render_view_id),
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      device_info_(device_info),
243d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      volume_(0),
2444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      peer_connection_mode_(false),
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      key_pressed_(false),
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      need_audio_processing_(false),
247a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      audio_device_(audio_device),
2480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      audio_source_(audio_source),
249a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      audio_power_monitor_(
250a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          device_info_.device.input.sample_rate,
251a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          base::TimeDelta::FromMilliseconds(kPowerMonitorTimeConstantMs)) {
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "WebRtcAudioCapturer::WebRtcAudioCapturer()";
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebRtcAudioCapturer::~WebRtcAudioCapturer() {
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(tracks_.IsEmpty());
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "WebRtcAudioCapturer::~WebRtcAudioCapturer()";
2590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  Stop();
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochvoid WebRtcAudioCapturer::AddTrack(WebRtcLocalAudioTrack* track) {
263b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(track);
264bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  DVLOG(1) << "WebRtcAudioCapturer::AddTrack()";
2657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::AutoLock auto_lock(lock_);
268f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Verify that |track| is not already added to the list.
269a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK(!tracks_.Contains(TrackOwner::TrackWrapper(track)));
270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
271a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Add with a tag, so we remember to call OnSetFormat() on the new
272a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // track.
273a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    scoped_refptr<TrackOwner> track_owner(new TrackOwner(track));
2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    tracks_.AddAndTag(track_owner.get());
275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
278bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochvoid WebRtcAudioCapturer::RemoveTrack(WebRtcLocalAudioTrack* track) {
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
2800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DVLOG(1) << "WebRtcAudioCapturer::RemoveTrack()";
2810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  bool stop_source = false;
2820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  {
2830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    base::AutoLock auto_lock(lock_);
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    scoped_refptr<TrackOwner> removed_item =
2860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        tracks_.Remove(TrackOwner::TrackWrapper(track));
2877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // Clear the delegate to ensure that no more capture callbacks will
2890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // be sent to this sink. Also avoids a possible crash which can happen
2900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // if this method is called while capturing is active.
2910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (removed_item.get()) {
2920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      removed_item->Reset();
2930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      stop_source = tracks_.IsEmpty();
2940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    }
2950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
2960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (stop_source) {
2970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // Since WebRtcAudioCapturer does not inherit MediaStreamAudioSource,
2980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // and instead MediaStreamAudioSource is composed of a WebRtcAudioCapturer,
2990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // we have to call StopSource on the MediaStreamSource. This will call
3000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // MediaStreamAudioSource::DoStopSource which in turn call
3010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    // WebRtcAudioCapturerer::Stop();
3020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    audio_source_->StopSource();
3030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRtcAudioCapturer::SetCapturerSource(
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const scoped_refptr<media::AudioCapturerSource>& source,
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    media::ChannelLayout channel_layout,
309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    float sample_rate) {
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "SetCapturerSource(channel_layout=" << channel_layout << ","
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           << "sample_rate=" << sample_rate << ")";
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<media::AudioCapturerSource> old_source;
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::AutoLock auto_lock(lock_);
316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (source_.get() == source.get())
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    source_.swap(old_source);
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    source_ = source;
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // Reset the flag to allow starting the new source.
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    running_ = false;
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
326d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DVLOG(1) << "Switching to a new capture source.";
327d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (old_source.get())
328d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    old_source->Stop();
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Dispatch the new parameters both to the sink(s) and to the new source,
3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // also apply the new |constraints|.
332d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // The idea is to get rid of any dependency of the microphone parameters
333d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // which would normally be used by default.
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // bits_per_sample is always 16 for now.
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int buffer_size = GetBufferSize(sample_rate);
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
3371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                channel_layout, sample_rate,
338a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                16, buffer_size,
339a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                device_info_.device.input.effects);
340a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  {
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::AutoLock auto_lock(lock_);
343a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Notify the |audio_processor_| of the new format.
344a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    audio_processor_->OnCaptureFormatChanged(params);
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MediaAudioConstraints audio_constraints(constraints_,
347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                            device_info_.device.input.effects);
348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    need_audio_processing_ = audio_constraints.NeedsAudioProcessing();
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Notify all tracks about the new format.
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    tracks_.TagAll();
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
352d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
353d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (source.get())
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    source->Initialize(params, this, session_id());
3557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  Start();
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
359d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void WebRtcAudioCapturer::EnablePeerConnectionMode() {
360d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
361d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DVLOG(1) << "EnablePeerConnectionMode";
362d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Do nothing if the peer connection mode has been enabled.
363d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (peer_connection_mode_)
364d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
365d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
366d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  peer_connection_mode_ = true;
367d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int render_view_id = -1;
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  media::AudioParameters input_params;
369d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  {
370d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    base::AutoLock auto_lock(lock_);
371d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Simply return if there is no existing source or the |render_view_id_| is
372d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // not valid.
373d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (!source_.get() || render_view_id_== -1)
374d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return;
375d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
376d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    render_view_id = render_view_id_;
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    input_params = audio_processor_->InputFormat();
378d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
379d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
3804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Do nothing if the current buffer size is the WebRtc native buffer size.
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (GetBufferSize(input_params.sample_rate()) ==
3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          input_params.frames_per_buffer()) {
3834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
386d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Create a new audio stream as source which will open the hardware using
387d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // WebRtc native buffer size.
388d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id),
3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    input_params.channel_layout(),
390a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    static_cast<float>(input_params.sample_rate()));
391d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
392d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRtcAudioCapturer::Start() {
394a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "WebRtcAudioCapturer::Start()";
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AutoLock auto_lock(lock_);
3971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (running_ || !source_.get())
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start the data source, i.e., start capturing data from the current source.
401f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // We need to set the AGC control before starting the stream.
402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  source_->SetAutomaticGainControl(true);
403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  source_->Start();
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  running_ = true;
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRtcAudioCapturer::Stop() {
408a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "WebRtcAudioCapturer::Stop()";
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<media::AudioCapturerSource> source;
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TrackList::ItemList tracks;
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::AutoLock auto_lock(lock_);
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!running_)
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    source = source_;
4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    tracks = tracks_.Items();
419a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    tracks_.Clear();
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    running_ = false;
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Remove the capturer object from the WebRtcAudioDeviceImpl.
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (audio_device_)
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    audio_device_->RemoveAudioCapturer(this);
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (TrackList::ItemList::const_iterator it = tracks.begin();
4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       it != tracks.end();
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       ++it) {
4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    (*it)->Stop();
4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (source.get())
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    source->Stop();
435116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
436116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Stop the audio processor to avoid feeding render data into the processor.
437116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  audio_processor_->Stop();
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
440bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochvoid WebRtcAudioCapturer::SetVolume(int volume) {
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "WebRtcAudioCapturer::SetVolume()";
442bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  DCHECK_LE(volume, MaxVolume());
443bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  double normalized_volume = static_cast<double>(volume) / MaxVolume();
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AutoLock auto_lock(lock_);
445868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (source_.get())
446bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    source_->SetVolume(normalized_volume);
447bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
448bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
449bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint WebRtcAudioCapturer::Volume() const {
450bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  base::AutoLock auto_lock(lock_);
451bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return volume_;
452bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
453bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
454bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochint WebRtcAudioCapturer::MaxVolume() const {
455bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return WebRtcAudioDeviceImpl::kMaxVolumeLevel;
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
458116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid WebRtcAudioCapturer::Capture(const media::AudioBus* audio_source,
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  int audio_delay_milliseconds,
4603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                  double volume,
4613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                  bool key_pressed) {
4623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// This callback is driven by AudioInputDevice::AudioThreadCallback if
4633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// |source_| is AudioInputDevice, otherwise it is driven by client's
4643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// CaptureCallback.
465bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#if defined(OS_WIN) || defined(OS_MACOSX)
466bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  DCHECK_LE(volume, 1.0);
46746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#elif (defined(OS_LINUX) && !defined(OS_CHROMEOS)) || defined(OS_OPENBSD)
468bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // We have a special situation on Linux where the microphone volume can be
469bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // "higher than maximum". The input volume slider in the sound preference
470bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // allows the user to set a scaling that is higher than 100%. It means that
471bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // even if the reported maximum levels is N, the actual microphone level can
472bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // go up to 1.5x*N and that corresponds to a normalized |volume| of 1.5x.
473bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  DCHECK_LE(volume, 1.6);
474bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#endif
475bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
476a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  TrackList::ItemList tracks;
477a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  TrackList::ItemList tracks_to_notify_format;
478d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int current_volume = 0;
4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::TimeDelta audio_delay;
4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool need_audio_processing = true;
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::AutoLock auto_lock(lock_);
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!running_)
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
486a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // Map internal volume range of [0.0, 1.0] into [0, 255] used by AGC.
487a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // The volume can be higher than 255 on Linux, and it will be cropped to
488a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // 255 since AGC does not allow values out of range.
489bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    volume_ = static_cast<int>((volume * MaxVolume()) + 0.5);
490a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    current_volume = volume_ > MaxVolume() ? MaxVolume() : volume_;
4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    audio_delay = base::TimeDelta::FromMilliseconds(audio_delay_milliseconds);
4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    audio_delay_ = audio_delay;
493f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    key_pressed_ = key_pressed;
494a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    tracks = tracks_.Items();
495a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    tracks_.RetrieveAndClearTags(&tracks_to_notify_format);
496f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Set the flag to turn on the audio processing in PeerConnection level.
4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Note that, we turn off the audio processing in PeerConnection if the
4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // processor has already processed the data.
5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    need_audio_processing = need_audio_processing_ ?
5010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        !MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled() : false;
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(audio_processor_->InputFormat().IsValid());
5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(audio_source->channels(),
506a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            audio_processor_->InputFormat().channels());
5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(audio_source->frames(),
508a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            audio_processor_->InputFormat().frames_per_buffer());
5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
510f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Notify the tracks on when the format changes. This will do nothing if
511f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // |tracks_to_notify_format| is empty.
5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  media::AudioParameters output_params = audio_processor_->OutputFormat();
513a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (TrackList::ItemList::const_iterator it = tracks_to_notify_format.begin();
514f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       it != tracks_to_notify_format.end(); ++it) {
5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    (*it)->OnSetFormat(output_params);
516a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    (*it)->SetAudioProcessor(audio_processor_);
517f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
519a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if ((base::TimeTicks::Now() - last_audio_level_log_time_).InSeconds() >
520a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          kPowerMonitorLogIntervalSeconds) {
521a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    audio_power_monitor_.Scan(*audio_source, audio_source->frames());
522a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
523a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    last_audio_level_log_time_ = base::TimeTicks::Now();
524a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
525a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    std::pair<float, bool> result =
526a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        audio_power_monitor_.ReadCurrentPowerAndClip();
527a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    WebRtcLogMessage(base::StringPrintf(
528a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        "WAC::Capture: current_audio_power=%.2fdBFS.", result.first));
529a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
530a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    audio_power_monitor_.Reset();
531a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
532a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
533ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch  // Figure out if the pre-processed data has any energy or not, the
534ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch  // information will be passed to the track to force the calculator
535ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch  // to report energy in case the post-processed data is zeroed by the audio
536ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch  // processing.
537ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch  const bool force_report_nonzero_energy = HasDataEnergy(*audio_source);
538ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch
5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Push the data to the processor for processing.
540a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  audio_processor_->PushCaptureData(audio_source);
5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Process and consume the data in the processor until there is not enough
5435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // data in the processor.
5445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int16* output = NULL;
5455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int new_volume = 0;
546a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  while (audio_processor_->ProcessAndConsumeData(
5475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      audio_delay, current_volume, key_pressed, &new_volume, &output)) {
5485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Feed the post-processed data to the tracks.
5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (TrackList::ItemList::const_iterator it = tracks.begin();
5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         it != tracks.end(); ++it) {
5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (*it)->Capture(output, audio_delay, current_volume, key_pressed,
552ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch                     need_audio_processing, force_report_nonzero_energy);
5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (new_volume) {
5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SetVolume(new_volume);
5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Update the |current_volume| to avoid passing the old volume to AGC.
5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      current_volume = new_volume;
5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRtcAudioCapturer::OnCaptureError() {
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTIMPLEMENTED();
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)media::AudioParameters WebRtcAudioCapturer::source_audio_parameters() const {
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AutoLock auto_lock(lock_);
5701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return audio_processor_.get() ? audio_processor_->InputFormat()
5711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                : media::AudioParameters();
572d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
573d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
5744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool WebRtcAudioCapturer::GetPairedOutputParameters(
5754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    int* session_id,
5764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    int* output_sample_rate,
5774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    int* output_frames_per_buffer) const {
578f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Don't set output parameters unless all of them are valid.
5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (device_info_.session_id <= 0 ||
5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !device_info_.device.matched_output.sample_rate ||
5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !device_info_.device.matched_output.frames_per_buffer)
582f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
583f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  *session_id = device_info_.session_id;
5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  *output_sample_rate = device_info_.device.matched_output.sample_rate;
5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  *output_frames_per_buffer =
5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      device_info_.device.matched_output.frames_per_buffer;
588f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
589f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return true;
5904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
5914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
592d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int WebRtcAudioCapturer::GetBufferSize(int sample_rate) const {
593d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
594d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if defined(OS_ANDROID)
595d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // TODO(henrika): Tune and adjust buffer size on Android.
596d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return (2 * sample_rate / 100);
597d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#endif
598d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
599f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // PeerConnection is running at a buffer size of 10ms data. A multiple of
600f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // 10ms as the buffer size can give the best performance to PeerConnection.
601f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int peer_connection_buffer_size = sample_rate / 100;
602f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
603f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Use the native hardware buffer size in non peer connection mode when the
604f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // platform is using a native buffer size smaller than the PeerConnection
605f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // buffer size.
6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int hardware_buffer_size = device_info_.device.input.frames_per_buffer;
6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!peer_connection_mode_ && hardware_buffer_size &&
6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      hardware_buffer_size <= peer_connection_buffer_size) {
6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return hardware_buffer_size;
610f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
611d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
612d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return (sample_rate / 100);
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
615f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void WebRtcAudioCapturer::GetAudioProcessingParams(
616f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::TimeDelta* delay, int* volume, bool* key_pressed) {
617f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::AutoLock auto_lock(lock_);
618f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  *delay = audio_delay_;
619f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  *volume = volume_;
620f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  *key_pressed = key_pressed_;
621f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
622f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRtcAudioCapturer::SetCapturerSourceForTesting(
6245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const scoped_refptr<media::AudioCapturerSource>& source,
6255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    media::AudioParameters params) {
6265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Create a new audio stream as source which uses the new source.
6275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetCapturerSource(source, params.channel_layout(),
628a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    static_cast<float>(params.sample_rate()));
629a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
630a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace content
632