OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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_device_impl.h" | 5 #include "content/renderer/media/webrtc_audio_device_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
10 #include "base/win/windows_version.h" | 10 #include "base/win/windows_version.h" |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 // Calling Terminate() multiple times in a row is OK. | 163 // Calling Terminate() multiple times in a row is OK. |
164 if (!initialized_) | 164 if (!initialized_) |
165 return 0; | 165 return 0; |
166 | 166 |
167 StopRecording(); | 167 StopRecording(); |
168 StopPlayout(); | 168 StopPlayout(); |
169 | 169 |
170 DCHECK(!renderer_.get() || !renderer_->IsStarted()) | 170 DCHECK(!renderer_.get() || !renderer_->IsStarted()) |
171 << "The shared audio renderer shouldn't be running"; | 171 << "The shared audio renderer shouldn't be running"; |
172 | 172 |
173 // Stop all the capturers to ensure no further OnData() and | 173 { |
174 // RemoveAudioCapturer() callback. | 174 base::AutoLock auto_lock(lock_); |
175 // Cache the capturers in a local list since WebRtcAudioCapturer::Stop() | 175 capturers_.clear(); |
176 // will trigger RemoveAudioCapturer() callback. | |
177 CapturerList capturers; | |
178 capturers.swap(capturers_); | |
179 for (CapturerList::const_iterator iter = capturers.begin(); | |
180 iter != capturers.end(); ++iter) { | |
181 (*iter)->Stop(); | |
182 } | 176 } |
183 | 177 |
184 initialized_ = false; | 178 initialized_ = false; |
185 return 0; | 179 return 0; |
186 } | 180 } |
187 | 181 |
188 bool WebRtcAudioDeviceImpl::Initialized() const { | 182 bool WebRtcAudioDeviceImpl::Initialized() const { |
189 DCHECK(signaling_thread_checker_.CalledOnValidThread()); | 183 DCHECK(signaling_thread_checker_.CalledOnValidThread()); |
190 return initialized_; | 184 return initialized_; |
191 } | 185 } |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 return recording_; | 281 return recording_; |
288 } | 282 } |
289 | 283 |
290 int32_t WebRtcAudioDeviceImpl::SetMicrophoneVolume(uint32_t volume) { | 284 int32_t WebRtcAudioDeviceImpl::SetMicrophoneVolume(uint32_t volume) { |
291 DVLOG(1) << "WebRtcAudioDeviceImpl::SetMicrophoneVolume(" << volume << ")"; | 285 DVLOG(1) << "WebRtcAudioDeviceImpl::SetMicrophoneVolume(" << volume << ")"; |
292 DCHECK(signaling_thread_checker_.CalledOnValidThread()); | 286 DCHECK(signaling_thread_checker_.CalledOnValidThread()); |
293 DCHECK(initialized_); | 287 DCHECK(initialized_); |
294 | 288 |
295 // Only one microphone is supported at the moment, which is represented by | 289 // Only one microphone is supported at the moment, which is represented by |
296 // the default capturer. | 290 // the default capturer. |
297 scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer()); | 291 base::AutoLock auto_lock(lock_); |
298 if (!capturer.get()) | 292 if (capturers_.empty()) |
299 return -1; | 293 return -1; |
300 | 294 capturers_.back()->SetVolume(volume); |
301 capturer->SetVolume(volume); | |
302 return 0; | 295 return 0; |
303 } | 296 } |
304 | 297 |
305 // TODO(henrika): sort out calling thread once we start using this API. | 298 // TODO(henrika): sort out calling thread once we start using this API. |
306 int32_t WebRtcAudioDeviceImpl::MicrophoneVolume(uint32_t* volume) const { | 299 int32_t WebRtcAudioDeviceImpl::MicrophoneVolume(uint32_t* volume) const { |
307 DVLOG(1) << "WebRtcAudioDeviceImpl::MicrophoneVolume()"; | 300 DVLOG(1) << "WebRtcAudioDeviceImpl::MicrophoneVolume()"; |
308 DCHECK(signaling_thread_checker_.CalledOnValidThread()); | 301 DCHECK(signaling_thread_checker_.CalledOnValidThread()); |
309 // We only support one microphone now, which is accessed via the default | 302 // We only support one microphone now, which is accessed via the default |
310 // capturer. | 303 // capturer. |
311 DCHECK(initialized_); | 304 DCHECK(initialized_); |
312 scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer()); | 305 base::AutoLock auto_lock(lock_); |
313 if (!capturer.get()) | 306 if (capturers_.empty()) |
314 return -1; | 307 return -1; |
315 | 308 *volume = static_cast<uint32_t>(capturers_.back()->Volume()); |
316 *volume = static_cast<uint32_t>(capturer->Volume()); | |
317 | |
318 return 0; | 309 return 0; |
319 } | 310 } |
320 | 311 |
321 int32_t WebRtcAudioDeviceImpl::MaxMicrophoneVolume(uint32_t* max_volume) const { | 312 int32_t WebRtcAudioDeviceImpl::MaxMicrophoneVolume(uint32_t* max_volume) const { |
322 DCHECK(initialized_); | 313 DCHECK(initialized_); |
323 DCHECK(signaling_thread_checker_.CalledOnValidThread()); | 314 DCHECK(signaling_thread_checker_.CalledOnValidThread()); |
324 *max_volume = kMaxVolumeLevel; | 315 *max_volume = kMaxVolumeLevel; |
325 return 0; | 316 return 0; |
326 } | 317 } |
327 | 318 |
(...skipping 17 matching lines...) Expand all Loading... |
345 int32_t WebRtcAudioDeviceImpl::StereoRecordingIsAvailable( | 336 int32_t WebRtcAudioDeviceImpl::StereoRecordingIsAvailable( |
346 bool* available) const { | 337 bool* available) const { |
347 DCHECK(initialized_); | 338 DCHECK(initialized_); |
348 // This method is called during initialization on the signaling thread and | 339 // This method is called during initialization on the signaling thread and |
349 // then later on the worker thread. Due to this we cannot DCHECK on what | 340 // then later on the worker thread. Due to this we cannot DCHECK on what |
350 // thread we're on since it might incorrectly initialize the | 341 // thread we're on since it might incorrectly initialize the |
351 // worker_thread_checker_. | 342 // worker_thread_checker_. |
352 | 343 |
353 // TODO(xians): These kind of hardware methods do not make much sense since we | 344 // TODO(xians): These kind of hardware methods do not make much sense since we |
354 // support multiple sources. Remove or figure out new APIs for such methods. | 345 // support multiple sources. Remove or figure out new APIs for such methods. |
355 scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer()); | 346 base::AutoLock auto_lock(lock_); |
356 if (!capturer.get()) | 347 if (capturers_.empty()) |
357 return -1; | 348 return -1; |
358 | 349 *available = (capturers_.back()->GetInputFormat().channels() == 2); |
359 *available = (capturer->source_audio_parameters().channels() == 2); | |
360 return 0; | 350 return 0; |
361 } | 351 } |
362 | 352 |
363 int32_t WebRtcAudioDeviceImpl::PlayoutDelay(uint16_t* delay_ms) const { | 353 int32_t WebRtcAudioDeviceImpl::PlayoutDelay(uint16_t* delay_ms) const { |
364 DCHECK(worker_thread_checker_.CalledOnValidThread()); | 354 DCHECK(worker_thread_checker_.CalledOnValidThread()); |
365 base::AutoLock auto_lock(lock_); | 355 base::AutoLock auto_lock(lock_); |
366 *delay_ms = static_cast<uint16_t>(output_delay_ms_); | 356 *delay_ms = static_cast<uint16_t>(output_delay_ms_); |
367 return 0; | 357 return 0; |
368 } | 358 } |
369 | 359 |
370 int32_t WebRtcAudioDeviceImpl::RecordingDelay(uint16_t* delay_ms) const { | 360 int32_t WebRtcAudioDeviceImpl::RecordingDelay(uint16_t* delay_ms) const { |
371 DCHECK(signaling_thread_checker_.CalledOnValidThread()); | 361 DCHECK(signaling_thread_checker_.CalledOnValidThread()); |
372 | 362 |
373 // There is no way to report a correct delay value to WebRTC since there | 363 // There is no way to report a correct delay value to WebRTC since there |
374 // might be multiple WebRtcAudioCapturer instances. | 364 // might be multiple WebRtcAudioCapturer instances. |
375 NOTREACHED(); | 365 NOTREACHED(); |
376 return -1; | 366 return -1; |
377 } | 367 } |
378 | 368 |
379 int32_t WebRtcAudioDeviceImpl::RecordingSampleRate( | 369 int32_t WebRtcAudioDeviceImpl::RecordingSampleRate( |
380 uint32_t* sample_rate) const { | 370 uint32_t* sample_rate) const { |
381 DCHECK(signaling_thread_checker_.CalledOnValidThread()); | 371 DCHECK(signaling_thread_checker_.CalledOnValidThread()); |
382 // We use the default capturer as the recording sample rate. | 372 // We use the default capturer as the recording sample rate. |
383 scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer()); | 373 base::AutoLock auto_lock(lock_); |
384 if (!capturer.get()) | 374 if (capturers_.empty()) |
385 return -1; | 375 return -1; |
386 | 376 const media::AudioParameters& params = capturers_.back()->GetInputFormat(); |
387 *sample_rate = static_cast<uint32_t>( | 377 *sample_rate = static_cast<uint32_t>(params.sample_rate()); |
388 capturer->source_audio_parameters().sample_rate()); | |
389 return 0; | 378 return 0; |
390 } | 379 } |
391 | 380 |
392 int32_t WebRtcAudioDeviceImpl::PlayoutSampleRate( | 381 int32_t WebRtcAudioDeviceImpl::PlayoutSampleRate( |
393 uint32_t* sample_rate) const { | 382 uint32_t* sample_rate) const { |
394 DCHECK(signaling_thread_checker_.CalledOnValidThread()); | 383 DCHECK(signaling_thread_checker_.CalledOnValidThread()); |
395 *sample_rate = renderer_.get() ? renderer_->sample_rate() : 0; | 384 *sample_rate = renderer_.get() ? renderer_->sample_rate() : 0; |
396 return 0; | 385 return 0; |
397 } | 386 } |
398 | 387 |
(...skipping 27 matching lines...) Expand all Loading... |
426 audio_renderer_thread_checker_.DetachFromThread(); | 415 audio_renderer_thread_checker_.DetachFromThread(); |
427 | 416 |
428 // We acquire |lock_| again and assert our precondition, since we are | 417 // We acquire |lock_| again and assert our precondition, since we are |
429 // accessing the internal state again. | 418 // accessing the internal state again. |
430 base::AutoLock auto_lock(lock_); | 419 base::AutoLock auto_lock(lock_); |
431 DCHECK(!renderer_.get()); | 420 DCHECK(!renderer_.get()); |
432 renderer_ = renderer; | 421 renderer_ = renderer; |
433 return true; | 422 return true; |
434 } | 423 } |
435 | 424 |
436 void WebRtcAudioDeviceImpl::AddAudioCapturer( | 425 void WebRtcAudioDeviceImpl::AddAudioCapturer(WebRtcAudioCapturer* capturer) { |
437 const scoped_refptr<WebRtcAudioCapturer>& capturer) { | |
438 DCHECK(main_thread_checker_.CalledOnValidThread()); | 426 DCHECK(main_thread_checker_.CalledOnValidThread()); |
439 DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()"; | 427 DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()"; |
440 DCHECK(capturer.get()); | 428 DCHECK(capturer); |
441 DCHECK(!capturer->device_id().empty()); | 429 DCHECK(!capturer->device_info().device.id.empty()); |
442 | 430 |
443 base::AutoLock auto_lock(lock_); | 431 base::AutoLock auto_lock(lock_); |
444 DCHECK(std::find(capturers_.begin(), capturers_.end(), capturer) == | 432 DCHECK(std::find(capturers_.begin(), capturers_.end(), capturer) == |
445 capturers_.end()); | 433 capturers_.end()); |
446 capturers_.push_back(capturer); | 434 capturers_.push_back(capturer); |
447 } | 435 } |
448 | 436 |
449 void WebRtcAudioDeviceImpl::RemoveAudioCapturer( | 437 void WebRtcAudioDeviceImpl::RemoveAudioCapturer(WebRtcAudioCapturer* capturer) { |
450 const scoped_refptr<WebRtcAudioCapturer>& capturer) { | |
451 DCHECK(main_thread_checker_.CalledOnValidThread()); | 438 DCHECK(main_thread_checker_.CalledOnValidThread()); |
452 DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()"; | 439 DVLOG(1) << "WebRtcAudioDeviceImpl::RemoveAudioCapturer()"; |
453 DCHECK(capturer.get()); | 440 DCHECK(capturer); |
454 base::AutoLock auto_lock(lock_); | 441 base::AutoLock auto_lock(lock_); |
455 capturers_.remove(capturer); | 442 capturers_.remove(capturer); |
456 } | 443 } |
457 | 444 |
458 scoped_refptr<WebRtcAudioCapturer> | |
459 WebRtcAudioDeviceImpl::GetDefaultCapturer() const { | |
460 // Called on the signaling thread (during initialization), worker | |
461 // thread during capture or main thread for a WebAudio source. | |
462 // We can't DCHECK on those three checks here since GetDefaultCapturer | |
463 // may be the first call and therefore could incorrectly initialize the | |
464 // thread checkers. | |
465 DCHECK(initialized_); | |
466 base::AutoLock auto_lock(lock_); | |
467 // Use the last |capturer| which is from the latest getUserMedia call as | |
468 // the default capture device. | |
469 return capturers_.empty() ? NULL : capturers_.back(); | |
470 } | |
471 | |
472 void WebRtcAudioDeviceImpl::AddPlayoutSink( | 445 void WebRtcAudioDeviceImpl::AddPlayoutSink( |
473 WebRtcPlayoutDataSource::Sink* sink) { | 446 WebRtcPlayoutDataSource::Sink* sink) { |
474 DCHECK(main_thread_checker_.CalledOnValidThread()); | 447 DCHECK(main_thread_checker_.CalledOnValidThread()); |
475 DCHECK(sink); | 448 DCHECK(sink); |
476 base::AutoLock auto_lock(lock_); | 449 base::AutoLock auto_lock(lock_); |
477 DCHECK(std::find(playout_sinks_.begin(), playout_sinks_.end(), sink) == | 450 DCHECK(std::find(playout_sinks_.begin(), playout_sinks_.end(), sink) == |
478 playout_sinks_.end()); | 451 playout_sinks_.end()); |
479 playout_sinks_.push_back(sink); | 452 playout_sinks_.push_back(sink); |
480 } | 453 } |
481 | 454 |
482 void WebRtcAudioDeviceImpl::RemovePlayoutSink( | 455 void WebRtcAudioDeviceImpl::RemovePlayoutSink( |
483 WebRtcPlayoutDataSource::Sink* sink) { | 456 WebRtcPlayoutDataSource::Sink* sink) { |
484 DCHECK(main_thread_checker_.CalledOnValidThread()); | 457 DCHECK(main_thread_checker_.CalledOnValidThread()); |
485 DCHECK(sink); | 458 DCHECK(sink); |
486 base::AutoLock auto_lock(lock_); | 459 base::AutoLock auto_lock(lock_); |
487 playout_sinks_.remove(sink); | 460 playout_sinks_.remove(sink); |
488 } | 461 } |
489 | 462 |
490 bool WebRtcAudioDeviceImpl::GetAuthorizedDeviceInfoForAudioRenderer( | 463 bool WebRtcAudioDeviceImpl::GetAuthorizedDeviceInfoForAudioRenderer( |
491 int* session_id, | 464 int* session_id, |
492 int* output_sample_rate, | 465 int* output_sample_rate, |
493 int* output_frames_per_buffer) { | 466 int* output_frames_per_buffer) { |
494 DCHECK(main_thread_checker_.CalledOnValidThread()); | 467 DCHECK(main_thread_checker_.CalledOnValidThread()); |
495 base::AutoLock lock(lock_); | 468 base::AutoLock lock(lock_); |
496 // If there is no capturer or there are more than one open capture devices, | 469 // If there is no capturer or there are more than one open capture devices, |
497 // return false. | 470 // return false. |
498 if (capturers_.size() != 1) | 471 if (capturers_.size() != 1) |
499 return false; | 472 return false; |
500 | 473 |
501 return capturers_.back()->GetPairedOutputParameters( | 474 // Don't set output parameters unless all of them are valid. |
502 session_id, output_sample_rate, output_frames_per_buffer); | 475 const StreamDeviceInfo& device_info = capturers_.back()->device_info(); |
| 476 if (device_info.session_id <= 0 || |
| 477 !device_info.device.matched_output.sample_rate || |
| 478 !device_info.device.matched_output.frames_per_buffer) |
| 479 return false; |
| 480 |
| 481 *session_id = device_info.session_id; |
| 482 *output_sample_rate = device_info.device.matched_output.sample_rate; |
| 483 *output_frames_per_buffer = |
| 484 device_info.device.matched_output.frames_per_buffer; |
| 485 |
| 486 return true; |
503 } | 487 } |
504 | 488 |
505 } // namespace content | 489 } // namespace content |
OLD | NEW |