xref: /aosp_15_r20/frameworks/wilhelm/src/data.cpp (revision bebae9c0e76121f8312ccb50385c080b3a0b023c)
1*bebae9c0SAndroid Build Coastguard Worker /*
2*bebae9c0SAndroid Build Coastguard Worker  * Copyright (C) 2010 The Android Open Source Project
3*bebae9c0SAndroid Build Coastguard Worker  *
4*bebae9c0SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*bebae9c0SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*bebae9c0SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*bebae9c0SAndroid Build Coastguard Worker  *
8*bebae9c0SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*bebae9c0SAndroid Build Coastguard Worker  *
10*bebae9c0SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*bebae9c0SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*bebae9c0SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*bebae9c0SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*bebae9c0SAndroid Build Coastguard Worker  * limitations under the License.
15*bebae9c0SAndroid Build Coastguard Worker  */
16*bebae9c0SAndroid Build Coastguard Worker 
17*bebae9c0SAndroid Build Coastguard Worker /** Data locator, data format, data source, and data sink support */
18*bebae9c0SAndroid Build Coastguard Worker 
19*bebae9c0SAndroid Build Coastguard Worker #include "sles_allinclusive.h"
20*bebae9c0SAndroid Build Coastguard Worker #ifdef ANDROID  // FIXME This file should be portable
21*bebae9c0SAndroid Build Coastguard Worker #include "android/channels.h"
22*bebae9c0SAndroid Build Coastguard Worker #include "data.h"
23*bebae9c0SAndroid Build Coastguard Worker #endif
24*bebae9c0SAndroid Build Coastguard Worker 
25*bebae9c0SAndroid Build Coastguard Worker /** \brief Check a data locator and make local deep copy */
26*bebae9c0SAndroid Build Coastguard Worker 
checkDataLocator(const char * name,void * pLocator,DataLocator * pDataLocator,SLuint32 allowedDataLocatorMask)27*bebae9c0SAndroid Build Coastguard Worker static SLresult checkDataLocator(const char *name, void *pLocator, DataLocator *pDataLocator,
28*bebae9c0SAndroid Build Coastguard Worker         SLuint32 allowedDataLocatorMask)
29*bebae9c0SAndroid Build Coastguard Worker {
30*bebae9c0SAndroid Build Coastguard Worker     assert(NULL != name && NULL != pDataLocator);
31*bebae9c0SAndroid Build Coastguard Worker     SLresult result = SL_RESULT_SUCCESS;
32*bebae9c0SAndroid Build Coastguard Worker 
33*bebae9c0SAndroid Build Coastguard Worker     SLuint32 locatorType;
34*bebae9c0SAndroid Build Coastguard Worker     if (NULL == pLocator) {
35*bebae9c0SAndroid Build Coastguard Worker         pDataLocator->mLocatorType = locatorType = SL_DATALOCATOR_NULL;
36*bebae9c0SAndroid Build Coastguard Worker     } else {
37*bebae9c0SAndroid Build Coastguard Worker         locatorType = *(SLuint32 *)pLocator;
38*bebae9c0SAndroid Build Coastguard Worker         switch (locatorType) {
39*bebae9c0SAndroid Build Coastguard Worker 
40*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_ADDRESS:
41*bebae9c0SAndroid Build Coastguard Worker             pDataLocator->mAddress = *(SLDataLocator_Address *)pLocator;
42*bebae9c0SAndroid Build Coastguard Worker             // if length is greater than zero, then the address must be non-NULL
43*bebae9c0SAndroid Build Coastguard Worker             if ((0 < pDataLocator->mAddress.length) && (NULL == pDataLocator->mAddress.pAddress)) {
44*bebae9c0SAndroid Build Coastguard Worker                 SL_LOGE("%s: pAddress=NULL", name);
45*bebae9c0SAndroid Build Coastguard Worker                 result = SL_RESULT_PARAMETER_INVALID;
46*bebae9c0SAndroid Build Coastguard Worker             }
47*bebae9c0SAndroid Build Coastguard Worker             break;
48*bebae9c0SAndroid Build Coastguard Worker 
49*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_BUFFERQUEUE:
50*bebae9c0SAndroid Build Coastguard Worker #ifdef ANDROID
51*bebae9c0SAndroid Build Coastguard Worker         // This is an alias that is _not_ converted; the rest of the code must check for both
52*bebae9c0SAndroid Build Coastguard Worker         // locator types. That's because it is only an alias for audio players, not audio recorder
53*bebae9c0SAndroid Build Coastguard Worker         // objects so we have to remember the distinction.
54*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
55*bebae9c0SAndroid Build Coastguard Worker #endif
56*bebae9c0SAndroid Build Coastguard Worker             pDataLocator->mBufferQueue = *(SLDataLocator_BufferQueue *)pLocator;
57*bebae9c0SAndroid Build Coastguard Worker             // number of buffers must be specified, there is no default value, and can't be too big
58*bebae9c0SAndroid Build Coastguard Worker             if (!((1 <= pDataLocator->mBufferQueue.numBuffers) &&
59*bebae9c0SAndroid Build Coastguard Worker                 (pDataLocator->mBufferQueue.numBuffers <= 255))) {
60*bebae9c0SAndroid Build Coastguard Worker                 SL_LOGE("%s: numBuffers=%u", name, pDataLocator->mBufferQueue.numBuffers);
61*bebae9c0SAndroid Build Coastguard Worker                 result = SL_RESULT_PARAMETER_INVALID;
62*bebae9c0SAndroid Build Coastguard Worker             }
63*bebae9c0SAndroid Build Coastguard Worker             break;
64*bebae9c0SAndroid Build Coastguard Worker 
65*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_IODEVICE:
66*bebae9c0SAndroid Build Coastguard Worker             {
67*bebae9c0SAndroid Build Coastguard Worker             pDataLocator->mIODevice = *(SLDataLocator_IODevice *)pLocator;
68*bebae9c0SAndroid Build Coastguard Worker             SLuint32 deviceType = pDataLocator->mIODevice.deviceType;
69*bebae9c0SAndroid Build Coastguard Worker             SLObjectItf device = pDataLocator->mIODevice.device;
70*bebae9c0SAndroid Build Coastguard Worker             if (NULL != device) {
71*bebae9c0SAndroid Build Coastguard Worker                 pDataLocator->mIODevice.deviceID = 0;
72*bebae9c0SAndroid Build Coastguard Worker                 SLuint32 expectedObjectID;
73*bebae9c0SAndroid Build Coastguard Worker                 switch (deviceType) {
74*bebae9c0SAndroid Build Coastguard Worker                 case SL_IODEVICE_LEDARRAY:
75*bebae9c0SAndroid Build Coastguard Worker                     expectedObjectID = SL_OBJECTID_LEDDEVICE;
76*bebae9c0SAndroid Build Coastguard Worker                     break;
77*bebae9c0SAndroid Build Coastguard Worker                 case SL_IODEVICE_VIBRA:
78*bebae9c0SAndroid Build Coastguard Worker                     expectedObjectID = SL_OBJECTID_VIBRADEVICE;
79*bebae9c0SAndroid Build Coastguard Worker                     break;
80*bebae9c0SAndroid Build Coastguard Worker                 case XA_IODEVICE_CAMERA:
81*bebae9c0SAndroid Build Coastguard Worker                     expectedObjectID = XA_OBJECTID_CAMERADEVICE;
82*bebae9c0SAndroid Build Coastguard Worker                     break;
83*bebae9c0SAndroid Build Coastguard Worker                 case XA_IODEVICE_RADIO:
84*bebae9c0SAndroid Build Coastguard Worker                     expectedObjectID = XA_OBJECTID_RADIODEVICE;
85*bebae9c0SAndroid Build Coastguard Worker                     break;
86*bebae9c0SAndroid Build Coastguard Worker                 // audio input and audio output cannot be specified via objects
87*bebae9c0SAndroid Build Coastguard Worker                 case SL_IODEVICE_AUDIOINPUT:
88*bebae9c0SAndroid Build Coastguard Worker                 // case SL_IODEVICE_AUDIOOUTPUT:   // does not exist in 1.0.1, added in 1.1
89*bebae9c0SAndroid Build Coastguard Worker                 default:
90*bebae9c0SAndroid Build Coastguard Worker                     SL_LOGE("%s: deviceType=%u", name, deviceType);
91*bebae9c0SAndroid Build Coastguard Worker                     pDataLocator->mIODevice.device = NULL;
92*bebae9c0SAndroid Build Coastguard Worker                     expectedObjectID = 0;
93*bebae9c0SAndroid Build Coastguard Worker                     result = SL_RESULT_PARAMETER_INVALID;
94*bebae9c0SAndroid Build Coastguard Worker                 }
95*bebae9c0SAndroid Build Coastguard Worker                 if (result == SL_RESULT_SUCCESS) {
96*bebae9c0SAndroid Build Coastguard Worker                     // check that device has the correct object ID and is realized,
97*bebae9c0SAndroid Build Coastguard Worker                     // and acquire a strong reference to it
98*bebae9c0SAndroid Build Coastguard Worker                     result = AcquireStrongRef((IObject *) device, expectedObjectID);
99*bebae9c0SAndroid Build Coastguard Worker                     if (SL_RESULT_SUCCESS != result) {
100*bebae9c0SAndroid Build Coastguard Worker                         SL_LOGE("%s: locatorType=IODEVICE, but device field %p has wrong " \
101*bebae9c0SAndroid Build Coastguard Worker                             "object ID or is not realized", name, device);
102*bebae9c0SAndroid Build Coastguard Worker                         pDataLocator->mIODevice.device = NULL;
103*bebae9c0SAndroid Build Coastguard Worker                     }
104*bebae9c0SAndroid Build Coastguard Worker                 }
105*bebae9c0SAndroid Build Coastguard Worker             } else {
106*bebae9c0SAndroid Build Coastguard Worker                 SLuint32 deviceID = pDataLocator->mIODevice.deviceID;
107*bebae9c0SAndroid Build Coastguard Worker                 switch (deviceType) {
108*bebae9c0SAndroid Build Coastguard Worker                 case SL_IODEVICE_LEDARRAY:
109*bebae9c0SAndroid Build Coastguard Worker                     if (SL_DEFAULTDEVICEID_LED != deviceID) {
110*bebae9c0SAndroid Build Coastguard Worker                         SL_LOGE("%s: invalid LED deviceID=%u", name, deviceID);
111*bebae9c0SAndroid Build Coastguard Worker                         result = SL_RESULT_PARAMETER_INVALID;
112*bebae9c0SAndroid Build Coastguard Worker                     }
113*bebae9c0SAndroid Build Coastguard Worker                     break;
114*bebae9c0SAndroid Build Coastguard Worker                 case SL_IODEVICE_VIBRA:
115*bebae9c0SAndroid Build Coastguard Worker                     if (SL_DEFAULTDEVICEID_VIBRA != deviceID) {
116*bebae9c0SAndroid Build Coastguard Worker                         SL_LOGE("%s: invalid vibra deviceID=%u", name, deviceID);
117*bebae9c0SAndroid Build Coastguard Worker                         result = SL_RESULT_PARAMETER_INVALID;
118*bebae9c0SAndroid Build Coastguard Worker                     }
119*bebae9c0SAndroid Build Coastguard Worker                     break;
120*bebae9c0SAndroid Build Coastguard Worker                 case SL_IODEVICE_AUDIOINPUT:
121*bebae9c0SAndroid Build Coastguard Worker                     if (SL_DEFAULTDEVICEID_AUDIOINPUT != deviceID) {
122*bebae9c0SAndroid Build Coastguard Worker                         SL_LOGE("%s: invalid audio input deviceID=%u", name, deviceID);
123*bebae9c0SAndroid Build Coastguard Worker                         result = SL_RESULT_PARAMETER_INVALID;
124*bebae9c0SAndroid Build Coastguard Worker                     }
125*bebae9c0SAndroid Build Coastguard Worker                     break;
126*bebae9c0SAndroid Build Coastguard Worker                 case XA_IODEVICE_RADIO:
127*bebae9c0SAndroid Build Coastguard Worker                     // no default device ID for radio; see Khronos bug XXXX
128*bebae9c0SAndroid Build Coastguard Worker                     break;
129*bebae9c0SAndroid Build Coastguard Worker                 case XA_IODEVICE_CAMERA:
130*bebae9c0SAndroid Build Coastguard Worker                     if (XA_DEFAULTDEVICEID_CAMERA != deviceID) {
131*bebae9c0SAndroid Build Coastguard Worker                         SL_LOGE("%s: invalid audio input deviceID=%u", name, deviceID);
132*bebae9c0SAndroid Build Coastguard Worker                         result = XA_RESULT_PARAMETER_INVALID;
133*bebae9c0SAndroid Build Coastguard Worker                     }
134*bebae9c0SAndroid Build Coastguard Worker                     break;
135*bebae9c0SAndroid Build Coastguard Worker                 // case SL_IODEVICE_AUDIOOUTPUT:
136*bebae9c0SAndroid Build Coastguard Worker                     // does not exist in 1.0.1, added in 1.1
137*bebae9c0SAndroid Build Coastguard Worker                     // break;
138*bebae9c0SAndroid Build Coastguard Worker                 default:
139*bebae9c0SAndroid Build Coastguard Worker                     SL_LOGE("%s: deviceType=%u is invalid", name, deviceType);
140*bebae9c0SAndroid Build Coastguard Worker                     result = SL_RESULT_PARAMETER_INVALID;
141*bebae9c0SAndroid Build Coastguard Worker                 }
142*bebae9c0SAndroid Build Coastguard Worker             }
143*bebae9c0SAndroid Build Coastguard Worker             }
144*bebae9c0SAndroid Build Coastguard Worker             break;
145*bebae9c0SAndroid Build Coastguard Worker 
146*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_MIDIBUFFERQUEUE:
147*bebae9c0SAndroid Build Coastguard Worker             pDataLocator->mMIDIBufferQueue = *(SLDataLocator_MIDIBufferQueue *)pLocator;
148*bebae9c0SAndroid Build Coastguard Worker             if (0 == pDataLocator->mMIDIBufferQueue.tpqn) {
149*bebae9c0SAndroid Build Coastguard Worker                 pDataLocator->mMIDIBufferQueue.tpqn = 192;
150*bebae9c0SAndroid Build Coastguard Worker             }
151*bebae9c0SAndroid Build Coastguard Worker             // number of buffers must be specified, there is no default value, and can't be too big
152*bebae9c0SAndroid Build Coastguard Worker             if (!((1 <= pDataLocator->mMIDIBufferQueue.numBuffers) &&
153*bebae9c0SAndroid Build Coastguard Worker                 (pDataLocator->mMIDIBufferQueue.numBuffers <= 255))) {
154*bebae9c0SAndroid Build Coastguard Worker                 SL_LOGE("%s: SLDataLocator_MIDIBufferQueue.numBuffers=%d", name,
155*bebae9c0SAndroid Build Coastguard Worker                         pDataLocator->mMIDIBufferQueue.numBuffers);
156*bebae9c0SAndroid Build Coastguard Worker                 result = SL_RESULT_PARAMETER_INVALID;
157*bebae9c0SAndroid Build Coastguard Worker             }
158*bebae9c0SAndroid Build Coastguard Worker             break;
159*bebae9c0SAndroid Build Coastguard Worker 
160*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_OUTPUTMIX:
161*bebae9c0SAndroid Build Coastguard Worker             pDataLocator->mOutputMix = *(SLDataLocator_OutputMix *)pLocator;
162*bebae9c0SAndroid Build Coastguard Worker             // check that output mix object has the correct object ID and is realized,
163*bebae9c0SAndroid Build Coastguard Worker             // and acquire a strong reference to it
164*bebae9c0SAndroid Build Coastguard Worker             result = AcquireStrongRef((IObject *) pDataLocator->mOutputMix.outputMix,
165*bebae9c0SAndroid Build Coastguard Worker                 SL_OBJECTID_OUTPUTMIX);
166*bebae9c0SAndroid Build Coastguard Worker             if (SL_RESULT_SUCCESS != result) {
167*bebae9c0SAndroid Build Coastguard Worker                 SL_LOGE("%s: locatorType=SL_DATALOCATOR_OUTPUTMIX, but outputMix field %p does " \
168*bebae9c0SAndroid Build Coastguard Worker                     "not refer to an SL_OBJECTID_OUTPUTMIX or the output mix is not realized", \
169*bebae9c0SAndroid Build Coastguard Worker                     name, pDataLocator->mOutputMix.outputMix);
170*bebae9c0SAndroid Build Coastguard Worker                 pDataLocator->mOutputMix.outputMix = NULL;
171*bebae9c0SAndroid Build Coastguard Worker             }
172*bebae9c0SAndroid Build Coastguard Worker             break;
173*bebae9c0SAndroid Build Coastguard Worker 
174*bebae9c0SAndroid Build Coastguard Worker         case XA_DATALOCATOR_NATIVEDISPLAY:
175*bebae9c0SAndroid Build Coastguard Worker             pDataLocator->mNativeDisplay = *(XADataLocator_NativeDisplay *)pLocator;
176*bebae9c0SAndroid Build Coastguard Worker             // hWindow is NDK C ANativeWindow * and hDisplay must be NULL
177*bebae9c0SAndroid Build Coastguard Worker             if (pDataLocator->mNativeDisplay.hWindow == NULL) {
178*bebae9c0SAndroid Build Coastguard Worker                 SL_LOGE("%s: hWindow must be non-NULL ANativeWindow *", name);
179*bebae9c0SAndroid Build Coastguard Worker                 result = SL_RESULT_PARAMETER_INVALID;
180*bebae9c0SAndroid Build Coastguard Worker             }
181*bebae9c0SAndroid Build Coastguard Worker             if (pDataLocator->mNativeDisplay.hDisplay != NULL) {
182*bebae9c0SAndroid Build Coastguard Worker                 SL_LOGE("%s: hDisplay must be NULL, but is %p", name,
183*bebae9c0SAndroid Build Coastguard Worker                         pDataLocator->mNativeDisplay.hDisplay);
184*bebae9c0SAndroid Build Coastguard Worker                 result = SL_RESULT_PARAMETER_INVALID;
185*bebae9c0SAndroid Build Coastguard Worker             }
186*bebae9c0SAndroid Build Coastguard Worker             break;
187*bebae9c0SAndroid Build Coastguard Worker 
188*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_URI:
189*bebae9c0SAndroid Build Coastguard Worker             {
190*bebae9c0SAndroid Build Coastguard Worker             pDataLocator->mURI = *(SLDataLocator_URI *)pLocator;
191*bebae9c0SAndroid Build Coastguard Worker             if (NULL == pDataLocator->mURI.URI) {
192*bebae9c0SAndroid Build Coastguard Worker                 SL_LOGE("%s: invalid URI=NULL", name);
193*bebae9c0SAndroid Build Coastguard Worker                 result = SL_RESULT_PARAMETER_INVALID;
194*bebae9c0SAndroid Build Coastguard Worker             } else {
195*bebae9c0SAndroid Build Coastguard Worker                 // NTH verify URI address for validity
196*bebae9c0SAndroid Build Coastguard Worker                 size_t len = strlen((const char *) pDataLocator->mURI.URI);
197*bebae9c0SAndroid Build Coastguard Worker                 SLchar *myURI = (SLchar *) malloc(len + 1);
198*bebae9c0SAndroid Build Coastguard Worker                 if (NULL == myURI) {
199*bebae9c0SAndroid Build Coastguard Worker                     result = SL_RESULT_MEMORY_FAILURE;
200*bebae9c0SAndroid Build Coastguard Worker                 } else {
201*bebae9c0SAndroid Build Coastguard Worker                     memcpy(myURI, pDataLocator->mURI.URI, len + 1);
202*bebae9c0SAndroid Build Coastguard Worker                     // Verify that another thread didn't change the NUL-terminator after we used it
203*bebae9c0SAndroid Build Coastguard Worker                     // to determine length of string to copy. It's OK if the string became shorter.
204*bebae9c0SAndroid Build Coastguard Worker                     if ('\0' != myURI[len]) {
205*bebae9c0SAndroid Build Coastguard Worker                         free(myURI);
206*bebae9c0SAndroid Build Coastguard Worker                         myURI = NULL;
207*bebae9c0SAndroid Build Coastguard Worker                         result = SL_RESULT_PARAMETER_INVALID;
208*bebae9c0SAndroid Build Coastguard Worker                     }
209*bebae9c0SAndroid Build Coastguard Worker                 }
210*bebae9c0SAndroid Build Coastguard Worker                 pDataLocator->mURI.URI = myURI;
211*bebae9c0SAndroid Build Coastguard Worker             }
212*bebae9c0SAndroid Build Coastguard Worker             }
213*bebae9c0SAndroid Build Coastguard Worker             break;
214*bebae9c0SAndroid Build Coastguard Worker 
215*bebae9c0SAndroid Build Coastguard Worker #ifdef ANDROID
216*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_ANDROIDFD:
217*bebae9c0SAndroid Build Coastguard Worker         {
218*bebae9c0SAndroid Build Coastguard Worker             pDataLocator->mFD = *(SLDataLocator_AndroidFD *)pLocator;
219*bebae9c0SAndroid Build Coastguard Worker             SL_LOGV("%s: fd=%d offset=%lld length=%lld", name, pDataLocator->mFD.fd,
220*bebae9c0SAndroid Build Coastguard Worker                     pDataLocator->mFD.offset, pDataLocator->mFD.length);
221*bebae9c0SAndroid Build Coastguard Worker             // NTH check against process fd limit
222*bebae9c0SAndroid Build Coastguard Worker             if (0 > pDataLocator->mFD.fd) {
223*bebae9c0SAndroid Build Coastguard Worker                 SL_LOGE("%s: fd=%d\n", name, pDataLocator->mFD.fd);
224*bebae9c0SAndroid Build Coastguard Worker                 result = SL_RESULT_PARAMETER_INVALID;
225*bebae9c0SAndroid Build Coastguard Worker             }
226*bebae9c0SAndroid Build Coastguard Worker             break;
227*bebae9c0SAndroid Build Coastguard Worker         }
228*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_ANDROIDBUFFERQUEUE:
229*bebae9c0SAndroid Build Coastguard Worker         {
230*bebae9c0SAndroid Build Coastguard Worker             pDataLocator->mABQ = *(SLDataLocator_AndroidBufferQueue*)pLocator;
231*bebae9c0SAndroid Build Coastguard Worker             // number of buffers must be specified, there is no default value, and can't be too big
232*bebae9c0SAndroid Build Coastguard Worker             if (!((1 <= pDataLocator->mBufferQueue.numBuffers) &&
233*bebae9c0SAndroid Build Coastguard Worker                     (pDataLocator->mBufferQueue.numBuffers <= 255))) {
234*bebae9c0SAndroid Build Coastguard Worker                 SL_LOGE("%s: numBuffers=%u", name, pDataLocator->mABQ.numBuffers);
235*bebae9c0SAndroid Build Coastguard Worker                 result = SL_RESULT_PARAMETER_INVALID;
236*bebae9c0SAndroid Build Coastguard Worker             }
237*bebae9c0SAndroid Build Coastguard Worker             break;
238*bebae9c0SAndroid Build Coastguard Worker         }
239*bebae9c0SAndroid Build Coastguard Worker #endif
240*bebae9c0SAndroid Build Coastguard Worker 
241*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_NULL:   // a NULL pointer is allowed, but not a pointer to NULL
242*bebae9c0SAndroid Build Coastguard Worker         default:
243*bebae9c0SAndroid Build Coastguard Worker             SL_LOGE("%s: locatorType=%u", name, locatorType);
244*bebae9c0SAndroid Build Coastguard Worker             result = SL_RESULT_PARAMETER_INVALID;
245*bebae9c0SAndroid Build Coastguard Worker         }
246*bebae9c0SAndroid Build Coastguard Worker 
247*bebae9c0SAndroid Build Coastguard Worker         // Verify that another thread didn't change the locatorType field after we used it
248*bebae9c0SAndroid Build Coastguard Worker         // to determine sizeof struct to copy.
249*bebae9c0SAndroid Build Coastguard Worker         if ((SL_RESULT_SUCCESS == result) && (locatorType != pDataLocator->mLocatorType)) {
250*bebae9c0SAndroid Build Coastguard Worker             SL_LOGE("%s: locatorType changed from %u to %u", name, locatorType,
251*bebae9c0SAndroid Build Coastguard Worker                     pDataLocator->mLocatorType);
252*bebae9c0SAndroid Build Coastguard Worker             result = SL_RESULT_PRECONDITIONS_VIOLATED;
253*bebae9c0SAndroid Build Coastguard Worker         }
254*bebae9c0SAndroid Build Coastguard Worker 
255*bebae9c0SAndroid Build Coastguard Worker     }
256*bebae9c0SAndroid Build Coastguard Worker 
257*bebae9c0SAndroid Build Coastguard Worker     // Verify that the data locator type is allowed in this context
258*bebae9c0SAndroid Build Coastguard Worker     if (SL_RESULT_SUCCESS == result) {
259*bebae9c0SAndroid Build Coastguard Worker         SLuint32 actualMask;
260*bebae9c0SAndroid Build Coastguard Worker         switch (locatorType) {
261*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_NULL:
262*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_URI:
263*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_ADDRESS:
264*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_IODEVICE:
265*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_OUTPUTMIX:
266*bebae9c0SAndroid Build Coastguard Worker         case XA_DATALOCATOR_NATIVEDISPLAY:
267*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_BUFFERQUEUE:
268*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_MIDIBUFFERQUEUE:
269*bebae9c0SAndroid Build Coastguard Worker             actualMask = 1L << locatorType;
270*bebae9c0SAndroid Build Coastguard Worker             break;
271*bebae9c0SAndroid Build Coastguard Worker #ifdef ANDROID
272*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_ANDROIDFD:
273*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
274*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_ANDROIDBUFFERQUEUE:
275*bebae9c0SAndroid Build Coastguard Worker             actualMask = 0x100L << (locatorType - SL_DATALOCATOR_ANDROIDFD);
276*bebae9c0SAndroid Build Coastguard Worker             break;
277*bebae9c0SAndroid Build Coastguard Worker #endif
278*bebae9c0SAndroid Build Coastguard Worker         default:
279*bebae9c0SAndroid Build Coastguard Worker             assert(false);
280*bebae9c0SAndroid Build Coastguard Worker             actualMask = 0L;
281*bebae9c0SAndroid Build Coastguard Worker             break;
282*bebae9c0SAndroid Build Coastguard Worker         }
283*bebae9c0SAndroid Build Coastguard Worker         if (!(allowedDataLocatorMask & actualMask)) {
284*bebae9c0SAndroid Build Coastguard Worker             SL_LOGE("%s: data locator type 0x%x not allowed", name, locatorType);
285*bebae9c0SAndroid Build Coastguard Worker             result = SL_RESULT_CONTENT_UNSUPPORTED;
286*bebae9c0SAndroid Build Coastguard Worker         }
287*bebae9c0SAndroid Build Coastguard Worker     }
288*bebae9c0SAndroid Build Coastguard Worker 
289*bebae9c0SAndroid Build Coastguard Worker     return result;
290*bebae9c0SAndroid Build Coastguard Worker }
291*bebae9c0SAndroid Build Coastguard Worker 
292*bebae9c0SAndroid Build Coastguard Worker 
293*bebae9c0SAndroid Build Coastguard Worker /** \brief Free the local deep copy of a data locator */
294*bebae9c0SAndroid Build Coastguard Worker 
freeDataLocator(DataLocator * pDataLocator)295*bebae9c0SAndroid Build Coastguard Worker static void freeDataLocator(DataLocator *pDataLocator)
296*bebae9c0SAndroid Build Coastguard Worker {
297*bebae9c0SAndroid Build Coastguard Worker     switch (pDataLocator->mLocatorType) {
298*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_NULL:
299*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_ADDRESS:
300*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_BUFFERQUEUE:
301*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_MIDIBUFFERQUEUE:
302*bebae9c0SAndroid Build Coastguard Worker     case XA_DATALOCATOR_NATIVEDISPLAY:
303*bebae9c0SAndroid Build Coastguard Worker         break;
304*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_URI:
305*bebae9c0SAndroid Build Coastguard Worker         if (NULL != pDataLocator->mURI.URI) {
306*bebae9c0SAndroid Build Coastguard Worker             free(pDataLocator->mURI.URI);
307*bebae9c0SAndroid Build Coastguard Worker             pDataLocator->mURI.URI = NULL;
308*bebae9c0SAndroid Build Coastguard Worker         }
309*bebae9c0SAndroid Build Coastguard Worker         pDataLocator->mURI.URI = NULL;
310*bebae9c0SAndroid Build Coastguard Worker         break;
311*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_IODEVICE:
312*bebae9c0SAndroid Build Coastguard Worker         if (NULL != pDataLocator->mIODevice.device) {
313*bebae9c0SAndroid Build Coastguard Worker             ReleaseStrongRef((IObject *) pDataLocator->mIODevice.device);
314*bebae9c0SAndroid Build Coastguard Worker             pDataLocator->mIODevice.device = NULL;
315*bebae9c0SAndroid Build Coastguard Worker         }
316*bebae9c0SAndroid Build Coastguard Worker         break;
317*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_OUTPUTMIX:
318*bebae9c0SAndroid Build Coastguard Worker         if (NULL != pDataLocator->mOutputMix.outputMix) {
319*bebae9c0SAndroid Build Coastguard Worker             ReleaseStrongRef((IObject *) pDataLocator->mOutputMix.outputMix);
320*bebae9c0SAndroid Build Coastguard Worker             pDataLocator->mOutputMix.outputMix = NULL;
321*bebae9c0SAndroid Build Coastguard Worker         }
322*bebae9c0SAndroid Build Coastguard Worker         break;
323*bebae9c0SAndroid Build Coastguard Worker #ifdef ANDROID
324*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_ANDROIDBUFFERQUEUE:
325*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
326*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_ANDROIDFD:
327*bebae9c0SAndroid Build Coastguard Worker         break;
328*bebae9c0SAndroid Build Coastguard Worker #endif
329*bebae9c0SAndroid Build Coastguard Worker     default:
330*bebae9c0SAndroid Build Coastguard Worker         // an invalid data locator is caught earlier when making the copy
331*bebae9c0SAndroid Build Coastguard Worker         assert(false);
332*bebae9c0SAndroid Build Coastguard Worker         break;
333*bebae9c0SAndroid Build Coastguard Worker     }
334*bebae9c0SAndroid Build Coastguard Worker }
335*bebae9c0SAndroid Build Coastguard Worker 
336*bebae9c0SAndroid Build Coastguard Worker 
337*bebae9c0SAndroid Build Coastguard Worker /** \brief Check a data format and make local deep copy */
338*bebae9c0SAndroid Build Coastguard Worker 
checkDataFormat(const char * name,void * pFormat,DataFormat * pDataFormat,SLuint32 allowedDataFormatMask,SLboolean isOutputFormat)339*bebae9c0SAndroid Build Coastguard Worker static SLresult checkDataFormat(const char *name, void *pFormat, DataFormat *pDataFormat,
340*bebae9c0SAndroid Build Coastguard Worker         SLuint32 allowedDataFormatMask, SLboolean isOutputFormat)
341*bebae9c0SAndroid Build Coastguard Worker {
342*bebae9c0SAndroid Build Coastguard Worker     assert(NULL != name && NULL != pDataFormat);
343*bebae9c0SAndroid Build Coastguard Worker     SLresult result = SL_RESULT_SUCCESS;
344*bebae9c0SAndroid Build Coastguard Worker     const SLuint32 *df_representation = NULL; // pointer to representation field, if it exists
345*bebae9c0SAndroid Build Coastguard Worker     SLuint32 formatType;
346*bebae9c0SAndroid Build Coastguard Worker     if (NULL == pFormat) {
347*bebae9c0SAndroid Build Coastguard Worker         pDataFormat->mFormatType = formatType = SL_DATAFORMAT_NULL;
348*bebae9c0SAndroid Build Coastguard Worker     } else {
349*bebae9c0SAndroid Build Coastguard Worker         formatType = *(SLuint32 *)pFormat;
350*bebae9c0SAndroid Build Coastguard Worker         switch (formatType) {
351*bebae9c0SAndroid Build Coastguard Worker         case SL_ANDROID_DATAFORMAT_PCM_EX:
352*bebae9c0SAndroid Build Coastguard Worker             pDataFormat->mPCMEx.representation =
353*bebae9c0SAndroid Build Coastguard Worker                     ((SLAndroidDataFormat_PCM_EX *)pFormat)->representation;
354*bebae9c0SAndroid Build Coastguard Worker             switch (pDataFormat->mPCMEx.representation) {
355*bebae9c0SAndroid Build Coastguard Worker             case SL_ANDROID_PCM_REPRESENTATION_SIGNED_INT:
356*bebae9c0SAndroid Build Coastguard Worker             case SL_ANDROID_PCM_REPRESENTATION_UNSIGNED_INT:
357*bebae9c0SAndroid Build Coastguard Worker             case SL_ANDROID_PCM_REPRESENTATION_FLOAT:
358*bebae9c0SAndroid Build Coastguard Worker                 df_representation = &pDataFormat->mPCMEx.representation;
359*bebae9c0SAndroid Build Coastguard Worker                 break;
360*bebae9c0SAndroid Build Coastguard Worker             default:
361*bebae9c0SAndroid Build Coastguard Worker                 SL_LOGE("%s: unsupported representation: %d", name,
362*bebae9c0SAndroid Build Coastguard Worker                         pDataFormat->mPCMEx.representation);
363*bebae9c0SAndroid Build Coastguard Worker                 result = SL_RESULT_PARAMETER_INVALID;
364*bebae9c0SAndroid Build Coastguard Worker                 break;
365*bebae9c0SAndroid Build Coastguard Worker             }
366*bebae9c0SAndroid Build Coastguard Worker             // SL_ANDROID_DATAFORMAT_PCM_EX - fall through to next test.
367*bebae9c0SAndroid Build Coastguard Worker             FALLTHROUGH_INTENDED;
368*bebae9c0SAndroid Build Coastguard Worker         case SL_DATAFORMAT_PCM:
369*bebae9c0SAndroid Build Coastguard Worker             pDataFormat->mPCM = *(SLDataFormat_PCM *)pFormat;
370*bebae9c0SAndroid Build Coastguard Worker             do {
371*bebae9c0SAndroid Build Coastguard Worker                 if (pDataFormat->mPCM.numChannels == 0) {
372*bebae9c0SAndroid Build Coastguard Worker                     result = SL_RESULT_PARAMETER_INVALID;
373*bebae9c0SAndroid Build Coastguard Worker                 } else if (pDataFormat->mPCM.numChannels > SL_ANDROID_SPEAKER_COUNT_MAX) {
374*bebae9c0SAndroid Build Coastguard Worker                     result = SL_RESULT_CONTENT_UNSUPPORTED;
375*bebae9c0SAndroid Build Coastguard Worker                 }
376*bebae9c0SAndroid Build Coastguard Worker                 if (SL_RESULT_SUCCESS != result) {
377*bebae9c0SAndroid Build Coastguard Worker                     SL_LOGE("%s: numChannels=%u", name, (unsigned) pDataFormat->mPCM.numChannels);
378*bebae9c0SAndroid Build Coastguard Worker                     break;
379*bebae9c0SAndroid Build Coastguard Worker                 }
380*bebae9c0SAndroid Build Coastguard Worker 
381*bebae9c0SAndroid Build Coastguard Worker                 // check the sampling rate
382*bebae9c0SAndroid Build Coastguard Worker                 if (pDataFormat->mPCM.samplesPerSec == 0) {
383*bebae9c0SAndroid Build Coastguard Worker                     result = SL_RESULT_PARAMETER_INVALID;
384*bebae9c0SAndroid Build Coastguard Worker                 } else if (pDataFormat->mPCM.samplesPerSec < SL_SAMPLINGRATE_8 ||
385*bebae9c0SAndroid Build Coastguard Worker                         pDataFormat->mPCM.samplesPerSec > SL_SAMPLINGRATE_192) {
386*bebae9c0SAndroid Build Coastguard Worker                     result = SL_RESULT_CONTENT_UNSUPPORTED;
387*bebae9c0SAndroid Build Coastguard Worker                 }
388*bebae9c0SAndroid Build Coastguard Worker                 if (SL_RESULT_SUCCESS != result) {
389*bebae9c0SAndroid Build Coastguard Worker                     SL_LOGE("%s: samplesPerSec=%u", name, pDataFormat->mPCM.samplesPerSec);
390*bebae9c0SAndroid Build Coastguard Worker                     break;
391*bebae9c0SAndroid Build Coastguard Worker                 }
392*bebae9c0SAndroid Build Coastguard Worker 
393*bebae9c0SAndroid Build Coastguard Worker                 // check the container bit depth and representation
394*bebae9c0SAndroid Build Coastguard Worker                 switch (pDataFormat->mPCM.containerSize) {
395*bebae9c0SAndroid Build Coastguard Worker                 case 8:
396*bebae9c0SAndroid Build Coastguard Worker                     if (df_representation != NULL &&
397*bebae9c0SAndroid Build Coastguard Worker                             *df_representation != SL_ANDROID_PCM_REPRESENTATION_UNSIGNED_INT) {
398*bebae9c0SAndroid Build Coastguard Worker                         result = SL_RESULT_PARAMETER_INVALID;
399*bebae9c0SAndroid Build Coastguard Worker                     }
400*bebae9c0SAndroid Build Coastguard Worker                     break;
401*bebae9c0SAndroid Build Coastguard Worker                 case 16:
402*bebae9c0SAndroid Build Coastguard Worker                 case 24:
403*bebae9c0SAndroid Build Coastguard Worker                     if (df_representation != NULL &&
404*bebae9c0SAndroid Build Coastguard Worker                             *df_representation != SL_ANDROID_PCM_REPRESENTATION_SIGNED_INT) {
405*bebae9c0SAndroid Build Coastguard Worker                         result = SL_RESULT_PARAMETER_INVALID;
406*bebae9c0SAndroid Build Coastguard Worker                     }
407*bebae9c0SAndroid Build Coastguard Worker                     break;
408*bebae9c0SAndroid Build Coastguard Worker                 case 32:
409*bebae9c0SAndroid Build Coastguard Worker                     if (df_representation != NULL
410*bebae9c0SAndroid Build Coastguard Worker                             && *df_representation != SL_ANDROID_PCM_REPRESENTATION_SIGNED_INT
411*bebae9c0SAndroid Build Coastguard Worker                             && *df_representation != SL_ANDROID_PCM_REPRESENTATION_FLOAT) {
412*bebae9c0SAndroid Build Coastguard Worker                         result = SL_RESULT_PARAMETER_INVALID;
413*bebae9c0SAndroid Build Coastguard Worker                     }
414*bebae9c0SAndroid Build Coastguard Worker                     break;
415*bebae9c0SAndroid Build Coastguard Worker                 default:
416*bebae9c0SAndroid Build Coastguard Worker                     result = SL_RESULT_PARAMETER_INVALID;
417*bebae9c0SAndroid Build Coastguard Worker                     break;
418*bebae9c0SAndroid Build Coastguard Worker                 }
419*bebae9c0SAndroid Build Coastguard Worker                 if (SL_RESULT_SUCCESS != result) {
420*bebae9c0SAndroid Build Coastguard Worker                     SL_LOGE("%s: containerSize=%u", name, pDataFormat->mPCM.containerSize);
421*bebae9c0SAndroid Build Coastguard Worker                     break;
422*bebae9c0SAndroid Build Coastguard Worker                 }
423*bebae9c0SAndroid Build Coastguard Worker 
424*bebae9c0SAndroid Build Coastguard Worker                 // sample size cannot be zero, and container size cannot be less than sample size
425*bebae9c0SAndroid Build Coastguard Worker                 if (pDataFormat->mPCM.bitsPerSample == 0 ||
426*bebae9c0SAndroid Build Coastguard Worker                         pDataFormat->mPCM.containerSize < pDataFormat->mPCM.bitsPerSample) {
427*bebae9c0SAndroid Build Coastguard Worker                     result = SL_RESULT_PARAMETER_INVALID;
428*bebae9c0SAndroid Build Coastguard Worker                 }
429*bebae9c0SAndroid Build Coastguard Worker                 if (SL_RESULT_SUCCESS != result) {
430*bebae9c0SAndroid Build Coastguard Worker                     SL_LOGE("%s: containerSize=%u, bitsPerSample=%u", name,
431*bebae9c0SAndroid Build Coastguard Worker                             (unsigned) pDataFormat->mPCM.containerSize,
432*bebae9c0SAndroid Build Coastguard Worker                             (unsigned) pDataFormat->mPCM.bitsPerSample);
433*bebae9c0SAndroid Build Coastguard Worker                     break;
434*bebae9c0SAndroid Build Coastguard Worker                 }
435*bebae9c0SAndroid Build Coastguard Worker 
436*bebae9c0SAndroid Build Coastguard Worker                 // check the channel mask
437*bebae9c0SAndroid Build Coastguard Worker                 SL_LOGV("%s: Requested channel mask of 0x%x for %d channel audio",
438*bebae9c0SAndroid Build Coastguard Worker                     name,
439*bebae9c0SAndroid Build Coastguard Worker                     pDataFormat->mPCM.channelMask,
440*bebae9c0SAndroid Build Coastguard Worker                     pDataFormat->mPCM.numChannels);
441*bebae9c0SAndroid Build Coastguard Worker 
442*bebae9c0SAndroid Build Coastguard Worker                 if (pDataFormat->mPCM.channelMask == 0) {
443*bebae9c0SAndroid Build Coastguard Worker                     // We can derive the channel mask from the channel count,
444*bebae9c0SAndroid Build Coastguard Worker                     // but issue a warning--the automatic mask generation
445*bebae9c0SAndroid Build Coastguard Worker                     // makes a lot of assumptions that may or may not be what
446*bebae9c0SAndroid Build Coastguard Worker                     // the app was expecting.
447*bebae9c0SAndroid Build Coastguard Worker                     SLuint32 mask = isOutputFormat
448*bebae9c0SAndroid Build Coastguard Worker                             ? sles_channel_out_mask_from_count(pDataFormat->mPCM.numChannels)
449*bebae9c0SAndroid Build Coastguard Worker                             : sles_channel_in_mask_from_count(pDataFormat->mPCM.numChannels);
450*bebae9c0SAndroid Build Coastguard Worker                     if (mask == SL_ANDROID_UNKNOWN_CHANNELMASK) {
451*bebae9c0SAndroid Build Coastguard Worker                         SL_LOGE("No channel mask specified and no default mapping for"
452*bebae9c0SAndroid Build Coastguard Worker                                 "requested speaker count of %u", pDataFormat->mPCM.numChannels);
453*bebae9c0SAndroid Build Coastguard Worker                         result = SL_RESULT_PARAMETER_INVALID;
454*bebae9c0SAndroid Build Coastguard Worker                     } else {
455*bebae9c0SAndroid Build Coastguard Worker                         pDataFormat->mPCM.channelMask = mask;
456*bebae9c0SAndroid Build Coastguard Worker                         SL_LOGW("No channel mask specified; Using mask %#x based on requested"
457*bebae9c0SAndroid Build Coastguard Worker                                         "speaker count of %u",
458*bebae9c0SAndroid Build Coastguard Worker                                 pDataFormat->mPCM.channelMask,
459*bebae9c0SAndroid Build Coastguard Worker                                 pDataFormat->mPCM.numChannels);
460*bebae9c0SAndroid Build Coastguard Worker                     }
461*bebae9c0SAndroid Build Coastguard Worker                 }
462*bebae9c0SAndroid Build Coastguard Worker 
463*bebae9c0SAndroid Build Coastguard Worker                 SLuint32 mask = pDataFormat->mPCM.channelMask;
464*bebae9c0SAndroid Build Coastguard Worker                 SLuint32 count = sles_channel_count_from_mask(mask);
465*bebae9c0SAndroid Build Coastguard Worker                 if (count != pDataFormat->mPCM.numChannels) {
466*bebae9c0SAndroid Build Coastguard Worker                     SL_LOGE("%s: requested %d channels but mask (0x%x) has %d channel bits set",
467*bebae9c0SAndroid Build Coastguard Worker                         name,
468*bebae9c0SAndroid Build Coastguard Worker                         pDataFormat->mPCM.numChannels,
469*bebae9c0SAndroid Build Coastguard Worker                         mask,
470*bebae9c0SAndroid Build Coastguard Worker                         count);
471*bebae9c0SAndroid Build Coastguard Worker                     result = SL_RESULT_PARAMETER_INVALID;
472*bebae9c0SAndroid Build Coastguard Worker                     break;
473*bebae9c0SAndroid Build Coastguard Worker                 }
474*bebae9c0SAndroid Build Coastguard Worker 
475*bebae9c0SAndroid Build Coastguard Worker                 SL_LOGV("%s: final channel mask is 0x%x", name, pDataFormat->mPCM.channelMask);
476*bebae9c0SAndroid Build Coastguard Worker 
477*bebae9c0SAndroid Build Coastguard Worker                 // check the endianness / byte order
478*bebae9c0SAndroid Build Coastguard Worker                 switch (pDataFormat->mPCM.endianness) {
479*bebae9c0SAndroid Build Coastguard Worker                 case SL_BYTEORDER_LITTLEENDIAN:
480*bebae9c0SAndroid Build Coastguard Worker                 case SL_BYTEORDER_BIGENDIAN:
481*bebae9c0SAndroid Build Coastguard Worker                     break;
482*bebae9c0SAndroid Build Coastguard Worker                 // native is proposed but not yet in spec
483*bebae9c0SAndroid Build Coastguard Worker                 default:
484*bebae9c0SAndroid Build Coastguard Worker                     result = SL_RESULT_PARAMETER_INVALID;
485*bebae9c0SAndroid Build Coastguard Worker                     break;
486*bebae9c0SAndroid Build Coastguard Worker                 }
487*bebae9c0SAndroid Build Coastguard Worker                 if (SL_RESULT_SUCCESS != result) {
488*bebae9c0SAndroid Build Coastguard Worker                     SL_LOGE("%s: endianness=%u", name, (unsigned) pDataFormat->mPCM.endianness);
489*bebae9c0SAndroid Build Coastguard Worker                     break;
490*bebae9c0SAndroid Build Coastguard Worker                 }
491*bebae9c0SAndroid Build Coastguard Worker 
492*bebae9c0SAndroid Build Coastguard Worker                 // here if all checks passed successfully
493*bebae9c0SAndroid Build Coastguard Worker 
494*bebae9c0SAndroid Build Coastguard Worker             } while(0);
495*bebae9c0SAndroid Build Coastguard Worker             break;
496*bebae9c0SAndroid Build Coastguard Worker 
497*bebae9c0SAndroid Build Coastguard Worker         case SL_DATAFORMAT_MIME:
498*bebae9c0SAndroid Build Coastguard Worker             pDataFormat->mMIME = *(SLDataFormat_MIME *)pFormat;
499*bebae9c0SAndroid Build Coastguard Worker             if (NULL != pDataFormat->mMIME.mimeType) {
500*bebae9c0SAndroid Build Coastguard Worker                 // NTH check address for validity
501*bebae9c0SAndroid Build Coastguard Worker                 size_t len = strlen((const char *) pDataFormat->mMIME.mimeType);
502*bebae9c0SAndroid Build Coastguard Worker                 SLchar *myMIME = (SLchar *) malloc(len + 1);
503*bebae9c0SAndroid Build Coastguard Worker                 if (NULL == myMIME) {
504*bebae9c0SAndroid Build Coastguard Worker                     result = SL_RESULT_MEMORY_FAILURE;
505*bebae9c0SAndroid Build Coastguard Worker                 } else {
506*bebae9c0SAndroid Build Coastguard Worker                     memcpy(myMIME, pDataFormat->mMIME.mimeType, len + 1);
507*bebae9c0SAndroid Build Coastguard Worker                     // make sure MIME string was not modified asynchronously
508*bebae9c0SAndroid Build Coastguard Worker                     if ('\0' != myMIME[len]) {
509*bebae9c0SAndroid Build Coastguard Worker                         free(myMIME);
510*bebae9c0SAndroid Build Coastguard Worker                         myMIME = NULL;
511*bebae9c0SAndroid Build Coastguard Worker                         result = SL_RESULT_PRECONDITIONS_VIOLATED;
512*bebae9c0SAndroid Build Coastguard Worker                     }
513*bebae9c0SAndroid Build Coastguard Worker                 }
514*bebae9c0SAndroid Build Coastguard Worker                 pDataFormat->mMIME.mimeType = myMIME;
515*bebae9c0SAndroid Build Coastguard Worker             }
516*bebae9c0SAndroid Build Coastguard Worker             break;
517*bebae9c0SAndroid Build Coastguard Worker 
518*bebae9c0SAndroid Build Coastguard Worker         case XA_DATAFORMAT_RAWIMAGE:
519*bebae9c0SAndroid Build Coastguard Worker             pDataFormat->mRawImage = *(XADataFormat_RawImage *)pFormat;
520*bebae9c0SAndroid Build Coastguard Worker             switch (pDataFormat->mRawImage.colorFormat) {
521*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_MONOCHROME:
522*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_8BITRGB332:
523*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_12BITRGB444:
524*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_16BITARGB4444:
525*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_16BITARGB1555:
526*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_16BITRGB565:
527*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_16BITBGR565:
528*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_18BITRGB666:
529*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_18BITARGB1665:
530*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_19BITARGB1666:
531*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_24BITRGB888:
532*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_24BITBGR888:
533*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_24BITARGB1887:
534*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_25BITARGB1888:
535*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_32BITBGRA8888:
536*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_32BITARGB8888:
537*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_YUV411PLANAR:
538*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_YUV420PLANAR:
539*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_YUV420SEMIPLANAR:
540*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_YUV422PLANAR:
541*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_YUV422SEMIPLANAR:
542*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_YCBYCR:
543*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_YCRYCB:
544*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_CBYCRY:
545*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_CRYCBY:
546*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_YUV444INTERLEAVED:
547*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_RAWBAYER8BIT:
548*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_RAWBAYER10BIT:
549*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_RAWBAYER8BITCOMPRESSED:
550*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_L2:
551*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_L4:
552*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_L8:
553*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_L16:
554*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_L24:
555*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_L32:
556*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_18BITBGR666:
557*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_24BITARGB6666:
558*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_24BITABGR6666:
559*bebae9c0SAndroid Build Coastguard Worker                 break;
560*bebae9c0SAndroid Build Coastguard Worker             case XA_COLORFORMAT_UNUSED:
561*bebae9c0SAndroid Build Coastguard Worker             default:
562*bebae9c0SAndroid Build Coastguard Worker                 result = XA_RESULT_PARAMETER_INVALID;
563*bebae9c0SAndroid Build Coastguard Worker                 SL_LOGE("%s: unsupported color format %d", name,
564*bebae9c0SAndroid Build Coastguard Worker                     pDataFormat->mRawImage.colorFormat);
565*bebae9c0SAndroid Build Coastguard Worker                 break;
566*bebae9c0SAndroid Build Coastguard Worker             }
567*bebae9c0SAndroid Build Coastguard Worker             // no checks for height, width, or stride
568*bebae9c0SAndroid Build Coastguard Worker             break;
569*bebae9c0SAndroid Build Coastguard Worker 
570*bebae9c0SAndroid Build Coastguard Worker         default:
571*bebae9c0SAndroid Build Coastguard Worker             result = SL_RESULT_PARAMETER_INVALID;
572*bebae9c0SAndroid Build Coastguard Worker             SL_LOGE("%s: formatType=%u", name, (unsigned) formatType);
573*bebae9c0SAndroid Build Coastguard Worker             break;
574*bebae9c0SAndroid Build Coastguard Worker 
575*bebae9c0SAndroid Build Coastguard Worker         }
576*bebae9c0SAndroid Build Coastguard Worker 
577*bebae9c0SAndroid Build Coastguard Worker         // make sure format type was not modified asynchronously
578*bebae9c0SAndroid Build Coastguard Worker         if ((SL_RESULT_SUCCESS == result) && (formatType != pDataFormat->mFormatType)) {
579*bebae9c0SAndroid Build Coastguard Worker             SL_LOGE("%s: formatType changed from %u to %u", name, formatType,
580*bebae9c0SAndroid Build Coastguard Worker                     pDataFormat->mFormatType);
581*bebae9c0SAndroid Build Coastguard Worker             result = SL_RESULT_PRECONDITIONS_VIOLATED;
582*bebae9c0SAndroid Build Coastguard Worker         }
583*bebae9c0SAndroid Build Coastguard Worker 
584*bebae9c0SAndroid Build Coastguard Worker     }
585*bebae9c0SAndroid Build Coastguard Worker 
586*bebae9c0SAndroid Build Coastguard Worker     // Verify that the data format type is allowed in this context
587*bebae9c0SAndroid Build Coastguard Worker     if (SL_RESULT_SUCCESS == result) {
588*bebae9c0SAndroid Build Coastguard Worker         SLuint32 actualMask;
589*bebae9c0SAndroid Build Coastguard Worker         switch (formatType) {
590*bebae9c0SAndroid Build Coastguard Worker         case SL_DATAFORMAT_NULL:
591*bebae9c0SAndroid Build Coastguard Worker         case SL_DATAFORMAT_MIME:
592*bebae9c0SAndroid Build Coastguard Worker         case SL_DATAFORMAT_PCM:
593*bebae9c0SAndroid Build Coastguard Worker         case SL_ANDROID_DATAFORMAT_PCM_EX:
594*bebae9c0SAndroid Build Coastguard Worker         case XA_DATAFORMAT_RAWIMAGE:
595*bebae9c0SAndroid Build Coastguard Worker             actualMask = 1L << formatType;
596*bebae9c0SAndroid Build Coastguard Worker             break;
597*bebae9c0SAndroid Build Coastguard Worker         default:
598*bebae9c0SAndroid Build Coastguard Worker             assert(false);
599*bebae9c0SAndroid Build Coastguard Worker             actualMask = 0L;
600*bebae9c0SAndroid Build Coastguard Worker             break;
601*bebae9c0SAndroid Build Coastguard Worker         }
602*bebae9c0SAndroid Build Coastguard Worker         if (!(allowedDataFormatMask & actualMask)) {
603*bebae9c0SAndroid Build Coastguard Worker             SL_LOGE("%s: data format %d not allowed", name, formatType);
604*bebae9c0SAndroid Build Coastguard Worker             result = SL_RESULT_CONTENT_UNSUPPORTED;
605*bebae9c0SAndroid Build Coastguard Worker         }
606*bebae9c0SAndroid Build Coastguard Worker     }
607*bebae9c0SAndroid Build Coastguard Worker 
608*bebae9c0SAndroid Build Coastguard Worker     return result;
609*bebae9c0SAndroid Build Coastguard Worker }
610*bebae9c0SAndroid Build Coastguard Worker 
611*bebae9c0SAndroid Build Coastguard Worker 
612*bebae9c0SAndroid Build Coastguard Worker /** \brief Check interface ID compatibility with respect to a particular source
613*bebae9c0SAndroid Build Coastguard Worker  *         and sink data locator format
614*bebae9c0SAndroid Build Coastguard Worker  */
615*bebae9c0SAndroid Build Coastguard Worker 
checkSourceSinkVsInterfacesCompatibility(const DataLocatorFormat * pSrcDataLocatorFormat,const DataLocatorFormat * pSinkDataLocatorFormat,const ClassTable * clazz,unsigned requiredMask)616*bebae9c0SAndroid Build Coastguard Worker SLresult checkSourceSinkVsInterfacesCompatibility(const DataLocatorFormat *pSrcDataLocatorFormat,
617*bebae9c0SAndroid Build Coastguard Worker         const DataLocatorFormat *pSinkDataLocatorFormat,
618*bebae9c0SAndroid Build Coastguard Worker         const ClassTable *clazz, unsigned requiredMask) {
619*bebae9c0SAndroid Build Coastguard Worker     int index;
620*bebae9c0SAndroid Build Coastguard Worker     switch (pSrcDataLocatorFormat->mLocator.mLocatorType) {
621*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_URI:
622*bebae9c0SAndroid Build Coastguard Worker #ifdef ANDROID
623*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_ANDROIDFD:
624*bebae9c0SAndroid Build Coastguard Worker #endif
625*bebae9c0SAndroid Build Coastguard Worker         // URIs and FD can be sources when "playing" to an OutputMix or a Buffer Queue for decode
626*bebae9c0SAndroid Build Coastguard Worker         // so we don't prevent the retrieval of the BufferQueue interfaces for those sources
627*bebae9c0SAndroid Build Coastguard Worker         switch (pSinkDataLocatorFormat->mLocator.mLocatorType) {
628*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_BUFFERQUEUE:
629*bebae9c0SAndroid Build Coastguard Worker #ifdef ANDROID
630*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
631*bebae9c0SAndroid Build Coastguard Worker #endif
632*bebae9c0SAndroid Build Coastguard Worker             break;
633*bebae9c0SAndroid Build Coastguard Worker         default:
634*bebae9c0SAndroid Build Coastguard Worker             // can't require SLBufferQueueItf or its alias SLAndroidSimpleBufferQueueItf
635*bebae9c0SAndroid Build Coastguard Worker             // if the data sink is not a buffer queue
636*bebae9c0SAndroid Build Coastguard Worker             index = clazz->mMPH_to_index[MPH_BUFFERQUEUE];
637*bebae9c0SAndroid Build Coastguard Worker #ifdef ANDROID
638*bebae9c0SAndroid Build Coastguard Worker             assert(index == clazz->mMPH_to_index[MPH_ANDROIDSIMPLEBUFFERQUEUE]);
639*bebae9c0SAndroid Build Coastguard Worker #endif
640*bebae9c0SAndroid Build Coastguard Worker             if (0 <= index) {
641*bebae9c0SAndroid Build Coastguard Worker                 if (requiredMask & (1 << index)) {
642*bebae9c0SAndroid Build Coastguard Worker                     SL_LOGE("can't require SL_IID_BUFFERQUEUE "
643*bebae9c0SAndroid Build Coastguard Worker #ifdef ANDROID
644*bebae9c0SAndroid Build Coastguard Worker                             "or SL_IID_ANDROIDSIMPLEBUFFERQUEUE "
645*bebae9c0SAndroid Build Coastguard Worker #endif
646*bebae9c0SAndroid Build Coastguard Worker                             "with a non-buffer queue data sink");
647*bebae9c0SAndroid Build Coastguard Worker                     return SL_RESULT_FEATURE_UNSUPPORTED;
648*bebae9c0SAndroid Build Coastguard Worker                 }
649*bebae9c0SAndroid Build Coastguard Worker             }
650*bebae9c0SAndroid Build Coastguard Worker             break;
651*bebae9c0SAndroid Build Coastguard Worker         }
652*bebae9c0SAndroid Build Coastguard Worker         break;
653*bebae9c0SAndroid Build Coastguard Worker 
654*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_BUFFERQUEUE:
655*bebae9c0SAndroid Build Coastguard Worker #ifdef ANDROID
656*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
657*bebae9c0SAndroid Build Coastguard Worker #endif
658*bebae9c0SAndroid Build Coastguard Worker         // can't require SLSeekItf if data source is a buffer queue
659*bebae9c0SAndroid Build Coastguard Worker         index = clazz->mMPH_to_index[MPH_SEEK];
660*bebae9c0SAndroid Build Coastguard Worker         if (0 <= index) {
661*bebae9c0SAndroid Build Coastguard Worker             if (requiredMask & (1 << index)) {
662*bebae9c0SAndroid Build Coastguard Worker                 SL_LOGE("can't require SL_IID_SEEK with a buffer queue data source");
663*bebae9c0SAndroid Build Coastguard Worker                 return SL_RESULT_FEATURE_UNSUPPORTED;
664*bebae9c0SAndroid Build Coastguard Worker             }
665*bebae9c0SAndroid Build Coastguard Worker         }
666*bebae9c0SAndroid Build Coastguard Worker         // can't require SLMuteSoloItf if data source is a mono buffer queue
667*bebae9c0SAndroid Build Coastguard Worker         index = clazz->mMPH_to_index[MPH_MUTESOLO];
668*bebae9c0SAndroid Build Coastguard Worker         if (0 <= index) {
669*bebae9c0SAndroid Build Coastguard Worker             if ((requiredMask & (1 << index)) &&
670*bebae9c0SAndroid Build Coastguard Worker                     (SL_DATAFORMAT_PCM == pSrcDataLocatorFormat->mFormat.mFormatType) &&
671*bebae9c0SAndroid Build Coastguard Worker                     (1 == pSrcDataLocatorFormat->mFormat.mPCM.numChannels)) {
672*bebae9c0SAndroid Build Coastguard Worker                 SL_LOGE("can't require SL_IID_MUTESOLO with a mono buffer queue data source");
673*bebae9c0SAndroid Build Coastguard Worker                 return SL_RESULT_FEATURE_UNSUPPORTED;
674*bebae9c0SAndroid Build Coastguard Worker             }
675*bebae9c0SAndroid Build Coastguard Worker         }
676*bebae9c0SAndroid Build Coastguard Worker         break;
677*bebae9c0SAndroid Build Coastguard Worker 
678*bebae9c0SAndroid Build Coastguard Worker #ifdef ANDROID
679*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_ANDROIDBUFFERQUEUE:
680*bebae9c0SAndroid Build Coastguard Worker         // can't require SLSeekItf if data source is an Android buffer queue
681*bebae9c0SAndroid Build Coastguard Worker         index = clazz->mMPH_to_index[MPH_SEEK];
682*bebae9c0SAndroid Build Coastguard Worker         if (0 <= index) {
683*bebae9c0SAndroid Build Coastguard Worker             if (requiredMask & (1 << index)) {
684*bebae9c0SAndroid Build Coastguard Worker                 SL_LOGE("can't require SL_IID_SEEK with a SL_DATALOCATOR_ANDROIDBUFFERQUEUE "\
685*bebae9c0SAndroid Build Coastguard Worker                         "source");
686*bebae9c0SAndroid Build Coastguard Worker                 return SL_RESULT_FEATURE_UNSUPPORTED;
687*bebae9c0SAndroid Build Coastguard Worker             }
688*bebae9c0SAndroid Build Coastguard Worker         }
689*bebae9c0SAndroid Build Coastguard Worker         switch (pSinkDataLocatorFormat->mLocator.mLocatorType) {
690*bebae9c0SAndroid Build Coastguard Worker         // for use-case AAC decode from SLAndroidBufferQueueItf with AAC ADTS data
691*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_BUFFERQUEUE:
692*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
693*bebae9c0SAndroid Build Coastguard Worker             break;
694*bebae9c0SAndroid Build Coastguard Worker         // for use-case audio playback from SLAndroidBufferQueueItf with MP2TS data
695*bebae9c0SAndroid Build Coastguard Worker         case SL_DATALOCATOR_OUTPUTMIX:
696*bebae9c0SAndroid Build Coastguard Worker             break;
697*bebae9c0SAndroid Build Coastguard Worker         default:
698*bebae9c0SAndroid Build Coastguard Worker             SL_LOGE("Invalid sink for SL_DATALOCATOR_ANDROIDBUFFERQUEUE source");
699*bebae9c0SAndroid Build Coastguard Worker             return SL_RESULT_FEATURE_UNSUPPORTED;
700*bebae9c0SAndroid Build Coastguard Worker             break;
701*bebae9c0SAndroid Build Coastguard Worker         }
702*bebae9c0SAndroid Build Coastguard Worker         break;
703*bebae9c0SAndroid Build Coastguard Worker #endif
704*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_ADDRESS:
705*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_MIDIBUFFERQUEUE:
706*bebae9c0SAndroid Build Coastguard Worker     case XA_DATALOCATOR_NATIVEDISPLAY:
707*bebae9c0SAndroid Build Coastguard Worker         // any special checks here???
708*bebae9c0SAndroid Build Coastguard Worker     default:
709*bebae9c0SAndroid Build Coastguard Worker         // can't require SLBufferQueueItf or its alias SLAndroidSimpleBufferQueueItf
710*bebae9c0SAndroid Build Coastguard Worker         // if the data source is not a buffer queue
711*bebae9c0SAndroid Build Coastguard Worker         index = clazz->mMPH_to_index[MPH_BUFFERQUEUE];
712*bebae9c0SAndroid Build Coastguard Worker #ifdef ANDROID
713*bebae9c0SAndroid Build Coastguard Worker         assert(index == clazz->mMPH_to_index[MPH_ANDROIDSIMPLEBUFFERQUEUE]);
714*bebae9c0SAndroid Build Coastguard Worker #endif
715*bebae9c0SAndroid Build Coastguard Worker         if (0 <= index) {
716*bebae9c0SAndroid Build Coastguard Worker             if (requiredMask & (1 << index)) {
717*bebae9c0SAndroid Build Coastguard Worker                 SL_LOGE("can't require SL_IID_BUFFERQUEUE "
718*bebae9c0SAndroid Build Coastguard Worker #ifdef ANDROID
719*bebae9c0SAndroid Build Coastguard Worker                         "or SL_IID_ANDROIDSIMPLEBUFFERQUEUE "
720*bebae9c0SAndroid Build Coastguard Worker #endif
721*bebae9c0SAndroid Build Coastguard Worker                         "with a non-buffer queue data source");
722*bebae9c0SAndroid Build Coastguard Worker                 return SL_RESULT_FEATURE_UNSUPPORTED;
723*bebae9c0SAndroid Build Coastguard Worker             }
724*bebae9c0SAndroid Build Coastguard Worker         }
725*bebae9c0SAndroid Build Coastguard Worker         break;
726*bebae9c0SAndroid Build Coastguard Worker     }
727*bebae9c0SAndroid Build Coastguard Worker     return SL_RESULT_SUCCESS;
728*bebae9c0SAndroid Build Coastguard Worker }
729*bebae9c0SAndroid Build Coastguard Worker 
730*bebae9c0SAndroid Build Coastguard Worker 
731*bebae9c0SAndroid Build Coastguard Worker /** \brief Free the local deep copy of a data format */
732*bebae9c0SAndroid Build Coastguard Worker 
freeDataFormat(DataFormat * pDataFormat)733*bebae9c0SAndroid Build Coastguard Worker static void freeDataFormat(DataFormat *pDataFormat)
734*bebae9c0SAndroid Build Coastguard Worker {
735*bebae9c0SAndroid Build Coastguard Worker     switch (pDataFormat->mFormatType) {
736*bebae9c0SAndroid Build Coastguard Worker     case SL_DATAFORMAT_MIME:
737*bebae9c0SAndroid Build Coastguard Worker         if (NULL != pDataFormat->mMIME.mimeType) {
738*bebae9c0SAndroid Build Coastguard Worker             free(pDataFormat->mMIME.mimeType);
739*bebae9c0SAndroid Build Coastguard Worker             pDataFormat->mMIME.mimeType = NULL;
740*bebae9c0SAndroid Build Coastguard Worker         }
741*bebae9c0SAndroid Build Coastguard Worker         break;
742*bebae9c0SAndroid Build Coastguard Worker     case SL_ANDROID_DATAFORMAT_PCM_EX:
743*bebae9c0SAndroid Build Coastguard Worker     case SL_DATAFORMAT_PCM:
744*bebae9c0SAndroid Build Coastguard Worker     case XA_DATAFORMAT_RAWIMAGE:
745*bebae9c0SAndroid Build Coastguard Worker     case SL_DATAFORMAT_NULL:
746*bebae9c0SAndroid Build Coastguard Worker         break;
747*bebae9c0SAndroid Build Coastguard Worker     default:
748*bebae9c0SAndroid Build Coastguard Worker         // an invalid data format is caught earlier during the copy
749*bebae9c0SAndroid Build Coastguard Worker         assert(false);
750*bebae9c0SAndroid Build Coastguard Worker         break;
751*bebae9c0SAndroid Build Coastguard Worker     }
752*bebae9c0SAndroid Build Coastguard Worker }
753*bebae9c0SAndroid Build Coastguard Worker 
754*bebae9c0SAndroid Build Coastguard Worker 
755*bebae9c0SAndroid Build Coastguard Worker /** \brief Check a data source and make local deep copy */
756*bebae9c0SAndroid Build Coastguard Worker 
checkDataSource(const char * name,const SLDataSource * pDataSrc,DataLocatorFormat * pDataLocatorFormat,SLuint32 allowedDataLocatorMask,SLuint32 allowedDataFormatMask)757*bebae9c0SAndroid Build Coastguard Worker SLresult checkDataSource(const char *name, const SLDataSource *pDataSrc,
758*bebae9c0SAndroid Build Coastguard Worker         DataLocatorFormat *pDataLocatorFormat, SLuint32 allowedDataLocatorMask,
759*bebae9c0SAndroid Build Coastguard Worker         SLuint32 allowedDataFormatMask)
760*bebae9c0SAndroid Build Coastguard Worker {
761*bebae9c0SAndroid Build Coastguard Worker     assert(NULL != name && NULL != pDataLocatorFormat);
762*bebae9c0SAndroid Build Coastguard Worker     pDataLocatorFormat->u.mSource.pLocator = &pDataLocatorFormat->mLocator;
763*bebae9c0SAndroid Build Coastguard Worker     pDataLocatorFormat->u.mSource.pFormat = &pDataLocatorFormat->mFormat;
764*bebae9c0SAndroid Build Coastguard Worker 
765*bebae9c0SAndroid Build Coastguard Worker     if (NULL == pDataSrc) {
766*bebae9c0SAndroid Build Coastguard Worker         pDataLocatorFormat->mLocator.mLocatorType = SL_DATALOCATOR_NULL;
767*bebae9c0SAndroid Build Coastguard Worker         pDataLocatorFormat->mFormat.mFormatType = SL_DATAFORMAT_NULL;
768*bebae9c0SAndroid Build Coastguard Worker         if ((allowedDataLocatorMask & DATALOCATOR_MASK_NULL) &&
769*bebae9c0SAndroid Build Coastguard Worker                 (allowedDataFormatMask & DATAFORMAT_MASK_NULL)) {
770*bebae9c0SAndroid Build Coastguard Worker             return SL_RESULT_SUCCESS;
771*bebae9c0SAndroid Build Coastguard Worker         }
772*bebae9c0SAndroid Build Coastguard Worker         SL_LOGE("%s: data source cannot be NULL", name);
773*bebae9c0SAndroid Build Coastguard Worker         return SL_RESULT_PARAMETER_INVALID;
774*bebae9c0SAndroid Build Coastguard Worker     }
775*bebae9c0SAndroid Build Coastguard Worker     SLDataSource myDataSrc = *pDataSrc;
776*bebae9c0SAndroid Build Coastguard Worker     SLresult result;
777*bebae9c0SAndroid Build Coastguard Worker     result = checkDataLocator(name, myDataSrc.pLocator, &pDataLocatorFormat->mLocator,
778*bebae9c0SAndroid Build Coastguard Worker             allowedDataLocatorMask);
779*bebae9c0SAndroid Build Coastguard Worker     if (SL_RESULT_SUCCESS != result) {
780*bebae9c0SAndroid Build Coastguard Worker         return result;
781*bebae9c0SAndroid Build Coastguard Worker     }
782*bebae9c0SAndroid Build Coastguard Worker 
783*bebae9c0SAndroid Build Coastguard Worker     switch (pDataLocatorFormat->mLocator.mLocatorType) {
784*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_URI:
785*bebae9c0SAndroid Build Coastguard Worker         allowedDataFormatMask &= DATAFORMAT_MASK_MIME;
786*bebae9c0SAndroid Build Coastguard Worker         break;
787*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_ADDRESS:
788*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_BUFFERQUEUE:
789*bebae9c0SAndroid Build Coastguard Worker         allowedDataFormatMask &= DATAFORMAT_MASK_PCM | DATAFORMAT_MASK_PCM_EX;
790*bebae9c0SAndroid Build Coastguard Worker         break;
791*bebae9c0SAndroid Build Coastguard Worker     // Per the spec, the pFormat field is ignored in some cases
792*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_IODEVICE:
793*bebae9c0SAndroid Build Coastguard Worker         myDataSrc.pFormat = NULL;
794*bebae9c0SAndroid Build Coastguard Worker         FALLTHROUGH_INTENDED;
795*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_NULL:
796*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_MIDIBUFFERQUEUE:
797*bebae9c0SAndroid Build Coastguard Worker         allowedDataFormatMask &= DATAFORMAT_MASK_NULL;
798*bebae9c0SAndroid Build Coastguard Worker         break;
799*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_OUTPUTMIX:
800*bebae9c0SAndroid Build Coastguard Worker     case XA_DATALOCATOR_NATIVEDISPLAY:
801*bebae9c0SAndroid Build Coastguard Worker         allowedDataFormatMask = DATAFORMAT_MASK_NONE;
802*bebae9c0SAndroid Build Coastguard Worker         break;
803*bebae9c0SAndroid Build Coastguard Worker #ifdef ANDROID
804*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_ANDROIDFD:
805*bebae9c0SAndroid Build Coastguard Worker         allowedDataFormatMask &= DATAFORMAT_MASK_MIME;
806*bebae9c0SAndroid Build Coastguard Worker         break;
807*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
808*bebae9c0SAndroid Build Coastguard Worker         allowedDataFormatMask &= DATAFORMAT_MASK_PCM | DATAFORMAT_MASK_PCM_EX;
809*bebae9c0SAndroid Build Coastguard Worker         break;
810*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_ANDROIDBUFFERQUEUE:
811*bebae9c0SAndroid Build Coastguard Worker         allowedDataFormatMask &= DATAFORMAT_MASK_MIME;;
812*bebae9c0SAndroid Build Coastguard Worker         break;
813*bebae9c0SAndroid Build Coastguard Worker #endif
814*bebae9c0SAndroid Build Coastguard Worker     default:
815*bebae9c0SAndroid Build Coastguard Worker         // invalid data locator type is caught earlier
816*bebae9c0SAndroid Build Coastguard Worker         assert(false);
817*bebae9c0SAndroid Build Coastguard Worker         allowedDataFormatMask = DATAFORMAT_MASK_NONE;
818*bebae9c0SAndroid Build Coastguard Worker         break;
819*bebae9c0SAndroid Build Coastguard Worker     }
820*bebae9c0SAndroid Build Coastguard Worker 
821*bebae9c0SAndroid Build Coastguard Worker     result = checkDataFormat(name,
822*bebae9c0SAndroid Build Coastguard Worker                              myDataSrc.pFormat,
823*bebae9c0SAndroid Build Coastguard Worker                              &pDataLocatorFormat->mFormat,
824*bebae9c0SAndroid Build Coastguard Worker                              allowedDataFormatMask,
825*bebae9c0SAndroid Build Coastguard Worker                              SL_BOOLEAN_TRUE /*isOutputFormat*/);
826*bebae9c0SAndroid Build Coastguard Worker     if (SL_RESULT_SUCCESS != result) {
827*bebae9c0SAndroid Build Coastguard Worker         freeDataLocator(&pDataLocatorFormat->mLocator);
828*bebae9c0SAndroid Build Coastguard Worker         return result;
829*bebae9c0SAndroid Build Coastguard Worker     }
830*bebae9c0SAndroid Build Coastguard Worker 
831*bebae9c0SAndroid Build Coastguard Worker     return SL_RESULT_SUCCESS;
832*bebae9c0SAndroid Build Coastguard Worker }
833*bebae9c0SAndroid Build Coastguard Worker 
834*bebae9c0SAndroid Build Coastguard Worker 
835*bebae9c0SAndroid Build Coastguard Worker /** \brief Check a data sink and make local deep copy */
836*bebae9c0SAndroid Build Coastguard Worker 
checkDataSink(const char * name,const SLDataSink * pDataSink,DataLocatorFormat * pDataLocatorFormat,SLuint32 allowedDataLocatorMask,SLuint32 allowedDataFormatMask)837*bebae9c0SAndroid Build Coastguard Worker SLresult checkDataSink(const char *name, const SLDataSink *pDataSink,
838*bebae9c0SAndroid Build Coastguard Worker         DataLocatorFormat *pDataLocatorFormat, SLuint32 allowedDataLocatorMask,
839*bebae9c0SAndroid Build Coastguard Worker         SLuint32 allowedDataFormatMask)
840*bebae9c0SAndroid Build Coastguard Worker {
841*bebae9c0SAndroid Build Coastguard Worker     assert(NULL != name && NULL != pDataLocatorFormat);
842*bebae9c0SAndroid Build Coastguard Worker     pDataLocatorFormat->u.mSink.pLocator = &pDataLocatorFormat->mLocator;
843*bebae9c0SAndroid Build Coastguard Worker     pDataLocatorFormat->u.mSink.pFormat = &pDataLocatorFormat->mFormat;
844*bebae9c0SAndroid Build Coastguard Worker 
845*bebae9c0SAndroid Build Coastguard Worker     if (NULL == pDataSink) {
846*bebae9c0SAndroid Build Coastguard Worker         pDataLocatorFormat->mLocator.mLocatorType = SL_DATALOCATOR_NULL;
847*bebae9c0SAndroid Build Coastguard Worker         pDataLocatorFormat->mFormat.mFormatType = SL_DATAFORMAT_NULL;
848*bebae9c0SAndroid Build Coastguard Worker         if ((allowedDataLocatorMask & DATALOCATOR_MASK_NULL) &&
849*bebae9c0SAndroid Build Coastguard Worker                 (allowedDataFormatMask & DATAFORMAT_MASK_NULL)) {
850*bebae9c0SAndroid Build Coastguard Worker             return SL_RESULT_SUCCESS;
851*bebae9c0SAndroid Build Coastguard Worker         }
852*bebae9c0SAndroid Build Coastguard Worker         SL_LOGE("%s: data sink cannot be NULL", name);
853*bebae9c0SAndroid Build Coastguard Worker         return SL_RESULT_PARAMETER_INVALID;
854*bebae9c0SAndroid Build Coastguard Worker     }
855*bebae9c0SAndroid Build Coastguard Worker     SLDataSink myDataSink = *pDataSink;
856*bebae9c0SAndroid Build Coastguard Worker     SLresult result;
857*bebae9c0SAndroid Build Coastguard Worker     result = checkDataLocator(name, myDataSink.pLocator, &pDataLocatorFormat->mLocator,
858*bebae9c0SAndroid Build Coastguard Worker             allowedDataLocatorMask);
859*bebae9c0SAndroid Build Coastguard Worker     if (SL_RESULT_SUCCESS != result) {
860*bebae9c0SAndroid Build Coastguard Worker         return result;
861*bebae9c0SAndroid Build Coastguard Worker     }
862*bebae9c0SAndroid Build Coastguard Worker 
863*bebae9c0SAndroid Build Coastguard Worker     switch (pDataLocatorFormat->mLocator.mLocatorType) {
864*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_URI:
865*bebae9c0SAndroid Build Coastguard Worker         allowedDataFormatMask &= DATAFORMAT_MASK_MIME;
866*bebae9c0SAndroid Build Coastguard Worker         break;
867*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_ADDRESS:
868*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_BUFFERQUEUE:
869*bebae9c0SAndroid Build Coastguard Worker         allowedDataFormatMask &= DATAFORMAT_MASK_PCM | DATAFORMAT_MASK_PCM_EX;
870*bebae9c0SAndroid Build Coastguard Worker         break;
871*bebae9c0SAndroid Build Coastguard Worker     // Per the spec, the pFormat field is ignored in some cases
872*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_IODEVICE:
873*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_OUTPUTMIX:
874*bebae9c0SAndroid Build Coastguard Worker     case XA_DATALOCATOR_NATIVEDISPLAY:
875*bebae9c0SAndroid Build Coastguard Worker         myDataSink.pFormat = NULL;
876*bebae9c0SAndroid Build Coastguard Worker         FALLTHROUGH_INTENDED;
877*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_NULL:
878*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_MIDIBUFFERQUEUE:
879*bebae9c0SAndroid Build Coastguard Worker         allowedDataFormatMask &= DATAFORMAT_MASK_NULL;
880*bebae9c0SAndroid Build Coastguard Worker         break;
881*bebae9c0SAndroid Build Coastguard Worker #ifdef ANDROID
882*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_ANDROIDFD:
883*bebae9c0SAndroid Build Coastguard Worker         allowedDataFormatMask = DATAFORMAT_MASK_NONE;
884*bebae9c0SAndroid Build Coastguard Worker         break;
885*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
886*bebae9c0SAndroid Build Coastguard Worker         allowedDataFormatMask &= DATAFORMAT_MASK_PCM | DATAFORMAT_MASK_PCM_EX;
887*bebae9c0SAndroid Build Coastguard Worker         break;
888*bebae9c0SAndroid Build Coastguard Worker     case SL_DATALOCATOR_ANDROIDBUFFERQUEUE:
889*bebae9c0SAndroid Build Coastguard Worker         allowedDataFormatMask = DATAFORMAT_MASK_NONE;
890*bebae9c0SAndroid Build Coastguard Worker         break;
891*bebae9c0SAndroid Build Coastguard Worker #endif
892*bebae9c0SAndroid Build Coastguard Worker     default:
893*bebae9c0SAndroid Build Coastguard Worker         // invalid data locator type is caught earlier
894*bebae9c0SAndroid Build Coastguard Worker         assert(false);
895*bebae9c0SAndroid Build Coastguard Worker         allowedDataFormatMask = DATAFORMAT_MASK_NONE;
896*bebae9c0SAndroid Build Coastguard Worker         break;
897*bebae9c0SAndroid Build Coastguard Worker     }
898*bebae9c0SAndroid Build Coastguard Worker 
899*bebae9c0SAndroid Build Coastguard Worker     result = checkDataFormat(name,
900*bebae9c0SAndroid Build Coastguard Worker             myDataSink.pFormat,
901*bebae9c0SAndroid Build Coastguard Worker             &pDataLocatorFormat->mFormat,
902*bebae9c0SAndroid Build Coastguard Worker             allowedDataFormatMask,
903*bebae9c0SAndroid Build Coastguard Worker             SL_BOOLEAN_FALSE /*isOutputFormat*/);
904*bebae9c0SAndroid Build Coastguard Worker 
905*bebae9c0SAndroid Build Coastguard Worker     if (SL_RESULT_SUCCESS != result) {
906*bebae9c0SAndroid Build Coastguard Worker         freeDataLocator(&pDataLocatorFormat->mLocator);
907*bebae9c0SAndroid Build Coastguard Worker         return result;
908*bebae9c0SAndroid Build Coastguard Worker     }
909*bebae9c0SAndroid Build Coastguard Worker 
910*bebae9c0SAndroid Build Coastguard Worker     return SL_RESULT_SUCCESS;
911*bebae9c0SAndroid Build Coastguard Worker }
912*bebae9c0SAndroid Build Coastguard Worker 
913*bebae9c0SAndroid Build Coastguard Worker 
914*bebae9c0SAndroid Build Coastguard Worker /** \brief Free the local deep copy of a data locator format */
915*bebae9c0SAndroid Build Coastguard Worker 
freeDataLocatorFormat(DataLocatorFormat * dlf)916*bebae9c0SAndroid Build Coastguard Worker void freeDataLocatorFormat(DataLocatorFormat *dlf)
917*bebae9c0SAndroid Build Coastguard Worker {
918*bebae9c0SAndroid Build Coastguard Worker     assert(NULL != dlf);
919*bebae9c0SAndroid Build Coastguard Worker     freeDataLocator(&dlf->mLocator);
920*bebae9c0SAndroid Build Coastguard Worker     freeDataFormat(&dlf->mFormat);
921*bebae9c0SAndroid Build Coastguard Worker }
922