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

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

Issue 133903004: Cleaned up the WebRtcAudioCapturer a bit. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: addressed the comments Created 6 years, 11 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 | Annotate | Revision Log
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"
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 } 101 }
102 102
103 // Do NOT reference count the |delegate_| to avoid cyclic reference counting. 103 // Do NOT reference count the |delegate_| to avoid cyclic reference counting.
104 WebRtcLocalAudioTrack* delegate_; 104 WebRtcLocalAudioTrack* delegate_;
105 mutable base::Lock lock_; 105 mutable base::Lock lock_;
106 106
107 DISALLOW_COPY_AND_ASSIGN(TrackOwner); 107 DISALLOW_COPY_AND_ASSIGN(TrackOwner);
108 }; 108 };
109 109
110 // static 110 // static
111 scoped_refptr<WebRtcAudioCapturer> WebRtcAudioCapturer::CreateCapturer() { 111 scoped_refptr<WebRtcAudioCapturer> WebRtcAudioCapturer::CreateCapturer(
112 scoped_refptr<WebRtcAudioCapturer> capturer = new WebRtcAudioCapturer(); 112 int render_view_id, const StreamDeviceInfo& device_info,
113 return capturer; 113 WebRtcAudioDeviceImpl* audio_device) {
114 scoped_refptr<WebRtcAudioCapturer> capturer = new WebRtcAudioCapturer(
115 render_view_id, device_info, audio_device);
116 if (capturer->Initialize())
117 return capturer;
118
119 return NULL;
114 } 120 }
115 121
116 void WebRtcAudioCapturer::Reconfigure(int sample_rate, 122 void WebRtcAudioCapturer::Reconfigure(int sample_rate,
117 media::ChannelLayout channel_layout, 123 media::ChannelLayout channel_layout,
118 int effects) { 124 int effects) {
119 DCHECK(thread_checker_.CalledOnValidThread()); 125 DCHECK(thread_checker_.CalledOnValidThread());
120 int buffer_size = GetBufferSize(sample_rate); 126 int buffer_size = GetBufferSize(sample_rate);
121 DVLOG(1) << "Using WebRTC input buffer size: " << buffer_size; 127 DVLOG(1) << "Using WebRTC input buffer size: " << buffer_size;
122 128
123 media::AudioParameters::Format format = 129 media::AudioParameters::Format format =
124 media::AudioParameters::AUDIO_PCM_LOW_LATENCY; 130 media::AudioParameters::AUDIO_PCM_LOW_LATENCY;
125 131
126 // bits_per_sample is always 16 for now. 132 // bits_per_sample is always 16 for now.
127 int bits_per_sample = 16; 133 int bits_per_sample = 16;
128 media::AudioParameters params(format, channel_layout, 0, sample_rate, 134 media::AudioParameters params(format, channel_layout, 0, sample_rate,
129 bits_per_sample, buffer_size, effects); 135 bits_per_sample, buffer_size, effects);
130 { 136 {
131 base::AutoLock auto_lock(lock_); 137 base::AutoLock auto_lock(lock_);
132 params_ = params; 138 params_ = params;
133 139
134 // Notify all tracks about the new format. 140 // Notify all tracks about the new format.
135 tracks_.TagAll(); 141 tracks_.TagAll();
136 } 142 }
137 } 143 }
138 144
139 bool WebRtcAudioCapturer::Initialize(int render_view_id, 145 bool WebRtcAudioCapturer::Initialize() {
140 media::ChannelLayout channel_layout,
141 int sample_rate,
142 int buffer_size,
143 int session_id,
144 const std::string& device_id,
145 int paired_output_sample_rate,
146 int paired_output_frames_per_buffer,
147 int effects) {
148 DCHECK(thread_checker_.CalledOnValidThread()); 146 DCHECK(thread_checker_.CalledOnValidThread());
149 DVLOG(1) << "WebRtcAudioCapturer::Initialize()"; 147 DVLOG(1) << "WebRtcAudioCapturer::Initialize()";
148 WebRtcLogMessage(base::StringPrintf(
149 "WAC::Initialize. render_view_id=%d"
150 ", channel_layout=%d, sample_rate=%d, buffer_size=%d"
151 ", session_id=%d, paired_output_sample_rate=%d"
152 ", paired_output_frames_per_buffer=%d, effects=%d. ",
153 render_view_id_,
154 device_info_.device.input.channel_layout,
155 device_info_.device.input.sample_rate,
156 device_info_.device.input.frames_per_buffer,
157 device_info_.session_id,
158 device_info_.device.matched_output.sample_rate,
159 device_info_.device.matched_output.frames_per_buffer,
160 device_info_.device.input.effects));
150 161
162 if (render_view_id_ == -1) {
163 // Return true here to allow injecting a new source via
164 // SetCapturerSourceForTesting() at a later state.
165 return true;
166 }
167
168 media::ChannelLayout channel_layout = static_cast<media::ChannelLayout>(
169 device_info_.device.input.channel_layout);
151 DVLOG(1) << "Audio input hardware channel layout: " << channel_layout; 170 DVLOG(1) << "Audio input hardware channel layout: " << channel_layout;
152 UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputChannelLayout", 171 UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputChannelLayout",
153 channel_layout, media::CHANNEL_LAYOUT_MAX); 172 channel_layout, media::CHANNEL_LAYOUT_MAX);
154 173
155 WebRtcLogMessage(base::StringPrintf(
156 "WAC::Initialize. render_view_id=%d"
157 ", channel_layout=%d, sample_rate=%d, buffer_size=%d"
158 ", session_id=%d, paired_output_sample_rate=%d"
159 ", paired_output_frames_per_buffer=%d",
160 render_view_id,
161 channel_layout,
162 sample_rate,
163 buffer_size,
164 session_id,
165 paired_output_sample_rate,
166 paired_output_frames_per_buffer));
167
168 render_view_id_ = render_view_id;
169 session_id_ = session_id;
170 device_id_ = device_id;
171 hardware_buffer_size_ = buffer_size;
172 output_sample_rate_ = paired_output_sample_rate;
173 output_frames_per_buffer_= paired_output_frames_per_buffer;
174
175 if (render_view_id == -1) {
176 // Return true here to allow injecting a new source via SetCapturerSource()
177 // at a later state.
178 return true;
179 }
180
181 // Verify that the reported input channel configuration is supported. 174 // Verify that the reported input channel configuration is supported.
182 if (channel_layout != media::CHANNEL_LAYOUT_MONO && 175 if (channel_layout != media::CHANNEL_LAYOUT_MONO &&
183 channel_layout != media::CHANNEL_LAYOUT_STEREO) { 176 channel_layout != media::CHANNEL_LAYOUT_STEREO) {
184 DLOG(ERROR) << channel_layout 177 DLOG(ERROR) << channel_layout
185 << " is not a supported input channel configuration."; 178 << " is not a supported input channel configuration.";
186 return false; 179 return false;
187 } 180 }
188 181
189 DVLOG(1) << "Audio input hardware sample rate: " << sample_rate; 182 DVLOG(1) << "Audio input hardware sample rate: "
190 media::AudioSampleRate asr = media::AsAudioSampleRate(sample_rate); 183 << device_info_.device.input.sample_rate;
184 media::AudioSampleRate asr = media::AsAudioSampleRate(
185 device_info_.device.input.sample_rate);
191 if (asr != media::kUnexpectedAudioSampleRate) { 186 if (asr != media::kUnexpectedAudioSampleRate) {
192 UMA_HISTOGRAM_ENUMERATION( 187 UMA_HISTOGRAM_ENUMERATION(
193 "WebRTC.AudioInputSampleRate", asr, media::kUnexpectedAudioSampleRate); 188 "WebRTC.AudioInputSampleRate", asr, media::kUnexpectedAudioSampleRate);
194 } else { 189 } else {
195 UMA_HISTOGRAM_COUNTS("WebRTC.AudioInputSampleRateUnexpected", sample_rate); 190 UMA_HISTOGRAM_COUNTS("WebRTC.AudioInputSampleRateUnexpected",
191 device_info_.device.input.sample_rate);
196 } 192 }
197 193
198 // Verify that the reported input hardware sample rate is supported 194 // Verify that the reported input hardware sample rate is supported
199 // on the current platform. 195 // on the current platform.
200 if (std::find(&kValidInputRates[0], 196 if (std::find(&kValidInputRates[0],
201 &kValidInputRates[0] + arraysize(kValidInputRates), 197 &kValidInputRates[0] + arraysize(kValidInputRates),
202 sample_rate) == 198 device_info_.device.input.sample_rate) ==
203 &kValidInputRates[arraysize(kValidInputRates)]) { 199 &kValidInputRates[arraysize(kValidInputRates)]) {
204 DLOG(ERROR) << sample_rate << " is not a supported input rate."; 200 DLOG(ERROR) << device_info_.device.input.sample_rate
201 << " is not a supported input rate.";
205 return false; 202 return false;
206 } 203 }
207 204
208 // Create and configure the default audio capturing source. The |source_| 205 // Create and configure the default audio capturing source.
209 // will be overwritten if an external client later calls SetCapturerSource() 206 SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id_),
210 // providing an alternative media::AudioCapturerSource.
211 SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id),
212 channel_layout, 207 channel_layout,
213 static_cast<float>(sample_rate), 208 static_cast<float>(device_info_.device.input.sample_rate),
214 effects); 209 device_info_.device.input.effects);
210
211 // Add the capturer to the WebRtcAudioDeviceImpl since it needs some hardware
212 // information from the capturer.
213 if (audio_device_)
214 audio_device_->AddAudioCapturer(this);
215 215
216 return true; 216 return true;
217 } 217 }
218 218
219 WebRtcAudioCapturer::WebRtcAudioCapturer() 219 WebRtcAudioCapturer::WebRtcAudioCapturer(int render_view_id,
220 const StreamDeviceInfo& device_info,
221 WebRtcAudioDeviceImpl* audio_device)
220 : running_(false), 222 : running_(false),
221 render_view_id_(-1), 223 render_view_id_(render_view_id),
222 hardware_buffer_size_(0), 224 device_info_(device_info),
223 session_id_(0),
224 volume_(0), 225 volume_(0),
225 peer_connection_mode_(false), 226 peer_connection_mode_(false),
226 output_sample_rate_(0), 227 key_pressed_(false),
227 output_frames_per_buffer_(0), 228 audio_device_(audio_device) {
228 key_pressed_(false) {
229 DVLOG(1) << "WebRtcAudioCapturer::WebRtcAudioCapturer()"; 229 DVLOG(1) << "WebRtcAudioCapturer::WebRtcAudioCapturer()";
230 } 230 }
231 231
232 WebRtcAudioCapturer::~WebRtcAudioCapturer() { 232 WebRtcAudioCapturer::~WebRtcAudioCapturer() {
233 DCHECK(thread_checker_.CalledOnValidThread()); 233 DCHECK(thread_checker_.CalledOnValidThread());
234 DCHECK(tracks_.IsEmpty()); 234 DCHECK(tracks_.IsEmpty());
235 DCHECK(!running_); 235 DCHECK(!running_);
236 DVLOG(1) << "WebRtcAudioCapturer::~WebRtcAudioCapturer()"; 236 DVLOG(1) << "WebRtcAudioCapturer::~WebRtcAudioCapturer()";
237 } 237 }
238 238
(...skipping 13 matching lines...) Expand all
252 } 252 }
253 253
254 // Start the source if the first audio track is connected to the capturer. 254 // Start the source if the first audio track is connected to the capturer.
255 // Start() will do nothing if the capturer has already been started. 255 // Start() will do nothing if the capturer has already been started.
256 Start(); 256 Start();
257 257
258 } 258 }
259 259
260 void WebRtcAudioCapturer::RemoveTrack(WebRtcLocalAudioTrack* track) { 260 void WebRtcAudioCapturer::RemoveTrack(WebRtcLocalAudioTrack* track) {
261 DCHECK(thread_checker_.CalledOnValidThread()); 261 DCHECK(thread_checker_.CalledOnValidThread());
262 base::AutoLock auto_lock(lock_);
262 263
263 bool stop_source = false; 264 scoped_refptr<TrackOwner> removed_item =
264 { 265 tracks_.Remove(TrackOwner::TrackWrapper(track));
265 base::AutoLock auto_lock(lock_);
266 266
267 scoped_refptr<TrackOwner> removed_item = 267 // Clear the delegate to ensure that no more capture callbacks will
268 tracks_.Remove(TrackOwner::TrackWrapper(track)); 268 // be sent to this sink. Also avoids a possible crash which can happen
269 269 // if this method is called while capturing is active.
270 // Clear the delegate to ensure that no more capture callbacks will 270 if (removed_item.get())
271 // be sent to this sink. Also avoids a possible crash which can happen 271 removed_item->Reset();
272 // if this method is called while capturing is active.
273 if (removed_item.get())
274 removed_item->Reset();
275
276 // Stop the source if the last audio track is going away.
277 stop_source = tracks_.IsEmpty();
278 }
279
280 if (stop_source)
281 Stop();
282 } 272 }
283 273
284 void WebRtcAudioCapturer::SetCapturerSource( 274 void WebRtcAudioCapturer::SetCapturerSource(
285 const scoped_refptr<media::AudioCapturerSource>& source, 275 const scoped_refptr<media::AudioCapturerSource>& source,
286 media::ChannelLayout channel_layout, 276 media::ChannelLayout channel_layout,
287 float sample_rate, 277 float sample_rate,
288 int effects) { 278 int effects) {
289 DCHECK(thread_checker_.CalledOnValidThread()); 279 DCHECK(thread_checker_.CalledOnValidThread());
290 DVLOG(1) << "SetCapturerSource(channel_layout=" << channel_layout << "," 280 DVLOG(1) << "SetCapturerSource(channel_layout=" << channel_layout << ","
291 << "sample_rate=" << sample_rate << ")"; 281 << "sample_rate=" << sample_rate << ")";
(...skipping 17 matching lines...) Expand all
309 old_source->Stop(); 299 old_source->Stop();
310 300
311 // Dispatch the new parameters both to the sink(s) and to the new source. 301 // Dispatch the new parameters both to the sink(s) and to the new source.
312 // The idea is to get rid of any dependency of the microphone parameters 302 // The idea is to get rid of any dependency of the microphone parameters
313 // which would normally be used by default. 303 // which would normally be used by default.
314 Reconfigure(sample_rate, channel_layout, effects); 304 Reconfigure(sample_rate, channel_layout, effects);
315 305
316 // Make sure to grab the new parameters in case they were reconfigured. 306 // Make sure to grab the new parameters in case they were reconfigured.
317 media::AudioParameters params = audio_parameters(); 307 media::AudioParameters params = audio_parameters();
318 if (source.get()) 308 if (source.get())
319 source->Initialize(params, this, session_id_); 309 source->Initialize(params, this, session_id());
320 310
321 if (restart_source) 311 if (restart_source)
322 Start(); 312 Start();
323 } 313 }
324 314
325 void WebRtcAudioCapturer::EnablePeerConnectionMode() { 315 void WebRtcAudioCapturer::EnablePeerConnectionMode() {
326 DCHECK(thread_checker_.CalledOnValidThread()); 316 DCHECK(thread_checker_.CalledOnValidThread());
327 DVLOG(1) << "EnablePeerConnectionMode"; 317 DVLOG(1) << "EnablePeerConnectionMode";
328 // Do nothing if the peer connection mode has been enabled. 318 // Do nothing if the peer connection mode has been enabled.
329 if (peer_connection_mode_) 319 if (peer_connection_mode_)
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 base::AutoLock auto_lock(lock_); 365 base::AutoLock auto_lock(lock_);
376 if (!running_) 366 if (!running_)
377 return; 367 return;
378 368
379 source = source_; 369 source = source_;
380 tracks = tracks_.Items(); 370 tracks = tracks_.Items();
381 tracks_.Clear(); 371 tracks_.Clear();
382 running_ = false; 372 running_ = false;
383 } 373 }
384 374
375 // Remove the capturer object from the WebRtcAudioDeviceImpl.
376 if (audio_device_)
perkj_chrome 2014/01/14 12:53:55 Can audio_device_ be NULL? Otherwise skip the chec
no longer working on chromium 2014/01/14 14:10:56 Yes, for example, for most of the unittests they a
377 audio_device_->RemoveAudioCapturer(this);
378
385 for (TrackList::ItemList::const_iterator it = tracks.begin(); 379 for (TrackList::ItemList::const_iterator it = tracks.begin();
386 it != tracks.end(); 380 it != tracks.end();
387 ++it) { 381 ++it) {
388 (*it)->Stop(); 382 (*it)->Stop();
389 } 383 }
390 384
391 if (source.get()) 385 if (source.get())
392 source->Stop(); 386 source->Stop();
393 } 387 }
394 388
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 media::AudioParameters WebRtcAudioCapturer::audio_parameters() const { 470 media::AudioParameters WebRtcAudioCapturer::audio_parameters() const {
477 base::AutoLock auto_lock(lock_); 471 base::AutoLock auto_lock(lock_);
478 return params_; 472 return params_;
479 } 473 }
480 474
481 bool WebRtcAudioCapturer::GetPairedOutputParameters( 475 bool WebRtcAudioCapturer::GetPairedOutputParameters(
482 int* session_id, 476 int* session_id,
483 int* output_sample_rate, 477 int* output_sample_rate,
484 int* output_frames_per_buffer) const { 478 int* output_frames_per_buffer) const {
485 // Don't set output parameters unless all of them are valid. 479 // Don't set output parameters unless all of them are valid.
486 if (session_id_ <= 0 || !output_sample_rate_ || !output_frames_per_buffer_) 480 if (device_info_.session_id <= 0 ||
481 !device_info_.device.matched_output.sample_rate ||
482 !device_info_.device.matched_output.frames_per_buffer)
487 return false; 483 return false;
488 484
489 *session_id = session_id_; 485 *session_id = device_info_.session_id;
490 *output_sample_rate = output_sample_rate_; 486 *output_sample_rate = device_info_.device.matched_output.sample_rate;
491 *output_frames_per_buffer = output_frames_per_buffer_; 487 *output_frames_per_buffer =
488 device_info_.device.matched_output.frames_per_buffer;
492 489
493 return true; 490 return true;
494 } 491 }
495 492
496 int WebRtcAudioCapturer::GetBufferSize(int sample_rate) const { 493 int WebRtcAudioCapturer::GetBufferSize(int sample_rate) const {
497 DCHECK(thread_checker_.CalledOnValidThread()); 494 DCHECK(thread_checker_.CalledOnValidThread());
498 #if defined(OS_ANDROID) 495 #if defined(OS_ANDROID)
499 // TODO(henrika): Tune and adjust buffer size on Android. 496 // TODO(henrika): Tune and adjust buffer size on Android.
500 return (2 * sample_rate / 100); 497 return (2 * sample_rate / 100);
501 #endif 498 #endif
502 499
503 // PeerConnection is running at a buffer size of 10ms data. A multiple of 500 // PeerConnection is running at a buffer size of 10ms data. A multiple of
504 // 10ms as the buffer size can give the best performance to PeerConnection. 501 // 10ms as the buffer size can give the best performance to PeerConnection.
505 int peer_connection_buffer_size = sample_rate / 100; 502 int peer_connection_buffer_size = sample_rate / 100;
506 503
507 // Use the native hardware buffer size in non peer connection mode when the 504 // Use the native hardware buffer size in non peer connection mode when the
508 // platform is using a native buffer size smaller than the PeerConnection 505 // platform is using a native buffer size smaller than the PeerConnection
509 // buffer size. 506 // buffer size.
510 if (!peer_connection_mode_ && hardware_buffer_size_ && 507 int hardware_buffer_size = device_info_.device.input.frames_per_buffer;
511 hardware_buffer_size_ <= peer_connection_buffer_size) { 508 if (!peer_connection_mode_ && hardware_buffer_size &&
512 return hardware_buffer_size_; 509 hardware_buffer_size <= peer_connection_buffer_size) {
510 return hardware_buffer_size;
513 } 511 }
514 512
515 return (sample_rate / 100); 513 return (sample_rate / 100);
516 } 514 }
517 515
518 void WebRtcAudioCapturer::GetAudioProcessingParams( 516 void WebRtcAudioCapturer::GetAudioProcessingParams(
519 base::TimeDelta* delay, int* volume, bool* key_pressed) { 517 base::TimeDelta* delay, int* volume, bool* key_pressed) {
520 base::AutoLock auto_lock(lock_); 518 base::AutoLock auto_lock(lock_);
521 *delay = audio_delay_; 519 *delay = audio_delay_;
522 *volume = volume_; 520 *volume = volume_;
523 *key_pressed = key_pressed_; 521 *key_pressed = key_pressed_;
524 } 522 }
525 523
524 void WebRtcAudioCapturer::SetCapturerSourceForTesting(
525 const scoped_refptr<media::AudioCapturerSource>& source,
526 media::AudioParameters params) {
527 // Create a new audio stream as source which uses the new source.
528 SetCapturerSource(source, params.channel_layout(),
529 static_cast<float>(params.sample_rate()),
530 params.effects());
531 }
532
526 } // namespace content 533 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698