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 media player associated with a buffer queue.
27 * Note that PLAYSTATE and RECORDSTATE values are equivalent (where PLAYING == RECORDING).
28 */
29
getAssociatedState(IAndroidBufferQueue * thiz)30 static 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 default:
41 // unreachable, but just in case we will assume it is stopped
42 assert(SL_BOOLEAN_FALSE);
43 state = SL_PLAYSTATE_STOPPED;
44 break;
45 }
46 return state;
47 }
48
49
50 /**
51 * parse and set the items associated with the given buffer, based on the buffer type,
52 * which determines the set of authorized items and format
53 */
setItems(SLuint32 dataLength,const SLAndroidBufferItem * pItems,SLuint32 itemsLength,SLuint16 bufferType,AdvancedBufferHeader * pBuff,bool * pEOS)54 static SLresult setItems(SLuint32 dataLength,
55 const SLAndroidBufferItem *pItems, SLuint32 itemsLength,
56 SLuint16 bufferType, AdvancedBufferHeader *pBuff, bool *pEOS)
57 {
58 // reset item structure based on type
59 switch (bufferType) {
60 case kAndroidBufferTypeMpeg2Ts:
61 pBuff->mItems.mTsCmdData.mTsCmdCode = ANDROID_MP2TSEVENT_NONE;
62 pBuff->mItems.mTsCmdData.mPts = 0;
63 break;
64 case kAndroidBufferTypeAacadts:
65 pBuff->mItems.mAdtsCmdData.mAdtsCmdCode = ANDROID_ADTSEVENT_NONE;
66 break;
67 case kAndroidBufferTypeInvalid:
68 default:
69 // shouldn't happen, but just in case clear out the item structure
70 memset(&pBuff->mItems, 0, sizeof(AdvancedBufferItems));
71 return SL_RESULT_INTERNAL_ERROR;
72 }
73
74 // process all items in the array; if no items then we break out of loop immediately
75 while (itemsLength > 0) {
76
77 // remaining length must be large enough for one full item without any associated data
78 if (itemsLength < sizeof(SLAndroidBufferItem)) {
79 SL_LOGE("Partial item at end of array");
80 return SL_RESULT_PARAMETER_INVALID;
81 }
82 itemsLength -= sizeof(SLAndroidBufferItem);
83
84 // remaining length must be large enough for data with current item and alignment padding
85 SLuint32 itemDataSizeWithAlignmentPadding = (pItems->itemSize + 3) & ~3;
86 if (itemsLength < itemDataSizeWithAlignmentPadding) {
87 SL_LOGE("Partial item data at end of array");
88 return SL_RESULT_PARAMETER_INVALID;
89 }
90 itemsLength -= itemDataSizeWithAlignmentPadding;
91
92 // parse item data based on type
93 switch (bufferType) {
94
95 case kAndroidBufferTypeMpeg2Ts: {
96 switch (pItems->itemKey) {
97
98 case SL_ANDROID_ITEMKEY_EOS:
99 pBuff->mItems.mTsCmdData.mTsCmdCode |= ANDROID_MP2TSEVENT_EOS;
100 //SL_LOGD("Found EOS event=%d", pBuff->mItems.mTsCmdData.mTsCmdCode);
101 if (pItems->itemSize != 0) {
102 SL_LOGE("Invalid item parameter size %u for EOS", pItems->itemSize);
103 return SL_RESULT_PARAMETER_INVALID;
104 }
105 break;
106
107 case SL_ANDROID_ITEMKEY_DISCONTINUITY:
108 if (pItems->itemSize == 0) {
109 pBuff->mItems.mTsCmdData.mTsCmdCode |= ANDROID_MP2TSEVENT_DISCONTINUITY;
110 //SL_LOGD("Found DISCONTINUITYevent=%d", pBuff->mItems.mTsCmdData.mTsCmdCode);
111 } else if (pItems->itemSize == sizeof(SLAuint64)) {
112 pBuff->mItems.mTsCmdData.mTsCmdCode |= ANDROID_MP2TSEVENT_DISCON_NEWPTS;
113 pBuff->mItems.mTsCmdData.mPts = *((SLAuint64*)pItems->itemData);
114 //SL_LOGD("Found PTS=%lld", pBuff->mItems.mTsCmdData.mPts);
115 } else {
116 SL_LOGE("Invalid item parameter size %u for MPEG-2 PTS", pItems->itemSize);
117 return SL_RESULT_PARAMETER_INVALID;
118 }
119 break;
120
121 case SL_ANDROID_ITEMKEY_FORMAT_CHANGE:
122 // distinguish between a "full" format change and one where it says what changed
123 if (pItems->itemSize == 0) {
124 SL_LOGV("Received format change with no data == full format change");
125 pBuff->mItems.mTsCmdData.mTsCmdCode |= ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL;
126 } else if (pItems->itemSize == sizeof(SLuint32)) {
127 XAuint32 formatData = *((XAuint32*)pItems->itemData);
128 // intentionally only supporting video change when reading which specific
129 // stream has changed, interpret other changes as full change
130 if (formatData == XA_ANDROID_FORMATCHANGE_ITEMDATA_VIDEO) {
131 pBuff->mItems.mTsCmdData.mTsCmdCode |=
132 ANDROID_MP2TSEVENT_FORMAT_CHANGE_VIDEO;
133 SL_LOGV("Received video format change");
134 } else {
135 // note that we don't support specifying
136 // ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL by having all bits of
137 // the data mask set, we default to it with unsupported masks
138 SL_LOGE("Received format change with unsupported data, ignoring data");
139 pBuff->mItems.mTsCmdData.mTsCmdCode |=
140 ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL;
141 }
142 } else {
143 SL_LOGE("Received format change with invalid data size, ignoring data");
144 pBuff->mItems.mTsCmdData.mTsCmdCode |= ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL;
145 }
146 break;
147
148 default:
149 // unknown item key
150 SL_LOGE("Unknown item key %u with size %u", pItems->itemKey, pItems->itemSize);
151 return SL_RESULT_PARAMETER_INVALID;
152
153 }// switch (pItems->itemKey)
154 } break;
155
156 case kAndroidBufferTypeAacadts: {
157 switch (pItems->itemKey) {
158
159 case SL_ANDROID_ITEMKEY_EOS:
160 pBuff->mItems.mAdtsCmdData.mAdtsCmdCode |= ANDROID_ADTSEVENT_EOS;
161 if (pItems->itemSize != 0) {
162 SL_LOGE("Invalid item parameter size %u for EOS", pItems->itemSize);
163 return SL_RESULT_PARAMETER_INVALID;
164 }
165 break;
166
167 default:
168 // unknown item key
169 SL_LOGE("Unknown item key %u with size %u", pItems->itemKey, pItems->itemSize);
170 return SL_RESULT_PARAMETER_INVALID;
171
172 }// switch (pItems->itemKey)
173 } break;
174
175 case kAndroidBufferTypeInvalid:
176 default:
177 // not reachable as we checked this earlier
178 return SL_RESULT_INTERNAL_ERROR;
179
180 }// switch (bufferType)
181
182 // skip past this item, including data with alignment padding
183 pItems = (SLAndroidBufferItem *) ((char *) pItems +
184 sizeof(SLAndroidBufferItem) + itemDataSizeWithAlignmentPadding);
185 }
186
187 // now check for invalid combinations of items
188 switch (bufferType) {
189
190 case kAndroidBufferTypeMpeg2Ts: {
191 // supported Mpeg2Ts commands are mutually exclusive
192 switch (pBuff->mItems.mTsCmdData.mTsCmdCode) {
193 // single items are allowed
194 case ANDROID_MP2TSEVENT_EOS:
195 if (dataLength > 0) {
196 SL_LOGE("Can't enqueue non-zero data with EOS");
197 return SL_RESULT_PRECONDITIONS_VIOLATED;
198 }
199 *pEOS = true;
200 break;
201 case ANDROID_MP2TSEVENT_NONE:
202 case ANDROID_MP2TSEVENT_DISCONTINUITY:
203 case ANDROID_MP2TSEVENT_DISCON_NEWPTS:
204 case ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL:
205 case ANDROID_MP2TSEVENT_FORMAT_CHANGE_VIDEO:
206 break;
207 // no combinations are allowed
208 default:
209 SL_LOGE("Invalid combination of items");
210 return SL_RESULT_PARAMETER_INVALID;
211 }
212 } break;
213
214 case kAndroidBufferTypeAacadts: {
215 // only one item supported, and thus no combination check needed
216 if (pBuff->mItems.mAdtsCmdData.mAdtsCmdCode == ANDROID_ADTSEVENT_EOS) {
217 if (dataLength > 0) {
218 SL_LOGE("Can't enqueue non-zero data with EOS");
219 return SL_RESULT_PRECONDITIONS_VIOLATED;
220 }
221 *pEOS = true;
222 }
223 } break;
224
225 case kAndroidBufferTypeInvalid:
226 default:
227 // not reachable as we checked this earlier
228 return SL_RESULT_INTERNAL_ERROR;
229 }
230
231 return SL_RESULT_SUCCESS;
232 }
233
234
IAndroidBufferQueue_RegisterCallback(SLAndroidBufferQueueItf self,slAndroidBufferQueueCallback callback,void * pContext)235 static SLresult IAndroidBufferQueue_RegisterCallback(SLAndroidBufferQueueItf self,
236 slAndroidBufferQueueCallback callback, void *pContext)
237 {
238 SL_ENTER_INTERFACE
239
240 IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
241
242 interface_lock_exclusive(thiz);
243
244 // verify pre-condition that media object is in the SL_PLAYSTATE_STOPPED state
245 if (SL_PLAYSTATE_STOPPED == getAssociatedState(thiz)) {
246 thiz->mCallback = callback;
247 thiz->mContext = pContext;
248 result = SL_RESULT_SUCCESS;
249
250 } else {
251 result = SL_RESULT_PRECONDITIONS_VIOLATED;
252 }
253
254 interface_unlock_exclusive(thiz);
255
256 SL_LEAVE_INTERFACE
257 }
258
259
IAndroidBufferQueue_Clear(SLAndroidBufferQueueItf self)260 static SLresult IAndroidBufferQueue_Clear(SLAndroidBufferQueueItf self)
261 {
262 SL_ENTER_INTERFACE
263 result = SL_RESULT_SUCCESS;
264
265 IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
266
267 interface_lock_exclusive(thiz);
268
269 // reset the queue pointers
270 thiz->mFront = &thiz->mBufferArray[0];
271 thiz->mRear = &thiz->mBufferArray[0];
272 // reset the queue state
273 thiz->mState.count = 0;
274 thiz->mState.index = 0;
275
276 // object-specific behavior for a clear
277 switch (InterfaceToObjectID(thiz)) {
278 case SL_OBJECTID_AUDIOPLAYER:
279 android_audioPlayer_androidBufferQueue_clear_l((CAudioPlayer*) thiz->mThis);
280 break;
281 case XA_OBJECTID_MEDIAPLAYER:
282 android_Player_androidBufferQueue_clear_l((CMediaPlayer*) thiz->mThis);
283 break;
284 default:
285 result = SL_RESULT_PARAMETER_INVALID;
286 }
287
288 interface_unlock_exclusive(thiz);
289
290 SL_LEAVE_INTERFACE
291 }
292
293
IAndroidBufferQueue_Enqueue(SLAndroidBufferQueueItf self,void * pBufferContext,void * pData,SLuint32 dataLength,const SLAndroidBufferItem * pItems,SLuint32 itemsLength)294 static SLresult IAndroidBufferQueue_Enqueue(SLAndroidBufferQueueItf self,
295 void *pBufferContext,
296 void *pData,
297 SLuint32 dataLength,
298 const SLAndroidBufferItem *pItems,
299 SLuint32 itemsLength)
300 {
301 SL_ENTER_INTERFACE
302 SL_LOGD("IAndroidBufferQueue_Enqueue pData=%p dataLength=%d", pData, dataLength);
303
304 if ((dataLength > 0) && (NULL == pData)) {
305 SL_LOGE("Enqueue failure: non-zero data length %u but NULL data pointer", dataLength);
306 result = SL_RESULT_PARAMETER_INVALID;
307 } else if ((itemsLength > 0) && (NULL == pItems)) {
308 SL_LOGE("Enqueue failure: non-zero items length %u but NULL items pointer", itemsLength);
309 result = SL_RESULT_PARAMETER_INVALID;
310 } else if ((0 == dataLength) && (0 == itemsLength)) {
311 // no data and no msg
312 SL_LOGE("Enqueue failure: trying to enqueue buffer with no data and no items.");
313 result = SL_RESULT_PARAMETER_INVALID;
314 // Note that a non-NULL data pointer with zero data length is allowed.
315 // We track that data pointer as it moves through the queue
316 // to assist the application in accounting for data buffers.
317 // A non-NULL items pointer with zero items length is also allowed, but has no value.
318 } else {
319 IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
320
321 // buffer size check, can be done outside of lock because buffer type can't change
322 switch (thiz->mBufferType) {
323 case kAndroidBufferTypeMpeg2Ts:
324 if (dataLength % MPEG2_TS_PACKET_SIZE == 0) {
325 // The downstream Stagefright MPEG-2 TS parser is sensitive to format errors,
326 // so do a quick sanity check beforehand on the first packet of the buffer.
327 // We don't check all the packets to avoid thrashing the data cache.
328 if ((dataLength > 0) && (*(SLuint8 *)pData != MPEG2_TS_PACKET_SYNC)) {
329 SL_LOGE("Error enqueueing MPEG-2 TS data: incorrect packet sync");
330 result = SL_RESULT_CONTENT_CORRUPTED;
331 SL_LEAVE_INTERFACE
332 }
333 break;
334 }
335 SL_LOGE("Error enqueueing MPEG-2 TS data: size must be a multiple of %d (packet size)",
336 MPEG2_TS_PACKET_SIZE);
337 result = SL_RESULT_PARAMETER_INVALID;
338 SL_LEAVE_INTERFACE
339 break;
340 case kAndroidBufferTypeAacadts:
341 // zero dataLength is permitted in case of EOS command only
342 if (dataLength > 0) {
343 result = android::AacBqToPcmCbRenderer::validateBufferStartEndOnFrameBoundaries(
344 pData, dataLength);
345 if (SL_RESULT_SUCCESS != result) {
346 SL_LOGE("Error enqueueing ADTS data: data must start and end on frame "
347 "boundaries");
348 SL_LEAVE_INTERFACE
349 }
350 }
351 break;
352 case kAndroidBufferTypeInvalid:
353 default:
354 result = SL_RESULT_PARAMETER_INVALID;
355 SL_LEAVE_INTERFACE
356 }
357
358 interface_lock_exclusive(thiz);
359
360 AdvancedBufferHeader *oldRear = thiz->mRear, *newRear;
361 if ((newRear = oldRear + 1) == &thiz->mBufferArray[thiz->mNumBuffers + 1]) {
362 newRear = thiz->mBufferArray;
363 }
364 if (thiz->mEOS) {
365 SL_LOGE("Can't enqueue after EOS");
366 result = SL_RESULT_PRECONDITIONS_VIOLATED;
367 } else if (newRear == thiz->mFront) {
368 result = SL_RESULT_BUFFER_INSUFFICIENT;
369 } else {
370 // set oldRear->mItems based on items
371 result = setItems(dataLength, pItems, itemsLength, thiz->mBufferType, oldRear,
372 &thiz->mEOS);
373 if (SL_RESULT_SUCCESS == result) {
374 oldRear->mDataBuffer = pData;
375 oldRear->mDataSize = dataLength;
376 oldRear->mDataSizeConsumed = 0;
377 oldRear->mBufferContext = pBufferContext;
378 //oldRear->mBufferState = TBD;
379 thiz->mRear = newRear;
380 ++thiz->mState.count;
381 }
382 }
383 // set enqueue attribute if state is PLAYING and the first buffer is enqueued
384 interface_unlock_exclusive_attributes(thiz, ((SL_RESULT_SUCCESS == result) &&
385 (1 == thiz->mState.count) && (SL_PLAYSTATE_PLAYING == getAssociatedState(thiz))) ?
386 ATTR_ABQ_ENQUEUE : ATTR_NONE);
387 }
388
389 SL_LEAVE_INTERFACE
390 }
391
392
IAndroidBufferQueue_GetState(SLAndroidBufferQueueItf self,SLAndroidBufferQueueState * pState)393 static SLresult IAndroidBufferQueue_GetState(SLAndroidBufferQueueItf self,
394 SLAndroidBufferQueueState *pState)
395 {
396 SL_ENTER_INTERFACE
397
398 // Note that GetState while a Clear is pending is equivalent to GetState before the Clear
399
400 if (NULL == pState) {
401 result = SL_RESULT_PARAMETER_INVALID;
402 } else {
403 IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
404
405 interface_lock_shared(thiz);
406
407 pState->count = thiz->mState.count;
408 pState->index = thiz->mState.index;
409
410 interface_unlock_shared(thiz);
411
412 result = SL_RESULT_SUCCESS;
413 }
414
415 SL_LEAVE_INTERFACE
416 }
417
418
IAndroidBufferQueue_SetCallbackEventsMask(SLAndroidBufferQueueItf self,SLuint32 eventFlags)419 static SLresult IAndroidBufferQueue_SetCallbackEventsMask(SLAndroidBufferQueueItf self,
420 SLuint32 eventFlags)
421 {
422 SL_ENTER_INTERFACE
423
424 IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
425 interface_lock_exclusive(thiz);
426 // FIXME only supporting SL_ANDROIDBUFFERQUEUEEVENT_PROCESSED in this implementation
427 if (!(~(SL_ANDROIDBUFFERQUEUEEVENT_PROCESSED /* | others TBD */ ) & eventFlags)) {
428 thiz->mCallbackEventsMask = eventFlags;
429 result = SL_RESULT_SUCCESS;
430 } else {
431 result = SL_RESULT_FEATURE_UNSUPPORTED;
432 }
433 interface_unlock_exclusive(thiz);
434
435 SL_LEAVE_INTERFACE
436 }
437
438
IAndroidBufferQueue_GetCallbackEventsMask(SLAndroidBufferQueueItf self,SLuint32 * pEventFlags)439 static SLresult IAndroidBufferQueue_GetCallbackEventsMask(SLAndroidBufferQueueItf self,
440 SLuint32 *pEventFlags)
441 {
442 SL_ENTER_INTERFACE
443
444 if (NULL == pEventFlags) {
445 result = SL_RESULT_PARAMETER_INVALID;
446 } else {
447 IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
448 interface_lock_shared(thiz);
449 SLuint32 callbackEventsMask = thiz->mCallbackEventsMask;
450 interface_unlock_shared(thiz);
451 *pEventFlags = callbackEventsMask;
452 result = SL_RESULT_SUCCESS;
453 }
454
455 SL_LEAVE_INTERFACE
456 }
457
458
459 static const struct SLAndroidBufferQueueItf_ IAndroidBufferQueue_Itf = {
460 IAndroidBufferQueue_RegisterCallback,
461 IAndroidBufferQueue_Clear,
462 IAndroidBufferQueue_Enqueue,
463 IAndroidBufferQueue_GetState,
464 IAndroidBufferQueue_SetCallbackEventsMask,
465 IAndroidBufferQueue_GetCallbackEventsMask
466 };
467
468
IAndroidBufferQueue_init(void * self)469 void IAndroidBufferQueue_init(void *self)
470 {
471 IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
472 thiz->mItf = &IAndroidBufferQueue_Itf;
473
474 thiz->mState.count = 0;
475 thiz->mState.index = 0;
476
477 thiz->mCallback = NULL;
478 thiz->mContext = NULL;
479 thiz->mCallbackEventsMask = SL_ANDROIDBUFFERQUEUEEVENT_PROCESSED;
480
481 thiz->mBufferType = kAndroidBufferTypeInvalid;
482 thiz->mBufferArray = NULL;
483 thiz->mFront = NULL;
484 thiz->mRear = NULL;
485 thiz->mEOS = false;
486 }
487
488
IAndroidBufferQueue_deinit(void * self)489 void IAndroidBufferQueue_deinit(void *self)
490 {
491 IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
492 if (NULL != thiz->mBufferArray) {
493 free(thiz->mBufferArray);
494 thiz->mBufferArray = NULL;
495 }
496 }
497
498
499 #if 0
500 // Dump the contents of an IAndroidBufferQueue to the log. This is for debugging only,
501 // and is not a documented API. The associated object is locked throughout for atomicity,
502 // but the log entries may be interspersed with unrelated logs.
503
504 void IAndroidBufferQueue_log(IAndroidBufferQueue *thiz)
505 {
506 interface_lock_shared(thiz);
507 SL_LOGI("IAndroidBufferQueue %p:", thiz);
508 SL_LOGI(" mState.count=%u mState.index=%u mCallback=%p mContext=%p",
509 thiz->mState.count, thiz->mState.index, thiz->mCallback, thiz->mContext);
510 const char *bufferTypeString;
511 switch (thiz->mBufferType) {
512 case kAndroidBufferTypeInvalid:
513 bufferTypeString = "kAndroidBufferTypeInvalid";
514 break;
515 case kAndroidBufferTypeMpeg2Ts:
516 bufferTypeString = "kAndroidBufferTypeMpeg2Ts";
517 break;
518 case kAndroidBufferTypeAacadts:
519 bufferTypeString = "kAndroidBufferTypeAacadts";
520 break;
521 default:
522 bufferTypeString = "unknown";
523 break;
524 }
525 SL_LOGI(" mCallbackEventsMask=0x%x, mBufferType=0x%x (%s), mEOS=%s",
526 thiz->mCallbackEventsMask,
527 thiz->mBufferType, bufferTypeString,
528 thiz->mEOS ? "true" : "false");
529 SL_LOGI(" mBufferArray=%p, mFront=%p (%u), mRear=%p (%u)",
530 thiz->mBufferArray,
531 thiz->mFront, thiz->mFront - thiz->mBufferArray,
532 thiz->mRear, thiz->mRear - thiz->mBufferArray);
533 SL_LOGI(" index mDataBuffer mDataSize mDataSizeConsumed mBufferContext mItems");
534 const AdvancedBufferHeader *hdr;
535 for (hdr = thiz->mFront; hdr != thiz->mRear; ) {
536 SLuint32 i = hdr - thiz->mBufferArray;
537 char itemString[32];
538 switch (thiz->mBufferType) {
539 case kAndroidBufferTypeMpeg2Ts:
540 switch (hdr->mItems.mTsCmdData.mTsCmdCode) {
541 case ANDROID_MP2TSEVENT_NONE:
542 strcpy(itemString, "NONE");
543 break;
544 case ANDROID_MP2TSEVENT_EOS:
545 strcpy(itemString, "EOS");
546 break;
547 case ANDROID_MP2TSEVENT_DISCONTINUITY:
548 strcpy(itemString, "DISCONTINUITY");
549 break;
550 case ANDROID_MP2TSEVENT_DISCON_NEWPTS:
551 snprintf(itemString, sizeof(itemString), "NEWPTS %llu",
552 hdr->mItems.mTsCmdData.mPts);
553 break;
554 case ANDROID_MP2TSEVENT_FORMAT_CHANGE:
555 strcpy(itemString, "FORMAT_CHANGE");
556 break;
557 default:
558 snprintf(itemString, sizeof(itemString), "0x%x", hdr->mItems.mTsCmdData.mTsCmdCode);
559 break;
560 }
561 break;
562 case kAndroidBufferTypeAacadts:
563 switch (hdr->mItems.mAdtsCmdData.mAdtsCmdCode) {
564 case ANDROID_ADTSEVENT_NONE:
565 strcpy(itemString, "NONE");
566 break;
567 case ANDROID_ADTSEVENT_EOS:
568 strcpy(itemString, "EOS");
569 break;
570 default:
571 snprintf(itemString, sizeof(itemString), "0x%x",
572 hdr->mItems.mAdtsCmdData.mAdtsCmdCode);
573 break;
574 }
575 break;
576 default:
577 strcpy(itemString, "");
578 break;
579 }
580 SL_LOGI(" %5u %11p %9u %17u %14p %s",
581 i, hdr->mDataBuffer, hdr->mDataSize, hdr->mDataSizeConsumed,
582 hdr->mBufferContext, itemString);
583 // mBufferState
584 if (++hdr == &thiz->mBufferArray[thiz->mNumBuffers + 1]) {
585 hdr = thiz->mBufferArray;
586 }
587 }
588 interface_unlock_shared(thiz);
589 }
590
591 #endif
592