summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-24 23:32:33 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-24 23:32:33 +0000
commitc54fa28a44dad9ccf4c5b03b0a791f69540c16a4 (patch)
tree3008a22b3fb86afa547c589b274b306a99b1695d /media
parent53a4597d56e4ca47d70a0f72901d005f0019aca3 (diff)
downloadchromium_src-c54fa28a44dad9ccf4c5b03b0a791f69540c16a4.zip
chromium_src-c54fa28a44dad9ccf4c5b03b0a791f69540c16a4.tar.gz
chromium_src-c54fa28a44dad9ccf4c5b03b0a791f69540c16a4.tar.bz2
Revert 57254 - Share one thread between all AudioOutputControllers instead of creating one per stream.
TEST=unittests BUG=39825 Review URL: http://codereview.chromium.org/3185022 TBR=sergeyu@chromium.org Review URL: http://codereview.chromium.org/3192017 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@57256 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/audio/audio_input_controller.h1
-rw-r--r--media/audio/audio_io.h76
-rw-r--r--media/audio/audio_manager.cc59
-rw-r--r--media/audio/audio_manager.h101
-rw-r--r--media/audio/audio_manager_base.cc19
-rw-r--r--media/audio/audio_manager_base.h35
-rw-r--r--media/audio/audio_output_controller.cc108
-rw-r--r--media/audio/audio_output_controller.h14
-rw-r--r--media/audio/audio_output_controller_unittest.cc43
-rw-r--r--media/audio/fake_audio_input_stream_unittest.cc2
-rw-r--r--media/audio/linux/alsa_output.cc16
-rw-r--r--media/audio/linux/alsa_output.h2
-rw-r--r--media/audio/linux/audio_manager_linux.cc33
-rw-r--r--media/audio/linux/audio_manager_linux.h9
-rw-r--r--media/audio/mac/audio_manager_mac.cc22
-rw-r--r--media/audio/mac/audio_manager_mac.h4
-rw-r--r--media/audio/openbsd/audio_manager_openbsd.cc7
-rw-r--r--media/audio/openbsd/audio_manager_openbsd.h2
-rw-r--r--media/audio/simple_sources_unittest.cc1
-rw-r--r--media/audio/win/audio_manager_win.cc17
-rw-r--r--media/audio/win/audio_manager_win.h4
-rw-r--r--media/filters/audio_renderer_impl.cc1
-rw-r--r--media/media.gyp4
23 files changed, 228 insertions, 352 deletions
diff --git a/media/audio/audio_input_controller.h b/media/audio/audio_input_controller.h
index deded58..a00e2bc 100644
--- a/media/audio/audio_input_controller.h
+++ b/media/audio/audio_input_controller.h
@@ -10,7 +10,6 @@
#include "base/scoped_ptr.h"
#include "base/thread.h"
#include "media/audio/audio_io.h"
-#include "media/audio/audio_manager.h"
// An AudioInputController controls an AudioInputStream and records data
// from this input stream. It has an important function that it executes
diff --git a/media/audio/audio_io.h b/media/audio/audio_io.h
index 4f23686..6e1e289 100644
--- a/media/audio/audio_io.h
+++ b/media/audio/audio_io.h
@@ -153,4 +153,80 @@ class AudioInputStream {
virtual ~AudioInputStream() {}
};
+// Manages all audio resources. In particular it owns the AudioOutputStream
+// objects. Provides some convenience functions that avoid the need to provide
+// iterators over the existing streams.
+class AudioManager {
+ public:
+ enum Format {
+ AUDIO_PCM_LINEAR = 0, // PCM is 'raw' amplitude samples.
+ AUDIO_PCM_LOW_LATENCY, // Linear PCM, low latency requested.
+ AUDIO_MOCK, // Creates a dummy AudioOutputStream object.
+ AUDIO_LAST_FORMAT // Only used for validation of format.
+ };
+
+ // Telephone quality sample rate, mostly for speech-only audio.
+ static const uint32 kTelephoneSampleRate = 8000;
+ // CD sampling rate is 44.1 KHz or conveniently 2x2x3x3x5x5x7x7.
+ static const uint32 kAudioCDSampleRate = 44100;
+ // Digital Audio Tape sample rate.
+ static const uint32 kAudioDATSampleRate = 48000;
+
+ // Returns true if the OS reports existence of audio devices. This does not
+ // guarantee that the existing devices support all formats and sample rates.
+ virtual bool HasAudioOutputDevices() = 0;
+
+ // Returns true if the OS reports existence of audio recording devices. This
+ // does not guarantee that the existing devices support all formats and
+ // sample rates.
+ virtual bool HasAudioInputDevices() = 0;
+
+ // Factory for all the supported stream formats. The |channels| can be 1 to 5.
+ // The |sample_rate| is in hertz and can be any value supported by the
+ // platform. For some future formats the |sample_rate| and |bits_per_sample|
+ // can take special values.
+ // Returns NULL if the combination of the parameters is not supported, or if
+ // we have reached some other platform specific limit.
+ //
+ // AUDIO_PCM_LOW_LATENCY can be passed to this method and it has two effects:
+ // 1- Instead of triple buffered the audio will be double buffered.
+ // 2- A low latency driver or alternative audio subsystem will be used when
+ // available.
+ //
+ // Do not free the returned AudioOutputStream. It is owned by AudioManager.
+ virtual AudioOutputStream* MakeAudioOutputStream(Format format, int channels,
+ int sample_rate,
+ char bits_per_sample) = 0;
+
+ // Factory to create audio recording streams.
+ // |channels| can be 1 or 2.
+ // |sample_rate| is in hertz and can be any value supported by the platform.
+ // |bits_per_sample| can be any value supported by the platform.
+ // |samples_per_packet| is in hertz as well and can be 0 to |sample_rate|,
+ // with 0 suggesting that the implementation use a default value for that
+ // platform.
+ // Returns NULL if the combination of the parameters is not supported, or if
+ // we have reached some other platform specific limit.
+ //
+ // Do not free the returned AudioInputStream. It is owned by AudioManager.
+ // When you are done with it, call |Stop()| and |Close()| to release it.
+ virtual AudioInputStream* MakeAudioInputStream(Format format, int channels,
+ int sample_rate,
+ char bits_per_sample,
+ uint32 samples_per_packet) = 0;
+
+ // Muting continues playback but effectively the volume is set to zero.
+ // Un-muting returns the volume to the previous level.
+ virtual void MuteAll() = 0;
+ virtual void UnMuteAll() = 0;
+
+ // Get AudioManager singleton.
+ // TODO(cpu): Define threading requirements for interacting with AudioManager.
+ static AudioManager* GetAudioManager();
+
+ protected:
+ virtual ~AudioManager() {}
+};
+
+
#endif // MEDIA_AUDIO_AUDIO_IO_H_
diff --git a/media/audio/audio_manager.cc b/media/audio/audio_manager.cc
deleted file mode 100644
index 7148d21..0000000
--- a/media/audio/audio_manager.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/audio/audio_manager.h"
-
-#include "base/at_exit.h"
-#include "base/logging.h"
-
-namespace {
-
-AudioManager* g_audio_manager = NULL;
-
-// NullAudioManager is the audio manager used on the systems that have no
-// audio support.
-class NullAudioManager : public AudioManager {
- public:
- NullAudioManager() { }
-
- // Implementation of AudioManager.
- virtual bool HasAudioOutputDevices() { return false; }
- virtual bool HasAudioInputDevices() { return false; }
- virtual AudioOutputStream* MakeAudioOutputStream(Format format, int channels,
- int sample_rate,
- char bits_per_sample) {
- NOTIMPLEMENTED();
- return NULL;
- }
- virtual AudioInputStream* MakeAudioInputStream(Format format, int channels,
- int sample_rate,
- char bits_per_sample,
- uint32 samples_per_packet) {
- NOTIMPLEMENTED();
- return NULL;
- }
- virtual void MuteAll() { NOTIMPLEMENTED(); }
- virtual void UnMuteAll() { NOTIMPLEMENTED(); }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(NullAudioManager);
-};
-
-} // namespace
-
-// static
-void AudioManager::Destroy(void* not_used) {
- delete g_audio_manager;
- g_audio_manager = NULL;
-}
-
-// static
-AudioManager* AudioManager::GetAudioManager() {
- if (!g_audio_manager) {
- g_audio_manager = CreateAudioManager();
- g_audio_manager->Init();
- base::AtExitManager::RegisterCallback(&AudioManager::Destroy, NULL);
- }
- return g_audio_manager;
-}
diff --git a/media/audio/audio_manager.h b/media/audio/audio_manager.h
deleted file mode 100644
index 2185950..0000000
--- a/media/audio/audio_manager.h
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MEDIA_AUDIO_AUDIO_MANAGER_H_
-#define MEDIA_AUDIO_AUDIO_MANAGER_H_
-
-#include "base/basictypes.h"
-
-class AudioInputStream;
-class AudioOutputStream;
-class MessageLoop;
-
-// Manages all audio resources. In particular it owns the AudioOutputStream
-// objects. Provides some convenience functions that avoid the need to provide
-// iterators over the existing streams.
-class AudioManager {
- public:
- enum Format {
- AUDIO_PCM_LINEAR = 0, // PCM is 'raw' amplitude samples.
- AUDIO_PCM_LOW_LATENCY, // Linear PCM, low latency requested.
- AUDIO_MOCK, // Creates a dummy AudioOutputStream object.
- AUDIO_LAST_FORMAT // Only used for validation of format.
- };
-
- // Telephone quality sample rate, mostly for speech-only audio.
- static const uint32 kTelephoneSampleRate = 8000;
- // CD sampling rate is 44.1 KHz or conveniently 2x2x3x3x5x5x7x7.
- static const uint32 kAudioCDSampleRate = 44100;
- // Digital Audio Tape sample rate.
- static const uint32 kAudioDATSampleRate = 48000;
-
- // Returns true if the OS reports existence of audio devices. This does not
- // guarantee that the existing devices support all formats and sample rates.
- virtual bool HasAudioOutputDevices() = 0;
-
- // Returns true if the OS reports existence of audio recording devices. This
- // does not guarantee that the existing devices support all formats and
- // sample rates.
- virtual bool HasAudioInputDevices() = 0;
-
- // Factory for all the supported stream formats. The |channels| can be 1 to 5.
- // The |sample_rate| is in hertz and can be any value supported by the
- // platform. For some future formats the |sample_rate| and |bits_per_sample|
- // can take special values.
- // Returns NULL if the combination of the parameters is not supported, or if
- // we have reached some other platform specific limit.
- //
- // AUDIO_PCM_LOW_LATENCY can be passed to this method and it has two effects:
- // 1- Instead of triple buffered the audio will be double buffered.
- // 2- A low latency driver or alternative audio subsystem will be used when
- // available.
- //
- // Do not free the returned AudioOutputStream. It is owned by AudioManager.
- virtual AudioOutputStream* MakeAudioOutputStream(Format format, int channels,
- int sample_rate,
- char bits_per_sample) = 0;
-
- // Factory to create audio recording streams.
- // |channels| can be 1 or 2.
- // |sample_rate| is in hertz and can be any value supported by the platform.
- // |bits_per_sample| can be any value supported by the platform.
- // |samples_per_packet| is in hertz as well and can be 0 to |sample_rate|,
- // with 0 suggesting that the implementation use a default value for that
- // platform.
- // Returns NULL if the combination of the parameters is not supported, or if
- // we have reached some other platform specific limit.
- //
- // Do not free the returned AudioInputStream. It is owned by AudioManager.
- // When you are done with it, call |Stop()| and |Close()| to release it.
- virtual AudioInputStream* MakeAudioInputStream(Format format, int channels,
- int sample_rate,
- char bits_per_sample,
- uint32 samples_per_packet) = 0;
-
- // Muting continues playback but effectively the volume is set to zero.
- // Un-muting returns the volume to the previous level.
- virtual void MuteAll() = 0;
- virtual void UnMuteAll() = 0;
-
- // Returns message loop used for audio IO.
- virtual MessageLoop* GetMessageLoop() = 0;
-
- // Get AudioManager singleton.
- // TODO(cpu): Define threading requirements for interacting with AudioManager.
- static AudioManager* GetAudioManager();
-
- protected:
- virtual ~AudioManager() {}
-
- // Called from GetAudioManager() to initialiaze the instance.
- virtual void Init() = 0;
-
- private:
- static void Destroy(void*);
-
- // Called by GetAudioManager() to create platform-specific audio manager.
- static AudioManager* CreateAudioManager();
-};
-
-#endif // MEDIA_AUDIO_AUDIO_MANAGER_H_
diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc
deleted file mode 100644
index 7fa4761..0000000
--- a/media/audio/audio_manager_base.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/audio/audio_manager_base.h"
-
-AudioManagerBase::AudioManagerBase()
- : audio_thread_("AudioThread"),
- initialized_(false) {
-}
-
-void AudioManagerBase::Init() {
- initialized_ = audio_thread_.Start();
-}
-
-MessageLoop* AudioManagerBase::GetMessageLoop() {
- DCHECK(initialized_);
- return audio_thread_.message_loop();
-}
diff --git a/media/audio/audio_manager_base.h b/media/audio/audio_manager_base.h
deleted file mode 100644
index ed8ab0e..0000000
--- a/media/audio/audio_manager_base.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MEDIA_AUDIO_AUDIO_MANAGER_BASE_H_
-#define MEDIA_AUDIO_AUDIO_MANAGER_BASE_H_
-
-#include "base/thread.h"
-#include "media/audio/audio_manager.h"
-
-// AudioManagerBase provides AudioManager functions common for all platforms.
-class AudioManagerBase : public AudioManager {
- public:
- AudioManagerBase();
-
- virtual void Init();
-
- virtual MessageLoop* GetMessageLoop();
-
- protected:
- virtual ~AudioManagerBase() {}
-
- bool initialized() { return initialized_; }
-
- protected:
- // Thread used to interact with AudioOutputStreams created by this
- // audio manger.
- base::Thread audio_thread_;
-
- bool initialized_;
-
- DISALLOW_COPY_AND_ASSIGN(AudioManagerBase);
-};
-
-#endif // MEDIA_AUDIO_AUDIO_MANAGER_BASE_H_
diff --git a/media/audio/audio_output_controller.cc b/media/audio/audio_output_controller.cc
index 27938f9..74e2261 100644
--- a/media/audio/audio_output_controller.cc
+++ b/media/audio/audio_output_controller.cc
@@ -4,8 +4,6 @@
#include "media/audio/audio_output_controller.h"
-#include "base/message_loop.h"
-
// The following parameters limit the request buffer and packet size from the
// renderer to avoid renderer from requesting too much memory.
static const uint32 kMegabytes = 1024 * 1024;
@@ -37,12 +35,12 @@ AudioOutputController::AudioOutputController(EventHandler* handler,
uint32 capacity,
SyncReader* sync_reader)
: handler_(handler),
- stream_(NULL),
volume_(1.0),
state_(kEmpty),
hardware_pending_bytes_(0),
buffer_capacity_(capacity),
- sync_reader_(sync_reader) {
+ sync_reader_(sync_reader),
+ thread_("AudioOutputControllerThread") {
}
AudioOutputController::~AudioOutputController() {
@@ -67,9 +65,10 @@ scoped_refptr<AudioOutputController> AudioOutputController::Create(
scoped_refptr<AudioOutputController> controller = new AudioOutputController(
event_handler, buffer_capacity, NULL);
- controller->message_loop_ =
- AudioManager::GetAudioManager()->GetMessageLoop();
- controller->message_loop_->PostTask(
+ // Start the audio controller thread and post a task to create the
+ // audio stream.
+ controller->thread_.Start();
+ controller->thread_.message_loop()->PostTask(
FROM_HERE,
NewRunnableMethod(controller.get(), &AudioOutputController::DoCreate,
format, channels, sample_rate, bits_per_sample,
@@ -97,9 +96,10 @@ scoped_refptr<AudioOutputController> AudioOutputController::CreateLowLatency(
scoped_refptr<AudioOutputController> controller = new AudioOutputController(
event_handler, 0, sync_reader);
- controller->message_loop_ =
- AudioManager::GetAudioManager()->GetMessageLoop();
- controller->message_loop_->PostTask(
+ // Start the audio controller thread and post a task to create the
+ // audio stream.
+ controller->thread_.Start();
+ controller->thread_.message_loop()->PostTask(
FROM_HERE,
NewRunnableMethod(controller.get(), &AudioOutputController::DoCreate,
format, channels, sample_rate, bits_per_sample,
@@ -108,43 +108,43 @@ scoped_refptr<AudioOutputController> AudioOutputController::CreateLowLatency(
}
void AudioOutputController::Play() {
- DCHECK(message_loop_);
- message_loop_->PostTask(
+ DCHECK(thread_.IsRunning());
+ thread_.message_loop()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &AudioOutputController::DoPlay));
}
void AudioOutputController::Pause() {
- DCHECK(message_loop_);
- message_loop_->PostTask(
+ DCHECK(thread_.IsRunning());
+ thread_.message_loop()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &AudioOutputController::DoPause));
}
void AudioOutputController::Flush() {
- DCHECK(message_loop_);
- message_loop_->PostTask(
+ DCHECK(thread_.IsRunning());
+ thread_.message_loop()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &AudioOutputController::DoFlush));
}
void AudioOutputController::Close() {
- {
- AutoLock auto_lock(lock_);
- // Don't do anything if the stream is already closed.
- if (state_ == kClosed)
- return;
- state_ = kClosed;
+ if (!thread_.IsRunning()) {
+ // If the thread is not running make sure we are stopped.
+ DCHECK_EQ(kClosed, state_);
+ return;
}
- message_loop_->PostTask(
+ // Wait for all tasks to complete on the audio thread.
+ thread_.message_loop()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &AudioOutputController::DoClose));
+ thread_.Stop();
}
void AudioOutputController::SetVolume(double volume) {
- DCHECK(message_loop_);
- message_loop_->PostTask(
+ DCHECK(thread_.IsRunning());
+ thread_.message_loop()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &AudioOutputController::DoSetVolume, volume));
}
@@ -159,14 +159,8 @@ void AudioOutputController::EnqueueData(const uint8* data, uint32 size) {
void AudioOutputController::DoCreate(AudioManager::Format format, int channels,
int sample_rate, int bits_per_sample,
uint32 hardware_buffer_size) {
- DCHECK_EQ(message_loop_, MessageLoop::current());
-
- AutoLock auto_lock(lock_);
-
- // Close() can be called before DoCreate() is executed.
- if (state_ == kClosed)
- return;
- DCHECK(state_ == kEmpty);
+ DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
+ DCHECK_EQ(kEmpty, state_);
// Create the stream in the first place.
stream_ = AudioManager::GetAudioManager()->MakeAudioOutputStream(
@@ -197,20 +191,22 @@ void AudioOutputController::DoCreate(AudioManager::Format format, int channels,
// If in normal latency mode then start buffering.
if (!LowLatencyMode()) {
+ AutoLock auto_lock(lock_);
SubmitOnMoreData_Locked();
}
}
void AudioOutputController::DoPlay() {
- DCHECK_EQ(message_loop_, MessageLoop::current());
+ DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
+
+ // We can start from created or paused state.
+ if (state_ != kCreated && state_ != kPaused)
+ return;
State old_state;
// Update the |state_| to kPlaying.
{
AutoLock auto_lock(lock_);
- // We can start from created or paused state.
- if (state_ != kCreated && state_ != kPaused)
- return;
old_state = state_;
state_ = kPlaying;
}
@@ -223,14 +219,15 @@ void AudioOutputController::DoPlay() {
}
void AudioOutputController::DoPause() {
- DCHECK_EQ(message_loop_, MessageLoop::current());
+ DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
+
+ // We can pause from started state.
+ if (state_ != kPlaying)
+ return;
// Sets the |state_| to kPaused so we don't draw more audio data.
{
AutoLock auto_lock(lock_);
- // We can pause from started state.
- if (state_ != kPlaying)
- return;
state_ = kPaused;
}
@@ -243,22 +240,24 @@ void AudioOutputController::DoPause() {
}
void AudioOutputController::DoFlush() {
- DCHECK_EQ(message_loop_, MessageLoop::current());
+ DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
+
+ if (state_ != kPaused)
+ return;
// TODO(hclam): Actually flush the audio device.
// If we are in the regular latency mode then flush the push source.
if (!sync_reader_) {
AutoLock auto_lock(lock_);
- if (state_ != kPaused)
- return;
push_source_.ClearAll();
}
}
void AudioOutputController::DoClose() {
- DCHECK_EQ(message_loop_, MessageLoop::current());
- DCHECK_EQ(kClosed, state_);
+ DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
+ DCHECK_NE(kClosed, state_);
+
// |stream_| can be null if creating the device failed in DoCreate().
if (stream_) {
stream_->Stop();
@@ -266,26 +265,27 @@ void AudioOutputController::DoClose() {
// After stream is closed it is destroyed, so don't keep a reference to it.
stream_ = NULL;
}
+
+ // Update the current state. Since the stream is closed at this point
+ // there's no other threads reading |state_| so we don't need to lock.
+ state_ = kClosed;
}
void AudioOutputController::DoSetVolume(double volume) {
- DCHECK_EQ(message_loop_, MessageLoop::current());
+ DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
// Saves the volume to a member first. We may not be able to set the volume
// right away but when the stream is created we'll set the volume.
volume_ = volume;
- {
- AutoLock auto_lock(lock_);
- if (state_ != kPlaying && state_ != kPaused && state_ != kCreated)
- return;
- }
+ if (state_ != kPlaying && state_ != kPaused && state_ != kCreated)
+ return;
stream_->SetVolume(volume_);
}
void AudioOutputController::DoReportError(int code) {
- DCHECK_EQ(message_loop_, MessageLoop::current());
+ DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
handler_->OnError(this, code);
}
@@ -332,7 +332,7 @@ void AudioOutputController::OnClose(AudioOutputStream* stream) {
void AudioOutputController::OnError(AudioOutputStream* stream, int code) {
// Handle error on the audio controller thread.
- message_loop_->PostTask(
+ thread_.message_loop()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &AudioOutputController::DoReportError, code));
}
diff --git a/media/audio/audio_output_controller.h b/media/audio/audio_output_controller.h
index 4600067..10e3d03 100644
--- a/media/audio/audio_output_controller.h
+++ b/media/audio/audio_output_controller.h
@@ -8,13 +8,11 @@
#include "base/lock.h"
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
+#include "base/thread.h"
#include "base/time.h"
#include "media/audio/audio_io.h"
-#include "media/audio/audio_manager.h"
#include "media/audio/simple_sources.h"
-class MessageLoop;
-
// An AudioOutputController controls an AudioOutputStream and provides data
// to this output stream. It has an important function that it executes
// audio operations like play, pause, stop, etc. on a separate thread,
@@ -140,9 +138,9 @@ class AudioOutputController
// has effect when the stream is paused.
void Flush();
- // Closes the audio output stream. It changes state to kClosed and returns
- // right away. The physical resources are freed on the audio thread if
- // neccessary.
+ // Closes the audio output stream and shutdown the audio controller thread.
+ // This method returns only after all operations are completed. This
+ // controller cannot be used after this method is called.
//
// It is safe to call this method more than once. Calls after the first one
// will have no effect.
@@ -205,8 +203,8 @@ class AudioOutputController
// SyncReader is used only in low latency mode for synchronous reading.
SyncReader* sync_reader_;
- // The message loop of audio thread that this object runs on.
- MessageLoop* message_loop_;
+ // The audio controller thread that this object runs on.
+ base::Thread thread_;
DISALLOW_COPY_AND_ASSIGN(AudioOutputController);
};
diff --git a/media/audio/audio_output_controller_unittest.cc b/media/audio/audio_output_controller_unittest.cc
index df96f4a..a68571a 100644
--- a/media/audio/audio_output_controller_unittest.cc
+++ b/media/audio/audio_output_controller_unittest.cc
@@ -14,7 +14,6 @@ using ::testing::AtLeast;
using ::testing::Exactly;
using ::testing::InvokeWithoutArgs;
using ::testing::NotNull;
-using ::testing::Return;
static const int kSampleRate = AudioManager::kAudioCDSampleRate;
static const int kBitsPerSample = 16;
@@ -69,10 +68,6 @@ static bool IsRunningHeadless() {
return false;
}
-ACTION_P(SignalEvent, event) {
- event->Signal();
-}
-
ACTION_P3(SignalEvent, event, count, limit) {
if (++*count >= limit) {
event->Signal();
@@ -91,10 +86,7 @@ TEST(AudioOutputControllerTest, CreateAndClose) {
kHardwareBufferSize, kBufferCapacity);
ASSERT_TRUE(controller.get());
- // Close the controller immediately. At this point, chances are that
- // DoCreate() hasn't been called yet. In any case, it should be safe to call
- // Close() and it should not try to call |event_handler| later (the test
- // would crash otherwise).
+ // Close the controller immediately.
controller->Close();
}
@@ -108,7 +100,7 @@ TEST(AudioOutputControllerTest, PlayAndClose) {
// If OnCreated is called then signal the event.
EXPECT_CALL(event_handler, OnCreated(NotNull()))
- .WillOnce(SignalEvent(&event));
+ .WillOnce(InvokeWithoutArgs(&event, &base::WaitableEvent::Signal));
// OnPlaying() will be called only once.
EXPECT_CALL(event_handler, OnPlaying(NotNull()))
@@ -128,13 +120,14 @@ TEST(AudioOutputControllerTest, PlayAndClose) {
// Wait for OnCreated() to be called.
event.Wait();
+ event.Reset();
// Play and then wait for the event to be signaled.
controller->Play();
event.Wait();
- // Now stop the controller. The object is freed later after DoClose() is
- // executed.
+ // Now stop the controller. This should shutdown the internal
+ // thread and we hold the only reference to it.
controller->Close();
}
@@ -185,8 +178,8 @@ TEST(AudioOutputControllerTest, PlayPauseClose) {
controller->Pause();
event.Wait();
- // Now stop the controller. The object is freed later after DoClose() is
- // executed.
+ // Now stop the controller. This should shutdown the internal
+ // thread and we hold the only reference to it.
controller->Close();
}
@@ -249,8 +242,8 @@ TEST(AudioOutputControllerTest, PlayPausePlay) {
controller->Play();
event.Wait();
- // Now stop the controller. The object is freed later after DoClose() is
- // executed.
+ // Now stop the controller. This should shutdown the internal
+ // thread and we hold the only reference to it.
controller->Close();
}
@@ -277,17 +270,6 @@ TEST(AudioOutputControllerTest, CloseTwice) {
return;
MockAudioOutputControllerEventHandler event_handler;
- base::WaitableEvent event(false, false);
-
- // If OnCreated is called then signal the event.
- EXPECT_CALL(event_handler, OnCreated(NotNull()))
- .WillOnce(SignalEvent(&event));
-
- // One OnMoreData() is expected.
- EXPECT_CALL(event_handler, OnMoreData(NotNull(), _, 0))
- .Times(AtLeast(1))
- .WillRepeatedly(SignalEvent(&event));
-
scoped_refptr<AudioOutputController> controller =
AudioOutputController::Create(&event_handler,
AudioManager::AUDIO_PCM_LINEAR, kChannels,
@@ -295,12 +277,7 @@ TEST(AudioOutputControllerTest, CloseTwice) {
kHardwareBufferSize, kBufferCapacity);
ASSERT_TRUE(controller.get());
- // Wait for OnCreated() to be called.
- event.Wait();
-
- // Wait for OnMoreData() to be called.
- event.Wait();
-
+ // Close the controller immediately.
controller->Close();
controller->Close();
}
diff --git a/media/audio/fake_audio_input_stream_unittest.cc b/media/audio/fake_audio_input_stream_unittest.cc
index 473ed10..16e86a4 100644
--- a/media/audio/fake_audio_input_stream_unittest.cc
+++ b/media/audio/fake_audio_input_stream_unittest.cc
@@ -5,7 +5,6 @@
#include "base/basictypes.h"
#include "base/platform_thread.h"
#include "media/audio/audio_io.h"
-#include "media/audio/audio_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -49,3 +48,4 @@ TEST(FakeAudioInputTest, BasicCallbacks) {
stream->Stop();
stream->Close();
}
+
diff --git a/media/audio/linux/alsa_output.cc b/media/audio/linux/alsa_output.cc
index e8ebc5c..1358dc3 100644
--- a/media/audio/linux/alsa_output.cc
+++ b/media/audio/linux/alsa_output.cc
@@ -376,7 +376,7 @@ void AlsaPcmOutputStream::GetVolume(double* volume) {
}
void AlsaPcmOutputStream::OpenTask(uint32 packet_size) {
- DCHECK_EQ(message_loop_, MessageLoop::current());
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
// Initialize the configuration variables.
packet_size_ = packet_size;
@@ -422,7 +422,7 @@ void AlsaPcmOutputStream::OpenTask(uint32 packet_size) {
}
void AlsaPcmOutputStream::StartTask() {
- DCHECK_EQ(message_loop_, MessageLoop::current());
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
if (stop_stream_) {
return;
@@ -454,7 +454,7 @@ void AlsaPcmOutputStream::StartTask() {
void AlsaPcmOutputStream::CloseTask() {
// NOTE: Keep this function idempotent to handle errors that might cause
// multiple CloseTasks to be posted.
- DCHECK_EQ(message_loop_, MessageLoop::current());
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
// Shutdown the audio device.
if (playback_handle_ && !CloseDevice(playback_handle_)) {
@@ -470,7 +470,7 @@ void AlsaPcmOutputStream::CloseTask() {
}
void AlsaPcmOutputStream::BufferPacket(bool* source_exhausted) {
- DCHECK_EQ(message_loop_, MessageLoop::current());
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
// If stopped, simulate a 0-lengthed packet.
if (stop_stream_) {
@@ -558,7 +558,7 @@ void AlsaPcmOutputStream::BufferPacket(bool* source_exhausted) {
}
void AlsaPcmOutputStream::WritePacket() {
- DCHECK_EQ(message_loop_, MessageLoop::current());
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
// If the device is in error, just eat the bytes.
if (stop_stream_) {
@@ -611,7 +611,7 @@ void AlsaPcmOutputStream::WritePacket() {
}
void AlsaPcmOutputStream::WriteTask() {
- DCHECK_EQ(message_loop_, MessageLoop::current());
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
if (stop_stream_) {
return;
@@ -625,7 +625,7 @@ void AlsaPcmOutputStream::WriteTask() {
}
void AlsaPcmOutputStream::ScheduleNextWrite(bool source_exhausted) {
- DCHECK_EQ(message_loop_, MessageLoop::current());
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
if (stop_stream_) {
return;
@@ -778,7 +778,7 @@ bool AlsaPcmOutputStream::CloseDevice(snd_pcm_t* handle) {
}
snd_pcm_sframes_t AlsaPcmOutputStream::GetAvailableFrames() {
- DCHECK_EQ(message_loop_, MessageLoop::current());
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
if (stop_stream_) {
return 0;
diff --git a/media/audio/linux/alsa_output.h b/media/audio/linux/alsa_output.h
index f98f2c0..0fb5ac5 100644
--- a/media/audio/linux/alsa_output.h
+++ b/media/audio/linux/alsa_output.h
@@ -36,8 +36,8 @@
#include "base/lock.h"
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
+#include "base/thread.h"
#include "media/audio/audio_io.h"
-#include "media/audio/audio_manager_base.h"
namespace media {
class SeekableBuffer;
diff --git a/media/audio/linux/audio_manager_linux.cc b/media/audio/linux/audio_manager_linux.cc
index 713a753..17a1f74 100644
--- a/media/audio/linux/audio_manager_linux.cc
+++ b/media/audio/linux/audio_manager_linux.cc
@@ -4,6 +4,7 @@
#include "media/audio/linux/audio_manager_linux.h"
+#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "media/audio/fake_audio_input_stream.h"
@@ -12,6 +13,12 @@
#include "media/audio/linux/alsa_wrapper.h"
#include "media/base/media_switches.h"
+
+namespace {
+
+AudioManagerLinux* g_audio_manager = NULL;
+} // namespace
+
// Implementation of AudioManager.
bool AudioManagerLinux::HasAudioOutputDevices() {
// TODO(ajwong): Make this actually query audio devices.
@@ -49,7 +56,7 @@ AudioOutputStream* AudioManagerLinux::MakeAudioOutputStream(
return FakeAudioOutputStream::MakeFakeStream();
}
- if (!initialized()) {
+ if (!initialized_) {
return NULL;
}
@@ -61,14 +68,16 @@ AudioOutputStream* AudioManagerLinux::MakeAudioOutputStream(
AlsaPcmOutputStream* stream =
new AlsaPcmOutputStream(device_name, format, channels, sample_rate,
bits_per_sample, wrapper_.get(), this,
- GetMessageLoop());
+ audio_thread_.message_loop());
AutoLock l(lock_);
active_streams_[stream] = scoped_refptr<AlsaPcmOutputStream>(stream);
return stream;
}
-AudioManagerLinux::AudioManagerLinux() {
+AudioManagerLinux::AudioManagerLinux()
+ : audio_thread_("AudioThread"),
+ initialized_(false) {
}
AudioManagerLinux::~AudioManagerLinux() {
@@ -82,7 +91,7 @@ AudioManagerLinux::~AudioManagerLinux() {
}
void AudioManagerLinux::Init() {
- AudioManagerBase::Init();
+ initialized_ = audio_thread_.Start();
wrapper_.reset(new AlsaWrapper());
}
@@ -101,7 +110,17 @@ void AudioManagerLinux::ReleaseOutputStream(AlsaPcmOutputStream* stream) {
}
}
-// static
-AudioManager* AudioManager::CreateAudioManager() {
- return new AudioManagerLinux();
+// TODO(ajwong): Collapse this with the windows version.
+void DestroyAudioManagerLinux(void* not_used) {
+ delete g_audio_manager;
+ g_audio_manager = NULL;
+}
+
+AudioManager* AudioManager::GetAudioManager() {
+ if (!g_audio_manager) {
+ g_audio_manager = new AudioManagerLinux();
+ g_audio_manager->Init();
+ base::AtExitManager::RegisterCallback(&DestroyAudioManagerLinux, NULL);
+ }
+ return g_audio_manager;
}
diff --git a/media/audio/linux/audio_manager_linux.h b/media/audio/linux/audio_manager_linux.h
index 2703eed..ea335f0 100644
--- a/media/audio/linux/audio_manager_linux.h
+++ b/media/audio/linux/audio_manager_linux.h
@@ -11,12 +11,12 @@
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
#include "base/thread.h"
-#include "media/audio/audio_manager_base.h"
+#include "media/audio/audio_io.h"
class AlsaPcmOutputStream;
class AlsaWrapper;
-class AudioManagerLinux : public AudioManagerBase {
+class AudioManagerLinux : public AudioManager {
public:
AudioManagerLinux();
@@ -44,12 +44,17 @@ class AudioManagerLinux : public AudioManagerBase {
virtual ~AudioManagerLinux();
private:
+ // Thread used to interact with AudioOutputStreams created by this
+ // audio manger.
+ base::Thread audio_thread_;
scoped_ptr<AlsaWrapper> wrapper_;
Lock lock_;
std::map<AlsaPcmOutputStream*, scoped_refptr<AlsaPcmOutputStream> >
active_streams_;
+ bool initialized_;
+
DISALLOW_COPY_AND_ASSIGN(AudioManagerLinux);
};
diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc
index 528fd6e..312ecbb 100644
--- a/media/audio/mac/audio_manager_mac.cc
+++ b/media/audio/mac/audio_manager_mac.cc
@@ -4,6 +4,7 @@
#include <CoreAudio/AudioHardware.h>
+#include "base/at_exit.h"
#include "media/audio/fake_audio_input_stream.h"
#include "media/audio/fake_audio_output_stream.h"
#include "media/audio/mac/audio_manager_mac.h"
@@ -74,7 +75,22 @@ void AudioManagerMac::ReleaseOutputStream(
delete stream;
}
-// static
-AudioManager* AudioManager::CreateAudioManager() {
- return new AudioManagerMac();
+namespace {
+
+AudioManagerMac* g_audio_manager = NULL;
+
+} // namespace.
+
+void DestroyAudioManagerMac(void* param) {
+ delete g_audio_manager;
+ g_audio_manager = NULL;
+}
+
+// By convention, the AudioManager is not thread safe.
+AudioManager* AudioManager::GetAudioManager() {
+ if (!g_audio_manager) {
+ g_audio_manager = new AudioManagerMac();
+ base::AtExitManager::RegisterCallback(&DestroyAudioManagerMac, NULL);
+ }
+ return g_audio_manager;
}
diff --git a/media/audio/mac/audio_manager_mac.h b/media/audio/mac/audio_manager_mac.h
index fa25ece..c05e092 100644
--- a/media/audio/mac/audio_manager_mac.h
+++ b/media/audio/mac/audio_manager_mac.h
@@ -6,14 +6,14 @@
#define MEDIA_AUDIO_MAC_AUDIO_MANAGER_MAC_H_
#include "base/basictypes.h"
-#include "media/audio/audio_manager_base.h"
+#include "media/audio/audio_io.h"
class PCMQueueOutAudioOutputStream;
// Mac OS X implementation of the AudioManager singleton. This class is internal
// to the audio output and only internal users can call methods not exposed by
// the AudioManager class.
-class AudioManagerMac : public AudioManagerBase {
+class AudioManagerMac : public AudioManager {
public:
AudioManagerMac() {};
diff --git a/media/audio/openbsd/audio_manager_openbsd.cc b/media/audio/openbsd/audio_manager_openbsd.cc
index c2c7b98..7d7a249 100644
--- a/media/audio/openbsd/audio_manager_openbsd.cc
+++ b/media/audio/openbsd/audio_manager_openbsd.cc
@@ -4,6 +4,7 @@
#include "media/audio/openbsd/audio_manager_openbsd.h"
+#include "base/at_exit.h"
#include "base/logging.h"
namespace {
@@ -47,7 +48,6 @@ AudioManagerOpenBSD::~AudioManagerOpenBSD() {
}
void AudioManagerOpenBSD::Init() {
- AudioManagerBase::Init();
}
void AudioManagerOpenBSD::MuteAll() {
@@ -71,8 +71,3 @@ AudioManager* AudioManager::GetAudioManager() {
}
return g_audio_manager;
}
-
-// static
-AudioManager* AudioManager::CreateAudioManager() {
- return new AudioManagerOpenBSD();
-}
diff --git a/media/audio/openbsd/audio_manager_openbsd.h b/media/audio/openbsd/audio_manager_openbsd.h
index fc35a37..ddbce23 100644
--- a/media/audio/openbsd/audio_manager_openbsd.h
+++ b/media/audio/openbsd/audio_manager_openbsd.h
@@ -7,7 +7,7 @@
#include "media/audio/audio_io.h"
-class AudioManagerOpenBSD : public AudioManagerBase {
+class AudioManagerOpenBSD : public AudioManager {
public:
AudioManagerOpenBSD();
diff --git a/media/audio/simple_sources_unittest.cc b/media/audio/simple_sources_unittest.cc
index 029d565..7ddc23f 100644
--- a/media/audio/simple_sources_unittest.cc
+++ b/media/audio/simple_sources_unittest.cc
@@ -6,7 +6,6 @@
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
#include "base/time.h"
-#include "media/audio/audio_manager.h"
#include "media/audio/fake_audio_output_stream.h"
#include "media/audio/simple_sources.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/media/audio/win/audio_manager_win.cc b/media/audio/win/audio_manager_win.cc
index 6c4a606..061d2d8 100644
--- a/media/audio/win/audio_manager_win.cc
+++ b/media/audio/win/audio_manager_win.cc
@@ -7,6 +7,7 @@
#include <windows.h>
#include <mmsystem.h>
+#include "base/at_exit.h"
#include "base/basictypes.h"
#include "media/audio/fake_audio_input_stream.h"
#include "media/audio/fake_audio_output_stream.h"
@@ -41,6 +42,8 @@ const int kMaxSamplesPerPacket = kMaxSampleRate;
// play.
const int kNumInputBuffers = 3;
+AudioManagerWin* g_audio_manager = NULL;
+
} // namespace.
bool AudioManagerWin::HasAudioOutputDevices() {
@@ -122,7 +125,15 @@ void AudioManagerWin::UnMuteAll() {
AudioManagerWin::~AudioManagerWin() {
}
-// static
-AudioManager* AudioManager::CreateAudioManager() {
- return new AudioManagerWin();
+void DestroyAudioManagerWin(void* param) {
+ delete g_audio_manager;
+ g_audio_manager = NULL;
+}
+
+AudioManager* AudioManager::GetAudioManager() {
+ if (!g_audio_manager) {
+ g_audio_manager = new AudioManagerWin();
+ base::AtExitManager::RegisterCallback(&DestroyAudioManagerWin, NULL);
+ }
+ return g_audio_manager;
}
diff --git a/media/audio/win/audio_manager_win.h b/media/audio/win/audio_manager_win.h
index b8bd579..21a4014 100644
--- a/media/audio/win/audio_manager_win.h
+++ b/media/audio/win/audio_manager_win.h
@@ -8,7 +8,7 @@
#include <windows.h>
#include "base/basictypes.h"
-#include "media/audio/audio_manager_base.h"
+#include "media/audio/audio_io.h"
class PCMWaveInAudioInputStream;
class PCMWaveOutAudioOutputStream;
@@ -16,7 +16,7 @@ class PCMWaveOutAudioOutputStream;
// Windows implementation of the AudioManager singleton. This class is internal
// to the audio output and only internal users can call methods not exposed by
// the AudioManager class.
-class AudioManagerWin : public AudioManagerBase {
+class AudioManagerWin : public AudioManager {
public:
AudioManagerWin() {}
// Implementation of AudioManager.
diff --git a/media/filters/audio_renderer_impl.cc b/media/filters/audio_renderer_impl.cc
index 9fd1034..0f4a053 100644
--- a/media/filters/audio_renderer_impl.cc
+++ b/media/filters/audio_renderer_impl.cc
@@ -7,7 +7,6 @@
#include <math.h>
#include "media/base/filter_host.h"
-#include "media/audio/audio_manager.h"
namespace media {
diff --git a/media/media.gyp b/media/media.gyp
index eec7678..45815e72 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -23,10 +23,6 @@
'audio/audio_io.h',
'audio/audio_input_controller.cc',
'audio/audio_input_controller.h',
- 'audio/audio_manager.h',
- 'audio/audio_manager.cc',
- 'audio/audio_manager_base.h',
- 'audio/audio_manager_base.cc',
'audio/audio_output_controller.cc',
'audio/audio_output_controller.h',
'audio/audio_util.cc',