diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-24 23:32:33 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-24 23:32:33 +0000 |
commit | c54fa28a44dad9ccf4c5b03b0a791f69540c16a4 (patch) | |
tree | 3008a22b3fb86afa547c589b274b306a99b1695d /media | |
parent | 53a4597d56e4ca47d70a0f72901d005f0019aca3 (diff) | |
download | chromium_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')
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', |