OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/android/opensles_output.h" | 5 #include "media/audio/android/opensles_output.h" |
6 | 6 |
7 #include "base/debug/trace_event.h" | 7 #include "base/debug/trace_event.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "media/audio/android/audio_manager_android.h" | 9 #include "media/audio/android/audio_manager_android.h" |
10 | 10 |
11 #define LOG_ON_FAILURE_AND_RETURN(op, ...) \ | 11 #define LOG_ON_FAILURE_AND_RETURN(op, ...) \ |
12 do { \ | 12 do { \ |
13 SLresult err = (op); \ | 13 SLresult err = (op); \ |
14 if (err != SL_RESULT_SUCCESS) { \ | 14 if (err != SL_RESULT_SUCCESS) { \ |
15 DLOG(ERROR) << #op << " failed: " << err; \ | 15 DLOG(ERROR) << #op << " failed: " << err; \ |
16 return __VA_ARGS__; \ | 16 return __VA_ARGS__; \ |
17 } \ | 17 } \ |
18 } while (0) | 18 } while (0) |
19 | 19 |
20 namespace media { | 20 namespace media { |
21 | 21 |
22 OpenSLESOutputStream::OpenSLESOutputStream(AudioManagerAndroid* manager, | 22 OpenSLESOutputStream::OpenSLESOutputStream(AudioManagerAndroid* manager, |
23 const AudioParameters& params) | 23 const AudioParameters& params) |
24 : audio_manager_(manager), | 24 : audio_manager_(manager), |
25 callback_(NULL), | 25 callback_(NULL), |
26 player_(NULL), | 26 player_(NULL), |
27 simple_buffer_queue_(NULL), | 27 simple_buffer_queue_(NULL), |
28 active_queue_(0), | 28 active_buffer_index_(0), |
29 buffer_size_bytes_(0), | 29 buffer_size_bytes_(0), |
30 started_(false), | 30 started_(false), |
31 volume_(1.0) { | 31 volume_(1.0) { |
32 DVLOG(2) << "OpenSLESOutputStream::OpenSLESOutputStream()"; | |
32 format_.formatType = SL_DATAFORMAT_PCM; | 33 format_.formatType = SL_DATAFORMAT_PCM; |
33 format_.numChannels = static_cast<SLuint32>(params.channels()); | 34 format_.numChannels = static_cast<SLuint32>(params.channels()); |
34 // Provides sampling rate in milliHertz to OpenSLES. | 35 // Provides sampling rate in milliHertz to OpenSLES. |
35 format_.samplesPerSec = static_cast<SLuint32>(params.sample_rate() * 1000); | 36 format_.samplesPerSec = static_cast<SLuint32>(params.sample_rate() * 1000); |
36 format_.bitsPerSample = params.bits_per_sample(); | 37 format_.bitsPerSample = params.bits_per_sample(); |
37 format_.containerSize = params.bits_per_sample(); | 38 format_.containerSize = params.bits_per_sample(); |
38 format_.endianness = SL_BYTEORDER_LITTLEENDIAN; | 39 format_.endianness = SL_BYTEORDER_LITTLEENDIAN; |
39 if (format_.numChannels == 1) | 40 if (format_.numChannels == 1) |
40 format_.channelMask = SL_SPEAKER_FRONT_CENTER; | 41 format_.channelMask = SL_SPEAKER_FRONT_CENTER; |
41 else if (format_.numChannels == 2) | 42 else if (format_.numChannels == 2) |
42 format_.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; | 43 format_.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; |
43 else | 44 else |
44 NOTREACHED() << "Unsupported number of channels: " << format_.numChannels; | 45 NOTREACHED() << "Unsupported number of channels: " << format_.numChannels; |
45 | 46 |
46 buffer_size_bytes_ = params.GetBytesPerBuffer(); | 47 buffer_size_bytes_ = params.GetBytesPerBuffer(); |
47 audio_bus_ = AudioBus::Create(params); | 48 audio_bus_ = AudioBus::Create(params); |
48 | 49 |
49 memset(&audio_data_, 0, sizeof(audio_data_)); | 50 memset(&audio_data_, 0, sizeof(audio_data_)); |
50 } | 51 } |
51 | 52 |
52 OpenSLESOutputStream::~OpenSLESOutputStream() { | 53 OpenSLESOutputStream::~OpenSLESOutputStream() { |
54 DVLOG(2) << "OpenSLESOutputStream::~OpenSLESOutputStream()"; | |
55 DCHECK(thread_checker_.CalledOnValidThread()); | |
53 DCHECK(!engine_object_.Get()); | 56 DCHECK(!engine_object_.Get()); |
54 DCHECK(!player_object_.Get()); | 57 DCHECK(!player_object_.Get()); |
55 DCHECK(!output_mixer_.Get()); | 58 DCHECK(!output_mixer_.Get()); |
56 DCHECK(!player_); | 59 DCHECK(!player_); |
57 DCHECK(!simple_buffer_queue_); | 60 DCHECK(!simple_buffer_queue_); |
58 DCHECK(!audio_data_[0]); | 61 DCHECK(!audio_data_[0]); |
59 } | 62 } |
60 | 63 |
61 bool OpenSLESOutputStream::Open() { | 64 bool OpenSLESOutputStream::Open() { |
65 DVLOG(2) << "OpenSLESOutputStream::Open()"; | |
66 DCHECK(thread_checker_.CalledOnValidThread()); | |
62 if (engine_object_.Get()) | 67 if (engine_object_.Get()) |
63 return false; | 68 return false; |
64 | 69 |
65 if (!CreatePlayer()) | 70 if (!CreatePlayer()) |
66 return false; | 71 return false; |
67 | 72 |
68 SetupAudioBuffer(); | 73 SetupAudioBuffer(); |
74 active_buffer_index_ = 0; | |
69 | 75 |
70 return true; | 76 return true; |
71 } | 77 } |
72 | 78 |
73 void OpenSLESOutputStream::Start(AudioSourceCallback* callback) { | 79 void OpenSLESOutputStream::Start(AudioSourceCallback* callback) { |
80 DVLOG(2) << "OpenSLESOutputStream::Start()"; | |
81 DCHECK(thread_checker_.CalledOnValidThread()); | |
74 DCHECK(callback); | 82 DCHECK(callback); |
75 DCHECK(player_); | 83 DCHECK(player_); |
76 DCHECK(simple_buffer_queue_); | 84 DCHECK(simple_buffer_queue_); |
77 if (started_) | 85 if (started_) |
78 return; | 86 return; |
79 | 87 |
80 // Enable the flags before streaming. | 88 base::AutoLock lock(lock_); |
89 DCHECK(callback_ == NULL || callback_ == callback); | |
81 callback_ = callback; | 90 callback_ = callback; |
82 active_queue_ = 0; | |
83 started_ = true; | |
84 | 91 |
85 // Avoid start-up glitches by filling up one buffer queue before starting | 92 // Avoid start-up glitches by filling up one buffer queue before starting |
86 // the stream. | 93 // the stream. |
87 FillBufferQueue(); | 94 FillBufferQueueNoLock(); |
88 | 95 |
89 // Start streaming data by setting the play state to |SL_PLAYSTATE_PLAYING|. | 96 // Start streaming data by setting the play state to SL_PLAYSTATE_PLAYING. |
97 // For a player object, when the object is in the SL_PLAYSTATE_PLAYING | |
98 // state, adding buffers will implicitly start playback. | |
90 LOG_ON_FAILURE_AND_RETURN( | 99 LOG_ON_FAILURE_AND_RETURN( |
91 (*player_)->SetPlayState(player_, SL_PLAYSTATE_PLAYING)); | 100 (*player_)->SetPlayState(player_, SL_PLAYSTATE_PLAYING)); |
101 | |
102 started_ = true; | |
92 } | 103 } |
93 | 104 |
94 void OpenSLESOutputStream::Stop() { | 105 void OpenSLESOutputStream::Stop() { |
106 DVLOG(2) << "OpenSLESOutputStream::Stop()"; | |
107 DCHECK(thread_checker_.CalledOnValidThread()); | |
95 if (!started_) | 108 if (!started_) |
96 return; | 109 return; |
97 | 110 |
98 started_ = false; | 111 base::AutoLock lock(lock_); |
99 // Stop playing by setting the play state to |SL_PLAYSTATE_STOPPED|. | 112 |
113 // Stop playing by setting the play state to SL_PLAYSTATE_STOPPED. | |
100 LOG_ON_FAILURE_AND_RETURN( | 114 LOG_ON_FAILURE_AND_RETURN( |
101 (*player_)->SetPlayState(player_, SL_PLAYSTATE_STOPPED)); | 115 (*player_)->SetPlayState(player_, SL_PLAYSTATE_STOPPED)); |
102 | 116 |
103 // Clear the buffer queue so that the old data won't be played when | 117 // Clear the buffer queue so that the old data won't be played when |
104 // resuming playing. | 118 // resuming playing. |
105 LOG_ON_FAILURE_AND_RETURN( | 119 LOG_ON_FAILURE_AND_RETURN( |
106 (*simple_buffer_queue_)->Clear(simple_buffer_queue_)); | 120 (*simple_buffer_queue_)->Clear(simple_buffer_queue_)); |
121 | |
122 #ifndef NDEBUG | |
123 // Verify that the buffer queue is in fact cleared as it should. | |
124 SLAndroidSimpleBufferQueueState buffer_queue_state; | |
125 LOG_ON_FAILURE_AND_RETURN((*simple_buffer_queue_)->GetState( | |
126 simple_buffer_queue_, &buffer_queue_state)); | |
127 DCHECK_EQ(0u, buffer_queue_state.count); | |
128 DCHECK_EQ(0u, buffer_queue_state.index); | |
129 #endif | |
130 | |
131 started_ = false; | |
107 } | 132 } |
108 | 133 |
109 void OpenSLESOutputStream::Close() { | 134 void OpenSLESOutputStream::Close() { |
135 DVLOG(2) << "OpenSLESOutputStream::Close()"; | |
136 DCHECK(thread_checker_.CalledOnValidThread()); | |
137 | |
110 // Stop the stream if it is still playing. | 138 // Stop the stream if it is still playing. |
111 Stop(); | 139 Stop(); |
140 { | |
141 // Destroy the buffer queue player object and invalidate all associated | |
142 // interfaces. | |
143 player_object_.Reset(); | |
144 simple_buffer_queue_ = NULL; | |
145 player_ = NULL; | |
112 | 146 |
113 // Explicitly free the player objects and invalidate their associated | 147 // Destroy the mixer object. We don't store any associated interface for |
114 // interfaces. They have to be done in the correct order. | 148 // this object. |
115 player_object_.Reset(); | 149 output_mixer_.Reset(); |
116 output_mixer_.Reset(); | |
117 engine_object_.Reset(); | |
118 simple_buffer_queue_ = NULL; | |
119 player_ = NULL; | |
120 | 150 |
121 ReleaseAudioBuffer(); | 151 // Destroy the engine object. We don't store any associated interface for |
152 // this object. | |
153 engine_object_.Reset(); | |
154 ReleaseAudioBuffer(); | |
155 } | |
122 | 156 |
123 audio_manager_->ReleaseOutputStream(this); | 157 audio_manager_->ReleaseOutputStream(this); |
124 } | 158 } |
125 | 159 |
126 void OpenSLESOutputStream::SetVolume(double volume) { | 160 void OpenSLESOutputStream::SetVolume(double volume) { |
161 DVLOG(2) << "OpenSLESOutputStream::SetVolume(" << volume << ")"; | |
162 DCHECK(thread_checker_.CalledOnValidThread()); | |
127 float volume_float = static_cast<float>(volume); | 163 float volume_float = static_cast<float>(volume); |
128 if (volume_float < 0.0f || volume_float > 1.0f) { | 164 if (volume_float < 0.0f || volume_float > 1.0f) { |
129 return; | 165 return; |
130 } | 166 } |
131 volume_ = volume_float; | 167 volume_ = volume_float; |
132 } | 168 } |
133 | 169 |
134 void OpenSLESOutputStream::GetVolume(double* volume) { | 170 void OpenSLESOutputStream::GetVolume(double* volume) { |
171 DCHECK(thread_checker_.CalledOnValidThread()); | |
135 *volume = static_cast<double>(volume_); | 172 *volume = static_cast<double>(volume_); |
136 } | 173 } |
137 | 174 |
138 bool OpenSLESOutputStream::CreatePlayer() { | 175 bool OpenSLESOutputStream::CreatePlayer() { |
176 DCHECK(thread_checker_.CalledOnValidThread()); | |
177 DCHECK(!engine_object_.Get()); | |
178 DCHECK(!player_object_.Get()); | |
179 DCHECK(!output_mixer_.Get()); | |
180 DCHECK(!player_); | |
181 DCHECK(!simple_buffer_queue_); | |
182 | |
139 // Initializes the engine object with specific option. After working with the | 183 // Initializes the engine object with specific option. After working with the |
140 // object, we need to free the object and its resources. | 184 // object, we need to free the object and its resources. |
141 SLEngineOption option[] = { | 185 SLEngineOption option[] = { |
142 { SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE) } | 186 {SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE)}}; |
143 }; | |
144 LOG_ON_FAILURE_AND_RETURN( | 187 LOG_ON_FAILURE_AND_RETURN( |
145 slCreateEngine(engine_object_.Receive(), 1, option, 0, NULL, NULL), | 188 slCreateEngine(engine_object_.Receive(), 1, option, 0, NULL, NULL), |
146 false); | 189 false); |
147 | 190 |
148 // Realize the SL engine object in synchronous mode. | 191 // Realize the SL engine object in synchronous mode. |
149 LOG_ON_FAILURE_AND_RETURN( | 192 LOG_ON_FAILURE_AND_RETURN( |
150 engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE), | 193 engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE), false); |
151 false); | |
152 | 194 |
153 // Get the SL engine interface which is implicit. | 195 // Get the SL engine interface which is implicit. |
154 SLEngineItf engine; | 196 SLEngineItf engine; |
155 LOG_ON_FAILURE_AND_RETURN( | 197 LOG_ON_FAILURE_AND_RETURN(engine_object_->GetInterface( |
156 engine_object_->GetInterface(engine_object_.Get(), | 198 engine_object_.Get(), SL_IID_ENGINE, &engine), |
157 SL_IID_ENGINE, | 199 false); |
158 &engine), | |
159 false); | |
160 | 200 |
161 // Create ouput mixer object to be used by the player. | 201 // Create ouput mixer object to be used by the player. |
162 LOG_ON_FAILURE_AND_RETURN( | 202 LOG_ON_FAILURE_AND_RETURN((*engine)->CreateOutputMix( |
163 (*engine)->CreateOutputMix(engine, | 203 engine, output_mixer_.Receive(), 0, NULL, NULL), |
164 output_mixer_.Receive(), | 204 false); |
165 0, | |
166 NULL, | |
167 NULL), | |
168 false); | |
169 | 205 |
170 // Realizing the output mix object in synchronous mode. | 206 // Realizing the output mix object in synchronous mode. |
171 LOG_ON_FAILURE_AND_RETURN( | 207 LOG_ON_FAILURE_AND_RETURN( |
172 output_mixer_->Realize(output_mixer_.Get(), SL_BOOLEAN_FALSE), | 208 output_mixer_->Realize(output_mixer_.Get(), SL_BOOLEAN_FALSE), false); |
173 false); | |
174 | 209 |
175 // Audio source configuration. | 210 // Audio source configuration. |
176 SLDataLocator_AndroidSimpleBufferQueue simple_buffer_queue = { | 211 SLDataLocator_AndroidSimpleBufferQueue simple_buffer_queue = { |
177 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, | 212 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, |
178 static_cast<SLuint32>(kNumOfQueuesInBuffer) | 213 static_cast<SLuint32>(kMaxNumOfBuffersInQueue)}; |
179 }; | 214 SLDataSource audio_source = {&simple_buffer_queue, &format_}; |
180 SLDataSource audio_source = { &simple_buffer_queue, &format_ }; | |
181 | 215 |
182 // Audio sink configuration. | 216 // Audio sink configuration. |
183 SLDataLocator_OutputMix locator_output_mix = { | 217 SLDataLocator_OutputMix locator_output_mix = {SL_DATALOCATOR_OUTPUTMIX, |
184 SL_DATALOCATOR_OUTPUTMIX, output_mixer_.Get() | 218 output_mixer_.Get()}; |
185 }; | 219 SLDataSink audio_sink = {&locator_output_mix, NULL}; |
186 SLDataSink audio_sink = { &locator_output_mix, NULL }; | |
187 | 220 |
188 // Create an audio player. | 221 // Create an audio player. |
189 const SLInterfaceID interface_id[] = { | 222 const SLInterfaceID interface_id[] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME, |
190 SL_IID_BUFFERQUEUE, | 223 SL_IID_ANDROIDCONFIGURATION}; |
191 SL_IID_VOLUME, | 224 const SLboolean interface_required[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, |
192 SL_IID_ANDROIDCONFIGURATION | 225 SL_BOOLEAN_TRUE}; |
193 }; | |
194 const SLboolean interface_required[] = { | |
195 SL_BOOLEAN_TRUE, | |
196 SL_BOOLEAN_TRUE, | |
197 SL_BOOLEAN_TRUE | |
198 }; | |
199 LOG_ON_FAILURE_AND_RETURN( | 226 LOG_ON_FAILURE_AND_RETURN( |
200 (*engine)->CreateAudioPlayer(engine, | 227 (*engine)->CreateAudioPlayer(engine, |
201 player_object_.Receive(), | 228 player_object_.Receive(), |
202 &audio_source, | 229 &audio_source, |
203 &audio_sink, | 230 &audio_sink, |
204 arraysize(interface_id), | 231 arraysize(interface_id), |
205 interface_id, | 232 interface_id, |
206 interface_required), | 233 interface_required), |
207 false); | 234 false); |
208 | 235 |
209 // Create AudioPlayer and specify SL_IID_ANDROIDCONFIGURATION. | 236 // Create AudioPlayer and specify SL_IID_ANDROIDCONFIGURATION. |
210 SLAndroidConfigurationItf player_config; | 237 SLAndroidConfigurationItf player_config; |
211 LOG_ON_FAILURE_AND_RETURN( | 238 LOG_ON_FAILURE_AND_RETURN( |
212 player_object_->GetInterface(player_object_.Get(), | 239 player_object_->GetInterface( |
213 SL_IID_ANDROIDCONFIGURATION, | 240 player_object_.Get(), SL_IID_ANDROIDCONFIGURATION, &player_config), |
214 &player_config), | |
215 false); | 241 false); |
216 | 242 |
217 SLint32 stream_type = SL_ANDROID_STREAM_VOICE; | 243 SLint32 stream_type = SL_ANDROID_STREAM_VOICE; |
218 LOG_ON_FAILURE_AND_RETURN( | 244 LOG_ON_FAILURE_AND_RETURN( |
219 (*player_config)->SetConfiguration(player_config, | 245 (*player_config)->SetConfiguration(player_config, |
220 SL_ANDROID_KEY_STREAM_TYPE, | 246 SL_ANDROID_KEY_STREAM_TYPE, |
221 &stream_type, sizeof(SLint32)), | 247 &stream_type, |
248 sizeof(SLint32)), | |
222 false); | 249 false); |
223 | 250 |
224 // Realize the player object in synchronous mode. | 251 // Realize the player object in synchronous mode. |
225 LOG_ON_FAILURE_AND_RETURN( | 252 LOG_ON_FAILURE_AND_RETURN( |
226 player_object_->Realize(player_object_.Get(), SL_BOOLEAN_FALSE), | 253 player_object_->Realize(player_object_.Get(), SL_BOOLEAN_FALSE), false); |
227 false); | |
228 | 254 |
229 // Get an implicit player interface. | 255 // Get an implicit player interface. |
230 LOG_ON_FAILURE_AND_RETURN( | 256 LOG_ON_FAILURE_AND_RETURN( |
231 player_object_->GetInterface(player_object_.Get(), SL_IID_PLAY, &player_), | 257 player_object_->GetInterface(player_object_.Get(), SL_IID_PLAY, &player_), |
232 false); | 258 false); |
233 | 259 |
234 // Get the simple buffer queue interface. | 260 // Get the simple buffer queue interface. |
235 LOG_ON_FAILURE_AND_RETURN( | 261 LOG_ON_FAILURE_AND_RETURN( |
236 player_object_->GetInterface(player_object_.Get(), | 262 player_object_->GetInterface( |
237 SL_IID_BUFFERQUEUE, | 263 player_object_.Get(), SL_IID_BUFFERQUEUE, &simple_buffer_queue_), |
238 &simple_buffer_queue_), | |
239 false); | 264 false); |
240 | 265 |
241 // Register the input callback for the simple buffer queue. | 266 // Register the input callback for the simple buffer queue. |
242 // This callback will be called when the soundcard needs data. | 267 // This callback will be called when the soundcard needs data. |
243 LOG_ON_FAILURE_AND_RETURN( | 268 LOG_ON_FAILURE_AND_RETURN( |
244 (*simple_buffer_queue_)->RegisterCallback(simple_buffer_queue_, | 269 (*simple_buffer_queue_)->RegisterCallback( |
245 SimpleBufferQueueCallback, | 270 simple_buffer_queue_, SimpleBufferQueueCallback, this), |
246 this), | |
247 false); | 271 false); |
248 | 272 |
249 return true; | 273 return true; |
250 } | 274 } |
251 | 275 |
252 void OpenSLESOutputStream::SimpleBufferQueueCallback( | 276 void OpenSLESOutputStream::SimpleBufferQueueCallback( |
253 SLAndroidSimpleBufferQueueItf buffer_queue, void* instance) { | 277 SLAndroidSimpleBufferQueueItf buffer_queue, |
278 void* instance) { | |
254 OpenSLESOutputStream* stream = | 279 OpenSLESOutputStream* stream = |
255 reinterpret_cast<OpenSLESOutputStream*>(instance); | 280 reinterpret_cast<OpenSLESOutputStream*>(instance); |
256 stream->FillBufferQueue(); | 281 stream->FillBufferQueue(); |
257 } | 282 } |
258 | 283 |
259 void OpenSLESOutputStream::FillBufferQueue() { | 284 void OpenSLESOutputStream::FillBufferQueue() { |
260 if (!started_) | 285 base::AutoLock lock(lock_); |
286 if (!player_) | |
wjia(left Chromium)
2013/09/07 17:09:36
|started_| is a better flag used here than |player
henrika (OOO until Aug 14)
2013/09/10 11:17:18
Done.
| |
261 return; | 287 return; |
262 | 288 |
263 TRACE_EVENT0("audio", "OpenSLESOutputStream::FillBufferQueue"); | 289 TRACE_EVENT0("audio", "OpenSLESOutputStream::FillBufferQueue"); |
290 | |
291 // Verify that we are in a playing state. | |
292 SLuint32 state; | |
293 SLresult err = (*player_)->GetPlayState(player_, &state); | |
294 if (SL_RESULT_SUCCESS != err) { | |
295 HandleError(err); | |
296 return; | |
297 } | |
298 if (state != SL_PLAYSTATE_PLAYING) { | |
299 DLOG(WARNING) << "Received callback in non-playing state"; | |
300 return; | |
301 } | |
302 | |
303 // Fill up one buffer in the queue by asking the registered source for | |
304 // data using the OnMoreData() callback. | |
305 FillBufferQueueNoLock(); | |
306 } | |
307 | |
308 void OpenSLESOutputStream::FillBufferQueueNoLock() { | |
309 // Ensure that the calling thread has acquired the lock since it is not | |
310 // done in this method. | |
311 lock_.AssertAcquired(); | |
312 | |
264 // Read data from the registered client source. | 313 // Read data from the registered client source. |
265 // TODO(xians): Get an accurate delay estimation. | 314 // TODO(henrika): Investigate if it is possible to get a more accurate |
266 uint32 hardware_delay = buffer_size_bytes_; | 315 // delay estimation. |
316 const uint32 hardware_delay = buffer_size_bytes_; | |
267 int frames_filled = callback_->OnMoreData( | 317 int frames_filled = callback_->OnMoreData( |
268 audio_bus_.get(), AudioBuffersState(0, hardware_delay)); | 318 audio_bus_.get(), AudioBuffersState(0, hardware_delay)); |
269 if (frames_filled <= 0) | 319 if (frames_filled <= 0) { |
270 return; // Audio source is shutting down, or halted on error. | 320 // Audio source is shutting down, or halted on error. |
271 int num_filled_bytes = | 321 return; |
322 } | |
323 | |
324 // Note: If the internal representation ever changes from 16-bit PCM to | |
325 // raw float, the data must be clipped and sanitized since it may come | |
326 // from an untrusted source such as NaCl. | |
327 audio_bus_->Scale(volume_); | |
328 audio_bus_->ToInterleaved(frames_filled, | |
329 format_.bitsPerSample / 8, | |
330 audio_data_[active_buffer_index_]); | |
331 | |
332 const int num_filled_bytes = | |
272 frames_filled * audio_bus_->channels() * format_.bitsPerSample / 8; | 333 frames_filled * audio_bus_->channels() * format_.bitsPerSample / 8; |
273 DCHECK_LE(static_cast<size_t>(num_filled_bytes), buffer_size_bytes_); | 334 DCHECK_LE(static_cast<size_t>(num_filled_bytes), buffer_size_bytes_); |
274 // Note: If this ever changes to output raw float the data must be clipped and | |
275 // sanitized since it may come from an untrusted source such as NaCl. | |
276 audio_bus_->Scale(volume_); | |
277 audio_bus_->ToInterleaved( | |
278 frames_filled, format_.bitsPerSample / 8, audio_data_[active_queue_]); | |
279 | 335 |
280 // Enqueue the buffer for playback. | 336 // Enqueue the buffer for playback. |
281 SLresult err = (*simple_buffer_queue_)->Enqueue( | 337 SLresult err = |
282 simple_buffer_queue_, | 338 (*simple_buffer_queue_)->Enqueue(simple_buffer_queue_, |
283 audio_data_[active_queue_], | 339 audio_data_[active_buffer_index_], |
284 num_filled_bytes); | 340 num_filled_bytes); |
285 if (SL_RESULT_SUCCESS != err) | 341 if (SL_RESULT_SUCCESS != err) |
286 HandleError(err); | 342 HandleError(err); |
287 | 343 |
288 active_queue_ = (active_queue_ + 1) % kNumOfQueuesInBuffer; | 344 active_buffer_index_ = (active_buffer_index_ + 1) % kMaxNumOfBuffersInQueue; |
289 } | 345 } |
290 | 346 |
291 void OpenSLESOutputStream::SetupAudioBuffer() { | 347 void OpenSLESOutputStream::SetupAudioBuffer() { |
348 DCHECK(thread_checker_.CalledOnValidThread()); | |
292 DCHECK(!audio_data_[0]); | 349 DCHECK(!audio_data_[0]); |
293 for (int i = 0; i < kNumOfQueuesInBuffer; ++i) { | 350 for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) { |
294 audio_data_[i] = new uint8[buffer_size_bytes_]; | 351 audio_data_[i] = new uint8[buffer_size_bytes_]; |
295 } | 352 } |
296 } | 353 } |
297 | 354 |
298 void OpenSLESOutputStream::ReleaseAudioBuffer() { | 355 void OpenSLESOutputStream::ReleaseAudioBuffer() { |
356 DCHECK(thread_checker_.CalledOnValidThread()); | |
299 if (audio_data_[0]) { | 357 if (audio_data_[0]) { |
300 for (int i = 0; i < kNumOfQueuesInBuffer; ++i) { | 358 for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) { |
301 delete [] audio_data_[i]; | 359 delete[] audio_data_[i]; |
302 audio_data_[i] = NULL; | 360 audio_data_[i] = NULL; |
303 } | 361 } |
304 } | 362 } |
305 } | 363 } |
306 | 364 |
307 void OpenSLESOutputStream::HandleError(SLresult error) { | 365 void OpenSLESOutputStream::HandleError(SLresult error) { |
308 DLOG(ERROR) << "OpenSLES Output error " << error; | 366 DLOG(ERROR) << "OpenSLES Output error " << error; |
309 if (callback_) | 367 if (callback_) |
310 callback_->OnError(this); | 368 callback_->OnError(this); |
311 } | 369 } |
312 | 370 |
313 } // namespace media | 371 } // namespace media |
OLD | NEW |