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