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

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: Created 7 years, 2 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"
11 #include "content/child/child_process.h" 11 #include "content/child/child_process.h"
12 #include "content/renderer/media/audio_device_factory.h" 12 #include "content/renderer/media/audio_device_factory.h"
13 #include "content/renderer/media/webrtc_audio_device_impl.h" 13 #include "content/renderer/media/webrtc_audio_device_impl.h"
14 #include "content/renderer/media/webrtc_audio_processing_wrapper.h"
14 #include "content/renderer/media/webrtc_local_audio_track.h" 15 #include "content/renderer/media/webrtc_local_audio_track.h"
15 #include "media/audio/sample_rates.h" 16 #include "media/audio/sample_rates.h"
16 17
17 namespace content { 18 namespace content {
18 19
19 namespace { 20 namespace {
20 21
21 // Supported hardware sample rates for input and output sides. 22 // Supported hardware sample rates for input and output sides.
22 #if defined(OS_WIN) || defined(OS_MACOSX) 23 #if defined(OS_WIN) || defined(OS_MACOSX)
23 // media::GetAudioInputHardwareSampleRate() asks the audio layer 24 // media::GetAudioInputHardwareSampleRate() asks the audio layer
(...skipping 11 matching lines...) Expand all
35 36
36 } // namespace 37 } // namespace
37 38
38 // Reference counted container of WebRtcLocalAudioTrack delegate. 39 // Reference counted container of WebRtcLocalAudioTrack delegate.
39 class WebRtcAudioCapturer::TrackOwner 40 class WebRtcAudioCapturer::TrackOwner
40 : public base::RefCountedThreadSafe<WebRtcAudioCapturer::TrackOwner> { 41 : public base::RefCountedThreadSafe<WebRtcAudioCapturer::TrackOwner> {
41 public: 42 public:
42 explicit TrackOwner(WebRtcLocalAudioTrack* track) 43 explicit TrackOwner(WebRtcLocalAudioTrack* track)
43 : delegate_(track) {} 44 : delegate_(track) {}
44 45
45 void Capture(media::AudioBus* audio_source, 46 void Capture(const int16* data,
46 int audio_delay_milliseconds, 47 int sample_rate,
47 double volume, 48 int number_of_channels,
48 bool key_pressed) { 49 int number_of_frames) {
49 base::AutoLock lock(lock_); 50 base::AutoLock lock(lock_);
50 if (delegate_) { 51 if (delegate_) {
51 delegate_->Capture(audio_source, 52 delegate_->Capture(data,
52 audio_delay_milliseconds, 53 sample_rate,
53 volume, 54 number_of_channels,
54 key_pressed); 55 number_of_frames);
55 } 56 }
56 } 57 }
57 58
58 void SetCaptureFormat(const media::AudioParameters& params) { 59 void SetCaptureFormat(const media::AudioParameters& params) {
59 base::AutoLock lock(lock_); 60 base::AutoLock lock(lock_);
60 if (delegate_) 61 if (delegate_)
61 delegate_->SetCaptureFormat(params); 62 delegate_->SetCaptureFormat(params);
62 } 63 }
63 64
64 void Reset() { 65 void Reset() {
(...skipping 29 matching lines...) Expand all
94 95
95 DISALLOW_COPY_AND_ASSIGN(TrackOwner); 96 DISALLOW_COPY_AND_ASSIGN(TrackOwner);
96 }; 97 };
97 98
98 // static 99 // static
99 scoped_refptr<WebRtcAudioCapturer> WebRtcAudioCapturer::CreateCapturer() { 100 scoped_refptr<WebRtcAudioCapturer> WebRtcAudioCapturer::CreateCapturer() {
100 scoped_refptr<WebRtcAudioCapturer> capturer = new WebRtcAudioCapturer(); 101 scoped_refptr<WebRtcAudioCapturer> capturer = new WebRtcAudioCapturer();
101 return capturer; 102 return capturer;
102 } 103 }
103 104
104 void WebRtcAudioCapturer::Reconfigure(int sample_rate, 105 void WebRtcAudioCapturer::Reconfigure(
105 media::ChannelLayout channel_layout) { 106 int sample_rate,
107 media::ChannelLayout channel_layout,
108 const webrtc::MediaConstraintsInterface* constraints) {
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);
117 120
121 audio_processing_.reset(new WebRtcAudioProcessingWrapper());
122 audio_processing_->Configure(params, constraints);
123 sink_params_ = audio_processing_->OutputFormat();
124
118 TrackList tracks; 125 TrackList tracks;
119 { 126 {
120 base::AutoLock auto_lock(lock_); 127 base::AutoLock auto_lock(lock_);
121 tracks = tracks_; 128 tracks = tracks_;
122 params_ = params; 129 source_params_ = params;
123 } 130 }
124 131
125 // Tell all audio_tracks which format we use. 132 // Tell all audio_tracks which format we use.
126 for (TrackList::const_iterator it = tracks.begin(); 133 for (TrackList::const_iterator it = tracks.begin();
127 it != tracks.end(); ++it) 134 it != tracks.end(); ++it)
128 (*it)->SetCaptureFormat(params); 135 (*it)->SetCaptureFormat(sink_params_);
129 } 136 }
130 137
131 bool WebRtcAudioCapturer::Initialize(int render_view_id, 138 bool WebRtcAudioCapturer::Initialize(
132 media::ChannelLayout channel_layout, 139 int render_view_id,
133 int sample_rate, 140 media::ChannelLayout channel_layout,
134 int buffer_size, 141 int sample_rate,
135 int session_id, 142 int buffer_size,
136 const std::string& device_id, 143 int session_id,
137 int paired_output_sample_rate, 144 const std::string& device_id,
138 int paired_output_frames_per_buffer) { 145 int paired_output_sample_rate,
146 int paired_output_frames_per_buffer,
147 const webrtc::MediaConstraintsInterface* constraints) {
139 DCHECK(thread_checker_.CalledOnValidThread()); 148 DCHECK(thread_checker_.CalledOnValidThread());
140 DCHECK_GE(render_view_id, 0); 149 DCHECK_GE(render_view_id, 0);
141 DVLOG(1) << "WebRtcAudioCapturer::Initialize()"; 150 DVLOG(1) << "WebRtcAudioCapturer::Initialize()";
142 151
143 DVLOG(1) << "Audio input hardware channel layout: " << channel_layout; 152 DVLOG(1) << "Audio input hardware channel layout: " << channel_layout;
144 UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputChannelLayout", 153 UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputChannelLayout",
145 channel_layout, media::CHANNEL_LAYOUT_MAX); 154 channel_layout, media::CHANNEL_LAYOUT_MAX);
146 155
147 render_view_id_ = render_view_id; 156 render_view_id_ = render_view_id;
148 session_id_ = session_id; 157 session_id_ = session_id;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 &kValidInputRates[0] + arraysize(kValidInputRates), 189 &kValidInputRates[0] + arraysize(kValidInputRates),
181 sample_rate) == 190 sample_rate) ==
182 &kValidInputRates[arraysize(kValidInputRates)]) { 191 &kValidInputRates[arraysize(kValidInputRates)]) {
183 DLOG(ERROR) << sample_rate << " is not a supported input rate."; 192 DLOG(ERROR) << sample_rate << " is not a supported input rate.";
184 return false; 193 return false;
185 } 194 }
186 195
187 // Create and configure the default audio capturing source. The |source_| 196 // Create and configure the default audio capturing source. The |source_|
188 // will be overwritten if an external client later calls SetCapturerSource() 197 // will be overwritten if an external client later calls SetCapturerSource()
189 // providing an alternative media::AudioCapturerSource. 198 // providing an alternative media::AudioCapturerSource.
190 SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id), 199 InitializeCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id),
191 channel_layout, 200 channel_layout,
192 static_cast<float>(sample_rate)); 201 static_cast<float>(sample_rate),
202 constraints);
193 203
194 return true; 204 return true;
195 } 205 }
196 206
197 WebRtcAudioCapturer::WebRtcAudioCapturer() 207 WebRtcAudioCapturer::WebRtcAudioCapturer()
198 : source_(NULL), 208 : source_(NULL),
199 running_(false), 209 running_(false),
200 agc_is_enabled_(false), 210 agc_is_enabled_(false),
201 render_view_id_(-1), 211 render_view_id_(-1),
202 hardware_buffer_size_(0), 212 hardware_buffer_size_(0),
(...skipping 20 matching lines...) Expand all
223 233
224 // Start the source if the first audio track is connected to the capturer. 234 // 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. 235 // Start() will do nothing if the capturer has already been started.
226 Start(); 236 Start();
227 237
228 base::AutoLock auto_lock(lock_); 238 base::AutoLock auto_lock(lock_);
229 // Verify that |track| is not already added to the list. 239 // Verify that |track| is not already added to the list.
230 DCHECK(std::find_if(tracks_.begin(), tracks_.end(), 240 DCHECK(std::find_if(tracks_.begin(), tracks_.end(),
231 TrackOwner::TrackWrapper(track)) == tracks_.end()); 241 TrackOwner::TrackWrapper(track)) == tracks_.end());
232 242
233 track->SetCaptureFormat(params_); 243 track->SetCaptureFormat(sink_params_);
234 tracks_.push_back(new WebRtcAudioCapturer::TrackOwner(track)); 244 tracks_.push_back(new WebRtcAudioCapturer::TrackOwner(track));
235 } 245 }
236 246
237 void WebRtcAudioCapturer::RemoveTrack(WebRtcLocalAudioTrack* track) { 247 void WebRtcAudioCapturer::RemoveTrack(WebRtcLocalAudioTrack* track) {
238 DCHECK(thread_checker_.CalledOnValidThread()); 248 DCHECK(thread_checker_.CalledOnValidThread());
239 249
240 bool stop_source = false; 250 bool stop_source = false;
241 { 251 {
242 base::AutoLock auto_lock(lock_); 252 base::AutoLock auto_lock(lock_);
243 // Get iterator to the first element for which WrapsSink(track) returns 253 // Get iterator to the first element for which WrapsSink(track) returns
244 // true. 254 // true.
245 TrackList::iterator it = std::find_if( 255 TrackList::iterator it = std::find_if(
246 tracks_.begin(), tracks_.end(), TrackOwner::TrackWrapper(track)); 256 tracks_.begin(), tracks_.end(), TrackOwner::TrackWrapper(track));
247 if (it != tracks_.end()) { 257 if (it != tracks_.end()) {
248 // Clear the delegate to ensure that no more capture callbacks will 258 // 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 259 // be sent to this sink. Also avoids a possible crash which can happen
250 // if this method is called while capturing is active. 260 // if this method is called while capturing is active.
251 (*it)->Reset(); 261 (*it)->Reset();
252 tracks_.erase(it); 262 tracks_.erase(it);
253 } 263 }
254 264
255 // Stop the source if the last audio track is going away. 265 // Stop the source if the last audio track is going away.
256 stop_source = tracks_.empty(); 266 stop_source = tracks_.empty();
257 } 267 }
258 268
259 if (stop_source) 269 if (stop_source)
260 Stop(); 270 Stop();
261 } 271 }
262 272
263 void WebRtcAudioCapturer::SetCapturerSource( 273 void WebRtcAudioCapturer::InitializeCapturerSource(
264 const scoped_refptr<media::AudioCapturerSource>& source, 274 const scoped_refptr<media::AudioCapturerSource>& source,
265 media::ChannelLayout channel_layout, 275 media::ChannelLayout channel_layout,
266 float sample_rate) { 276 float sample_rate,
277 const webrtc::MediaConstraintsInterface* constraints) {
267 DCHECK(thread_checker_.CalledOnValidThread()); 278 DCHECK(thread_checker_.CalledOnValidThread());
268 DVLOG(1) << "SetCapturerSource(channel_layout=" << channel_layout << "," 279 DVLOG(1) << "InitializeCapturerSource(channel_layout=" << channel_layout
269 << "sample_rate=" << sample_rate << ")"; 280 << "," << "sample_rate=" << sample_rate << ")";
270 scoped_refptr<media::AudioCapturerSource> old_source; 281 scoped_refptr<media::AudioCapturerSource> old_source;
271 bool restart_source = false; 282 bool restart_source = false;
272 { 283 {
273 base::AutoLock auto_lock(lock_); 284 base::AutoLock auto_lock(lock_);
274 if (source_.get() == source.get()) 285 if (source_.get() == source.get())
275 return; 286 return;
276 287
277 source_.swap(old_source); 288 source_.swap(old_source);
278 source_ = source; 289 source_ = source;
279 290
280 // Reset the flag to allow starting the new source. 291 // Reset the flag to allow starting the new source.
281 restart_source = running_; 292 restart_source = running_;
282 running_ = false; 293 running_ = false;
283 } 294 }
284 295
285 DVLOG(1) << "Switching to a new capture source."; 296 DVLOG(1) << "Switching to a new capture source.";
286 if (old_source.get()) 297 if (old_source.get())
287 old_source->Stop(); 298 old_source->Stop();
288 299
289 // Dispatch the new parameters both to the sink(s) and to the new source. 300 // 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 301 // The idea is to get rid of any dependency of the microphone parameters
291 // which would normally be used by default. 302 // which would normally be used by default.
292 Reconfigure(sample_rate, channel_layout); 303 Reconfigure(sample_rate, channel_layout, constraints);
293 304
294 // Make sure to grab the new parameters in case they were reconfigured. 305 // Make sure to grab the new parameters in case they were reconfigured.
295 media::AudioParameters params = audio_parameters(); 306 media::AudioParameters params = audio_parameters();
296 source_provider_->Initialize(params); 307 source_provider_->Initialize(params);
297 if (source.get()) 308 if (source.get())
298 source->Initialize(params, this, session_id_); 309 source->Initialize(params, this, session_id_);
299 310
300 if (restart_source) 311 if (restart_source)
301 Start(); 312 Start();
302 } 313 }
(...skipping 17 matching lines...) Expand all
320 render_view_id = render_view_id_; 331 render_view_id = render_view_id_;
321 } 332 }
322 333
323 // Do nothing if the current buffer size is the WebRtc native buffer size. 334 // Do nothing if the current buffer size is the WebRtc native buffer size.
324 media::AudioParameters params = audio_parameters(); 335 media::AudioParameters params = audio_parameters();
325 if (GetBufferSize(params.sample_rate()) == params.frames_per_buffer()) 336 if (GetBufferSize(params.sample_rate()) == params.frames_per_buffer())
326 return; 337 return;
327 338
328 // Create a new audio stream as source which will open the hardware using 339 // Create a new audio stream as source which will open the hardware using
329 // WebRtc native buffer size. 340 // WebRtc native buffer size.
330 SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id), 341 InitializeCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id),
331 params.channel_layout(), 342 params.channel_layout(),
332 static_cast<float>(params.sample_rate())); 343 static_cast<float>(params.sample_rate()),
344 NULL);
333 } 345 }
334 346
347 void WebRtcAudioCapturer::FeedRenderDataToAudioProcessing(
348 const int16* render_audio,
349 int sample_rate,
350 int number_of_channels,
351 int number_of_frames,
352 int render_delay_ms) {
353 audio_processing_->FeedRenderDataToAudioProcessing(render_audio,
354 sample_rate,
355 number_of_channels,
356 number_of_frames,
357 render_delay_ms);
358
359 }
335 void WebRtcAudioCapturer::Start() { 360 void WebRtcAudioCapturer::Start() {
336 DVLOG(1) << "WebRtcAudioCapturer::Start()"; 361 DVLOG(1) << "WebRtcAudioCapturer::Start()";
337 base::AutoLock auto_lock(lock_); 362 base::AutoLock auto_lock(lock_);
338 if (running_) 363 if (running_)
339 return; 364 return;
340 365
341 // Start the data source, i.e., start capturing data from the current source. 366 // 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. 367 // Note that, the source does not have to be a microphone.
343 if (source_.get()) { 368 if (source_.get()) {
344 // We need to set the AGC control before starting the stream. 369 // We need to set the AGC control before starting the stream.
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 #elif defined(OS_LINUX) || defined(OS_OPENBSD) 430 #elif defined(OS_LINUX) || defined(OS_OPENBSD)
406 // We have a special situation on Linux where the microphone volume can be 431 // We have a special situation on Linux where the microphone volume can be
407 // "higher than maximum". The input volume slider in the sound preference 432 // "higher than maximum". The input volume slider in the sound preference
408 // allows the user to set a scaling that is higher than 100%. It means that 433 // allows the user to set a scaling that is higher than 100%. It means that
409 // even if the reported maximum levels is N, the actual microphone level can 434 // even if the reported maximum levels is N, the actual microphone level can
410 // go up to 1.5x*N and that corresponds to a normalized |volume| of 1.5x. 435 // go up to 1.5x*N and that corresponds to a normalized |volume| of 1.5x.
411 DCHECK_LE(volume, 1.6); 436 DCHECK_LE(volume, 1.6);
412 #endif 437 #endif
413 438
414 TrackList tracks; 439 TrackList tracks;
415 int current_volume = 0;
416 { 440 {
417 base::AutoLock auto_lock(lock_); 441 base::AutoLock auto_lock(lock_);
418 if (!running_) 442 if (!running_)
419 return; 443 return;
420 444
421 // Map internal volume range of [0.0, 1.0] into [0, 255] used by the 445 // 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 446 // webrtc::VoiceEngine. webrtc::VoiceEngine will handle the case when the
423 // volume is higher than 255. 447 // volume is higher than 255.
424 volume_ = static_cast<int>((volume * MaxVolume()) + 0.5); 448 volume_ = static_cast<int>((volume * MaxVolume()) + 0.5);
425 current_volume = volume_;
426 tracks = tracks_; 449 tracks = tracks_;
427 } 450 }
428 451
429 // Deliver captured data to source provider, which stores the data into FIFO 452 audio_processing_->Push(audio_source);
430 // for WebAudio to fetch. 453 int current_volume = volume;
431 source_provider_->DeliverData(audio_source, audio_delay_milliseconds, 454 while (audio_processing_->ProcessAndConsume10MsData(audio_delay_milliseconds,
432 current_volume, key_pressed); 455 current_volume,
456 key_pressed)) {
457 // TODO(xians): Get the new volume and set it to |current_volume|.
433 458
434 // Feed the data to the tracks. 459 for (TrackList::const_iterator it = tracks.begin();
435 for (TrackList::const_iterator it = tracks.begin(); 460 it != tracks.end(); ++it) {
436 it != tracks.end(); 461 (*it)->Capture(audio_processing_->OutputBuffer(),
437 ++it) { 462 sink_params_.sample_rate(),
438 (*it)->Capture(audio_source, audio_delay_milliseconds, 463 sink_params_.channels(),
439 current_volume, key_pressed); 464 sink_params_.frames_per_buffer());
465 }
466
467 // TODO(xians): Make the source provider as one of the sinks.
468 // Deliver captured data to source provider, which stores the data into FIFO
469 // for WebAudio to fetch.
470 source_provider_->DeliverData(audio_processing_->OutputBuffer(),
471 sink_params_.sample_rate(),
472 sink_params_.channels(),
473 sink_params_.frames_per_buffer());
440 } 474 }
441 } 475 }
442 476
443 void WebRtcAudioCapturer::OnCaptureError() { 477 void WebRtcAudioCapturer::OnCaptureError() {
444 NOTIMPLEMENTED(); 478 NOTIMPLEMENTED();
445 } 479 }
446 480
447 media::AudioParameters WebRtcAudioCapturer::audio_parameters() const { 481 media::AudioParameters WebRtcAudioCapturer::audio_parameters() const {
448 base::AutoLock auto_lock(lock_); 482 base::AutoLock auto_lock(lock_);
449 return params_; 483 return source_params_;
450 } 484 }
451 485
452 bool WebRtcAudioCapturer::GetPairedOutputParameters( 486 bool WebRtcAudioCapturer::GetPairedOutputParameters(
453 int* session_id, 487 int* session_id,
454 int* output_sample_rate, 488 int* output_sample_rate,
455 int* output_frames_per_buffer) const { 489 int* output_frames_per_buffer) const {
456 *session_id = session_id_; 490 *session_id = session_id_;
457 *output_sample_rate = output_sample_rate_; 491 *output_sample_rate = output_sample_rate_;
458 *output_frames_per_buffer = output_frames_per_buffer_; 492 *output_frames_per_buffer = output_frames_per_buffer_;
459 return session_id_ > 0 && output_sample_rate_ > 0 && 493 return session_id_ > 0 && output_sample_rate_ > 0 &&
(...skipping 12 matching lines...) Expand all
472 if (!peer_connection_mode_ && hardware_buffer_size_) 506 if (!peer_connection_mode_ && hardware_buffer_size_)
473 return hardware_buffer_size_; 507 return hardware_buffer_size_;
474 #endif 508 #endif
475 509
476 // WebRtc is running at a buffer size of 10ms data. Use a multiple of 10ms 510 // 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. 511 // as the buffer size to achieve the best performance for WebRtc.
478 return (sample_rate / 100); 512 return (sample_rate / 100);
479 } 513 }
480 514
481 } // namespace content 515 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698