BufferQueueSource.cpp revision 4efb2aa0d563b86b3c95d418d6d61d97f51c0bbb
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define USE_LOG SLAndroidLogLevel_Verbose 18 19#include "sles_allinclusive.h" 20#include "android/BufferQueueSource.h" 21 22#include <media/stagefright/MediaDebug.h> 23#include <sys/types.h> 24#include <unistd.h> 25#include <sys/types.h> 26#include <sys/stat.h> 27#include <fcntl.h> 28 29namespace android { 30 31 32const SLuint32 BufferQueueSource::kItemProcessed[NB_BUFFEREVENT_ITEM_FIELDS] = { 33 SL_ANDROID_ITEMKEY_BUFFERQUEUEEVENT, // item key 34 sizeof(SLuint32), // item size 35 SL_ANDROIDBUFFERQUEUEEVENT_PROCESSED // item data 36}; 37 38 39BufferQueueSource::BufferQueueSource(const void* user, void *context, const void *caller) : 40 mAndroidBufferQueueSource(NULL), 41 mStreamToBqOffset(0), 42 mEosReached(false) 43{ 44 if (NULL != user) { 45 mAndroidBufferQueueSource = &((CAudioPlayer*)user)->mAndroidBufferQueue; 46 } else { 47 SL_LOGE("Can't create BufferQueueSource with NULL user"); 48 } 49 50} 51 52 53BufferQueueSource::~BufferQueueSource() { 54 SL_LOGD("BufferQueueSource::~BufferQueueSource"); 55} 56 57 58//-------------------------------------------------------------------------- 59status_t BufferQueueSource::initCheck() const { 60 return mAndroidBufferQueueSource != NULL ? OK : NO_INIT; 61} 62 63ssize_t BufferQueueSource::readAt(off64_t offset, void *data, size_t size) { 64 SL_LOGD("BufferQueueSource::readAt(offset=%lld, data=%p, size=%d)", offset, data, size); 65 66 if (mEosReached) { 67 // once EOS has been received from the buffer queue, you can't read anymore 68 return 0; 69 } 70 71 ssize_t readSize; 72 slAndroidBufferQueueCallback callback = NULL; 73 void* pBufferContext, *pBufferData, *callbackPContext; 74 uint32_t dataSize, dataUsed; 75 76 interface_lock_exclusive(mAndroidBufferQueueSource); 77 78 if (mAndroidBufferQueueSource->mState.count == 0) { 79 readSize = 0; 80 } else { 81 assert(mAndroidBufferQueueSource->mFront != mAndroidBufferQueueSource->mRear); 82 83 AdvancedBufferHeader *oldFront = mAndroidBufferQueueSource->mFront; 84 AdvancedBufferHeader *newFront = &oldFront[1]; 85 86 // where to read from 87 char *pSrc = NULL; 88 // can this read operation cause us to call the buffer queue callback 89 // (either because there was a command with no data, or all the data has been consumed) 90 bool queueCallbackCandidate = false; 91 92 // consume events when starting to read data from a buffer for the first time 93 if (oldFront->mDataSizeConsumed == 0) { 94 if (oldFront->mItems.mAdtsCmdData.mAdtsCmdCode & ANDROID_ADTSEVENT_EOS) { 95 mEosReached = true; 96 // EOS has no associated data 97 queueCallbackCandidate = true; 98 } 99 oldFront->mItems.mAdtsCmdData.mAdtsCmdCode = ANDROID_ADTSEVENT_NONE; 100 } 101 102 //assert(mStreamToBqOffset <= offset); 103 CHECK(mStreamToBqOffset <= offset); 104 105 if (offset + size <= mStreamToBqOffset + oldFront->mDataSize) { 106 pSrc = ((char*)oldFront->mDataBuffer) + (offset - mStreamToBqOffset); 107 108 if (offset - mStreamToBqOffset + size == oldFront->mDataSize) { 109 // consumed buffer entirely 110 oldFront->mDataSizeConsumed = oldFront->mDataSize; 111 mStreamToBqOffset += oldFront->mDataSize; 112 queueCallbackCandidate = true; 113 114 // move queue to next buffer 115 if (newFront == &mAndroidBufferQueueSource-> 116 mBufferArray[mAndroidBufferQueueSource->mNumBuffers + 1]) { 117 // reached the end, circle back 118 newFront = mAndroidBufferQueueSource->mBufferArray; 119 } 120 mAndroidBufferQueueSource->mFront = newFront; 121 // update the queue state 122 mAndroidBufferQueueSource->mState.count--; 123 mAndroidBufferQueueSource->mState.index++; 124 SL_LOGV("BufferQueueSource moving to next buffer"); 125 } 126 } 127 128 // consume data: copy to given destination 129 if (NULL != pSrc) { 130 memcpy(data, pSrc, size); 131 readSize = size; 132 } else { 133 readSize = 0; 134 } 135 136 if (queueCallbackCandidate) { 137 // data has been consumed, and the buffer queue state has been updated 138 // we will notify the client if applicable 139 if (mAndroidBufferQueueSource->mCallbackEventsMask & 140 SL_ANDROIDBUFFERQUEUEEVENT_PROCESSED) { 141 callback = mAndroidBufferQueueSource->mCallback; 142 // save callback data while under lock 143 callbackPContext = mAndroidBufferQueueSource->mContext; 144 pBufferContext = (void *)oldFront->mBufferContext; 145 pBufferData = (void *)oldFront->mDataBuffer; 146 dataSize = oldFront->mDataSize; 147 dataUsed = oldFront->mDataSizeConsumed; 148 } 149 } 150 } 151 152 interface_unlock_exclusive(mAndroidBufferQueueSource); 153 154 // notify client 155 if (NULL != callback) { 156 SLresult result = (*callback)(&mAndroidBufferQueueSource->mItf, callbackPContext, 157 pBufferContext, pBufferData, dataSize, dataUsed, 158 // no messages during playback other than marking the buffer as processed 159 (const SLAndroidBufferItem*)(&kItemProcessed) /* pItems */, 160 NB_BUFFEREVENT_ITEM_FIELDS * sizeof(SLuint32) /* itemsLength */ ); 161 if (SL_RESULT_SUCCESS != result) { 162 // Reserved for future use 163 SL_LOGW("Unsuccessful result %d returned from AndroidBufferQueueCallback", result); 164 } 165 } 166 167 return readSize; 168} 169 170 171status_t BufferQueueSource::getSize(off64_t *size) { 172 SL_LOGD("BufferQueueSource::getSize()"); 173 // we're streaming, we don't know how much there is 174 *size = 0; 175 return ERROR_UNSUPPORTED; 176} 177 178} // namespace android 179