1fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi/*
2fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi * Copyright (C) 2010 The Android Open Source Project
3fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi *
4fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
5fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi * you may not use this file except in compliance with the License.
6fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi * You may obtain a copy of the License at
7fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi *
8fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
9fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi *
10fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
11fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
12fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi * See the License for the specific language governing permissions and
14fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi * limitations under the License.
15fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi */
16fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
17fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi/* AndroidBufferQueue implementation */
18fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
19bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi//#define USE_LOG SLAndroidLogLevel_Verbose
20fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
21bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi#include "sles_allinclusive.h"
22bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi// for AAC ADTS verification on enqueue:
23bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi#include "android/include/AacBqToPcmCbRenderer.h"
24d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
2570c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi/**
26682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten * Determine the state of the audio player or media player associated with a buffer queue.
27d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi *  Note that PLAYSTATE and RECORDSTATE values are equivalent (where PLAYING == RECORDING).
28d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi */
29d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
30d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivistatic SLuint32 getAssociatedState(IAndroidBufferQueue *thiz)
31d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi{
32d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi    SLuint32 state;
33d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi    switch (InterfaceToObjectID(thiz)) {
3470c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi      case XA_OBJECTID_MEDIAPLAYER:
35d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        state = ((CMediaPlayer *) thiz->mThis)->mPlay.mState;
36d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        break;
3770c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi      case SL_OBJECTID_AUDIOPLAYER:
38d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        state = ((CAudioPlayer *) thiz->mThis)->mPlay.mState;
39d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        break;
4070c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi      default:
41d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        // unreachable, but just in case we will assume it is stopped
42d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        assert(SL_BOOLEAN_FALSE);
43d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        state = SL_PLAYSTATE_STOPPED;
44d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        break;
45d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi    }
46d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi    return state;
47d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi}
48d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
49d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
5070c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi/**
5170c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi * parse and set the items associated with the given buffer, based on the buffer type,
5270c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi * which determines the set of authorized items and format
5370c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi */
54682f9be91e641e80739c21d6ff124379a806182aGlenn Kastenstatic SLresult setItems(SLuint32 dataLength,
55682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        const SLAndroidBufferItem *pItems, SLuint32 itemsLength,
56682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        SLuint16 bufferType, AdvancedBufferHeader *pBuff, bool *pEOS)
5770c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi{
58677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten    // reset item structure based on type
59677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten    switch (bufferType) {
60677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten      case kAndroidBufferTypeMpeg2Ts:
61677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        pBuff->mItems.mTsCmdData.mTsCmdCode = ANDROID_MP2TSEVENT_NONE;
62677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        pBuff->mItems.mTsCmdData.mPts = 0;
63677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        break;
64677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten      case kAndroidBufferTypeAacadts:
65677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        pBuff->mItems.mAdtsCmdData.mAdtsCmdCode = ANDROID_ADTSEVENT_NONE;
66677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        break;
67677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten      case kAndroidBufferTypeInvalid:
68677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten      default:
69677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        // shouldn't happen, but just in case clear out the item structure
70677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        memset(&pBuff->mItems, 0, sizeof(AdvancedBufferItems));
71682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        return SL_RESULT_INTERNAL_ERROR;
72677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten    }
73677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten
74677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten    // process all items in the array; if no items then we break out of loop immediately
75677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten    while (itemsLength > 0) {
76677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten
77677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        // remaining length must be large enough for one full item without any associated data
78677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        if (itemsLength < sizeof(SLAndroidBufferItem)) {
79682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            SL_LOGE("Partial item at end of array");
80682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
8170c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi        }
82677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        itemsLength -= sizeof(SLAndroidBufferItem);
83677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten
84677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        // remaining length must be large enough for data with current item and alignment padding
85677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        SLuint32 itemDataSizeWithAlignmentPadding = (pItems->itemSize + 3) & ~3;
86677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        if (itemsLength < itemDataSizeWithAlignmentPadding) {
87682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            SL_LOGE("Partial item data at end of array");
88682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
89677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        }
90677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        itemsLength -= itemDataSizeWithAlignmentPadding;
91677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten
9270c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi        // parse item data based on type
9370c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi        switch (bufferType) {
9470c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi
9570c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi          case kAndroidBufferTypeMpeg2Ts: {
966f0f5640d190b0187c356eb53bd96d9f9e49da60Jean-Michel Trivi            switch (pItems->itemKey) {
976f0f5640d190b0187c356eb53bd96d9f9e49da60Jean-Michel Trivi
986f0f5640d190b0187c356eb53bd96d9f9e49da60Jean-Michel Trivi              case SL_ANDROID_ITEMKEY_EOS:
9970c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                pBuff->mItems.mTsCmdData.mTsCmdCode |= ANDROID_MP2TSEVENT_EOS;
100a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten                //SL_LOGD("Found EOS event=%d", pBuff->mItems.mTsCmdData.mTsCmdCode);
101677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten                if (pItems->itemSize != 0) {
102682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                    SL_LOGE("Invalid item parameter size %u for EOS", pItems->itemSize);
103682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                    return SL_RESULT_PARAMETER_INVALID;
104677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten                }
1056f0f5640d190b0187c356eb53bd96d9f9e49da60Jean-Michel Trivi                break;
1066f0f5640d190b0187c356eb53bd96d9f9e49da60Jean-Michel Trivi
1076f0f5640d190b0187c356eb53bd96d9f9e49da60Jean-Michel Trivi              case SL_ANDROID_ITEMKEY_DISCONTINUITY:
10870c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                if (pItems->itemSize == 0) {
10970c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                    pBuff->mItems.mTsCmdData.mTsCmdCode |= ANDROID_MP2TSEVENT_DISCONTINUITY;
110a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten                    //SL_LOGD("Found DISCONTINUITYevent=%d", pBuff->mItems.mTsCmdData.mTsCmdCode);
111e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi                } else if (pItems->itemSize == sizeof(SLAuint64)) {
11270c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                    pBuff->mItems.mTsCmdData.mTsCmdCode |= ANDROID_MP2TSEVENT_DISCON_NEWPTS;
113e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi                    pBuff->mItems.mTsCmdData.mPts = *((SLAuint64*)pItems->itemData);
11470c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                    //SL_LOGD("Found PTS=%lld", pBuff->mItems.mTsCmdData.mPts);
11570c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                } else {
116682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                    SL_LOGE("Invalid item parameter size %u for MPEG-2 PTS", pItems->itemSize);
117682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                    return SL_RESULT_PARAMETER_INVALID;
11870c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                }
1196f0f5640d190b0187c356eb53bd96d9f9e49da60Jean-Michel Trivi                break;
1206f0f5640d190b0187c356eb53bd96d9f9e49da60Jean-Michel Trivi
1216f0f5640d190b0187c356eb53bd96d9f9e49da60Jean-Michel Trivi              case SL_ANDROID_ITEMKEY_FORMAT_CHANGE:
122af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                // distinguish between a "full" format change and one where it says what changed
123af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                if (pItems->itemSize == 0) {
124af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                    SL_LOGV("Received format change with no data == full format change");
125af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                    pBuff->mItems.mTsCmdData.mTsCmdCode |= ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL;
126af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                } else if (pItems->itemSize == sizeof(SLuint32)) {
127af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                    XAuint32 formatData = *((XAuint32*)pItems->itemData);
128af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                    // intentionally only supporting video change when reading which specific
129af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                    //    stream has changed, interpret other changes as full change
130af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                    if (formatData == XA_ANDROID_FORMATCHANGE_ITEMDATA_VIDEO) {
131af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                        pBuff->mItems.mTsCmdData.mTsCmdCode |=
132af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                                ANDROID_MP2TSEVENT_FORMAT_CHANGE_VIDEO;
133af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                        SL_LOGV("Received video format change");
134af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                    } else {
135af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                        // note that we don't support specifying
136af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                        //    ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL by having all bits of
137af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                        //    the data mask set, we default to it with unsupported masks
138af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                        SL_LOGE("Received format change with unsupported data, ignoring data");
139af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                        pBuff->mItems.mTsCmdData.mTsCmdCode |=
140af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                                ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL;
141af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                    }
142af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                } else {
143af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                    SL_LOGE("Received format change with invalid data size, ignoring data");
144af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi                    pBuff->mItems.mTsCmdData.mTsCmdCode |= ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL;
145677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten                }
146677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten                break;
147677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten
148677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten              default:
149677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten                // unknown item key
150682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                SL_LOGE("Unknown item key %u with size %u", pItems->itemKey, pItems->itemSize);
151682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                return SL_RESULT_PARAMETER_INVALID;
152677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten
153677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten            }// switch (pItems->itemKey)
154677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten          } break;
155677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten
156677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten          case kAndroidBufferTypeAacadts: {
157677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten            switch (pItems->itemKey) {
158677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten
159677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten              case SL_ANDROID_ITEMKEY_EOS:
160677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten                pBuff->mItems.mAdtsCmdData.mAdtsCmdCode |= ANDROID_ADTSEVENT_EOS;
161677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten                if (pItems->itemSize != 0) {
162682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                    SL_LOGE("Invalid item parameter size %u for EOS", pItems->itemSize);
163682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                    return SL_RESULT_PARAMETER_INVALID;
1646f0f5640d190b0187c356eb53bd96d9f9e49da60Jean-Michel Trivi                }
1656f0f5640d190b0187c356eb53bd96d9f9e49da60Jean-Michel Trivi                break;
1666f0f5640d190b0187c356eb53bd96d9f9e49da60Jean-Michel Trivi
1676f0f5640d190b0187c356eb53bd96d9f9e49da60Jean-Michel Trivi              default:
168677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten                // unknown item key
169682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                SL_LOGE("Unknown item key %u with size %u", pItems->itemKey, pItems->itemSize);
170682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                return SL_RESULT_PARAMETER_INVALID;
171677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten
1726f0f5640d190b0187c356eb53bd96d9f9e49da60Jean-Michel Trivi            }// switch (pItems->itemKey)
1736f0f5640d190b0187c356eb53bd96d9f9e49da60Jean-Michel Trivi          } break;
17470c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi
175677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten          case kAndroidBufferTypeInvalid:
17670c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi          default:
177677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten            // not reachable as we checked this earlier
178682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            return SL_RESULT_INTERNAL_ERROR;
179677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten
1806f0f5640d190b0187c356eb53bd96d9f9e49da60Jean-Michel Trivi        }// switch (bufferType)
181677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten
182677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        // skip past this item, including data with alignment padding
183677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        pItems = (SLAndroidBufferItem *) ((char *) pItems +
184677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten                sizeof(SLAndroidBufferItem) + itemDataSizeWithAlignmentPadding);
185677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten    }
186677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten
187677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten    // now check for invalid combinations of items
188677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten    switch (bufferType) {
189677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten
190677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten      case kAndroidBufferTypeMpeg2Ts: {
191677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        // supported Mpeg2Ts commands are mutually exclusive
192677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        switch (pBuff->mItems.mTsCmdData.mTsCmdCode) {
193677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten          // single items are allowed
194677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten          case ANDROID_MP2TSEVENT_EOS:
195682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            if (dataLength > 0) {
196682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                SL_LOGE("Can't enqueue non-zero data with EOS");
197682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                return SL_RESULT_PRECONDITIONS_VIOLATED;
198682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            }
199682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            *pEOS = true;
200682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            break;
201682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten          case ANDROID_MP2TSEVENT_NONE:
202677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten          case ANDROID_MP2TSEVENT_DISCONTINUITY:
203677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten          case ANDROID_MP2TSEVENT_DISCON_NEWPTS:
204af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi          case ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL:
205af9b87de97356722370d11d2c5797d75cb43969eJean-Michel Trivi          case ANDROID_MP2TSEVENT_FORMAT_CHANGE_VIDEO:
206677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten            break;
207677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten          // no combinations are allowed
208677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten          default:
209682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            SL_LOGE("Invalid combination of items");
210682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
211677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        }
212677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten      } break;
213677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten
214677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten      case kAndroidBufferTypeAacadts: {
215677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        // only one item supported, and thus no combination check needed
216682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        if (pBuff->mItems.mAdtsCmdData.mAdtsCmdCode == ANDROID_ADTSEVENT_EOS) {
217682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            if (dataLength > 0) {
218682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                SL_LOGE("Can't enqueue non-zero data with EOS");
219682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                return SL_RESULT_PRECONDITIONS_VIOLATED;
220682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            }
221682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            *pEOS = true;
222682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        }
223677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten      } break;
224677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten
225677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten      case kAndroidBufferTypeInvalid:
226677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten      default:
227677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        // not reachable as we checked this earlier
228682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        return SL_RESULT_INTERNAL_ERROR;
22970c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi    }
230677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten
231682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    return SL_RESULT_SUCCESS;
23270c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi}
23370c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi
23470c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi
2351c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivistatic SLresult IAndroidBufferQueue_RegisterCallback(SLAndroidBufferQueueItf self,
236fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi        slAndroidBufferQueueCallback callback, void *pContext)
237fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi{
238fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi    SL_ENTER_INTERFACE
239fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
240bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
241fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
242bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    interface_lock_exclusive(thiz);
243fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
244fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi    // verify pre-condition that media object is in the SL_PLAYSTATE_STOPPED state
24570c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi    if (SL_PLAYSTATE_STOPPED == getAssociatedState(thiz)) {
246bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz->mCallback = callback;
247bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        thiz->mContext = pContext;
24870e6a0238597223221a8bf5e506c92acf28aa35fGlenn Kasten        result = SL_RESULT_SUCCESS;
249eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi
25070c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi    } else {
25170c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi        result = SL_RESULT_PRECONDITIONS_VIOLATED;
25270c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi    }
253fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
254bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    interface_unlock_exclusive(thiz);
255fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
256fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi    SL_LEAVE_INTERFACE
257fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi}
258fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
259fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
2601c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivistatic SLresult IAndroidBufferQueue_Clear(SLAndroidBufferQueueItf self)
261fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi{
262fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi    SL_ENTER_INTERFACE
263e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi    result = SL_RESULT_SUCCESS;
264fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
265bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
266fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
267bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    interface_lock_exclusive(thiz);
268fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
269e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi    // reset the queue pointers
270e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi    thiz->mFront = &thiz->mBufferArray[0];
271e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi    thiz->mRear = &thiz->mBufferArray[0];
272e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi    // reset the queue state
273e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi    thiz->mState.count = 0;
274e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi    thiz->mState.index = 0;
275e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi
276682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    // object-specific behavior for a clear
277682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    switch (InterfaceToObjectID(thiz)) {
278682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    case SL_OBJECTID_AUDIOPLAYER:
279682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        android_audioPlayer_androidBufferQueue_clear_l((CAudioPlayer*) thiz->mThis);
280682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        break;
281682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    case XA_OBJECTID_MEDIAPLAYER:
282682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        android_Player_androidBufferQueue_clear_l((CMediaPlayer*) thiz->mThis);
283682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        break;
284682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    default:
285682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
286e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi    }
287fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
288bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    interface_unlock_exclusive(thiz);
289fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
290fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi    SL_LEAVE_INTERFACE
291fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi}
292fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
293fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
2941c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivistatic SLresult IAndroidBufferQueue_Enqueue(SLAndroidBufferQueueItf self,
29537dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi        void *pBufferContext,
29637dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi        void *pData,
297d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        SLuint32 dataLength,
298d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        const SLAndroidBufferItem *pItems,
299d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        SLuint32 itemsLength)
300fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi{
301fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi    SL_ENTER_INTERFACE
302bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi    SL_LOGD("IAndroidBufferQueue_Enqueue pData=%p dataLength=%d", pData, dataLength);
303fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
304677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten    if ((dataLength > 0) && (NULL == pData)) {
305677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        SL_LOGE("Enqueue failure: non-zero data length %u but NULL data pointer", dataLength);
306677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
307677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten    } else if ((itemsLength > 0) && (NULL == pItems)) {
308677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        SL_LOGE("Enqueue failure: non-zero items length %u but NULL items pointer", itemsLength);
309677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
310677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten    } else if ((0 == dataLength) && (0 == itemsLength)) {
311d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        // no data and no msg
312d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        SL_LOGE("Enqueue failure: trying to enqueue buffer with no data and no items.");
313d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        result = SL_RESULT_PARAMETER_INVALID;
314677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten    // Note that a non-NULL data pointer with zero data length is allowed.
315677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten    // We track that data pointer as it moves through the queue
316677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten    // to assist the application in accounting for data buffers.
317677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten    // A non-NULL items pointer with zero items length is also allowed, but has no value.
318d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi    } else {
319d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
320fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
32170c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi        // buffer size check, can be done outside of lock because buffer type can't change
32270c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi        switch (thiz->mBufferType) {
32370c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi          case kAndroidBufferTypeMpeg2Ts:
324682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            if (dataLength % MPEG2_TS_PACKET_SIZE == 0) {
325682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                // The downstream Stagefright MPEG-2 TS parser is sensitive to format errors,
326682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                // so do a quick sanity check beforehand on the first packet of the buffer.
327682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                // We don't check all the packets to avoid thrashing the data cache.
328682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                if ((dataLength > 0) && (*(SLuint8 *)pData != MPEG2_TS_PACKET_SYNC)) {
329682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                    SL_LOGE("Error enqueueing MPEG-2 TS data: incorrect packet sync");
330682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                    result = SL_RESULT_CONTENT_CORRUPTED;
331682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                    SL_LEAVE_INTERFACE
332682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                }
33370c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                break;
33470c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi            }
335682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            SL_LOGE("Error enqueueing MPEG-2 TS data: size must be a multiple of %d (packet size)",
336682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                    MPEG2_TS_PACKET_SIZE);
337bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi            result = SL_RESULT_PARAMETER_INVALID;
338bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi            SL_LEAVE_INTERFACE
339bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi            break;
340bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi          case kAndroidBufferTypeAacadts:
341682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            // zero dataLength is permitted in case of EOS command only
342677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten            if (dataLength > 0) {
343677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten                result = android::AacBqToPcmCbRenderer::validateBufferStartEndOnFrameBoundaries(
344677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten                    pData, dataLength);
345677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten                if (SL_RESULT_SUCCESS != result) {
346677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten                    SL_LOGE("Error enqueueing ADTS data: data must start and end on frame "
347677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten                            "boundaries");
348677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten                    SL_LEAVE_INTERFACE
349677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten                }
350bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi            }
351bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi            break;
35270c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi          case kAndroidBufferTypeInvalid:
35370c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi          default:
35470c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi            result = SL_RESULT_PARAMETER_INVALID;
35570c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi            SL_LEAVE_INTERFACE
35670c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi        }
35770c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi
358d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        interface_lock_exclusive(thiz);
359fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
360d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        AdvancedBufferHeader *oldRear = thiz->mRear, *newRear;
361d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        if ((newRear = oldRear + 1) == &thiz->mBufferArray[thiz->mNumBuffers + 1]) {
362d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi            newRear = thiz->mBufferArray;
363d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        }
364682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        if (thiz->mEOS) {
365682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            SL_LOGE("Can't enqueue after EOS");
366682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            result = SL_RESULT_PRECONDITIONS_VIOLATED;
367682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        } else if (newRear == thiz->mFront) {
368d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi            result = SL_RESULT_BUFFER_INSUFFICIENT;
369d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        } else {
370677c76347d9aaca4cf3746b3dbfc8a741281066bGlenn Kasten            // set oldRear->mItems based on items
371682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            result = setItems(dataLength, pItems, itemsLength, thiz->mBufferType, oldRear,
372682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                    &thiz->mEOS);
373682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            if (SL_RESULT_SUCCESS == result) {
374682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                oldRear->mDataBuffer = pData;
375682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                oldRear->mDataSize = dataLength;
376682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                oldRear->mDataSizeConsumed = 0;
377682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                oldRear->mBufferContext = pBufferContext;
378682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                //oldRear->mBufferState = TBD;
379682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                thiz->mRear = newRear;
380682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                ++thiz->mState.count;
381682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            }
382d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        }
383d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        // set enqueue attribute if state is PLAYING and the first buffer is enqueued
384d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        interface_unlock_exclusive_attributes(thiz, ((SL_RESULT_SUCCESS == result) &&
385d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                (1 == thiz->mState.count) && (SL_PLAYSTATE_PLAYING == getAssociatedState(thiz))) ?
38670c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi                        ATTR_ABQ_ENQUEUE : ATTR_NONE);
387eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi    }
388fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
389fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi    SL_LEAVE_INTERFACE
390fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi}
391fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
392fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
3931c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivistatic SLresult IAndroidBufferQueue_GetState(SLAndroidBufferQueueItf self,
394e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi        SLAndroidBufferQueueState *pState)
395e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi{
396e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi    SL_ENTER_INTERFACE
397e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi
398e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi    // Note that GetState while a Clear is pending is equivalent to GetState before the Clear
399e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi
400e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi    if (NULL == pState) {
401e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi        result = SL_RESULT_PARAMETER_INVALID;
402e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi    } else {
403e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi        IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
404e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi
405e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi        interface_lock_shared(thiz);
406e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi
407e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi        pState->count = thiz->mState.count;
408e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi        pState->index = thiz->mState.index;
409e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi
410e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi        interface_unlock_shared(thiz);
411e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi
412e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi        result = SL_RESULT_SUCCESS;
413e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi    }
414e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi
415e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi    SL_LEAVE_INTERFACE
416e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi}
417e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi
418e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi
4191c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivistatic SLresult IAndroidBufferQueue_SetCallbackEventsMask(SLAndroidBufferQueueItf self,
4201c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi        SLuint32 eventFlags)
4211c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi{
4221c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi    SL_ENTER_INTERFACE
4231c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi
4241c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi    IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
4251c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi    interface_lock_exclusive(thiz);
4261c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi    // FIXME only supporting SL_ANDROIDBUFFERQUEUEEVENT_PROCESSED in this implementation
427682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    if (!(~(SL_ANDROIDBUFFERQUEUEEVENT_PROCESSED /* | others TBD */ ) & eventFlags)) {
4281c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi        thiz->mCallbackEventsMask = eventFlags;
4291c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi        result = SL_RESULT_SUCCESS;
4301c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi    } else {
4311c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi        result = SL_RESULT_FEATURE_UNSUPPORTED;
4321c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi    }
4331c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi    interface_unlock_exclusive(thiz);
4341c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi
4351c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi    SL_LEAVE_INTERFACE
4361c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi}
4371c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi
4381c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi
4391c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivistatic SLresult IAndroidBufferQueue_GetCallbackEventsMask(SLAndroidBufferQueueItf self,
4401c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi        SLuint32 *pEventFlags)
4411c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi{
4421c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi    SL_ENTER_INTERFACE
4431c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi
4441c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi    if (NULL == pEventFlags) {
4451c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi        result = SL_RESULT_PARAMETER_INVALID;
4461c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi    } else {
4471c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi        IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
448b566926611b2105a46c4ff98238ad06aca54104dGlenn Kasten        interface_lock_shared(thiz);
4491c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi        SLuint32 callbackEventsMask = thiz->mCallbackEventsMask;
450b566926611b2105a46c4ff98238ad06aca54104dGlenn Kasten        interface_unlock_shared(thiz);
4511c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi        *pEventFlags = callbackEventsMask;
4521c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi        result = SL_RESULT_SUCCESS;
4531c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi    }
4541c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi
4551c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi    SL_LEAVE_INTERFACE
4561c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi}
4571c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi
4581c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi
459fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivistatic const struct SLAndroidBufferQueueItf_ IAndroidBufferQueue_Itf = {
460fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi    IAndroidBufferQueue_RegisterCallback,
461fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi    IAndroidBufferQueue_Clear,
462e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi    IAndroidBufferQueue_Enqueue,
4631c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi    IAndroidBufferQueue_GetState,
4641c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi    IAndroidBufferQueue_SetCallbackEventsMask,
4651c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi    IAndroidBufferQueue_GetCallbackEventsMask
466fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi};
467fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
468d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
469fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivivoid IAndroidBufferQueue_init(void *self)
470fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi{
471bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
472bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mItf = &IAndroidBufferQueue_Itf;
473fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi
474d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi    thiz->mState.count = 0;
475d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi    thiz->mState.index = 0;
476d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
477bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mCallback = NULL;
478bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mContext = NULL;
4791c853a41d9d9886e60618a7c878ce3912f46bf3cJean-Michel Trivi    thiz->mCallbackEventsMask = SL_ANDROIDBUFFERQUEUEEVENT_PROCESSED;
480d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
48170c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi    thiz->mBufferType = kAndroidBufferTypeInvalid;
482d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi    thiz->mBufferArray = NULL;
483d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi    thiz->mFront = NULL;
484d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi    thiz->mRear = NULL;
485682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    thiz->mEOS = false;
486d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi}
487d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
488d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi
489d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivivoid IAndroidBufferQueue_deinit(void *self)
490d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi{
491d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi    IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self;
492d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi    if (NULL != thiz->mBufferArray) {
493d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        free(thiz->mBufferArray);
494d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        thiz->mBufferArray = NULL;
495d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi    }
496fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi}
497682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten
498682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten
499682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten#if 0
500682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten// Dump the contents of an IAndroidBufferQueue to the log.  This is for debugging only,
501682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten// and is not a documented API.  The associated object is locked throughout for atomicity,
502682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten// but the log entries may be interspersed with unrelated logs.
503682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten
504682f9be91e641e80739c21d6ff124379a806182aGlenn Kastenvoid IAndroidBufferQueue_log(IAndroidBufferQueue *thiz)
505682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten{
506682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    interface_lock_shared(thiz);
507682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    SL_LOGI("IAndroidBufferQueue %p:", thiz);
508682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    SL_LOGI("  mState.count=%u mState.index=%u mCallback=%p mContext=%p",
509682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            thiz->mState.count, thiz->mState.index, thiz->mCallback, thiz->mContext);
510682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    const char *bufferTypeString;
511682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    switch (thiz->mBufferType) {
512682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    case kAndroidBufferTypeInvalid:
513682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        bufferTypeString = "kAndroidBufferTypeInvalid";
514682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        break;
515682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    case kAndroidBufferTypeMpeg2Ts:
516682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        bufferTypeString = "kAndroidBufferTypeMpeg2Ts";
517682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        break;
518682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    case kAndroidBufferTypeAacadts:
519682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        bufferTypeString = "kAndroidBufferTypeAacadts";
520682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        break;
521682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    default:
522682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        bufferTypeString = "unknown";
523682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        break;
524682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    }
525682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    SL_LOGI("  mCallbackEventsMask=0x%x, mBufferType=0x%x (%s), mEOS=%s",
526682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            thiz->mCallbackEventsMask,
527682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            thiz->mBufferType, bufferTypeString,
528682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            thiz->mEOS ? "true" : "false");
529682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    SL_LOGI("  mBufferArray=%p, mFront=%p (%u), mRear=%p (%u)",
530682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            thiz->mBufferArray,
531682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            thiz->mFront, thiz->mFront - thiz->mBufferArray,
532682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            thiz->mRear, thiz->mRear - thiz->mBufferArray);
533682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    SL_LOGI("  index mDataBuffer mDataSize mDataSizeConsumed mBufferContext mItems");
534682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    const AdvancedBufferHeader *hdr;
535682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    for (hdr = thiz->mFront; hdr != thiz->mRear; ) {
536682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        SLuint32 i = hdr - thiz->mBufferArray;
537682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        char itemString[32];
538682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        switch (thiz->mBufferType) {
539682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        case kAndroidBufferTypeMpeg2Ts:
540682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            switch (hdr->mItems.mTsCmdData.mTsCmdCode) {
541682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            case ANDROID_MP2TSEVENT_NONE:
542682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                strcpy(itemString, "NONE");
543682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                break;
544682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            case ANDROID_MP2TSEVENT_EOS:
545682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                strcpy(itemString, "EOS");
546682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                break;
547682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            case ANDROID_MP2TSEVENT_DISCONTINUITY:
548682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                strcpy(itemString, "DISCONTINUITY");
549682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                break;
550682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            case ANDROID_MP2TSEVENT_DISCON_NEWPTS:
551682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                snprintf(itemString, sizeof(itemString), "NEWPTS %llu",
552682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                        hdr->mItems.mTsCmdData.mPts);
553682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                break;
554682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            case ANDROID_MP2TSEVENT_FORMAT_CHANGE:
555682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                strcpy(itemString, "FORMAT_CHANGE");
556682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                break;
557682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            default:
558682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                snprintf(itemString, sizeof(itemString), "0x%x", hdr->mItems.mTsCmdData.mTsCmdCode);
559682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                break;
560682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            }
561682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            break;
562682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        case kAndroidBufferTypeAacadts:
563682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            switch (hdr->mItems.mAdtsCmdData.mAdtsCmdCode) {
564682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            case ANDROID_ADTSEVENT_NONE:
565682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                strcpy(itemString, "NONE");
566682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                break;
567682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            case ANDROID_ADTSEVENT_EOS:
568682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                strcpy(itemString, "EOS");
569682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                break;
570682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            default:
571682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                snprintf(itemString, sizeof(itemString), "0x%x",
572682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                        hdr->mItems.mAdtsCmdData.mAdtsCmdCode);
573682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                break;
574682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            }
575682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            break;
576682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        default:
577682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            strcpy(itemString, "");
578682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            break;
579682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        }
580682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        SL_LOGI("  %5u %11p %9u %17u %14p %s",
581682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                i, hdr->mDataBuffer, hdr->mDataSize, hdr->mDataSizeConsumed,
582682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                hdr->mBufferContext, itemString);
583682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten                // mBufferState
584682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        if (++hdr == &thiz->mBufferArray[thiz->mNumBuffers + 1]) {
585682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten            hdr = thiz->mBufferArray;
586682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten        }
587682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    }
588682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten    interface_unlock_shared(thiz);
589682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten}
590682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten
591682f9be91e641e80739c21d6ff124379a806182aGlenn Kasten#endif
592