| Index: content/renderer/media/webrtc_audio_device_impl.cc
 | 
| diff --git a/content/renderer/media/webrtc_audio_device_impl.cc b/content/renderer/media/webrtc_audio_device_impl.cc
 | 
| index 17a058506df29f8345c98812840b888f9844ae4a..b5dc5008ad7ff831a8de3c05ff9d9795c005d950 100644
 | 
| --- a/content/renderer/media/webrtc_audio_device_impl.cc
 | 
| +++ b/content/renderer/media/webrtc_audio_device_impl.cc
 | 
| @@ -170,9 +170,15 @@
 | 
|    DCHECK(!renderer_.get() || !renderer_->IsStarted())
 | 
|        << "The shared audio renderer shouldn't be running";
 | 
|  
 | 
| -  {
 | 
| -    base::AutoLock auto_lock(lock_);
 | 
| -    capturers_.clear();
 | 
| +  // Stop all the capturers to ensure no further OnData() and
 | 
| +  // RemoveAudioCapturer() callback.
 | 
| +  // Cache the capturers in a local list since WebRtcAudioCapturer::Stop()
 | 
| +  // will trigger RemoveAudioCapturer() callback.
 | 
| +  CapturerList capturers;
 | 
| +  capturers.swap(capturers_);
 | 
| +  for (CapturerList::const_iterator iter = capturers.begin();
 | 
| +       iter != capturers.end(); ++iter) {
 | 
| +    (*iter)->Stop();
 | 
|    }
 | 
|  
 | 
|    initialized_ = false;
 | 
| @@ -288,10 +294,11 @@
 | 
|  
 | 
|    // Only one microphone is supported at the moment, which is represented by
 | 
|    // the default capturer.
 | 
| -  base::AutoLock auto_lock(lock_);
 | 
| -  if (capturers_.empty())
 | 
| +  scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer());
 | 
| +  if (!capturer.get())
 | 
|      return -1;
 | 
| -  capturers_.back()->SetVolume(volume);
 | 
| +
 | 
| +  capturer->SetVolume(volume);
 | 
|    return 0;
 | 
|  }
 | 
|  
 | 
| @@ -302,10 +309,12 @@
 | 
|    // We only support one microphone now, which is accessed via the default
 | 
|    // capturer.
 | 
|    DCHECK(initialized_);
 | 
| -  base::AutoLock auto_lock(lock_);
 | 
| -  if (capturers_.empty())
 | 
| +  scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer());
 | 
| +  if (!capturer.get())
 | 
|      return -1;
 | 
| -  *volume = static_cast<uint32_t>(capturers_.back()->Volume());
 | 
| +
 | 
| +  *volume = static_cast<uint32_t>(capturer->Volume());
 | 
| +
 | 
|    return 0;
 | 
|  }
 | 
|  
 | 
| @@ -343,10 +352,11 @@
 | 
|  
 | 
|    // TODO(xians): These kind of hardware methods do not make much sense since we
 | 
|    // support multiple sources. Remove or figure out new APIs for such methods.
 | 
| -  base::AutoLock auto_lock(lock_);
 | 
| -  if (capturers_.empty())
 | 
| +  scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer());
 | 
| +  if (!capturer.get())
 | 
|      return -1;
 | 
| -  *available = (capturers_.back()->GetInputFormat().channels() == 2);
 | 
| +
 | 
| +  *available = (capturer->source_audio_parameters().channels() == 2);
 | 
|    return 0;
 | 
|  }
 | 
|  
 | 
| @@ -370,11 +380,12 @@
 | 
|      uint32_t* sample_rate) const {
 | 
|    DCHECK(signaling_thread_checker_.CalledOnValidThread());
 | 
|    // We use the default capturer as the recording sample rate.
 | 
| -  base::AutoLock auto_lock(lock_);
 | 
| -  if (capturers_.empty())
 | 
| +  scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer());
 | 
| +  if (!capturer.get())
 | 
|      return -1;
 | 
| -  const media::AudioParameters& params = capturers_.back()->GetInputFormat();
 | 
| -  *sample_rate = static_cast<uint32_t>(params.sample_rate());
 | 
| +
 | 
