IBufferQueue.c revision 9c03f04a9c6cc2a821182c8be8f2efe964a27efe
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
2623c38816f7c210afae5072fd44658c98fec7e119Glenn Kastenstatic SLuint32 getAssociatedState(IBufferQueue *this)
2723c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten{
2823c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    SLuint32 state;
2923c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    switch (InterfaceToObjectID(this)) {
3023c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    case SL_OBJECTID_AUDIOPLAYER:
3123c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        state = ((CAudioPlayer *) this->mThis)->mPlay.mState;
3223c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        break;
3323c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    case SL_OBJECTID_AUDIORECORDER:
3423c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        state = ((CAudioRecorder *) this->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
49bdb243c16be832f5853083480965a437b81df3c8Jean-Michel Trivi    //SL_LOGV("IBufferQueue_Enqueue(%p, %p, %lu)", 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 {
56f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        IBufferQueue *this = (IBufferQueue *) self;
57f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        interface_lock_exclusive(this);
58f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        BufferHeader *oldRear = this->mRear, *newRear;
59f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        if ((newRear = oldRear + 1) == &this->mArray[this->mNumBuffers + 1])
60f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            newRear = this->mArray;
61f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        if (newRear == this->mFront) {
62f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            result = SL_RESULT_BUFFER_INSUFFICIENT;
63f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        } else {
64f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            oldRear->mBuffer = pBuffer;
65f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            oldRear->mSize = size;
66f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            this->mRear = newRear;
67f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            ++this->mState.count;
68f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            result = SL_RESULT_SUCCESS;
69f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        }
7023c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        // set enqueue attribute if state is PLAYING and the first buffer is enqueued
7123c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        interface_unlock_exclusive_attributes(this, ((SL_RESULT_SUCCESS == result) &&
7223c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten            (1 == this->mState.count) && (SL_PLAYSTATE_PLAYING == getAssociatedState(this))) ?
7323c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten            ATTR_ENQUEUE : ATTR_NONE);
744c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    }
75f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_LEAVE_INTERFACE
764c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten}
774c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten
78f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
799c03f04a9c6cc2a821182c8be8f2efe964a27efeGlenn KastenSLresult IBufferQueue_Clear(SLBufferQueueItf self)
804c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten{
81f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_ENTER_INTERFACE
82f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
8323c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    result = SL_RESULT_SUCCESS;
844c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    IBufferQueue *this = (IBufferQueue *) self;
854c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    interface_lock_exclusive(this);
8623c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
879db8335361c67c4ed877f68218835df96ce43a4bJean-Michel Trivi#ifdef ANDROID
8823c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    if (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) {
8923c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        CAudioPlayer *audioPlayer = (CAudioPlayer *) this->mThis;
9023c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        // flush associated audio player
9123c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        result = android_audioPlayerClear(audioPlayer);
9223c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        if (SL_RESULT_SUCCESS == result) {
9323c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten            this->mFront = &this->mArray[0];
9423c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten            this->mRear = &this->mArray[0];
9523c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten            this->mState.count = 0;
9623c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten            this->mSizeConsumed = 0;
9723c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        }
9823c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    }
9923c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten#endif
10023c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
10123c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten#ifdef USE_OUTPUTMIXEXT
10223c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    // mixer might be reading from the front buffer, so tread carefully here
10323c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    // NTH asynchronous cancel instead of blocking until mixer acknowledges
10423c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    this->mClearRequested = SL_BOOLEAN_TRUE;
10523c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    do
10623c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        interface_cond_wait(this);
10723c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    while (this->mClearRequested);
108d99183b5bbafc783e0a14ee12ce107326051811bJean-Michel Trivi#endif
10923c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
1104c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    interface_unlock_exclusive(this);
111f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
112f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_LEAVE_INTERFACE
1134c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten}
1144c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten
115f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
116f156301680273e71e56e898f98798f5b5b2431f6Glenn Kastenstatic SLresult IBufferQueue_GetState(SLBufferQueueItf self, SLBufferQueueState *pState)
1174c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten{
118f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_ENTER_INTERFACE
119f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
12023c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    // Note that GetState while a Clear is pending is equivalent to GetState before the Clear
12123c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten
122f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    if (NULL == pState) {
123f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
124f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    } else {
125f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        IBufferQueue *this = (IBufferQueue *) self;
126f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        SLBufferQueueState state;
127f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        interface_lock_shared(this);
1284c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten#ifdef __cplusplus // FIXME Is this a compiler bug?
129f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        state.count = this->mState.count;
130f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        state.playIndex = this->mState.playIndex;
1314c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten#else
132f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        state = this->mState;
1334c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten#endif
134f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        interface_unlock_shared(this);
135f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        *pState = state;
136f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_SUCCESS;
137f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    }
138f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
139f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_LEAVE_INTERFACE
1404c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten}
1414c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten
142f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
1439c03f04a9c6cc2a821182c8be8f2efe964a27efeGlenn KastenSLresult IBufferQueue_RegisterCallback(SLBufferQueueItf self,
1444c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    slBufferQueueCallback callback, void *pContext)
1454c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten{
146f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_ENTER_INTERFACE
147f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
1484c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    IBufferQueue *this = (IBufferQueue *) self;
1494c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    interface_lock_exclusive(this);
15023c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    // verify pre-condition that media object is in the SL_PLAYSTATE_STOPPED state
15123c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    if (SL_PLAYSTATE_STOPPED == getAssociatedState(this)) {
15223c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        this->mCallback = callback;
15323c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        this->mContext = pContext;
15423c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        result = SL_RESULT_SUCCESS;
15523c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    } else {
15623c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
15723c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    }
1584c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    interface_unlock_exclusive(this);
159f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
160f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_LEAVE_INTERFACE
1614c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten}
1624c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten
163f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
1644c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kastenstatic const struct SLBufferQueueItf_ IBufferQueue_Itf = {
1654c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    IBufferQueue_Enqueue,
1664c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    IBufferQueue_Clear,
1674c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    IBufferQueue_GetState,
1684c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    IBufferQueue_RegisterCallback
1694c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten};
1704c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten
1714c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kastenvoid IBufferQueue_init(void *self)
1724c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten{
173bdb243c16be832f5853083480965a437b81df3c8Jean-Michel Trivi    //SL_LOGV("IBufferQueue_init(%p) entering", self);
1744c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    IBufferQueue *this = (IBufferQueue *) self;
1754c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mItf = &IBufferQueue_Itf;
1764c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mState.count = 0;
1774c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mState.playIndex = 0;
1784c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mCallback = NULL;
1794c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mContext = NULL;
1804c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mNumBuffers = 0;
18123c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten    this->mClearRequested = SL_BOOLEAN_FALSE;
1824c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mArray = NULL;
1834c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mFront = NULL;
1844c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mRear = NULL;
18523c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten#ifdef ANDROID
1864c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mSizeConsumed = 0;
18723c38816f7c210afae5072fd44658c98fec7e119Glenn Kasten#endif
188437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten    BufferHeader *bufferHeader = this->mTypical;
1894c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    unsigned i;
1904c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    for (i = 0; i < BUFFER_HEADER_TYPICAL+1; ++i, ++bufferHeader) {
1914c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten        bufferHeader->mBuffer = NULL;
1924c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten        bufferHeader->mSize = 0;
1934c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    }
1944c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten}
195