2 * Copyright (C) 2010 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "sles_allinclusive.h"
18 #include "utils/RefBase.h"
21 //-----------------------------------------------------------------------------
22 int android_getMinFrameCount(uint32_t sampleRate) {
24 if (android::AudioSystem::getOutputSamplingRate(&afSampleRate,
25 ANDROID_DEFAULT_OUTPUT_STREAM_TYPE) != android::NO_ERROR) {
26 return ANDROID_DEFAULT_AUDIOTRACK_BUFFER_SIZE;
29 if (android::AudioSystem::getOutputFrameCount(&afFrameCount,
30 ANDROID_DEFAULT_OUTPUT_STREAM_TYPE) != android::NO_ERROR) {
31 return ANDROID_DEFAULT_AUDIOTRACK_BUFFER_SIZE;
34 if (android::AudioSystem::getOutputLatency(&afLatency,
35 ANDROID_DEFAULT_OUTPUT_STREAM_TYPE) != android::NO_ERROR) {
36 return ANDROID_DEFAULT_AUDIOTRACK_BUFFER_SIZE;
38 // minimum nb of buffers to cover output latency, given the size of each hardware audio buffer
39 uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
40 if (minBufCount < 2) minBufCount = 2;
41 // minimum number of frames to cover output latency at the sample rate of the content
42 return (afFrameCount*sampleRate*minBufCount)/afSampleRate;
46 //-----------------------------------------------------------------------------
47 #define LEFT_CHANNEL_MASK 0x1 << 0
48 #define RIGHT_CHANNEL_MASK 0x1 << 1
50 static void android_audioPlayer_updateStereoVolume(CAudioPlayer* ap) {
51 float leftVol = 1.0f, rightVol = 1.0f;
53 if (NULL == ap->mAudioTrack) {
56 // should not be used when muted
57 if (SL_BOOLEAN_TRUE == ap->mMute) {
61 int channelCount = ap->mNumChannels;
63 // mute has priority over solo
64 int leftAudibilityFactor = 1, rightAudibilityFactor = 1;
66 if (channelCount >= STEREO_CHANNELS) {
67 if (ap->mMuteMask & LEFT_CHANNEL_MASK) {
69 leftAudibilityFactor = 0;
72 if (ap->mSoloMask & LEFT_CHANNEL_MASK) {
74 leftAudibilityFactor = 1;
77 if (ap->mSoloMask & RIGHT_CHANNEL_MASK) {
78 // right solo silences left
79 leftAudibilityFactor = 0;
81 // left and right are not soloed, and left is not muted
82 leftAudibilityFactor = 1;
87 if (ap->mMuteMask & RIGHT_CHANNEL_MASK) {
89 rightAudibilityFactor = 0;
92 if (ap->mSoloMask & RIGHT_CHANNEL_MASK) {
94 rightAudibilityFactor = 1;
97 if (ap->mSoloMask & LEFT_CHANNEL_MASK) {
98 // left solo silences right
99 rightAudibilityFactor = 0;
101 // left and right are not soloed, and right is not muted
102 rightAudibilityFactor = 1;
108 // compute amplification as the combination of volume level and stereo position
109 // amplification from volume level
110 ap->mAmplFromVolLevel = sles_to_android_amplification(ap->mVolume.mLevel);
111 leftVol *= ap->mAmplFromVolLevel * ap->mAmplFromDirectLevel;
112 rightVol *= ap->mAmplFromVolLevel * ap->mAmplFromDirectLevel;
114 // amplification from stereo position
115 if (ap->mVolume.mEnableStereoPosition) {
116 // panning law depends on number of channels of content: stereo panning vs 2ch. balance
117 if(1 == channelCount) {
119 double theta = (1000+ap->mVolume.mStereoPosition)*M_PI_4/1000.0f; // 0 <= theta <= Pi/2
120 ap->mAmplFromStereoPos[0] = cos(theta);
121 ap->mAmplFromStereoPos[1] = sin(theta);
124 if (ap->mVolume.mStereoPosition > 0) {
125 ap->mAmplFromStereoPos[0] = (1000-ap->mVolume.mStereoPosition)/1000.0f;
126 ap->mAmplFromStereoPos[1] = 1.0f;
128 ap->mAmplFromStereoPos[0] = 1.0f;
129 ap->mAmplFromStereoPos[1] = (1000+ap->mVolume.mStereoPosition)/1000.0f;
132 leftVol *= ap->mAmplFromStereoPos[0];
133 rightVol *= ap->mAmplFromStereoPos[1];
136 ap->mAudioTrack->setVolume(leftVol * leftAudibilityFactor, rightVol * rightAudibilityFactor);
139 //-----------------------------------------------------------------------------
140 void audioTrack_handleMarker_lockPlay(CAudioPlayer* ap) {
141 //SL_LOGV("received event EVENT_MARKER from AudioTrack");
142 slPlayCallback callback = NULL;
143 void* callbackPContext = NULL;
145 interface_lock_shared(&ap->mPlay);
146 callback = ap->mPlay.mCallback;
147 callbackPContext = ap->mPlay.mContext;
148 interface_unlock_shared(&ap->mPlay);
150 if (NULL != callback) {
151 // getting this event implies SL_PLAYEVENT_HEADATMARKER was set in the event mask
152 (*callback)(&ap->mPlay.mItf, callbackPContext, SL_PLAYEVENT_HEADATMARKER);
156 //-----------------------------------------------------------------------------
157 void audioTrack_handleNewPos_lockPlay(CAudioPlayer* ap) {
158 //SL_LOGV("received event EVENT_NEW_POS from AudioTrack");
159 slPlayCallback callback = NULL;
160 void* callbackPContext = NULL;
162 interface_lock_shared(&ap->mPlay);
163 callback = ap->mPlay.mCallback;
164 callbackPContext = ap->mPlay.mContext;
165 interface_unlock_shared(&ap->mPlay);
167 if (NULL != callback) {
168 // getting this event implies SL_PLAYEVENT_HEADATNEWPOS was set in the event mask
169 (*callback)(&ap->mPlay.mItf, callbackPContext, SL_PLAYEVENT_HEADATNEWPOS);
174 //-----------------------------------------------------------------------------
175 void audioTrack_handleUnderrun_lockPlay(CAudioPlayer* ap) {
176 slPlayCallback callback = NULL;
177 void* callbackPContext = NULL;
179 interface_lock_shared(&ap->mPlay);
180 callback = ap->mPlay.mCallback;
181 callbackPContext = ap->mPlay.mContext;
182 bool headStalled = (ap->mPlay.mEventFlags & SL_PLAYEVENT_HEADSTALLED) != 0;
183 interface_unlock_shared(&ap->mPlay);
185 if ((NULL != callback) && headStalled) {
186 (*callback)(&ap->mPlay.mItf, callbackPContext, SL_PLAYEVENT_HEADSTALLED);
190 //-----------------------------------------------------------------------------
192 * post-condition: play state of AudioPlayer is SL_PLAYSTATE_PAUSED if setPlayStateToPaused is true
194 * note: a conditional flag, setPlayStateToPaused, is used here to specify whether the play state
195 * needs to be changed when the player reaches the end of the content to play. This is
196 * relative to what the specification describes for buffer queues vs the
197 * SL_PLAYEVENT_HEADATEND event. In the OpenSL ES specification 1.0.1:
198 * - section 8.12 SLBufferQueueItf states "In the case of starvation due to insufficient
199 * buffers in the queue, the playing of audio data stops. The player remains in the
200 * SL_PLAYSTATE_PLAYING state."
201 * - section 9.2.31 SL_PLAYEVENT states "SL_PLAYEVENT_HEADATEND Playback head is at the end
202 * of the current content and the player has paused."
204 void audioPlayer_dispatch_headAtEnd_lockPlay(CAudioPlayer *ap, bool setPlayStateToPaused,
206 //SL_LOGV("ap=%p, setPlayStateToPaused=%d, needToLock=%d", ap, setPlayStateToPaused,
208 slPlayCallback playCallback = NULL;
209 void * playContext = NULL;
210 // SLPlayItf callback or no callback?
212 interface_lock_peek(&ap->mPlay);
214 if (ap->mPlay.mEventFlags & SL_PLAYEVENT_HEADATEND) {
215 playCallback = ap->mPlay.mCallback;
216 playContext = ap->mPlay.mContext;
219 interface_unlock_peek(&ap->mPlay);
221 if (setPlayStateToPaused) {
223 interface_lock_poke(&ap->mPlay)
224 ap->mPlay.mState = SL_PLAYSTATE_PAUSED;
225 interface_unlock_poke(&ap->mPlay);
227 ap->mPlay.mState = SL_PLAYSTATE_PAUSED;
230 // callback with no lock held
231 if (NULL != playCallback) {
232 (*playCallback)(&ap->mPlay.mItf, playContext, SL_PLAYEVENT_HEADATEND);
238 //-----------------------------------------------------------------------------
240 * pre-condition: AudioPlayer has SLPrefetchStatusItf initialized
242 * - ap->mPrefetchStatus.mStatus == status
243 * - the prefetch status callback, if any, has been notified if a change occurred
246 void audioPlayer_dispatch_prefetchStatus_lockPrefetch(CAudioPlayer *ap, SLuint32 status,
248 slPrefetchCallback prefetchCallback = NULL;
249 void * prefetchContext = NULL;
252 interface_lock_exclusive(&ap->mPrefetchStatus);
255 if (ap->mPrefetchStatus.mStatus != status) {
256 ap->mPrefetchStatus.mStatus = status;
257 // callback or no callback?
258 if (ap->mPrefetchStatus.mCallbackEventsMask & SL_PREFETCHEVENT_STATUSCHANGE) {
259 prefetchCallback = ap->mPrefetchStatus.mCallback;
260 prefetchContext = ap->mPrefetchStatus.mContext;
264 interface_unlock_exclusive(&ap->mPrefetchStatus);
267 // callback with no lock held
268 if (NULL != prefetchCallback) {
269 (*prefetchCallback)(&ap->mPrefetchStatus.mItf, prefetchContext, status);
275 //-----------------------------------------------------------------------------
276 // Callback associated with an SfPlayer of an SL ES AudioPlayer that gets its data
277 // from a URI or FD, for prefetching events
278 static void sfplayer_handlePrefetchEvent(const int event, const int data1, void* user) {
283 CAudioPlayer *ap = (CAudioPlayer *)user;
284 //SL_LOGV("received event %d, data %d from SfAudioPlayer", event, data1);
287 case(android::SfPlayer::kEventPrefetchFillLevelUpdate): {
288 if (!IsInterfaceInitialized(&(ap->mObject), MPH_PREFETCHSTATUS)) {
291 // FIXME implement buffer filler level updates
292 SL_LOGE("[ FIXME implement buffer filler level updates ]");
293 //ap->mPrefetchStatus.mLevel = ;
296 case(android::SfPlayer::kEventPrefetchStatusChange): {
297 if (!IsInterfaceInitialized(&(ap->mObject), MPH_PREFETCHSTATUS)) {
300 slPrefetchCallback callback = NULL;
301 void* callbackPContext = NULL;
302 // SLPrefetchStatusItf callback or no callback?
303 interface_lock_exclusive(&ap->mPrefetchStatus);
304 if (ap->mPrefetchStatus.mCallbackEventsMask & SL_PREFETCHEVENT_STATUSCHANGE) {
305 callback = ap->mPrefetchStatus.mCallback;
306 callbackPContext = ap->mPrefetchStatus.mContext;
308 if (data1 >= android::SfPlayer::kStatusIntermediate) {
309 ap->mPrefetchStatus.mStatus = SL_PREFETCHSTATUS_SUFFICIENTDATA;
310 // FIXME estimate fill level better?
311 ap->mPrefetchStatus.mLevel = 1000;
312 ap->mAndroidObjState = ANDROID_READY;
313 } else if (data1 < android::SfPlayer::kStatusIntermediate) {
314 ap->mPrefetchStatus.mStatus = SL_PREFETCHSTATUS_UNDERFLOW;
315 // FIXME estimate fill level better?
316 ap->mPrefetchStatus.mLevel = 0;
318 interface_unlock_exclusive(&ap->mPrefetchStatus);
319 // callback with no lock held
320 if (NULL != callback) {
321 (*callback)(&ap->mPrefetchStatus.mItf, callbackPContext, SL_PREFETCHEVENT_STATUSCHANGE);
325 case(android::SfPlayer::kEventEndOfStream): {
326 audioPlayer_dispatch_headAtEnd_lockPlay(ap, true /*set state to paused?*/, true);
327 // FIXME update play position to make sure it's at the same value
328 // as getDuration if it's known?
329 ap->mAudioTrack->stop();
338 //-----------------------------------------------------------------------------
339 SLresult android_audioPlayer_checkSourceSink(CAudioPlayer *pAudioPlayer)
341 const SLDataSource *pAudioSrc = &pAudioPlayer->mDataSource.u.mSource;
342 const SLDataSink *pAudioSnk = &pAudioPlayer->mDataSink.u.mSink;
343 //--------------------------------------
345 // currently only OutputMix sinks are supported, regardless of the data source
346 if (*(SLuint32 *)pAudioSnk->pLocator != SL_DATALOCATOR_OUTPUTMIX) {
347 SL_LOGE("Cannot create audio player: data sink is not SL_DATALOCATOR_OUTPUTMIX");
348 return SL_RESULT_PARAMETER_INVALID;
351 //--------------------------------------
353 SLuint32 locatorType = *(SLuint32 *)pAudioSrc->pLocator;
354 SLuint32 formatType = *(SLuint32 *)pAudioSrc->pFormat;
356 switch (locatorType) {
359 case SL_DATALOCATOR_BUFFERQUEUE: {
360 SLDataLocator_BufferQueue *dl_bq = (SLDataLocator_BufferQueue *) pAudioSrc->pLocator;
363 switch (formatType) {
364 // currently only PCM buffer queues are supported,
365 case SL_DATAFORMAT_PCM: {
366 SLDataFormat_PCM *df_pcm = (SLDataFormat_PCM *) pAudioSrc->pFormat;
367 switch (df_pcm->numChannels) {
372 // this should have already been rejected by checkDataFormat
373 SL_LOGE("Cannot create audio player: unsupported " \
374 "PCM data source with %u channels", (unsigned) df_pcm->numChannels);
375 return SL_RESULT_CONTENT_UNSUPPORTED;
377 switch (df_pcm->samplesPerSec) {
378 case SL_SAMPLINGRATE_8:
379 case SL_SAMPLINGRATE_11_025:
380 case SL_SAMPLINGRATE_12:
381 case SL_SAMPLINGRATE_16:
382 case SL_SAMPLINGRATE_22_05:
383 case SL_SAMPLINGRATE_24:
384 case SL_SAMPLINGRATE_32:
385 case SL_SAMPLINGRATE_44_1:
387 case SL_SAMPLINGRATE_48: // not 48?
388 case SL_SAMPLINGRATE_64:
389 case SL_SAMPLINGRATE_88_2:
390 case SL_SAMPLINGRATE_96:
391 case SL_SAMPLINGRATE_192:
393 SL_LOGE("Cannot create audio player: unsupported sample rate %u milliHz",
394 (unsigned) df_pcm->samplesPerSec);
395 return SL_RESULT_CONTENT_UNSUPPORTED;
397 switch (df_pcm->bitsPerSample) {
398 case SL_PCMSAMPLEFORMAT_FIXED_8:
399 // FIXME We should support this
400 SL_LOGE("Cannot create audio player: unsupported 8-bit data");
401 return SL_RESULT_CONTENT_UNSUPPORTED;
402 case SL_PCMSAMPLEFORMAT_FIXED_16:
406 // this should have already been rejected by checkDataFormat
407 SL_LOGE("Cannot create audio player: unsupported sample bit depth %lu",
408 (SLuint32)df_pcm->bitsPerSample);
409 return SL_RESULT_CONTENT_UNSUPPORTED;
411 switch (df_pcm->containerSize) {
416 SL_LOGE("Cannot create audio player: unsupported container size %u",
417 (unsigned) df_pcm->containerSize);
418 return SL_RESULT_CONTENT_UNSUPPORTED;
420 switch (df_pcm->channelMask) {
425 switch (df_pcm->endianness) {
426 case SL_BYTEORDER_LITTLEENDIAN:
428 case SL_BYTEORDER_BIGENDIAN:
429 SL_LOGE("Cannot create audio player: unsupported big-endian byte order");
430 return SL_RESULT_CONTENT_UNSUPPORTED;
431 // native is proposed but not yet in spec
433 SL_LOGE("Cannot create audio player: unsupported byte order %u",
434 (unsigned) df_pcm->endianness);
435 return SL_RESULT_CONTENT_UNSUPPORTED;
437 } //case SL_DATAFORMAT_PCM
439 case SL_DATAFORMAT_MIME:
440 case SL_DATAFORMAT_RESERVED3:
441 SL_LOGE("Cannot create audio player with SL_DATALOCATOR_BUFFERQUEUE data source "
442 "without SL_DATAFORMAT_PCM format");
443 return SL_RESULT_CONTENT_UNSUPPORTED;
445 SL_LOGE("Cannot create audio player with SL_DATALOCATOR_BUFFERQUEUE data source "
446 "without SL_DATAFORMAT_PCM format");
447 return SL_RESULT_PARAMETER_INVALID;
448 } // switch (formatType)
449 } // case SL_DATALOCATOR_BUFFERQUEUE
453 case SL_DATALOCATOR_URI:
455 SLDataLocator_URI *dl_uri = (SLDataLocator_URI *) pAudioSrc->pLocator;
456 if (NULL == dl_uri->URI) {
457 return SL_RESULT_PARAMETER_INVALID;
460 switch (formatType) {
461 case SL_DATAFORMAT_MIME:
463 case SL_DATAFORMAT_PCM:
464 case SL_DATAFORMAT_RESERVED3:
465 SL_LOGE("Cannot create audio player with SL_DATALOCATOR_URI data source without "
466 "SL_DATAFORMAT_MIME format");
467 return SL_RESULT_CONTENT_UNSUPPORTED;
468 } // switch (formatType)
469 } // case SL_DATALOCATOR_URI
473 case SL_DATALOCATOR_ANDROIDFD:
475 // fd is already non null
476 switch (formatType) {
477 case SL_DATAFORMAT_MIME:
479 case SL_DATAFORMAT_PCM:
481 SL_LOGE("[ FIXME implement PCM FD data sources ]");
483 case SL_DATAFORMAT_RESERVED3:
484 SL_LOGE("Cannot create audio player with SL_DATALOCATOR_ANDROIDFD data source "
485 "without SL_DATAFORMAT_MIME or SL_DATAFORMAT_PCM format");
486 return SL_RESULT_CONTENT_UNSUPPORTED;
487 } // switch (formatType)
488 } // case SL_DATALOCATOR_ANDROIDFD
492 case SL_DATALOCATOR_ADDRESS:
493 case SL_DATALOCATOR_IODEVICE:
494 case SL_DATALOCATOR_OUTPUTMIX:
495 case SL_DATALOCATOR_RESERVED5:
496 case SL_DATALOCATOR_MIDIBUFFERQUEUE:
497 case SL_DATALOCATOR_RESERVED8:
498 SL_LOGE("Cannot create audio player with data locator type 0x%x", (unsigned) locatorType);
499 return SL_RESULT_CONTENT_UNSUPPORTED;
501 return SL_RESULT_PARAMETER_INVALID;
502 }// switch (locatorType)
504 return SL_RESULT_SUCCESS;
509 //-----------------------------------------------------------------------------
510 static void audioTrack_callBack_uri(int event, void* user, void *info) {
511 // EVENT_MORE_DATA needs to be handled with priority over the other events
512 // because it will be called the most often during playback
513 if (event == android::AudioTrack::EVENT_MORE_DATA) {
514 //SL_LOGV("received event EVENT_MORE_DATA from AudioTrack");
515 // set size to 0 to signal we're not using the callback to write more data
516 android::AudioTrack::Buffer* pBuff = (android::AudioTrack::Buffer*)info;
518 } else if (NULL != user) {
520 case (android::AudioTrack::EVENT_MARKER) :
521 audioTrack_handleMarker_lockPlay((CAudioPlayer *)user);
523 case (android::AudioTrack::EVENT_NEW_POS) :
524 audioTrack_handleNewPos_lockPlay((CAudioPlayer *)user);
526 case (android::AudioTrack::EVENT_UNDERRUN) :
527 audioTrack_handleUnderrun_lockPlay((CAudioPlayer *)user);
530 SL_LOGE("Encountered unknown AudioTrack event %d for CAudioPlayer %p", event,
531 (CAudioPlayer *)user);
537 //-----------------------------------------------------------------------------
538 // Callback associated with an AudioTrack of an SL ES AudioPlayer that gets its data
539 // from a buffer queue.
540 static void audioTrack_callBack_pullFromBuffQueue(int event, void* user, void *info) {
541 CAudioPlayer *ap = (CAudioPlayer *)user;
542 void * callbackPContext = NULL;
545 case (android::AudioTrack::EVENT_MORE_DATA) : {
546 //SL_LOGV("received event EVENT_MORE_DATA from AudioTrack");
547 slBufferQueueCallback callback = NULL;
548 android::AudioTrack::Buffer* pBuff = (android::AudioTrack::Buffer*)info;
549 // retrieve data from the buffer queue
550 interface_lock_exclusive(&ap->mBufferQueue);
551 if (ap->mBufferQueue.mState.count != 0) {
552 //SL_LOGV("nbBuffers in queue = %lu",ap->mBufferQueue.mState.count);
553 assert(ap->mBufferQueue.mFront != ap->mBufferQueue.mRear);
555 BufferHeader *oldFront = ap->mBufferQueue.mFront;
556 BufferHeader *newFront = &oldFront[1];
558 // FIXME handle 8bit based on buffer format
559 short *pSrc = (short*)((char *)oldFront->mBuffer
560 + ap->mBufferQueue.mSizeConsumed);
561 if (ap->mBufferQueue.mSizeConsumed + pBuff->size < oldFront->mSize) {
562 // can't consume the whole or rest of the buffer in one shot
563 ap->mBufferQueue.mSizeConsumed += pBuff->size;
564 // leave pBuff->size untouched
566 // FIXME can we avoid holding the lock during the copy?
567 memcpy (pBuff->i16, pSrc, pBuff->size);
569 // finish consuming the buffer or consume the buffer in one shot
570 pBuff->size = oldFront->mSize - ap->mBufferQueue.mSizeConsumed;
571 ap->mBufferQueue.mSizeConsumed = 0;
574 &ap->mBufferQueue.mArray
575 [ap->mBufferQueue.mNumBuffers + 1])
577 newFront = ap->mBufferQueue.mArray;
579 ap->mBufferQueue.mFront = newFront;
581 ap->mBufferQueue.mState.count--;
582 ap->mBufferQueue.mState.playIndex++;
585 // FIXME can we avoid holding the lock during the copy?
586 memcpy (pBuff->i16, pSrc, pBuff->size);
588 // data has been consumed, and the buffer queue state has been updated
589 // we will notify the client if applicable
590 callback = ap->mBufferQueue.mCallback;
591 // save callback data
592 callbackPContext = ap->mBufferQueue.mContext;
594 } else { // empty queue
595 // signal no data available
598 // signal we're at the end of the content, but don't pause (see note in function)
599 audioPlayer_dispatch_headAtEnd_lockPlay(ap, false /*set state to paused?*/, false);
601 // signal underflow to prefetch status itf
602 if (IsInterfaceInitialized(&(ap->mObject), MPH_PREFETCHSTATUS)) {
603 audioPlayer_dispatch_prefetchStatus_lockPrefetch(ap, SL_PREFETCHSTATUS_UNDERFLOW,
607 // stop the track so it restarts playing faster when new data is enqueued
608 ap->mAudioTrack->stop();
610 interface_unlock_exclusive(&ap->mBufferQueue);
612 if (NULL != callback) {
613 (*callback)(&ap->mBufferQueue.mItf, callbackPContext);
618 case (android::AudioTrack::EVENT_MARKER) :
619 audioTrack_handleMarker_lockPlay(ap);
622 case (android::AudioTrack::EVENT_NEW_POS) :
623 audioTrack_handleNewPos_lockPlay(ap);
626 case (android::AudioTrack::EVENT_UNDERRUN) :
627 audioTrack_handleUnderrun_lockPlay(ap);
631 // FIXME where does the notification of SL_PLAYEVENT_HEADMOVING fit?
632 SL_LOGE("Encountered unknown AudioTrack event %d for CAudioPlayer %p", event,
633 (CAudioPlayer *)user);
639 //-----------------------------------------------------------------------------
640 SLresult android_audioPlayer_create(
641 CAudioPlayer *pAudioPlayer) {
643 const SLDataSource *pAudioSrc = &pAudioPlayer->mDataSource.u.mSource;
644 const SLDataSink *pAudioSnk = &pAudioPlayer->mDataSink.u.mSink;
645 SLresult result = SL_RESULT_SUCCESS;
647 //--------------------------------------
649 // currently only OutputMix sinks are supported
650 // this has been verified in sles_to_android_CheckAudioPlayerSourceSink
651 SLuint32 locatorType = *(SLuint32 *)pAudioSnk->pLocator;
652 if (SL_DATALOCATOR_OUTPUTMIX == locatorType) {
653 // FIXME possible race between the earlier check and here - should atomically link these
654 // commented out to fix the build
655 //pAudioPlayer->mEffectSend->mOutputMix = pAudioSnk->pLocator->mOutputMix.outputMix;
658 //--------------------------------------
660 locatorType = *(SLuint32 *)pAudioSrc->pLocator;
661 switch (locatorType) {
662 // -----------------------------------
663 // Buffer Queue to AudioTrack
664 case SL_DATALOCATOR_BUFFERQUEUE:
665 pAudioPlayer->mAndroidObjType = AUDIOTRACK_PULL;
666 pAudioPlayer->mpLock = new android::Mutex();
667 pAudioPlayer->mPlaybackRate.mCapabilities = SL_RATEPROP_NOPITCHCORAUDIO;
669 // -----------------------------------
670 // URI or FD to MediaPlayer
671 case SL_DATALOCATOR_URI:
672 case SL_DATALOCATOR_ANDROIDFD:
673 pAudioPlayer->mAndroidObjType = MEDIAPLAYER;
674 pAudioPlayer->mpLock = new android::Mutex();
675 pAudioPlayer->mPlaybackRate.mCapabilities = SL_RATEPROP_NOPITCHCORAUDIO;
678 pAudioPlayer->mAndroidObjType = INVALID_TYPE;
679 pAudioPlayer->mpLock = NULL;
680 pAudioPlayer->mPlaybackRate.mCapabilities = 0;
681 result = SL_RESULT_PARAMETER_INVALID;
685 pAudioPlayer->mAndroidObjState = ANDROID_UNINITIALIZED;
686 pAudioPlayer->mAudioTrack = NULL;
688 pAudioPlayer->mSfPlayer.clear();
689 pAudioPlayer->mRenderLooper.clear();
692 pAudioPlayer->mAmplFromVolLevel = 1.0f;
693 pAudioPlayer->mAmplFromStereoPos[0] = 1.0f;
694 pAudioPlayer->mAmplFromStereoPos[1] = 1.0f;
695 pAudioPlayer->mDirectLevel = 0; // no attenuation
696 pAudioPlayer->mAmplFromDirectLevel = 1.0f; // matches initial mDirectLevel value
703 //-----------------------------------------------------------------------------
704 SLresult android_audioPlayer_realize(CAudioPlayer *pAudioPlayer, SLboolean async) {
706 SLresult result = SL_RESULT_SUCCESS;
707 SL_LOGV("pAudioPlayer=%p", pAudioPlayer);
709 switch (pAudioPlayer->mAndroidObjType) {
710 //-----------------------------------
712 case AUDIOTRACK_PUSH:
713 case AUDIOTRACK_PULL:
715 // initialize platform-specific CAudioPlayer fields
717 SLDataLocator_BufferQueue *dl_bq = (SLDataLocator_BufferQueue *)
718 pAudioPlayer->mDynamicSource.mDataSource;
719 SLDataFormat_PCM *df_pcm = (SLDataFormat_PCM *)
720 pAudioPlayer->mDynamicSource.mDataSource->pFormat;
722 uint32_t sampleRate = sles_to_android_sampleRate(df_pcm->samplesPerSec);
724 pAudioPlayer->mAudioTrack = new android::AudioTrack(
725 pAudioPlayer->mAndroidStreamType.mStreamType, // streamType
726 sampleRate, // sampleRate
727 sles_to_android_sampleFormat(df_pcm->bitsPerSample), // format
728 sles_to_android_channelMask(df_pcm->numChannels, df_pcm->channelMask),//channel mask
729 0, // frameCount (here min)
731 audioTrack_callBack_pullFromBuffQueue, // callback
732 (void *) pAudioPlayer, // user
733 0); // FIXME find appropriate frame count // notificationFrame
734 android::status_t status = pAudioPlayer->mAudioTrack->initCheck();
735 if (status != android::NO_ERROR) {
736 SL_LOGE("AudioTrack::initCheck status %u", status);
737 result = SL_RESULT_CONTENT_UNSUPPORTED;
740 // initialize platform-independent CAudioPlayer fields
742 pAudioPlayer->mNumChannels = df_pcm->numChannels;
743 pAudioPlayer->mSampleRateMilliHz = df_pcm->samplesPerSec; // Note: bad field name in SL ES
746 //-----------------------------------
749 object_lock_exclusive(&pAudioPlayer->mObject);
750 pAudioPlayer->mAndroidObjState = ANDROID_PREPARING;
752 pAudioPlayer->mRenderLooper = new android::ALooper();
753 pAudioPlayer->mSfPlayer = new android::SfPlayer(pAudioPlayer->mRenderLooper);
754 pAudioPlayer->mSfPlayer->setNotifListener(sfplayer_handlePrefetchEvent,
755 (void*)pAudioPlayer /*notifUSer*/);
756 pAudioPlayer->mRenderLooper->registerHandler(pAudioPlayer->mSfPlayer);
757 pAudioPlayer->mRenderLooper->start(false /*runOnCallingThread*/, false /*canCallJava*/,
758 ANDROID_PRIORITY_AUDIO);
759 object_unlock_exclusive(&pAudioPlayer->mObject);
762 switch (pAudioPlayer->mDataSource.mLocator.mLocatorType) {
763 case SL_DATALOCATOR_URI:
764 pAudioPlayer->mSfPlayer->setDataSource(
765 (const char*)pAudioPlayer->mDataSource.mLocator.mURI.URI);
766 res = pAudioPlayer->mSfPlayer->prepare_sync();
768 case SL_DATALOCATOR_ANDROIDFD: {
769 int64_t offset = (int64_t)pAudioPlayer->mDataSource.mLocator.mFD.offset;
770 pAudioPlayer->mSfPlayer->setDataSource(
771 (int)pAudioPlayer->mDataSource.mLocator.mFD.fd,
772 offset == SL_DATALOCATOR_ANDROIDFD_USE_FILE_SIZE ?
773 (int64_t)SFPLAYER_FD_FIND_FILE_SIZE : offset,
774 (int64_t)pAudioPlayer->mDataSource.mLocator.mFD.length);
775 res = pAudioPlayer->mSfPlayer->prepare_sync();
778 res = ~SFPLAYER_SUCCESS;
782 object_lock_exclusive(&pAudioPlayer->mObject);
783 if (SFPLAYER_SUCCESS != res) {
784 pAudioPlayer->mAndroidObjState = ANDROID_UNINITIALIZED;
785 pAudioPlayer->mNumChannels = 0;
786 pAudioPlayer->mSampleRateMilliHz = 0;
787 pAudioPlayer->mAudioTrack = NULL;
789 // create audio track based on parameters retrieved from Stagefright
790 pAudioPlayer->mAudioTrack = new android::AudioTrack(
791 pAudioPlayer->mAndroidStreamType.mStreamType, // streamType
792 pAudioPlayer->mSfPlayer->getSampleRateHz(), // sampleRate
793 android::AudioSystem::PCM_16_BIT, // format
794 pAudioPlayer->mSfPlayer->getNumChannels() == 1 ? //channel mask
795 android::AudioSystem::CHANNEL_OUT_MONO :
796 android::AudioSystem::CHANNEL_OUT_STEREO,
797 0, // frameCount (here min)
799 audioTrack_callBack_uri, // callback
800 (void *) pAudioPlayer, // user
801 0); // notificationFrame
802 pAudioPlayer->mNumChannels = pAudioPlayer->mSfPlayer->getNumChannels();
803 pAudioPlayer->mSampleRateMilliHz =
804 android_to_sles_sampleRate(pAudioPlayer->mSfPlayer->getSampleRateHz());
805 pAudioPlayer->mSfPlayer->useAudioTrack(pAudioPlayer->mAudioTrack);
807 if (pAudioPlayer->mSfPlayer->wantPrefetch()) {
808 pAudioPlayer->mAndroidObjState = ANDROID_PREPARED;
810 pAudioPlayer->mAndroidObjState = ANDROID_READY;
813 object_unlock_exclusive(&pAudioPlayer->mObject);
818 SL_LOGE("Unexpected object type %d", pAudioPlayer->mAndroidObjType);
819 result = SL_RESULT_INTERNAL_ERROR;
825 if (ANDROID_UNINITIALIZED == pAudioPlayer->mAndroidObjState) {
828 // proceed with effect initialization
830 int sessionId = pAudioPlayer->mAudioTrack->getSessionId();
832 // FIXME use a table of effect descriptors when adding support for more effects
833 if (memcmp(SL_IID_EQUALIZER, &pAudioPlayer->mEqualizer.mEqDescriptor.type,
834 sizeof(effect_uuid_t)) == 0) {
835 SL_LOGV("Need to initialize EQ for AudioPlayer=%p", pAudioPlayer);
836 android_eq_init(sessionId, &pAudioPlayer->mEqualizer);
838 // initialize BassBoost
839 if (memcmp(SL_IID_BASSBOOST, &pAudioPlayer->mBassBoost.mBassBoostDescriptor.type,
840 sizeof(effect_uuid_t)) == 0) {
841 SL_LOGV("Need to initialize BassBoost for AudioPlayer=%p", pAudioPlayer);
842 android_bb_init(sessionId, &pAudioPlayer->mBassBoost);
844 // initialize Virtualizer
845 if (memcmp(SL_IID_VIRTUALIZER, &pAudioPlayer->mVirtualizer.mVirtualizerDescriptor.type,
846 sizeof(effect_uuid_t)) == 0) {
847 SL_LOGV("Need to initialize Virtualizer for AudioPlayer=%p", pAudioPlayer);
848 android_virt_init(sessionId, &pAudioPlayer->mVirtualizer);
851 // initialize EffectSend
852 // FIXME initialize EffectSend
858 //-----------------------------------------------------------------------------
860 * Called with a lock held on the CAudioPlayer
862 SLresult android_audioPlayer_setStreamType_l(CAudioPlayer *pAudioPlayer, SLuint32 type) {
863 SLresult result = SL_RESULT_SUCCESS;
864 SL_LOGV("android_audioPlayer_setStreamType %lu", type);
866 if (pAudioPlayer->mAudioTrack == NULL) {
867 return SL_RESULT_RESOURCE_ERROR;
869 if (type == android_to_sles_streamType(pAudioPlayer->mAudioTrack->streamType())) {
870 return SL_RESULT_SUCCESS;
873 int format = pAudioPlayer->mAudioTrack->format();
875 int sessionId = pAudioPlayer->mAudioTrack->getSessionId();
877 uint32_t sr = sles_to_android_sampleRate(pAudioPlayer->mSampleRateMilliHz);
879 pAudioPlayer->mAudioTrack->stop();
880 delete pAudioPlayer->mAudioTrack;
881 pAudioPlayer->mAudioTrack = new android::AudioTrack(
882 sles_to_android_streamType(type), // streamType
885 pAudioPlayer->mNumChannels== 1 ? //channel mask
886 android::AudioSystem::CHANNEL_OUT_MONO :
887 android::AudioSystem::CHANNEL_OUT_STEREO,
888 0, // frameCount (here min)
890 pAudioPlayer->mAndroidObjType == MEDIAPLAYER ? // callback
891 audioTrack_callBack_uri : audioTrack_callBack_pullFromBuffQueue,
892 (void *) pAudioPlayer, // user
893 0 // FIXME find appropriate frame count // notificationFrame
899 if (pAudioPlayer->mAndroidObjType == MEDIAPLAYER) {
900 pAudioPlayer->mSfPlayer->useAudioTrack(pAudioPlayer->mAudioTrack);
907 //-----------------------------------------------------------------------------
908 SLresult android_audioPlayer_destroy(CAudioPlayer *pAudioPlayer) {
909 SLresult result = SL_RESULT_SUCCESS;
910 SL_LOGV("android_audioPlayer_destroy(%p)", pAudioPlayer);
911 switch (pAudioPlayer->mAndroidObjType) {
912 //-----------------------------------
914 case AUDIOTRACK_PUSH:
915 case AUDIOTRACK_PULL:
918 //-----------------------------------
921 // FIXME group in one function?
922 if (pAudioPlayer->mSfPlayer != NULL) {
923 pAudioPlayer->mRenderLooper->stop();
924 pAudioPlayer->mRenderLooper->unregisterHandler(pAudioPlayer->mSfPlayer->id());
925 pAudioPlayer->mSfPlayer.clear();
926 pAudioPlayer->mRenderLooper.clear();
931 SL_LOGE("Unexpected object type %d", pAudioPlayer->mAndroidObjType);
932 result = SL_RESULT_INTERNAL_ERROR;
936 if (pAudioPlayer->mAudioTrack != NULL) {
937 pAudioPlayer->mAudioTrack->stop();
938 delete pAudioPlayer->mAudioTrack;
939 pAudioPlayer->mAudioTrack = NULL;
942 if (pAudioPlayer->mpLock != NULL) {
943 delete pAudioPlayer->mpLock;
944 pAudioPlayer->mpLock = NULL;
947 pAudioPlayer->mAndroidObjType = INVALID_TYPE;
950 // FIXME this shouldn't have to be done here, there should be an "interface destroy" hook,
951 // just like there is an interface init hook, to avoid memory leaks.
952 pAudioPlayer->mEqualizer.mEqEffect.clear();
953 pAudioPlayer->mBassBoost.mBassBoostEffect.clear();
954 pAudioPlayer->mVirtualizer.mVirtualizerEffect.clear();
955 if (!pAudioPlayer->mAndroidEffect.mEffects.isEmpty()) {
956 for (size_t i = 0 ; i < pAudioPlayer->mAndroidEffect.mEffects.size() ; i++) {
957 delete pAudioPlayer->mAndroidEffect.mEffects.valueAt(i);
959 pAudioPlayer->mAndroidEffect.mEffects.clear();
967 //-----------------------------------------------------------------------------
968 // called with no lock held
969 SLresult android_audioPlayer_setPlayRate(IPlaybackRate *pRateItf, SLpermille rate) {
970 SLresult result = SL_RESULT_SUCCESS;
971 CAudioPlayer *ap = (CAudioPlayer *)pRateItf->mThis;
972 switch(ap->mAndroidObjType) {
973 case AUDIOTRACK_PUSH:
974 case AUDIOTRACK_PULL:
976 // get the content sample rate
977 object_lock_peek(ap);
978 uint32_t contentRate =
979 sles_to_android_sampleRate(ap->mDataSource.mFormat.mPCM.samplesPerSec);
980 object_unlock_peek(ap);
981 // apply the SL ES playback rate on the AudioTrack as a factor of its content sample rate
983 if (ap->mAudioTrack != NULL) {
984 ap->mAudioTrack->setSampleRate(contentRate * (rate/1000.0f));
986 ap->mpLock->unlock();
991 SL_LOGE("Unexpected object type %d", ap->mAndroidObjType);
992 result = SL_RESULT_INTERNAL_ERROR;
999 //-----------------------------------------------------------------------------
1000 // called with no lock held
1001 SLresult android_audioPlayer_setPlaybackRateBehavior(IPlaybackRate *pRateItf,
1002 SLuint32 constraints) {
1003 SLresult result = SL_RESULT_SUCCESS;
1004 CAudioPlayer *ap = (CAudioPlayer *)pRateItf->mThis;
1005 switch(ap->mAndroidObjType) {
1006 case AUDIOTRACK_PUSH:
1007 case AUDIOTRACK_PULL:
1009 if (constraints != (constraints & SL_RATEPROP_NOPITCHCORAUDIO)) {
1010 result = SL_RESULT_FEATURE_UNSUPPORTED;
1014 SL_LOGE("Unexpected object type %d", ap->mAndroidObjType);
1015 result = SL_RESULT_INTERNAL_ERROR;
1022 //-----------------------------------------------------------------------------
1023 // called with no lock held
1024 SLresult android_audioPlayer_getCapabilitiesOfRate(IPlaybackRate *pRateItf,
1025 SLuint32 *pCapabilities) {
1026 CAudioPlayer *ap = (CAudioPlayer *)pRateItf->mThis;
1027 switch(ap->mAndroidObjType) {
1028 case AUDIOTRACK_PUSH:
1029 case AUDIOTRACK_PULL:
1031 *pCapabilities = SL_RATEPROP_NOPITCHCORAUDIO;
1037 return SL_RESULT_SUCCESS;
1041 //-----------------------------------------------------------------------------
1042 void android_audioPlayer_setPlayState(CAudioPlayer *ap) {
1043 SLuint32 state = ap->mPlay.mState;
1044 switch(ap->mAndroidObjType) {
1045 case AUDIOTRACK_PUSH:
1046 case AUDIOTRACK_PULL:
1048 case SL_PLAYSTATE_STOPPED:
1049 SL_LOGV("setting AudioPlayer to SL_PLAYSTATE_STOPPED");
1050 ap->mAudioTrack->stop();
1052 case SL_PLAYSTATE_PAUSED:
1053 SL_LOGV("setting AudioPlayer to SL_PLAYSTATE_PAUSED");
1054 ap->mAudioTrack->pause();
1056 case SL_PLAYSTATE_PLAYING:
1057 SL_LOGV("setting AudioPlayer to SL_PLAYSTATE_PLAYING");
1058 ap->mAudioTrack->start();
1061 // checked by caller, should not happen
1065 #ifndef USE_BACKPORT
1068 case SL_PLAYSTATE_STOPPED: {
1069 SL_LOGV("setting AudioPlayer to SL_PLAYSTATE_STOPPED");
1070 ap->mSfPlayer->stop();
1072 case SL_PLAYSTATE_PAUSED: {
1073 SL_LOGV("setting AudioPlayer to SL_PLAYSTATE_PAUSED");
1074 object_lock_peek(&ap);
1075 AndroidObject_state state = ap->mAndroidObjState;
1076 object_unlock_peek(&ap);
1078 case(ANDROID_UNINITIALIZED):
1079 case(ANDROID_PREPARING):
1080 ap->mSfPlayer->pause();
1082 case(ANDROID_PREPARED):
1083 ap->mSfPlayer->startPrefetch_async();
1084 case(ANDROID_PREFETCHING):
1085 case(ANDROID_READY):
1086 ap->mSfPlayer->pause();
1092 case SL_PLAYSTATE_PLAYING: {
1093 SL_LOGV("setting AudioPlayer to SL_PLAYSTATE_PLAYING");
1094 object_lock_peek(&ap);
1095 AndroidObject_state state = ap->mAndroidObjState;
1096 object_unlock_peek(&ap);
1097 // FIXME check in spec when playback is allowed to start in another state
1098 if (state >= ANDROID_READY) {
1099 ap->mSfPlayer->play();
1103 // checked by caller, should not happen
1114 //-----------------------------------------------------------------------------
1115 void android_audioPlayer_useEventMask(CAudioPlayer *ap) {
1116 IPlay *pPlayItf = &ap->mPlay;
1117 SLuint32 eventFlags = pPlayItf->mEventFlags;
1118 /*switch(ap->mAndroidObjType) {
1119 case AUDIOTRACK_PUSH:
1120 case AUDIOTRACK_PULL:*/
1122 if (NULL == ap->mAudioTrack) {
1126 if (eventFlags & SL_PLAYEVENT_HEADATMARKER) {
1127 ap->mAudioTrack->setMarkerPosition((uint32_t)((((int64_t)pPlayItf->mMarkerPosition
1128 * sles_to_android_sampleRate(ap->mSampleRateMilliHz)))/1000));
1131 ap->mAudioTrack->setMarkerPosition(0);
1134 if (eventFlags & SL_PLAYEVENT_HEADATNEWPOS) {
1135 ap->mAudioTrack->setPositionUpdatePeriod(
1136 (uint32_t)((((int64_t)pPlayItf->mPositionUpdatePeriod
1137 * sles_to_android_sampleRate(ap->mSampleRateMilliHz)))/1000));
1139 // clear periodic update
1140 ap->mAudioTrack->setPositionUpdatePeriod(0);
1143 if (eventFlags & SL_PLAYEVENT_HEADATEND) {
1144 // nothing to do for SL_PLAYEVENT_HEADATEND, callback event will be checked against mask
1147 if (eventFlags & SL_PLAYEVENT_HEADMOVING) {
1148 // FIXME support SL_PLAYEVENT_HEADMOVING
1149 SL_LOGE("[ FIXME: IPlay_SetCallbackEventsMask(SL_PLAYEVENT_HEADMOVING) on an "
1150 "SL_OBJECTID_AUDIOPLAYER to be implemented ]");
1152 if (eventFlags & SL_PLAYEVENT_HEADSTALLED) {
1153 // nothing to do for SL_PLAYEVENT_HEADSTALLED, callback event will be checked against mask
1159 //-----------------------------------------------------------------------------
1160 SLresult android_audioPlayer_getDuration(IPlay *pPlayItf, SLmillisecond *pDurMsec) {
1161 CAudioPlayer *ap = (CAudioPlayer *)pPlayItf->mThis;
1162 switch(ap->mAndroidObjType) {
1163 case AUDIOTRACK_PUSH:
1164 case AUDIOTRACK_PULL:
1165 *pDurMsec = SL_TIME_UNKNOWN;
1166 // FIXME if the data source is not a buffer queue, and the audio data is saved in
1167 // shared memory with the mixer process, the duration is the size of the buffer
1168 SL_LOGE("FIXME: android_audioPlayer_getDuration() verify if duration can be retrieved");
1170 #ifndef USE_BACKPORT
1172 int64_t durationUsec = ap->mSfPlayer->getDurationUsec();
1173 *pDurMsec = durationUsec == -1 ? SL_TIME_UNKNOWN : durationUsec / 1000;
1179 return SL_RESULT_SUCCESS;
1183 //-----------------------------------------------------------------------------
1184 void android_audioPlayer_getPosition(IPlay *pPlayItf, SLmillisecond *pPosMsec) {
1185 CAudioPlayer *ap = (CAudioPlayer *)pPlayItf->mThis;
1186 switch(ap->mAndroidObjType) {
1187 case AUDIOTRACK_PUSH:
1188 case AUDIOTRACK_PULL:
1189 uint32_t positionInFrames;
1190 ap->mAudioTrack->getPosition(&positionInFrames);
1191 if (ap->mSampleRateMilliHz == 0) {
1194 *pPosMsec = ((int64_t)positionInFrames * 1000) /
1195 sles_to_android_sampleRate(ap->mSampleRateMilliHz);
1199 *pPosMsec = ap->mSfPlayer->getPositionMsec();
1207 //-----------------------------------------------------------------------------
1208 void android_audioPlayer_seek(CAudioPlayer *pAudioPlayer, SLmillisecond posMsec) {
1209 switch(pAudioPlayer->mAndroidObjType) {
1210 case AUDIOTRACK_PUSH:
1211 case AUDIOTRACK_PULL:
1213 #ifndef USE_BACKPORT
1215 pAudioPlayer->mSfPlayer->seek(posMsec);
1224 //-----------------------------------------------------------------------------
1226 * Mutes or unmutes the Android media framework object associated with the CAudioPlayer that carries
1227 * the IVolume interface.
1229 * if ap->mMute is SL_BOOLEAN_FALSE, a call to this function was preceded by a call
1230 * to android_audioPlayer_volumeUpdate()
1232 static void android_audioPlayer_setMute(CAudioPlayer* ap) {
1233 android::AudioTrack *t = NULL;
1234 switch(ap->mAndroidObjType) {
1235 case AUDIOTRACK_PUSH:
1236 case AUDIOTRACK_PULL:
1238 t = ap->mAudioTrack;
1243 // when unmuting: volume levels have already been updated in IVolume_SetMute
1250 //-----------------------------------------------------------------------------
1251 SLresult android_audioPlayer_volumeUpdate(CAudioPlayer* ap) {
1252 android_audioPlayer_updateStereoVolume(ap);
1253 android_audioPlayer_setMute(ap);
1254 return SL_RESULT_SUCCESS;
1258 //-----------------------------------------------------------------------------
1259 void android_audioPlayer_bufferQueueRefilled(CAudioPlayer *ap) {
1260 // the AudioTrack associated with the AudioPlayer receiving audio from a PCM buffer
1261 // queue was stopped when the queue become empty, we restart as soon as a new buffer
1262 // has been enqueued since we're in playing state
1263 if (NULL != ap->mAudioTrack) {
1264 ap->mAudioTrack->start();
1267 // when the queue became empty, an underflow on the prefetch status itf was sent. Now the queue
1268 // has received new data, signal it has sufficient data
1269 if (IsInterfaceInitialized(&(ap->mObject), MPH_PREFETCHSTATUS)) {
1270 audioPlayer_dispatch_prefetchStatus_lockPrefetch(ap, SL_PREFETCHSTATUS_SUFFICIENTDATA,
1276 //-----------------------------------------------------------------------------
1278 * BufferQueue::Clear
1280 SLresult android_audioPlayerClear(CAudioPlayer *pAudioPlayer) {
1281 SLresult result = SL_RESULT_SUCCESS;
1283 switch (pAudioPlayer->mAndroidObjType) {
1284 //-----------------------------------
1286 case AUDIOTRACK_PULL:
1287 case AUDIOTRACK_PUSH:
1288 pAudioPlayer->mAudioTrack->flush();
1291 result = SL_RESULT_INTERNAL_ERROR;