IAndroidBufferQueue.c revision bb832e853d4afb11b0a3287b2eb0cad87696d631
1/* 2 * Copyright (C) 2010 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/* AndroidBufferQueue implementation */ 18 19//#define USE_LOG SLAndroidLogLevel_Verbose 20 21#include "sles_allinclusive.h" 22// for AAC ADTS verification on enqueue: 23#include "android/include/AacBqToPcmCbRenderer.h" 24 25/** 26 * Determine the state of the audio player or audio recorder associated with a buffer queue. 27 * Note that PLAYSTATE and RECORDSTATE values are equivalent (where PLAYING == RECORDING). 28 */ 29 30static SLuint32 getAssociatedState(IAndroidBufferQueue *thiz) 31{ 32 SLuint32 state; 33 switch (InterfaceToObjectID(thiz)) { 34 case XA_OBJECTID_MEDIAPLAYER: 35 state = ((CMediaPlayer *) thiz->mThis)->mPlay.mState; 36 break; 37 case SL_OBJECTID_AUDIOPLAYER: 38 state = ((CAudioPlayer *) thiz->mThis)->mPlay.mState; 39 break; 40 case SL_OBJECTID_AUDIORECORDER: 41 state = ((CAudioRecorder *) thiz->mThis)->mRecord.mState; 42 break; 43 default: 44 // unreachable, but just in case we will assume it is stopped 45 assert(SL_BOOLEAN_FALSE); 46 state = SL_PLAYSTATE_STOPPED; 47 break; 48 } 49 return state; 50} 51 52 53/** 54 * parse and set the items associated with the given buffer, based on the buffer type, 55 * which determines the set of authorized items and format 56 */ 57static void setItems(const SLAndroidBufferItem *pItems, SLuint32 itemsLength, 58 SLuint16 bufferType, AdvancedBufferHeader *pBuff) 59{ 60 if ((NULL == pItems) || (0 == itemsLength)) { 61 // no item data, reset item structure based on type 62 switch (bufferType) { 63 case kAndroidBufferTypeMpeg2Ts: 64 pBuff->mItems.mTsCmdData.mTsCmdCode = ANDROID_MP2TSEVENT_NONE; 65 pBuff->mItems.mTsCmdData.mPts = 0; 66 break; 67 case kAndroidBufferTypeInvalid: 68 default: 69 return; 70 } 71 } else { 72 // parse item data based on type 73 switch (bufferType) { 74 75 case kAndroidBufferTypeMpeg2Ts: { 76 SLuint32 index = 0; 77 // supported Mpeg2Ts commands are mutually exclusive 78 switch (pItems->itemKey) { 79 80 case SL_ANDROID_ITEMKEY_EOS: 81 pBuff->mItems.mTsCmdData.mTsCmdCode |= ANDROID_MP2TSEVENT_EOS; 82 //SL_LOGD("Found EOS event=%d", pBuff->mItems.mTsCmdData.mTsCmdCode); 83 break; 84 85 case SL_ANDROID_ITEMKEY_DISCONTINUITY: 86 if (pItems->itemSize == 0) { 87 pBuff->mItems.mTsCmdData.mTsCmdCode |= ANDROID_MP2TSEVENT_DISCONTINUITY; 88 //SL_LOGD("Found DISCONTINUITYevent=%d", pBuff->mItems.mTsCmdData.mTsCmdCode); 89 } else if (pItems->itemSize == sizeof(SLAuint64)) { 90 pBuff->mItems.mTsCmdData.mTsCmdCode |= ANDROID_MP2TSEVENT_DISCON_NEWPTS; 91 pBuff->mItems.mTsCmdData.mPts = *((SLAuint64*)pItems->itemData); 92 //SL_LOGD("Found PTS=%lld", pBuff->mItems.mTsCmdData.mPts); 93 } else { 94 SL_LOGE("Invalid size for MPEG-2 PTS, ignoring value"); 95 pBuff->mItems.mTsCmdData.mTsCmdCode |= ANDROID_MP2TSEVENT_DISCONTINUITY; 96 } 97 break; 98 99 case SL_ANDROID_ITEMKEY_FORMAT_CHANGE: 100 pBuff->mItems.mTsCmdData.mTsCmdCode |= ANDROID_MP2TSEVENT_FORMAT_CHANGE; 101 if (pItems->itemSize != 0) { 102 SL_LOGE("Invalid item parameter size for format change, ignoring value"); 103 } 104 break; 105 106 default: 107 // no event with this buffer 108 pBuff->mItems.mTsCmdData.mTsCmdCode = ANDROID_MP2TSEVENT_NONE; 109 break; 110 }// switch (pItems->itemKey) 111 } break; 112 113 default: 114 return; 115 }// switch (bufferType) 116 } 117} 118 119 120static SLresult IAndroidBufferQueue_RegisterCallback(SLAndroidBufferQueueItf self, 121 slAndroidBufferQueueCallback callback, void *pContext) 122{ 123 SL_ENTER_INTERFACE 124 125 IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self; 126 127 interface_lock_exclusive(thiz); 128 129 // verify pre-condition that media object is in the SL_PLAYSTATE_STOPPED state 130 if (SL_PLAYSTATE_STOPPED == getAssociatedState(thiz)) { 131 thiz->mCallback = callback; 132 thiz->mContext = pContext; 133 134 switch (InterfaceToObjectID(thiz)) { 135 case SL_OBJECTID_AUDIOPLAYER: 136 result = android_audioPlayer_androidBufferQueue_registerCallback_l( 137 (CAudioPlayer*) thiz->mThis); 138 break; 139 case XA_OBJECTID_MEDIAPLAYER: 140 SL_LOGV("IAndroidBufferQueue_RegisterCallback()"); 141 result = SL_RESULT_SUCCESS; 142 //FIXME return error code 143 android_Player_androidBufferQueue_registerCallback_l((CMediaPlayer*) thiz->mThis); 144 break; 145 default: 146 result = SL_RESULT_PARAMETER_INVALID; 147 } 148 149 } else { 150 result = SL_RESULT_PRECONDITIONS_VIOLATED; 151 } 152 153 interface_unlock_exclusive(thiz); 154 155 SL_LEAVE_INTERFACE 156} 157 158 159static SLresult IAndroidBufferQueue_Clear(SLAndroidBufferQueueItf self) 160{ 161 SL_ENTER_INTERFACE 162 result = SL_RESULT_SUCCESS; 163 164 IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self; 165 166 interface_lock_exclusive(thiz); 167 168 // reset the queue pointers 169 thiz->mFront = &thiz->mBufferArray[0]; 170 thiz->mRear = &thiz->mBufferArray[0]; 171 // reset the queue state 172 thiz->mState.count = 0; 173 thiz->mState.index = 0; 174 // reset the individual buffers 175 for (XAuint16 i=0 ; i<(thiz->mNumBuffers + 1) ; i++) { 176 thiz->mBufferArray[i].mDataBuffer = NULL; 177 thiz->mBufferArray[i].mDataSize = 0; 178 thiz->mBufferArray[i].mDataSizeConsumed = 0; 179 thiz->mBufferArray[i].mBufferContext = NULL; 180 thiz->mBufferArray[i].mBufferState = SL_ANDROIDBUFFERQUEUEEVENT_NONE; 181 switch (thiz->mBufferType) { 182 case kAndroidBufferTypeMpeg2Ts: 183 thiz->mBufferArray[i].mItems.mTsCmdData.mTsCmdCode = ANDROID_MP2TSEVENT_NONE; 184 thiz->mBufferArray[i].mItems.mTsCmdData.mPts = 0; 185 break; 186 default: 187 result = SL_RESULT_CONTENT_UNSUPPORTED; 188 } 189 } 190 191 if (SL_RESULT_SUCCESS == result) { 192 // object-specific behavior for a clear 193 switch (InterfaceToObjectID(thiz)) { 194 case SL_OBJECTID_AUDIOPLAYER: 195 result = SL_RESULT_SUCCESS; 196 android_audioPlayer_androidBufferQueue_clear_l((CAudioPlayer*) thiz->mThis); 197 break; 198 case XA_OBJECTID_MEDIAPLAYER: 199 result = SL_RESULT_SUCCESS; 200 android_Player_androidBufferQueue_clear_l((CMediaPlayer*) thiz->mThis); 201 break; 202 default: 203 result = SL_RESULT_PARAMETER_INVALID; 204 } 205 } 206 207 interface_unlock_exclusive(thiz); 208 209 SL_LEAVE_INTERFACE 210} 211 212 213static SLresult IAndroidBufferQueue_Enqueue(SLAndroidBufferQueueItf self, 214 void *pBufferContext, 215 void *pData, 216 SLuint32 dataLength, 217 const SLAndroidBufferItem *pItems, 218 SLuint32 itemsLength) 219{ 220 SL_ENTER_INTERFACE 221 SL_LOGD("IAndroidBufferQueue_Enqueue pData=%p dataLength=%d", pData, dataLength); 222 223 if ( ((NULL == pData) || (0 == dataLength)) 224 && ((NULL == pItems) || (0 == itemsLength))) { 225 // no data and no msg 226 SL_LOGE("Enqueue failure: trying to enqueue buffer with no data and no items."); 227 result = SL_RESULT_PARAMETER_INVALID; 228 } else { 229 IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self; 230 231 // buffer size check, can be done outside of lock because buffer type can't change 232 switch (thiz->mBufferType) { 233 case kAndroidBufferTypeMpeg2Ts: 234 if (dataLength % MPEG2_TS_BLOCK_SIZE == 0) { 235 break; 236 } 237 SL_LOGE("Error enqueueing MPEG-2 TS data: size must be a multiple of %d (block size)", 238 MPEG2_TS_BLOCK_SIZE); 239 result = SL_RESULT_PARAMETER_INVALID; 240 SL_LEAVE_INTERFACE 241 break; 242 case kAndroidBufferTypeAacadts: 243 // FIXME allow commands as for mp2ts 244 if (!android::AacBqToPcmCbRenderer::validateBufferStartEndOnFrameBoundaries( 245 pData, dataLength)) { 246 SL_LOGE("Error enqueueing ADTS data: data must start and end on frame boundaries"); 247 result = SL_RESULT_PARAMETER_INVALID; 248 SL_LEAVE_INTERFACE 249 } 250 break; 251 case kAndroidBufferTypeInvalid: 252 default: 253 result = SL_RESULT_PARAMETER_INVALID; 254 SL_LEAVE_INTERFACE 255 } 256 257 interface_lock_exclusive(thiz); 258 259 AdvancedBufferHeader *oldRear = thiz->mRear, *newRear; 260 if ((newRear = oldRear + 1) == &thiz->mBufferArray[thiz->mNumBuffers + 1]) { 261 newRear = thiz->mBufferArray; 262 } 263 if (newRear == thiz->mFront) { 264 result = SL_RESULT_BUFFER_INSUFFICIENT; 265 } else { 266 oldRear->mDataBuffer = pData; 267 oldRear->mDataSize = dataLength; 268 oldRear->mDataSizeConsumed = 0; 269 oldRear->mBufferContext = pBufferContext; 270 oldRear->mBufferState = SL_ANDROIDBUFFERQUEUEEVENT_NONE; 271 thiz->mRear = newRear; 272 ++thiz->mState.count; 273 setItems(pItems, itemsLength, thiz->mBufferType, oldRear); 274 result = SL_RESULT_SUCCESS; 275 } 276 // set enqueue attribute if state is PLAYING and the first buffer is enqueued 277 interface_unlock_exclusive_attributes(thiz, ((SL_RESULT_SUCCESS == result) && 278 (1 == thiz->mState.count) && (SL_PLAYSTATE_PLAYING == getAssociatedState(thiz))) ? 279 ATTR_ABQ_ENQUEUE : ATTR_NONE); 280 } 281 282 SL_LEAVE_INTERFACE 283} 284 285 286static SLresult IAndroidBufferQueue_GetState(SLAndroidBufferQueueItf self, 287 SLAndroidBufferQueueState *pState) 288{ 289 SL_ENTER_INTERFACE 290 291 // Note that GetState while a Clear is pending is equivalent to GetState before the Clear 292 293 if (NULL == pState) { 294 result = SL_RESULT_PARAMETER_INVALID; 295 } else { 296 IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self; 297 298 interface_lock_shared(thiz); 299 300 pState->count = thiz->mState.count; 301 pState->index = thiz->mState.index; 302 303 interface_unlock_shared(thiz); 304 305 result = SL_RESULT_SUCCESS; 306 } 307 308 SL_LEAVE_INTERFACE 309} 310 311 312static SLresult IAndroidBufferQueue_SetCallbackEventsMask(SLAndroidBufferQueueItf self, 313 SLuint32 eventFlags) 314{ 315 SL_ENTER_INTERFACE 316 317 IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self; 318 interface_lock_exclusive(thiz); 319 // FIXME only supporting SL_ANDROIDBUFFERQUEUEEVENT_PROCESSED in this implementation 320 if ((SL_ANDROIDBUFFERQUEUEEVENT_PROCESSED == eventFlags) || 321 (SL_ANDROIDBUFFERQUEUEEVENT_NONE == eventFlags)) { 322 thiz->mCallbackEventsMask = eventFlags; 323 result = SL_RESULT_SUCCESS; 324 } else { 325 result = SL_RESULT_FEATURE_UNSUPPORTED; 326 } 327 interface_unlock_exclusive(thiz); 328 329 SL_LEAVE_INTERFACE 330} 331 332 333static SLresult IAndroidBufferQueue_GetCallbackEventsMask(SLAndroidBufferQueueItf self, 334 SLuint32 *pEventFlags) 335{ 336 SL_ENTER_INTERFACE 337 338 if (NULL == pEventFlags) { 339 result = SL_RESULT_PARAMETER_INVALID; 340 } else { 341 IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self; 342 interface_lock_peek(thiz); 343 SLuint32 callbackEventsMask = thiz->mCallbackEventsMask; 344 interface_unlock_peek(thiz); 345 *pEventFlags = callbackEventsMask; 346 result = SL_RESULT_SUCCESS; 347 } 348 349 SL_LEAVE_INTERFACE 350} 351 352 353static const struct SLAndroidBufferQueueItf_ IAndroidBufferQueue_Itf = { 354 IAndroidBufferQueue_RegisterCallback, 355 IAndroidBufferQueue_Clear, 356 IAndroidBufferQueue_Enqueue, 357 IAndroidBufferQueue_GetState, 358 IAndroidBufferQueue_SetCallbackEventsMask, 359 IAndroidBufferQueue_GetCallbackEventsMask 360}; 361 362 363void IAndroidBufferQueue_init(void *self) 364{ 365 IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self; 366 thiz->mItf = &IAndroidBufferQueue_Itf; 367 368 thiz->mState.count = 0; 369 thiz->mState.index = 0; 370 371 thiz->mCallback = NULL; 372 thiz->mContext = NULL; 373 thiz->mCallbackEventsMask = SL_ANDROIDBUFFERQUEUEEVENT_PROCESSED; 374 375 thiz->mBufferType = kAndroidBufferTypeInvalid; 376 thiz->mBufferArray = NULL; 377 thiz->mFront = NULL; 378 thiz->mRear = NULL; 379} 380 381 382void IAndroidBufferQueue_deinit(void *self) 383{ 384 IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self; 385 if (NULL != thiz->mBufferArray) { 386 free(thiz->mBufferArray); 387 thiz->mBufferArray = NULL; 388 } 389} 390