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