Chromium Code Reviews| 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 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 390 uint32_t* sample_rate) const { | 390 uint32_t* sample_rate) const { |
| 391 DCHECK(signaling_thread_checker_.CalledOnValidThread()); | 391 DCHECK(signaling_thread_checker_.CalledOnValidThread()); |
| 392 *sample_rate = renderer_.get() ? renderer_->sample_rate() : 0; | 392 *sample_rate = renderer_.get() ? renderer_->sample_rate() : 0; |
| 393 return 0; | 393 return 0; |
| 394 } | 394 } |
| 395 | 395 |
| 396 bool WebRtcAudioDeviceImpl::SetAudioRenderer(WebRtcAudioRenderer* renderer) { | 396 bool WebRtcAudioDeviceImpl::SetAudioRenderer(WebRtcAudioRenderer* renderer) { |
| 397 DCHECK(main_thread_checker_.CalledOnValidThread()); | 397 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 398 DCHECK(renderer); | 398 DCHECK(renderer); |
| 399 | 399 |
| 400 base::AutoLock auto_lock(lock_); | 400 // Here we acquire |lock_| in order to protect the internal state. |
| 401 if (renderer_.get()) | 401 { |
| 402 return false; | 402 base::AutoLock auto_lock(lock_); |
| 403 if (renderer_.get()) | |
| 404 return false; | |
| 405 } | |
| 403 | 406 |
| 407 // We release |lock_| here because invoking |renderer|->Initialize while | |
| 408 // holding |lock_| would result in locks taken in the sequence | |
| 409 // (|this->lock_|, |renderer->lock_|) while another thread (i.e, the | |
| 410 // AudioOutputDevice thread) might concurrently invoke a renderer method, | |
| 411 // which can itself invoke a method from |this|, resulting in locks taken in | |
| 412 // the sequence (|renderer->lock_|, |this->lock_|) in that thread. | |
| 413 // This order discrepancy can cause a deadlock (see Issue 433993). | |
| 414 // However, we do not need to hold |this->lock_| in order to invoke | |
| 415 // |renderer|->Initialize, since it does not involve any unprotected access to | |
| 416 // the internal state of |this|. | |
| 404 if (!renderer->Initialize(this)) | 417 if (!renderer->Initialize(this)) |
| 405 return false; | 418 return false; |
| 406 | 419 |
| 420 // We acquire |lock_| again and assert our precondition, since we are | |
| 421 // accessing the internal state again. | |
| 422 base::AutoLock auto_lock(lock_); | |
| 423 DCHECK(!renderer_.get()); | |
|
tommi (sloooow) - chröme
2015/03/31 08:29:13
Would also be good to have a note here about how i
| |
| 407 renderer_ = renderer; | 424 renderer_ = renderer; |
| 408 return true; | 425 return true; |
| 409 } | 426 } |
| 410 | 427 |
| 411 void WebRtcAudioDeviceImpl::AddAudioCapturer( | 428 void WebRtcAudioDeviceImpl::AddAudioCapturer( |
| 412 const scoped_refptr<WebRtcAudioCapturer>& capturer) { | 429 const scoped_refptr<WebRtcAudioCapturer>& capturer) { |
| 413 DCHECK(main_thread_checker_.CalledOnValidThread()); | 430 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 414 DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()"; | 431 DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()"; |
| 415 DCHECK(capturer.get()); | 432 DCHECK(capturer.get()); |
| 416 DCHECK(!capturer->device_id().empty()); | 433 DCHECK(!capturer->device_id().empty()); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 471 // If there is no capturer or there are more than one open capture devices, | 488 // If there is no capturer or there are more than one open capture devices, |
| 472 // return false. | 489 // return false. |
| 473 if (capturers_.size() != 1) | 490 if (capturers_.size() != 1) |
| 474 return false; | 491 return false; |
| 475 | 492 |
| 476 return capturers_.back()->GetPairedOutputParameters( | 493 return capturers_.back()->GetPairedOutputParameters( |
| 477 session_id, output_sample_rate, output_frames_per_buffer); | 494 session_id, output_sample_rate, output_frames_per_buffer); |
| 478 } | 495 } |
| 479 | 496 |
| 480 } // namespace content | 497 } // namespace content |
| OLD | NEW |