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 |