Index: media/audio/audio_manager_base.cc |
diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc |
index 4f7e676d21aa3188bc42b682bc8f52b71a3388d8..8141d715e5eee0e07762decc3daaedd278d26dd7 100644 |
--- a/media/audio/audio_manager_base.cc |
+++ b/media/audio/audio_manager_base.cc |
@@ -91,23 +91,7 @@ AudioManagerBase::AudioManagerBase(AudioLogFactory* audio_log_factory) |
// block the UI thread when swapping devices. |
output_listeners_( |
base::ObserverList<AudioDeviceListener>::NOTIFY_EXISTING_ONLY), |
- audio_thread_("AudioThread"), |
audio_log_factory_(audio_log_factory) { |
-#if defined(OS_WIN) |
- audio_thread_.init_com_with_mta(true); |
-#elif defined(OS_MACOSX) |
- // CoreAudio calls must occur on the main thread of the process, which in our |
- // case is sadly the browser UI thread. Failure to execute calls on the right |
- // thread leads to crashes and odd behavior. See http://crbug.com/158170. |
- // TODO(dalecurtis): We should require the message loop to be passed in. |
- if (base::MessageLoopForUI::IsCurrent()) { |
- task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
- return; |
- } |
-#endif |
- |
- CHECK(audio_thread_.Start()); |
- task_runner_ = audio_thread_.task_runner(); |
} |
AudioManagerBase::~AudioManagerBase() { |
@@ -116,7 +100,7 @@ AudioManagerBase::~AudioManagerBase() { |
// stopping the thread, resulting an unexpected behavior. |
// This way we make sure activities of the audio streams are all stopped |
// before we destroy them. |
- CHECK(!audio_thread_.IsRunning()); |
+ CHECK(!audio_thread_); |
// All the output streams should have been deleted. |
DCHECK_EQ(0, num_output_streams_); |
// All the input streams should have been deleted. |
@@ -127,18 +111,20 @@ base::string16 AudioManagerBase::GetAudioInputDeviceModel() { |
return base::string16(); |
} |
-scoped_refptr<base::SingleThreadTaskRunner> AudioManagerBase::GetTaskRunner() |
- const { |
- return task_runner_; |
+scoped_refptr<base::SingleThreadTaskRunner> AudioManagerBase::GetTaskRunner() { |
+ if (!audio_thread_) { |
+ audio_thread_.reset(new base::Thread("AudioThread")); |
+#if defined(OS_WIN) |
+ audio_thread_->init_com_with_mta(true); |
+#endif |
+ CHECK(audio_thread_->Start()); |
+ } |
+ return audio_thread_->task_runner(); |
} |
scoped_refptr<base::SingleThreadTaskRunner> |
AudioManagerBase::GetWorkerTaskRunner() { |
- // Lazily start the worker thread. |
- if (!audio_thread_.IsRunning()) |
- CHECK(audio_thread_.Start()); |
- |
- return audio_thread_.task_runner(); |
+ return GetTaskRunner(); |
} |
AudioOutputStream* AudioManagerBase::MakeAudioOutputStream( |
@@ -146,7 +132,7 @@ AudioOutputStream* AudioManagerBase::MakeAudioOutputStream( |
const std::string& device_id) { |
// TODO(miu): Fix ~50 call points across several unit test modules to call |
// this method on the audio thread, then uncomment the following: |
- // DCHECK(task_runner_->BelongsToCurrentThread()); |
+ // DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
if (!params.IsValid()) { |
DLOG(ERROR) << "Audio parameters are invalid"; |
@@ -195,7 +181,7 @@ AudioInputStream* AudioManagerBase::MakeAudioInputStream( |
const std::string& device_id) { |
// TODO(miu): Fix ~20 call points across several unit test modules to call |
// this method on the audio thread, then uncomment the following: |
- // DCHECK(task_runner_->BelongsToCurrentThread()); |
+ // DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
if (!params.IsValid() || (params.channels() > kMaxInputChannels) || |
device_id.empty()) { |
@@ -239,7 +225,7 @@ AudioInputStream* AudioManagerBase::MakeAudioInputStream( |
AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy( |
const AudioParameters& params, |
const std::string& device_id) { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
// If the caller supplied an empty device id to select the default device, |
// we fetch the actual device id of the default device so that the lookup |
@@ -337,19 +323,22 @@ void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) { |
void AudioManagerBase::Shutdown() { |
// Only true when we're sharing the UI message loop with the browser. The UI |
// loop is no longer running at this time and browser destruction is imminent. |
- if (task_runner_->BelongsToCurrentThread()) { |
+ auto task_runner = GetTaskRunner(); |
+ if (task_runner->BelongsToCurrentThread()) { |
ShutdownOnAudioThread(); |
} else { |
- task_runner_->PostTask(FROM_HERE, base::Bind( |
- &AudioManagerBase::ShutdownOnAudioThread, base::Unretained(this))); |
+ task_runner->PostTask(FROM_HERE, |
+ base::Bind(&AudioManagerBase::ShutdownOnAudioThread, |
+ base::Unretained(this))); |
} |
- // Stop() will wait for any posted messages to be processed first. |
- audio_thread_.Stop(); |
+ // Destryoing the audio thread will stop it if necessary, which in turn |
+ // will wait for any posted messages to be processed first. |
+ audio_thread_.reset(); |
} |
void AudioManagerBase::ShutdownOnAudioThread() { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
while (!output_dispatchers_.empty()) { |
output_dispatchers_.back()->dispatcher->Shutdown(); |
output_dispatchers_.pop_back(); |
@@ -358,18 +347,18 @@ void AudioManagerBase::ShutdownOnAudioThread() { |
void AudioManagerBase::AddOutputDeviceChangeListener( |
AudioDeviceListener* listener) { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
output_listeners_.AddObserver(listener); |
} |
void AudioManagerBase::RemoveOutputDeviceChangeListener( |
AudioDeviceListener* listener) { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
output_listeners_.RemoveObserver(listener); |
} |
void AudioManagerBase::NotifyAllOutputDeviceChangeListeners() { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
DVLOG(1) << "Firing OnDeviceChange() notifications."; |
FOR_EACH_OBSERVER(AudioDeviceListener, output_listeners_, OnDeviceChange()); |
} |