*/
#include "sles_allinclusive.h"
-#include "android/AndroidBufferQueueSource.h"
#include "utils/RefBase.h"
#include "android_prompts.h"
if (NULL == user) {
return sizeConsumed;
}
- SL_LOGI("received %d bytes from decoder", size);
+ SL_LOGD("received %d bytes from decoder", size);
CAudioPlayer *ap = (CAudioPlayer *)user;
slBufferQueueCallback callback = NULL;
void * callbackPContext = NULL;
//-----------------------------------------------------------------------------
// Callback associated with an SfPlayer of an SL ES AudioPlayer that gets its data
// from a URI or FD, for prepare and prefetch events
-static void sfplayer_handlePrefetchEvent(int event, int data1, void* user) {
+static void sfplayer_handlePrefetchEvent(int event, int data1, int data2, void* user) {
if (NULL == user) {
return;
}
} else if (A_PLR_PCM_BQ == ap->mAndroidObjType) {
((android::AudioToCbRenderer*)ap->mAPlayer.get())->startPrefetch_async();
} else if (A_PLR_TS_ABQ == ap->mAndroidObjType) {
- SL_LOGI("Received SfPlayer::kEventPrepared from AVPlayer for CAudioPlayer %p", ap);
+ SL_LOGD("Received SfPlayer::kEventPrepared from AVPlayer for CAudioPlayer %p", ap);
}
ap->mAndroidObjState = ANDROID_READY;
static void audioTrack_callBack_uri(int event, void* user, void *info) {
// EVENT_MORE_DATA needs to be handled with priority over the other events
// because it will be called the most often during playback
+
if (event == android::AudioTrack::EVENT_MORE_DATA) {
//SL_LOGV("received event EVENT_MORE_DATA from AudioTrack");
// set size to 0 to signal we're not using the callback to write more data
android::AudioTrack::Buffer* pBuff = (android::AudioTrack::Buffer*)info;
pBuff->size = 0;
} else if (NULL != user) {
+ CAudioPlayer *ap = (CAudioPlayer *)user;
+ if (!ap->mAudioTrackProtector->enterCb()) {
+ // it is not safe to enter the callback (the track is about to go away)
+ return;
+ }
switch (event) {
case android::AudioTrack::EVENT_MARKER :
- audioTrack_handleMarker_lockPlay((CAudioPlayer *)user);
+ audioTrack_handleMarker_lockPlay(ap);
break;
case android::AudioTrack::EVENT_NEW_POS :
- audioTrack_handleNewPos_lockPlay((CAudioPlayer *)user);
+ audioTrack_handleNewPos_lockPlay(ap);
break;
case android::AudioTrack::EVENT_UNDERRUN :
- audioTrack_handleUnderrun_lockPlay((CAudioPlayer *)user);
+ audioTrack_handleUnderrun_lockPlay(ap);
break;
case android::AudioTrack::EVENT_BUFFER_END :
case android::AudioTrack::EVENT_LOOP_END :
break;
default:
SL_LOGE("Encountered unknown AudioTrack event %d for CAudioPlayer %p", event,
- (CAudioPlayer *)user);
+ ap);
break;
}
+ ap->mAudioTrackProtector->exitCb();
}
}
//-----------------------------------------------------------------------------
// Callback associated with an AudioTrack of an SL ES AudioPlayer that gets its data
-// from a buffer queue.
+// from a buffer queue. This will not be called once the AudioTrack has been destroyed.
static void audioTrack_callBack_pullFromBuffQueue(int event, void* user, void *info) {
CAudioPlayer *ap = (CAudioPlayer *)user;
+
+ if (!ap->mAudioTrackProtector->enterCb()) {
+ // it is not safe to enter the callback (the track is about to go away)
+ return;
+ }
+
void * callbackPContext = NULL;
switch(event) {
case android::AudioTrack::EVENT_MORE_DATA: {
- //SL_LOGV("received event EVENT_MORE_DATA from AudioTrack");
+ //SL_LOGV("received event EVENT_MORE_DATA from AudioTrack TID=%d", gettid());
slBufferQueueCallback callback = NULL;
android::AudioTrack::Buffer* pBuff = (android::AudioTrack::Buffer*)info;
+
// retrieve data from the buffer queue
interface_lock_exclusive(&ap->mBufferQueue);
+
if (ap->mBufferQueue.mState.count != 0) {
//SL_LOGV("nbBuffers in queue = %lu",ap->mBufferQueue.mState.count);
assert(ap->mBufferQueue.mFront != ap->mBufferQueue.mRear);
ap->mAudioTrack->stop();
}
interface_unlock_exclusive(&ap->mBufferQueue);
+
// notify client
if (NULL != callback) {
(*callback)(&ap->mBufferQueue.mItf, callbackPContext);
break;
case android::AudioTrack::EVENT_MARKER:
+ //SL_LOGI("received event EVENT_MARKER from AudioTrack");
audioTrack_handleMarker_lockPlay(ap);
break;
case android::AudioTrack::EVENT_NEW_POS:
+ //SL_LOGI("received event EVENT_NEW_POS from AudioTrack");
audioTrack_handleNewPos_lockPlay(ap);
break;
case android::AudioTrack::EVENT_UNDERRUN:
+ //SL_LOGI("received event EVENT_UNDERRUN from AudioTrack");
audioTrack_handleUnderrun_lockPlay(ap);
break;
(CAudioPlayer *)user);
break;
}
+
+ ap->mAudioTrackProtector->exitCb();
}
// not needed, as placement new (explicit constructor) already does this
// pAudioPlayer->mSfPlayer.clear();
+ pAudioPlayer->mAudioTrackProtector = new android::AudioTrackProtector();
+
pAudioPlayer->mSessionId = android::AudioSystem::newAudioSessionId();
pAudioPlayer->mAmplFromVolLevel = 1.0f;
//-----------------------------------------------------------------------------
+/**
+ * Called with a lock on AudioPlayer
+ */
+SLresult android_audioPlayer_preDestroy(CAudioPlayer *pAudioPlayer) {
+ SLresult result = SL_RESULT_SUCCESS;
+
+ object_unlock_exclusive(&pAudioPlayer->mObject);
+ if (pAudioPlayer->mAudioTrackProtector != 0) {
+ pAudioPlayer->mAudioTrackProtector->requestCbExitAndWait();
+ }
+ object_lock_exclusive(&pAudioPlayer->mObject);
+
+ return result;
+}
+
+
+//-----------------------------------------------------------------------------
SLresult android_audioPlayer_destroy(CAudioPlayer *pAudioPlayer) {
SLresult result = SL_RESULT_SUCCESS;
SL_LOGV("android_audioPlayer_destroy(%p)", pAudioPlayer);
break;
}
+ pAudioPlayer->mAudioTrackProtector.clear();
+
// FIXME might not be needed
pAudioPlayer->mAndroidObjType = INVALID_TYPE;
// explicit destructor
+ pAudioPlayer->mAudioTrackProtector.~sp();
pAudioPlayer->mSfPlayer.~sp();
pAudioPlayer->mAuxEffect.~sp();
pAudioPlayer->mAPlayer.~sp();
case ANDROID_UNINITIALIZED:
sfplayer_prepare(ap, lockAP);
break;
- caseANDROID_PREPARING:
+ case ANDROID_PREPARING:
break;
case ANDROID_READY:
if (ap->mSfPlayer != 0) {
int64_t durationUsec = SL_TIME_UNKNOWN;
if (ap->mSfPlayer != 0) {
durationUsec = ap->mSfPlayer->getDurationUsec();
- *pDurMsec = durationUsec == -1 ? SL_TIME_UNKNOWN : durationUsec / 1000;
}
+ *pDurMsec = durationUsec == -1 ? SL_TIME_UNKNOWN : durationUsec / 1000;
}
break;
+ case A_PLR_TS_ABQ: // intended fall-through
default:
+ *pDurMsec = SL_TIME_UNKNOWN;
break;
}
return SL_RESULT_SUCCESS;
//-----------------------------------------------------------------------------
-void android_audioPlayer_bufferQueue_onRefilled(CAudioPlayer *ap) {
+void android_audioPlayer_bufferQueue_onRefilled_l(CAudioPlayer *ap) {
// the AudioTrack associated with the AudioPlayer receiving audio from a PCM buffer
// queue was stopped when the queue become empty, we restart as soon as a new buffer
// has been enqueued since we're in playing state
//-----------------------------------------------------------------------------
-// abqSrc_callBack_pullFromBuffQueue is implemented in AndroidBufferQueueSource.cpp
void android_audioPlayer_androidBufferQueue_registerCallback_l(CAudioPlayer *ap) {
if ((ap->mAndroidObjType == A_PLR_TS_ABQ) && (ap->mAPlayer != 0)) {
android::StreamPlayer* splr = static_cast<android::StreamPlayer*>(ap->mAPlayer.get());
splr->registerQueueCallback(
- ap->mAndroidBufferQueue.mCallback,
- abqSrc_callBack_pullFromBuffQueue,
(const void*)ap, true /*userIsAudioPlayer*/,
ap->mAndroidBufferQueue.mContext,
(const void*)&(ap->mAndroidBufferQueue.mItf));
//-----------------------------------------------------------------------------
void android_audioPlayer_androidBufferQueue_clear_l(CAudioPlayer *ap) {
- if (ap->mAndroidObjType == A_PLR_TS_ABQ) {
- android_StreamPlayer_clear_l(ap);
+ if ((ap->mAndroidObjType == A_PLR_TS_ABQ) && (ap->mAPlayer != 0)) {
+ android::StreamPlayer* splr = static_cast<android::StreamPlayer*>(ap->mAPlayer.get());
+ splr->appClear_l();
}
}
-void android_audioPlayer_androidBufferQueue_enqueue_l(CAudioPlayer *ap,
- SLuint32 bufferId, SLuint32 length, SLuint32 event, void *pData) {
- if (ap->mAndroidObjType == A_PLR_TS_ABQ) {
- android_StreamPlayer_enqueue_l(ap, bufferId, length, event, pData);
+void android_audioPlayer_androidBufferQueue_onRefilled_l(CAudioPlayer *ap) {
+ if ((ap->mAndroidObjType == A_PLR_TS_ABQ) && (ap->mAPlayer != 0)) {
+ android::StreamPlayer* splr = static_cast<android::StreamPlayer*>(ap->mAPlayer.get());
+ splr->queueRefilled_l();
}
}