Chromium Code Reviews| 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" |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |