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. |