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 |