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