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