summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authoralokp <alokp@chromium.org>2016-03-15 12:34:18 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-15 19:35:46 +0000
commitf4945022d19aaa9a0c70346398f1b2b9e4d64899 (patch)
tree445ad5112787147f8069f88edb43d3fc51e552f1 /media
parentfde6c7118d13dbe3e219de55838b514187fffea9 (diff)
downloadchromium_src-f4945022d19aaa9a0c70346398f1b2b9e4d64899.zip
chromium_src-f4945022d19aaa9a0c70346398f1b2b9e4d64899.tar.gz
chromium_src-f4945022d19aaa9a0c70346398f1b2b9e4d64899.tar.bz2
AudioManagerBase: Create and run the audio thread lazily.
This allows AudioManagerBase subclasses not have to create an unnecessary thread if they want to use a different audio task runner. BUG=594234 Review URL: https://codereview.chromium.org/1780333007 Cr-Commit-Position: refs/heads/master@{#381282}
Diffstat (limited to 'media')
-rw-r--r--media/audio/alsa/alsa_output_unittest.cc2
-rw-r--r--media/audio/audio_low_latency_input_output_unittest.cc2
-rw-r--r--media/audio/audio_manager.h2
-rw-r--r--media/audio/audio_manager_base.cc63
-rw-r--r--media/audio/audio_manager_base.h9
-rw-r--r--media/audio/audio_output_proxy_unittest.cc3
-rw-r--r--media/audio/mac/audio_manager_mac.cc54
-rw-r--r--media/audio/mac/audio_manager_mac.h5
-rw-r--r--media/audio/mock_audio_manager.cc3
-rw-r--r--media/audio/mock_audio_manager.h2
10 files changed, 80 insertions, 65 deletions
diff --git a/media/audio/alsa/alsa_output_unittest.cc b/media/audio/alsa/alsa_output_unittest.cc
index 908da6b..1b13863 100644
--- a/media/audio/alsa/alsa_output_unittest.cc
+++ b/media/audio/alsa/alsa_output_unittest.cc
@@ -95,7 +95,7 @@ class MockAudioManagerAlsa : public AudioManagerAlsa {
// We don't mock this method since all tests will do the same thing
// and use the current task runner.
- scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() const override {
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override {
return base::MessageLoop::current()->task_runner();
}
diff --git a/media/audio/audio_low_latency_input_output_unittest.cc b/media/audio/audio_low_latency_input_output_unittest.cc
index 9d5f5b1..010b349 100644
--- a/media/audio/audio_low_latency_input_output_unittest.cc
+++ b/media/audio/audio_low_latency_input_output_unittest.cc
@@ -99,7 +99,7 @@ class MockAudioManager : public AudioManagerAnyPlatform {
MockAudioManager() : AudioManagerAnyPlatform(&fake_audio_log_factory_) {}
~MockAudioManager() override {}
- scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() const override {
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override {
return base::MessageLoop::current()->task_runner();
}
diff --git a/media/audio/audio_manager.h b/media/audio/audio_manager.h
index c5b7f194..d3eea4a 100644
--- a/media/audio/audio_manager.h
+++ b/media/audio/audio_manager.h
@@ -178,7 +178,7 @@ class MEDIA_EXPORT AudioManager {
const std::string& device_id) = 0;
// Returns the task runner used for audio IO.
- virtual scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() const = 0;
+ virtual scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() = 0;
// Heavyweight tasks should use GetWorkerTaskRunner() instead of
// GetTaskRunner(). On most platforms they are the same, but some share the
diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc
index 4f7e676..9e88442 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,24 @@ 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();
+ if (audio_thread_) {
+ audio_thread_->Stop();
+ 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 +349,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());
}
diff --git a/media/audio/audio_manager_base.h b/media/audio/audio_manager_base.h
index bcb6fe3..2a92690 100644
--- a/media/audio/audio_manager_base.h
+++ b/media/audio/audio_manager_base.h
@@ -52,7 +52,7 @@ class MEDIA_EXPORT AudioManagerBase : public AudioManager {
~AudioManagerBase() override;
// AudioManager:
- scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() const override;
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> GetWorkerTaskRunner() override;
base::string16 GetAudioInputDeviceModel() override;
void ShowAudioInputSettings() override;
@@ -171,12 +171,7 @@ class MEDIA_EXPORT AudioManagerBase : public AudioManager {
base::ObserverList<AudioDeviceListener> output_listeners_;
// Thread used to interact with audio streams created by this audio manager.
- base::Thread audio_thread_;
-
- // The task runner of the audio thread this object runs on. Used for internal
- // tasks which run on the audio thread even after Shutdown() has been started
- // and GetTaskRunner() starts returning NULL.
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ scoped_ptr<base::Thread> audio_thread_;
// Map of cached AudioOutputDispatcher instances. Must only be touched
// from the audio thread (no locking).
diff --git a/media/audio/audio_output_proxy_unittest.cc b/media/audio/audio_output_proxy_unittest.cc
index 019e7b7..f037461 100644
--- a/media/audio/audio_output_proxy_unittest.cc
+++ b/media/audio/audio_output_proxy_unittest.cc
@@ -104,8 +104,7 @@ class MockAudioManager : public AudioManagerBase {
MOCK_METHOD2(MakeAudioInputStream, AudioInputStream*(
const AudioParameters& params, const std::string& device_id));
MOCK_METHOD0(ShowAudioInputSettings, void());
- MOCK_CONST_METHOD0(GetTaskRunner,
- scoped_refptr<base::SingleThreadTaskRunner>());
+ MOCK_METHOD0(GetTaskRunner, scoped_refptr<base::SingleThreadTaskRunner>());
MOCK_METHOD0(GetWorkerTaskRunner,
scoped_refptr<base::SingleThreadTaskRunner>());
MOCK_METHOD1(GetAudioInputDeviceNames, void(
diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc
index 6eefcf4..78bdb9f 100644
--- a/media/audio/mac/audio_manager_mac.cc
+++ b/media/audio/mac/audio_manager_mac.cc
@@ -370,26 +370,49 @@ AudioManagerMac::AudioManagerMac(AudioLogFactory* audio_log_factory)
current_output_device_(kAudioDeviceUnknown) {
SetMaxOutputStreamsAllowed(kMaxOutputStreams);
+ // 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.
+ task_runner_ = base::MessageLoopForUI::IsCurrent()
+ ? base::ThreadTaskRunnerHandle::Get()
+ : AudioManagerBase::GetTaskRunner();
+
// Task must be posted last to avoid races from handing out "this" to the
// audio thread. Always PostTask even if we're on the right thread since
// AudioManager creation is on the startup path and this may be slow.
- GetTaskRunner()->PostTask(FROM_HERE, base::Bind(
- &AudioManagerMac::InitializeOnAudioThread, base::Unretained(this)));
+ task_runner_->PostTask(FROM_HERE,
+ base::Bind(&AudioManagerMac::InitializeOnAudioThread,
+ base::Unretained(this)));
}
AudioManagerMac::~AudioManagerMac() {
- if (GetTaskRunner()->BelongsToCurrentThread()) {
+ if (task_runner_->BelongsToCurrentThread()) {
ShutdownOnAudioThread();
} else {
// It's safe to post a task here since Shutdown() will wait for all tasks to
// complete before returning.
- GetTaskRunner()->PostTask(FROM_HERE, base::Bind(
- &AudioManagerMac::ShutdownOnAudioThread, base::Unretained(this)));
+ task_runner_->PostTask(FROM_HERE,
+ base::Bind(&AudioManagerMac::ShutdownOnAudioThread,
+ base::Unretained(this)));
}
Shutdown();
}
+scoped_refptr<base::SingleThreadTaskRunner> AudioManagerMac::GetTaskRunner() {
+ return task_runner_;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+AudioManagerMac::GetWorkerTaskRunner() {
+ if (!worker_thread_) {
+ worker_thread_.reset(new base::Thread("AudioWorkerThread"));
+ CHECK(worker_thread_->Start());
+ }
+ return worker_thread_->task_runner();
+}
+
bool AudioManagerMac::HasAudioOutputDevices() {
return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice);
}
@@ -398,6 +421,7 @@ bool AudioManagerMac::HasAudioInputDevices() {
return HasAudioHardware(kAudioHardwarePropertyDefaultInputDevice);
}
+// static
bool AudioManagerMac::GetDeviceChannels(AudioDeviceID device,
AudioObjectPropertyScope scope,
int* channels) {
@@ -441,6 +465,7 @@ bool AudioManagerMac::GetDeviceChannels(AudioDeviceID device,
return true;
}
+// static
int AudioManagerMac::HardwareSampleRateForDevice(AudioDeviceID device_id) {
DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
Float64 nominal_sample_rate;
@@ -466,6 +491,7 @@ int AudioManagerMac::HardwareSampleRateForDevice(AudioDeviceID device_id) {
return static_cast<int>(nominal_sample_rate);
}
+// static
int AudioManagerMac::HardwareSampleRate() {
// Determine the default output device's sample-rate.
AudioDeviceID device_id = kAudioObjectUnknown;
@@ -524,7 +550,7 @@ AudioParameters AudioManagerMac::GetInputStreamParameters(
std::string AudioManagerMac::GetAssociatedOutputDeviceID(
const std::string& input_device_id) {
- DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+ DCHECK(task_runner_->BelongsToCurrentThread());
AudioDeviceID device = GetAudioDeviceIdByUId(true, input_device_id);
if (device == kAudioObjectUnknown)
return std::string();
@@ -649,7 +675,7 @@ AudioOutputStream* AudioManagerMac::MakeLowLatencyOutputStream(
}
std::string AudioManagerMac::GetDefaultOutputDeviceID() {
- DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+ DCHECK(task_runner_->BelongsToCurrentThread());
AudioDeviceID device_id = kAudioObjectUnknown;
if (!GetDefaultOutputDevice(&device_id))
return std::string();
@@ -748,12 +774,12 @@ AudioParameters AudioManagerMac::GetPreferredOutputStreamParameters(
}
void AudioManagerMac::InitializeOnAudioThread() {
- DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+ DCHECK(task_runner_->BelongsToCurrentThread());
power_observer_.reset(new AudioPowerObserver());
}
void AudioManagerMac::ShutdownOnAudioThread() {
- DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+ DCHECK(task_runner_->BelongsToCurrentThread());
output_device_listener_.reset();
power_observer_.reset();
@@ -772,7 +798,7 @@ void AudioManagerMac::ShutdownOnAudioThread() {
}
void AudioManagerMac::HandleDeviceChanges() {
- DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+ DCHECK(task_runner_->BelongsToCurrentThread());
const int new_sample_rate = HardwareSampleRate();
AudioDeviceID new_output_device;
GetDefaultOutputDevice(&new_output_device);
@@ -814,17 +840,17 @@ int AudioManagerMac::ChooseBufferSize(bool is_input, int sample_rate) {
}
bool AudioManagerMac::ShouldDeferStreamStart() const {
- DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+ DCHECK(task_runner_->BelongsToCurrentThread());
return power_observer_->ShouldDeferStreamStart();
}
bool AudioManagerMac::IsOnBatteryPower() const {
- DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+ DCHECK(task_runner_->BelongsToCurrentThread());
return power_observer_->IsOnBatteryPower();
}
size_t AudioManagerMac::GetNumberOfResumeNotifications() const {
- DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+ DCHECK(task_runner_->BelongsToCurrentThread());
return power_observer_->num_resume_notifications();
}
@@ -834,7 +860,7 @@ bool AudioManagerMac::MaybeChangeBufferSize(AudioDeviceID device_id,
size_t desired_buffer_size,
bool* size_was_changed,
size_t* io_buffer_frame_size) {
- DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+ DCHECK(task_runner_->BelongsToCurrentThread());
const bool is_input = (element == 1);
DVLOG(1) << "MaybeChangeBufferSize(id=0x" << std::hex << device_id
<< ", is_input=" << is_input << ", desired_buffer_size=" << std::dec
diff --git a/media/audio/mac/audio_manager_mac.h b/media/audio/mac/audio_manager_mac.h
index 2112a88..0545f43 100644
--- a/media/audio/mac/audio_manager_mac.h
+++ b/media/audio/mac/audio_manager_mac.h
@@ -29,6 +29,8 @@ class MEDIA_EXPORT AudioManagerMac : public AudioManagerBase {
AudioManagerMac(AudioLogFactory* audio_log_factory);
// Implementation of AudioManager.
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override;
+ scoped_refptr<base::SingleThreadTaskRunner> GetWorkerTaskRunner() override;
bool HasAudioOutputDevices() override;
bool HasAudioInputDevices() override;
void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override;
@@ -122,6 +124,9 @@ class MEDIA_EXPORT AudioManagerMac : public AudioManagerBase {
scoped_ptr<AudioDeviceListenerMac> output_device_listener_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ scoped_ptr<base::Thread> worker_thread_;
+
// Track the output sample-rate and the default output device
// so we can intelligently handle device notifications only when necessary.
int current_sample_rate_;
diff --git a/media/audio/mock_audio_manager.cc b/media/audio/mock_audio_manager.cc
index e8aacbe..7183405 100644
--- a/media/audio/mock_audio_manager.cc
+++ b/media/audio/mock_audio_manager.cc
@@ -63,8 +63,7 @@ media::AudioInputStream* MockAudioManager::MakeAudioInputStream(
return NULL;
}
-scoped_refptr<base::SingleThreadTaskRunner> MockAudioManager::GetTaskRunner()
- const {
+scoped_refptr<base::SingleThreadTaskRunner> MockAudioManager::GetTaskRunner() {
return task_runner_;
}
diff --git a/media/audio/mock_audio_manager.h b/media/audio/mock_audio_manager.h
index 536ff6a..60a8b1e 100644
--- a/media/audio/mock_audio_manager.h
+++ b/media/audio/mock_audio_manager.h
@@ -50,7 +50,7 @@ class MockAudioManager : public media::AudioManager {
const media::AudioParameters& params,
const std::string& device_id) override;
- scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() const override;
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> GetWorkerTaskRunner() override;
void AddOutputDeviceChangeListener(AudioDeviceListener* listener) override;