Chromium Code Reviews| OLD | NEW |
|---|---|
| 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_capturer.h" | 5 #include "content/renderer/media/webrtc_audio_capturer.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| 11 #include "base/strings/stringprintf.h" | 11 #include "base/strings/stringprintf.h" |
| 12 #include "cc/base/math_util.h" | |
| 12 #include "content/child/child_process.h" | 13 #include "content/child/child_process.h" |
| 13 #include "content/renderer/media/audio_device_factory.h" | 14 #include "content/renderer/media/audio_device_factory.h" |
| 14 #include "content/renderer/media/media_stream_audio_processor.h" | 15 #include "content/renderer/media/media_stream_audio_processor.h" |
| 15 #include "content/renderer/media/media_stream_audio_processor_options.h" | 16 #include "content/renderer/media/media_stream_audio_processor_options.h" |
| 16 #include "content/renderer/media/media_stream_audio_source.h" | 17 #include "content/renderer/media/media_stream_audio_source.h" |
| 18 #include "content/renderer/media/media_stream_constraints_util.h" | |
| 17 #include "content/renderer/media/webrtc_audio_device_impl.h" | 19 #include "content/renderer/media/webrtc_audio_device_impl.h" |
| 18 #include "content/renderer/media/webrtc_local_audio_track.h" | 20 #include "content/renderer/media/webrtc_local_audio_track.h" |
| 19 #include "content/renderer/media/webrtc_logging.h" | 21 #include "content/renderer/media/webrtc_logging.h" |
| 20 #include "media/audio/sample_rates.h" | 22 #include "media/audio/sample_rates.h" |
| 21 | 23 |
| 22 namespace content { | 24 namespace content { |
| 23 | 25 |
| 24 namespace { | 26 namespace { |
| 25 | 27 |
| 28 const char kAudioLatency[] = "latency"; | |
|
henrika (OOO until Aug 14)
2015/05/14 15:19:51
Is it clear from this name that this is for the ca
Charlie
2015/05/14 16:46:10
The JS will look like this:
navigator.webkitGetUs
| |
| 29 const double kMinAudioLatency = 0; | |
|
henrika (OOO until Aug 14)
2015/05/14 15:19:51
Add unit.
tommi (sloooow) - chröme
2015/05/14 16:29:26
It's not clear if this is a buffer size or time va
Charlie
2015/05/14 17:30:52
Done.
| |
| 30 const double kMaxAudioLatency = 60; | |
| 31 | |
| 32 const int kDontUseBufferSizeParameter = 0; | |
|
henrika (OOO until Aug 14)
2015/05/14 15:19:51
Is it used?
tommi (sloooow) - chröme
2015/05/14 16:29:26
From the name, it sounds like this should be a boo
Charlie
2015/05/14 16:46:10
I think Henrik was suggesting that we "tag" the ze
Charlie
2015/05/14 17:30:52
Done.
| |
| 33 | |
| 26 // Method to check if any of the data in |audio_source| has energy. | 34 // Method to check if any of the data in |audio_source| has energy. |
| 27 bool HasDataEnergy(const media::AudioBus& audio_source) { | 35 bool HasDataEnergy(const media::AudioBus& audio_source) { |
| 28 for (int ch = 0; ch < audio_source.channels(); ++ch) { | 36 for (int ch = 0; ch < audio_source.channels(); ++ch) { |
| 29 const float* channel_ptr = audio_source.channel(ch); | 37 const float* channel_ptr = audio_source.channel(ch); |
| 30 for (int frame = 0; frame < audio_source.frames(); ++frame) { | 38 for (int frame = 0; frame < audio_source.frames(); ++frame) { |
| 31 if (channel_ptr[frame] != 0) | 39 if (channel_ptr[frame] != 0) |
| 32 return true; | 40 return true; |
| 33 } | 41 } |
| 34 } | 42 } |
| 35 | 43 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 82 | 90 |
| 83 // This can be reentrant so reset |delegate_| before calling out. | 91 // This can be reentrant so reset |delegate_| before calling out. |
| 84 WebRtcLocalAudioTrack* temp = delegate_; | 92 WebRtcLocalAudioTrack* temp = delegate_; |
| 85 delegate_ = NULL; | 93 delegate_ = NULL; |
| 86 temp->Stop(); | 94 temp->Stop(); |
| 87 } | 95 } |
| 88 | 96 |
| 89 // Wrapper which allows to use std::find_if() when adding and removing | 97 // Wrapper which allows to use std::find_if() when adding and removing |
| 90 // sinks to/from the list. | 98 // sinks to/from the list. |
| 91 struct TrackWrapper { | 99 struct TrackWrapper { |
| 92 TrackWrapper(WebRtcLocalAudioTrack* track) : track_(track) {} | 100 explicit TrackWrapper(WebRtcLocalAudioTrack* track) : track_(track) {} |
| 93 bool operator()( | 101 bool operator()( |
| 94 const scoped_refptr<WebRtcAudioCapturer::TrackOwner>& owner) const { | 102 const scoped_refptr<WebRtcAudioCapturer::TrackOwner>& owner) const { |
| 95 return owner->IsEqual(track_); | 103 return owner->IsEqual(track_); |
| 96 } | 104 } |
| 97 WebRtcLocalAudioTrack* track_; | 105 WebRtcLocalAudioTrack* track_; |
| 98 }; | 106 }; |
| 99 | 107 |
| 100 protected: | 108 protected: |
| 101 virtual ~TrackOwner() {} | 109 virtual ~TrackOwner() {} |
| 102 | 110 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 181 | 189 |
| 182 // Verify that the reported input channel configuration is supported. | 190 // Verify that the reported input channel configuration is supported. |
| 183 if (channel_layout != media::CHANNEL_LAYOUT_MONO && | 191 if (channel_layout != media::CHANNEL_LAYOUT_MONO && |
| 184 channel_layout != media::CHANNEL_LAYOUT_STEREO && | 192 channel_layout != media::CHANNEL_LAYOUT_STEREO && |
| 185 channel_layout != media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) { | 193 channel_layout != media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) { |
| 186 DLOG(ERROR) << channel_layout | 194 DLOG(ERROR) << channel_layout |
| 187 << " is not a supported input channel configuration."; | 195 << " is not a supported input channel configuration."; |
| 188 return false; | 196 return false; |
| 189 } | 197 } |
| 190 | 198 |
| 199 const int& sample_rate = device_info_.device.input.sample_rate; | |
| 191 DVLOG(1) << "Audio input hardware sample rate: " | 200 DVLOG(1) << "Audio input hardware sample rate: " |
| 192 << device_info_.device.input.sample_rate; | 201 << device_info_.device.input.sample_rate; |
| 193 media::AudioSampleRate asr; | 202 media::AudioSampleRate asr; |
| 194 if (media::ToAudioSampleRate(device_info_.device.input.sample_rate, &asr)) { | 203 if (media::ToAudioSampleRate(sample_rate, &asr)) { |
|
tommi (sloooow) - chröme
2015/05/14 16:29:26
nit: to keep the change simple, can you revert the
Charlie
2015/05/14 17:30:52
Done.
| |
| 195 UMA_HISTOGRAM_ENUMERATION( | 204 UMA_HISTOGRAM_ENUMERATION( |
| 196 "WebRTC.AudioInputSampleRate", asr, media::kAudioSampleRateMax + 1); | 205 "WebRTC.AudioInputSampleRate", asr, media::kAudioSampleRateMax + 1); |
| 197 } else { | 206 } else { |
| 198 UMA_HISTOGRAM_COUNTS("WebRTC.AudioInputSampleRateUnexpected", | 207 UMA_HISTOGRAM_COUNTS("WebRTC.AudioInputSampleRateUnexpected", sample_rate); |
| 199 device_info_.device.input.sample_rate); | |
| 200 } | 208 } |
| 201 | 209 |
| 210 double buffer_size_seconds = 0; | |
|
henrika (OOO until Aug 14)
2015/05/14 15:19:51
is it really in seconds!? Should it not be in mill
Charlie
2015/05/14 16:46:10
I can drop the max to 10 seconds if you want. I do
| |
| 211 GetConstraintValueAsDouble( | |
| 212 constraints_, kAudioLatency, &buffer_size_seconds); | |
|
tommi (sloooow) - chröme
2015/05/14 16:29:26
seconds doesn't feel right. also I think you need
Charlie
2015/05/14 16:46:10
On the w3c thread it was pointed out that millisec
Charlie
2015/05/14 17:30:52
Fixed to ignore out-of-range values.
| |
| 213 buffer_size_seconds = cc::MathUtil::ClampToRange( | |
|
tommi (sloooow) - chröme
2015/05/14 16:29:25
with the above, I think that would also remove the
Charlie
2015/05/14 16:46:10
Well, we still need to clamp the value if the user
| |
| 214 buffer_size_seconds, kMinAudioLatency, kMaxAudioLatency); | |
| 215 int buffer_size = sample_rate * buffer_size_seconds; | |
| 216 if (buffer_size > 0) | |
|
henrika (OOO until Aug 14)
2015/05/14 15:19:51
> kDontUse...
Charlie
2015/05/14 17:30:52
Done.
| |
| 217 DVLOG(1) << "Custom audio buffer size: " << buffer_size; | |
| 218 | |
| 202 // Create and configure the default audio capturing source. | 219 // Create and configure the default audio capturing source. |
| 203 SetCapturerSourceInternal( | 220 SetCapturerSourceInternal( |
| 204 AudioDeviceFactory::NewInputDevice(render_frame_id_), channel_layout, | 221 AudioDeviceFactory::NewInputDevice(render_frame_id_), |
| 205 static_cast<float>(device_info_.device.input.sample_rate)); | 222 channel_layout, |
| 223 sample_rate, | |
| 224 buffer_size); | |
| 206 | 225 |
| 207 // Add the capturer to the WebRtcAudioDeviceImpl since it needs some hardware | 226 // Add the capturer to the WebRtcAudioDeviceImpl since it needs some hardware |
| 208 // information from the capturer. | 227 // information from the capturer. |
| 209 if (audio_device_) | 228 if (audio_device_) |
| 210 audio_device_->AddAudioCapturer(this); | 229 audio_device_->AddAudioCapturer(this); |
| 211 | 230 |
| 212 return true; | 231 return true; |
| 213 } | 232 } |
| 214 | 233 |
| 215 WebRtcAudioCapturer::WebRtcAudioCapturer( | 234 WebRtcAudioCapturer::WebRtcAudioCapturer( |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 280 // we have to call StopSource on the MediaStreamSource. This will call | 299 // we have to call StopSource on the MediaStreamSource. This will call |
| 281 // MediaStreamAudioSource::DoStopSource which in turn call | 300 // MediaStreamAudioSource::DoStopSource which in turn call |
| 282 // WebRtcAudioCapturerer::Stop(); | 301 // WebRtcAudioCapturerer::Stop(); |
| 283 audio_source_->StopSource(); | 302 audio_source_->StopSource(); |
| 284 } | 303 } |
| 285 } | 304 } |
| 286 | 305 |
| 287 void WebRtcAudioCapturer::SetCapturerSourceInternal( | 306 void WebRtcAudioCapturer::SetCapturerSourceInternal( |
| 288 const scoped_refptr<media::AudioCapturerSource>& source, | 307 const scoped_refptr<media::AudioCapturerSource>& source, |
| 289 media::ChannelLayout channel_layout, | 308 media::ChannelLayout channel_layout, |
| 290 float sample_rate) { | 309 int sample_rate, |
| 310 int buffer_size) { | |
| 291 DCHECK(thread_checker_.CalledOnValidThread()); | 311 DCHECK(thread_checker_.CalledOnValidThread()); |
| 292 DVLOG(1) << "SetCapturerSource(channel_layout=" << channel_layout << "," | 312 DVLOG(1) << "SetCapturerSource(channel_layout=" << channel_layout << "," |
| 293 << "sample_rate=" << sample_rate << ")"; | 313 << "sample_rate=" << sample_rate << ")"; |
| 294 scoped_refptr<media::AudioCapturerSource> old_source; | 314 scoped_refptr<media::AudioCapturerSource> old_source; |
| 295 { | 315 { |
| 296 base::AutoLock auto_lock(lock_); | 316 base::AutoLock auto_lock(lock_); |
| 297 if (source_.get() == source.get()) | 317 if (source_.get() == source.get()) |
| 298 return; | 318 return; |
| 299 | 319 |
| 300 source_.swap(old_source); | 320 source_.swap(old_source); |
| 301 source_ = source; | 321 source_ = source; |
| 302 | 322 |
| 303 // Reset the flag to allow starting the new source. | 323 // Reset the flag to allow starting the new source. |
| 304 running_ = false; | 324 running_ = false; |
| 305 } | 325 } |
| 306 | 326 |
| 307 DVLOG(1) << "Switching to a new capture source."; | 327 DVLOG(1) << "Switching to a new capture source."; |
| 308 if (old_source.get()) | 328 if (old_source.get()) |
| 309 old_source->Stop(); | 329 old_source->Stop(); |
| 310 | 330 |
| 311 // Dispatch the new parameters both to the sink(s) and to the new source, | 331 // Dispatch the new parameters both to the sink(s) and to the new source, |
| 312 // also apply the new |constraints|. | 332 // also apply the new |constraints|. |
| 313 // The idea is to get rid of any dependency of the microphone parameters | 333 // The idea is to get rid of any dependency of the microphone parameters |
| 314 // which would normally be used by default. | 334 // which would normally be used by default. |
| 315 // bits_per_sample is always 16 for now. | 335 // bits_per_sample is always 16 for now. |
| 316 int buffer_size = GetBufferSize(sample_rate); | 336 if (buffer_size == kDontUseBufferSizeParameter) |
|
henrika (OOO until Aug 14)
2015/05/14 15:19:51
Make a clear comment about what happens here and w
Charlie
2015/05/14 17:30:53
Done.
| |
| 337 buffer_size = GetBufferSize(sample_rate); | |
| 317 media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, | 338 media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, |
| 318 channel_layout, sample_rate, | 339 channel_layout, |
| 319 16, buffer_size, | 340 sample_rate, |
| 341 16, | |
| 342 buffer_size, | |
| 320 device_info_.device.input.effects); | 343 device_info_.device.input.effects); |
| 321 | 344 |
| 322 { | 345 { |
| 323 base::AutoLock auto_lock(lock_); | 346 base::AutoLock auto_lock(lock_); |
| 324 // Notify the |audio_processor_| of the new format. | 347 // Notify the |audio_processor_| of the new format. |
| 325 audio_processor_->OnCaptureFormatChanged(params); | 348 audio_processor_->OnCaptureFormatChanged(params); |
| 326 | 349 |
| 327 // Notify all tracks about the new format. | 350 // Notify all tracks about the new format. |
| 328 tracks_.TagAll(); | 351 tracks_.TagAll(); |
| 329 } | 352 } |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 358 // Do nothing if the current buffer size is the WebRtc native buffer size. | 381 // Do nothing if the current buffer size is the WebRtc native buffer size. |
| 359 if (GetBufferSize(input_params.sample_rate()) == | 382 if (GetBufferSize(input_params.sample_rate()) == |
| 360 input_params.frames_per_buffer()) { | 383 input_params.frames_per_buffer()) { |
| 361 return; | 384 return; |
| 362 } | 385 } |
| 363 | 386 |
| 364 // Create a new audio stream as source which will open the hardware using | 387 // Create a new audio stream as source which will open the hardware using |
| 365 // WebRtc native buffer size. | 388 // WebRtc native buffer size. |
| 366 SetCapturerSourceInternal(AudioDeviceFactory::NewInputDevice(render_frame_id), | 389 SetCapturerSourceInternal(AudioDeviceFactory::NewInputDevice(render_frame_id), |
| 367 input_params.channel_layout(), | 390 input_params.channel_layout(), |
| 368 static_cast<float>(input_params.sample_rate())); | 391 input_params.sample_rate(), |
| 392 0); | |
| 369 } | 393 } |
| 370 | 394 |
| 371 void WebRtcAudioCapturer::Start() { | 395 void WebRtcAudioCapturer::Start() { |
| 372 DCHECK(thread_checker_.CalledOnValidThread()); | 396 DCHECK(thread_checker_.CalledOnValidThread()); |
| 373 DVLOG(1) << "WebRtcAudioCapturer::Start()"; | 397 DVLOG(1) << "WebRtcAudioCapturer::Start()"; |
| 374 base::AutoLock auto_lock(lock_); | 398 base::AutoLock auto_lock(lock_); |
| 375 if (running_ || !source_.get()) | 399 if (running_ || !source_.get()) |
| 376 return; | 400 return; |
| 377 | 401 |
| 378 // Start the data source, i.e., start capturing data from the current source. | 402 // Start the data source, i.e., start capturing data from the current source. |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 581 return hardware_buffer_size; | 605 return hardware_buffer_size; |
| 582 } | 606 } |
| 583 | 607 |
| 584 return (sample_rate / 100); | 608 return (sample_rate / 100); |
| 585 } | 609 } |
| 586 | 610 |
| 587 void WebRtcAudioCapturer::SetCapturerSource( | 611 void WebRtcAudioCapturer::SetCapturerSource( |
| 588 const scoped_refptr<media::AudioCapturerSource>& source, | 612 const scoped_refptr<media::AudioCapturerSource>& source, |
| 589 media::AudioParameters params) { | 613 media::AudioParameters params) { |
| 590 // Create a new audio stream as source which uses the new source. | 614 // Create a new audio stream as source which uses the new source. |
| 591 SetCapturerSourceInternal(source, params.channel_layout(), | 615 SetCapturerSourceInternal(source, |
| 592 static_cast<float>(params.sample_rate())); | 616 params.channel_layout(), |
| 617 params.sample_rate(), | |
| 618 0); | |
| 593 } | 619 } |
| 594 | 620 |
| 595 } // namespace content | 621 } // namespace content |
| OLD | NEW |