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

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: rebased and fixed the comment. 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 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 } 106 }
107 107
108 // Do NOT reference count the |delegate_| to avoid cyclic reference counting. 108 // Do NOT reference count the |delegate_| to avoid cyclic reference counting.
109 WebRtcLocalAudioTrack* delegate_; 109 WebRtcLocalAudioTrack* delegate_;
110 mutable base::Lock lock_; 110 mutable base::Lock lock_;
111 111
112 DISALLOW_COPY_AND_ASSIGN(TrackOwner); 112 DISALLOW_COPY_AND_ASSIGN(TrackOwner);
113 }; 113 };
114 114
115 // static 115 // static
116 scoped_refptr<WebRtcAudioCapturer> WebRtcAudioCapturer::CreateCapturer() { 116 scoped_refptr<WebRtcAudioCapturer> WebRtcAudioCapturer::CreateCapturer(
117 scoped_refptr<WebRtcAudioCapturer> capturer = new WebRtcAudioCapturer(); 117 int render_view_id, const StreamDeviceInfo& device_info,
118 return capturer; 118 const blink::WebMediaConstraints& constraints,
119 WebRtcAudioDeviceImpl* audio_device) {
120 scoped_refptr<WebRtcAudioCapturer> capturer = new WebRtcAudioCapturer(
121 render_view_id, device_info, constraints, audio_device);
122 if (capturer->Initialize())
123 return capturer;
124
125 return NULL;
119 } 126 }
120 127
121 bool WebRtcAudioCapturer::Initialize(int render_view_id, 128 bool WebRtcAudioCapturer::Initialize() {
122 media::ChannelLayout channel_layout,
123 int sample_rate,
124 int buffer_size,
125 int session_id,
126 const std::string& device_id,
127 int paired_output_sample_rate,
128 int paired_output_frames_per_buffer,
129 int effects,
130 const blink::WebMediaConstraints& constraints) {
131 DCHECK(thread_checker_.CalledOnValidThread()); 129 DCHECK(thread_checker_.CalledOnValidThread());
132 DVLOG(1) << "WebRtcAudioCapturer::Initialize()"; 130 DVLOG(1) << "WebRtcAudioCapturer::Initialize()";
131 WebRtcLogMessage(base::StringPrintf(
132 "WAC::Initialize. render_view_id=%d"
133 ", channel_layout=%d, sample_rate=%d, buffer_size=%d"
134 ", session_id=%d, paired_output_sample_rate=%d"
135 ", paired_output_frames_per_buffer=%d, effects=%d. ",
136 render_view_id_,
137 device_info_.device.input.channel_layout,
138 device_info_.device.input.sample_rate,
139 device_info_.device.input.frames_per_buffer,
140 device_info_.session_id,
141 device_info_.device.matched_output.sample_rate,
142 device_info_.device.matched_output.frames_per_buffer,
143 device_info_.device.input.effects));
133 144
145 if (render_view_id_ == -1) {
146 // Return true here to allow injecting a new source via
147 // SetCapturerSourceForTesting() at a later state.
148 return true;
149 }
150
151 media::ChannelLayout channel_layout = static_cast<media::ChannelLayout>(
152 device_info_.device.input.channel_layout);
134 DVLOG(1) << "Audio input hardware channel layout: " << channel_layout; 153 DVLOG(1) << "Audio input hardware channel layout: " << channel_layout;
135 UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputChannelLayout", 154 UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputChannelLayout",
136 channel_layout, media::CHANNEL_LAYOUT_MAX); 155 channel_layout, media::CHANNEL_LAYOUT_MAX);
137 156
138 WebRtcLogMessage(base::StringPrintf(
139 "WAC::Initialize. render_view_id=%d"
140 ", channel_layout=%d, sample_rate=%d, buffer_size=%d"
141 ", session_id=%d, paired_output_sample_rate=%d"
142 ", paired_output_frames_per_buffer=%d",
143 render_view_id,
144 channel_layout,
145 sample_rate,
146 buffer_size,
147 session_id,
148 paired_output_sample_rate,
149 paired_output_frames_per_buffer));
150
151 render_view_id_ = render_view_id;
152 session_id_ = session_id;
153 device_id_ = device_id;
154 hardware_buffer_size_ = buffer_size;
155 output_sample_rate_ = paired_output_sample_rate;
156 output_frames_per_buffer_= paired_output_frames_per_buffer;
157 constraints_ = constraints;
158
159 if (render_view_id == -1) {
160 // Return true here to allow injecting a new source via SetCapturerSource()
161 // at a later state.
162 return true;
163 }
164
165 // Verify that the reported input channel configuration is supported. 157 // Verify that the reported input channel configuration is supported.
166 if (channel_layout != media::CHANNEL_LAYOUT_MONO && 158 if (channel_layout != media::CHANNEL_LAYOUT_MONO &&
167 channel_layout != media::CHANNEL_LAYOUT_STEREO) { 159 channel_layout != media::CHANNEL_LAYOUT_STEREO) {
168 DLOG(ERROR) << channel_layout 160 DLOG(ERROR) << channel_layout
169 << " is not a supported input channel configuration."; 161 << " is not a supported input channel configuration.";
170 return false; 162 return false;
171 } 163 }
172 164
173 DVLOG(1) << "Audio input hardware sample rate: " << sample_rate; 165 DVLOG(1) << "Audio input hardware sample rate: "
174 media::AudioSampleRate asr = media::AsAudioSampleRate(sample_rate); 166 << device_info_.device.input.sample_rate;
167 media::AudioSampleRate asr = media::AsAudioSampleRate(
168 device_info_.device.input.sample_rate);
175 if (asr != media::kUnexpectedAudioSampleRate) { 169 if (asr != media::kUnexpectedAudioSampleRate) {
176 UMA_HISTOGRAM_ENUMERATION( 170 UMA_HISTOGRAM_ENUMERATION(
177 "WebRTC.AudioInputSampleRate", asr, media::kUnexpectedAudioSampleRate); 171 "WebRTC.AudioInputSampleRate", asr, media::kUnexpectedAudioSampleRate);
178 } else { 172 } else {
179 UMA_HISTOGRAM_COUNTS("WebRTC.AudioInputSampleRateUnexpected", sample_rate); 173 UMA_HISTOGRAM_COUNTS("WebRTC.AudioInputSampleRateUnexpected",
174 device_info_.device.input.sample_rate);
180 } 175 }
181 176
182 // Verify that the reported input hardware sample rate is supported 177 // Verify that the reported input hardware sample rate is supported
183 // on the current platform. 178 // on the current platform.
184 if (std::find(&kValidInputRates[0], 179 if (std::find(&kValidInputRates[0],
185 &kValidInputRates[0] + arraysize(kValidInputRates), 180 &kValidInputRates[0] + arraysize(kValidInputRates),
186 sample_rate) == 181 device_info_.device.input.sample_rate) ==
187 &kValidInputRates[arraysize(kValidInputRates)]) { 182 &kValidInputRates[arraysize(kValidInputRates)]) {
188 DLOG(ERROR) << sample_rate << " is not a supported input rate."; 183 DLOG(ERROR) << device_info_.device.input.sample_rate
184 << " is not a supported input rate.";
189 return false; 185 return false;
190 } 186 }
191 187
192 // Create and configure the default audio capturing source. The |source_| 188 // Create and configure the default audio capturing source.
193 // will be overwritten if an external client later calls SetCapturerSource() 189 SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id_),
194 // providing an alternative media::AudioCapturerSource.
195 SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id),
196 channel_layout, 190 channel_layout,
197 static_cast<float>(sample_rate), 191 static_cast<float>(device_info_.device.input.sample_rate),
198 effects, 192 device_info_.device.input.effects,
199 constraints); 193 constraints_);
194
195 // Add the capturer to the WebRtcAudioDeviceImpl since it needs some hardware
196 // information from the capturer.
197 if (audio_device_)
198 audio_device_->AddAudioCapturer(this);
200 199
201 return true; 200 return true;
202 } 201 }
203 202
204 WebRtcAudioCapturer::WebRtcAudioCapturer() 203 WebRtcAudioCapturer::WebRtcAudioCapturer(
205 : running_(false), 204 int render_view_id,
206 render_view_id_(-1), 205 const StreamDeviceInfo& device_info,
207 hardware_buffer_size_(0), 206 const blink::WebMediaConstraints& constraints,
208 session_id_(0), 207 WebRtcAudioDeviceImpl* audio_device)
208 : constraints_(constraints),
209 running_(false),
210 render_view_id_(render_view_id),
211 device_info_(device_info),
209 volume_(0), 212 volume_(0),
210 peer_connection_mode_(false), 213 peer_connection_mode_(false),
211 output_sample_rate_(0),
212 output_frames_per_buffer_(0),
213 key_pressed_(false), 214 key_pressed_(false),
214 need_audio_processing_(false) { 215 need_audio_processing_(false),
216 audio_device_(audio_device) {
215 DVLOG(1) << "WebRtcAudioCapturer::WebRtcAudioCapturer()"; 217 DVLOG(1) << "WebRtcAudioCapturer::WebRtcAudioCapturer()";
216 } 218 }
217 219
218 WebRtcAudioCapturer::~WebRtcAudioCapturer() { 220 WebRtcAudioCapturer::~WebRtcAudioCapturer() {
219 DCHECK(thread_checker_.CalledOnValidThread()); 221 DCHECK(thread_checker_.CalledOnValidThread());
220 DCHECK(tracks_.IsEmpty()); 222 DCHECK(tracks_.IsEmpty());
221 DCHECK(!running_); 223 DCHECK(!running_);
222 DVLOG(1) << "WebRtcAudioCapturer::~WebRtcAudioCapturer()"; 224 DVLOG(1) << "WebRtcAudioCapturer::~WebRtcAudioCapturer()";
223 } 225 }
224 226
(...skipping 13 matching lines...) Expand all
238 } 240 }
239 241
240 // Start the source if the first audio track is connected to the capturer. 242 // Start the source if the first audio track is connected to the capturer.
241 // Start() will do nothing if the capturer has already been started. 243 // Start() will do nothing if the capturer has already been started.
242 Start(); 244 Start();
243 245
244 } 246 }
245 247
246 void WebRtcAudioCapturer::RemoveTrack(WebRtcLocalAudioTrack* track) { 248 void WebRtcAudioCapturer::RemoveTrack(WebRtcLocalAudioTrack* track) {
247 DCHECK(thread_checker_.CalledOnValidThread()); 249 DCHECK(thread_checker_.CalledOnValidThread());
250 base::AutoLock auto_lock(lock_);
248 251
249 bool stop_source = false; 252 scoped_refptr<TrackOwner> removed_item =
250 { 253 tracks_.Remove(TrackOwner::TrackWrapper(track));
251 base::AutoLock auto_lock(lock_);
252 254
253 scoped_refptr<TrackOwner> removed_item = 255 // Clear the delegate to ensure that no more capture callbacks will
254 tracks_.Remove(TrackOwner::TrackWrapper(track)); 256 // be sent to this sink. Also avoids a possible crash which can happen
255 257 // if this method is called while capturing is active.
256 // Clear the delegate to ensure that no more capture callbacks will 258 if (removed_item.get())
257 // be sent to this sink. Also avoids a possible crash which can happen 259 removed_item->Reset();
258 // if this method is called while capturing is active.
259 if (removed_item.get())
260 removed_item->Reset();
261
262 // Stop the source if the last audio track is going away.
263 stop_source = tracks_.IsEmpty();
264 }
265
266 if (stop_source)
267 Stop();
268 } 260 }
269 261
270 void WebRtcAudioCapturer::SetCapturerSource( 262 void WebRtcAudioCapturer::SetCapturerSource(
271 const scoped_refptr<media::AudioCapturerSource>& source, 263 const scoped_refptr<media::AudioCapturerSource>& source,
272 media::ChannelLayout channel_layout, 264 media::ChannelLayout channel_layout,
273 float sample_rate, 265 float sample_rate,
274 int effects, 266 int effects,
275 const blink::WebMediaConstraints& constraints) { 267 const blink::WebMediaConstraints& constraints) {
276 DCHECK(thread_checker_.CalledOnValidThread()); 268 DCHECK(thread_checker_.CalledOnValidThread());
277 DVLOG(1) << "SetCapturerSource(channel_layout=" << channel_layout << "," 269 DVLOG(1) << "SetCapturerSource(channel_layout=" << channel_layout << ","
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 { 301 {
310 base::AutoLock auto_lock(lock_); 302 base::AutoLock auto_lock(lock_);
311 audio_processor_ = new_audio_processor; 303 audio_processor_ = new_audio_processor;
312 need_audio_processing_ = NeedsAudioProcessing(constraints, effects); 304 need_audio_processing_ = NeedsAudioProcessing(constraints, effects);
313 305
314 // Notify all tracks about the new format. 306 // Notify all tracks about the new format.
315 tracks_.TagAll(); 307 tracks_.TagAll();
316 } 308 }
317 309
318 if (source.get()) 310 if (source.get())
319 source->Initialize(params, this, session_id_); 311 source->Initialize(params, this, session_id());
320 312
321 if (restart_source) 313 if (restart_source)
322 Start(); 314 Start();
323 } 315 }
324 316
325 void WebRtcAudioCapturer::EnablePeerConnectionMode() { 317 void WebRtcAudioCapturer::EnablePeerConnectionMode() {
326 DCHECK(thread_checker_.CalledOnValidThread()); 318 DCHECK(thread_checker_.CalledOnValidThread());
327 DVLOG(1) << "EnablePeerConnectionMode"; 319 DVLOG(1) << "EnablePeerConnectionMode";
328 // Do nothing if the peer connection mode has been enabled. 320 // Do nothing if the peer connection mode has been enabled.
329 if (peer_connection_mode_) 321 if (peer_connection_mode_)
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 base::AutoLock auto_lock(lock_); 371 base::AutoLock auto_lock(lock_);
380 if (!running_) 372 if (!running_)
381 return; 373 return;
382 374
383 source = source_; 375 source = source_;
384 tracks = tracks_.Items(); 376 tracks = tracks_.Items();
385 tracks_.Clear(); 377 tracks_.Clear();
386 running_ = false; 378 running_ = false;
387 } 379 }
388 380
381 // Remove the capturer object from the WebRtcAudioDeviceImpl.
382 if (audio_device_)
383 audio_device_->RemoveAudioCapturer(this);
384
389 for (TrackList::ItemList::const_iterator it = tracks.begin(); 385 for (TrackList::ItemList::const_iterator it = tracks.begin();
390 it != tracks.end(); 386 it != tracks.end();
391 ++it) { 387 ++it) {
392 (*it)->Stop(); 388 (*it)->Stop();
393 } 389 }
394 390
395 if (source.get()) 391 if (source.get())
396 source->Stop(); 392 source->Stop();
397 } 393 }
398 394
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 base::AutoLock auto_lock(lock_); 499 base::AutoLock auto_lock(lock_);
504 return audio_processor_ ? 500 return audio_processor_ ?
505 audio_processor_->InputFormat() : media::AudioParameters(); 501 audio_processor_->InputFormat() : media::AudioParameters();
506 } 502 }
507 503
508 bool WebRtcAudioCapturer::GetPairedOutputParameters( 504 bool WebRtcAudioCapturer::GetPairedOutputParameters(
509 int* session_id, 505 int* session_id,
510 int* output_sample_rate, 506 int* output_sample_rate,
511 int* output_frames_per_buffer) const { 507 int* output_frames_per_buffer) const {
512 // Don't set output parameters unless all of them are valid. 508 // Don't set output parameters unless all of them are valid.
513 if (session_id_ <= 0 || !output_sample_rate_ || !output_frames_per_buffer_) 509 if (device_info_.session_id <= 0 ||
510 !device_info_.device.matched_output.sample_rate ||
511 !device_info_.device.matched_output.frames_per_buffer)
514 return false; 512 return false;
515 513
516 *session_id = session_id_; 514 *session_id = device_info_.session_id;
517 *output_sample_rate = output_sample_rate_; 515 *output_sample_rate = device_info_.device.matched_output.sample_rate;
518 *output_frames_per_buffer = output_frames_per_buffer_; 516 *output_frames_per_buffer =
517 device_info_.device.matched_output.frames_per_buffer;
519 518
520 return true; 519 return true;
521 } 520 }
522 521
523 int WebRtcAudioCapturer::GetBufferSize(int sample_rate) const { 522 int WebRtcAudioCapturer::GetBufferSize(int sample_rate) const {
524 DCHECK(thread_checker_.CalledOnValidThread()); 523 DCHECK(thread_checker_.CalledOnValidThread());
525 #if defined(OS_ANDROID) 524 #if defined(OS_ANDROID)
526 // TODO(henrika): Tune and adjust buffer size on Android. 525 // TODO(henrika): Tune and adjust buffer size on Android.
527 return (2 * sample_rate / 100); 526 return (2 * sample_rate / 100);
528 #endif 527 #endif
529 528
530 // PeerConnection is running at a buffer size of 10ms data. A multiple of 529 // PeerConnection is running at a buffer size of 10ms data. A multiple of
531 // 10ms as the buffer size can give the best performance to PeerConnection. 530 // 10ms as the buffer size can give the best performance to PeerConnection.
532 int peer_connection_buffer_size = sample_rate / 100; 531 int peer_connection_buffer_size = sample_rate / 100;
533 532
534 // Use the native hardware buffer size in non peer connection mode when the 533 // Use the native hardware buffer size in non peer connection mode when the
535 // platform is using a native buffer size smaller than the PeerConnection 534 // platform is using a native buffer size smaller than the PeerConnection
536 // buffer size. 535 // buffer size.
537 if (!peer_connection_mode_ && hardware_buffer_size_ && 536 int hardware_buffer_size = device_info_.device.input.frames_per_buffer;
538 hardware_buffer_size_ <= peer_connection_buffer_size) { 537 if (!peer_connection_mode_ && hardware_buffer_size &&
539 return hardware_buffer_size_; 538 hardware_buffer_size <= peer_connection_buffer_size) {
539 return hardware_buffer_size;
540 } 540 }
541 541
542 return (sample_rate / 100); 542 return (sample_rate / 100);
543 } 543 }
544 544
545 void WebRtcAudioCapturer::GetAudioProcessingParams( 545 void WebRtcAudioCapturer::GetAudioProcessingParams(
546 base::TimeDelta* delay, int* volume, bool* key_pressed) { 546 base::TimeDelta* delay, int* volume, bool* key_pressed) {
547 base::AutoLock auto_lock(lock_); 547 base::AutoLock auto_lock(lock_);
548 *delay = audio_delay_; 548 *delay = audio_delay_;
549 *volume = volume_; 549 *volume = volume_;
(...skipping 14 matching lines...) Expand all
564 564
565 audio_processor = audio_processor_; 565 audio_processor = audio_processor_;
566 } 566 }
567 567
568 audio_processor->PushRenderData(render_audio, sample_rate, 568 audio_processor->PushRenderData(render_audio, sample_rate,
569 number_of_channels, 569 number_of_channels,
570 number_of_frames, 570 number_of_frames,
571 render_delay); 571 render_delay);
572 } 572 }
573 573
574 void WebRtcAudioCapturer::SetCapturerSourceForTesting(
575 const scoped_refptr<media::AudioCapturerSource>& source,
576 media::AudioParameters params) {
577 // Create a new audio stream as source which uses the new source.
578 SetCapturerSource(source, params.channel_layout(),
579 static_cast<float>(params.sample_rate()),
580 params.effects(),
581 constraints_);
582 }
583
574 } // namespace content 584 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/media/webrtc_audio_capturer.h ('k') | content/renderer/media/webrtc_audio_capturer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698