IBufferQueue.c revision d99183b5bbafc783e0a14ee12ce107326051811b
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
214c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kastenstatic SLresult IBufferQueue_Enqueue(SLBufferQueueItf self, const void *pBuffer,
224c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    SLuint32 size)
234c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten{
244c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    //FIXME if queue is empty and associated player is not in SL_PLAYSTATE_PLAYING state,
254c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    // set it to SL_PLAYSTATE_PLAYING (and start playing)
264c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    if (NULL == pBuffer)
274c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
284c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    IBufferQueue *this = (IBufferQueue *) self;
294c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    SLresult result;
304c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    interface_lock_exclusive(this);
314c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    struct BufferHeader *oldRear = this->mRear, *newRear;
324c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    if ((newRear = oldRear + 1) == &this->mArray[this->mNumBuffers])
334c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten        newRear = this->mArray;
344c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    if (newRear == this->mFront) {
354c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten        result = SL_RESULT_BUFFER_INSUFFICIENT;
364c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    } else {
374c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten        oldRear->mBuffer = pBuffer;
384c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten        oldRear->mSize = size;
394c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten        this->mRear = newRear;
404c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten        ++this->mState.count;
414c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten        result = SL_RESULT_SUCCESS;
424c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    }
434c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    //fprintf(stderr, "Enqueue: nbBuffers in queue = %lu\n", this->mState.count);
444c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    interface_unlock_exclusive(this);
454c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    return result;
464c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten}
474c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten
484c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kastenstatic SLresult IBufferQueue_Clear(SLBufferQueueItf self)
494c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten{
504c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    IBufferQueue *this = (IBufferQueue *) self;
514c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    interface_lock_exclusive(this);
524c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mFront = &this->mArray[0];
534c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mRear = &this->mArray[0];
544c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mSizeConsumed = 0;
554c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mState.count = 0;
56d99183b5bbafc783e0a14ee12ce107326051811bJean-Michel Trivi#ifdef USE_ANDROID
57d99183b5bbafc783e0a14ee12ce107326051811bJean-Michel Trivi    // FIXME must flush associated player
58d99183b5bbafc783e0a14ee12ce107326051811bJean-Michel Trivi    fprintf(stderr, "FIXME: IBufferQueue_Clear must flush associated player, not implemented\n");
59d99183b5bbafc783e0a14ee12ce107326051811bJean-Michel Trivi#endif
604c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    interface_unlock_exclusive(this);
614c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    return SL_RESULT_SUCCESS;
624c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten}
634c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten
644c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kastenstatic SLresult IBufferQueue_GetState(SLBufferQueueItf self,
654c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    SLBufferQueueState *pState)
664c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten{
674c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    if (NULL == pState)
684c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten        return SL_RESULT_PARAMETER_INVALID;
694c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    IBufferQueue *this = (IBufferQueue *) self;
704c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    SLBufferQueueState state;
714c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    interface_lock_shared(this);
724c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten#ifdef __cplusplus // FIXME Is this a compiler bug?
734c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    state.count = this->mState.count;
744c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    state.playIndex = this->mState.playIndex;
754c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten#else
764c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    state = this->mState;
774c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten#endif
784c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    interface_unlock_shared(this);
794c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten#ifdef __cplusplus // FIXME Is this a compiler bug?
804c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    pState->count = state.count;
814c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    pState->playIndex = state.playIndex;
824c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten#else
834c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    *pState = state;
844c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten#endif
854c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    return SL_RESULT_SUCCESS;
864c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten}
874c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten
884c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kastenstatic SLresult IBufferQueue_RegisterCallback(SLBufferQueueItf self,
894c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    slBufferQueueCallback callback, void *pContext)
904c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten{
914c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    IBufferQueue *this = (IBufferQueue *) self;
924c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    // FIXME This could be a poke lock, if we had atomic double-word load/store
934c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    interface_lock_exclusive(this);
944c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mCallback = callback;
954c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mContext = pContext;
964c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    interface_unlock_exclusive(this);
974c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    return SL_RESULT_SUCCESS;
984c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten}
994c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten
1004c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kastenstatic const struct SLBufferQueueItf_ IBufferQueue_Itf = {
1014c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    IBufferQueue_Enqueue,
1024c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    IBufferQueue_Clear,
1034c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    IBufferQueue_GetState,
1044c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    IBufferQueue_RegisterCallback
1054c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten};
1064c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten
1074c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kastenvoid IBufferQueue_init(void *self)
1084c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten{
1094c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    IBufferQueue *this = (IBufferQueue *) self;
1104c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mItf = &IBufferQueue_Itf;
1114c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten#ifndef NDEBUG
1124c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mState.count = 0;
1134c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mState.playIndex = 0;
1144c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mCallback = NULL;
1154c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mContext = NULL;
1164c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mNumBuffers = 0;
1174c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mArray = NULL;
1184c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mFront = NULL;
1194c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mRear = NULL;
1204c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    this->mSizeConsumed = 0;
1214c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    struct BufferHeader *bufferHeader = this->mTypical;
1224c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    unsigned i;
1234c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    for (i = 0; i < BUFFER_HEADER_TYPICAL+1; ++i, ++bufferHeader) {
1244c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten        bufferHeader->mBuffer = NULL;
1254c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten        bufferHeader->mSize = 0;
1264c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten    }
1274c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten#endif
1284c048c5d0d281e4e5777d732fc92a98aee876f71Glenn Kasten}
129