IBufferQueue.c revision a3080daa505f91df51a808c85ddb37c48745bf7c
10b167267bda99b68346045ccab14e810121d5de4Glenn Kasten/*
20b167267bda99b68346045ccab14e810121d5de4Glenn Kasten * Copyright (C) 2010 The Android Open Source Project
30b167267bda99b68346045ccab14e810121d5de4Glenn Kasten *
40b167267bda99b68346045ccab14e810121d5de4Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
50b167267bda99b68346045ccab14e810121d5de4Glenn Kasten * you may not use this file except in compliance with the License.
60b167267bda99b68346045ccab14e810121d5de4Glenn Kasten * You may obtain a copy of the License at
70b167267bda99b68346045ccab14e810121d5de4Glenn Kasten *
80b167267bda99b68346045ccab14e810121d5de4Glenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
90b167267bda99b68346045ccab14e810121d5de4Glenn Kasten *
100b167267bda99b68346045ccab14e810121d5de4Glenn Kasten * Unless required by applicable law or agreed to in writing, software
110b167267bda99b68346045ccab14e810121d5de4Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
120b167267bda99b68346045ccab14e810121d5de4Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130b167267bda99b68346045ccab14e810121d5de4Glenn Kasten * See the License for the specific language governing permissions and
140b167267bda99b68346045ccab14e810121d5de4Glenn Kasten * limitations under the License.
150b167267bda99b68346045ccab14e810121d5de4Glenn Kasten */
160b167267bda99b68346045ccab14e810121d5de4Glenn Kasten
170b167267bda99b68346045ccab14e810121d5de4Glenn Kasten/* BufferQueue implementation */
180b167267bda99b68346045ccab14e810121d5de4Glenn Kasten
190b167267bda99b68346045ccab14e810121d5de4Glenn Kasten#include "sles_allinclusive.h"
200b167267bda99b68346045ccab14e810121d5de4Glenn Kasten
21ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
224b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten/** Determine the state of the audio player or audio recorder associated with a buffer queue.
234b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten *  Note that PLAYSTATE and RECORDSTATE values are equivalent (where PLAYING == RECORDING).
244b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten */
254b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
264b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kastenstatic SLuint32 getAssociatedState(IBufferQueue *this)
274b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten{
284b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    SLuint32 state;
294b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    switch (InterfaceToObjectID(this)) {
304b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    case SL_OBJECTID_AUDIOPLAYER:
314b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        state = ((CAudioPlayer *) this->mThis)->mPlay.mState;
324b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        break;
334b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    case SL_OBJECTID_AUDIORECORDER:
344b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        state = ((CAudioRecorder *) this->mThis)->mRecord.mState;
354b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        break;
364b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    default:
374b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        // unreachable, but just in case we will assume it is stopped
384b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        assert(SL_BOOLEAN_FALSE);
394b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        state = SL_PLAYSTATE_STOPPED;
404b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        break;
414b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    }
424b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    return state;
434b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten}
444b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
454b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
46e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn KastenSLresult IBufferQueue_Enqueue(SLBufferQueueItf self, const void *pBuffer, SLuint32 size)
470b167267bda99b68346045ccab14e810121d5de4Glenn Kasten{
48ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
493af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    //SL_LOGV("IBufferQueue_Enqueue(%p, %p, %lu)", self, pBuffer, size);
50ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
514b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    // Note that Enqueue while a Clear is pending is equivalent to Enqueue followed by Clear
524b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
53ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pBuffer || 0 == size) {
54ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
550b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    } else {
56ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IBufferQueue *this = (IBufferQueue *) self;
57ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        interface_lock_exclusive(this);
58ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        BufferHeader *oldRear = this->mRear, *newRear;
59a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten        if ((newRear = oldRear + 1) == &this->mArray[this->mNumBuffers + 1]) {
60ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            newRear = this->mArray;
61a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten        }
62ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (newRear == this->mFront) {
63ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_BUFFER_INSUFFICIENT;
64ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
65ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            oldRear->mBuffer = pBuffer;
66ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            oldRear->mSize = size;
67ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            this->mRear = newRear;
68ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            ++this->mState.count;
69ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_SUCCESS;
70ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
714b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        // set enqueue attribute if state is PLAYING and the first buffer is enqueued
724b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        interface_unlock_exclusive_attributes(this, ((SL_RESULT_SUCCESS == result) &&
734b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            (1 == this->mState.count) && (SL_PLAYSTATE_PLAYING == getAssociatedState(this))) ?
744b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            ATTR_ENQUEUE : ATTR_NONE);
750b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    }
76ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
770b167267bda99b68346045ccab14e810121d5de4Glenn Kasten}
780b167267bda99b68346045ccab14e810121d5de4Glenn Kasten
79ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
80e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn KastenSLresult IBufferQueue_Clear(SLBufferQueueItf self)
810b167267bda99b68346045ccab14e810121d5de4Glenn Kasten{
82ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
83ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
844b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    result = SL_RESULT_SUCCESS;
850b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IBufferQueue *this = (IBufferQueue *) self;
860b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    interface_lock_exclusive(this);
874b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
88ef8931ae547cd703e69df9ad350d69825da0f546Jean-Michel Trivi#ifdef ANDROID
894b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    if (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) {
904b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        CAudioPlayer *audioPlayer = (CAudioPlayer *) this->mThis;
914b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        // flush associated audio player
924b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        result = android_audioPlayerClear(audioPlayer);
934b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        if (SL_RESULT_SUCCESS == result) {
944b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            this->mFront = &this->mArray[0];
954b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            this->mRear = &this->mArray[0];
964b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            this->mState.count = 0;
974f064c143ef2b26347130a49788116b5d2e1252aGlenn Kasten            this->mState.playIndex = 0;
984b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten            this->mSizeConsumed = 0;
994b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        }
1004b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    }
1014b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten#endif
1024b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
1034b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten#ifdef USE_OUTPUTMIXEXT
1044b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    // mixer might be reading from the front buffer, so tread carefully here
1054b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    // NTH asynchronous cancel instead of blocking until mixer acknowledges
1064b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    this->mClearRequested = SL_BOOLEAN_TRUE;
107a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten    do {
1084b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        interface_cond_wait(this);
109a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten    } while (this->mClearRequested);
1106a7bf7733e955d4d89204627c34fb357d542a9ecJean-Michel Trivi#endif
1114b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
1120b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    interface_unlock_exclusive(this);
113ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
114ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
1150b167267bda99b68346045ccab14e810121d5de4Glenn Kasten}
1160b167267bda99b68346045ccab14e810121d5de4Glenn Kasten
117ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
118ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kastenstatic SLresult IBufferQueue_GetState(SLBufferQueueItf self, SLBufferQueueState *pState)
1190b167267bda99b68346045ccab14e810121d5de4Glenn Kasten{
120ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
121ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1224b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    // Note that GetState while a Clear is pending is equivalent to GetState before the Clear
1234b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten
124ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pState) {
125ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
126ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
127ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IBufferQueue *this = (IBufferQueue *) self;
128ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        SLBufferQueueState state;
129ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        interface_lock_shared(this);
1300b167267bda99b68346045ccab14e810121d5de4Glenn Kasten#ifdef __cplusplus // FIXME Is this a compiler bug?
131ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        state.count = this->mState.count;
132ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        state.playIndex = this->mState.playIndex;
1330b167267bda99b68346045ccab14e810121d5de4Glenn Kasten#else
134ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        state = this->mState;
1350b167267bda99b68346045ccab14e810121d5de4Glenn Kasten#endif
136ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        interface_unlock_shared(this);
137ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        *pState = state;
138ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_SUCCESS;
139ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
140ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
141ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
1420b167267bda99b68346045ccab14e810121d5de4Glenn Kasten}
1430b167267bda99b68346045ccab14e810121d5de4Glenn Kasten
144ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
145e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn KastenSLresult IBufferQueue_RegisterCallback(SLBufferQueueItf self,
1460b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    slBufferQueueCallback callback, void *pContext)
1470b167267bda99b68346045ccab14e810121d5de4Glenn Kasten{
148ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
149ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1500b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IBufferQueue *this = (IBufferQueue *) self;
1510b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    interface_lock_exclusive(this);
1524b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    // verify pre-condition that media object is in the SL_PLAYSTATE_STOPPED state
1534b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    if (SL_PLAYSTATE_STOPPED == getAssociatedState(this)) {
1544b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        this->mCallback = callback;
1554b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        this->mContext = pContext;
1564b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        result = SL_RESULT_SUCCESS;
1574b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    } else {
1584b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
1594b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    }
1600b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    interface_unlock_exclusive(this);
161ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
162ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
1630b167267bda99b68346045ccab14e810121d5de4Glenn Kasten}
1640b167267bda99b68346045ccab14e810121d5de4Glenn Kasten
165ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
1660b167267bda99b68346045ccab14e810121d5de4Glenn Kastenstatic const struct SLBufferQueueItf_ IBufferQueue_Itf = {
1670b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IBufferQueue_Enqueue,
1680b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IBufferQueue_Clear,
1690b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IBufferQueue_GetState,
1700b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IBufferQueue_RegisterCallback
1710b167267bda99b68346045ccab14e810121d5de4Glenn Kasten};
1720b167267bda99b68346045ccab14e810121d5de4Glenn Kasten
1730b167267bda99b68346045ccab14e810121d5de4Glenn Kastenvoid IBufferQueue_init(void *self)
1740b167267bda99b68346045ccab14e810121d5de4Glenn Kasten{
1753af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    //SL_LOGV("IBufferQueue_init(%p) entering", self);
1760b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    IBufferQueue *this = (IBufferQueue *) self;
1770b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    this->mItf = &IBufferQueue_Itf;
1780b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    this->mState.count = 0;
1790b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    this->mState.playIndex = 0;
1800b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    this->mCallback = NULL;
1810b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    this->mContext = NULL;
1820b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    this->mNumBuffers = 0;
1834b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten    this->mClearRequested = SL_BOOLEAN_FALSE;
1840b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    this->mArray = NULL;
1850b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    this->mFront = NULL;
1860b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    this->mRear = NULL;
1874b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten#ifdef ANDROID
1880b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    this->mSizeConsumed = 0;
1894b65ef9efdf5aba01bea89d8cdd64f500560a28dGlenn Kasten#endif
190d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten    BufferHeader *bufferHeader = this->mTypical;
1910b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    unsigned i;
1920b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    for (i = 0; i < BUFFER_HEADER_TYPICAL+1; ++i, ++bufferHeader) {
1930b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        bufferHeader->mBuffer = NULL;
1940b167267bda99b68346045ccab14e810121d5de4Glenn Kasten        bufferHeader->mSize = 0;
1950b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    }
1960b167267bda99b68346045ccab14e810121d5de4Glenn Kasten}
197a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
198a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
199a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten/** \brief Free the buffer queue, if it was larger than typical.
200a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten  * Called by CAudioPlayer_Destroy and CAudioRecorder_Destroy.
201a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten  */
202a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten
203a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kastenvoid IBufferQueue_Destroy(IBufferQueue *this)
204a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten{
205a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten    if ((NULL != this->mArray) && (this->mArray != this->mTypical)) {
206a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten        free(this->mArray);
207a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten        this->mArray = NULL;
208a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten    }
209a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten}
210