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