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