diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-07 18:36:51 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-07 18:36:51 +0000 |
commit | 94155a6b13969e7bb5cd96a6acf03277d12d9ae7 (patch) | |
tree | 773bbc2df939c85cb41ee1ae5fd6044f7199d3ed /media | |
parent | 62ede11c038242e242579cb312549acb7e64b518 (diff) | |
download | chromium_src-94155a6b13969e7bb5cd96a6acf03277d12d9ae7.zip chromium_src-94155a6b13969e7bb5cd96a6acf03277d12d9ae7.tar.gz chromium_src-94155a6b13969e7bb5cd96a6acf03277d12d9ae7.tar.bz2 |
Rewrite AudioRendererHost to use AudioController
This change will move all the audio device methods calls to
AudioController so we can move all the audio related methods calls off the IO
thread. This change will let AudioRendererHost to use the AudioController API.
This involves rewriting the whole AudioRendererHost.
After this patch we can implement proper pause operations that is only possible
if they are hosted on a separated thread due to their blocking nature.
Normal latency mode is fully covered by unit tests, including audio control
operations and data conversation.
Low latency mode using SyncSocket is tested only for stream creation and still
need to handle cases during shutdown when we want SyncSocket to return
immediately.
TEST=unit_tests --gtest_filter=AudioRendererTest.*
BUG=39885
Review URL: http://codereview.chromium.org/2850016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@51743 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/audio/audio_controller.cc | 34 | ||||
-rw-r--r-- | media/audio/audio_controller.h | 3 | ||||
-rw-r--r-- | media/audio/fake_audio_output_stream.cc | 8 |
3 files changed, 31 insertions, 14 deletions
diff --git a/media/audio/audio_controller.cc b/media/audio/audio_controller.cc index 21ecdfc..802a97c 100644 --- a/media/audio/audio_controller.cc +++ b/media/audio/audio_controller.cc @@ -34,7 +34,8 @@ namespace media { AudioController::AudioController(EventHandler* handler, uint32 capacity, SyncReader* sync_reader) : handler_(handler), - state_(kCreated), + volume_(0), + state_(kEmpty), hardware_pending_bytes_(0), buffer_capacity_(capacity), sync_reader_(sync_reader), @@ -42,7 +43,7 @@ AudioController::AudioController(EventHandler* handler, uint32 capacity, } AudioController::~AudioController() { - DCHECK(kClosed == state_ || kCreated == state_); + DCHECK(kClosed == state_); } // static @@ -157,6 +158,9 @@ void AudioController::EnqueueData(const uint8* data, uint32 size) { void AudioController::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_); + // Create the stream in the first place. stream_ = AudioManager::GetAudioManager()->MakeAudioStream( format, channels, sample_rate, bits_per_sample); @@ -175,6 +179,13 @@ void AudioController::DoCreate(AudioManager::Format format, int channels, handler_->OnError(this, 0); return; } + // We have successfully opened the stream. Set the initial volume. + stream_->SetVolume(volume_); + + // Finally set the state to kCreated. + state_ = kCreated; + + // And then report we have been created. handler_->OnCreated(this); // If in normal latency mode then start buffering. @@ -252,13 +263,6 @@ void AudioController::DoClose() { stream_ = NULL; } - // If we are in low latency mode then also close the SyncReader. - // TODO(hclam): The shutdown procedure for low latency mode if not complete, - // especially when OnModeData() is blocked on SyncReader for read and the - // above Stop() would deadlock. - if (sync_reader_) - sync_reader_->Close(); - // 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; @@ -267,10 +271,14 @@ void AudioController::DoClose() { void AudioController::DoSetVolume(double volume) { DCHECK_EQ(thread_.message_loop(), MessageLoop::current()); - if (state_ == kError || state_ == kEmpty) + // 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; - stream_->SetVolume(volume); + stream_->SetVolume(volume_); } void AudioController::DoReportError(int code) { @@ -311,7 +319,9 @@ uint32 AudioController::OnMoreData(AudioOutputStream* stream, void AudioController::OnClose(AudioOutputStream* stream) { // Push source doesn't need to know the stream so just pass in NULL. - if (!sync_reader_) { + if (LowLatencyMode()) { + sync_reader_->Close(); + } else { AutoLock auto_lock(lock_); push_source_.OnClose(NULL); } diff --git a/media/audio/audio_controller.h b/media/audio/audio_controller.h index 7b02af4..e7ef5f9 100644 --- a/media/audio/audio_controller.h +++ b/media/audio/audio_controller.h @@ -183,6 +183,9 @@ class AudioController : public base::RefCountedThreadSafe<AudioController>, EventHandler* handler_; AudioOutputStream* stream_; + // The current volume of the audio stream. + double volume_; + // |state_| is written on the audio controller thread and is read on the // hardware audio thread. These operations need to be locked. But lock // is not required for reading on the audio controller thread. diff --git a/media/audio/fake_audio_output_stream.cc b/media/audio/fake_audio_output_stream.cc index 8bfa28e..47b7d3e 100644 --- a/media/audio/fake_audio_output_stream.cc +++ b/media/audio/fake_audio_output_stream.cc @@ -49,8 +49,12 @@ void FakeAudioOutputStream::GetVolume(double* volume) { } void FakeAudioOutputStream::Close() { - callback_->OnClose(this); - callback_ = NULL; + // Calls |callback_| only if it is valid. We don't have |callback_| if + // we have not yet started. + if (callback_) { + callback_->OnClose(this); + callback_ = NULL; + } if (last_fake_stream_) delete last_fake_stream_; |