14c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten/*
24c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten * Copyright (C) 2010 The Android Open Source Project
34c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten *
44c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
54c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten * you may not use this file except in compliance with the License.
64c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten * You may obtain a copy of the License at
74c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten *
84c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
94c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten *
104c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten * Unless required by applicable law or agreed to in writing, software
114c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
124c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten * See the License for the specific language governing permissions and
144c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten * limitations under the License.
154c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten */
164c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten
174c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten/* BufferQueue implementation */
184c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten
194c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten#include "sles_allinclusive.h"
204c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten
21f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
2223c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten/** Determine the state of the audio player or audio recorder associated with a buffer queue.
2323c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten *  Note that PLAYSTATE and RECORDSTATE values are equivalent (where PLAYING == RECORDING).
2423c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten */
2523c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
2650bccde01980ae803b8656e8b08ecacb65540f50Glenn Kastenstatic SLuint32 getAssociatedState(IBufferQueue *thiz)
2723c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten{
2823c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    SLuint32 state;
2950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    switch (InterfaceToObjectID(thiz)) {
3023c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    case SL_OBJECTID_AUDIOPLAYER:
3150bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        state = ((CAudioPlayer *) thiz->mThis)->mPlay.mState;
3223c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        break;
3323c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    case SL_OBJECTID_AUDIORECORDER:
3450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        state = ((CAudioRecorder *) thiz->mThis)->mRecord.mState;
3523c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        break;
3623c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    default:
3723c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        // unreachable, but just in case we will assume it is stopped
3823c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        assert(SL_BOOLEAN_FALSE);
3923c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        state = SL_PLAYSTATE_STOPPED;
4023c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        break;
4123c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    }
4223c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    return state;
4323c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten}
4423c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
4523c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
469c03f04a9c6cc2a821182c8be8f2efe964a27efeGlenn KastenSLresult IBufferQueue_Enqueue(SLBufferQueueItf self, const void *pBuffer, SLuint32 size)
474c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten{
48f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_ENTER_INTERFACE
491c17ec55f629fdab909ab16d94e014f098369110Glenn Kasten    //SL_LOGV("IBufferQueue_Enqueue(%p, %p, %u)", self, pBuffer, size);
50f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
5123c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    // Note that Enqueue while a Clear is pending is equivalent to Enqueue followed by Clear
5223c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
53f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    if (NULL == pBuffer || 0 == size) {
54f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
554c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    } else {
5650bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        IBufferQueue *thiz = (IBufferQueue *) self;
5750bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        interface_lock_exclusive(thiz);
5850bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        BufferHeader *oldRear = thiz->mRear, *newRear;
5950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        if ((newRear = oldRear + 1) == &thiz->mArray[thiz->mNumBuffers + 1]) {
6050bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten            newRear = thiz->mArray;
6151cb31b09f6af53402b3fbe7e9de29badc1155a2Glenn Kasten        }
6250bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        if (newRear == thiz->mFront) {
63f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            result = SL_RESULT_BUFFER_INSUFFICIENT;
64f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        } else {
65f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            oldRear->mBuffer = pBuffer;
66f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            oldRear->mSize = size;
6750bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten            thiz->mRear = newRear;
6850bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten            ++thiz->mState.count;
69f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            result = SL_RESULT_SUCCESS;
70f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        }
7123c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        // set enqueue attribute if state is PLAYING and the first buffer is enqueued
7250bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        interface_unlock_exclusive_attributes(thiz, ((SL_RESULT_SUCCESS == result) &&
7350bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten            (1 == thiz->mState.count) && (SL_PLAYSTATE_PLAYING == getAssociatedState(thiz))) ?
74f65b260193e5ca669ec4479a7e1c4517e18cc6b0Jean-Michel Trivi            ATTR_BQ_ENQUEUE : ATTR_NONE);
754c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    }
76f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_LEAVE_INTERFACE
774c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten}
784c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten
79f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
809c03f04a9c6cc2a821182c8be8f2efe964a27efeGlenn KastenSLresult IBufferQueue_Clear(SLBufferQueueItf self)
814c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten{
82f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_ENTER_INTERFACE
83f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
8423c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    result = SL_RESULT_SUCCESS;
8550bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    IBufferQueue *thiz = (IBufferQueue *) self;
8650bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    interface_lock_exclusive(thiz);
8723c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
889db8335361c67c4ed877f68218835df96ce43a4bJean-Michel Trivi#ifdef ANDROID
8950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    if (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) {
9050bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        CAudioPlayer *audioPlayer = (CAudioPlayer *) thiz->mThis;
9123c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        // flush associated audio player
92614d5407d3fac1dae8975722f25e671642041282Jean-Michel Trivi        result = android_audioPlayer_bufferQueue_onClear(audioPlayer);
9323c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        if (SL_RESULT_SUCCESS == result) {
9450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten            thiz->mFront = &thiz->mArray[0];
9550bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten            thiz->mRear = &thiz->mArray[0];
9650bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten            thiz->mState.count = 0;
9750bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten            thiz->mState.playIndex = 0;
9850bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten            thiz->mSizeConsumed = 0;
9923c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        }
10023c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    }
10123c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten#endif
10223c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
10323c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten#ifdef USE_OUTPUTMIXEXT
10423c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    // mixer might be reading from the front buffer, so tread carefully here
10523c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    // NTH asynchronous cancel instead of blocking until mixer acknowledges
10650bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mClearRequested = SL_BOOLEAN_TRUE;
10751cb31b09f6af53402b3fbe7e9de29badc1155a2Glenn Kasten    do {
10850bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        interface_cond_wait(thiz);
10950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    } while (thiz->mClearRequested);
110d99183b5bbafc783e0a14ee12ce107326051811bJean-Michel Trivi#endif
11123c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
11250bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    interface_unlock_exclusive(thiz);
113f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
114f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_LEAVE_INTERFACE
1154c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten}
1164c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten
117f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
118f156301680273e71e56e898f98798f5b5b2431f6Glenn Kastenstatic SLresult IBufferQueue_GetState(SLBufferQueueItf self, SLBufferQueueState *pState)
1194c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten{
120f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_ENTER_INTERFACE
121f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
12223c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    // Note that GetState while a Clear is pending is equivalent to GetState before the Clear
12323c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
124f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    if (NULL == pState) {
125f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
126f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    } else {
12750bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        IBufferQueue *thiz = (IBufferQueue *) self;
128f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        SLBufferQueueState state;
12950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        interface_lock_shared(thiz);
1304c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten#ifdef __cplusplus // FIXME Is this a compiler bug?
13150bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        state.count = thiz->mState.count;
13250bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        state.playIndex = thiz->mState.playIndex;
1334c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten#else
13450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        state = thiz->mState;
1354c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten#endif
13650bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        interface_unlock_shared(thiz);
137f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        *pState = state;
138f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_SUCCESS;
139f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    }
140f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
141f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_LEAVE_INTERFACE
1424c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten}
1434c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten
144f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
1459c03f04a9c6cc2a821182c8be8f2efe964a27efeGlenn KastenSLresult IBufferQueue_RegisterCallback(SLBufferQueueItf self,
1464c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    slBufferQueueCallback callback, void *pContext)
1474c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten{
148f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_ENTER_INTERFACE
149f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
15050bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    IBufferQueue *thiz = (IBufferQueue *) self;
15150bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    interface_lock_exclusive(thiz);
15223c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    // verify pre-condition that media object is in the SL_PLAYSTATE_STOPPED state
15350bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    if (SL_PLAYSTATE_STOPPED == getAssociatedState(thiz)) {
15450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mCallback = callback;
15550bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mContext = pContext;
15623c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        result = SL_RESULT_SUCCESS;
15723c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    } else {
15823c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
15923c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    }
16050bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    interface_unlock_exclusive(thiz);
161f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
162f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_LEAVE_INTERFACE
1634c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten}
1644c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten
165f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
1664c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kastenstatic const struct SLBufferQueueItf_ IBufferQueue_Itf = {
1674c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    IBufferQueue_Enqueue,
1684c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    IBufferQueue_Clear,
1694c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    IBufferQueue_GetState,
1704c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    IBufferQueue_RegisterCallback
1714c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten};
1724c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten
1734c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kastenvoid IBufferQueue_init(void *self)
1744c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten{
17550bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    IBufferQueue *thiz = (IBufferQueue *) self;
17650bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mItf = &IBufferQueue_Itf;
17750bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mState.count = 0;
17850bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mState.playIndex = 0;
17950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mCallback = NULL;
18050bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mContext = NULL;
18150bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mNumBuffers = 0;
18250bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mClearRequested = SL_BOOLEAN_FALSE;
18350bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mArray = NULL;
18450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mFront = NULL;
18550bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mRear = NULL;
18623c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten#ifdef ANDROID
18750bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mSizeConsumed = 0;
18823c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten#endif
18950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    BufferHeader *bufferHeader = thiz->mTypical;
1904c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    unsigned i;
1914c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    for (i = 0; i < BUFFER_HEADER_TYPICAL+1; ++i, ++bufferHeader) {
1924c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten        bufferHeader->mBuffer = NULL;
1934c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten        bufferHeader->mSize = 0;
1944c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    }
1954c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten}
19651cb31b09f6af53402b3fbe7e9de29badc1155a2Glenn Kasten
19751cb31b09f6af53402b3fbe7e9de29badc1155a2Glenn Kasten
1982a25d97e40dbd5dd9195195a3a269095a4932097Glenn Kasten/** \brief Interface deinitialization hook called by IObject::Destroy.
1992a25d97e40dbd5dd9195195a3a269095a4932097Glenn Kasten *  Free the buffer queue, if it was larger than typical.
2002a25d97e40dbd5dd9195195a3a269095a4932097Glenn Kasten */
20151cb31b09f6af53402b3fbe7e9de29badc1155a2Glenn Kasten
2022a25d97e40dbd5dd9195195a3a269095a4932097Glenn Kastenvoid IBufferQueue_deinit(void *self)
20351cb31b09f6af53402b3fbe7e9de29badc1155a2Glenn Kasten{
20450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    IBufferQueue *thiz = (IBufferQueue *) self;
20550bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    if ((NULL != thiz->mArray) && (thiz->mArray != thiz->mTypical)) {
20650bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        free(thiz->mArray);
20750bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mArray = NULL;
20851cb31b09f6af53402b3fbe7e9de29badc1155a2Glenn Kasten    }
20951cb31b09f6af53402b3fbe7e9de29badc1155a2Glenn Kasten}
210