OLD | NEW |
---|---|
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" |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
114 } | 114 } |
115 | 115 |
116 return new_volume; | 116 return new_volume; |
117 } | 117 } |
118 | 118 |
119 void WebRtcAudioDeviceImpl::OnSetFormat( | 119 void WebRtcAudioDeviceImpl::OnSetFormat( |
120 const media::AudioParameters& params) { | 120 const media::AudioParameters& params) { |
121 DVLOG(1) << "WebRtcAudioDeviceImpl::OnSetFormat()"; | 121 DVLOG(1) << "WebRtcAudioDeviceImpl::OnSetFormat()"; |
122 } | 122 } |
123 | 123 |
124 void WebRtcAudioDeviceImpl::RenderData(uint8* audio_data, | 124 void WebRtcAudioDeviceImpl::RenderData(media::AudioBus* audio_bus, |
125 int number_of_channels, | 125 int sample_rate, |
126 int number_of_frames, | |
127 int audio_delay_milliseconds) { | 126 int audio_delay_milliseconds) { |
128 DCHECK_LE(number_of_frames, output_buffer_size()); | 127 render_buffer_.resize(audio_bus->frames() * audio_bus->channels()); |
128 | |
129 { | 129 { |
130 base::AutoLock auto_lock(lock_); | 130 base::AutoLock auto_lock(lock_); |
131 DCHECK(audio_transport_callback_); | 131 DCHECK(audio_transport_callback_); |
132 // Store the reported audio delay locally. | 132 // Store the reported audio delay locally. |
133 output_delay_ms_ = audio_delay_milliseconds; | 133 output_delay_ms_ = audio_delay_milliseconds; |
134 } | 134 } |
135 | 135 |
136 const int channels = number_of_channels; | 136 int samples_per_10_msec = (sample_rate / 100); |
137 DCHECK_LE(channels, output_channels()); | 137 int bytes_per_sample = 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 = | 138 const int bytes_per_10_msec = |
143 channels * samples_per_10_msec * bytes_per_sample; | 139 audio_bus->channels() * samples_per_10_msec * bytes_per_sample; |
144 | 140 DCHECK_EQ(audio_bus->frames() % samples_per_10_msec, 0); |
145 uint32_t num_audio_samples = 0; | |
146 int accumulated_audio_samples = 0; | |
147 | 141 |
148 // Get audio samples in blocks of 10 milliseconds from the registered | 142 // Get audio samples in blocks of 10 milliseconds from the registered |
149 // webrtc::AudioTransport source. Keep reading until our internal buffer | 143 // webrtc::AudioTransport source. Keep reading until our internal buffer |
150 // is full. | 144 // is full. |
151 while (accumulated_audio_samples < number_of_frames) { | 145 uint32_t num_audio_samples = 0; |
146 int accumulated_audio_samples = 0; | |
147 int16* audio_data = &render_buffer_[0]; | |
brucedawson
2016/01/30 18:32:07
This CL changes audio_data from uint8* to int16* b
tommi (sloooow) - chröme
2016/02/01 08:47:53
+Henrik A.
Thanks Bruce, I think you've found a b
henrika (OOO until Aug 14)
2016/02/01 14:46:46
Added
DCHECK_EQ(accumulated_audio_frames, audio_
| |
148 while (accumulated_audio_samples < audio_bus->frames()) { | |
152 // Get 10ms and append output to temporary byte buffer. | 149 // Get 10ms and append output to temporary byte buffer. |
153 audio_transport_callback_->NeedMorePlayData(samples_per_10_msec, | 150 audio_transport_callback_->NeedMorePlayData(samples_per_10_msec, |
154 bytes_per_sample, | 151 bytes_per_sample, |
155 channels, | 152 audio_bus->channels(), |
156 samples_per_sec, | 153 sample_rate, |
157 audio_data, | 154 audio_data, |
158 num_audio_samples); | 155 num_audio_samples); |
159 accumulated_audio_samples += num_audio_samples; | 156 accumulated_audio_samples += num_audio_samples; |
160 audio_data += bytes_per_10_msec; | 157 audio_data += bytes_per_10_msec; |
161 } | 158 } |
162 } | |
163 | 159 |
164 void WebRtcAudioDeviceImpl::SetRenderFormat(const AudioParameters& params) { | 160 // De-interleave each channel and convert to 32-bit floating-point |
165 DCHECK(thread_checker_.CalledOnValidThread()); | 161 // with nominal range -1.0 -> +1.0 to match the callback format. |
166 output_audio_parameters_ = params; | 162 audio_bus->FromInterleaved(&render_buffer_[0], |
163 audio_bus->frames(), | |
164 bytes_per_sample); | |
165 | |
166 // Pass the render data to the playout sinks. | |
167 base::AutoLock auto_lock(lock_); | |
168 for (PlayoutDataSinkList::const_iterator it = playout_sinks_.begin(); | |
169 it != playout_sinks_.end(); ++it) { | |
170 (*it)->OnPlayoutData(audio_bus, sample_rate, audio_delay_milliseconds); | |
171 } | |
167 } | 172 } |
168 | 173 |
169 void WebRtcAudioDeviceImpl::RemoveAudioRenderer(WebRtcAudioRenderer* renderer) { | 174 void WebRtcAudioDeviceImpl::RemoveAudioRenderer(WebRtcAudioRenderer* renderer) { |
170 DCHECK(thread_checker_.CalledOnValidThread()); | 175 DCHECK(thread_checker_.CalledOnValidThread()); |
171 DCHECK_EQ(renderer, renderer_); | 176 DCHECK_EQ(renderer, renderer_); |
172 base::AutoLock auto_lock(lock_); | 177 base::AutoLock auto_lock(lock_); |
173 renderer_ = NULL; | 178 renderer_ = NULL; |
174 playing_ = false; | 179 playing_ = false; |
175 } | 180 } |
176 | 181 |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
362 return 0; | 367 return 0; |
363 } | 368 } |
364 | 369 |
365 int32_t WebRtcAudioDeviceImpl::MinMicrophoneVolume(uint32_t* min_volume) const { | 370 int32_t WebRtcAudioDeviceImpl::MinMicrophoneVolume(uint32_t* min_volume) const { |
366 *min_volume = 0; | 371 *min_volume = 0; |
367 return 0; | 372 return 0; |
368 } | 373 } |
369 | 374 |
370 int32_t WebRtcAudioDeviceImpl::StereoPlayoutIsAvailable(bool* available) const { | 375 int32_t WebRtcAudioDeviceImpl::StereoPlayoutIsAvailable(bool* available) const { |
371 DCHECK(initialized_); | 376 DCHECK(initialized_); |
372 *available = (output_channels() == 2); | 377 *available = renderer_ && renderer_->channels() == 2; |
373 return 0; | 378 return 0; |
374 } | 379 } |
375 | 380 |
376 int32_t WebRtcAudioDeviceImpl::StereoRecordingIsAvailable( | 381 int32_t WebRtcAudioDeviceImpl::StereoRecordingIsAvailable( |
377 bool* available) const { | 382 bool* available) const { |
378 DCHECK(initialized_); | 383 DCHECK(initialized_); |
379 // TODO(xians): These kind of hardware methods do not make much sense since we | 384 // 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. | 385 // support multiple sources. Remove or figure out new APIs for such methods. |
381 scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer()); | 386 scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer()); |
382 if (!capturer.get()) | 387 if (!capturer.get()) |
(...skipping 22 matching lines...) Expand all Loading... | |
405 if (!capturer.get()) | 410 if (!capturer.get()) |
406 return -1; | 411 return -1; |
407 | 412 |
408 *samples_per_sec = static_cast<uint32_t>( | 413 *samples_per_sec = static_cast<uint32_t>( |
409 capturer->source_audio_parameters().sample_rate()); | 414 capturer->source_audio_parameters().sample_rate()); |
410 return 0; | 415 return 0; |
411 } | 416 } |
412 | 417 |
413 int32_t WebRtcAudioDeviceImpl::PlayoutSampleRate( | 418 int32_t WebRtcAudioDeviceImpl::PlayoutSampleRate( |
414 uint32_t* samples_per_sec) const { | 419 uint32_t* samples_per_sec) const { |
415 *samples_per_sec = static_cast<uint32_t>(output_sample_rate()); | 420 *samples_per_sec = renderer_ ? renderer_->sample_rate() : 0; |
416 return 0; | 421 return 0; |
417 } | 422 } |
418 | 423 |
419 bool WebRtcAudioDeviceImpl::SetAudioRenderer(WebRtcAudioRenderer* renderer) { | 424 bool WebRtcAudioDeviceImpl::SetAudioRenderer(WebRtcAudioRenderer* renderer) { |
420 DCHECK(thread_checker_.CalledOnValidThread()); | 425 DCHECK(thread_checker_.CalledOnValidThread()); |
421 DCHECK(renderer); | 426 DCHECK(renderer); |
422 | 427 |
423 base::AutoLock auto_lock(lock_); | 428 base::AutoLock auto_lock(lock_); |
424 if (renderer_.get()) | 429 if (renderer_.get()) |
425 return false; | 430 return false; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
458 // Use the last |capturer| which is from the latest getUserMedia call as | 463 // Use the last |capturer| which is from the latest getUserMedia call as |
459 // the default capture device. | 464 // the default capture device. |
460 for (CapturerList::const_reverse_iterator iter = capturers_.rbegin(); | 465 for (CapturerList::const_reverse_iterator iter = capturers_.rbegin(); |
461 iter != capturers_.rend(); ++iter) { | 466 iter != capturers_.rend(); ++iter) { |
462 return *iter; | 467 return *iter; |
463 } | 468 } |
464 | 469 |
465 return NULL; | 470 return NULL; |
466 } | 471 } |
467 | 472 |
473 void WebRtcAudioDeviceImpl::AddPlayoutSink( | |
474 WebRtcPlayoutDataSource::Sink* sink) { | |
475 DCHECK(thread_checker_.CalledOnValidThread()); | |
476 DCHECK(sink); | |
477 base::AutoLock auto_lock(lock_); | |
478 DCHECK(std::find(playout_sinks_.begin(), playout_sinks_.end(), sink) == | |
479 playout_sinks_.end()); | |
480 playout_sinks_.push_back(sink); | |
481 } | |
482 | |
483 void WebRtcAudioDeviceImpl::RemovePlayoutSink( | |
484 WebRtcPlayoutDataSource::Sink* sink) { | |
485 DCHECK(thread_checker_.CalledOnValidThread()); | |
486 DCHECK(sink); | |
487 base::AutoLock auto_lock(lock_); | |
488 playout_sinks_.remove(sink); | |
489 } | |
490 | |
468 bool WebRtcAudioDeviceImpl::GetAuthorizedDeviceInfoForAudioRenderer( | 491 bool WebRtcAudioDeviceImpl::GetAuthorizedDeviceInfoForAudioRenderer( |
469 int* session_id, | 492 int* session_id, |
470 int* output_sample_rate, | 493 int* output_sample_rate, |
471 int* output_frames_per_buffer) { | 494 int* output_frames_per_buffer) { |
472 DCHECK(thread_checker_.CalledOnValidThread()); | 495 DCHECK(thread_checker_.CalledOnValidThread()); |
473 // If there is no capturer or there are more than one open capture devices, | 496 // If there is no capturer or there are more than one open capture devices, |
474 // return false. | 497 // return false. |
475 if (capturers_.empty() || capturers_.size() > 1) | 498 if (capturers_.empty() || capturers_.size() > 1) |
476 return false; | 499 return false; |
477 | 500 |
478 return GetDefaultCapturer()->GetPairedOutputParameters( | 501 return GetDefaultCapturer()->GetPairedOutputParameters( |
479 session_id, output_sample_rate, output_frames_per_buffer); | 502 session_id, output_sample_rate, output_frames_per_buffer); |
480 } | 503 } |
481 | 504 |
482 } // namespace content | 505 } // namespace content |
OLD | NEW |