Index: media/audio/virtual_audio_input_stream.cc |
diff --git a/media/audio/virtual_audio_input_stream.cc b/media/audio/virtual_audio_input_stream.cc |
index b03bb836b4184d6bc4403f81651fcc17c7adcea0..d79ca9ff44d14aed9f060695d109dfed7a8b8eb0 100644 |
--- a/media/audio/virtual_audio_input_stream.cc |
+++ b/media/audio/virtual_audio_input_stream.cc |
@@ -8,6 +8,7 @@ |
#include <utility> |
#include "base/bind.h" |
+#include "base/message_loop.h" |
#include "base/message_loop/message_loop_proxy.h" |
#include "media/audio/virtual_audio_output_stream.h" |
@@ -49,50 +50,60 @@ class LoopbackAudioConverter : public AudioConverter::InputCallback { |
VirtualAudioInputStream::VirtualAudioInputStream( |
const AudioParameters& params, |
- const scoped_refptr<base::MessageLoopProxy>& message_loop, |
+ const scoped_refptr<base::MessageLoopProxy>& worker_loop, |
const AfterCloseCallback& after_close_cb) |
- : message_loop_(message_loop), |
+ : worker_loop_(worker_loop), |
after_close_cb_(after_close_cb), |
callback_(NULL), |
buffer_(new uint8[params.GetBytesPerBuffer()]), |
params_(params), |
mixer_(params_, params_, false), |
num_attached_output_streams_(0), |
- fake_consumer_(message_loop_, params_) { |
+ fake_consumer_(worker_loop_, params_) { |
DCHECK(params_.IsValid()); |
- DCHECK(message_loop_.get()); |
+ DCHECK(worker_loop_.get()); |
+ |
+ // VAIS can be constructed on any thread, but will DCHECK that all |
+ // AudioInputStream methods are called from the same thread. |
+ thread_checker_.DetachFromThread(); |
} |
VirtualAudioInputStream::~VirtualAudioInputStream() { |
+ DCHECK(!callback_); |
+ |
+ // Sanity-check: Contract for Add/RemoveOutputStream() requires that all |
+ // output streams be removed before VirtualAudioInputStream is destroyed. |
+ DCHECK_EQ(0, num_attached_output_streams_); |
+ |
for (AudioConvertersMap::iterator it = converters_.begin(); |
it != converters_.end(); ++it) { |
delete it->second; |
} |
- |
- DCHECK_EQ(0, num_attached_output_streams_); |
} |
bool VirtualAudioInputStream::Open() { |
- DCHECK(message_loop_->BelongsToCurrentThread()); |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
memset(buffer_.get(), 0, params_.GetBytesPerBuffer()); |
return true; |
} |
void VirtualAudioInputStream::Start(AudioInputCallback* callback) { |
- DCHECK(message_loop_->BelongsToCurrentThread()); |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
callback_ = callback; |
fake_consumer_.Start(base::Bind( |
- &VirtualAudioInputStream::ReadAudio, base::Unretained(this))); |
+ &VirtualAudioInputStream::PumpAudio, base::Unretained(this))); |
} |
void VirtualAudioInputStream::Stop() { |
- DCHECK(message_loop_->BelongsToCurrentThread()); |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
fake_consumer_.Stop(); |
} |
void VirtualAudioInputStream::AddOutputStream( |
VirtualAudioOutputStream* stream, const AudioParameters& output_params) { |
- DCHECK(message_loop_->BelongsToCurrentThread()); |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ base::AutoLock scoped_lock(converter_network_lock_); |
AudioConvertersMap::iterator converter = converters_.find(output_params); |
if (converter == converters_.end()) { |
@@ -110,7 +121,9 @@ void VirtualAudioInputStream::AddOutputStream( |
void VirtualAudioInputStream::RemoveOutputStream( |
VirtualAudioOutputStream* stream, const AudioParameters& output_params) { |
- DCHECK(message_loop_->BelongsToCurrentThread()); |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ base::AutoLock scoped_lock(converter_network_lock_); |
DCHECK(converters_.find(output_params) != converters_.end()); |
converters_[output_params]->RemoveInput(stream); |
@@ -119,15 +132,17 @@ void VirtualAudioInputStream::RemoveOutputStream( |
DCHECK_LE(0, num_attached_output_streams_); |
} |
-void VirtualAudioInputStream::ReadAudio(AudioBus* audio_bus) { |
- DCHECK(message_loop_->BelongsToCurrentThread()); |
+void VirtualAudioInputStream::PumpAudio(AudioBus* audio_bus) { |
+ DCHECK(worker_loop_->BelongsToCurrentThread()); |
DCHECK(callback_); |
- mixer_.Convert(audio_bus); |
+ { |
+ base::AutoLock scoped_lock(converter_network_lock_); |
+ mixer_.Convert(audio_bus); |
+ } |
audio_bus->ToInterleaved(params_.frames_per_buffer(), |
params_.bits_per_sample() / 8, |
buffer_.get()); |
- |
callback_->OnData(this, |
buffer_.get(), |
params_.GetBytesPerBuffer(), |
@@ -136,8 +151,9 @@ void VirtualAudioInputStream::ReadAudio(AudioBus* audio_bus) { |
} |
void VirtualAudioInputStream::Close() { |
- DCHECK(message_loop_->BelongsToCurrentThread()); |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ Stop(); // Make sure callback_ is no longer being used. |
if (callback_) { |
callback_->OnClose(this); |
callback_ = NULL; |