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 "content/child/child_process.h" | 12 #include "content/child/child_process.h" |
13 #include "content/renderer/media/audio_device_factory.h" | 13 #include "content/renderer/media/audio_device_factory.h" |
14 #include "content/renderer/media/media_stream_audio_processor.h" | 14 #include "content/renderer/media/media_stream_audio_processor.h" |
15 #include "content/renderer/media/media_stream_audio_processor_options.h" | 15 #include "content/renderer/media/media_stream_audio_processor_options.h" |
16 #include "content/renderer/media/media_stream_audio_source.h" | 16 #include "content/renderer/media/media_stream_audio_source.h" |
17 #include "content/renderer/media/media_stream_constraints_util.h" | |
17 #include "content/renderer/media/webrtc_audio_device_impl.h" | 18 #include "content/renderer/media/webrtc_audio_device_impl.h" |
18 #include "content/renderer/media/webrtc_local_audio_track.h" | 19 #include "content/renderer/media/webrtc_local_audio_track.h" |
19 #include "content/renderer/media/webrtc_logging.h" | 20 #include "content/renderer/media/webrtc_logging.h" |
20 #include "media/audio/sample_rates.h" | 21 #include "media/audio/sample_rates.h" |
21 | 22 |
22 namespace content { | 23 namespace content { |
23 | 24 |
24 namespace { | 25 namespace { |
25 | 26 |
27 const char kAudioBufferSizeMs[] = "audioBufferSizeMs"; | |
28 | |
26 // Method to check if any of the data in |audio_source| has energy. | 29 // Method to check if any of the data in |audio_source| has energy. |
27 bool HasDataEnergy(const media::AudioBus& audio_source) { | 30 bool HasDataEnergy(const media::AudioBus& audio_source) { |
28 for (int ch = 0; ch < audio_source.channels(); ++ch) { | 31 for (int ch = 0; ch < audio_source.channels(); ++ch) { |
29 const float* channel_ptr = audio_source.channel(ch); | 32 const float* channel_ptr = audio_source.channel(ch); |
30 for (int frame = 0; frame < audio_source.frames(); ++frame) { | 33 for (int frame = 0; frame < audio_source.frames(); ++frame) { |
31 if (channel_ptr[frame] != 0) | 34 if (channel_ptr[frame] != 0) |
32 return true; | 35 return true; |
33 } | 36 } |
34 } | 37 } |
35 | 38 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
82 | 85 |
83 // This can be reentrant so reset |delegate_| before calling out. | 86 // This can be reentrant so reset |delegate_| before calling out. |
84 WebRtcLocalAudioTrack* temp = delegate_; | 87 WebRtcLocalAudioTrack* temp = delegate_; |
85 delegate_ = NULL; | 88 delegate_ = NULL; |
86 temp->Stop(); | 89 temp->Stop(); |
87 } | 90 } |
88 | 91 |
89 // Wrapper which allows to use std::find_if() when adding and removing | 92 // Wrapper which allows to use std::find_if() when adding and removing |
90 // sinks to/from the list. | 93 // sinks to/from the list. |
91 struct TrackWrapper { | 94 struct TrackWrapper { |
92 TrackWrapper(WebRtcLocalAudioTrack* track) : track_(track) {} | 95 explicit TrackWrapper(WebRtcLocalAudioTrack* track) : track_(track) {} |
Charlie
2015/05/06 23:47:44
Fixing linter error.
| |
93 bool operator()( | 96 bool operator()( |
94 const scoped_refptr<WebRtcAudioCapturer::TrackOwner>& owner) const { | 97 const scoped_refptr<WebRtcAudioCapturer::TrackOwner>& owner) const { |
95 return owner->IsEqual(track_); | 98 return owner->IsEqual(track_); |
96 } | 99 } |
97 WebRtcLocalAudioTrack* track_; | 100 WebRtcLocalAudioTrack* track_; |
98 }; | 101 }; |
99 | 102 |
100 protected: | 103 protected: |
101 virtual ~TrackOwner() {} | 104 virtual ~TrackOwner() {} |
102 | 105 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
181 | 184 |
182 // Verify that the reported input channel configuration is supported. | 185 // Verify that the reported input channel configuration is supported. |
183 if (channel_layout != media::CHANNEL_LAYOUT_MONO && | 186 if (channel_layout != media::CHANNEL_LAYOUT_MONO && |
184 channel_layout != media::CHANNEL_LAYOUT_STEREO && | 187 channel_layout != media::CHANNEL_LAYOUT_STEREO && |
185 channel_layout != media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) { | 188 channel_layout != media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) { |
186 DLOG(ERROR) << channel_layout | 189 DLOG(ERROR) << channel_layout |
187 << " is not a supported input channel configuration."; | 190 << " is not a supported input channel configuration."; |
188 return false; | 191 return false; |
189 } | 192 } |
190 | 193 |
194 const int& sample_rate = device_info_.device.input.sample_rate; | |
191 DVLOG(1) << "Audio input hardware sample rate: " | 195 DVLOG(1) << "Audio input hardware sample rate: " |
192 << device_info_.device.input.sample_rate; | 196 << device_info_.device.input.sample_rate; |
193 media::AudioSampleRate asr; | 197 media::AudioSampleRate asr; |
194 if (media::ToAudioSampleRate(device_info_.device.input.sample_rate, &asr)) { | 198 if (media::ToAudioSampleRate(sample_rate, &asr)) { |
195 UMA_HISTOGRAM_ENUMERATION( | 199 UMA_HISTOGRAM_ENUMERATION( |
196 "WebRTC.AudioInputSampleRate", asr, media::kAudioSampleRateMax + 1); | 200 "WebRTC.AudioInputSampleRate", asr, media::kAudioSampleRateMax + 1); |
197 } else { | 201 } else { |
198 UMA_HISTOGRAM_COUNTS("WebRTC.AudioInputSampleRateUnexpected", | 202 UMA_HISTOGRAM_COUNTS("WebRTC.AudioInputSampleRateUnexpected", sample_rate); |
199 device_info_.device.input.sample_rate); | |
200 } | 203 } |
201 | 204 |
205 int buffer_size_ms = 0; | |
206 GetOptionalConstraintValueAsInteger( | |
207 constraints_, kAudioBufferSizeMs, &buffer_size_ms); | |
208 int buffer_size = sample_rate * buffer_size_ms / 1000; | |
209 if (buffer_size > 0) | |
210 DVLOG(1) << "Custom audio buffer size: " << buffer_size; | |
211 | |
202 // Create and configure the default audio capturing source. | 212 // Create and configure the default audio capturing source. |
203 SetCapturerSourceInternal( | 213 SetCapturerSourceInternal( |
204 AudioDeviceFactory::NewInputDevice(render_frame_id_), channel_layout, | 214 AudioDeviceFactory::NewInputDevice(render_frame_id_), |
205 static_cast<float>(device_info_.device.input.sample_rate)); | 215 channel_layout, |
216 sample_rate, | |
217 buffer_size); | |
206 | 218 |
207 // Add the capturer to the WebRtcAudioDeviceImpl since it needs some hardware | 219 // Add the capturer to the WebRtcAudioDeviceImpl since it needs some hardware |
208 // information from the capturer. | 220 // information from the capturer. |
209 if (audio_device_) | 221 if (audio_device_) |
210 audio_device_->AddAudioCapturer(this); | 222 audio_device_->AddAudioCapturer(this); |
211 | 223 |
212 return true; | 224 return true; |
213 } | 225 } |
214 | 226 |
215 WebRtcAudioCapturer::WebRtcAudioCapturer( | 227 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 | 292 // we have to call StopSource on the MediaStreamSource. This will call |
281 // MediaStreamAudioSource::DoStopSource which in turn call | 293 // MediaStreamAudioSource::DoStopSource which in turn call |
282 // WebRtcAudioCapturerer::Stop(); | 294 // WebRtcAudioCapturerer::Stop(); |
283 audio_source_->StopSource(); | 295 audio_source_->StopSource(); |
284 } | 296 } |
285 } | 297 } |
286 | 298 |
287 void WebRtcAudioCapturer::SetCapturerSourceInternal( | 299 void WebRtcAudioCapturer::SetCapturerSourceInternal( |
288 const scoped_refptr<media::AudioCapturerSource>& source, | 300 const scoped_refptr<media::AudioCapturerSource>& source, |
289 media::ChannelLayout channel_layout, | 301 media::ChannelLayout channel_layout, |
290 float sample_rate) { | 302 int sample_rate, |
303 int buffer_size) { | |
291 DCHECK(thread_checker_.CalledOnValidThread()); | 304 DCHECK(thread_checker_.CalledOnValidThread()); |
292 DVLOG(1) << "SetCapturerSource(channel_layout=" << channel_layout << "," | 305 DVLOG(1) << "SetCapturerSource(channel_layout=" << channel_layout << "," |
293 << "sample_rate=" << sample_rate << ")"; | 306 << "sample_rate=" << sample_rate << ")"; |
294 scoped_refptr<media::AudioCapturerSource> old_source; | 307 scoped_refptr<media::AudioCapturerSource> old_source; |
295 { | 308 { |
296 base::AutoLock auto_lock(lock_); | 309 base::AutoLock auto_lock(lock_); |
297 if (source_.get() == source.get()) | 310 if (source_.get() == source.get()) |
298 return; | 311 return; |
299 | 312 |
300 source_.swap(old_source); | 313 source_.swap(old_source); |
301 source_ = source; | 314 source_ = source; |
302 | 315 |
303 // Reset the flag to allow starting the new source. | 316 // Reset the flag to allow starting the new source. |
304 running_ = false; | 317 running_ = false; |
305 } | 318 } |
306 | 319 |
307 DVLOG(1) << "Switching to a new capture source."; | 320 DVLOG(1) << "Switching to a new capture source."; |
308 if (old_source.get()) | 321 if (old_source.get()) |
309 old_source->Stop(); | 322 old_source->Stop(); |
310 | 323 |
311 // Dispatch the new parameters both to the sink(s) and to the new source, | 324 // Dispatch the new parameters both to the sink(s) and to the new source, |
312 // also apply the new |constraints|. | 325 // also apply the new |constraints|. |
313 // The idea is to get rid of any dependency of the microphone parameters | 326 // The idea is to get rid of any dependency of the microphone parameters |
314 // which would normally be used by default. | 327 // which would normally be used by default. |
315 // bits_per_sample is always 16 for now. | 328 // bits_per_sample is always 16 for now. |
316 int buffer_size = GetBufferSize(sample_rate); | 329 if (!buffer_size) |
330 buffer_size = GetBufferSize(sample_rate); | |
317 media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, | 331 media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, |
318 channel_layout, sample_rate, | 332 channel_layout, |
319 16, buffer_size, | 333 sample_rate, |
334 16, | |
335 buffer_size, | |
320 device_info_.device.input.effects); | 336 device_info_.device.input.effects); |
321 | 337 |
322 { | 338 { |
323 base::AutoLock auto_lock(lock_); | 339 base::AutoLock auto_lock(lock_); |
324 // Notify the |audio_processor_| of the new format. | 340 // Notify the |audio_processor_| of the new format. |
325 audio_processor_->OnCaptureFormatChanged(params); | 341 audio_processor_->OnCaptureFormatChanged(params); |
326 | 342 |
327 // Notify all tracks about the new format. | 343 // Notify all tracks about the new format. |
328 tracks_.TagAll(); | 344 tracks_.TagAll(); |
329 } | 345 } |
(...skipping 28 matching lines...) Expand all Loading... | |
358 // Do nothing if the current buffer size is the WebRtc native buffer size. | 374 // Do nothing if the current buffer size is the WebRtc native buffer size. |
359 if (GetBufferSize(input_params.sample_rate()) == | 375 if (GetBufferSize(input_params.sample_rate()) == |
360 input_params.frames_per_buffer()) { | 376 input_params.frames_per_buffer()) { |
361 return; | 377 return; |
362 } | 378 } |
363 | 379 |
364 // Create a new audio stream as source which will open the hardware using | 380 // Create a new audio stream as source which will open the hardware using |
365 // WebRtc native buffer size. | 381 // WebRtc native buffer size. |
366 SetCapturerSourceInternal(AudioDeviceFactory::NewInputDevice(render_frame_id), | 382 SetCapturerSourceInternal(AudioDeviceFactory::NewInputDevice(render_frame_id), |
367 input_params.channel_layout(), | 383 input_params.channel_layout(), |
368 static_cast<float>(input_params.sample_rate())); | 384 input_params.sample_rate(), |
385 0); | |
369 } | 386 } |
370 | 387 |
371 void WebRtcAudioCapturer::Start() { | 388 void WebRtcAudioCapturer::Start() { |
372 DCHECK(thread_checker_.CalledOnValidThread()); | 389 DCHECK(thread_checker_.CalledOnValidThread()); |
373 DVLOG(1) << "WebRtcAudioCapturer::Start()"; | 390 DVLOG(1) << "WebRtcAudioCapturer::Start()"; |
374 base::AutoLock auto_lock(lock_); | 391 base::AutoLock auto_lock(lock_); |
375 if (running_ || !source_.get()) | 392 if (running_ || !source_.get()) |
376 return; | 393 return; |
377 | 394 |
378 // Start the data source, i.e., start capturing data from the current source. | 395 // 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; | 598 return hardware_buffer_size; |
582 } | 599 } |
583 | 600 |
584 return (sample_rate / 100); | 601 return (sample_rate / 100); |
585 } | 602 } |
586 | 603 |
587 void WebRtcAudioCapturer::SetCapturerSource( | 604 void WebRtcAudioCapturer::SetCapturerSource( |
588 const scoped_refptr<media::AudioCapturerSource>& source, | 605 const scoped_refptr<media::AudioCapturerSource>& source, |
589 media::AudioParameters params) { | 606 media::AudioParameters params) { |
590 // Create a new audio stream as source which uses the new source. | 607 // Create a new audio stream as source which uses the new source. |
591 SetCapturerSourceInternal(source, params.channel_layout(), | 608 SetCapturerSourceInternal(source, |
592 static_cast<float>(params.sample_rate())); | 609 params.channel_layout(), |
610 params.sample_rate(), | |
611 0); | |
593 } | 612 } |
594 | 613 |
595 } // namespace content | 614 } // namespace content |
OLD | NEW |