diff options
Diffstat (limited to 'chromium/media/audio/audio_manager_base.cc')
-rw-r--r-- | chromium/media/audio/audio_manager_base.cc | 109 |
1 files changed, 69 insertions, 40 deletions
diff --git a/chromium/media/audio/audio_manager_base.cc b/chromium/media/audio/audio_manager_base.cc index 5b1f4b3690a..f7b590ae724 100644 --- a/chromium/media/audio/audio_manager_base.cc +++ b/chromium/media/audio/audio_manager_base.cc @@ -8,12 +8,11 @@ #include "base/bind_helpers.h" #include "base/command_line.h" #include "base/message_loop/message_loop_proxy.h" -#include "base/threading/thread.h" +#include "base/strings/string_number_conversions.h" #include "build/build_config.h" #include "media/audio/audio_output_dispatcher_impl.h" #include "media/audio/audio_output_proxy.h" #include "media/audio/audio_output_resampler.h" -#include "media/audio/audio_util.h" #include "media/audio/fake_audio_input_stream.h" #include "media/audio/fake_audio_output_stream.h" #include "media/base/media_switches.h" @@ -78,7 +77,7 @@ class AudioManagerBase::CompareByParams { const DispatcherParams* dispatcher_; }; -AudioManagerBase::AudioManagerBase() +AudioManagerBase::AudioManagerBase(AudioLogFactory* audio_log_factory) : max_num_output_streams_(kDefaultMaxOutputStreams), max_num_input_streams_(kDefaultMaxInputStreams), num_output_streams_(0), @@ -87,9 +86,10 @@ AudioManagerBase::AudioManagerBase() // block the UI thread when swapping devices. output_listeners_( ObserverList<AudioDeviceListener>::NOTIFY_EXISTING_ONLY), - audio_thread_(new base::Thread("AudioThread")) { + audio_thread_("AudioThread"), + audio_log_factory_(audio_log_factory) { #if defined(OS_WIN) - audio_thread_->init_com_with_mta(true); + 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 @@ -104,8 +104,8 @@ AudioManagerBase::AudioManagerBase() } #endif - CHECK(audio_thread_->Start()); - message_loop_ = audio_thread_->message_loop_proxy(); + CHECK(audio_thread_.Start()); + message_loop_ = audio_thread_.message_loop_proxy(); } AudioManagerBase::~AudioManagerBase() { @@ -114,15 +114,15 @@ 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_.get()); + CHECK(!audio_thread_.IsRunning()); // All the output streams should have been deleted. DCHECK_EQ(0, num_output_streams_); // All the input streams should have been deleted. DCHECK_EQ(0, num_input_streams_); } -string16 AudioManagerBase::GetAudioInputDeviceModel() { - return string16(); +base::string16 AudioManagerBase::GetAudioInputDeviceModel() { + return base::string16(); } scoped_refptr<base::MessageLoopProxy> AudioManagerBase::GetMessageLoop() { @@ -131,10 +131,10 @@ scoped_refptr<base::MessageLoopProxy> AudioManagerBase::GetMessageLoop() { scoped_refptr<base::MessageLoopProxy> AudioManagerBase::GetWorkerLoop() { // Lazily start the worker thread. - if (!audio_thread_->IsRunning()) - CHECK(audio_thread_->Start()); + if (!audio_thread_.IsRunning()) + CHECK(audio_thread_.Start()); - return audio_thread_->message_loop_proxy(); + return audio_thread_.message_loop_proxy(); } AudioOutputStream* AudioManagerBase::MakeAudioOutputStream( @@ -330,17 +330,6 @@ void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) { } void AudioManagerBase::Shutdown() { - // To avoid running into deadlocks while we stop the thread, shut it down - // via a local variable while not holding the audio thread lock. - scoped_ptr<base::Thread> audio_thread; - { - base::AutoLock lock(audio_thread_lock_); - audio_thread_.swap(audio_thread); - } - - if (!audio_thread) - return; - // 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 (message_loop_->BelongsToCurrentThread()) { @@ -351,27 +340,24 @@ void AudioManagerBase::Shutdown() { } // Stop() will wait for any posted messages to be processed first. - audio_thread->Stop(); + audio_thread_.Stop(); } void AudioManagerBase::ShutdownOnAudioThread() { - // This should always be running on the audio thread, but since we've cleared - // the audio_thread_ member pointer when we get here, we can't verify exactly - // what thread we're running on. The method is not public though and only - // called from one place, so we'll leave it at that. + DCHECK(message_loop_->BelongsToCurrentThread()); + AudioOutputDispatchers::iterator it = output_dispatchers_.begin(); for (; it != output_dispatchers_.end(); ++it) { scoped_refptr<AudioOutputDispatcher>& dispatcher = (*it)->dispatcher; - if (dispatcher.get()) { - dispatcher->Shutdown(); - // All AudioOutputProxies must have been freed before Shutdown is called. - // If they still exist, things will go bad. They have direct pointers to - // both physical audio stream objects that belong to the dispatcher as - // well as the message loop of the audio thread that will soon go away. - // So, better crash now than later. - DCHECK(dispatcher->HasOneRef()) << "AudioOutputProxies are still alive"; - dispatcher = NULL; - } + dispatcher->Shutdown(); + + // All AudioOutputProxies must have been freed before Shutdown is called. + // If they still exist, things will go bad. They have direct pointers to + // both physical audio stream objects that belong to the dispatcher as + // well as the message loop of the audio thread that will soon go away. + // So, better crash now than later. + DCHECK(dispatcher->HasOneRef()) << "AudioOutputProxies are still alive"; + dispatcher = NULL; } output_dispatchers_.clear(); @@ -419,8 +405,51 @@ std::string AudioManagerBase::GetAssociatedOutputDeviceID( } std::string AudioManagerBase::GetDefaultOutputDeviceID() { - NOTIMPLEMENTED(); return ""; } +int AudioManagerBase::GetUserBufferSize() { + const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); + int buffer_size = 0; + std::string buffer_size_str(cmd_line->GetSwitchValueASCII( + switches::kAudioBufferSize)); + if (base::StringToInt(buffer_size_str, &buffer_size) && buffer_size > 0) + return buffer_size; + + return 0; +} + +scoped_ptr<AudioLog> AudioManagerBase::CreateAudioLog( + AudioLogFactory::AudioComponent component) { + return audio_log_factory_->CreateAudioLog(component); +} + +void AudioManagerBase::FixWedgedAudio() { + DCHECK(message_loop_->BelongsToCurrentThread()); +#if defined(OS_MACOSX) + // Through trial and error, we've found that one way to restore audio after a + // hang is to close all outstanding audio streams. Once all streams have been + // closed, new streams appear to work correctly. + // + // In Chrome terms, this means we need to ask all AudioOutputDispatchers to + // close all Open()'d streams. Once all streams across all dispatchers have + // been closed, we ask for all previously Start()'d streams to be recreated + // using the same AudioSourceCallback they had before. + // + // Since this operation takes place on the audio thread we can be sure that no + // other state-changing stream operations will take place while the fix is in + // progress. + // + // See http://crbug.com/160920 for additional details. + for (AudioOutputDispatchers::iterator it = output_dispatchers_.begin(); + it != output_dispatchers_.end(); ++it) { + (*it)->dispatcher->CloseStreamsForWedgeFix(); + } + for (AudioOutputDispatchers::iterator it = output_dispatchers_.begin(); + it != output_dispatchers_.end(); ++it) { + (*it)->dispatcher->RestartStreamsForWedgeFix(); + } +#endif +} + } // namespace media |