| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/audio/audio_controller.h" | 5 #include "media/audio/audio_controller.h" |
| 6 | 6 |
| 7 // The following parameters limit the request buffer and packet size from the | 7 // The following parameters limit the request buffer and packet size from the |
| 8 // renderer to avoid renderer from requesting too much memory. | 8 // renderer to avoid renderer from requesting too much memory. |
| 9 static const int kMegabytes = 1024 * 1024; | 9 static const uint32 kMegabytes = 1024 * 1024; |
| 10 static const int kMaxHardwareBufferSize = 2 * kMegabytes; | 10 static const uint32 kMaxHardwareBufferSize = 2 * kMegabytes; |
| 11 static const int kMaxChannels = 32; | 11 static const int kMaxChannels = 32; |
| 12 static const int kMaxBitsPerSample = 64; | 12 static const int kMaxBitsPerSample = 64; |
| 13 static const int kMaxSampleRate = 192000; | 13 static const int kMaxSampleRate = 192000; |
| 14 | 14 |
| 15 // Return true if the parameters for creating an audio stream is valid. | 15 // Return true if the parameters for creating an audio stream is valid. |
| 16 // Return false otherwise. | 16 // Return false otherwise. |
| 17 static bool CheckParameters(int channels, int sample_rate, | 17 static bool CheckParameters(int channels, int sample_rate, |
| 18 int bits_per_sample, int hardware_buffer_size) { | 18 int bits_per_sample, uint32 hardware_buffer_size) { |
| 19 if (channels <= 0 || channels > kMaxChannels) | 19 if (channels <= 0 || channels > kMaxChannels) |
| 20 return false; | 20 return false; |
| 21 if (sample_rate <= 0 || sample_rate > kMaxSampleRate) | 21 if (sample_rate <= 0 || sample_rate > kMaxSampleRate) |
| 22 return false; | 22 return false; |
| 23 if (bits_per_sample <= 0 || bits_per_sample > kMaxBitsPerSample) | 23 if (bits_per_sample <= 0 || bits_per_sample > kMaxBitsPerSample) |
| 24 return false; | 24 return false; |
| 25 if (hardware_buffer_size <= 0 || | 25 if (hardware_buffer_size <= 0 || |
| 26 hardware_buffer_size > kMaxHardwareBufferSize) { | 26 hardware_buffer_size > kMaxHardwareBufferSize) { |
| 27 return false; | 27 return false; |
| 28 } | 28 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 45 DCHECK(kClosed == state_ || kCreated == state_); | 45 DCHECK(kClosed == state_ || kCreated == state_); |
| 46 } | 46 } |
| 47 | 47 |
| 48 // static | 48 // static |
| 49 scoped_refptr<AudioController> AudioController::Create( | 49 scoped_refptr<AudioController> AudioController::Create( |
| 50 EventHandler* event_handler, | 50 EventHandler* event_handler, |
| 51 AudioManager::Format format, | 51 AudioManager::Format format, |
| 52 int channels, | 52 int channels, |
| 53 int sample_rate, | 53 int sample_rate, |
| 54 int bits_per_sample, | 54 int bits_per_sample, |
| 55 int hardware_buffer_size, | 55 uint32 hardware_buffer_size, |
| 56 uint32 buffer_capacity) { | 56 uint32 buffer_capacity) { |
| 57 | 57 |
| 58 if (!CheckParameters(channels, sample_rate, bits_per_sample, | 58 if (!CheckParameters(channels, sample_rate, bits_per_sample, |
| 59 hardware_buffer_size)) | 59 hardware_buffer_size)) |
| 60 return NULL; | 60 return NULL; |
| 61 | 61 |
| 62 // Starts the audio controller thread. | 62 // Starts the audio controller thread. |
| 63 scoped_refptr<AudioController> source = new AudioController( | 63 scoped_refptr<AudioController> controller = new AudioController( |
| 64 event_handler, buffer_capacity, NULL); | 64 event_handler, buffer_capacity, NULL); |
| 65 | 65 |
| 66 // Start the audio controller thread and post a task to create the | 66 // Start the audio controller thread and post a task to create the |
| 67 // audio stream. | 67 // audio stream. |
| 68 source->thread_.Start(); | 68 controller->thread_.Start(); |
| 69 source->thread_.message_loop()->PostTask( | 69 controller->thread_.message_loop()->PostTask( |
| 70 FROM_HERE, | 70 FROM_HERE, |
| 71 NewRunnableMethod(source.get(), &AudioController::DoCreate, | 71 NewRunnableMethod(controller.get(), &AudioController::DoCreate, |
| 72 format, channels, sample_rate, bits_per_sample, | 72 format, channels, sample_rate, bits_per_sample, |
| 73 hardware_buffer_size)); | 73 hardware_buffer_size)); |
| 74 return source; | 74 return controller; |
| 75 } | 75 } |
| 76 | 76 |
| 77 // static | 77 // static |
| 78 scoped_refptr<AudioController> AudioController::CreateLowLatency( | 78 scoped_refptr<AudioController> AudioController::CreateLowLatency( |
| 79 EventHandler* event_handler, | 79 EventHandler* event_handler, |
| 80 AudioManager::Format format, | 80 AudioManager::Format format, |
| 81 int channels, | 81 int channels, |
| 82 int sample_rate, | 82 int sample_rate, |
| 83 int bits_per_sample, | 83 int bits_per_sample, |
| 84 int hardware_buffer_size, | 84 uint32 hardware_buffer_size, |
| 85 SyncReader* sync_reader) { | 85 SyncReader* sync_reader) { |
| 86 | 86 |
| 87 DCHECK(sync_reader); | 87 DCHECK(sync_reader); |
| 88 | 88 |
| 89 if (!CheckParameters(channels, sample_rate, bits_per_sample, | 89 if (!CheckParameters(channels, sample_rate, bits_per_sample, |
| 90 hardware_buffer_size)) | 90 hardware_buffer_size)) |
| 91 return NULL; | 91 return NULL; |
| 92 | 92 |
| 93 // Starts the audio controller thread. | 93 // Starts the audio controller thread. |
| 94 scoped_refptr<AudioController> source = new AudioController( | 94 scoped_refptr<AudioController> controller = new AudioController( |
| 95 event_handler, 0, sync_reader); | 95 event_handler, 0, sync_reader); |
| 96 | 96 |
| 97 // Start the audio controller thread and post a task to create the | 97 // Start the audio controller thread and post a task to create the |
| 98 // audio stream. | 98 // audio stream. |
| 99 source->thread_.Start(); | 99 controller->thread_.Start(); |
| 100 source->thread_.message_loop()->PostTask( | 100 controller->thread_.message_loop()->PostTask( |
| 101 FROM_HERE, | 101 FROM_HERE, |
| 102 NewRunnableMethod(source.get(), &AudioController::DoCreate, | 102 NewRunnableMethod(controller.get(), &AudioController::DoCreate, |
| 103 format, channels, sample_rate, bits_per_sample, | 103 format, channels, sample_rate, bits_per_sample, |
| 104 hardware_buffer_size)); | 104 hardware_buffer_size)); |
| 105 return source; | 105 return controller; |
| 106 } | 106 } |
| 107 | 107 |
| 108 void AudioController::Play() { | 108 void AudioController::Play() { |
| 109 DCHECK(thread_.IsRunning()); | 109 DCHECK(thread_.IsRunning()); |
| 110 thread_.message_loop()->PostTask( | 110 thread_.message_loop()->PostTask( |
| 111 FROM_HERE, | 111 FROM_HERE, |
| 112 NewRunnableMethod(this, &AudioController::DoPlay)); | 112 NewRunnableMethod(this, &AudioController::DoPlay)); |
| 113 } | 113 } |
| 114 | 114 |
| 115 void AudioController::Pause() { | 115 void AudioController::Pause() { |
| 116 DCHECK(thread_.IsRunning()); | 116 DCHECK(thread_.IsRunning()); |
| 117 thread_.message_loop()->PostTask( | 117 thread_.message_loop()->PostTask( |
| 118 FROM_HERE, | 118 FROM_HERE, |
| 119 NewRunnableMethod(this, &AudioController::DoPause)); | 119 NewRunnableMethod(this, &AudioController::DoPause)); |
| 120 } | 120 } |
| 121 | 121 |
| 122 void AudioController::Flush() { | 122 void AudioController::Flush() { |
| 123 DCHECK(thread_.IsRunning()); | 123 DCHECK(thread_.IsRunning()); |
| 124 thread_.message_loop()->PostTask( | 124 thread_.message_loop()->PostTask( |
| 125 FROM_HERE, | 125 FROM_HERE, |
| 126 NewRunnableMethod(this, &AudioController::DoFlush)); | 126 NewRunnableMethod(this, &AudioController::DoFlush)); |
| 127 } | 127 } |
| 128 | 128 |
| 129 void AudioController::Close() { | 129 void AudioController::Close() { |
| 130 DCHECK(thread_.IsRunning()); | 130 if (!thread_.IsRunning()) { |
| 131 // If the thread is not running make sure we are stopped. |
| 132 DCHECK_EQ(kClosed, state_); |
| 133 return; |
| 134 } |
| 135 |
| 136 // Wait for all tasks to complete on the audio thread. |
| 131 thread_.message_loop()->PostTask( | 137 thread_.message_loop()->PostTask( |
| 132 FROM_HERE, | 138 FROM_HERE, |
| 133 NewRunnableMethod(this, &AudioController::DoClose)); | 139 NewRunnableMethod(this, &AudioController::DoClose)); |
| 134 thread_.Stop(); | 140 thread_.Stop(); |
| 135 } | 141 } |
| 136 | 142 |
| 137 void AudioController::SetVolume(double volume) { | 143 void AudioController::SetVolume(double volume) { |
| 138 DCHECK(thread_.IsRunning()); | 144 DCHECK(thread_.IsRunning()); |
| 139 thread_.message_loop()->PostTask( | 145 thread_.message_loop()->PostTask( |
| 140 FROM_HERE, | 146 FROM_HERE, |
| 141 NewRunnableMethod(this, &AudioController::DoSetVolume, volume)); | 147 NewRunnableMethod(this, &AudioController::DoSetVolume, volume)); |
| 142 } | 148 } |
| 143 | 149 |
| 144 void AudioController::EnqueueData(const uint8* data, uint32 size) { | 150 void AudioController::EnqueueData(const uint8* data, uint32 size) { |
| 145 // Write data to the push source and ask for more data if needed. | 151 // Write data to the push source and ask for more data if needed. |
| 146 AutoLock auto_lock(lock_); | 152 AutoLock auto_lock(lock_); |
| 147 push_source_.Write(data, size); | 153 push_source_.Write(data, size); |
| 148 SubmitOnMoreData_Locked(); | 154 SubmitOnMoreData_Locked(); |
| 149 } | 155 } |
| 150 | 156 |
| 151 void AudioController::DoCreate(AudioManager::Format format, int channels, | 157 void AudioController::DoCreate(AudioManager::Format format, int channels, |
| 152 int sample_rate, int bits_per_sample, | 158 int sample_rate, int bits_per_sample, |
| 153 int hardware_buffer_size) { | 159 uint32 hardware_buffer_size) { |
| 154 // Create the stream in the first place. | 160 // Create the stream in the first place. |
| 155 stream_ = AudioManager::GetAudioManager()->MakeAudioStream( | 161 stream_ = AudioManager::GetAudioManager()->MakeAudioStream( |
| 156 format, channels, sample_rate, bits_per_sample); | 162 format, channels, sample_rate, bits_per_sample); |
| 157 | 163 |
| 158 if (!stream_) { | 164 if (!stream_) { |
| 159 // TODO(hclam): Define error types. | 165 // TODO(hclam): Define error types. |
| 160 handler_->OnError(this, 0); | 166 handler_->OnError(this, 0); |
| 161 return; | 167 return; |
| 162 } | 168 } |
| 163 | 169 |
| 164 if (stream_ && !stream_->Open(hardware_buffer_size)) { | 170 if (stream_ && !stream_->Open(hardware_buffer_size)) { |
| 165 stream_->Close(); | 171 stream_->Close(); |
| 166 stream_ = NULL; | 172 stream_ = NULL; |
| 167 | 173 |
| 168 // TODO(hclam): Define error types. | 174 // TODO(hclam): Define error types. |
| 169 handler_->OnError(this, 0); | 175 handler_->OnError(this, 0); |
| 170 return; | 176 return; |
| 171 } | 177 } |
| 172 handler_->OnCreated(this); | 178 handler_->OnCreated(this); |
| 179 |
| 180 // If in normal latency mode then start buffering. |
| 181 if (!LowLatencyMode()) { |
| 182 AutoLock auto_lock(lock_); |
| 183 SubmitOnMoreData_Locked(); |
| 184 } |
| 173 } | 185 } |
| 174 | 186 |
| 175 void AudioController::DoPlay() { | 187 void AudioController::DoPlay() { |
| 176 DCHECK_EQ(thread_.message_loop(), MessageLoop::current()); | 188 DCHECK_EQ(thread_.message_loop(), MessageLoop::current()); |
| 177 | 189 |
| 178 // We can start from created or paused state. | 190 // We can start from created or paused state. |
| 179 if (state_ != kCreated && state_ != kPaused) | 191 if (state_ != kCreated && state_ != kPaused) |
| 180 return; | 192 return; |
| 181 | 193 |
| 182 State old_state; | 194 State old_state; |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 push_source_.UnProcessedBytes(); | 335 push_source_.UnProcessedBytes(); |
| 324 | 336 |
| 325 // If we need more data then call the event handler to ask for more data. | 337 // If we need more data then call the event handler to ask for more data. |
| 326 // It is okay that we don't lock in this block because the parameters are | 338 // It is okay that we don't lock in this block because the parameters are |
| 327 // correct and in the worst case we are just asking more data than needed. | 339 // correct and in the worst case we are just asking more data than needed. |
| 328 AutoUnlock auto_unlock(lock_); | 340 AutoUnlock auto_unlock(lock_); |
| 329 handler_->OnMoreData(this, timestamp, pending_bytes); | 341 handler_->OnMoreData(this, timestamp, pending_bytes); |
| 330 } | 342 } |
| 331 | 343 |
| 332 } // namespace media | 344 } // namespace media |
| OLD | NEW |