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

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

Issue 37793005: move the APM to chrome. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: added a switch, it uses the APM in WebRtc if the switch is off, otherwise use the APM in Chrome. Created 7 years, 1 month 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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 } 56 }
57 57
58 void SetCaptureFormat(const media::AudioParameters& params) { 58 void SetCaptureFormat(const media::AudioParameters& params) {
59 base::AutoLock lock(lock_); 59 base::AutoLock lock(lock_);
60 if (delegate_) 60 if (delegate_)
61 delegate_->SetCaptureFormat(params); 61 delegate_->SetCaptureFormat(params);
62 } 62 }
63 63
64 void Reset() { 64 void Reset() {
65 base::AutoLock lock(lock_); 65 base::AutoLock lock(lock_);
66 if (delegate_)
67 delegate_->Stop();
66 delegate_ = NULL; 68 delegate_ = NULL;
67 } 69 }
68 70
69 // Wrapper which allows to use std::find_if() when adding and removing 71 // Wrapper which allows to use std::find_if() when adding and removing
70 // sinks to/from the list. 72 // sinks to/from the list.
71 struct TrackWrapper { 73 struct TrackWrapper {
72 TrackWrapper(WebRtcLocalAudioTrack* track) : track_(track) {} 74 TrackWrapper(WebRtcLocalAudioTrack* track) : track_(track) {}
73 bool operator()( 75 bool operator()(
74 const scoped_refptr<WebRtcAudioCapturer::TrackOwner>& owner) { 76 const scoped_refptr<WebRtcAudioCapturer::TrackOwner>& owner) {
75 return owner->IsEqual(track_); 77 return owner->IsEqual(track_);
(...skipping 18 matching lines...) Expand all
94 96
95 DISALLOW_COPY_AND_ASSIGN(TrackOwner); 97 DISALLOW_COPY_AND_ASSIGN(TrackOwner);
96 }; 98 };
97 99
98 // static 100 // static
99 scoped_refptr<WebRtcAudioCapturer> WebRtcAudioCapturer::CreateCapturer() { 101 scoped_refptr<WebRtcAudioCapturer> WebRtcAudioCapturer::CreateCapturer() {
100 scoped_refptr<WebRtcAudioCapturer> capturer = new WebRtcAudioCapturer(); 102 scoped_refptr<WebRtcAudioCapturer> capturer = new WebRtcAudioCapturer();
101 return capturer; 103 return capturer;
102 } 104 }
103 105
104 void WebRtcAudioCapturer::Reconfigure(int sample_rate, 106 void WebRtcAudioCapturer::Reconfigure(
105 media::ChannelLayout channel_layout) { 107 int sample_rate,
108 media::ChannelLayout channel_layout) {
106 DCHECK(thread_checker_.CalledOnValidThread()); 109 DCHECK(thread_checker_.CalledOnValidThread());
107 int buffer_size = GetBufferSize(sample_rate); 110 int buffer_size = GetBufferSize(sample_rate);
108 DVLOG(1) << "Using WebRTC input buffer size: " << buffer_size; 111 DVLOG(1) << "Using WebRTC input buffer size: " << buffer_size;
109 112
110 media::AudioParameters::Format format = 113 media::AudioParameters::Format format =
111 media::AudioParameters::AUDIO_PCM_LOW_LATENCY; 114 media::AudioParameters::AUDIO_PCM_LOW_LATENCY;
112 115
113 // bits_per_sample is always 16 for now. 116 // bits_per_sample is always 16 for now.
114 int bits_per_sample = 16; 117 int bits_per_sample = 16;
115 media::AudioParameters params(format, channel_layout, sample_rate, 118 media::AudioParameters params(format, channel_layout, sample_rate,
116 bits_per_sample, buffer_size); 119 bits_per_sample, buffer_size);
120 DCHECK(params.IsValid());
117 121
118 TrackList tracks; 122 TrackList tracks;
119 { 123 {
120 base::AutoLock auto_lock(lock_); 124 base::AutoLock auto_lock(lock_);
121 tracks = tracks_; 125 tracks = tracks_;
122 params_ = params; 126 params_ = params;
123 } 127 }
124 128
125 // Tell all audio_tracks which format we use. 129 // Tell all audio_tracks which format we use.
126 for (TrackList::const_iterator it = tracks.begin(); 130 for (TrackList::const_iterator it = tracks.begin();
127 it != tracks.end(); ++it) 131 it != tracks.end(); ++it)
128 (*it)->SetCaptureFormat(params); 132 (*it)->SetCaptureFormat(params);
129 } 133 }
130 134
131 bool WebRtcAudioCapturer::Initialize(int render_view_id, 135 bool WebRtcAudioCapturer::Initialize(
132 media::ChannelLayout channel_layout, 136 int render_view_id,
133 int sample_rate, 137 media::ChannelLayout channel_layout,
134 int buffer_size, 138 int sample_rate,
135 int session_id, 139 int buffer_size,
136 const std::string& device_id, 140 int session_id,
137 int paired_output_sample_rate, 141 const std::string& device_id,
138 int paired_output_frames_per_buffer) { 142 int paired_output_sample_rate,
143 int paired_output_frames_per_buffer) {
139 DCHECK(thread_checker_.CalledOnValidThread()); 144 DCHECK(thread_checker_.CalledOnValidThread());
140 DCHECK_GE(render_view_id, 0); 145 DCHECK_GE(render_view_id, 0);
141 DVLOG(1) << "WebRtcAudioCapturer::Initialize()"; 146 DVLOG(1) << "WebRtcAudioCapturer::Initialize()";
142 147
143 DVLOG(1) << "Audio input hardware channel layout: " << channel_layout; 148 DVLOG(1) << "Audio input hardware channel layout: " << channel_layout;
144 UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputChannelLayout", 149 UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputChannelLayout",
145 channel_layout, media::CHANNEL_LAYOUT_MAX); 150 channel_layout, media::CHANNEL_LAYOUT_MAX);
146 151
147 render_view_id_ = render_view_id; 152 render_view_id_ = render_view_id;
148 session_id_ = session_id; 153 session_id_ = session_id;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 &kValidInputRates[0] + arraysize(kValidInputRates), 185 &kValidInputRates[0] + arraysize(kValidInputRates),
181 sample_rate) == 186 sample_rate) ==
182 &kValidInputRates[arraysize(kValidInputRates)]) { 187 &kValidInputRates[arraysize(kValidInputRates)]) {
183 DLOG(ERROR) << sample_rate << " is not a supported input rate."; 188 DLOG(ERROR) << sample_rate << " is not a supported input rate.";
184 return false; 189 return false;
185 } 190 }
186 191
187 // Create and configure the default audio capturing source. The |source_| 192 // Create and configure the default audio capturing source. The |source_|
188 // will be overwritten if an external client later calls SetCapturerSource() 193 // will be overwritten if an external client later calls SetCapturerSource()
189 // providing an alternative media::AudioCapturerSource. 194 // providing an alternative media::AudioCapturerSource.
190 SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id), 195 InitializeCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id),
191 channel_layout, 196 channel_layout,
192 static_cast<float>(sample_rate)); 197 static_cast<float>(sample_rate));
193 198
194 return true; 199 return true;
195 } 200 }
196 201
197 WebRtcAudioCapturer::WebRtcAudioCapturer() 202 WebRtcAudioCapturer::WebRtcAudioCapturer()
198 : source_(NULL), 203 : source_(NULL),
199 running_(false), 204 running_(false),
200 agc_is_enabled_(false), 205 agc_is_enabled_(false),
201 render_view_id_(-1), 206 render_view_id_(-1),
202 hardware_buffer_size_(0), 207 hardware_buffer_size_(0),
203 session_id_(0), 208 session_id_(0),
204 volume_(0), 209 volume_(0),
205 source_provider_(new WebRtcLocalAudioSourceProvider()),
206 peer_connection_mode_(false), 210 peer_connection_mode_(false),
207 output_sample_rate_(0), 211 output_sample_rate_(0),
208 output_frames_per_buffer_(0) { 212 output_frames_per_buffer_(0),
209 DCHECK(source_provider_.get()); 213 audio_delay_ms_(0),
214 key_pressed_(false) {
210 DVLOG(1) << "WebRtcAudioCapturer::WebRtcAudioCapturer()"; 215 DVLOG(1) << "WebRtcAudioCapturer::WebRtcAudioCapturer()";
211 } 216 }
212 217
213 WebRtcAudioCapturer::~WebRtcAudioCapturer() { 218 WebRtcAudioCapturer::~WebRtcAudioCapturer() {
214 DCHECK(thread_checker_.CalledOnValidThread()); 219 DCHECK(thread_checker_.CalledOnValidThread());
215 DCHECK(tracks_.empty()); 220 DCHECK(tracks_.empty());
216 DCHECK(!running_); 221 DCHECK(!running_);
217 DVLOG(1) << "WebRtcAudioCapturer::~WebRtcAudioCapturer()"; 222 DVLOG(1) << "WebRtcAudioCapturer::~WebRtcAudioCapturer()";
218 } 223 }
219 224
220 void WebRtcAudioCapturer::AddTrack(WebRtcLocalAudioTrack* track) { 225 void WebRtcAudioCapturer::AddTrack(WebRtcLocalAudioTrack* track) {
221 DCHECK(track); 226 DCHECK(track);
222 DVLOG(1) << "WebRtcAudioCapturer::AddTrack()"; 227 DVLOG(1) << "WebRtcAudioCapturer::AddTrack()";
223 228
224 // Start the source if the first audio track is connected to the capturer. 229 // Start the source if the first audio track is connected to the capturer.
225 // Start() will do nothing if the capturer has already been started. 230 // Start() will do nothing if the capturer has already been started.
226 Start(); 231 Start();
227 232
228 base::AutoLock auto_lock(lock_); 233 base::AutoLock auto_lock(lock_);
229 // Verify that |track| is not already added to the list. 234 // Verify that |track| is not already added to the list.
230 DCHECK(std::find_if(tracks_.begin(), tracks_.end(), 235 DCHECK(std::find_if(tracks_.begin(), tracks_.end(),
231 TrackOwner::TrackWrapper(track)) == tracks_.end()); 236 TrackOwner::TrackWrapper(track)) == tracks_.end());
232 237
233 track->SetCaptureFormat(params_); 238 if (params_.IsValid())
239 track->SetCaptureFormat(params_);
240
234 tracks_.push_back(new WebRtcAudioCapturer::TrackOwner(track)); 241 tracks_.push_back(new WebRtcAudioCapturer::TrackOwner(track));
235 } 242 }
236 243
237 void WebRtcAudioCapturer::RemoveTrack(WebRtcLocalAudioTrack* track) { 244 void WebRtcAudioCapturer::RemoveTrack(WebRtcLocalAudioTrack* track) {
238 DCHECK(thread_checker_.CalledOnValidThread()); 245 DCHECK(thread_checker_.CalledOnValidThread());
239 246
240 bool stop_source = false; 247 bool stop_source = false;
241 { 248 {
242 base::AutoLock auto_lock(lock_); 249 base::AutoLock auto_lock(lock_);
243 // Get iterator to the first element for which WrapsSink(track) returns 250 // Get iterator to the first element for which WrapsSink(track) returns
244 // true. 251 // true.
245 TrackList::iterator it = std::find_if( 252 TrackList::iterator it = std::find_if(
246 tracks_.begin(), tracks_.end(), TrackOwner::TrackWrapper(track)); 253 tracks_.begin(), tracks_.end(), TrackOwner::TrackWrapper(track));
247 if (it != tracks_.end()) { 254 if (it != tracks_.end()) {
248 // Clear the delegate to ensure that no more capture callbacks will 255 // Clear the delegate to ensure that no more capture callbacks will
249 // be sent to this sink. Also avoids a possible crash which can happen 256 // be sent to this sink. Also avoids a possible crash which can happen
250 // if this method is called while capturing is active. 257 // if this method is called while capturing is active.
251 (*it)->Reset(); 258 (*it)->Reset();
252 tracks_.erase(it); 259 tracks_.erase(it);
253 } 260 }
254 261
255 // Stop the source if the last audio track is going away. 262 // Stop the source if the last audio track is going away.
256 stop_source = tracks_.empty(); 263 stop_source = tracks_.empty();
257 } 264 }
258 265
259 if (stop_source) 266 if (stop_source)
260 Stop(); 267 Stop();
261 } 268 }
262 269
263 void WebRtcAudioCapturer::SetCapturerSource( 270 void WebRtcAudioCapturer::InitializeCapturerSource(
264 const scoped_refptr<media::AudioCapturerSource>& source, 271 const scoped_refptr<media::AudioCapturerSource>& source,
265 media::ChannelLayout channel_layout, 272 media::ChannelLayout channel_layout,
266 float sample_rate) { 273 float sample_rate) {
267 DCHECK(thread_checker_.CalledOnValidThread()); 274 DCHECK(thread_checker_.CalledOnValidThread());
268 DVLOG(1) << "SetCapturerSource(channel_layout=" << channel_layout << "," 275 DVLOG(1) << "InitializeCapturerSource(channel_layout=" << channel_layout
269 << "sample_rate=" << sample_rate << ")"; 276 << "," << "sample_rate=" << sample_rate << ")";
270 scoped_refptr<media::AudioCapturerSource> old_source; 277 scoped_refptr<media::AudioCapturerSource> old_source;
271 bool restart_source = false; 278 bool restart_source = false;
272 { 279 {
273 base::AutoLock auto_lock(lock_); 280 base::AutoLock auto_lock(lock_);
274 if (source_.get() == source.get()) 281 if (source_.get() == source.get())
275 return; 282 return;
276 283
277 source_.swap(old_source); 284 source_.swap(old_source);
278 source_ = source; 285 source_ = source;
279 286
280 // Reset the flag to allow starting the new source. 287 // Reset the flag to allow starting the new source.
281 restart_source = running_; 288 restart_source = running_;
282 running_ = false; 289 running_ = false;
283 } 290 }
284 291
285 DVLOG(1) << "Switching to a new capture source."; 292 DVLOG(1) << "Switching to a new capture source.";
286 if (old_source.get()) 293 if (old_source.get())
287 old_source->Stop(); 294 old_source->Stop();
288 295
289 // Dispatch the new parameters both to the sink(s) and to the new source. 296 // Dispatch the new parameters both to the sink(s) and to the new source.
290 // The idea is to get rid of any dependency of the microphone parameters 297 // The idea is to get rid of any dependency of the microphone parameters
291 // which would normally be used by default. 298 // which would normally be used by default.
292 Reconfigure(sample_rate, channel_layout); 299 Reconfigure(sample_rate, channel_layout);
293 300
294 // Make sure to grab the new parameters in case they were reconfigured. 301 // Make sure to grab the new parameters in case they were reconfigured.
295 media::AudioParameters params = audio_parameters(); 302 media::AudioParameters params = audio_parameters();
296 source_provider_->Initialize(params);
297 if (source.get()) 303 if (source.get())
298 source->Initialize(params, this, session_id_); 304 source->Initialize(params, this, session_id_);
299 305
300 if (restart_source) 306 if (restart_source)
301 Start(); 307 Start();
302 } 308 }
303 309
304 void WebRtcAudioCapturer::EnablePeerConnectionMode() { 310 void WebRtcAudioCapturer::EnablePeerConnectionMode() {
305 DCHECK(thread_checker_.CalledOnValidThread()); 311 DCHECK(thread_checker_.CalledOnValidThread());
306 DVLOG(1) << "EnablePeerConnectionMode"; 312 DVLOG(1) << "EnablePeerConnectionMode";
(...skipping 13 matching lines...) Expand all
320 render_view_id = render_view_id_; 326 render_view_id = render_view_id_;
321 } 327 }
322 328
323 // Do nothing if the current buffer size is the WebRtc native buffer size. 329 // Do nothing if the current buffer size is the WebRtc native buffer size.
324 media::AudioParameters params = audio_parameters(); 330 media::AudioParameters params = audio_parameters();
325 if (GetBufferSize(params.sample_rate()) == params.frames_per_buffer()) 331 if (GetBufferSize(params.sample_rate()) == params.frames_per_buffer())
326 return; 332 return;
327 333
328 // Create a new audio stream as source which will open the hardware using 334 // Create a new audio stream as source which will open the hardware using
329 // WebRtc native buffer size. 335 // WebRtc native buffer size.
330 SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id), 336 InitializeCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id),
331 params.channel_layout(), 337 params.channel_layout(),
332 static_cast<float>(params.sample_rate())); 338 static_cast<float>(params.sample_rate()));
333 } 339 }
334 340
335 void WebRtcAudioCapturer::Start() { 341 void WebRtcAudioCapturer::Start() {
336 DVLOG(1) << "WebRtcAudioCapturer::Start()"; 342 DVLOG(1) << "WebRtcAudioCapturer::Start()";
337 base::AutoLock auto_lock(lock_); 343 base::AutoLock auto_lock(lock_);
338 if (running_) 344 if (running_)
339 return; 345 return;
340 346
341 // Start the data source, i.e., start capturing data from the current source. 347 // Start the data source, i.e., start capturing data from the current source.
342 // Note that, the source does not have to be a microphone. 348 // Note that, the source does not have to be a microphone.
343 if (source_.get()) { 349 if (source_.get()) {
344 // We need to set the AGC control before starting the stream. 350 // We need to set the AGC control before starting the stream.
345 source_->SetAutomaticGainControl(agc_is_enabled_); 351 source_->SetAutomaticGainControl(agc_is_enabled_);
346 source_->Start(); 352 source_->Start();
347 } 353 }
348 354
349 running_ = true; 355 running_ = true;
350 } 356 }
351 357
352 void WebRtcAudioCapturer::Stop() { 358 void WebRtcAudioCapturer::Stop() {
353 DVLOG(1) << "WebRtcAudioCapturer::Stop()"; 359 DVLOG(1) << "WebRtcAudioCapturer::Stop()";
354 scoped_refptr<media::AudioCapturerSource> source; 360 scoped_refptr<media::AudioCapturerSource> source;
361 TrackList tracks;
355 { 362 {
356 base::AutoLock auto_lock(lock_); 363 base::AutoLock auto_lock(lock_);
357 if (!running_) 364 if (!running_)
358 return; 365 return;
359 366
360 source = source_; 367 source = source_;
368 tracks = tracks_;
361 running_ = false; 369 running_ = false;
362 } 370 }
363 371
364 if (source.get()) 372 if (source.get())
365 source->Stop(); 373 source->Stop();
374
375 for (TrackList::const_iterator it = tracks.begin(); it != tracks.end(); ++it)
376 (*it)->Reset();
366 } 377 }
367 378
368 void WebRtcAudioCapturer::SetVolume(int volume) { 379 void WebRtcAudioCapturer::SetVolume(int volume) {
369 DVLOG(1) << "WebRtcAudioCapturer::SetVolume()"; 380 DVLOG(1) << "WebRtcAudioCapturer::SetVolume()";
370 DCHECK_LE(volume, MaxVolume()); 381 DCHECK_LE(volume, MaxVolume());
371 double normalized_volume = static_cast<double>(volume) / MaxVolume(); 382 double normalized_volume = static_cast<double>(volume) / MaxVolume();
372 base::AutoLock auto_lock(lock_); 383 base::AutoLock auto_lock(lock_);
373 if (source_.get()) 384 if (source_.get())
374 source_->SetVolume(normalized_volume); 385 source_->SetVolume(normalized_volume);
375 } 386 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 return; 430 return;
420 431
421 // Map internal volume range of [0.0, 1.0] into [0, 255] used by the 432 // Map internal volume range of [0.0, 1.0] into [0, 255] used by the
422 // webrtc::VoiceEngine. webrtc::VoiceEngine will handle the case when the 433 // webrtc::VoiceEngine. webrtc::VoiceEngine will handle the case when the
423 // volume is higher than 255. 434 // volume is higher than 255.
424 volume_ = static_cast<int>((volume * MaxVolume()) + 0.5); 435 volume_ = static_cast<int>((volume * MaxVolume()) + 0.5);
425 current_volume = volume_; 436 current_volume = volume_;
426 tracks = tracks_; 437 tracks = tracks_;
427 } 438 }
428 439
429 // Deliver captured data to source provider, which stores the data into FIFO
430 // for WebAudio to fetch.
431 source_provider_->DeliverData(audio_source, audio_delay_milliseconds,
432 current_volume, key_pressed);
433
434 // Feed the data to the tracks. 440 // Feed the data to the tracks.
435 for (TrackList::const_iterator it = tracks.begin(); 441 for (TrackList::const_iterator it = tracks.begin();
436 it != tracks.end(); 442 it != tracks.end();
437 ++it) { 443 ++it) {
438 (*it)->Capture(audio_source, audio_delay_milliseconds, 444 (*it)->Capture(audio_source, audio_delay_milliseconds,
439 current_volume, key_pressed); 445 current_volume, key_pressed);
440 } 446 }
441 } 447 }
442 448
443 void WebRtcAudioCapturer::OnCaptureError() { 449 void WebRtcAudioCapturer::OnCaptureError() {
(...skipping 27 matching lines...) Expand all
471 // Use the native hardware buffer size in non peer connection mode on Mac. 477 // Use the native hardware buffer size in non peer connection mode on Mac.
472 if (!peer_connection_mode_ && hardware_buffer_size_) 478 if (!peer_connection_mode_ && hardware_buffer_size_)
473 return hardware_buffer_size_; 479 return hardware_buffer_size_;
474 #endif 480 #endif
475 481
476 // WebRtc is running at a buffer size of 10ms data. Use a multiple of 10ms 482 // WebRtc is running at a buffer size of 10ms data. Use a multiple of 10ms
477 // as the buffer size to achieve the best performance for WebRtc. 483 // as the buffer size to achieve the best performance for WebRtc.
478 return (sample_rate / 100); 484 return (sample_rate / 100);
479 } 485 }
480 486
487 void WebRtcAudioCapturer::GetAudioProcessingParams(
488 int* delay_ms, int* volume, bool* key_pressed) {
489 base::AutoLock auto_lock(lock_);
490 *delay_ms = audio_delay_ms_;
491 *volume = volume_;
492 *key_pressed = key_pressed_;
493 }
494
481 } // namespace content 495 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698