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

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: addressed Andrew's comments and fixed some testbots' errors 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();
156 {
157 // It is necessary to stop the |renderer_| before going away.
158 base::AutoLock auto_lock(lock_);
159 if (renderer_)
160 renderer_->Stop();
161 }
160 if (recording_) 162 if (recording_)
161 StopRecording(); 163 StopRecording();
162 if (initialized_) 164 if (initialized_)
163 Terminate(); 165 Terminate();
164 } 166 }
165 167
166 int32_t WebRtcAudioDeviceImpl::AddRef() { 168 int32_t WebRtcAudioDeviceImpl::AddRef() {
167 return base::subtle::Barrier_AtomicIncrement(&ref_count_, 1); 169 return base::subtle::Barrier_AtomicIncrement(&ref_count_, 1);
168 } 170 }
169 171
170 int32_t WebRtcAudioDeviceImpl::Release() { 172 int32_t WebRtcAudioDeviceImpl::Release() {
171 int ret = base::subtle::Barrier_AtomicIncrement(&ref_count_, -1); 173 int ret = base::subtle::Barrier_AtomicIncrement(&ref_count_, -1);
172 if (ret == 0) { 174 if (ret == 0) {
173 delete this; 175 delete this;
174 } 176 }
175 return ret; 177 return ret;
176 } 178 }
177 179
178 int WebRtcAudioDeviceImpl::Render( 180 void WebRtcAudioDeviceImpl::RenderData(uint8* audio_data,
179 media::AudioBus* audio_bus, 181 int number_of_channels,
180 int audio_delay_milliseconds) { 182 int number_of_frames,
181 DCHECK_LE(audio_bus->frames(), output_buffer_size()); 183 int audio_delay_milliseconds) {
184 DCHECK_LE(number_of_frames, output_buffer_size());
182 185
183 { 186 {
184 base::AutoLock auto_lock(lock_); 187 base::AutoLock auto_lock(lock_);
185 // Store the reported audio delay locally. 188 // Store the reported audio delay locally.
186 output_delay_ms_ = audio_delay_milliseconds; 189 output_delay_ms_ = audio_delay_milliseconds;
187 } 190 }
188 191
189 const int channels = audio_bus->channels(); 192 const int channels = number_of_channels;
190 DCHECK_LE(channels, output_channels()); 193 DCHECK_LE(channels, output_channels());
191 194
192 int samples_per_sec = output_sample_rate(); 195 int samples_per_sec = output_sample_rate();
193 if (samples_per_sec == 44100) { 196 if (samples_per_sec == 44100) {
194 // Even if the hardware runs at 44.1kHz, we use 44.0 internally. 197 // Even if the hardware runs at 44.1kHz, we use 44.0 internally.
195 samples_per_sec = 44000; 198 samples_per_sec = 44000;
196 } 199 }
197 int samples_per_10_msec = (samples_per_sec / 100); 200 int samples_per_10_msec = (samples_per_sec / 100);
198 const int bytes_per_10_msec = 201 const int bytes_per_10_msec =
199 channels * samples_per_10_msec * bytes_per_sample_; 202 channels * samples_per_10_msec * bytes_per_sample_;
200 203
201 uint32_t num_audio_samples = 0; 204 uint32_t num_audio_samples = 0;
202 int accumulated_audio_samples = 0; 205 int accumulated_audio_samples = 0;
203 206
204 char* audio_byte_buffer = reinterpret_cast<char*>(output_buffer_.get());
205
206 // Get audio samples in blocks of 10 milliseconds from the registered 207 // Get audio samples in blocks of 10 milliseconds from the registered
207 // webrtc::AudioTransport source. Keep reading until our internal buffer 208 // webrtc::AudioTransport source. Keep reading until our internal buffer
208 // is full. 209 // is full.
209 while (accumulated_audio_samples < audio_bus->frames()) { 210 while (accumulated_audio_samples < number_of_frames) {
210 // Get 10ms and append output to temporary byte buffer. 211 // Get 10ms and append output to temporary byte buffer.
211 audio_transport_callback_->NeedMorePlayData(samples_per_10_msec, 212 audio_transport_callback_->NeedMorePlayData(samples_per_10_msec,
212 bytes_per_sample_, 213 bytes_per_sample_,
213 channels, 214 channels,
214 samples_per_sec, 215 samples_per_sec,
215 audio_byte_buffer, 216 audio_data,
216 num_audio_samples); 217 num_audio_samples);
217 accumulated_audio_samples += num_audio_samples; 218 accumulated_audio_samples += num_audio_samples;
218 audio_byte_buffer += bytes_per_10_msec; 219 audio_data += bytes_per_10_msec;
219 } 220 }
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 } 221 }
227 222
228 void WebRtcAudioDeviceImpl::OnRenderError() { 223 void WebRtcAudioDeviceImpl::SetRenderFormat(const AudioParameters& params) {
229 DCHECK_EQ(MessageLoop::current(), ChildProcess::current()->io_message_loop()); 224 output_audio_parameters_ = params;
230 // TODO(henrika): Implement error handling.
231 LOG(ERROR) << "OnRenderError()";
232 } 225 }
233 226
234 void WebRtcAudioDeviceImpl::Capture(media::AudioBus* audio_bus, 227 void WebRtcAudioDeviceImpl::Capture(media::AudioBus* audio_bus,
235 int audio_delay_milliseconds, 228 int audio_delay_milliseconds,
236 double volume) { 229 double volume) {
237 DCHECK_LE(audio_bus->frames(), input_buffer_size()); 230 DCHECK_LE(audio_bus->frames(), input_buffer_size());
238 #if defined(OS_WIN) || defined(OS_MACOSX) 231 #if defined(OS_WIN) || defined(OS_MACOSX)
239 DCHECK_LE(volume, 1.0); 232 DCHECK_LE(volume, 1.0);
240 #elif defined(OS_LINUX) || defined(OS_OPENBSD) 233 #elif defined(OS_LINUX) || defined(OS_OPENBSD)
241 // We have a special situation on Linux where the microphone volume can be 234 // 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(); 397 event.Wait();
405 return error; 398 return error;
406 } 399 }
407 400
408 // Calling Init() multiple times in a row is OK. 401 // Calling Init() multiple times in a row is OK.
409 if (initialized_) 402 if (initialized_)
410 return 0; 403 return 0;
411 404
412 DCHECK(!audio_input_device_); 405 DCHECK(!audio_input_device_);
413 DCHECK(!input_buffer_.get()); 406 DCHECK(!input_buffer_.get());
414 DCHECK(!output_buffer_.get());
415 407
416 // TODO(henrika): it could be possible to allow one of the directions (input 408 // 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 409 // 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 410 // output rate is OK, we could finalize Init() and only set up an
419 // AudioOutputDevice. 411 // AudioOutputDevice.
420 412
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. 413 // Ask the browser for the default audio input hardware sample-rate.
438 // This request is based on a synchronous IPC message. 414 // This request is based on a synchronous IPC message.
439 int in_sample_rate = GetAudioInputSampleRate(); 415 int in_sample_rate = GetAudioInputSampleRate();
440 DVLOG(1) << "Audio input hardware sample rate: " << in_sample_rate; 416 DVLOG(1) << "Audio input hardware sample rate: " << in_sample_rate;
441 AddHistogramSampleRate(kAudioInput, in_sample_rate); 417 AddHistogramSampleRate(kAudioInput, in_sample_rate);
442 418
443 // Verify that the reported input hardware sample rate is supported 419 // Verify that the reported input hardware sample rate is supported
444 // on the current platform. 420 // on the current platform.
445 if (std::find(&kValidInputRates[0], 421 if (std::find(&kValidInputRates[0],
446 &kValidInputRates[0] + arraysize(kValidInputRates), 422 &kValidInputRates[0] + arraysize(kValidInputRates),
447 in_sample_rate) == 423 in_sample_rate) ==
448 &kValidInputRates[arraysize(kValidInputRates)]) { 424 &kValidInputRates[arraysize(kValidInputRates)]) {
449 DLOG(ERROR) << in_sample_rate << " is not a supported input rate."; 425 DLOG(ERROR) << in_sample_rate << " is not a supported input rate.";
450 return -1; 426 return -1;
451 } 427 }
452 428
453 // Ask the browser for the default number of audio input channels. 429 // Ask the browser for the default number of audio input channels.
454 // This request is based on a synchronous IPC message. 430 // This request is based on a synchronous IPC message.
455 ChannelLayout in_channel_layout = GetAudioInputChannelLayout(); 431 ChannelLayout in_channel_layout = GetAudioInputChannelLayout();
456 DVLOG(1) << "Audio input hardware channels: " << in_channel_layout; 432 DVLOG(1) << "Audio input hardware channels: " << in_channel_layout;
457 ChannelLayout out_channel_layout = media::CHANNEL_LAYOUT_MONO;
458 433
459 AudioParameters::Format in_format = AudioParameters::AUDIO_PCM_LINEAR; 434 AudioParameters::Format in_format = AudioParameters::AUDIO_PCM_LINEAR;
460 int in_buffer_size = 0; 435 int in_buffer_size = 0;
461 int out_buffer_size = 0;
462 436
463 // TODO(henrika): factor out all platform specific parts in separate 437 // TODO(henrika): factor out all platform specific parts in separate
464 // functions. Code is a bit messy right now. 438 // functions. Code is a bit messy right now.
465 439
466 // Windows 440 // Windows
467 #if defined(OS_WIN) 441 #if defined(OS_WIN)
468 // Always use stereo rendering on Windows.
469 out_channel_layout = media::CHANNEL_LAYOUT_STEREO;
470
471 DVLOG(1) << "Using AUDIO_PCM_LOW_LATENCY as input mode on Windows."; 442 DVLOG(1) << "Using AUDIO_PCM_LOW_LATENCY as input mode on Windows.";
472 in_format = AudioParameters::AUDIO_PCM_LOW_LATENCY; 443 in_format = AudioParameters::AUDIO_PCM_LOW_LATENCY;
473 444
474 // Capture side: AUDIO_PCM_LOW_LATENCY is based on the Core Audio (WASAPI) 445 // 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, 446 // API which was introduced in Windows Vista. For lower Windows versions,
476 // a callback-driven Wave implementation is used instead. An input buffer 447 // a callback-driven Wave implementation is used instead. An input buffer
477 // size of 10ms works well for both these implementations. 448 // size of 10ms works well for both these implementations.
478 449
479 // Use different buffer sizes depending on the current hardware sample rate. 450 // Use different buffer sizes depending on the current hardware sample rate.
480 if (in_sample_rate == 44100) { 451 if (in_sample_rate == 44100) {
481 // We do run at 44.1kHz at the actual audio layer, but ask for frames 452 // 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. 453 // at 44.0kHz to ensure that we can feed them to the webrtc::VoiceEngine.
483 in_buffer_size = 440; 454 in_buffer_size = 440;
484 } else { 455 } else {
485 in_buffer_size = (in_sample_rate / 100); 456 in_buffer_size = (in_sample_rate / 100);
486 DCHECK_EQ(in_buffer_size * 100, in_sample_rate) << 457 DCHECK_EQ(in_buffer_size * 100, in_sample_rate) <<
487 "Sample rate not supported. Should have been caught in Init()."; 458 "Sample rate not supported. Should have been caught in Init().";
488 } 459 }
489 460
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 461 // Mac OS X
515 #elif defined(OS_MACOSX) 462 #elif defined(OS_MACOSX)
516 out_channel_layout = media::CHANNEL_LAYOUT_MONO;
517
518 DVLOG(1) << "Using AUDIO_PCM_LOW_LATENCY as input mode on Mac OS X."; 463 DVLOG(1) << "Using AUDIO_PCM_LOW_LATENCY as input mode on Mac OS X.";
519 in_format = AudioParameters::AUDIO_PCM_LOW_LATENCY; 464 in_format = AudioParameters::AUDIO_PCM_LOW_LATENCY;
520 465
521 // Capture side: AUDIO_PCM_LOW_LATENCY on Mac OS X is based on a callback- 466 // 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 467 // driven Core Audio implementation. Tests have shown that 10ms is a suitable
523 // frame size to use, both for 48kHz and 44.1kHz. 468 // frame size to use, both for 48kHz and 44.1kHz.
524 469
525 // Use different buffer sizes depending on the current hardware sample rate. 470 // Use different buffer sizes depending on the current hardware sample rate.
526 if (in_sample_rate == 44100) { 471 if (in_sample_rate == 44100) {
527 // We do run at 44.1kHz at the actual audio layer, but ask for frames 472 // 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. 473 // at 44.0kHz to ensure that we can feed them to the webrtc::VoiceEngine.
529 in_buffer_size = 440; 474 in_buffer_size = 440;
530 } else { 475 } else {
531 in_buffer_size = (in_sample_rate / 100); 476 in_buffer_size = (in_sample_rate / 100);
532 DCHECK_EQ(in_buffer_size * 100, in_sample_rate) << 477 DCHECK_EQ(in_buffer_size * 100, in_sample_rate) <<
533 "Sample rate not supported. Should have been caught in Init()."; 478 "Sample rate not supported. Should have been caught in Init().";
534 } 479 }
535 480
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 481 // Linux
549 #elif defined(OS_LINUX) || defined(OS_OPENBSD) 482 #elif defined(OS_LINUX) || defined(OS_OPENBSD)
550 in_channel_layout = media::CHANNEL_LAYOUT_STEREO; 483 in_channel_layout = media::CHANNEL_LAYOUT_STEREO;
551 out_channel_layout = media::CHANNEL_LAYOUT_MONO;
552 484
553 // Based on tests using the current ALSA implementation in Chrome, we have 485 // 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 486 // found that the best combination is 20ms on the input side and 10ms on the
555 // output side. 487 // output side.
556 // TODO(henrika): It might be possible to reduce the input buffer 488 // TODO(henrika): It might be possible to reduce the input buffer
557 // size and reduce the delay even more. 489 // size and reduce the delay even more.
558 in_buffer_size = 2 * 480; 490 in_buffer_size = 2 * 480;
559 out_buffer_size = 480;
560 #else 491 #else
561 DLOG(ERROR) << "Unsupported platform"; 492 DLOG(ERROR) << "Unsupported platform";
562 return -1; 493 return -1;
563 #endif 494 #endif
564 495
565 // Store utilized parameters to ensure that we can check them 496 // Store utilized parameters to ensure that we can check them
566 // after a successful initialization. 497 // 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( 498 input_audio_parameters_.Reset(
572 in_format, in_channel_layout, in_sample_rate, 499 in_format, in_channel_layout, in_sample_rate,
573 16, in_buffer_size); 500 16, in_buffer_size);
574 501
575 // Create and configure the audio capturing client. 502 // Create and configure the audio capturing client.
576 audio_input_device_ = AudioDeviceFactory::NewInputDevice(); 503 audio_input_device_ = AudioDeviceFactory::NewInputDevice();
577 audio_input_device_->Initialize(input_audio_parameters_, this, this); 504 audio_input_device_->Initialize(input_audio_parameters_, this, this);
578 505
579 UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioOutputChannelLayout",
580 out_channel_layout, media::CHANNEL_LAYOUT_MAX);
581 UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputChannelLayout", 506 UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputChannelLayout",
582 in_channel_layout, media::CHANNEL_LAYOUT_MAX); 507 in_channel_layout, media::CHANNEL_LAYOUT_MAX);
583 AddHistogramFramesPerBuffer(kAudioOutput, out_buffer_size);
584 AddHistogramFramesPerBuffer(kAudioInput, in_buffer_size); 508 AddHistogramFramesPerBuffer(kAudioInput, in_buffer_size);
585 509
586 // Configure the audio rendering client.
587 audio_output_device_->Initialize(output_audio_parameters_, this);
588
589 DCHECK(audio_input_device_); 510 DCHECK(audio_input_device_);
590 511
591 // Allocate local audio buffers based on the parameters above. 512 // Allocate local audio buffers based on the parameters above.
592 // It is assumed that each audio sample contains 16 bits and each 513 // It is assumed that each audio sample contains 16 bits and each
593 // audio frame contains one or two audio samples depending on the 514 // audio frame contains one or two audio samples depending on the
594 // number of channels. 515 // number of channels.
595 input_buffer_.reset(new int16[input_buffer_size() * input_channels()]); 516 input_buffer_.reset(new int16[input_buffer_size() * input_channels()]);
596 output_buffer_.reset(new int16[output_buffer_size() * output_channels()]);
597 517
598 DCHECK(input_buffer_.get()); 518 DCHECK(input_buffer_.get());
599 DCHECK(output_buffer_.get());
600 519
601 bytes_per_sample_ = sizeof(*input_buffer_.get()); 520 bytes_per_sample_ = sizeof(*input_buffer_.get());
602 521
603 initialized_ = true; 522 initialized_ = true;
604 523
605 DVLOG(1) << "Capture parameters (size/channels/rate): (" 524 DVLOG(1) << "Capture parameters (size/channels/rate): ("
606 << input_buffer_size() << "/" << input_channels() << "/" 525 << input_buffer_size() << "/" << input_channels() << "/"
607 << input_sample_rate() << ")"; 526 << input_sample_rate() << ")";
608 DVLOG(1) << "Render parameters (size/channels/rate): (" 527 DVLOG(1) << "Render parameters (size/channels/rate): ("
609 << output_buffer_size() << "/" << output_channels() << "/" 528 << output_buffer_size() << "/" << output_channels() << "/"
(...skipping 10 matching lines...) Expand all
620 539
621 int32_t WebRtcAudioDeviceImpl::Terminate() { 540 int32_t WebRtcAudioDeviceImpl::Terminate() {
622 DVLOG(1) << "Terminate()"; 541 DVLOG(1) << "Terminate()";
623 542
624 // Calling Terminate() multiple times in a row is OK. 543 // Calling Terminate() multiple times in a row is OK.
625 if (!initialized_) 544 if (!initialized_)
626 return 0; 545 return 0;
627 546
628 DCHECK(audio_input_device_); 547 DCHECK(audio_input_device_);
629 DCHECK(input_buffer_.get()); 548 DCHECK(input_buffer_.get());
630 DCHECK(output_buffer_.get());
631 549
632 // Release all resources allocated in Init(). 550 // Release all resources allocated in Init().
633 audio_input_device_ = NULL; 551 audio_input_device_ = NULL;
634 input_buffer_.reset(); 552 input_buffer_.reset();
635 output_buffer_.reset();
636 553
637 initialized_ = false; 554 initialized_ = false;
638 return 0; 555 return 0;
639 } 556 }
640 557
641 bool WebRtcAudioDeviceImpl::Initialized() const { 558 bool WebRtcAudioDeviceImpl::Initialized() const {
642 return initialized_; 559 return initialized_;
643 } 560 }
644 561
645 int16_t WebRtcAudioDeviceImpl::PlayoutDevices() { 562 int16_t WebRtcAudioDeviceImpl::PlayoutDevices() {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
732 if (!audio_transport_callback_) { 649 if (!audio_transport_callback_) {
733 return -1; 650 return -1;
734 } 651 }
735 652
736 if (playing_) { 653 if (playing_) {
737 // webrtc::VoiceEngine assumes that it is OK to call Start() twice and 654 // webrtc::VoiceEngine assumes that it is OK to call Start() twice and
738 // that the call is ignored the second time. 655 // that the call is ignored the second time.
739 return 0; 656 return 0;
740 } 657 }
741 658
659 {
660 base::AutoLock auto_lock(lock_);
661 if (!renderer_)
662 return -1;
663
664 renderer_->Play();
665 }
666
667 playing_ = true;
668
742 start_render_time_ = base::Time::Now(); 669 start_render_time_ = base::Time::Now();
743 670
744 audio_output_device_->Start();
745 playing_ = true;
746 return 0; 671 return 0;
747 } 672 }
748 673
749 int32_t WebRtcAudioDeviceImpl::StopPlayout() { 674 int32_t WebRtcAudioDeviceImpl::StopPlayout() {
750 DVLOG(1) << "StopPlayout()"; 675 DVLOG(1) << "StopPlayout()";
751 if (!playing_) { 676 if (!playing_) {
752 // webrtc::VoiceEngine assumes that it is OK to call Stop() just in case. 677 // webrtc::VoiceEngine assumes that it is OK to call Stop() just in case.
753 return 0; 678 return 0;
754 } 679 }
755 680
756 // Add histogram data to be uploaded as part of an UMA logging event. 681 // Add histogram data to be uploaded as part of an UMA logging event.
757 // This histogram keeps track of total playout times. 682 // This histogram keeps track of total playout times.
758 if (!start_render_time_.is_null()) { 683 if (!start_render_time_.is_null()) {
759 base::TimeDelta render_time = base::Time::Now() - start_render_time_; 684 base::TimeDelta render_time = base::Time::Now() - start_render_time_;
760 UMA_HISTOGRAM_LONG_TIMES("WebRTC.AudioRenderTime", render_time); 685 UMA_HISTOGRAM_LONG_TIMES("WebRTC.AudioRenderTime", render_time);
761 } 686 }
762 687
763 audio_output_device_->Stop(); 688 {
689 base::AutoLock auto_lock(lock_);
690 if (!renderer_)
691 return -1;
692
693 renderer_->Pause();
scherkus (not reviewing) 2012/10/26 17:28:22 which thread is this being called on? is seems a
no longer working on chromium 2012/10/29 15:01:36 It is called on libjingle thread.
694 }
695
764 playing_ = false; 696 playing_ = false;
765 return 0; 697 return 0;
766 } 698 }
767 699
768 bool WebRtcAudioDeviceImpl::Playing() const { 700 bool WebRtcAudioDeviceImpl::Playing() const {
769 return playing_; 701 return playing_;
770 } 702 }
771 703
772 int32_t WebRtcAudioDeviceImpl::StartRecording() { 704 int32_t WebRtcAudioDeviceImpl::StartRecording() {
773 DVLOG(1) << "StartRecording()"; 705 DVLOG(1) << "StartRecording()";
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after
1159 1091
1160 int32_t WebRtcAudioDeviceImpl::GetLoudspeakerStatus(bool* enabled) const { 1092 int32_t WebRtcAudioDeviceImpl::GetLoudspeakerStatus(bool* enabled) const {
1161 NOTIMPLEMENTED(); 1093 NOTIMPLEMENTED();
1162 return -1; 1094 return -1;
1163 } 1095 }
1164 1096
1165 void WebRtcAudioDeviceImpl::SetSessionId(int session_id) { 1097 void WebRtcAudioDeviceImpl::SetSessionId(int session_id) {
1166 session_id_ = session_id; 1098 session_id_ = session_id;
1167 } 1099 }
1168 1100
1101 bool WebRtcAudioDeviceImpl::SetRenderer(WebRtcAudioRenderer* renderer) {
1102 DCHECK(renderer);
1103
1104 base::AutoLock auto_lock(lock_);
1105 if (renderer_)
1106 return false;
1107
1108 if (!renderer->Initialize(this))
1109 return false;
1110
1111 renderer_ = renderer;
1112 return true;
1113 }
1114
1169 } // namespace content 1115 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698