blob: 88eb783339451b35fdfd75685eed8bf90c4bdb1b [file] [log] [blame]
Hugo Hudsonb83ad732011-07-14 23:31:17 +01001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <variablespeed.h>
18
19#include <unistd.h>
20#include <stdlib.h>
21
22#include <sola_time_scaler.h>
23#include <ring_buffer.h>
24
25#include <hlogging.h>
26
27#include <vector>
28
Flavio Lerdae8638162011-09-02 16:40:13 +010029#include <sys/system_properties.h>
30
Hugo Hudsonb83ad732011-07-14 23:31:17 +010031// ****************************************************************************
32// Constants, utility methods, structures and other miscellany used throughout
33// this file.
34
35namespace {
36
37// These variables are used to determine the size of the buffer queue used by
38// the decoder.
39// This is not the same as the large buffer used to hold the uncompressed data
40// - for that see the member variable decodeBuffer_.
41// The choice of 1152 corresponds to the number of samples per mp3 frame, so is
42// a good choice of size for a decoding buffer in the absence of other
43// information (we don't know exactly what formats we will be working with).
44const size_t kNumberOfBuffersInQueue = 4;
45const size_t kNumberOfSamplesPerBuffer = 1152;
46const size_t kBufferSizeInBytes = 2 * kNumberOfSamplesPerBuffer;
47const size_t kSampleSizeInBytes = 4;
48
Hugo Hudson0bd6ec52011-07-26 20:05:25 +010049// Keys used when extracting metadata from the decoder.
50// TODO: Remove these constants once they are part of OpenSLES_Android.h.
51const char* kKeyPcmFormatNumChannels = "AndroidPcmFormatNumChannels";
52const char* kKeyPcmFormatSamplesPerSec = "AndroidPcmFormatSamplesPerSec";
53
Hugo Hudsonb83ad732011-07-14 23:31:17 +010054// When calculating play buffer size before pushing to audio player.
55const size_t kNumberOfBytesPerInt16 = 2;
56
57// How long to sleep during the main play loop and the decoding callback loop.
58// In due course this should be replaced with the better signal and wait on
59// condition rather than busy-looping.
60const int kSleepTimeMicros = 1000;
61
62// Used in detecting errors with the OpenSL ES framework.
63const SLuint32 kPrefetchErrorCandidate =
64 SL_PREFETCHEVENT_STATUSCHANGE | SL_PREFETCHEVENT_FILLLEVELCHANGE;
65
66// Structure used when we perform a decoding callback.
67typedef struct CallbackContext_ {
Hugo Hudson0bd6ec52011-07-26 20:05:25 +010068 // Pointer to local storage buffers for decoded audio data.
69 int8_t* pDataBase;
70 // Pointer to the current buffer within local storage.
71 int8_t* pData;
72 // Used to read the sample rate and channels from the decoding stream during
73 // the first decoding callback.
74 SLMetadataExtractionItf decoderMetadata;
75 // The play interface used for reading duration.
76 SLPlayItf playItf;
Hugo Hudsonb83ad732011-07-14 23:31:17 +010077} CallbackContext;
78
79// Local storage for decoded audio data.
80int8_t pcmData[kNumberOfBuffersInQueue * kBufferSizeInBytes];
81
82#define CheckSLResult(message, result) \
83 CheckSLResult_Real(message, result, __LINE__)
84
85// Helper function for debugging - checks the OpenSL result for success.
86void CheckSLResult_Real(const char* message, SLresult result, int line) {
87 // This can be helpful when debugging.
88 // LOGD("sl result %d for %s", result, message);
89 if (SL_RESULT_SUCCESS != result) {
90 LOGE("slresult was %d at %s file variablespeed line %d",
91 static_cast<int>(result), message, line);
92 }
93 CHECK(SL_RESULT_SUCCESS == result);
94}
95
Flavio Lerdae8638162011-09-02 16:40:13 +010096// Whether logging should be enabled. Only used if LOG_OPENSL_API_CALL is
97// defined to use it.
98bool gLogEnabled = false;
99// The property to set in order to enable logging.
100const char *const kLogTagVariableSpeed = "log.tag.VariableSpeed";
101
102bool ShouldLog() {
103 char buffer[PROP_VALUE_MAX];
104 __system_property_get(kLogTagVariableSpeed, buffer);
105 return strlen(buffer) > 0;
106}
107
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100108} // namespace
109
110// ****************************************************************************
111// Static instance of audio engine, and methods for getting, setting and
112// deleting it.
113
114// The single global audio engine instance.
115AudioEngine* AudioEngine::audioEngine_ = NULL;
116android::Mutex publishEngineLock_;
117
118AudioEngine* AudioEngine::GetEngine() {
119 android::Mutex::Autolock autoLock(publishEngineLock_);
120 if (audioEngine_ == NULL) {
121 LOGE("you haven't initialized the audio engine");
122 CHECK(false);
123 return NULL;
124 }
125 return audioEngine_;
126}
127
128void AudioEngine::SetEngine(AudioEngine* engine) {
129 if (audioEngine_ != NULL) {
130 LOGE("you have already set the audio engine");
131 CHECK(false);
132 return;
133 }
134 audioEngine_ = engine;
135}
136
137void AudioEngine::DeleteEngine() {
138 if (audioEngine_ == NULL) {
139 LOGE("you haven't initialized the audio engine");
140 CHECK(false);
141 return;
142 }
143 delete audioEngine_;
144 audioEngine_ = NULL;
145}
146
147// ****************************************************************************
148// The callbacks from the engine require static callback functions.
149// Here are the static functions - they just delegate to instance methods on
150// the engine.
151
152static void PlayingBufferQueueCb(SLAndroidSimpleBufferQueueItf, void*) {
153 AudioEngine::GetEngine()->PlayingBufferQueueCallback();
154}
155
156static void PrefetchEventCb(SLPrefetchStatusItf caller, void*, SLuint32 event) {
157 AudioEngine::GetEngine()->PrefetchEventCallback(caller, event);
158}
159
160static void DecodingBufferQueueCb(SLAndroidSimpleBufferQueueItf queueItf,
161 void *context) {
162 AudioEngine::GetEngine()->DecodingBufferQueueCallback(queueItf, context);
163}
164
165static void DecodingEventCb(SLPlayItf caller, void*, SLuint32 event) {
166 AudioEngine::GetEngine()->DecodingEventCallback(caller, event);
167}
168
169// ****************************************************************************
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100170// Macros for making working with OpenSL easier.
171
Flavio Lerdae8638162011-09-02 16:40:13 +0100172// Log based on the value of a property.
173#define LOG_OPENSL_API_CALL(string) (gLogEnabled && LOGV(string))
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100174
175// The regular macro: log an api call, make the api call, check the result.
176#define OpenSL(obj, method, ...) \
177{ \
178 LOG_OPENSL_API_CALL("OpenSL " #method "(" #obj ", " #__VA_ARGS__ ")"); \
179 SLresult result = (*obj)->method(obj, __VA_ARGS__); \
180 CheckSLResult("OpenSL " #method "(" #obj ", " #__VA_ARGS__ ")", result); \
181}
182
183// Special case call for api call that has void return value, can't be checked.
184#define VoidOpenSL(obj, method) \
185{ \
186 LOG_OPENSL_API_CALL("OpenSL (void) " #method "(" #obj ")"); \
187 (*obj)->method(obj); \
188}
189
190// Special case for api call with checked result but takes no arguments.
191#define OpenSL0(obj, method) \
192{ \
193 LOG_OPENSL_API_CALL("OpenSL " #method "(" #obj ")"); \
194 SLresult result = (*obj)->method(obj); \
195 CheckSLResult("OpenSL " #method "(" #obj ")", result); \
196}
197
198// Special case for api call whose result we want to store, not check.
199// We have to encapsulate the two calls in braces, so that this expression
200// evaluates to the last expression not the first.
201#define ReturnOpenSL(obj, method, ...) \
202( \
203 LOG_OPENSL_API_CALL("OpenSL (int) " \
204 #method "(" #obj ", " #__VA_ARGS__ ")"), \
205 (*obj)->method(obj, __VA_ARGS__) \
206) \
207
208// ****************************************************************************
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100209// Static utility methods.
210
Flavio Lerdadc442b42011-08-31 15:49:53 +0100211// Set the audio stream type for the player.
212//
213// Must be called before it is realized.
214//
215// The caller must have requested the SL_IID_ANDROIDCONFIGURATION interface when
216// creating the player.
217static void setAudioStreamType(SLObjectItf audioPlayer, SLint32 audioStreamType) {
218 SLAndroidConfigurationItf playerConfig;
219 OpenSL(audioPlayer, GetInterface, SL_IID_ANDROIDCONFIGURATION, &playerConfig);
220 // The STREAM_XXX constants defined by android.media.AudioManager match the
221 // corresponding SL_ANDROID_STREAM_XXX constants defined by
222 // include/SLES/OpenSLES_AndroidConfiguration.h, so we can just pass the
223 // value across.
224 OpenSL(playerConfig, SetConfiguration, SL_ANDROID_KEY_STREAM_TYPE,
225 &audioStreamType, sizeof(audioStreamType));
226}
227
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100228// Must be called with callbackLock_ held.
229static void ReadSampleRateAndChannelCount(CallbackContext *pContext,
230 SLuint32 *sampleRateOut, SLuint32 *channelsOut) {
231 SLMetadataExtractionItf decoderMetadata = pContext->decoderMetadata;
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100232 SLuint32 itemCount;
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100233 OpenSL(decoderMetadata, GetItemCount, &itemCount);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100234 SLuint32 i, keySize, valueSize;
235 SLMetadataInfo *keyInfo, *value;
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100236 for (i = 0; i < itemCount; ++i) {
237 keyInfo = value = NULL;
238 keySize = valueSize = 0;
239 OpenSL(decoderMetadata, GetKeySize, i, &keySize);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100240 keyInfo = static_cast<SLMetadataInfo*>(malloc(keySize));
241 if (keyInfo) {
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100242 OpenSL(decoderMetadata, GetKey, i, keySize, keyInfo);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100243 if (keyInfo->encoding == SL_CHARACTERENCODING_ASCII
244 || keyInfo->encoding == SL_CHARACTERENCODING_UTF8) {
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100245 OpenSL(decoderMetadata, GetValueSize, i, &valueSize);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100246 value = static_cast<SLMetadataInfo*>(malloc(valueSize));
247 if (value) {
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100248 OpenSL(decoderMetadata, GetValue, i, valueSize, value);
249 if (strcmp((char*) keyInfo->data, kKeyPcmFormatSamplesPerSec) == 0) {
250 SLuint32 sampleRate = *(reinterpret_cast<SLuint32*>(value->data));
251 LOGD("sample Rate: %d", sampleRate);
252 *sampleRateOut = sampleRate;
253 } else if (strcmp((char*) keyInfo->data, kKeyPcmFormatNumChannels) == 0) {
254 SLuint32 channels = *(reinterpret_cast<SLuint32*>(value->data));
255 LOGD("channels: %d", channels);
256 *channelsOut = channels;
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100257 }
258 free(value);
259 }
260 }
261 free(keyInfo);
262 }
263 }
264}
265
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100266// Must be called with callbackLock_ held.
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100267static void RegisterCallbackContextAndAddEnqueueBuffersToDecoder(
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100268 SLAndroidSimpleBufferQueueItf decoderQueue, CallbackContext* context) {
269 // Register a callback on the decoder queue, so that we will be called
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100270 // throughout the decoding process (and can then extract the decoded audio
271 // for the next bit of the pipeline).
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100272 OpenSL(decoderQueue, RegisterCallback, DecodingBufferQueueCb, context);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100273
274 // Enqueue buffers to map the region of memory allocated to store the
275 // decoded data.
276 for (size_t i = 0; i < kNumberOfBuffersInQueue; i++) {
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100277 OpenSL(decoderQueue, Enqueue, context->pData, kBufferSizeInBytes);
Hugo Hudson9730f152011-07-25 17:04:42 +0100278 context->pData += kBufferSizeInBytes;
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100279 }
Hugo Hudson9730f152011-07-25 17:04:42 +0100280 context->pData = context->pDataBase;
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100281}
282
283// ****************************************************************************
284// Constructor and Destructor.
285
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100286AudioEngine::AudioEngine(size_t targetFrames, float windowDuration,
287 float windowOverlapDuration, size_t maxPlayBufferCount, float initialRate,
Flavio Lerdadc442b42011-08-31 15:49:53 +0100288 size_t decodeInitialSize, size_t decodeMaxSize, size_t startPositionMillis,
289 int audioStreamType)
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100290 : decodeBuffer_(decodeInitialSize, decodeMaxSize),
291 playingBuffers_(), freeBuffers_(), timeScaler_(NULL),
292 floatBuffer_(NULL), injectBuffer_(NULL),
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100293 mSampleRate(0), mChannels(0),
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100294 targetFrames_(targetFrames),
295 windowDuration_(windowDuration),
296 windowOverlapDuration_(windowOverlapDuration),
297 maxPlayBufferCount_(maxPlayBufferCount), initialRate_(initialRate),
298 startPositionMillis_(startPositionMillis),
Flavio Lerdadc442b42011-08-31 15:49:53 +0100299 audioStreamType_(audioStreamType),
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100300 totalDurationMs_(0), decoderCurrentPosition_(0), startRequested_(false),
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100301 stopRequested_(false), finishedDecoding_(false) {
Flavio Lerdae8638162011-09-02 16:40:13 +0100302 // Determine whether we should log calls.
303 gLogEnabled = ShouldLog();
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100304}
305
306AudioEngine::~AudioEngine() {
307 // destroy the time scaler
308 if (timeScaler_ != NULL) {
309 delete timeScaler_;
310 timeScaler_ = NULL;
311 }
312
313 // delete all outstanding playing and free buffers
314 android::Mutex::Autolock autoLock(playBufferLock_);
315 while (playingBuffers_.size() > 0) {
316 delete[] playingBuffers_.front();
317 playingBuffers_.pop();
318 }
319 while (freeBuffers_.size() > 0) {
320 delete[] freeBuffers_.top();
321 freeBuffers_.pop();
322 }
323
324 delete[] floatBuffer_;
325 floatBuffer_ = NULL;
326 delete[] injectBuffer_;
327 injectBuffer_ = NULL;
328}
329
330// ****************************************************************************
331// Regular AudioEngine class methods.
332
333void AudioEngine::SetVariableSpeed(float speed) {
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100334 // TODO: Mutex for shared time scaler accesses.
Hugo Hudson64f5ba62011-08-10 15:57:28 +0100335 if (HasSampleRateAndChannels()) {
336 GetTimeScaler()->set_speed(speed);
337 } else {
338 // This is being called at a point where we have not yet processed enough
339 // data to determine the sample rate and number of channels.
340 // Ignore the call. See http://b/5140693.
341 LOGD("set varaible speed called, sample rate and channels not ready yet");
342 }
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100343}
344
345void AudioEngine::RequestStart() {
346 android::Mutex::Autolock autoLock(lock_);
347 startRequested_ = true;
348}
349
350void AudioEngine::ClearRequestStart() {
351 android::Mutex::Autolock autoLock(lock_);
352 startRequested_ = false;
353}
354
355bool AudioEngine::GetWasStartRequested() {
356 android::Mutex::Autolock autoLock(lock_);
357 return startRequested_;
358}
359
360void AudioEngine::RequestStop() {
361 android::Mutex::Autolock autoLock(lock_);
362 stopRequested_ = true;
363}
364
365int AudioEngine::GetCurrentPosition() {
366 android::Mutex::Autolock autoLock(decodeBufferLock_);
367 double result = decodeBuffer_.GetTotalAdvancedCount();
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100368 // TODO: This is horrible, but should be removed soon once the outstanding
369 // issue with get current position on decoder is fixed.
370 android::Mutex::Autolock autoLock2(callbackLock_);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100371 return static_cast<int>(
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100372 (result * 1000) / mSampleRate / mChannels + startPositionMillis_);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100373}
374
375int AudioEngine::GetTotalDuration() {
376 android::Mutex::Autolock autoLock(lock_);
377 return static_cast<int>(totalDurationMs_);
378}
379
380video_editing::SolaTimeScaler* AudioEngine::GetTimeScaler() {
381 if (timeScaler_ == NULL) {
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100382 CHECK(HasSampleRateAndChannels());
383 android::Mutex::Autolock autoLock(callbackLock_);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100384 timeScaler_ = new video_editing::SolaTimeScaler();
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100385 timeScaler_->Init(mSampleRate, mChannels, initialRate_, windowDuration_,
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100386 windowOverlapDuration_);
387 }
388 return timeScaler_;
389}
390
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100391bool AudioEngine::EnqueueNextBufferOfAudio(
392 SLAndroidSimpleBufferQueueItf audioPlayerQueue) {
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100393 size_t channels;
394 {
395 android::Mutex::Autolock autoLock(callbackLock_);
396 channels = mChannels;
397 }
398 size_t frameSizeInBytes = kSampleSizeInBytes * channels;
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100399 size_t frameCount = 0;
400 while (frameCount < targetFrames_) {
401 size_t framesLeft = targetFrames_ - frameCount;
402 // If there is data already in the time scaler, retrieve it.
403 if (GetTimeScaler()->available() > 0) {
404 size_t retrieveCount = min(GetTimeScaler()->available(), framesLeft);
405 int count = GetTimeScaler()->RetrieveSamples(
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100406 floatBuffer_ + frameCount * channels, retrieveCount);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100407 if (count <= 0) {
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100408 LOGD("error: count was %d", count);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100409 break;
410 }
411 frameCount += count;
412 continue;
413 }
414 // If there is no data in the time scaler, then feed some into it.
415 android::Mutex::Autolock autoLock(decodeBufferLock_);
416 size_t framesInDecodeBuffer =
417 decodeBuffer_.GetSizeInBytes() / frameSizeInBytes;
418 size_t framesScalerCanHandle = GetTimeScaler()->input_limit();
419 size_t framesToInject = min(framesInDecodeBuffer,
420 min(targetFrames_, framesScalerCanHandle));
421 if (framesToInject <= 0) {
422 // No more frames left to inject.
423 break;
424 }
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100425 for (size_t i = 0; i < framesToInject * channels; ++i) {
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100426 injectBuffer_[i] = decodeBuffer_.GetAtIndex(i);
427 }
428 int count = GetTimeScaler()->InjectSamples(injectBuffer_, framesToInject);
429 if (count <= 0) {
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100430 LOGD("error: count was %d", count);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100431 break;
432 }
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100433 decodeBuffer_.AdvanceHeadPointerShorts(count * channels);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100434 }
435 if (frameCount <= 0) {
436 // We must have finished playback.
437 if (GetEndOfDecoderReached()) {
438 // If we've finished decoding, clear the buffer - so we will terminate.
439 ClearDecodeBuffer();
440 }
441 return false;
442 }
443
444 // Get a free playing buffer.
445 int16* playBuffer;
446 {
447 android::Mutex::Autolock autoLock(playBufferLock_);
448 if (freeBuffers_.size() > 0) {
449 // If we have a free buffer, recycle it.
450 playBuffer = freeBuffers_.top();
451 freeBuffers_.pop();
452 } else {
453 // Otherwise allocate a new one.
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100454 playBuffer = new int16[targetFrames_ * channels];
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100455 }
456 }
457
458 // Try to play the buffer.
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100459 for (size_t i = 0; i < frameCount * channels; ++i) {
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100460 playBuffer[i] = floatBuffer_[i];
461 }
462 size_t sizeOfPlayBufferInBytes =
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100463 frameCount * channels * kNumberOfBytesPerInt16;
464 SLresult result = ReturnOpenSL(audioPlayerQueue, Enqueue, playBuffer,
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100465 sizeOfPlayBufferInBytes);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100466 if (result == SL_RESULT_SUCCESS) {
467 android::Mutex::Autolock autoLock(playBufferLock_);
468 playingBuffers_.push(playBuffer);
469 } else {
470 LOGE("could not enqueue audio buffer");
471 delete[] playBuffer;
472 }
473
474 return (result == SL_RESULT_SUCCESS);
475}
476
477bool AudioEngine::GetEndOfDecoderReached() {
478 android::Mutex::Autolock autoLock(lock_);
479 return finishedDecoding_;
480}
481
482void AudioEngine::SetEndOfDecoderReached() {
483 android::Mutex::Autolock autoLock(lock_);
484 finishedDecoding_ = true;
485}
486
487bool AudioEngine::PlayFileDescriptor(int fd, int64 offset, int64 length) {
488 SLDataLocator_AndroidFD loc_fd = {
489 SL_DATALOCATOR_ANDROIDFD, fd, offset, length };
490 SLDataFormat_MIME format_mime = {
491 SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED };
492 SLDataSource audioSrc = { &loc_fd, &format_mime };
493 return PlayFromThisSource(audioSrc);
494}
495
496bool AudioEngine::PlayUri(const char* uri) {
497 // Source of audio data for the decoding
498 SLDataLocator_URI decUri = { SL_DATALOCATOR_URI,
499 const_cast<SLchar*>(reinterpret_cast<const SLchar*>(uri)) };
500 SLDataFormat_MIME decMime = {
501 SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED };
502 SLDataSource decSource = { &decUri, &decMime };
503 return PlayFromThisSource(decSource);
504}
505
506bool AudioEngine::IsDecodeBufferEmpty() {
507 android::Mutex::Autolock autoLock(decodeBufferLock_);
508 return decodeBuffer_.GetSizeInBytes() <= 0;
509}
510
511void AudioEngine::ClearDecodeBuffer() {
512 android::Mutex::Autolock autoLock(decodeBufferLock_);
513 decodeBuffer_.Clear();
514}
515
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100516static size_t ReadDuration(SLPlayItf playItf) {
517 SLmillisecond durationInMsec = SL_TIME_UNKNOWN;
518 OpenSL(playItf, GetDuration, &durationInMsec);
519 if (durationInMsec == SL_TIME_UNKNOWN) {
520 LOGE("can't get duration");
521 return 0;
522 }
523 LOGD("duration: %d", static_cast<int>(durationInMsec));
524 return durationInMsec;
525}
526
527static size_t ReadPosition(SLPlayItf playItf) {
528 SLmillisecond positionInMsec = SL_TIME_UNKNOWN;
529 OpenSL(playItf, GetPosition, &positionInMsec);
530 if (positionInMsec == SL_TIME_UNKNOWN) {
531 LOGE("can't get position");
532 return 0;
533 }
534 LOGW("decoder position: %d", static_cast<int>(positionInMsec));
535 return positionInMsec;
536}
537
Hugo Hudson9730f152011-07-25 17:04:42 +0100538static void CreateAndRealizeEngine(SLObjectItf &engine,
539 SLEngineItf &engineInterface) {
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100540 SLEngineOption EngineOption[] = { {
541 SL_ENGINEOPTION_THREADSAFE, SL_BOOLEAN_TRUE } };
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100542 SLresult result = slCreateEngine(&engine, 1, EngineOption, 0, NULL, NULL);
543 CheckSLResult("create engine", result);
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100544 OpenSL(engine, Realize, SL_BOOLEAN_FALSE);
545 OpenSL(engine, GetInterface, SL_IID_ENGINE, &engineInterface);
Hugo Hudson9730f152011-07-25 17:04:42 +0100546}
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100547
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100548SLuint32 AudioEngine::GetSLSampleRate() {
549 android::Mutex::Autolock autoLock(callbackLock_);
550 return mSampleRate * 1000;
Hugo Hudson9730f152011-07-25 17:04:42 +0100551}
552
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100553SLuint32 AudioEngine::GetSLChannels() {
554 android::Mutex::Autolock autoLock(callbackLock_);
555 switch (mChannels) {
Hugo Hudson9730f152011-07-25 17:04:42 +0100556 case 2:
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100557 return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
Hugo Hudson9730f152011-07-25 17:04:42 +0100558 case 1:
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100559 return SL_SPEAKER_FRONT_CENTER;
Hugo Hudson9730f152011-07-25 17:04:42 +0100560 default:
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100561 LOGE("unknown channels %d, using 2", mChannels);
562 return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
Hugo Hudson9730f152011-07-25 17:04:42 +0100563 }
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100564}
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100565
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100566SLuint32 AudioEngine::GetChannelCount() {
567 android::Mutex::Autolock autoLock(callbackLock_);
568 return mChannels;
569}
570
571static void CreateAndRealizeAudioPlayer(SLuint32 slSampleRate,
Flavio Lerdadc442b42011-08-31 15:49:53 +0100572 size_t channelCount, SLuint32 slChannels, SLint32 audioStreamType, SLObjectItf &outputMix,
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100573 SLObjectItf &audioPlayer, SLEngineItf &engineInterface) {
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100574 // Define the source and sink for the audio player: comes from a buffer queue
575 // and goes to the output mix.
576 SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {
577 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2 };
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100578 SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, channelCount, slSampleRate,
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100579 SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100580 slChannels, SL_BYTEORDER_LITTLEENDIAN};
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100581 SLDataSource playingSrc = {&loc_bufq, &format_pcm};
582 SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMix};
583 SLDataSink audioSnk = {&loc_outmix, NULL};
584
585 // Create the audio player, which will play from the buffer queue and send to
586 // the output mix.
Flavio Lerdadc442b42011-08-31 15:49:53 +0100587 const size_t playerInterfaceCount = 2;
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100588 const SLInterfaceID iids[playerInterfaceCount] = {
Flavio Lerdadc442b42011-08-31 15:49:53 +0100589 SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION };
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100590 const SLboolean reqs[playerInterfaceCount] = { SL_BOOLEAN_TRUE };
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100591 OpenSL(engineInterface, CreateAudioPlayer, &audioPlayer, &playingSrc,
592 &audioSnk, playerInterfaceCount, iids, reqs);
Flavio Lerdadc442b42011-08-31 15:49:53 +0100593 setAudioStreamType(audioPlayer, audioStreamType);
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100594 OpenSL(audioPlayer, Realize, SL_BOOLEAN_FALSE);
Hugo Hudson9730f152011-07-25 17:04:42 +0100595}
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100596
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100597bool AudioEngine::HasSampleRateAndChannels() {
598 android::Mutex::Autolock autoLock(callbackLock_);
599 return mChannels != 0 && mSampleRate != 0;
Hugo Hudson9730f152011-07-25 17:04:42 +0100600}
601
602bool AudioEngine::PlayFromThisSource(const SLDataSource& audioSrc) {
603 ClearDecodeBuffer();
604
Hugo Hudson9730f152011-07-25 17:04:42 +0100605 SLObjectItf engine;
606 SLEngineItf engineInterface;
607 CreateAndRealizeEngine(engine, engineInterface);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100608
609 // Define the source and sink for the decoding player: comes from the source
610 // this method was called with, is sent to another buffer queue.
611 SLDataLocator_AndroidSimpleBufferQueue decBuffQueue;
612 decBuffQueue.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
613 decBuffQueue.numBuffers = kNumberOfBuffersInQueue;
614 // A valid value seems required here but is currently ignored.
Hugo Hudson9730f152011-07-25 17:04:42 +0100615 SLDataFormat_PCM pcm = {SL_DATAFORMAT_PCM, 1, SL_SAMPLINGRATE_44_1,
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100616 SL_PCMSAMPLEFORMAT_FIXED_16, 16,
617 SL_SPEAKER_FRONT_LEFT, SL_BYTEORDER_LITTLEENDIAN};
618 SLDataSink decDest = { &decBuffQueue, &pcm };
619
620 // Create the decoder with the given source and sink.
Flavio Lerdadc442b42011-08-31 15:49:53 +0100621 const size_t decoderInterfaceCount = 5;
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100622 SLObjectItf decoder;
623 const SLInterfaceID decodePlayerInterfaces[decoderInterfaceCount] = {
624 SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_PREFETCHSTATUS, SL_IID_SEEK,
Flavio Lerdadc442b42011-08-31 15:49:53 +0100625 SL_IID_METADATAEXTRACTION, SL_IID_ANDROIDCONFIGURATION };
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100626 const SLboolean decodePlayerRequired[decoderInterfaceCount] = {
627 SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
628 SLDataSource sourceCopy(audioSrc);
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100629 OpenSL(engineInterface, CreateAudioPlayer, &decoder, &sourceCopy, &decDest,
630 decoderInterfaceCount, decodePlayerInterfaces, decodePlayerRequired);
Flavio Lerdadc442b42011-08-31 15:49:53 +0100631 // Not sure if this is necessary, but just in case.
632 setAudioStreamType(decoder, audioStreamType_);
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100633 OpenSL(decoder, Realize, SL_BOOLEAN_FALSE);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100634
635 // Get the play interface from the decoder, and register event callbacks.
636 // Get the buffer queue, prefetch and seek interfaces.
Hugo Hudson9730f152011-07-25 17:04:42 +0100637 SLPlayItf decoderPlay = NULL;
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100638 SLAndroidSimpleBufferQueueItf decoderQueue = NULL;
639 SLPrefetchStatusItf decoderPrefetch = NULL;
640 SLSeekItf decoderSeek = NULL;
641 SLMetadataExtractionItf decoderMetadata = NULL;
642 OpenSL(decoder, GetInterface, SL_IID_PLAY, &decoderPlay);
643 OpenSL(decoderPlay, SetCallbackEventsMask, SL_PLAYEVENT_HEADATEND);
644 OpenSL(decoderPlay, RegisterCallback, DecodingEventCb, NULL);
645 OpenSL(decoder, GetInterface, SL_IID_PREFETCHSTATUS, &decoderPrefetch);
646 OpenSL(decoder, GetInterface, SL_IID_SEEK, &decoderSeek);
647 OpenSL(decoder, GetInterface, SL_IID_METADATAEXTRACTION, &decoderMetadata);
648 OpenSL(decoder, GetInterface, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
649 &decoderQueue);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100650
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100651 // Initialize the callback structure, used during the decoding.
Hugo Hudson9730f152011-07-25 17:04:42 +0100652 CallbackContext callbackContext;
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100653 {
654 android::Mutex::Autolock autoLock(callbackLock_);
655 callbackContext.pDataBase = pcmData;
656 callbackContext.pData = pcmData;
657 callbackContext.decoderMetadata = decoderMetadata;
658 callbackContext.playItf = decoderPlay;
659 RegisterCallbackContextAndAddEnqueueBuffersToDecoder(
660 decoderQueue, &callbackContext);
661 }
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100662
663 // Initialize the callback for prefetch errors, if we can't open the
664 // resource to decode.
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100665 OpenSL(decoderPrefetch, SetCallbackEventsMask, kPrefetchErrorCandidate);
666 OpenSL(decoderPrefetch, RegisterCallback, PrefetchEventCb, &decoderPrefetch);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100667
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100668 // Seek to the start position.
669 OpenSL(decoderSeek, SetPosition, startPositionMillis_, SL_SEEKMODE_ACCURATE);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100670
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100671 // Start decoding immediately.
672 OpenSL(decoderPlay, SetPlayState, SL_PLAYSTATE_PLAYING);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100673
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100674 // These variables hold the audio player and its output.
675 // They will only be constructed once the decoder has invoked the callback,
676 // and given us the correct sample rate, number of channels and duration.
Hugo Hudson9730f152011-07-25 17:04:42 +0100677 SLObjectItf outputMix = NULL;
678 SLObjectItf audioPlayer = NULL;
679 SLPlayItf audioPlayerPlay = NULL;
680 SLAndroidSimpleBufferQueueItf audioPlayerQueue = NULL;
681
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100682 // The main loop - until we're told to stop: if there is audio data coming
683 // out of the decoder, feed it through the time scaler.
684 // As it comes out of the time scaler, feed it into the audio player.
685 while (!Finished()) {
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100686 if (GetWasStartRequested() && HasSampleRateAndChannels()) {
687 // Build the audio player.
688 // TODO: What happens if I maliciously call start lots of times?
689 floatBuffer_ = new float[targetFrames_ * mChannels];
690 injectBuffer_ = new float[targetFrames_ * mChannels];
691 OpenSL(engineInterface, CreateOutputMix, &outputMix, 0, NULL, NULL);
692 OpenSL(outputMix, Realize, SL_BOOLEAN_FALSE);
693 CreateAndRealizeAudioPlayer(GetSLSampleRate(), GetChannelCount(),
Flavio Lerdadc442b42011-08-31 15:49:53 +0100694 GetSLChannels(), audioStreamType_, outputMix, audioPlayer,
695 engineInterface);
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100696 OpenSL(audioPlayer, GetInterface, SL_IID_PLAY, &audioPlayerPlay);
697 OpenSL(audioPlayer, GetInterface, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
698 &audioPlayerQueue);
699 OpenSL(audioPlayerQueue, RegisterCallback, PlayingBufferQueueCb, NULL);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100700 ClearRequestStart();
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100701 OpenSL(audioPlayerPlay, SetPlayState, SL_PLAYSTATE_PLAYING);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100702 }
703 EnqueueMoreAudioIfNecessary(audioPlayerQueue);
704 usleep(kSleepTimeMicros);
705 }
706
Hugo Hudson9730f152011-07-25 17:04:42 +0100707 // Delete the audio player and output mix, iff they have been created.
708 if (audioPlayer != NULL) {
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100709 OpenSL(audioPlayerPlay, SetPlayState, SL_PLAYSTATE_STOPPED);
710 OpenSL0(audioPlayerQueue, Clear);
711 OpenSL(audioPlayerQueue, RegisterCallback, NULL, NULL);
712 VoidOpenSL(audioPlayer, AbortAsyncOperation);
713 VoidOpenSL(audioPlayer, Destroy);
714 VoidOpenSL(outputMix, Destroy);
Hugo Hudson9730f152011-07-25 17:04:42 +0100715 audioPlayer = NULL;
716 audioPlayerPlay = NULL;
717 audioPlayerQueue = NULL;
718 outputMix = NULL;
719 }
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100720
721 // Delete the decoder.
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100722 OpenSL(decoderPlay, SetPlayState, SL_PLAYSTATE_STOPPED);
723 OpenSL(decoderPrefetch, RegisterCallback, NULL, NULL);
Hugo Hudson9730f152011-07-25 17:04:42 +0100724 // This is returning slresult 13 if I do no playback.
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100725 // Repro is to comment out all before this line, and all after enqueueing
726 // my buffers.
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100727 // OpenSL0(decoderQueue, Clear);
728 OpenSL(decoderQueue, RegisterCallback, NULL, NULL);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100729 decoderSeek = NULL;
730 decoderPrefetch = NULL;
731 decoderQueue = NULL;
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100732 OpenSL(decoderPlay, RegisterCallback, NULL, NULL);
733 VoidOpenSL(decoder, AbortAsyncOperation);
734 VoidOpenSL(decoder, Destroy);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100735 decoderPlay = NULL;
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100736
Hugo Hudson9730f152011-07-25 17:04:42 +0100737 // Delete the engine.
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100738 VoidOpenSL(engine, Destroy);
Hugo Hudson9730f152011-07-25 17:04:42 +0100739 engineInterface = NULL;
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100740
741 return true;
742}
743
744bool AudioEngine::Finished() {
745 if (GetWasStopRequested()) {
746 return true;
747 }
748 android::Mutex::Autolock autoLock(playBufferLock_);
749 return playingBuffers_.size() <= 0 &&
750 IsDecodeBufferEmpty() &&
751 GetEndOfDecoderReached();
752}
753
754bool AudioEngine::GetWasStopRequested() {
755 android::Mutex::Autolock autoLock(lock_);
756 return stopRequested_;
757}
758
759bool AudioEngine::GetHasReachedPlayingBuffersLimit() {
760 android::Mutex::Autolock autoLock(playBufferLock_);
761 return playingBuffers_.size() >= maxPlayBufferCount_;
762}
763
764void AudioEngine::EnqueueMoreAudioIfNecessary(
765 SLAndroidSimpleBufferQueueItf audioPlayerQueue) {
766 bool keepEnqueueing = true;
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100767 while (audioPlayerQueue != NULL &&
768 !GetWasStopRequested() &&
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100769 !IsDecodeBufferEmpty() &&
770 !GetHasReachedPlayingBuffersLimit() &&
771 keepEnqueueing) {
772 keepEnqueueing = EnqueueNextBufferOfAudio(audioPlayerQueue);
773 }
774}
775
776bool AudioEngine::DecodeBufferTooFull() {
777 android::Mutex::Autolock autoLock(decodeBufferLock_);
778 return decodeBuffer_.IsTooLarge();
779}
780
781// ****************************************************************************
782// Code for handling the static callbacks.
783
784void AudioEngine::PlayingBufferQueueCallback() {
785 // The head playing buffer is done, move it to the free list.
786 android::Mutex::Autolock autoLock(playBufferLock_);
787 if (playingBuffers_.size() > 0) {
788 freeBuffers_.push(playingBuffers_.front());
789 playingBuffers_.pop();
790 }
791}
792
793void AudioEngine::PrefetchEventCallback(
794 SLPrefetchStatusItf caller, SLuint32 event) {
795 // If there was a problem during decoding, then signal the end.
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100796 SLpermille level = 0;
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100797 SLuint32 status;
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100798 OpenSL(caller, GetFillLevel, &level);
799 OpenSL(caller, GetPrefetchStatus, &status);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100800 if ((kPrefetchErrorCandidate == (event & kPrefetchErrorCandidate)) &&
801 (level == 0) &&
802 (status == SL_PREFETCHSTATUS_UNDERFLOW)) {
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100803 LOGI("prefetcheventcallback error while prefetching data");
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100804 SetEndOfDecoderReached();
805 }
806 if (SL_PREFETCHSTATUS_SUFFICIENTDATA == event) {
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100807 // android::Mutex::Autolock autoLock(prefetchLock_);
808 // prefetchCondition_.broadcast();
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100809 }
810}
811
812void AudioEngine::DecodingBufferQueueCallback(
813 SLAndroidSimpleBufferQueueItf queueItf, void *context) {
814 if (GetWasStopRequested()) {
815 return;
816 }
817
818 CallbackContext *pCntxt;
819 {
820 android::Mutex::Autolock autoLock(callbackLock_);
821 pCntxt = reinterpret_cast<CallbackContext*>(context);
822 }
823 {
824 android::Mutex::Autolock autoLock(decodeBufferLock_);
Hugo Hudsond2772c42011-08-27 01:21:54 +0100825 decodeBuffer_.AddData(pCntxt->pData, kBufferSizeInBytes);
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100826 }
827
Hugo Hudson0bd6ec52011-07-26 20:05:25 +0100828 if (!HasSampleRateAndChannels()) {
829 android::Mutex::Autolock autoLock(callbackLock_);
830 ReadSampleRateAndChannelCount(pCntxt, &mSampleRate, &mChannels);
831 }
832
833 {
834 android::Mutex::Autolock autoLock(lock_);
835 if (totalDurationMs_ == 0) {
836 totalDurationMs_ = ReadDuration(pCntxt->playItf);
837 }
838 // TODO: This isn't working, it always reports zero.
839 // ReadPosition(pCntxt->playItf);
840 }
Hugo Hudson9730f152011-07-25 17:04:42 +0100841
Hugo Hudsond2772c42011-08-27 01:21:54 +0100842 OpenSL(queueItf, Enqueue, pCntxt->pData, kBufferSizeInBytes);
843
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100844 // Increase data pointer by buffer size
845 pCntxt->pData += kBufferSizeInBytes;
846 if (pCntxt->pData >= pCntxt->pDataBase +
847 (kNumberOfBuffersInQueue * kBufferSizeInBytes)) {
848 pCntxt->pData = pCntxt->pDataBase;
849 }
850
Hugo Hudsonb83ad732011-07-14 23:31:17 +0100851 // If we get too much data into the decoder,
852 // sleep until the playback catches up.
853 while (!GetWasStopRequested() && DecodeBufferTooFull()) {
854 usleep(kSleepTimeMicros);
855 }
856}
857
858void AudioEngine::DecodingEventCallback(SLPlayItf, SLuint32 event) {
859 if (SL_PLAYEVENT_HEADATEND & event) {
860 SetEndOfDecoderReached();
861 }
862}