Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(536)

Side by Side Diff: media/audio/android/opensles_output.cc

Issue 23296008: Adding audio unit tests for Android (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: dalecurtis@ Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698