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

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

Issue 139303016: Feed the render data to MediaStreamAudioProcessor and used AudioBus in render callback (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: addressed Per's comments. Created 6 years, 11 months 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/strings/string_util.h" 9 #include "base/strings/string_util.h"
10 #include "base/win/windows_version.h" 10 #include "base/win/windows_version.h"
11 #include "content/renderer/media/webrtc_audio_capturer.h" 11 #include "content/renderer/media/webrtc_audio_capturer.h"
12 #include "content/renderer/media/webrtc_audio_renderer.h" 12 #include "content/renderer/media/webrtc_audio_renderer.h"
13 #include "content/renderer/render_thread_impl.h" 13 #include "content/renderer/render_thread_impl.h"
14 #include "media/audio/audio_parameters.h" 14 #include "media/audio/audio_parameters.h"
15 #include "media/audio/sample_rates.h" 15 #include "media/audio/sample_rates.h"
16 16
17 using media::AudioParameters; 17 using media::AudioParameters;
18 using media::ChannelLayout; 18 using media::ChannelLayout;
19 19
20 namespace content { 20 namespace content {
21 21
22 WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl() 22 WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()
23 : ref_count_(0), 23 : ref_count_(0),
24 audio_transport_callback_(NULL), 24 audio_transport_callback_(NULL),
25 input_delay_ms_(0), 25 input_delay_ms_(0),
26 output_delay_ms_(0), 26 output_delay_ms_(0),
27 initialized_(false), 27 initialized_(false),
28 playing_(false), 28 playing_(false),
29 recording_(false), 29 recording_(false),
30 microphone_volume_(0) { 30 microphone_volume_(0),
31 render_buffer_size_(0) {
31 DVLOG(1) << "WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()"; 32 DVLOG(1) << "WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()";
32 } 33 }
33 34
34 WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl() { 35 WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl() {
35 DVLOG(1) << "WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl()"; 36 DVLOG(1) << "WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl()";
36 DCHECK(thread_checker_.CalledOnValidThread()); 37 DCHECK(thread_checker_.CalledOnValidThread());
37 Terminate(); 38 Terminate();
38 } 39 }
39 40
40 int32_t WebRtcAudioDeviceImpl::AddRef() { 41 int32_t WebRtcAudioDeviceImpl::AddRef() {
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 } 115 }
115 116
116 return new_volume; 117 return new_volume;
117 } 118 }
118 119
119 void WebRtcAudioDeviceImpl::OnSetFormat( 120 void WebRtcAudioDeviceImpl::OnSetFormat(
120 const media::AudioParameters& params) { 121 const media::AudioParameters& params) {
121 DVLOG(1) << "WebRtcAudioDeviceImpl::OnSetFormat()"; 122 DVLOG(1) << "WebRtcAudioDeviceImpl::OnSetFormat()";
122 } 123 }
123 124
124 void WebRtcAudioDeviceImpl::RenderData(uint8* audio_data, 125 void WebRtcAudioDeviceImpl::RenderData(media::AudioBus* audio_bus,
125 int number_of_channels, 126 int sample_rate,
126 int number_of_frames,
127 int audio_delay_milliseconds) { 127 int audio_delay_milliseconds) {
128 DCHECK_LE(number_of_frames, output_buffer_size()); 128 if (!render_buffer_ ||
miu 2014/01/24 22:27:19 You could simplify a lot here if render_buffer_ we
129 render_buffer_size_ != (audio_bus->frames() * audio_bus->channels())) {
130 render_buffer_size_ = audio_bus->frames() * audio_bus->channels();
131 render_buffer_.reset(new int16[render_buffer_size_]);
132 }
133
129 { 134 {
130 base::AutoLock auto_lock(lock_); 135 base::AutoLock auto_lock(lock_);
131 DCHECK(audio_transport_callback_); 136 DCHECK(audio_transport_callback_);
132 // Store the reported audio delay locally. 137 // Store the reported audio delay locally.
133 output_delay_ms_ = audio_delay_milliseconds; 138 output_delay_ms_ = audio_delay_milliseconds;
134 } 139 }
135 140
136 const int channels = number_of_channels; 141 int samples_per_10_msec = (sample_rate / 100);
137 DCHECK_LE(channels, output_channels()); 142 int bytes_per_sample = 2;
miu 2014/01/24 22:27:19 Replace 2 with sizeof(int16).
no longer working on chromium 2014/01/27 17:09:33 Done with changing it to sizeof(render_buffer_[0])
138
139 int samples_per_sec = output_sample_rate();
140 int samples_per_10_msec = (samples_per_sec / 100);
141 int bytes_per_sample = output_audio_parameters_.bits_per_sample() / 8;
142 const int bytes_per_10_msec = 143 const int bytes_per_10_msec =
143 channels * samples_per_10_msec * bytes_per_sample; 144 audio_bus->channels() * samples_per_10_msec * bytes_per_sample;
144 145 DCHECK_EQ(audio_bus->frames() % samples_per_10_msec, 0);
145 uint32_t num_audio_samples = 0;
146 int accumulated_audio_samples = 0;
147 146
148 // Get audio samples in blocks of 10 milliseconds from the registered 147 // Get audio samples in blocks of 10 milliseconds from the registered
149 // webrtc::AudioTransport source. Keep reading until our internal buffer 148 // webrtc::AudioTransport source. Keep reading until our internal buffer
150 // is full. 149 // is full.
151 while (accumulated_audio_samples < number_of_frames) { 150 uint32_t num_audio_samples = 0;
151 int accumulated_audio_samples = 0;
152 int16* audio_data = render_buffer_.get();
153 while (accumulated_audio_samples < audio_bus->frames()) {
152 // Get 10ms and append output to temporary byte buffer. 154 // Get 10ms and append output to temporary byte buffer.
153 audio_transport_callback_->NeedMorePlayData(samples_per_10_msec, 155 audio_transport_callback_->NeedMorePlayData(samples_per_10_msec,
154 bytes_per_sample, 156 bytes_per_sample,
155 channels, 157 audio_bus->channels(),
156 samples_per_sec, 158 sample_rate,
157 audio_data, 159 audio_data,
158 num_audio_samples); 160 num_audio_samples);
159 accumulated_audio_samples += num_audio_samples; 161 accumulated_audio_samples += num_audio_samples;
160 audio_data += bytes_per_10_msec; 162 audio_data += bytes_per_10_msec;
161 } 163 }
162 }
163 164
164 void WebRtcAudioDeviceImpl::SetRenderFormat(const AudioParameters& params) { 165 // De-interleave each channel and convert to 32-bit floating-point
165 DCHECK(thread_checker_.CalledOnValidThread()); 166 // with nominal range -1.0 -> +1.0 to match the callback format.
166 output_audio_parameters_ = params; 167 audio_bus->FromInterleaved(render_buffer_.get(),
168 audio_bus->frames(),
169 bytes_per_sample);
170
171 // Pass the render data to the observers.
172 base::AutoLock auto_lock(lock_);
173 for (RenderDataObservers::const_iterator it = render_data_observers_.begin();
174 it != render_data_observers_.end(); ++it) {
175 (*it)->RenderData(audio_bus, sample_rate, audio_delay_milliseconds);
176 }
167 } 177 }
168 178
169 void WebRtcAudioDeviceImpl::RemoveAudioRenderer(WebRtcAudioRenderer* renderer) { 179 void WebRtcAudioDeviceImpl::RemoveAudioRenderer(WebRtcAudioRenderer* renderer) {
170 DCHECK(thread_checker_.CalledOnValidThread()); 180 DCHECK(thread_checker_.CalledOnValidThread());
171 DCHECK_EQ(renderer, renderer_); 181 DCHECK_EQ(renderer, renderer_);
172 base::AutoLock auto_lock(lock_); 182 base::AutoLock auto_lock(lock_);
173 renderer_ = NULL; 183 renderer_ = NULL;
174 playing_ = false; 184 playing_ = false;
175 } 185 }
176 186
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 return 0; 372 return 0;
363 } 373 }
364 374
365 int32_t WebRtcAudioDeviceImpl::MinMicrophoneVolume(uint32_t* min_volume) const { 375 int32_t WebRtcAudioDeviceImpl::MinMicrophoneVolume(uint32_t* min_volume) const {
366 *min_volume = 0; 376 *min_volume = 0;
367 return 0; 377 return 0;
368 } 378 }
369 379
370 int32_t WebRtcAudioDeviceImpl::StereoPlayoutIsAvailable(bool* available) const { 380 int32_t WebRtcAudioDeviceImpl::StereoPlayoutIsAvailable(bool* available) const {
371 DCHECK(initialized_); 381 DCHECK(initialized_);
372 *available = (output_channels() == 2); 382 *available = renderer_ ? (renderer_->channels() == 2) : false;
miu 2014/01/24 22:27:19 For my own curiosity: What if renderer_->channels(
no longer working on chromium 2014/01/27 17:09:33 The playout of the webrtc only supports mono and s
373 return 0; 383 return 0;
374 } 384 }
375 385
376 int32_t WebRtcAudioDeviceImpl::StereoRecordingIsAvailable( 386 int32_t WebRtcAudioDeviceImpl::StereoRecordingIsAvailable(
377 bool* available) const { 387 bool* available) const {
378 DCHECK(initialized_); 388 DCHECK(initialized_);
379 // TODO(xians): These kind of hardware methods do not make much sense since we 389 // TODO(xians): These kind of hardware methods do not make much sense since we
380 // support multiple sources. Remove or figure out new APIs for such methods. 390 // support multiple sources. Remove or figure out new APIs for such methods.
381 scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer()); 391 scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer());
382 if (!capturer.get()) 392 if (!capturer.get())
(...skipping 22 matching lines...) Expand all
405 if (!capturer.get()) 415 if (!capturer.get())
406 return -1; 416 return -1;
407 417
408 *samples_per_sec = static_cast<uint32_t>( 418 *samples_per_sec = static_cast<uint32_t>(
409 capturer->source_audio_parameters().sample_rate()); 419 capturer->source_audio_parameters().sample_rate());
410 return 0; 420 return 0;
411 } 421 }
412 422
413 int32_t WebRtcAudioDeviceImpl::PlayoutSampleRate( 423 int32_t WebRtcAudioDeviceImpl::PlayoutSampleRate(
414 uint32_t* samples_per_sec) const { 424 uint32_t* samples_per_sec) const {
415 *samples_per_sec = static_cast<uint32_t>(output_sample_rate()); 425 *samples_per_sec = renderer_ ? renderer_->sample_rate() : 0;
416 return 0; 426 return 0;
417 } 427 }
418 428
419 bool WebRtcAudioDeviceImpl::SetAudioRenderer(WebRtcAudioRenderer* renderer) { 429 bool WebRtcAudioDeviceImpl::SetAudioRenderer(WebRtcAudioRenderer* renderer) {
420 DCHECK(thread_checker_.CalledOnValidThread()); 430 DCHECK(thread_checker_.CalledOnValidThread());
421 DCHECK(renderer); 431 DCHECK(renderer);
422 432
423 base::AutoLock auto_lock(lock_); 433 base::AutoLock auto_lock(lock_);
424 if (renderer_.get()) 434 if (renderer_.get())
425 return false; 435 return false;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 // Use the last |capturer| which is from the latest getUserMedia call as 468 // Use the last |capturer| which is from the latest getUserMedia call as
459 // the default capture device. 469 // the default capture device.
460 for (CapturerList::const_reverse_iterator iter = capturers_.rbegin(); 470 for (CapturerList::const_reverse_iterator iter = capturers_.rbegin();
461 iter != capturers_.rend(); ++iter) { 471 iter != capturers_.rend(); ++iter) {
462 return *iter; 472 return *iter;
463 } 473 }
464 474
465 return NULL; 475 return NULL;
466 } 476 }
467 477
478 void WebRtcAudioDeviceImpl::AddRenderDataObserver(
479 WebRtcAudioRendererSource* observer) {
480 DCHECK(observer);
481 base::AutoLock auto_lock(lock_);
482 DCHECK(std::find(render_data_observers_.begin(),
483 render_data_observers_.end(),
484 observer) == render_data_observers_.end());
485 render_data_observers_.push_back(observer);
486 }
487
488 void WebRtcAudioDeviceImpl::RemoveRenderDataObserver(
489 WebRtcAudioRendererSource* observer) {
490 DCHECK(observer);
491 base::AutoLock auto_lock(lock_);
492 render_data_observers_.remove(observer);
493 }
494
468 bool WebRtcAudioDeviceImpl::GetAuthorizedDeviceInfoForAudioRenderer( 495 bool WebRtcAudioDeviceImpl::GetAuthorizedDeviceInfoForAudioRenderer(
469 int* session_id, 496 int* session_id,
470 int* output_sample_rate, 497 int* output_sample_rate,
471 int* output_frames_per_buffer) { 498 int* output_frames_per_buffer) {
472 DCHECK(thread_checker_.CalledOnValidThread()); 499 DCHECK(thread_checker_.CalledOnValidThread());
473 // If there is no capturer or there are more than one open capture devices, 500 // If there is no capturer or there are more than one open capture devices,
474 // return false. 501 // return false.
475 if (capturers_.empty() || capturers_.size() > 1) 502 if (capturers_.empty() || capturers_.size() > 1)
476 return false; 503 return false;
477 504
478 return GetDefaultCapturer()->GetPairedOutputParameters( 505 return GetDefaultCapturer()->GetPairedOutputParameters(
479 session_id, output_sample_rate, output_frames_per_buffer); 506 session_id, output_sample_rate, output_frames_per_buffer);
480 } 507 }
481 508
482 } // namespace content 509 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698