blob: c40e0a2219b773eea21536cfc38d2259f3f966ea [file] [log] [blame]
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001// Copyright 2013 The Chromium Authors. All rights reserved.
Torne (Richard Coles)58218062012-11-14 11:43:16 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/renderer/media/webrtc_audio_device_impl.h"
6
7#include "base/bind.h"
8#include "base/metrics/histogram.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01009#include "base/strings/string_util.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000010#include "base/win/windows_version.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000011#include "content/renderer/media/webrtc_audio_capturer.h"
12#include "content/renderer/media/webrtc_audio_renderer.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000013#include "content/renderer/render_thread_impl.h"
14#include "media/audio/audio_parameters.h"
15#include "media/audio/audio_util.h"
16#include "media/audio/sample_rates.h"
17
18using media::AudioParameters;
19using media::ChannelLayout;
20
21namespace content {
22
Torne (Richard Coles)58218062012-11-14 11:43:16 +000023WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()
24 : ref_count_(0),
Torne (Richard Coles)58218062012-11-14 11:43:16 +000025 audio_transport_callback_(NULL),
26 input_delay_ms_(0),
27 output_delay_ms_(0),
Torne (Richard Coles)58218062012-11-14 11:43:16 +000028 initialized_(false),
29 playing_(false),
30 recording_(false),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000031 agc_is_enabled_(false),
32 microphone_volume_(0) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +000033 DVLOG(1) << "WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()";
Torne (Richard Coles)58218062012-11-14 11:43:16 +000034}
35
36WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl() {
37 DVLOG(1) << "WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl()";
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000038 DCHECK(thread_checker_.CalledOnValidThread());
Torne (Richard Coles)58218062012-11-14 11:43:16 +000039 Terminate();
40}
41
42int32_t WebRtcAudioDeviceImpl::AddRef() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000043 DCHECK(thread_checker_.CalledOnValidThread());
Torne (Richard Coles)58218062012-11-14 11:43:16 +000044 return base::subtle::Barrier_AtomicIncrement(&ref_count_, 1);
45}
46
47int32_t WebRtcAudioDeviceImpl::Release() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000048 DCHECK(thread_checker_.CalledOnValidThread());
Torne (Richard Coles)58218062012-11-14 11:43:16 +000049 int ret = base::subtle::Barrier_AtomicIncrement(&ref_count_, -1);
50 if (ret == 0) {
51 delete this;
52 }
53 return ret;
54}
Ben Murdochbb1529c2013-08-08 10:24:53 +010055int WebRtcAudioDeviceImpl::CaptureData(const std::vector<int>& channels,
56 const int16* audio_data,
57 int sample_rate,
58 int number_of_channels,
59 int number_of_frames,
60 int audio_delay_milliseconds,
61 int current_volume,
62 bool need_audio_processing) {
63 int total_delay_ms = 0;
Torne (Richard Coles)58218062012-11-14 11:43:16 +000064 {
65 base::AutoLock auto_lock(lock_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000066 if (!recording_)
Ben Murdochbb1529c2013-08-08 10:24:53 +010067 return 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000068
Torne (Richard Coles)58218062012-11-14 11:43:16 +000069 // Store the reported audio delay locally.
70 input_delay_ms_ = audio_delay_milliseconds;
Ben Murdochbb1529c2013-08-08 10:24:53 +010071 total_delay_ms = input_delay_ms_ + output_delay_ms_;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010072 DVLOG(2) << "total delay: " << input_delay_ms_ + output_delay_ms_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +000073 }
74
Torne (Richard Coles)58218062012-11-14 11:43:16 +000075 // Write audio samples in blocks of 10 milliseconds to the registered
76 // webrtc::AudioTransport sink. Keep writing until our internal byte
77 // buffer is empty.
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010078 // TODO(niklase): Wire up the key press detection.
Ben Murdochbb1529c2013-08-08 10:24:53 +010079 const int16* audio_buffer = audio_data;
80 const int samples_per_10_msec = (sample_rate / 100);
81 int accumulated_audio_samples = 0;
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010082 bool key_pressed = false;
Ben Murdochbb1529c2013-08-08 10:24:53 +010083 uint32_t new_volume = 0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000084 while (accumulated_audio_samples < number_of_frames) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +000085 // Deliver 10ms of recorded 16-bit linear PCM audio.
Ben Murdochbb1529c2013-08-08 10:24:53 +010086 int new_mic_level = audio_transport_callback_->OnDataAvailable(
87 &channels[0],
88 channels.size(),
89 audio_buffer,
90 sample_rate,
91 number_of_channels,
Torne (Richard Coles)58218062012-11-14 11:43:16 +000092 samples_per_10_msec,
Ben Murdochbb1529c2013-08-08 10:24:53 +010093 total_delay_ms,
94 current_volume,
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010095 key_pressed,
Ben Murdochbb1529c2013-08-08 10:24:53 +010096 need_audio_processing);
Torne (Richard Coles)58218062012-11-14 11:43:16 +000097
98 accumulated_audio_samples += samples_per_10_msec;
Ben Murdochbb1529c2013-08-08 10:24:53 +010099 audio_buffer += samples_per_10_msec * number_of_channels;
100
101 // The latest non-zero new microphone level will be returned.
102 if (new_mic_level)
103 new_volume = new_mic_level;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000104 }
105
Ben Murdochbb1529c2013-08-08 10:24:53 +0100106 return new_volume;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000107}
108
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000109void WebRtcAudioDeviceImpl::SetCaptureFormat(
110 const media::AudioParameters& params) {
111 DVLOG(1) << "WebRtcAudioDeviceImpl::SetCaptureFormat()";
112 DCHECK(thread_checker_.CalledOnValidThread());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000113}
114
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000115void WebRtcAudioDeviceImpl::RenderData(uint8* audio_data,
116 int number_of_channels,
117 int number_of_frames,
118 int audio_delay_milliseconds) {
119 DCHECK_LE(number_of_frames, output_buffer_size());
120 {
121 base::AutoLock auto_lock(lock_);
122 // Store the reported audio delay locally.
123 output_delay_ms_ = audio_delay_milliseconds;
124 }
125
126 const int channels = number_of_channels;
127 DCHECK_LE(channels, output_channels());
128
129 int samples_per_sec = output_sample_rate();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000130 int samples_per_10_msec = (samples_per_sec / 100);
131 int bytes_per_sample = output_audio_parameters_.bits_per_sample() / 8;
132 const int bytes_per_10_msec =
133 channels * samples_per_10_msec * bytes_per_sample;
134
135 uint32_t num_audio_samples = 0;
136 int accumulated_audio_samples = 0;
137
138 // Get audio samples in blocks of 10 milliseconds from the registered
139 // webrtc::AudioTransport source. Keep reading until our internal buffer
140 // is full.
141 while (accumulated_audio_samples < number_of_frames) {
142 // Get 10ms and append output to temporary byte buffer.
143 audio_transport_callback_->NeedMorePlayData(samples_per_10_msec,
144 bytes_per_sample,
145 channels,
146 samples_per_sec,
147 audio_data,
148 num_audio_samples);
149 accumulated_audio_samples += num_audio_samples;
150 audio_data += bytes_per_10_msec;
151 }
152}
153
154void WebRtcAudioDeviceImpl::SetRenderFormat(const AudioParameters& params) {
155 DCHECK(thread_checker_.CalledOnValidThread());
156 output_audio_parameters_ = params;
157}
158
159void WebRtcAudioDeviceImpl::RemoveAudioRenderer(WebRtcAudioRenderer* renderer) {
160 DCHECK(thread_checker_.CalledOnValidThread());
161 DCHECK_EQ(renderer, renderer_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000162 base::AutoLock auto_lock(lock_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000163 renderer_ = NULL;
164 playing_ = false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000165}
166
167int32_t WebRtcAudioDeviceImpl::RegisterAudioCallback(
168 webrtc::AudioTransport* audio_callback) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000169 DVLOG(1) << "WebRtcAudioDeviceImpl::RegisterAudioCallback()";
170 DCHECK(thread_checker_.CalledOnValidThread());
171 DCHECK_EQ(audio_transport_callback_ == NULL, audio_callback != NULL);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000172 audio_transport_callback_ = audio_callback;
173 return 0;
174}
175
176int32_t WebRtcAudioDeviceImpl::Init() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000177 DVLOG(1) << "WebRtcAudioDeviceImpl::Init()";
178 DCHECK(thread_checker_.CalledOnValidThread());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000179
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000180 // We need to return a success to continue the initialization of WebRtc VoE
181 // because failure on the capturer_ initialization should not prevent WebRTC
182 // from working. See issue http://crbug.com/144421 for details.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000183 initialized_ = true;
184
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000185 return 0;
186}
187
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000188int32_t WebRtcAudioDeviceImpl::Terminate() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000189 DVLOG(1) << "WebRtcAudioDeviceImpl::Terminate()";
190 DCHECK(thread_checker_.CalledOnValidThread());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000191
192 // Calling Terminate() multiple times in a row is OK.
193 if (!initialized_)
194 return 0;
195
196 StopRecording();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000197 StopPlayout();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000198
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000199 // It is necessary to stop the |renderer_| before going away.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100200 if (renderer_.get()) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100201 // Grab a local reference while we call Stop(), which will trigger a call to
202 // RemoveAudioRenderer that clears our reference to the audio renderer.
203 scoped_refptr<WebRtcAudioRenderer> local_renderer(renderer_);
204 local_renderer->Stop();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100205 DCHECK(!renderer_.get());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000206 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000207
Ben Murdochbb1529c2013-08-08 10:24:53 +0100208 capturers_.clear();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000209
210 initialized_ = false;
211 return 0;
212}
213
214bool WebRtcAudioDeviceImpl::Initialized() const {
215 return initialized_;
216}
217
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000218int32_t WebRtcAudioDeviceImpl::PlayoutIsAvailable(bool* available) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000219 *available = initialized_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000220 return 0;
221}
222
223bool WebRtcAudioDeviceImpl::PlayoutIsInitialized() const {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000224 return initialized_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000225}
226
227int32_t WebRtcAudioDeviceImpl::RecordingIsAvailable(bool* available) {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100228 *available = (!capturers_.empty());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000229 return 0;
230}
231
232bool WebRtcAudioDeviceImpl::RecordingIsInitialized() const {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000233 DVLOG(1) << "WebRtcAudioDeviceImpl::RecordingIsInitialized()";
234 DCHECK(thread_checker_.CalledOnValidThread());
Ben Murdochbb1529c2013-08-08 10:24:53 +0100235 return (!capturers_.empty());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000236}
237
238int32_t WebRtcAudioDeviceImpl::StartPlayout() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000239 DVLOG(1) << "WebRtcAudioDeviceImpl::StartPlayout()";
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000240 LOG_IF(ERROR, !audio_transport_callback_) << "Audio transport is missing";
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000241 {
242 base::AutoLock auto_lock(lock_);
243 if (!audio_transport_callback_)
244 return 0;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000245 }
246
247 if (playing_) {
248 // webrtc::VoiceEngine assumes that it is OK to call Start() twice and
249 // that the call is ignored the second time.
250 return 0;
251 }
252
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000253 playing_ = true;
254 start_render_time_ = base::Time::Now();
255 return 0;
256}
257
258int32_t WebRtcAudioDeviceImpl::StopPlayout() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000259 DVLOG(1) << "WebRtcAudioDeviceImpl::StopPlayout()";
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000260 if (!playing_) {
261 // webrtc::VoiceEngine assumes that it is OK to call Stop() just in case.
262 return 0;
263 }
264
265 // Add histogram data to be uploaded as part of an UMA logging event.
266 // This histogram keeps track of total playout times.
267 if (!start_render_time_.is_null()) {
268 base::TimeDelta render_time = base::Time::Now() - start_render_time_;
269 UMA_HISTOGRAM_LONG_TIMES("WebRTC.AudioRenderTime", render_time);
270 }
271
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000272 playing_ = false;
273 return 0;
274}
275
276bool WebRtcAudioDeviceImpl::Playing() const {
277 return playing_;
278}
279
280int32_t WebRtcAudioDeviceImpl::StartRecording() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000281 DVLOG(1) << "WebRtcAudioDeviceImpl::StartRecording()";
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000282 DCHECK(initialized_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000283 LOG_IF(ERROR, !audio_transport_callback_) << "Audio transport is missing";
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000284 if (!audio_transport_callback_) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000285 return -1;
286 }
287
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100288 {
289 base::AutoLock auto_lock(lock_);
290 if (recording_)
291 return 0;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000292
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100293 recording_ = true;
294 }
295
296 start_capture_time_ = base::Time::Now();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000297
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000298 return 0;
299}
300
301int32_t WebRtcAudioDeviceImpl::StopRecording() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000302 DVLOG(1) << "WebRtcAudioDeviceImpl::StopRecording()";
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100303 {
304 base::AutoLock auto_lock(lock_);
305 if (!recording_)
306 return 0;
307
308 recording_ = false;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000309 }
310
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000311 // Add histogram data to be uploaded as part of an UMA logging event.
312 // This histogram keeps track of total recording times.
313 if (!start_capture_time_.is_null()) {
314 base::TimeDelta capture_time = base::Time::Now() - start_capture_time_;
315 UMA_HISTOGRAM_LONG_TIMES("WebRTC.AudioCaptureTime", capture_time);
316 }
317
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000318 return 0;
319}
320
321bool WebRtcAudioDeviceImpl::Recording() const {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000322 base::AutoLock auto_lock(lock_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000323 return recording_;
324}
325
326int32_t WebRtcAudioDeviceImpl::SetAGC(bool enable) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000327 DVLOG(1) << "WebRtcAudioDeviceImpl::SetAGC(enable=" << enable << ")";
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000328 DCHECK(initialized_);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000329
330 // Return early if we are not changing the AGC state.
331 if (enable == agc_is_enabled_)
332 return 0;
333
Ben Murdochbb1529c2013-08-08 10:24:53 +0100334 // Set the AGC on all the capturers. It depends on the source of the
335 // capturer whether AGC is supported or not.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000336 // The current implementation does not support changing the AGC state while
337 // recording. Using this approach simplifies the design and it is also
Ben Murdochbb1529c2013-08-08 10:24:53 +0100338 // inline with the latest WebRTC standard.
339 for (CapturerList::const_iterator iter = capturers_.begin();
340 iter != capturers_.end(); ++iter) {
341 if (!(*iter)->is_recording())
342 (*iter)->SetAutomaticGainControl(enable);
343 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000344
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000345 agc_is_enabled_ = enable;
346 return 0;
347}
348
349bool WebRtcAudioDeviceImpl::AGC() const {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000350 DVLOG(1) << "WebRtcAudioDeviceImpl::AGC()";
351 DCHECK(thread_checker_.CalledOnValidThread());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000352 // To reduce the usage of IPC messages, an internal AGC state is used.
353 // TODO(henrika): investigate if there is a need for a "deeper" getter.
354 return agc_is_enabled_;
355}
356
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000357int32_t WebRtcAudioDeviceImpl::SetMicrophoneVolume(uint32_t volume) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000358 DVLOG(1) << "WebRtcAudioDeviceImpl::SetMicrophoneVolume(" << volume << ")";
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000359 DCHECK(initialized_);
Ben Murdochbb1529c2013-08-08 10:24:53 +0100360
361 // Only one microphone is supported at the moment, which is represented by
362 // the default capturer.
363 scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer());
364 if (!capturer.get())
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000365 return -1;
366
Ben Murdochbb1529c2013-08-08 10:24:53 +0100367 capturer->SetVolume(volume);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000368 return 0;
369}
370
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000371// TODO(henrika): sort out calling thread once we start using this API.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000372int32_t WebRtcAudioDeviceImpl::MicrophoneVolume(uint32_t* volume) const {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000373 DVLOG(1) << "WebRtcAudioDeviceImpl::MicrophoneVolume()";
Ben Murdochbb1529c2013-08-08 10:24:53 +0100374 // We only support one microphone now, which is accessed via the default
375 // capturer.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000376 DCHECK(initialized_);
Ben Murdochbb1529c2013-08-08 10:24:53 +0100377 scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer());
378 if (!capturer.get())
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000379 return -1;
Ben Murdochbb1529c2013-08-08 10:24:53 +0100380
381 *volume = static_cast<uint32_t>(capturer->Volume());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000382 return 0;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000383}
384
385int32_t WebRtcAudioDeviceImpl::MaxMicrophoneVolume(uint32_t* max_volume) const {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100386 DCHECK(initialized_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000387 *max_volume = kMaxVolumeLevel;
388 return 0;
389}
390
391int32_t WebRtcAudioDeviceImpl::MinMicrophoneVolume(uint32_t* min_volume) const {
392 *min_volume = 0;
393 return 0;
394}
395
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000396int32_t WebRtcAudioDeviceImpl::StereoPlayoutIsAvailable(bool* available) const {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000397 DCHECK(initialized_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000398 *available = (output_channels() == 2);
399 return 0;
400}
401
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000402int32_t WebRtcAudioDeviceImpl::StereoRecordingIsAvailable(
403 bool* available) const {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000404 DCHECK(initialized_);
Ben Murdochbb1529c2013-08-08 10:24:53 +0100405 // TODO(xians): These kind of hardware methods do not make much sense since we
406 // support multiple sources. Remove or figure out new APIs for such methods.
407 scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer());
408 if (!capturer.get())
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000409 return -1;
Ben Murdochbb1529c2013-08-08 10:24:53 +0100410
411 *available = (capturer->audio_parameters().channels() == 2);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000412 return 0;
413}
414
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000415int32_t WebRtcAudioDeviceImpl::PlayoutDelay(uint16_t* delay_ms) const {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000416 base::AutoLock auto_lock(lock_);
417 *delay_ms = static_cast<uint16_t>(output_delay_ms_);
418 return 0;
419}
420
421int32_t WebRtcAudioDeviceImpl::RecordingDelay(uint16_t* delay_ms) const {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000422 base::AutoLock auto_lock(lock_);
423 *delay_ms = static_cast<uint16_t>(input_delay_ms_);
424 return 0;
425}
426
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000427int32_t WebRtcAudioDeviceImpl::RecordingSampleRate(
428 uint32_t* samples_per_sec) const {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100429 // We use the default capturer as the recording sample rate.
430 scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer());
431 if (!capturer.get())
432 return -1;
433
434 *samples_per_sec = static_cast<uint32_t>(
435 capturer->audio_parameters().sample_rate());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000436 return 0;
437}
438
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000439int32_t WebRtcAudioDeviceImpl::PlayoutSampleRate(
440 uint32_t* samples_per_sec) const {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000441 *samples_per_sec = static_cast<uint32_t>(output_sample_rate());
442 return 0;
443}
444
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000445bool WebRtcAudioDeviceImpl::SetAudioRenderer(WebRtcAudioRenderer* renderer) {
446 DCHECK(thread_checker_.CalledOnValidThread());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000447 DCHECK(renderer);
448
449 base::AutoLock auto_lock(lock_);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100450 if (renderer_.get())
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000451 return false;
452
453 if (!renderer->Initialize(this))
454 return false;
455
456 renderer_ = renderer;
457 return true;
458}
459
Ben Murdochbb1529c2013-08-08 10:24:53 +0100460void WebRtcAudioDeviceImpl::AddAudioCapturer(
461 const scoped_refptr<WebRtcAudioCapturer>& capturer) {
462 DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()";
463 DCHECK(thread_checker_.CalledOnValidThread());
464 DCHECK(capturer.get());
465
466 // Enable/disable the AGC on the new capture.
467 DCHECK(!capturer->is_recording());
468 capturer->SetAutomaticGainControl(agc_is_enabled_);
469
470 // We only support one microphone today, which means the list can contain
471 // only one capturer with a valid device id.
472 DCHECK(capturer->device_id().empty() || !GetDefaultCapturer());
473 base::AutoLock auto_lock(lock_);
474 capturers_.push_back(capturer);
475}
476
477scoped_refptr<WebRtcAudioCapturer>
478WebRtcAudioDeviceImpl::GetDefaultCapturer() const {
479 base::AutoLock auto_lock(lock_);
480 for (CapturerList::const_iterator iter = capturers_.begin();
481 iter != capturers_.end(); ++iter) {
482 if (!(*iter)->device_id().empty())
483 return *iter;
484 }
485
486 return NULL;
487}
488
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000489} // namespace content