| Index: media/audio/audio_output_mixer.cc
|
| ===================================================================
|
| --- media/audio/audio_output_mixer.cc (revision 141503)
|
| +++ media/audio/audio_output_mixer.cc (working copy)
|
| @@ -47,8 +47,6 @@
|
| }
|
| pending_bytes_ = 0; // Just in case.
|
| physical_stream_.reset(stream);
|
| - physical_stream_->SetVolume(1.0);
|
| - physical_stream_->Start(this);
|
| close_timer_.Reset();
|
| return true;
|
| }
|
| @@ -66,24 +64,46 @@
|
|
|
| double volume = 0.0;
|
| stream_proxy->GetVolume(&volume);
|
| -
|
| - base::AutoLock lock(lock_);
|
| - ProxyData* proxy_data = &proxies_[stream_proxy];
|
| - proxy_data->audio_source_callback = callback;
|
| - proxy_data->volume = volume;
|
| - proxy_data->pending_bytes = 0;
|
| + bool should_start = proxies_.empty();
|
| + {
|
| + base::AutoLock lock(lock_);
|
| + ProxyData* proxy_data = &proxies_[stream_proxy];
|
| + proxy_data->audio_source_callback = callback;
|
| + proxy_data->volume = volume;
|
| + proxy_data->pending_bytes = 0;
|
| + }
|
| + // We cannot start physical stream under the lock,
|
| + // OnMoreData() would try acquiring it...
|
| + if (should_start) {
|
| + physical_stream_->SetVolume(1.0);
|
| + physical_stream_->Start(this);
|
| + }
|
| return true;
|
| }
|
|
|
| void AudioOutputMixer::StopStream(AudioOutputProxy* stream_proxy) {
|
| DCHECK_EQ(MessageLoop::current(), message_loop_);
|
|
|
| - base::AutoLock lock(lock_);
|
| - ProxyMap::iterator it = proxies_.find(stream_proxy);
|
| - if (it != proxies_.end())
|
| - proxies_.erase(it);
|
| - if (physical_stream_.get())
|
| + // Because of possible deadlock we cannot stop physical stream under the lock
|
| + // (physical_stream_->Stop() can call OnError(), and it acquires the lock to
|
| + // iterate through proxies), so acquire the lock, update proxy list, release
|
| + // the lock, and only then stop physical stream if necessary.
|
| + bool stop_physical_stream = false;
|
| + {
|
| + base::AutoLock lock(lock_);
|
| + ProxyMap::iterator it = proxies_.find(stream_proxy);
|
| + if (it != proxies_.end()) {
|
| + proxies_.erase(it);
|
| + stop_physical_stream = proxies_.empty();
|
| + }
|
| + }
|
| + if (physical_stream_.get()) {
|
| + if (stop_physical_stream) {
|
| + physical_stream_->Stop();
|
| + pending_bytes_ = 0; // Just in case.
|
| + }
|
| close_timer_.Reset();
|
| + }
|
| }
|
|
|
| void AudioOutputMixer::StreamVolumeSet(AudioOutputProxy* stream_proxy,
|
| @@ -124,10 +144,8 @@
|
| void AudioOutputMixer::ClosePhysicalStream() {
|
| DCHECK_EQ(MessageLoop::current(), message_loop_);
|
|
|
| - if (proxies_.empty() && physical_stream_.get() != NULL) {
|
| - physical_stream_->Stop();
|
| + if (proxies_.empty() && physical_stream_.get() != NULL)
|
| physical_stream_.release()->Close();
|
| - }
|
| }
|
|
|
| // AudioSourceCallback implementation.
|
|
|