| 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_output_controller.h" | 5 #include "media/audio/audio_output_controller.h" |
| 6 | 6 |
| 7 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
| 8 | 8 |
| 9 // The following parameters limit the request buffer and packet size from the | |
| 10 // renderer to avoid renderer from requesting too much memory. | |
| 11 static const uint32 kMegabytes = 1024 * 1024; | |
| 12 static const uint32 kMaxHardwareBufferSize = 2 * kMegabytes; | |
| 13 // Signal a pause in low-latency mode. | 9 // Signal a pause in low-latency mode. |
| 14 static const int kPauseMark = -1; | 10 static const int kPauseMark = -1; |
| 15 | 11 |
| 16 namespace { | 12 namespace { |
| 17 // Return true if the parameters for creating an audio stream is valid. | 13 // Return true if the parameters for creating an audio stream is valid. |
| 18 // Return false otherwise. | 14 // Return false otherwise. |
| 19 static bool CheckParameters(AudioParameters params, | 15 static bool CheckParameters(AudioParameters params) { |
| 20 uint32 hardware_buffer_size) { | |
| 21 if (!params.IsValid()) | 16 if (!params.IsValid()) |
| 22 return false; | 17 return false; |
| 23 if (hardware_buffer_size <= 0 || | |
| 24 hardware_buffer_size > kMaxHardwareBufferSize) | |
| 25 return false; | |
| 26 return true; | 18 return true; |
| 27 } | 19 } |
| 28 | 20 |
| 29 } // namespace | 21 } // namespace |
| 30 | 22 |
| 31 namespace media { | 23 namespace media { |
| 32 | 24 |
| 33 AudioOutputController::AudioOutputController(EventHandler* handler, | 25 AudioOutputController::AudioOutputController(EventHandler* handler, |
| 34 uint32 capacity, | 26 uint32 capacity, |
| 35 SyncReader* sync_reader) | 27 SyncReader* sync_reader) |
| 36 : handler_(handler), | 28 : handler_(handler), |
| 37 stream_(NULL), | 29 stream_(NULL), |
| 38 volume_(1.0), | 30 volume_(1.0), |
| 39 state_(kEmpty), | 31 state_(kEmpty), |
| 40 buffer_(0, capacity), | 32 buffer_(0, capacity), |
| 41 pending_request_(false), | 33 pending_request_(false), |
| 42 sync_reader_(sync_reader), | 34 sync_reader_(sync_reader), |
| 43 message_loop_(NULL) { | 35 message_loop_(NULL) { |
| 44 } | 36 } |
| 45 | 37 |
| 46 AudioOutputController::~AudioOutputController() { | 38 AudioOutputController::~AudioOutputController() { |
| 47 DCHECK(kClosed == state_); | 39 DCHECK(kClosed == state_); |
| 48 } | 40 } |
| 49 | 41 |
| 50 // static | 42 // static |
| 51 scoped_refptr<AudioOutputController> AudioOutputController::Create( | 43 scoped_refptr<AudioOutputController> AudioOutputController::Create( |
| 52 EventHandler* event_handler, | 44 EventHandler* event_handler, |
| 53 AudioParameters params, | 45 AudioParameters params, |
| 54 uint32 hardware_buffer_size, | |
| 55 uint32 buffer_capacity) { | 46 uint32 buffer_capacity) { |
| 56 | 47 |
| 57 if (!CheckParameters(params, hardware_buffer_size)) | 48 if (!CheckParameters(params)) |
| 58 return NULL; | 49 return NULL; |
| 59 | 50 |
| 60 // Starts the audio controller thread. | 51 // Starts the audio controller thread. |
| 61 scoped_refptr<AudioOutputController> controller(new AudioOutputController( | 52 scoped_refptr<AudioOutputController> controller(new AudioOutputController( |
| 62 event_handler, buffer_capacity, NULL)); | 53 event_handler, buffer_capacity, NULL)); |
| 63 | 54 |
| 64 controller->message_loop_ = | 55 controller->message_loop_ = |
| 65 AudioManager::GetAudioManager()->GetMessageLoop(); | 56 AudioManager::GetAudioManager()->GetMessageLoop(); |
| 66 controller->message_loop_->PostTask( | 57 controller->message_loop_->PostTask( |
| 67 FROM_HERE, | 58 FROM_HERE, |
| 68 NewRunnableMethod(controller.get(), &AudioOutputController::DoCreate, | 59 NewRunnableMethod(controller.get(), &AudioOutputController::DoCreate, |
| 69 params, hardware_buffer_size)); | 60 params)); |
| 70 return controller; | 61 return controller; |
| 71 } | 62 } |
| 72 | 63 |
| 73 // static | 64 // static |
| 74 scoped_refptr<AudioOutputController> AudioOutputController::CreateLowLatency( | 65 scoped_refptr<AudioOutputController> AudioOutputController::CreateLowLatency( |
| 75 EventHandler* event_handler, | 66 EventHandler* event_handler, |
| 76 AudioParameters params, | 67 AudioParameters params, |
| 77 uint32 hardware_buffer_size, | |
| 78 SyncReader* sync_reader) { | 68 SyncReader* sync_reader) { |
| 79 | 69 |
| 80 DCHECK(sync_reader); | 70 DCHECK(sync_reader); |
| 81 | 71 |
| 82 if (!CheckParameters(params, hardware_buffer_size)) | 72 if (!CheckParameters(params)) |
| 83 return NULL; | 73 return NULL; |
| 84 | 74 |
| 85 // Starts the audio controller thread. | 75 // Starts the audio controller thread. |
| 86 scoped_refptr<AudioOutputController> controller(new AudioOutputController( | 76 scoped_refptr<AudioOutputController> controller(new AudioOutputController( |
| 87 event_handler, 0, sync_reader)); | 77 event_handler, 0, sync_reader)); |
| 88 | 78 |
| 89 controller->message_loop_ = | 79 controller->message_loop_ = |
| 90 AudioManager::GetAudioManager()->GetMessageLoop(); | 80 AudioManager::GetAudioManager()->GetMessageLoop(); |
| 91 controller->message_loop_->PostTask( | 81 controller->message_loop_->PostTask( |
| 92 FROM_HERE, | 82 FROM_HERE, |
| 93 NewRunnableMethod(controller.get(), &AudioOutputController::DoCreate, | 83 NewRunnableMethod(controller.get(), &AudioOutputController::DoCreate, |
| 94 params, hardware_buffer_size)); | 84 params)); |
| 95 return controller; | 85 return controller; |
| 96 } | 86 } |
| 97 | 87 |
| 98 void AudioOutputController::Play() { | 88 void AudioOutputController::Play() { |
| 99 DCHECK(message_loop_); | 89 DCHECK(message_loop_); |
| 100 message_loop_->PostTask( | 90 message_loop_->PostTask( |
| 101 FROM_HERE, | 91 FROM_HERE, |
| 102 NewRunnableMethod(this, &AudioOutputController::DoPlay)); | 92 NewRunnableMethod(this, &AudioOutputController::DoPlay)); |
| 103 } | 93 } |
| 104 | 94 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 pending_request_ = false; | 127 pending_request_ = false; |
| 138 // If |size| is set to 0, it indicates that the audio source doesn't have | 128 // If |size| is set to 0, it indicates that the audio source doesn't have |
| 139 // more data right now, and so it doesn't make sense to send additional | 129 // more data right now, and so it doesn't make sense to send additional |
| 140 // request. | 130 // request. |
| 141 if (size) { | 131 if (size) { |
| 142 buffer_.Append(data, size); | 132 buffer_.Append(data, size); |
| 143 SubmitOnMoreData_Locked(); | 133 SubmitOnMoreData_Locked(); |
| 144 } | 134 } |
| 145 } | 135 } |
| 146 | 136 |
| 147 void AudioOutputController::DoCreate(AudioParameters params, | 137 void AudioOutputController::DoCreate(AudioParameters params) { |
| 148 uint32 hardware_buffer_size) { | |
| 149 DCHECK_EQ(message_loop_, MessageLoop::current()); | 138 DCHECK_EQ(message_loop_, MessageLoop::current()); |
| 150 | 139 |
| 151 // Close() can be called before DoCreate() is executed. | 140 // Close() can be called before DoCreate() is executed. |
| 152 if (state_ == kClosed) | 141 if (state_ == kClosed) |
| 153 return; | 142 return; |
| 154 DCHECK(state_ == kEmpty); | 143 DCHECK(state_ == kEmpty); |
| 155 | 144 |
| 156 stream_ = AudioManager::GetAudioManager()->MakeAudioOutputStream(params); | 145 stream_ = AudioManager::GetAudioManager()->MakeAudioOutputStream(params); |
| 157 if (!stream_) { | 146 if (!stream_) { |
| 158 // TODO(hclam): Define error types. | 147 // TODO(hclam): Define error types. |
| 159 handler_->OnError(this, 0); | 148 handler_->OnError(this, 0); |
| 160 return; | 149 return; |
| 161 } | 150 } |
| 162 | 151 |
| 163 if (!stream_->Open(hardware_buffer_size)) { | 152 if (!stream_->Open()) { |
| 164 stream_->Close(); | 153 stream_->Close(); |
| 165 stream_ = NULL; | 154 stream_ = NULL; |
| 166 | 155 |
| 167 // TODO(hclam): Define error types. | 156 // TODO(hclam): Define error types. |
| 168 handler_->OnError(this, 0); | 157 handler_->OnError(this, 0); |
| 169 return; | 158 return; |
| 170 } | 159 } |
| 160 |
| 171 // We have successfully opened the stream. Set the initial volume. | 161 // We have successfully opened the stream. Set the initial volume. |
| 172 stream_->SetVolume(volume_); | 162 stream_->SetVolume(volume_); |
| 173 | 163 |
| 174 // Finally set the state to kCreated. | 164 // Finally set the state to kCreated. |
| 175 state_ = kCreated; | 165 state_ = kCreated; |
| 176 | 166 |
| 177 // And then report we have been created. | 167 // And then report we have been created. |
| 178 handler_->OnCreated(this); | 168 handler_->OnCreated(this); |
| 179 | 169 |
| 180 // If in normal latency mode then start buffering. | 170 // If in normal latency mode then start buffering. |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 if (state_ != kClosed) { | 229 if (state_ != kClosed) { |
| 240 // |stream_| can be null if creating the device failed in DoCreate(). | 230 // |stream_| can be null if creating the device failed in DoCreate(). |
| 241 if (stream_) { | 231 if (stream_) { |
| 242 stream_->Stop(); | 232 stream_->Stop(); |
| 243 stream_->Close(); | 233 stream_->Close(); |
| 244 // After stream is closed it is destroyed, so don't keep a reference to | 234 // After stream is closed it is destroyed, so don't keep a reference to |
| 245 // it. | 235 // it. |
| 246 stream_ = NULL; | 236 stream_ = NULL; |
| 247 } | 237 } |
| 248 | 238 |
| 239 if (LowLatencyMode()) { |
| 240 sync_reader_->Close(); |
| 241 } |
| 242 |
| 249 state_ = kClosed; | 243 state_ = kClosed; |
| 250 } | 244 } |
| 251 | 245 |
| 252 closed_task->Run(); | 246 closed_task->Run(); |
| 253 delete closed_task; | 247 delete closed_task; |
| 254 } | 248 } |
| 255 | 249 |
| 256 void AudioOutputController::DoSetVolume(double volume) { | 250 void AudioOutputController::DoSetVolume(double volume) { |
| 257 DCHECK_EQ(message_loop_, MessageLoop::current()); | 251 DCHECK_EQ(message_loop_, MessageLoop::current()); |
| 258 | 252 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 SubmitOnMoreData_Locked(); | 286 SubmitOnMoreData_Locked(); |
| 293 return size; | 287 return size; |
| 294 } | 288 } |
| 295 | 289 |
| 296 // Low latency mode. | 290 // Low latency mode. |
| 297 uint32 size = sync_reader_->Read(dest, max_size); | 291 uint32 size = sync_reader_->Read(dest, max_size); |
| 298 sync_reader_->UpdatePendingBytes(buffers_state.total_bytes() + size); | 292 sync_reader_->UpdatePendingBytes(buffers_state.total_bytes() + size); |
| 299 return size; | 293 return size; |
| 300 } | 294 } |
| 301 | 295 |
| 302 void AudioOutputController::OnClose(AudioOutputStream* stream) { | |
| 303 DCHECK_EQ(message_loop_, MessageLoop::current()); | |
| 304 | |
| 305 // Push source doesn't need to know the stream so just pass in NULL. | |
| 306 if (LowLatencyMode()) { | |
| 307 sync_reader_->Close(); | |
| 308 } | |
| 309 } | |
| 310 | |
| 311 void AudioOutputController::OnError(AudioOutputStream* stream, int code) { | 296 void AudioOutputController::OnError(AudioOutputStream* stream, int code) { |
| 312 // Handle error on the audio controller thread. | 297 // Handle error on the audio controller thread. |
| 313 message_loop_->PostTask( | 298 message_loop_->PostTask( |
| 314 FROM_HERE, | 299 FROM_HERE, |
| 315 NewRunnableMethod(this, &AudioOutputController::DoReportError, code)); | 300 NewRunnableMethod(this, &AudioOutputController::DoReportError, code)); |
| 316 } | 301 } |
| 317 | 302 |
| 318 void AudioOutputController::SubmitOnMoreData_Locked() { | 303 void AudioOutputController::SubmitOnMoreData_Locked() { |
| 319 lock_.AssertAcquired(); | 304 lock_.AssertAcquired(); |
| 320 | 305 |
| 321 if (buffer_.forward_bytes() > buffer_.forward_capacity()) | 306 if (buffer_.forward_bytes() > buffer_.forward_capacity()) |
| 322 return; | 307 return; |
| 323 | 308 |
| 324 if (pending_request_) | 309 if (pending_request_) |
| 325 return; | 310 return; |
| 326 pending_request_ = true; | 311 pending_request_ = true; |
| 327 | 312 |
| 328 AudioBuffersState buffers_state = buffers_state_; | 313 AudioBuffersState buffers_state = buffers_state_; |
| 329 buffers_state.pending_bytes += buffer_.forward_bytes(); | 314 buffers_state.pending_bytes += buffer_.forward_bytes(); |
| 330 | 315 |
| 331 // If we need more data then call the event handler to ask for more data. | 316 // If we need more data then call the event handler to ask for more data. |
| 332 // It is okay that we don't lock in this block because the parameters are | 317 // It is okay that we don't lock in this block because the parameters are |
| 333 // correct and in the worst case we are just asking more data than needed. | 318 // correct and in the worst case we are just asking more data than needed. |
| 334 AutoUnlock auto_unlock(lock_); | 319 AutoUnlock auto_unlock(lock_); |
| 335 handler_->OnMoreData(this, buffers_state); | 320 handler_->OnMoreData(this, buffers_state); |
| 336 } | 321 } |
| 337 | 322 |
| 338 } // namespace media | 323 } // namespace media |
| OLD | NEW |