| +  *sample_rate = static_cast<uint32_t>(
 | 
| +      capturer->source_audio_parameters().sample_rate());
 | 
|    return 0;
 | 
|  }
 | 
|  
 | 
| @@ -422,11 +433,12 @@
 | 
|    return true;
 | 
|  }
 | 
|  
 | 
| -void WebRtcAudioDeviceImpl::AddAudioCapturer(WebRtcAudioCapturer* capturer) {
 | 
| +void WebRtcAudioDeviceImpl::AddAudioCapturer(
 | 
| +    const scoped_refptr<WebRtcAudioCapturer>& capturer) {
 | 
|    DCHECK(main_thread_checker_.CalledOnValidThread());
 | 
|    DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()";
 | 
| -  DCHECK(capturer);
 | 
| -  DCHECK(!capturer->device_info().device.id.empty());
 | 
| +  DCHECK(capturer.get());
 | 
| +  DCHECK(!capturer->device_id().empty());
 | 
|  
 | 
|    base::AutoLock auto_lock(lock_);
 | 
|    DCHECK(std::find(capturers_.begin(), capturers_.end(), capturer) ==
 | 
| @@ -434,12 +446,27 @@
 | 
|    capturers_.push_back(capturer);
 | 
|  }
 | 
|  
 | 
| -void WebRtcAudioDeviceImpl::RemoveAudioCapturer(WebRtcAudioCapturer* capturer) {
 | 
| -  DCHECK(main_thread_checker_.CalledOnValidThread());
 | 
| -  DVLOG(1) << "WebRtcAudioDeviceImpl::RemoveAudioCapturer()";
 | 
| -  DCHECK(capturer);
 | 
| +void WebRtcAudioDeviceImpl::RemoveAudioCapturer(
 | 
| +    const scoped_refptr<WebRtcAudioCapturer>& capturer) {
 | 
| +  DCHECK(main_thread_checker_.CalledOnValidThread());
 | 
| +  DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()";
 | 
| +  DCHECK(capturer.get());
 | 
|    base::AutoLock auto_lock(lock_);
 | 
|    capturers_.remove(capturer);
 | 
| +}
 | 
| +
 | 
| +scoped_refptr<WebRtcAudioCapturer>
 | 
| +WebRtcAudioDeviceImpl::GetDefaultCapturer() const {
 | 
| +  // Called on the signaling thread (during initialization), worker
 | 
| +  // thread during capture or main thread for a WebAudio source.
 | 
| +  // We can't DCHECK on those three checks here since GetDefaultCapturer
 | 
| +  // may be the first call and therefore could incorrectly initialize the
 | 
| +  // thread checkers.
 | 
| +  DCHECK(initialized_);
 | 
| +  base::AutoLock auto_lock(lock_);
 | 
| +  // Use the last |capturer| which is from the latest getUserMedia call as
 | 
| +  // the default capture device.
 | 
| +  return capturers_.empty() ? NULL : capturers_.back();
 | 
|  }
 | 
|  
 | 
|  void WebRtcAudioDeviceImpl::AddPlayoutSink(
 | 
| @@ -471,20 +498,8 @@
 | 
|    if (capturers_.size() != 1)
 | 
|      return false;
 | 
|  
 | 
| -  // Don't set output parameters unless all of them are valid.
 | 
| -  const StreamDeviceInfo& device_info = capturers_.back()->device_info();
 | 
| -  if (device_info.session_id <= 0 ||
 | 
| -      !device_info.device.matched_output.sample_rate ||
 | 
| -      !device_info.device.matched_output.frames_per_buffer) {
 | 
| -    return false;
 | 
| -  }
 | 
| -
 | 
| -  *session_id = device_info.session_id;
 | 
| -  *output_sample_rate = device_info.device.matched_output.sample_rate;
 | 
| -  *output_frames_per_buffer =
 | 
| -      device_info.device.matched_output.frames_per_buffer;
 | 
| -
 | 
| -  return true;
 | 
| +  return capturers_.back()->GetPairedOutputParameters(
 | 
| +      session_id, output_sample_rate, output_frames_per_buffer);
 | 
|  }
 | 
|  
 | 
|  }  // namespace content
 | 
| 
 |