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