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

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

Issue 1130063002: Allowing a custom audio buffer size in WebRtcAudioCapturer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 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
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698