Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(203)

Side by Side Diff: content/renderer/media/webrtc_audio_device_impl.cc

Issue 11270012: Adding audio support to the new webmediaplyer (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: added a lock to protect the |renderer_| Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/media/webrtc_audio_device_impl.h" 5 #include "content/renderer/media/webrtc_audio_device_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/metrics/histogram.h" 8 #include "base/metrics/histogram.h"
9 #include "base/string_util.h" 9 #include "base/string_util.h"
10 #include "base/win/windows_version.h" 10 #include "base/win/windows_version.h"
(...skipping 12 matching lines...) Expand all
23 static const int64 kMillisecondsBetweenProcessCalls = 5000; 23 static const int64 kMillisecondsBetweenProcessCalls = 5000;
24 static const double kMaxVolumeLevel = 255.0; 24 static const double kMaxVolumeLevel = 255.0;
25 25
26 // Supported hardware sample rates for input and output sides. 26 // Supported hardware sample rates for input and output sides.
27 #if defined(OS_WIN) || defined(OS_MACOSX) 27 #if defined(OS_WIN) || defined(OS_MACOSX)
28 // media::GetAudioInput[Output]HardwareSampleRate() asks the audio layer 28 // media::GetAudioInput[Output]HardwareSampleRate() asks the audio layer
29 // for its current sample rate (set by the user) on Windows and Mac OS X. 29 // for its current sample rate (set by the user) on Windows and Mac OS X.
30 // The listed rates below adds restrictions and WebRtcAudioDeviceImpl::Init() 30 // The listed rates below adds restrictions and WebRtcAudioDeviceImpl::Init()
31 // will fail if the user selects any rate outside these ranges. 31 // will fail if the user selects any rate outside these ranges.
32 static int kValidInputRates[] = {96000, 48000, 44100, 32000, 16000, 8000}; 32 static int kValidInputRates[] = {96000, 48000, 44100, 32000, 16000, 8000};
33 static int kValidOutputRates[] = {96000, 48000, 44100};
34 #elif defined(OS_LINUX) || defined(OS_OPENBSD) 33 #elif defined(OS_LINUX) || defined(OS_OPENBSD)
35 // media::GetAudioInput[Output]HardwareSampleRate() is hardcoded to return 34 // media::GetAudioInput[Output]HardwareSampleRate() is hardcoded to return
36 // 48000 in both directions on Linux. 35 // 48000 in both directions on Linux.
37 static int kValidInputRates[] = {48000}; 36 static int kValidInputRates[] = {48000};
38 static int kValidOutputRates[] = {48000};
39 #endif 37 #endif
40 38
41 namespace { 39 namespace {
42 40
43 // Helper enum used for histogramming buffer sizes expressed in number of 41 // Helper enum used for histogramming buffer sizes expressed in number of
44 // audio frames. This enumerator covers all supported sizes for all platforms. 42 // audio frames. This enumerator covers all supported sizes for all platforms.
45 // Example: k480 <=> 480 audio frames <=> 10ms@48kHz. 43 // Example: k480 <=> 480 audio frames <=> 10ms@48kHz.
46 // TODO(henrika): can be moved to the media namespace if more clients need it. 44 // TODO(henrika): can be moved to the media namespace if more clients need it.
47 // TODO(henrika): add support for k80 as well. Will be listed as unexpected for 45 // TODO(henrika): add support for k80 as well. Will be listed as unexpected for
48 // now. Very rare case though and most likeley only on Mac OS X. 46 // now. Very rare case though and most likeley only on Mac OS X.
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 bytes_per_sample_(0), 140 bytes_per_sample_(0),
143 initialized_(false), 141 initialized_(false),
144 playing_(false), 142 playing_(false),
145 recording_(false), 143 recording_(false),
146 agc_is_enabled_(false) { 144 agc_is_enabled_(false) {
147 DVLOG(1) << "WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()"; 145 DVLOG(1) << "WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()";
148 // TODO(henrika): remove this restriction when factory is used for the 146 // TODO(henrika): remove this restriction when factory is used for the
149 // input side as well. 147 // input side as well.
150 DCHECK(RenderThreadImpl::current()) << 148 DCHECK(RenderThreadImpl::current()) <<
151 "WebRtcAudioDeviceImpl must be constructed on the render thread"; 149 "WebRtcAudioDeviceImpl must be constructed on the render thread";
152 audio_output_device_ = AudioDeviceFactory::NewOutputDevice();
153 DCHECK(audio_output_device_);
154 } 150 }
155 151
156 WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl() { 152 WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl() {
157 DVLOG(1) << "WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl()"; 153 DVLOG(1) << "WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl()";
158 if (playing_) 154 if (playing_)
159 StopPlayout(); 155 StopPlayout();
160 if (recording_) 156 if (recording_)
161 StopRecording(); 157 StopRecording();
162 if (initialized_) 158 if (initialized_)
163 Terminate(); 159 Terminate();
164 } 160 }
165 161
166 int32_t WebRtcAudioDeviceImpl::AddRef() { 162 int32_t WebRtcAudioDeviceImpl::AddRef() {
167 return base::subtle::Barrier_AtomicIncrement(&ref_count_, 1); 163 return base::subtle::Barrier_AtomicIncrement(&ref_count_, 1);
168 } 164 }
169 165
170 int32_t WebRtcAudioDeviceImpl::Release() { 166 int32_t WebRtcAudioDeviceImpl::Release() {
171 int ret = base::subtle::Barrier_AtomicIncrement(&ref_count_, -1); 167 int ret = base::subtle::Barrier_AtomicIncrement(&ref_count_, -1);
172 if (ret == 0) { 168 if (ret == 0) {
173 delete this; 169 delete this;
174 } 170 }
175 return ret; 171 return ret;
176 } 172 }
177 173
178 int WebRtcAudioDeviceImpl::Render( 174 void WebRtcAudioDeviceImpl::RenderData(uint8* audio_data,
179 media::AudioBus* audio_bus, 175 int number_of_channels,
180 int audio_delay_milliseconds) { 176 int number_of_frames,
181 DCHECK_LE(audio_bus->frames(), output_buffer_size()); 177 int audio_delay_milliseconds) {
178 DCHECK_LE(number_of_frames, output_buffer_size());
182 179
183 { 180 {
184 base::AutoLock auto_lock(lock_); 181 base::AutoLock auto_lock(lock_);
185 // Store the reported audio delay locally. 182 // Store the reported audio delay locally.
186 output_delay_ms_ = audio_delay_milliseconds; 183 output_delay_ms_ = audio_delay_milliseconds;
187 } 184 }
188 185
189 const int channels = audio_bus->channels(); 186 const int channels = number_of_channels;
190 DCHECK_LE(channels, output_channels()); 187 DCHECK_LE(channels, output_channels());
191 188
192 int samples_per_sec = output_sample_rate(); 189 int samples_per_sec = output_sample_rate();
193 if (samples_per_sec == 44100) { 190 if (samples_per_sec == 44100) {
194 // Even if the hardware runs at 44.1kHz, we use 44.0 internally. 191 // Even if the hardware runs at 44.1kHz, we use 44.0 internally.
195 samples_per_sec = 44000; 192 samples_per_sec = 44000;
196 } 193 }
197 int samples_per_10_msec = (samples_per_sec / 100); 194 int samples_per_10_msec = (samples_per_sec / 100);
198 const int bytes_per_10_msec = 195 const int bytes_per_10_msec =
199 channels * samples_per_10_msec * bytes_per_sample_; 196 channels * samples_per_10_msec * bytes_per_sample_;
200 197
201 uint32_t num_audio_samples = 0; 198 uint32_t num_audio_samples = 0;
202 int accumulated_audio_samples = 0; 199 int accumulated_audio_samples = 0;
203 200
204 char* audio_byte_buffer = reinterpret_cast<char*>(output_buffer_.get());
205
206 // Get audio samples in blocks of 10 milliseconds from the registered 201 // Get audio samples in blocks of 10 milliseconds from the registered
207 // webrtc::AudioTransport source. Keep reading until our internal buffer 202 // webrtc::AudioTransport source. Keep reading until our internal buffer
208 // is full. 203 // is full.
209 while (accumulated_audio_samples < audio_bus->frames()) { 204 while (accumulated_audio_samples < number_of_frames) {
210 // Get 10ms and append output to temporary byte buffer. 205 // Get 10ms and append output to temporary byte buffer.
211 audio_transport_callback_->NeedMorePlayData(samples_per_10_msec, 206 audio_transport_callback_->NeedMorePlayData(samples_per_10_msec,
212 bytes_per_sample_, 207 bytes_per_sample_,
213 channels, 208 channels,
214 samples_per_sec, 209 samples_per_sec,
215 audio_byte_buffer, 210 audio_data,
216 num_audio_samples); 211 num_audio_samples);
217 accumulated_audio_samples += num_audio_samples; 212 accumulated_audio_samples += num_audio_samples;
218 audio_byte_buffer += bytes_per_10_msec; 213 audio_data += bytes_per_10_msec;
219 } 214 }
220
221 // Deinterleave each channel and convert to 32-bit floating-point
222 // with nominal range -1.0 -> +1.0 to match the callback format.
223 audio_bus->FromInterleaved(output_buffer_.get(), audio_bus->frames(),
224 bytes_per_sample_);
225 return audio_bus->frames();
226 } 215 }
227 216
228 void WebRtcAudioDeviceImpl::OnRenderError() { 217 void WebRtcAudioDeviceImpl::SetRenderFormat(media::AudioParameters params) {
229 DCHECK_EQ(MessageLoop::current(), ChildProcess::current()->io_message_loop()); 218 output_audio_parameters_ = params;
230 // TODO(henrika): Implement error handling.
231 LOG(ERROR) << "OnRenderError()";
232 } 219 }
233 220
234 void WebRtcAudioDeviceImpl::Capture(media::AudioBus* audio_bus, 221 void WebRtcAudioDeviceImpl::Capture(media::AudioBus* audio_bus,
235 int audio_delay_milliseconds, 222 int audio_delay_milliseconds,
236 double volume) { 223 double volume) {
237 DCHECK_LE(audio_bus->frames(), input_buffer_size()); 224 DCHECK_LE(audio_bus->frames(), input_buffer_size());
238 #if defined(OS_WIN) || defined(OS_MACOSX) 225 #if defined(OS_WIN) || defined(OS_MACOSX)
239 DCHECK_LE(volume, 1.0); 226 DCHECK_LE(volume, 1.0);
240 #elif defined(OS_LINUX) || defined(OS_OPENBSD) 227 #elif defined(OS_LINUX) || defined(OS_OPENBSD)
241 // We have a special situation on Linux where the microphone volume can be 228 // We have a special situation on Linux where the microphone volume can be
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 event.Wait(); 391 event.Wait();
405 return error; 392 return error;
406 } 393 }
407 394
408 // Calling Init() multiple times in a row is OK. 395 // Calling Init() multiple times in a row is OK.
409 if (initialized_) 396 if (initialized_)
410 return 0; 397 return 0;
411 398
412 DCHECK(!audio_input_device_); 399 DCHECK(!audio_input_device_);
413 DCHECK(!input_buffer_.get()); 400 DCHECK(!input_buffer_.get());
414 DCHECK(!output_buffer_.get());
415 401
416 // TODO(henrika): it could be possible to allow one of the directions (input 402 // TODO(henrika): it could be possible to allow one of the directions (input
417 // or output) to use a non-supported rate. As an example: if only the 403 // or output) to use a non-supported rate. As an example: if only the
418 // output rate is OK, we could finalize Init() and only set up an 404 // output rate is OK, we could finalize Init() and only set up an
419 // AudioOutputDevice. 405 // AudioOutputDevice.
420 406
421 // Ask the browser for the default audio output hardware sample-rate.
422 // This request is based on a synchronous IPC message.
423 int out_sample_rate = GetAudioOutputSampleRate();
424 DVLOG(1) << "Audio output hardware sample rate: " << out_sample_rate;
425 AddHistogramSampleRate(kAudioOutput, out_sample_rate);
426
427 // Verify that the reported output hardware sample rate is supported
428 // on the current platform.
429 if (std::find(&kValidOutputRates[0],
430 &kValidOutputRates[0] + arraysize(kValidOutputRates),
431 out_sample_rate) ==
432 &kValidOutputRates[arraysize(kValidOutputRates)]) {
433 DLOG(ERROR) << out_sample_rate << " is not a supported output rate.";
434 return -1;
435 }
436
437 // Ask the browser for the default audio input hardware sample-rate. 407 // Ask the browser for the default audio input hardware sample-rate.
438 // This request is based on a synchronous IPC message. 408 // This request is based on a synchronous IPC message.
439 int in_sample_rate = GetAudioInputSampleRate(); 409 int in_sample_rate = GetAudioInputSampleRate();
440 DVLOG(1) << "Audio input hardware sample rate: " << in_sample_rate; 410 DVLOG(1) << "Audio input hardware sample rate: " << in_sample_rate;
441 AddHistogramSampleRate(kAudioInput, in_sample_rate); 411 AddHistogramSampleRate(kAudioInput, in_sample_rate);
442 412
443 // Verify that the reported input hardware sample rate is supported 413 // Verify that the reported input hardware sample rate is supported
444 // on the current platform. 414 // on the current platform.
445 if (std::find(&kValidInputRates[0], 415 if (std::find(&kValidInputRates[0],
446 &kValidInputRates[0] + arraysize(kValidInputRates), 416 &kValidInputRates[0] + arraysize(kValidInputRates),
447 in_sample_rate) == 417 in_sample_rate) ==
448 &kValidInputRates[arraysize(kValidInputRates)]) { 418 &kValidInputRates[arraysize(kValidInputRates)]) {
449 DLOG(ERROR) << in_sample_rate << " is not a supported input rate."; 419 DLOG(ERROR) << in_sample_rate << " is not a supported input rate.";
450 return -1; 420 return -1;
451 } 421 }
452 422
453 // Ask the browser for the default number of audio input channels. 423 // Ask the browser for the default number of audio input channels.
454 // This request is based on a synchronous IPC message. 424 // This request is based on a synchronous IPC message.
455 ChannelLayout in_channel_layout = GetAudioInputChannelLayout(); 425 ChannelLayout in_channel_layout = GetAudioInputChannelLayout();
456 DVLOG(1) << "Audio input hardware channels: " << in_channel_layout; 426 DVLOG(1) << "Audio input hardware channels: " << in_channel_layout;
457 ChannelLayout out_channel_layout = media::CHANNEL_LAYOUT_MONO;
458 427
459 AudioParameters::Format in_format = AudioParameters::AUDIO_PCM_LINEAR; 428 AudioParameters::Format in_format = AudioParameters::AUDIO_PCM_LINEAR;
460 int in_buffer_size = 0; 429 int in_buffer_size = 0;
461 int out_buffer_size = 0;
462 430
463 // TODO(henrika): factor out all platform specific parts in separate 431 // TODO(henrika): factor out all platform specific parts in separate
464 // functions. Code is a bit messy right now. 432 // functions. Code is a bit messy right now.
465 433
466 // Windows 434 // Windows
467 #if defined(OS_WIN) 435 #if defined(OS_WIN)
468 // Always use stereo rendering on Windows.
469 out_channel_layout = media::CHANNEL_LAYOUT_STEREO;
470 436
471 DVLOG(1) << "Using AUDIO_PCM_LOW_LATENCY as input mode on Windows."; 437 DVLOG(1) << "Using AUDIO_PCM_LOW_LATENCY as input mode on Windows.";
472 in_format = AudioParameters::AUDIO_PCM_LOW_LATENCY; 438 in_format = AudioParameters::AUDIO_PCM_LOW_LATENCY;
473 439
474 // Capture side: AUDIO_PCM_LOW_LATENCY is based on the Core Audio (WASAPI) 440 // Capture side: AUDIO_PCM_LOW_LATENCY is based on the Core Audio (WASAPI)
475 // API which was introduced in Windows Vista. For lower Windows versions, 441 // API which was introduced in Windows Vista. For lower Windows versions,
476 // a callback-driven Wave implementation is used instead. An input buffer 442 // a callback-driven Wave implementation is used instead. An input buffer
477 // size of 10ms works well for both these implementations. 443 // size of 10ms works well for both these implementations.
478 444
479 // Use different buffer sizes depending on the current hardware sample rate. 445 // Use different buffer sizes depending on the current hardware sample rate.
480 if (in_sample_rate == 44100) { 446 if (in_sample_rate == 44100) {
481 // We do run at 44.1kHz at the actual audio layer, but ask for frames 447 // We do run at 44.1kHz at the actual audio layer, but ask for frames
482 // at 44.0kHz to ensure that we can feed them to the webrtc::VoiceEngine. 448 // at 44.0kHz to ensure that we can feed them to the webrtc::VoiceEngine.
483 in_buffer_size = 440; 449 in_buffer_size = 440;
484 } else { 450 } else {
485 in_buffer_size = (in_sample_rate / 100); 451 in_buffer_size = (in_sample_rate / 100);
486 DCHECK_EQ(in_buffer_size * 100, in_sample_rate) << 452 DCHECK_EQ(in_buffer_size * 100, in_sample_rate) <<
487 "Sample rate not supported. Should have been caught in Init()."; 453 "Sample rate not supported. Should have been caught in Init().";
488 } 454 }
489 455
490 // Render side: AUDIO_PCM_LOW_LATENCY is based on the Core Audio (WASAPI)
491 // API which was introduced in Windows Vista. For lower Windows versions,
492 // a callback-driven Wave implementation is used instead. An output buffer
493 // size of 10ms works well for WASAPI but 30ms is needed for Wave.
494
495 // Use different buffer sizes depending on the current hardware sample rate.
496 if (out_sample_rate == 96000 || out_sample_rate == 48000) {
497 out_buffer_size = (out_sample_rate / 100);
498 } else {
499 // We do run at 44.1kHz at the actual audio layer, but ask for frames
500 // at 44.0kHz to ensure that we can feed them to the webrtc::VoiceEngine.
501 // TODO(henrika): figure out why we seem to need 20ms here for glitch-
502 // free audio.
503 out_buffer_size = 2 * 440;
504 }
505
506 // Windows XP and lower can't cope with 10 ms output buffer size.
507 // It must be extended to 30 ms (60 ms will be used internally by WaveOut).
508 if (!media::IsWASAPISupported()) {
509 out_buffer_size = 3 * out_buffer_size;
510 DLOG(WARNING) << "Extending the output buffer size by a factor of three "
511 << "since Windows XP has been detected.";
512 }
513
514 // Mac OS X 456 // Mac OS X
515 #elif defined(OS_MACOSX) 457 #elif defined(OS_MACOSX)
516 out_channel_layout = media::CHANNEL_LAYOUT_MONO; 458 out_channel_layout = media::CHANNEL_LAYOUT_MONO;
517 459
518 DVLOG(1) << "Using AUDIO_PCM_LOW_LATENCY as input mode on Mac OS X."; 460 DVLOG(1) << "Using AUDIO_PCM_LOW_LATENCY as input mode on Mac OS X.";
519 in_format = AudioParameters::AUDIO_PCM_LOW_LATENCY; 461 in_format = AudioParameters::AUDIO_PCM_LOW_LATENCY;
520 462
521 // Capture side: AUDIO_PCM_LOW_LATENCY on Mac OS X is based on a callback- 463 // Capture side: AUDIO_PCM_LOW_LATENCY on Mac OS X is based on a callback-
522 // driven Core Audio implementation. Tests have shown that 10ms is a suitable 464 // driven Core Audio implementation. Tests have shown that 10ms is a suitable
523 // frame size to use, both for 48kHz and 44.1kHz. 465 // frame size to use, both for 48kHz and 44.1kHz.
524 466
525 // Use different buffer sizes depending on the current hardware sample rate. 467 // Use different buffer sizes depending on the current hardware sample rate.
526 if (in_sample_rate == 44100) { 468 if (in_sample_rate == 44100) {
527 // We do run at 44.1kHz at the actual audio layer, but ask for frames 469 // We do run at 44.1kHz at the actual audio layer, but ask for frames
528 // at 44.0kHz to ensure that we can feed them to the webrtc::VoiceEngine. 470 // at 44.0kHz to ensure that we can feed them to the webrtc::VoiceEngine.
529 in_buffer_size = 440; 471 in_buffer_size = 440;
530 } else { 472 } else {
531 in_buffer_size = (in_sample_rate / 100); 473 in_buffer_size = (in_sample_rate / 100);
532 DCHECK_EQ(in_buffer_size * 100, in_sample_rate) << 474 DCHECK_EQ(in_buffer_size * 100, in_sample_rate) <<
533 "Sample rate not supported. Should have been caught in Init()."; 475 "Sample rate not supported. Should have been caught in Init().";
534 } 476 }
535 477
536 // Render side: AUDIO_PCM_LOW_LATENCY on Mac OS X is based on a callback-
537 // driven Core Audio implementation. Tests have shown that 10ms is a suitable
538 // frame size to use, both for 48kHz and 44.1kHz.
539
540 // Use different buffer sizes depending on the current hardware sample rate.
541 if (out_sample_rate == 48000) {
542 out_buffer_size = 480;
543 } else {
544 // We do run at 44.1kHz at the actual audio layer, but ask for frames
545 // at 44.0kHz to ensure that we can feed them to the webrtc::VoiceEngine.
546 out_buffer_size = 440;
547 }
548 // Linux 478 // Linux
549 #elif defined(OS_LINUX) || defined(OS_OPENBSD) 479 #elif defined(OS_LINUX) || defined(OS_OPENBSD)
550 in_channel_layout = media::CHANNEL_LAYOUT_STEREO; 480 in_channel_layout = media::CHANNEL_LAYOUT_STEREO;
551 out_channel_layout = media::CHANNEL_LAYOUT_MONO;
552 481
553 // Based on tests using the current ALSA implementation in Chrome, we have 482 // Based on tests using the current ALSA implementation in Chrome, we have
554 // found that the best combination is 20ms on the input side and 10ms on the 483 // found that the best combination is 20ms on the input side and 10ms on the
555 // output side. 484 // output side.
556 // TODO(henrika): It might be possible to reduce the input buffer 485 // TODO(henrika): It might be possible to reduce the input buffer
557 // size and reduce the delay even more. 486 // size and reduce the delay even more.
558 in_buffer_size = 2 * 480; 487 in_buffer_size = 2 * 480;
559 out_buffer_size = 480; 488 #else
560 #else
561 DLOG(ERROR) << "Unsupported platform"; 489 DLOG(ERROR) << "Unsupported platform";
562 return -1; 490 return -1;
563 #endif 491 #endif
564 492
565 // Store utilized parameters to ensure that we can check them 493 // Store utilized parameters to ensure that we can check them
566 // after a successful initialization. 494 // after a successful initialization.
567 output_audio_parameters_.Reset(
568 AudioParameters::AUDIO_PCM_LOW_LATENCY, out_channel_layout,
569 out_sample_rate, 16, out_buffer_size);
570
571 input_audio_parameters_.Reset( 495 input_audio_parameters_.Reset(
572 in_format, in_channel_layout, in_sample_rate, 496 in_format, in_channel_layout, in_sample_rate,
573 16, in_buffer_size); 497 16, in_buffer_size);
574 498
575 // Create and configure the audio capturing client. 499 // Create and configure the audio capturing client.
576 audio_input_device_ = AudioDeviceFactory::NewInputDevice(); 500 audio_input_device_ = AudioDeviceFactory::NewInputDevice();
577 audio_input_device_->Initialize(input_audio_parameters_, this, this); 501 audio_input_device_->Initialize(input_audio_parameters_, this, this);
578 502
579 UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioOutputChannelLayout",
580 out_channel_layout, media::CHANNEL_LAYOUT_MAX);
581 UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputChannelLayout", 503 UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputChannelLayout",
582 in_channel_layout, media::CHANNEL_LAYOUT_MAX); 504 in_channel_layout, media::CHANNEL_LAYOUT_MAX);
583 AddHistogramFramesPerBuffer(kAudioOutput, out_buffer_size);
584 AddHistogramFramesPerBuffer(kAudioInput, in_buffer_size); 505 AddHistogramFramesPerBuffer(kAudioInput, in_buffer_size);
585 506
586 // Configure the audio rendering client.
587 audio_output_device_->Initialize(output_audio_parameters_, this);
588
589 DCHECK(audio_input_device_); 507 DCHECK(audio_input_device_);
590 508
591 // Allocate local audio buffers based on the parameters above. 509 // Allocate local audio buffers based on the parameters above.
592 // It is assumed that each audio sample contains 16 bits and each 510 // It is assumed that each audio sample contains 16 bits and each
593 // audio frame contains one or two audio samples depending on the 511 // audio frame contains one or two audio samples depending on the
594 // number of channels. 512 // number of channels.
595 input_buffer_.reset(new int16[input_buffer_size() * input_channels()]); 513 input_buffer_.reset(new int16[input_buffer_size() * input_channels()]);
596 output_buffer_.reset(new int16[output_buffer_size() * output_channels()]);
597 514
598 DCHECK(input_buffer_.get()); 515 DCHECK(input_buffer_.get());
599 DCHECK(output_buffer_.get());
600 516
601 bytes_per_sample_ = sizeof(*input_buffer_.get()); 517 bytes_per_sample_ = sizeof(*input_buffer_.get());
602 518
603 initialized_ = true; 519 initialized_ = true;
604 520
605 DVLOG(1) << "Capture parameters (size/channels/rate): (" 521 DVLOG(1) << "Capture parameters (size/channels/rate): ("
606 << input_buffer_size() << "/" << input_channels() << "/" 522 << input_buffer_size() << "/" << input_channels() << "/"
607 << input_sample_rate() << ")"; 523 << input_sample_rate() << ")";
608 DVLOG(1) << "Render parameters (size/channels/rate): (" 524 DVLOG(1) << "Render parameters (size/channels/rate): ("
609 << output_buffer_size() << "/" << output_channels() << "/" 525 << output_buffer_size() << "/" << output_channels() << "/"
(...skipping 10 matching lines...) Expand all
620 536
621 int32_t WebRtcAudioDeviceImpl::Terminate() { 537 int32_t WebRtcAudioDeviceImpl::Terminate() {
622 DVLOG(1) << "Terminate()"; 538 DVLOG(1) << "Terminate()";
623 539
624 // Calling Terminate() multiple times in a row is OK. 540 // Calling Terminate() multiple times in a row is OK.
625 if (!initialized_) 541 if (!initialized_)
626 return 0; 542 return 0;
627 543
628 DCHECK(audio_input_device_); 544 DCHECK(audio_input_device_);
629 DCHECK(input_buffer_.get()); 545 DCHECK(input_buffer_.get());
630 DCHECK(output_buffer_.get());
631 546
632 // Release all resources allocated in Init(). 547 // Release all resources allocated in Init().
633 audio_input_device_ = NULL; 548 audio_input_device_ = NULL;
634 input_buffer_.reset(); 549 input_buffer_.reset();
635 output_buffer_.reset();
636 550
637 initialized_ = false; 551 initialized_ = false;
638 return 0; 552 return 0;
639 } 553 }
640 554
641 bool WebRtcAudioDeviceImpl::Initialized() const { 555 bool WebRtcAudioDeviceImpl::Initialized() const {
642 return initialized_; 556 return initialized_;
643 } 557 }
644 558
645 int16_t WebRtcAudioDeviceImpl::PlayoutDevices() { 559 int16_t WebRtcAudioDeviceImpl::PlayoutDevices() {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
732 if (!audio_transport_callback_) { 646 if (!audio_transport_callback_) {
733 return -1; 647 return -1;
734 } 648 }
735 649
736 if (playing_) { 650 if (playing_) {
737 // webrtc::VoiceEngine assumes that it is OK to call Start() twice and 651 // webrtc::VoiceEngine assumes that it is OK to call Start() twice and
738 // that the call is ignored the second time. 652 // that the call is ignored the second time.
739 return 0; 653 return 0;
740 } 654 }
741 655
656 {
657 base::AutoLock auto_lock(lock_);
658 if (!renderer_)
659 return 0;
660
661 renderer_->Play();
662 }
663
664 playing_ = true;
665
742 start_render_time_ = base::Time::Now(); 666 start_render_time_ = base::Time::Now();
743 667
744 audio_output_device_->Start();
745 playing_ = true;
746 return 0; 668 return 0;
747 } 669 }
748 670
749 int32_t WebRtcAudioDeviceImpl::StopPlayout() { 671 int32_t WebRtcAudioDeviceImpl::StopPlayout() {
750 DVLOG(1) << "StopPlayout()"; 672 DVLOG(1) << "StopPlayout()";
751 if (!playing_) { 673 if (!playing_) {
752 // webrtc::VoiceEngine assumes that it is OK to call Stop() just in case. 674 // webrtc::VoiceEngine assumes that it is OK to call Stop() just in case.
753 return 0; 675 return 0;
754 } 676 }
755 677
756 // Add histogram data to be uploaded as part of an UMA logging event. 678 // Add histogram data to be uploaded as part of an UMA logging event.
757 // This histogram keeps track of total playout times. 679 // This histogram keeps track of total playout times.
758 if (!start_render_time_.is_null()) { 680 if (!start_render_time_.is_null()) {
759 base::TimeDelta render_time = base::Time::Now() - start_render_time_; 681 base::TimeDelta render_time = base::Time::Now() - start_render_time_;
760 UMA_HISTOGRAM_LONG_TIMES("WebRTC.AudioRenderTime", render_time); 682 UMA_HISTOGRAM_LONG_TIMES("WebRTC.AudioRenderTime", render_time);
761 } 683 }
762 684
763 audio_output_device_->Stop(); 685 {
686 base::AutoLock auto_lock(lock_);
687 if (!renderer_)
688 return 0;
689
690 renderer_->Pause();
691 }
692
764 playing_ = false; 693 playing_ = false;
765 return 0; 694 return 0;
766 } 695 }
767 696
768 bool WebRtcAudioDeviceImpl::Playing() const { 697 bool WebRtcAudioDeviceImpl::Playing() const {
769 return playing_; 698 return playing_;
770 } 699 }
771 700
772 int32_t WebRtcAudioDeviceImpl::StartRecording() { 701 int32_t WebRtcAudioDeviceImpl::StartRecording() {
773 DVLOG(1) << "StartRecording()"; 702 DVLOG(1) << "StartRecording()";
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after
1159 1088
1160 int32_t WebRtcAudioDeviceImpl::GetLoudspeakerStatus(bool* enabled) const { 1089 int32_t WebRtcAudioDeviceImpl::GetLoudspeakerStatus(bool* enabled) const {
1161 NOTIMPLEMENTED(); 1090 NOTIMPLEMENTED();
1162 return -1; 1091 return -1;
1163 } 1092 }
1164 1093
1165 void WebRtcAudioDeviceImpl::SetSessionId(int session_id) { 1094 void WebRtcAudioDeviceImpl::SetSessionId(int session_id) {
1166 session_id_ = session_id; 1095 session_id_ = session_id;
1167 } 1096 }
1168 1097
1098 void WebRtcAudioDeviceImpl::SetRenderer(WebRtcAudioRenderer* renderer) {
1099 DCHECK(!playing_);
1100
1101 base::AutoLock auto_lock(lock_);
1102 DCHECK(!renderer_);
1103 renderer_ = renderer;
1104 // Initialize the |renderer_| if it exists.
1105 if (renderer_) {
1106 renderer_->Initialize(this);
1107 }
1108 }
1109
1169 } // namespace content 1110 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698