diff options
author | tommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-19 09:16:58 +0000 |
---|---|---|
committer | tommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-19 09:16:58 +0000 |
commit | 8f5fc718853a128dc2f70ec4e55db4044af64bcc (patch) | |
tree | 4f283d47012fd9594433990e89ad7f4fff3f0bcd /media | |
parent | ae4e03118d9a8792b907c923adf6516495f20536 (diff) | |
download | chromium_src-8f5fc718853a128dc2f70ec4e55db4044af64bcc.zip chromium_src-8f5fc718853a128dc2f70ec4e55db4044af64bcc.tar.gz chromium_src-8f5fc718853a128dc2f70ec4e55db4044af64bcc.tar.bz2 |
Add thread safety to AudioManagerBase to protect access to the audio thread member variable.
This is is a tentative fix for an issue where the AudioManager can crash while tearing down
the audio thread. I suspect that this happens because more than one cleanup attempts were
made since the class wasn't thread safe. I'm also changing direct access to the thread's
MessageLoop* to use MessageLoopProxy based on the same theory.
BUG=110051
TEST=Run media tests.
Review URL: https://chromiumcodereview.appspot.com/9255017
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@118272 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/audio/audio_low_latency_input_output_unittest.cc | 7 | ||||
-rw-r--r-- | media/audio/audio_manager.h | 5 | ||||
-rw-r--r-- | media/audio/audio_manager_base.cc | 61 | ||||
-rw-r--r-- | media/audio/audio_manager_base.h | 18 | ||||
-rw-r--r-- | media/audio/audio_output_controller.cc | 29 | ||||
-rw-r--r-- | media/audio/audio_output_controller.h | 2 | ||||
-rw-r--r-- | media/audio/audio_output_dispatcher.cc | 10 | ||||
-rw-r--r-- | media/audio/audio_output_dispatcher.h | 2 | ||||
-rw-r--r-- | media/audio/audio_output_proxy.cc | 17 | ||||
-rw-r--r-- | media/audio/audio_output_proxy.h | 7 | ||||
-rw-r--r-- | media/audio/audio_output_proxy_unittest.cc | 5 | ||||
-rw-r--r-- | media/audio/linux/alsa_output.cc | 30 | ||||
-rw-r--r-- | media/audio/linux/alsa_output_unittest.cc | 6 | ||||
-rw-r--r-- | media/audio/linux/audio_manager_linux.cc | 17 |
14 files changed, 118 insertions, 98 deletions
diff --git a/media/audio/audio_low_latency_input_output_unittest.cc b/media/audio/audio_low_latency_input_output_unittest.cc index 683bf2b..a989a4e 100644 --- a/media/audio/audio_low_latency_input_output_unittest.cc +++ b/media/audio/audio_low_latency_input_output_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -6,6 +6,7 @@ #include "base/environment.h" #include "base/file_util.h" #include "base/memory/scoped_ptr.h" +#include "base/message_loop.h" #include "base/path_service.h" #include "base/synchronization/lock.h" #include "base/test/test_timeouts.h" @@ -82,8 +83,8 @@ class MockAudioManager : public AudioManagerAnyPlatform { virtual ~MockAudioManager() {} - virtual MessageLoop* GetMessageLoop() OVERRIDE { - return MessageLoop::current(); + virtual scoped_refptr<base::MessageLoopProxy> GetMessageLoop() OVERRIDE { + return MessageLoop::current()->message_loop_proxy(); } private: diff --git a/media/audio/audio_manager.h b/media/audio/audio_manager.h index fd59486..b1ca217 100644 --- a/media/audio/audio_manager.h +++ b/media/audio/audio_manager.h @@ -16,6 +16,9 @@ class AudioInputStream; class AudioOutputStream; class MessageLoop; +namespace base { +class MessageLoopProxy; +} // Manages all audio resources. In particular it owns the AudioOutputStream // objects. Provides some convenience functions that avoid the need to provide @@ -121,7 +124,7 @@ class MEDIA_EXPORT AudioManager virtual bool IsRecordingInProcess() = 0; // Returns message loop used for audio IO. - virtual MessageLoop* GetMessageLoop() = 0; + virtual scoped_refptr<base::MessageLoopProxy> GetMessageLoop() = 0; protected: // Called from Create() to initialize the instance. diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc index 696dd86..9202e58 100644 --- a/media/audio/audio_manager_base.cc +++ b/media/audio/audio_manager_base.cc @@ -5,6 +5,8 @@ #include "media/audio/audio_manager_base.h" #include "base/bind.h" +#include "base/message_loop_proxy.h" +#include "base/threading/thread.h" #include "media/audio/audio_output_dispatcher.h" #include "media/audio/audio_output_proxy.h" @@ -14,8 +16,7 @@ const char AudioManagerBase::kDefaultDeviceName[] = "Default"; const char AudioManagerBase::kDefaultDeviceId[] = "default"; AudioManagerBase::AudioManagerBase() - : audio_thread_("AudioThread"), - num_active_input_streams_(0) { + : num_active_input_streams_(0) { } AudioManagerBase::~AudioManagerBase() { @@ -24,36 +25,45 @@ AudioManagerBase::~AudioManagerBase() { #ifndef NDEBUG void AudioManagerBase::AddRef() const { - const MessageLoop* loop = audio_thread_.message_loop(); - DCHECK(loop == NULL || loop != MessageLoop::current()); + { + base::AutoLock lock(audio_thread_lock_); + const MessageLoop* loop = audio_thread_.get() ? + audio_thread_->message_loop() : NULL; + DCHECK(loop == NULL || loop != MessageLoop::current()); + } AudioManager::AddRef(); } void AudioManagerBase::Release() const { - const MessageLoop* loop = audio_thread_.message_loop(); - DCHECK(loop == NULL || loop != MessageLoop::current()); + { + base::AutoLock lock(audio_thread_lock_); + const MessageLoop* loop = audio_thread_.get() ? + audio_thread_->message_loop() : NULL; + DCHECK(loop == NULL || loop != MessageLoop::current()); + } AudioManager::Release(); } #endif void AudioManagerBase::Init() { - CHECK(audio_thread_.Start()); + base::AutoLock lock(audio_thread_lock_); + DCHECK(!audio_thread_.get()); + audio_thread_.reset(new base::Thread("AudioThread")); + CHECK(audio_thread_->Start()); } string16 AudioManagerBase::GetAudioInputDeviceModel() { return string16(); } -MessageLoop* AudioManagerBase::GetMessageLoop() { - return audio_thread_.message_loop(); +scoped_refptr<base::MessageLoopProxy> AudioManagerBase::GetMessageLoop() { + base::AutoLock lock(audio_thread_lock_); + return audio_thread_.get() ? audio_thread_->message_loop_proxy() : NULL; } AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy( const AudioParameters& params) { - DCHECK_EQ(MessageLoop::current(), GetMessageLoop()); - - if (!initialized()) - return NULL; + DCHECK(GetMessageLoop()->BelongsToCurrentThread()); scoped_refptr<AudioOutputDispatcher>& dispatcher = output_dispatchers_[params]; @@ -88,23 +98,34 @@ bool AudioManagerBase::IsRecordingInProcess() { } void AudioManagerBase::Shutdown() { - if (!initialized()) - return; + // 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); + } - DCHECK_NE(MessageLoop::current(), GetMessageLoop()); + if (!audio_thread.get()) + return; + + CHECK_NE(MessageLoop::current(), audio_thread->message_loop()); // We must use base::Unretained since Shutdown might have been called from // the destructor and we can't alter the refcount of the object at that point. - GetMessageLoop()->PostTask(FROM_HERE, base::Bind( + audio_thread->message_loop()->PostTask(FROM_HERE, base::Bind( &AudioManagerBase::ShutdownOnAudioThread, base::Unretained(this))); + // Stop() will wait for any posted messages to be processed first. - audio_thread_.Stop(); + audio_thread->Stop(); } void AudioManagerBase::ShutdownOnAudioThread() { - DCHECK_EQ(MessageLoop::current(), GetMessageLoop()); - + // 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. AudioOutputDispatchersMap::iterator it = output_dispatchers_.begin(); for (; it != output_dispatchers_.end(); ++it) { scoped_refptr<AudioOutputDispatcher>& dispatcher = (*it).second; diff --git a/media/audio/audio_manager_base.h b/media/audio/audio_manager_base.h index 15e18be..1cba8a8 100644 --- a/media/audio/audio_manager_base.h +++ b/media/audio/audio_manager_base.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -9,11 +9,16 @@ #include "base/atomic_ref_count.h" #include "base/compiler_specific.h" -#include "base/threading/thread.h" +#include "base/memory/scoped_ptr.h" +#include "base/synchronization/lock.h" #include "media/audio/audio_manager.h" class AudioOutputDispatcher; +namespace base { +class Thread; +} + // AudioManagerBase provides AudioManager functions common for all platforms. class MEDIA_EXPORT AudioManagerBase : public AudioManager { public: @@ -34,7 +39,7 @@ class MEDIA_EXPORT AudioManagerBase : public AudioManager { virtual void Init() OVERRIDE; - virtual MessageLoop* GetMessageLoop() OVERRIDE; + virtual scoped_refptr<base::MessageLoopProxy> GetMessageLoop() OVERRIDE; virtual string16 GetAudioInputDeviceModel() OVERRIDE; @@ -66,12 +71,13 @@ class MEDIA_EXPORT AudioManagerBase : public AudioManager { void ShutdownOnAudioThread(); - bool initialized() { return audio_thread_.IsRunning(); } - // Thread used to interact with AudioOutputStreams created by this // audio manger. - base::Thread audio_thread_; + scoped_ptr<base::Thread> audio_thread_; + mutable base::Lock audio_thread_lock_; + // Map of cached AudioOutputDispatcher instances. Must only be touched + // from the audio thread (no locking). AudioOutputDispatchersMap output_dispatchers_; // Counts the number of active input streams to find out if something else diff --git a/media/audio/audio_output_controller.cc b/media/audio/audio_output_controller.cc index 9f6d7da..d087a70 100644 --- a/media/audio/audio_output_controller.cc +++ b/media/audio/audio_output_controller.cc @@ -42,10 +42,11 @@ AudioOutputController::AudioOutputController(AudioManager* audio_manager, AudioOutputController::~AudioOutputController() { DCHECK_EQ(kClosed, state_); - if (message_loop_ == MessageLoop::current()) { + DCHECK(message_loop_); + + if (!message_loop_.get() || message_loop_->BelongsToCurrentThread()) { DoStopCloseAndClearStream(NULL); } else { - DCHECK(message_loop_); WaitableEvent completion(true /* manual reset */, false /* initial state */); message_loop_->PostTask(FROM_HERE, @@ -145,7 +146,7 @@ void AudioOutputController::EnqueueData(const uint8* data, uint32 size) { } void AudioOutputController::DoCreate(const AudioParameters& params) { - DCHECK_EQ(message_loop_, MessageLoop::current()); + DCHECK(message_loop_->BelongsToCurrentThread()); // Close() can be called before DoCreate() is executed. if (state_ == kClosed) @@ -185,7 +186,7 @@ void AudioOutputController::DoCreate(const AudioParameters& params) { } void AudioOutputController::DoPlay() { - DCHECK_EQ(message_loop_, MessageLoop::current()); + DCHECK(message_loop_->BelongsToCurrentThread()); // We can start from created or paused state. if (state_ != kCreated && state_ != kPaused) @@ -204,14 +205,14 @@ void AudioOutputController::DoPlay() { FROM_HERE, base::Bind(&AudioOutputController::PollAndStartIfDataReady, weak_this_.GetWeakPtr()), - base::TimeDelta::FromMilliseconds(kPollPauseInMilliseconds)); + kPollPauseInMilliseconds); } else { StartStream(); } } void AudioOutputController::PollAndStartIfDataReady() { - DCHECK_EQ(message_loop_, MessageLoop::current()); + DCHECK(message_loop_->BelongsToCurrentThread()); // Being paranoid: do nothing if state unexpectedly changed. if ((state_ != kStarting) && (state_ != kPausedWhenStarting)) @@ -232,12 +233,12 @@ void AudioOutputController::PollAndStartIfDataReady() { FROM_HERE, base::Bind(&AudioOutputController::PollAndStartIfDataReady, weak_this_.GetWeakPtr()), - base::TimeDelta::FromMilliseconds(kPollPauseInMilliseconds)); + kPollPauseInMilliseconds); } } void AudioOutputController::StartStream() { - DCHECK_EQ(message_loop_, MessageLoop::current()); + DCHECK(message_loop_->BelongsToCurrentThread()); state_ = kPlaying; // We start the AudioOutputStream lazily. @@ -248,7 +249,7 @@ void AudioOutputController::StartStream() { } void AudioOutputController::DoPause() { - DCHECK_EQ(message_loop_, MessageLoop::current()); + DCHECK(message_loop_->BelongsToCurrentThread()); if (stream_) stream_->Stop(); @@ -282,7 +283,7 @@ void AudioOutputController::DoPause() { } void AudioOutputController::DoFlush() { - DCHECK_EQ(message_loop_, MessageLoop::current()); + DCHECK(message_loop_->BelongsToCurrentThread()); // TODO(hclam): Actually flush the audio device. @@ -296,7 +297,7 @@ void AudioOutputController::DoFlush() { } void AudioOutputController::DoClose(const base::Closure& closed_task) { - DCHECK_EQ(message_loop_, MessageLoop::current()); + DCHECK(message_loop_->BelongsToCurrentThread()); if (state_ != kClosed) { DoStopCloseAndClearStream(NULL); @@ -312,7 +313,7 @@ void AudioOutputController::DoClose(const base::Closure& closed_task) { } void AudioOutputController::DoSetVolume(double volume) { - DCHECK_EQ(message_loop_, MessageLoop::current()); + DCHECK(message_loop_->BelongsToCurrentThread()); // 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. @@ -332,7 +333,7 @@ void AudioOutputController::DoSetVolume(double volume) { } void AudioOutputController::DoReportError(int code) { - DCHECK_EQ(message_loop_, MessageLoop::current()); + DCHECK(message_loop_->BelongsToCurrentThread()); if (state_ != kClosed) handler_->OnError(this, code); } @@ -415,7 +416,7 @@ void AudioOutputController::SubmitOnMoreData_Locked() { } void AudioOutputController::DoStopCloseAndClearStream(WaitableEvent *done) { - DCHECK_EQ(message_loop_, MessageLoop::current()); + DCHECK(message_loop_->BelongsToCurrentThread()); // Allow calling unconditionally and bail if we don't have a stream_ to close. if (stream_ != NULL) { diff --git a/media/audio/audio_output_controller.h b/media/audio/audio_output_controller.h index 24de175..f6e5722 100644 --- a/media/audio/audio_output_controller.h +++ b/media/audio/audio_output_controller.h @@ -254,7 +254,7 @@ class MEDIA_EXPORT AudioOutputController SyncReader* sync_reader_; // The message loop of audio thread that this object runs on. - MessageLoop* message_loop_; + scoped_refptr<base::MessageLoopProxy> message_loop_; // When starting stream we wait for data to become available. // Number of times left. diff --git a/media/audio/audio_output_dispatcher.cc b/media/audio/audio_output_dispatcher.cc index 8e40277..b1f265b 100644 --- a/media/audio/audio_output_dispatcher.cc +++ b/media/audio/audio_output_dispatcher.cc @@ -14,7 +14,7 @@ AudioOutputDispatcher::AudioOutputDispatcher( AudioManager* audio_manager, const AudioParameters& params, base::TimeDelta close_delay) : audio_manager_(audio_manager), - message_loop_(audio_manager->GetMessageLoop()), + message_loop_(MessageLoop::current()), params_(params), pause_delay_(base::TimeDelta::FromMilliseconds( 2 * params.samples_per_packet * @@ -25,7 +25,9 @@ AudioOutputDispatcher::AudioOutputDispatcher( close_delay, weak_this_.GetWeakPtr(), &AudioOutputDispatcher::ClosePendingStreams) { - DCHECK_EQ(MessageLoop::current(), message_loop_); + // We expect to be instantiated on the audio thread. Otherwise the + // message_loop_ member will point to the wrong message loop! + DCHECK(audio_manager->GetMessageLoop()->BelongsToCurrentThread()); } AudioOutputDispatcher::~AudioOutputDispatcher() { @@ -133,10 +135,6 @@ void AudioOutputDispatcher::Shutdown() { pausing_streams_.clear(); } -MessageLoop* AudioOutputDispatcher::message_loop() { - return message_loop_; -} - bool AudioOutputDispatcher::CreateAndOpenStream() { AudioOutputStream* stream = audio_manager_->MakeAudioOutputStream(params_); if (!stream) diff --git a/media/audio/audio_output_dispatcher.h b/media/audio/audio_output_dispatcher.h index 08e6893..cf01a31 100644 --- a/media/audio/audio_output_dispatcher.h +++ b/media/audio/audio_output_dispatcher.h @@ -69,8 +69,6 @@ class MEDIA_EXPORT AudioOutputDispatcher // Called on the audio thread when the AudioManager is shutting down. void Shutdown(); - MessageLoop* message_loop(); - private: friend class AudioOutputProxyTest; diff --git a/media/audio/audio_output_proxy.cc b/media/audio/audio_output_proxy.cc index e8309cf..29490db 100644 --- a/media/audio/audio_output_proxy.cc +++ b/media/audio/audio_output_proxy.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -14,17 +14,16 @@ AudioOutputProxy::AudioOutputProxy(AudioOutputDispatcher* dispatcher) state_(kCreated), physical_stream_(NULL), volume_(1.0) { - DCHECK_EQ(MessageLoop::current(), dispatcher_->message_loop()); } AudioOutputProxy::~AudioOutputProxy() { - DCHECK_EQ(MessageLoop::current(), dispatcher_->message_loop()); + DCHECK(CalledOnValidThread()); DCHECK(state_ == kCreated || state_ == kClosed); DCHECK(!physical_stream_); } bool AudioOutputProxy::Open() { - DCHECK_EQ(MessageLoop::current(), dispatcher_->message_loop()); + DCHECK(CalledOnValidThread()); DCHECK_EQ(state_, kCreated); if (!dispatcher_->StreamOpened()) { @@ -37,7 +36,7 @@ bool AudioOutputProxy::Open() { } void AudioOutputProxy::Start(AudioSourceCallback* callback) { - DCHECK_EQ(MessageLoop::current(), dispatcher_->message_loop()); + DCHECK(CalledOnValidThread()); DCHECK(physical_stream_ == NULL); DCHECK_EQ(state_, kOpened); @@ -54,7 +53,7 @@ void AudioOutputProxy::Start(AudioSourceCallback* callback) { } void AudioOutputProxy::Stop() { - DCHECK_EQ(MessageLoop::current(), dispatcher_->message_loop()); + DCHECK(CalledOnValidThread()); if (state_ != kPlaying) return; @@ -66,7 +65,7 @@ void AudioOutputProxy::Stop() { } void AudioOutputProxy::SetVolume(double volume) { - DCHECK_EQ(MessageLoop::current(), dispatcher_->message_loop()); + DCHECK(CalledOnValidThread()); volume_ = volume; if (physical_stream_) { physical_stream_->SetVolume(volume); @@ -74,12 +73,12 @@ void AudioOutputProxy::SetVolume(double volume) { } void AudioOutputProxy::GetVolume(double* volume) { - DCHECK_EQ(MessageLoop::current(), dispatcher_->message_loop()); + DCHECK(CalledOnValidThread()); *volume = volume_; } void AudioOutputProxy::Close() { - DCHECK_EQ(MessageLoop::current(), dispatcher_->message_loop()); + DCHECK(CalledOnValidThread()); DCHECK(state_ == kCreated || state_ == kError || state_ == kOpened); DCHECK(!physical_stream_); diff --git a/media/audio/audio_output_proxy.h b/media/audio/audio_output_proxy.h index af081c1..8e1b350 100644 --- a/media/audio/audio_output_proxy.h +++ b/media/audio/audio_output_proxy.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -8,6 +8,7 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" +#include "base/threading/non_thread_safe.h" #include "media/audio/audio_io.h" #include "media/audio/audio_parameters.h" @@ -21,7 +22,9 @@ class AudioOutputDispatcher; // // AudioOutputProxy uses AudioOutputDispatcher to open and close // physical output streams. -class MEDIA_EXPORT AudioOutputProxy : public AudioOutputStream { +class MEDIA_EXPORT AudioOutputProxy + : public AudioOutputStream, + public NON_EXPORTED_BASE(base::NonThreadSafe) { public: // Caller keeps ownership of |dispatcher|. explicit AudioOutputProxy(AudioOutputDispatcher* dispatcher); diff --git a/media/audio/audio_output_proxy_unittest.cc b/media/audio/audio_output_proxy_unittest.cc index b2ff1a9..957e77a 100644 --- a/media/audio/audio_output_proxy_unittest.cc +++ b/media/audio/audio_output_proxy_unittest.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/message_loop.h" +#include "base/message_loop_proxy.h" #include "base/threading/platform_thread.h" #include "media/audio/audio_output_dispatcher.h" #include "media/audio/audio_output_proxy.h" @@ -50,7 +51,7 @@ class MockAudioManager : public AudioManager { MOCK_METHOD0(UnMuteAll, void()); MOCK_METHOD0(CanShowAudioInputSettings, bool()); MOCK_METHOD0(ShowAudioInputSettings, void()); - MOCK_METHOD0(GetMessageLoop, MessageLoop*()); + MOCK_METHOD0(GetMessageLoop, scoped_refptr<base::MessageLoopProxy>()); MOCK_METHOD1(GetAudioInputDeviceNames, void( media::AudioDeviceNames* device_name)); MOCK_METHOD0(IsRecordingInProcess, bool()); @@ -69,7 +70,7 @@ class AudioOutputProxyTest : public testing::Test { virtual void SetUp() { MockAudioManager* manager = new MockAudioManager(); EXPECT_CALL(*manager, GetMessageLoop()) - .WillRepeatedly(Return(&message_loop_)); + .WillRepeatedly(Return(message_loop_.message_loop_proxy())); manager_ = manager; InitDispatcher(base::TimeDelta::FromMilliseconds(kTestCloseDelayMs)); } diff --git a/media/audio/linux/alsa_output.cc b/media/audio/linux/alsa_output.cc index ef872c0..b3f931d 100644 --- a/media/audio/linux/alsa_output.cc +++ b/media/audio/linux/alsa_output.cc @@ -206,7 +206,7 @@ AlsaPcmOutputStream::AlsaPcmOutputStream(const std::string& device_name, state_(kCreated), volume_(1.0f), source_callback_(NULL) { - DCHECK_EQ(MessageLoop::current(), manager_->GetMessageLoop()); + DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); // Sanity check input values. if ((params.sample_rate > kAlsaMaxSampleRate) || (params.sample_rate <= 0)) { @@ -235,7 +235,7 @@ AlsaPcmOutputStream::~AlsaPcmOutputStream() { } bool AlsaPcmOutputStream::Open() { - DCHECK_EQ(MessageLoop::current(), manager_->GetMessageLoop()); + DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); if (state() == kInError) return false; @@ -293,7 +293,7 @@ bool AlsaPcmOutputStream::Open() { } void AlsaPcmOutputStream::Close() { - DCHECK_EQ(MessageLoop::current(), manager_->GetMessageLoop()); + DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); // Sanity check that the transition occurs correctly. It is safe to // continue anyways because all operations for closing are idempotent. @@ -322,7 +322,7 @@ void AlsaPcmOutputStream::Close() { } void AlsaPcmOutputStream::Start(AudioSourceCallback* callback) { - DCHECK_EQ(MessageLoop::current(), manager_->GetMessageLoop()); + DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); CHECK(callback); @@ -361,7 +361,7 @@ void AlsaPcmOutputStream::Start(AudioSourceCallback* callback) { } void AlsaPcmOutputStream::Stop() { - DCHECK_EQ(MessageLoop::current(), manager_->GetMessageLoop()); + DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); // Reset the callback, so that it is not called anymore. set_source_callback(NULL); @@ -370,19 +370,19 @@ void AlsaPcmOutputStream::Stop() { } void AlsaPcmOutputStream::SetVolume(double volume) { - DCHECK_EQ(MessageLoop::current(), manager_->GetMessageLoop()); + DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); volume_ = static_cast<float>(volume); } void AlsaPcmOutputStream::GetVolume(double* volume) { - DCHECK_EQ(MessageLoop::current(), manager_->GetMessageLoop()); + DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); *volume = volume_; } void AlsaPcmOutputStream::BufferPacket(bool* source_exhausted) { - DCHECK_EQ(MessageLoop::current(), manager_->GetMessageLoop()); + DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); // If stopped, simulate a 0-length packet. if (stop_stream_) { @@ -473,7 +473,7 @@ void AlsaPcmOutputStream::BufferPacket(bool* source_exhausted) { } void AlsaPcmOutputStream::WritePacket() { - DCHECK_EQ(MessageLoop::current(), manager_->GetMessageLoop()); + DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); // If the device is in error, just eat the bytes. if (stop_stream_) { @@ -537,7 +537,7 @@ void AlsaPcmOutputStream::WritePacket() { } void AlsaPcmOutputStream::WriteTask() { - DCHECK_EQ(MessageLoop::current(), manager_->GetMessageLoop()); + DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); if (stop_stream_) return; @@ -553,7 +553,7 @@ void AlsaPcmOutputStream::WriteTask() { } void AlsaPcmOutputStream::ScheduleNextWrite(bool source_exhausted) { - DCHECK_EQ(MessageLoop::current(), manager_->GetMessageLoop()); + DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); if (stop_stream_) return; @@ -607,7 +607,7 @@ void AlsaPcmOutputStream::ScheduleNextWrite(bool source_exhausted) { manager_->GetMessageLoop()->PostDelayedTask(FROM_HERE, base::Bind(&AlsaPcmOutputStream::WriteTask, weak_factory_.GetWeakPtr()), - base::TimeDelta::FromMilliseconds(next_fill_time_ms)); + next_fill_time_ms); } } } @@ -695,7 +695,7 @@ snd_pcm_sframes_t AlsaPcmOutputStream::GetCurrentDelay() { } snd_pcm_sframes_t AlsaPcmOutputStream::GetAvailableFrames() { - DCHECK_EQ(MessageLoop::current(), manager_->GetMessageLoop()); + DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); if (stop_stream_) return 0; @@ -809,7 +809,7 @@ bool AlsaPcmOutputStream::CanTransitionTo(InternalState to) { AlsaPcmOutputStream::InternalState AlsaPcmOutputStream::TransitionTo(InternalState to) { - DCHECK_EQ(MessageLoop::current(), manager_->GetMessageLoop()); + DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); if (!CanTransitionTo(to)) { NOTREACHED() << "Cannot transition from: " << state_ << " to: " << to; @@ -843,6 +843,6 @@ void AlsaPcmOutputStream::RunErrorCallback(int code) { // Changes the AudioSourceCallback to proxy calls to. Pass in NULL to // release ownership of the currently registered callback. void AlsaPcmOutputStream::set_source_callback(AudioSourceCallback* callback) { - DCHECK_EQ(MessageLoop::current(), manager_->GetMessageLoop()); + DCHECK(manager_->GetMessageLoop()->BelongsToCurrentThread()); source_callback_ = callback; } diff --git a/media/audio/linux/alsa_output_unittest.cc b/media/audio/linux/alsa_output_unittest.cc index 5b8405a..f1870d2 100644 --- a/media/audio/linux/alsa_output_unittest.cc +++ b/media/audio/linux/alsa_output_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -88,8 +88,8 @@ class MockAudioManagerLinux : public AudioManagerLinux { // We don't mock this method since all tests will do the same thing // and use the current message loop. - virtual MessageLoop* GetMessageLoop() { - return MessageLoop::current(); + virtual scoped_refptr<base::MessageLoopProxy> GetMessageLoop() OVERRIDE { + return MessageLoop::current()->message_loop_proxy(); } }; diff --git a/media/audio/linux/audio_manager_linux.cc b/media/audio/linux/audio_manager_linux.cc index 6aaf591..da24f12 100644 --- a/media/audio/linux/audio_manager_linux.cc +++ b/media/audio/linux/audio_manager_linux.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -49,17 +49,9 @@ bool AudioManagerLinux::HasAudioInputDevices() { AudioOutputStream* AudioManagerLinux::MakeAudioOutputStream( const AudioParameters& params) { - // Early return for testing hook. Do this before checking for - // |initialized_|. - if (params.format == AudioParameters::AUDIO_MOCK) { + // Early return for testing hook. + if (params.format == AudioParameters::AUDIO_MOCK) return FakeAudioOutputStream::MakeFakeStream(params); - } - - if (!initialized()) { - // We should never get here since this method is called on the audio thread. - NOTREACHED(); - return NULL; - } // Don't allow opening more than |kMaxOutputStreams| streams. if (active_output_stream_count_ >= kMaxOutputStreams) @@ -97,9 +89,6 @@ AudioInputStream* AudioManagerLinux::MakeAudioInputStream( return FakeAudioInputStream::MakeFakeStream(params); } - if (!initialized()) - return NULL; - std::string device_name = (device_id == AudioManagerBase::kDefaultDeviceId) ? AlsaPcmInputStream::kAutoSelectDevice : device_id; if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAlsaInputDevice)) { |