Index: media/audio/audio_output_controller.cc |
diff --git a/media/audio/audio_output_controller.cc b/media/audio/audio_output_controller.cc |
index 74e2261d6978e83075139d5661c68332f37eec89..27938f98fdd5b8e974ffdbfc6c50e305406cdcba 100644 |
--- a/media/audio/audio_output_controller.cc |
+++ b/media/audio/audio_output_controller.cc |
@@ -4,6 +4,8 @@ |
#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; |
@@ -35,12 +37,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), |
- thread_("AudioOutputControllerThread") { |
+ sync_reader_(sync_reader) { |
} |
AudioOutputController::~AudioOutputController() { |
@@ -65,10 +67,9 @@ scoped_refptr<AudioOutputController> AudioOutputController::Create( |
scoped_refptr<AudioOutputController> controller = new AudioOutputController( |
event_handler, buffer_capacity, NULL); |
- // Start the audio controller thread and post a task to create the |
- // audio stream. |
- controller->thread_.Start(); |
- controller->thread_.message_loop()->PostTask( |
+ controller->message_loop_ = |
+ AudioManager::GetAudioManager()->GetMessageLoop(); |
+ controller->message_loop_->PostTask( |
FROM_HERE, |
NewRunnableMethod(controller.get(), &AudioOutputController::DoCreate, |
format, channels, sample_rate, bits_per_sample, |
@@ -96,10 +97,9 @@ scoped_refptr<AudioOutputController> AudioOutputController::CreateLowLatency( |
scoped_refptr<AudioOutputController> controller = new AudioOutputController( |
event_handler, 0, sync_reader); |
- // Start the audio controller thread and post a task to create the |
- // audio stream. |
- controller->thread_.Start(); |
- controller->thread_.message_loop()->PostTask( |
+ controller->message_loop_ = |
+ AudioManager::GetAudioManager()->GetMessageLoop(); |
+ controller->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(thread_.IsRunning()); |
- thread_.message_loop()->PostTask( |
+ DCHECK(message_loop_); |
+ message_loop_->PostTask( |
FROM_HERE, |
NewRunnableMethod(this, &AudioOutputController::DoPlay)); |
} |
void AudioOutputController::Pause() { |
- DCHECK(thread_.IsRunning()); |
- thread_.message_loop()->PostTask( |
+ DCHECK(message_loop_); |
+ message_loop_->PostTask( |
FROM_HERE, |
NewRunnableMethod(this, &AudioOutputController::DoPause)); |
} |
void AudioOutputController::Flush() { |
- DCHECK(thread_.IsRunning()); |
- thread_.message_loop()->PostTask( |
+ DCHECK(message_loop_); |
+ message_loop_->PostTask( |
FROM_HERE, |
NewRunnableMethod(this, &AudioOutputController::DoFlush)); |
} |
void AudioOutputController::Close() { |
- if (!thread_.IsRunning()) { |
- // If the thread is not running make sure we are stopped. |
- DCHECK_EQ(kClosed, state_); |
- return; |
+ { |
+ AutoLock auto_lock(lock_); |
+ // Don't do anything if the stream is already closed. |
+ if (state_ == kClosed) |
+ return; |
+ state_ = kClosed; |
} |
- // Wait for all tasks to complete on the audio thread. |
- thread_.message_loop()->PostTask( |
+ message_loop_->PostTask( |
FROM_HERE, |
NewRunnableMethod(this, &AudioOutputController::DoClose)); |
- thread_.Stop(); |
} |
void AudioOutputController::SetVolume(double volume) { |
- DCHECK(thread_.IsRunning()); |
- thread_.message_loop()->PostTask( |
+ DCHECK(message_loop_); |
+ message_loop_->PostTask( |
FROM_HERE, |
NewRunnableMethod(this, &AudioOutputController::DoSetVolume, volume)); |
} |
@@ -159,8 +159,14 @@ 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(thread_.message_loop(), MessageLoop::current()); |
- DCHECK_EQ(kEmpty, state_); |
+ 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); |
// Create the stream in the first place. |
stream_ = AudioManager::GetAudioManager()->MakeAudioOutputStream( |
@@ -191,22 +197,20 @@ 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(thread_.message_loop(), MessageLoop::current()); |
- |
- // We can start from created or paused state. |
- if (state_ != kCreated && state_ != kPaused) |
- return; |
+ DCHECK_EQ(message_loop_, MessageLoop::current()); |
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; |
} |
@@ -219,15 +223,14 @@ void AudioOutputController::DoPlay() { |
} |
void AudioOutputController::DoPause() { |
- DCHECK_EQ(thread_.message_loop(), MessageLoop::current()); |
- |
- // We can pause from started state. |
- if (state_ != kPlaying) |
- return; |
+ DCHECK_EQ(message_loop_, MessageLoop::current()); |
// 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; |
} |
@@ -240,24 +243,22 @@ void AudioOutputController::DoPause() { |
} |
void AudioOutputController::DoFlush() { |
- DCHECK_EQ(thread_.message_loop(), MessageLoop::current()); |
- |
- if (state_ != kPaused) |
- return; |
+ DCHECK_EQ(message_loop_, MessageLoop::current()); |
// 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(thread_.message_loop(), MessageLoop::current()); |
- DCHECK_NE(kClosed, state_); |
- |
+ DCHECK_EQ(message_loop_, MessageLoop::current()); |
+ DCHECK_EQ(kClosed, state_); |
// |stream_| can be null if creating the device failed in DoCreate(). |
if (stream_) { |
stream_->Stop(); |
@@ -265,27 +266,26 @@ 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(thread_.message_loop(), MessageLoop::current()); |
+ DCHECK_EQ(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; |
- if (state_ != kPlaying && state_ != kPaused && state_ != kCreated) |
- return; |
+ { |
+ AutoLock auto_lock(lock_); |
+ if (state_ != kPlaying && state_ != kPaused && state_ != kCreated) |
+ return; |
+ } |
stream_->SetVolume(volume_); |
} |
void AudioOutputController::DoReportError(int code) { |
- DCHECK_EQ(thread_.message_loop(), MessageLoop::current()); |
+ DCHECK_EQ(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. |
- thread_.message_loop()->PostTask( |
+ message_loop_->PostTask( |
FROM_HERE, |
NewRunnableMethod(this, &AudioOutputController::DoReportError, code)); |
} |