18db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten/*
28db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten * Copyright (C) 2010 The Android Open Source Project
38db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten *
48db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
58db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten * you may not use this file except in compliance with the License.
68db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten * You may obtain a copy of the License at
78db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten *
88db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
98db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten *
108db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten * Unless required by applicable law or agreed to in writing, software
118db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
128db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten * See the License for the specific language governing permissions and
148db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten * limitations under the License.
158db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten */
168db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
178db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten/** Data locator, data format, data source, and data sink support */
188db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
198db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten#include "sles_allinclusive.h"
20ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten#ifdef ANDROID  // FIXME This file should be portable
21ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten#include "android/channels.h"
224e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean#include "data.h"
23ff25010cb77455a46357d6dd012631a2599d7bf4Glenn Kasten#endif
248db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
258db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten/** \brief Check a data locator and make local deep copy */
268db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
2794a37e8117fb72790882dfb815f99e2365754c74Glenn Kastenstatic SLresult checkDataLocator(const char *name, void *pLocator, DataLocator *pDataLocator,
2894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        SLuint32 allowedDataLocatorMask)
298db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten{
3094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    assert(NULL != name && NULL != pDataLocator);
3194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    SLresult result = SL_RESULT_SUCCESS;
328db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
3394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    SLuint32 locatorType;
3494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    if (NULL == pLocator) {
3594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        pDataLocator->mLocatorType = locatorType = SL_DATALOCATOR_NULL;
3694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    } else {
3794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        locatorType = *(SLuint32 *)pLocator;
3894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        switch (locatorType) {
3994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten
4094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATALOCATOR_ADDRESS:
4194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            pDataLocator->mAddress = *(SLDataLocator_Address *)pLocator;
4294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            // if length is greater than zero, then the address must be non-NULL
4394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            if ((0 < pDataLocator->mAddress.length) && (NULL == pDataLocator->mAddress.pAddress)) {
4494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                SL_LOGE("%s: pAddress=NULL", name);
4594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                result = SL_RESULT_PARAMETER_INVALID;
4694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            }
4794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            break;
488db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
4994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATALOCATOR_BUFFERQUEUE:
508db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten#ifdef ANDROID
5194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        // This is an alias that is _not_ converted; the rest of the code must check for both
5294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        // locator types. That's because it is only an alias for audio players, not audio recorder
5394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        // objects so we have to remember the distinction.
5494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
558db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten#endif
5694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            pDataLocator->mBufferQueue = *(SLDataLocator_BufferQueue *)pLocator;
5794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            // number of buffers must be specified, there is no default value, and can't be too big
5894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            if (!((1 <= pDataLocator->mBufferQueue.numBuffers) &&
5994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                (pDataLocator->mBufferQueue.numBuffers <= 255))) {
60a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten                SL_LOGE("%s: numBuffers=%u", name, pDataLocator->mBufferQueue.numBuffers);
6194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                result = SL_RESULT_PARAMETER_INVALID;
628db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            }
6394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            break;
6494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten
6594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATALOCATOR_IODEVICE:
6694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            {
6794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            pDataLocator->mIODevice = *(SLDataLocator_IODevice *)pLocator;
6894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            SLuint32 deviceType = pDataLocator->mIODevice.deviceType;
6994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            SLObjectItf device = pDataLocator->mIODevice.device;
7094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            if (NULL != device) {
7194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                pDataLocator->mIODevice.deviceID = 0;
7294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                SLuint32 expectedObjectID;
7394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                switch (deviceType) {
7494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                case SL_IODEVICE_LEDARRAY:
7594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    expectedObjectID = SL_OBJECTID_LEDDEVICE;
7694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    break;
7794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                case SL_IODEVICE_VIBRA:
7894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    expectedObjectID = SL_OBJECTID_VIBRADEVICE;
7994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    break;
8094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                case XA_IODEVICE_CAMERA:
8194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    expectedObjectID = XA_OBJECTID_CAMERADEVICE;
8294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    break;
8394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                case XA_IODEVICE_RADIO:
8494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    expectedObjectID = XA_OBJECTID_RADIODEVICE;
8594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    break;
8694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                // audio input and audio output cannot be specified via objects
8794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                case SL_IODEVICE_AUDIOINPUT:
8894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                // case SL_IODEVICE_AUDIOOUTPUT:   // does not exist in 1.0.1, added in 1.1
8994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                default:
90a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten                    SL_LOGE("%s: deviceType=%u", name, deviceType);
9194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    pDataLocator->mIODevice.device = NULL;
9294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    expectedObjectID = 0;
9394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    result = SL_RESULT_PARAMETER_INVALID;
948db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                }
9594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                if (result == SL_RESULT_SUCCESS) {
9694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    // check that device has the correct object ID and is realized,
9794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    // and acquire a strong reference to it
9894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    result = AcquireStrongRef((IObject *) device, expectedObjectID);
9994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    if (SL_RESULT_SUCCESS != result) {
10094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                        SL_LOGE("%s: locatorType=IODEVICE, but device field %p has wrong " \
10194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                            "object ID or is not realized", name, device);
10294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                        pDataLocator->mIODevice.device = NULL;
10394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    }
1048db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                }
10594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            } else {
10694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                SLuint32 deviceID = pDataLocator->mIODevice.deviceID;
10794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                switch (deviceType) {
10894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                case SL_IODEVICE_LEDARRAY:
10994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    if (SL_DEFAULTDEVICEID_LED != deviceID) {
110a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten                        SL_LOGE("%s: invalid LED deviceID=%u", name, deviceID);
11194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                        result = SL_RESULT_PARAMETER_INVALID;
11294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    }
11394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    break;
11494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                case SL_IODEVICE_VIBRA:
11594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    if (SL_DEFAULTDEVICEID_VIBRA != deviceID) {
116a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten                        SL_LOGE("%s: invalid vibra deviceID=%u", name, deviceID);
11794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                        result = SL_RESULT_PARAMETER_INVALID;
11894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    }
11994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    break;
12094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                case SL_IODEVICE_AUDIOINPUT:
12194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    if (SL_DEFAULTDEVICEID_AUDIOINPUT != deviceID) {
122a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten                        SL_LOGE("%s: invalid audio input deviceID=%u", name, deviceID);
12394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                        result = SL_RESULT_PARAMETER_INVALID;
12494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    }
12594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    break;
12694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                case XA_IODEVICE_RADIO:
12794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    // no default device ID for radio; see Khronos bug XXXX
12894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    break;
12994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                case XA_IODEVICE_CAMERA:
13094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    if (XA_DEFAULTDEVICEID_CAMERA != deviceID) {
131a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten                        SL_LOGE("%s: invalid audio input deviceID=%u", name, deviceID);
13294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                        result = XA_RESULT_PARAMETER_INVALID;
13394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    }
13494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    break;
13594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                // case SL_IODEVICE_AUDIOOUTPUT:
13694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    // does not exist in 1.0.1, added in 1.1
13794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    // break;
13894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                default:
139a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten                    SL_LOGE("%s: deviceType=%u is invalid", name, deviceType);
14094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    result = SL_RESULT_PARAMETER_INVALID;
1418b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten                }
1428db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            }
14394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            }
14494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            break;
1458db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
14694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATALOCATOR_MIDIBUFFERQUEUE:
14794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            pDataLocator->mMIDIBufferQueue = *(SLDataLocator_MIDIBufferQueue *)pLocator;
14894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            if (0 == pDataLocator->mMIDIBufferQueue.tpqn) {
14994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                pDataLocator->mMIDIBufferQueue.tpqn = 192;
15094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            }
15194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            // number of buffers must be specified, there is no default value, and can't be too big
15294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            if (!((1 <= pDataLocator->mMIDIBufferQueue.numBuffers) &&
15394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                (pDataLocator->mMIDIBufferQueue.numBuffers <= 255))) {
154a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten                SL_LOGE("%s: SLDataLocator_MIDIBufferQueue.numBuffers=%d", name,
15594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                        pDataLocator->mMIDIBufferQueue.numBuffers);
15694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                result = SL_RESULT_PARAMETER_INVALID;
15794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            }
15894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            break;
1598db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
16094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATALOCATOR_OUTPUTMIX:
16194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            pDataLocator->mOutputMix = *(SLDataLocator_OutputMix *)pLocator;
16294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            // check that output mix object has the correct object ID and is realized,
16394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            // and acquire a strong reference to it
16494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            result = AcquireStrongRef((IObject *) pDataLocator->mOutputMix.outputMix,
16594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                SL_OBJECTID_OUTPUTMIX);
16694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            if (SL_RESULT_SUCCESS != result) {
16794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                SL_LOGE("%s: locatorType=SL_DATALOCATOR_OUTPUTMIX, but outputMix field %p does " \
16894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    "not refer to an SL_OBJECTID_OUTPUTMIX or the output mix is not realized", \
16994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    name, pDataLocator->mOutputMix.outputMix);
17094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                pDataLocator->mOutputMix.outputMix = NULL;
17194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            }
17294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            break;
1738db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
17494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case XA_DATALOCATOR_NATIVEDISPLAY:
17594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            pDataLocator->mNativeDisplay = *(XADataLocator_NativeDisplay *)pLocator;
17639310fca2e30101fa6e5168da443581cc60c20bfGlenn Kasten            // hWindow is NDK C ANativeWindow * and hDisplay must be NULL
177ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten            if (pDataLocator->mNativeDisplay.hWindow == NULL) {
17839310fca2e30101fa6e5168da443581cc60c20bfGlenn Kasten                SL_LOGE("%s: hWindow must be non-NULL ANativeWindow *", name);
17939310fca2e30101fa6e5168da443581cc60c20bfGlenn Kasten                result = SL_RESULT_PARAMETER_INVALID;
18039310fca2e30101fa6e5168da443581cc60c20bfGlenn Kasten            }
18139310fca2e30101fa6e5168da443581cc60c20bfGlenn Kasten            if (pDataLocator->mNativeDisplay.hDisplay != NULL) {
18239310fca2e30101fa6e5168da443581cc60c20bfGlenn Kasten                SL_LOGE("%s: hDisplay must be NULL, but is %p", name,
18339310fca2e30101fa6e5168da443581cc60c20bfGlenn Kasten                        pDataLocator->mNativeDisplay.hDisplay);
184ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten                result = SL_RESULT_PARAMETER_INVALID;
185ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten            }
18694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            break;
1878b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten
18894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATALOCATOR_URI:
18994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            {
19094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            pDataLocator->mURI = *(SLDataLocator_URI *)pLocator;
19194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            if (NULL == pDataLocator->mURI.URI) {
19294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                SL_LOGE("%s: invalid URI=NULL", name);
19394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                result = SL_RESULT_PARAMETER_INVALID;
194c9919caaee38e3c4dbe09ea7cd5916d9b4a0f4a2Glenn Kasten            } else {
1955793033ccaeb30cc4936497f64dfa2cfe2cc405fGlenn Kasten                // NTH verify URI address for validity
1965793033ccaeb30cc4936497f64dfa2cfe2cc405fGlenn Kasten                size_t len = strlen((const char *) pDataLocator->mURI.URI);
1975793033ccaeb30cc4936497f64dfa2cfe2cc405fGlenn Kasten                SLchar *myURI = (SLchar *) malloc(len + 1);
1985793033ccaeb30cc4936497f64dfa2cfe2cc405fGlenn Kasten                if (NULL == myURI) {
1995793033ccaeb30cc4936497f64dfa2cfe2cc405fGlenn Kasten                    result = SL_RESULT_MEMORY_FAILURE;
2005793033ccaeb30cc4936497f64dfa2cfe2cc405fGlenn Kasten                } else {
2015793033ccaeb30cc4936497f64dfa2cfe2cc405fGlenn Kasten                    memcpy(myURI, pDataLocator->mURI.URI, len + 1);
2025793033ccaeb30cc4936497f64dfa2cfe2cc405fGlenn Kasten                    // Verify that another thread didn't change the NUL-terminator after we used it
2035793033ccaeb30cc4936497f64dfa2cfe2cc405fGlenn Kasten                    // to determine length of string to copy. It's OK if the string became shorter.
2045793033ccaeb30cc4936497f64dfa2cfe2cc405fGlenn Kasten                    if ('\0' != myURI[len]) {
2055793033ccaeb30cc4936497f64dfa2cfe2cc405fGlenn Kasten                        free(myURI);
2065793033ccaeb30cc4936497f64dfa2cfe2cc405fGlenn Kasten                        myURI = NULL;
2075793033ccaeb30cc4936497f64dfa2cfe2cc405fGlenn Kasten                        result = SL_RESULT_PARAMETER_INVALID;
2085793033ccaeb30cc4936497f64dfa2cfe2cc405fGlenn Kasten                    }
209c9919caaee38e3c4dbe09ea7cd5916d9b4a0f4a2Glenn Kasten                }
2105793033ccaeb30cc4936497f64dfa2cfe2cc405fGlenn Kasten                pDataLocator->mURI.URI = myURI;
21194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            }
21294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            }
21394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            break;
2148db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
2158db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten#ifdef ANDROID
21694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATALOCATOR_ANDROIDFD:
217d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        {
21894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            pDataLocator->mFD = *(SLDataLocator_AndroidFD *)pLocator;
219a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten            SL_LOGV("%s: fd=%d offset=%lld length=%lld", name, pDataLocator->mFD.fd,
22094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    pDataLocator->mFD.offset, pDataLocator->mFD.length);
22194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            // NTH check against process fd limit
22294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            if (0 > pDataLocator->mFD.fd) {
223a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten                SL_LOGE("%s: fd=%d\n", name, pDataLocator->mFD.fd);
22494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                result = SL_RESULT_PARAMETER_INVALID;
22594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            }
22694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            break;
227d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        }
22894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATALOCATOR_ANDROIDBUFFERQUEUE:
229d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        {
230d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi            pDataLocator->mABQ = *(SLDataLocator_AndroidBufferQueue*)pLocator;
231d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi            // number of buffers must be specified, there is no default value, and can't be too big
232d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi            if (!((1 <= pDataLocator->mBufferQueue.numBuffers) &&
233d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                    (pDataLocator->mBufferQueue.numBuffers <= 255))) {
234a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten                SL_LOGE("%s: numBuffers=%u", name, pDataLocator->mABQ.numBuffers);
235d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi                result = SL_RESULT_PARAMETER_INVALID;
23694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            }
23794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            break;
238d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi        }
23994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten#endif
24094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten
24194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATALOCATOR_NULL:   // a NULL pointer is allowed, but not a pointer to NULL
24294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        default:
243a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten            SL_LOGE("%s: locatorType=%u", name, locatorType);
24494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
2458db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        }
24694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten
24794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        // Verify that another thread didn't change the locatorType field after we used it
24894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        // to determine sizeof struct to copy.
2491d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten        if ((SL_RESULT_SUCCESS == result) && (locatorType != pDataLocator->mLocatorType)) {
250a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten            SL_LOGE("%s: locatorType changed from %u to %u", name, locatorType,
25194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    pDataLocator->mLocatorType);
25294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            result = SL_RESULT_PRECONDITIONS_VIOLATED;
2538db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        }
2548db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
2558db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    }
2568db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
25794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    // Verify that the data locator type is allowed in this context
25894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    if (SL_RESULT_SUCCESS == result) {
25994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        SLuint32 actualMask;
26094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        switch (locatorType) {
26194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATALOCATOR_NULL:
26294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATALOCATOR_URI:
26394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATALOCATOR_ADDRESS:
26494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATALOCATOR_IODEVICE:
26594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATALOCATOR_OUTPUTMIX:
26694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case XA_DATALOCATOR_NATIVEDISPLAY:
26794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATALOCATOR_BUFFERQUEUE:
26894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATALOCATOR_MIDIBUFFERQUEUE:
26994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            actualMask = 1L << locatorType;
27094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            break;
27194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten#ifdef ANDROID
27294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATALOCATOR_ANDROIDFD:
27394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
27494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATALOCATOR_ANDROIDBUFFERQUEUE:
27594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            actualMask = 0x100L << (locatorType - SL_DATALOCATOR_ANDROIDFD);
27694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            break;
27794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten#endif
27894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        default:
27994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            assert(false);
28094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            actualMask = 0L;
28194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            break;
28294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        }
28394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        if (!(allowedDataLocatorMask & actualMask)) {
284a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten            SL_LOGE("%s: data locator type 0x%x not allowed", name, locatorType);
28594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            result = SL_RESULT_CONTENT_UNSUPPORTED;
28694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        }
2878db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    }
28894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten
28994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    return result;
2908db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten}
2918db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
2928db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
2938db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten/** \brief Free the local deep copy of a data locator */
2948db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
2958db0b106cdce5f5216b1535492de7930ad738aedGlenn Kastenstatic void freeDataLocator(DataLocator *pDataLocator)
2968db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten{
2978db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    switch (pDataLocator->mLocatorType) {
29894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    case SL_DATALOCATOR_NULL:
2998b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten    case SL_DATALOCATOR_ADDRESS:
3008b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten    case SL_DATALOCATOR_BUFFERQUEUE:
3018b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten    case SL_DATALOCATOR_MIDIBUFFERQUEUE:
3028b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten    case XA_DATALOCATOR_NATIVEDISPLAY:
3038b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten        break;
3048db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    case SL_DATALOCATOR_URI:
3058db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        if (NULL != pDataLocator->mURI.URI) {
3068db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            free(pDataLocator->mURI.URI);
3078db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            pDataLocator->mURI.URI = NULL;
3088db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        }
3098db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        pDataLocator->mURI.URI = NULL;
3108db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        break;
3118db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    case SL_DATALOCATOR_IODEVICE:
3128db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        if (NULL != pDataLocator->mIODevice.device) {
3138db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            ReleaseStrongRef((IObject *) pDataLocator->mIODevice.device);
3148db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            pDataLocator->mIODevice.device = NULL;
3158db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        }
3168db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        break;
3178db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    case SL_DATALOCATOR_OUTPUTMIX:
3188db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        if (NULL != pDataLocator->mOutputMix.outputMix) {
3198db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            ReleaseStrongRef((IObject *) pDataLocator->mOutputMix.outputMix);
3208db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            pDataLocator->mOutputMix.outputMix = NULL;
3218db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        }
3228db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        break;
3238db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten#ifdef ANDROID
324fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi    case SL_DATALOCATOR_ANDROIDBUFFERQUEUE:
3258b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten    case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
3268b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten    case SL_DATALOCATOR_ANDROIDFD:
3278db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        break;
3288db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten#endif
3298db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    default:
3308b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten        // an invalid data locator is caught earlier when making the copy
3318b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten        assert(false);
3328db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        break;
3338db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    }
3348db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten}
3358db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
3368db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
3378db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten/** \brief Check a data format and make local deep copy */
3388db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
33994a37e8117fb72790882dfb815f99e2365754c74Glenn Kastenstatic SLresult checkDataFormat(const char *name, void *pFormat, DataFormat *pDataFormat,
3404e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean        SLuint32 allowedDataFormatMask, SLboolean isOutputFormat)
3418db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten{
34294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    assert(NULL != name && NULL != pDataFormat);
3438db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    SLresult result = SL_RESULT_SUCCESS;
344e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung    const SLuint32 *df_representation = NULL; // pointer to representation field, if it exists
34594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    SLuint32 formatType;
3468db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    if (NULL == pFormat) {
34794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        pDataFormat->mFormatType = formatType = SL_DATAFORMAT_NULL;
3488db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    } else {
34994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        formatType = *(SLuint32 *)pFormat;
3508db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        switch (formatType) {
351e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung        case SL_ANDROID_DATAFORMAT_PCM_EX:
352e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung            pDataFormat->mPCMEx.representation =
353e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                    ((SLAndroidDataFormat_PCM_EX *)pFormat)->representation;
354e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung            switch (pDataFormat->mPCMEx.representation) {
355e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung            case SL_ANDROID_PCM_REPRESENTATION_SIGNED_INT:
356e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung            case SL_ANDROID_PCM_REPRESENTATION_UNSIGNED_INT:
357e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung            case SL_ANDROID_PCM_REPRESENTATION_FLOAT:
358e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                df_representation = &pDataFormat->mPCMEx.representation;
359e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                break;
360e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung            default:
361e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                SL_LOGE("%s: unsupported representation: %d", name,
362e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                        pDataFormat->mPCMEx.representation);
363e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                result = SL_RESULT_PARAMETER_INVALID;
364e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                break;
365e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung            }
366e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung            // SL_ANDROID_DATAFORMAT_PCM_EX - fall through to next test.
3678db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        case SL_DATAFORMAT_PCM:
3688db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            pDataFormat->mPCM = *(SLDataFormat_PCM *)pFormat;
3698db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            do {
3704e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                if (pDataFormat->mPCM.numChannels == 0) {
3718db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    result = SL_RESULT_PARAMETER_INVALID;
3724e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                } else if (pDataFormat->mPCM.numChannels > SL_ANDROID_SPEAKER_COUNT_MAX) {
3738db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    result = SL_RESULT_CONTENT_UNSUPPORTED;
3748db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                }
3758db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                if (SL_RESULT_SUCCESS != result) {
3761d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                    SL_LOGE("%s: numChannels=%u", name, (unsigned) pDataFormat->mPCM.numChannels);
3778db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    break;
3788db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                }
3798db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
3808db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                // check the sampling rate
381cc97dbea7dbe0726f097d235163f2085a1b21498Glenn Kasten                if (pDataFormat->mPCM.samplesPerSec == 0) {
3828db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    result = SL_RESULT_PARAMETER_INVALID;
383cc97dbea7dbe0726f097d235163f2085a1b21498Glenn Kasten                } else if (pDataFormat->mPCM.samplesPerSec < SL_SAMPLINGRATE_8 ||
384cc97dbea7dbe0726f097d235163f2085a1b21498Glenn Kasten                        pDataFormat->mPCM.samplesPerSec > SL_SAMPLINGRATE_192) {
3858db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    result = SL_RESULT_CONTENT_UNSUPPORTED;
3868db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                }
3878db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                if (SL_RESULT_SUCCESS != result) {
388a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten                    SL_LOGE("%s: samplesPerSec=%u", name, pDataFormat->mPCM.samplesPerSec);
3898db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    break;
3908db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                }
3918db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
39271065fbf12abafd4c2a0dc85c81f13b564ff69fbGlenn Kasten                // check the container bit depth and representation
393e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                switch (pDataFormat->mPCM.containerSize) {
394e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                case 8:
3950d4d82daff89115d5a6318c53f94f22fa36a862bGlenn Kasten                    if (df_representation != NULL &&
396e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                            *df_representation != SL_ANDROID_PCM_REPRESENTATION_UNSIGNED_INT) {
397e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                        result = SL_RESULT_PARAMETER_INVALID;
398e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                    }
3998db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    break;
400e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                case 16:
401e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                case 24:
4020d4d82daff89115d5a6318c53f94f22fa36a862bGlenn Kasten                    if (df_representation != NULL &&
403e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                            *df_representation != SL_ANDROID_PCM_REPRESENTATION_SIGNED_INT) {
404e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                        result = SL_RESULT_PARAMETER_INVALID;
405e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                    }
406e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                    break;
407e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                case 32:
4080d4d82daff89115d5a6318c53f94f22fa36a862bGlenn Kasten                    if (df_representation != NULL
409e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                            && *df_representation != SL_ANDROID_PCM_REPRESENTATION_SIGNED_INT
410e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                            && *df_representation != SL_ANDROID_PCM_REPRESENTATION_FLOAT) {
411e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                        result = SL_RESULT_PARAMETER_INVALID;
412e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                    }
4138db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    break;
4148db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                default:
4158db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    result = SL_RESULT_PARAMETER_INVALID;
4168db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    break;
4178db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                }
4188db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                if (SL_RESULT_SUCCESS != result) {
419e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung                    SL_LOGE("%s: containerSize=%u", name, pDataFormat->mPCM.containerSize);
4208db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    break;
4218db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                }
4228db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
42371065fbf12abafd4c2a0dc85c81f13b564ff69fbGlenn Kasten                // sample size cannot be zero, and container size cannot be less than sample size
42471065fbf12abafd4c2a0dc85c81f13b564ff69fbGlenn Kasten                if (pDataFormat->mPCM.bitsPerSample == 0 ||
42571065fbf12abafd4c2a0dc85c81f13b564ff69fbGlenn Kasten                        pDataFormat->mPCM.containerSize < pDataFormat->mPCM.bitsPerSample) {
4268db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    result = SL_RESULT_PARAMETER_INVALID;
4278db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                }
4288db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                if (SL_RESULT_SUCCESS != result) {
4291d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                    SL_LOGE("%s: containerSize=%u, bitsPerSample=%u", name,
4308db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                            (unsigned) pDataFormat->mPCM.containerSize,
4318db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                            (unsigned) pDataFormat->mPCM.bitsPerSample);
4328db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    break;
4338db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                }
4348db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
4358db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                // check the channel mask
4364e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                SL_LOGV("%s: Requested channel mask of 0x%x for %d channel audio",
4374e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                    name,
4384e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                    pDataFormat->mPCM.channelMask,
4394e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                    pDataFormat->mPCM.numChannels);
4404e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
4414e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                if (pDataFormat->mPCM.channelMask == 0) {
4424e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                    // We can derive the channel mask from the channel count,
4434e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                    // but issue a warning--the automatic mask generation
4444e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                    // makes a lot of assumptions that may or may not be what
4454e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                    // the app was expecting.
4464e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                    SLuint32 mask = isOutputFormat
4474e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                            ? sles_channel_out_mask_from_count(pDataFormat->mPCM.numChannels)
4484e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                            : sles_channel_in_mask_from_count(pDataFormat->mPCM.numChannels);
4494e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                    if (mask == SL_ANDROID_UNKNOWN_CHANNELMASK) {
4504e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                        SL_LOGE("No channel mask specified and no default mapping for"
4514e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                                "requested speaker count of %u", pDataFormat->mPCM.numChannels);
45284bbadf848f606ff28273baf26fc246cf967059aAndy Hung                        result = SL_RESULT_PARAMETER_INVALID;
45384bbadf848f606ff28273baf26fc246cf967059aAndy Hung                    } else {
45484bbadf848f606ff28273baf26fc246cf967059aAndy Hung                        pDataFormat->mPCM.channelMask = mask;
4554e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                        SL_LOGW("No channel mask specified; Using mask %#x based on requested"
4564e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                                        "speaker count of %u",
4574e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                                pDataFormat->mPCM.channelMask,
4584e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                                pDataFormat->mPCM.numChannels);
45984bbadf848f606ff28273baf26fc246cf967059aAndy Hung                    }
4608db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                }
4614e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
4624e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                SLuint32 mask = pDataFormat->mPCM.channelMask;
4634e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                SLuint32 count = sles_channel_count_from_mask(mask);
4644e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                if (count != pDataFormat->mPCM.numChannels) {
4654e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                    SL_LOGE("%s: requested %d channels but mask (0x%x) has %d channel bits set",
4664e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                        name,
4674e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                        pDataFormat->mPCM.numChannels,
4684e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                        mask,
4694e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                        count);
4704e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                    result = SL_RESULT_PARAMETER_INVALID;
4718db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    break;
4728db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                }
4738db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
4744e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                SL_LOGV("%s: final channel mask is 0x%x", name, pDataFormat->mPCM.channelMask);
4754e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
4768db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                // check the endianness / byte order
4778db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                switch (pDataFormat->mPCM.endianness) {
4788db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                case SL_BYTEORDER_LITTLEENDIAN:
4798db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                case SL_BYTEORDER_BIGENDIAN:
4808db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    break;
4818db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                // native is proposed but not yet in spec
4828db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                default:
4838db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    result = SL_RESULT_PARAMETER_INVALID;
4848db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    break;
4858db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                }
4868db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                if (SL_RESULT_SUCCESS != result) {
4871d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                    SL_LOGE("%s: endianness=%u", name, (unsigned) pDataFormat->mPCM.endianness);
4888db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    break;
4898db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                }
4908db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
4918db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                // here if all checks passed successfully
4928db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
4938db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            } while(0);
4948db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            break;
4958db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
4968db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        case SL_DATAFORMAT_MIME:
4978db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            pDataFormat->mMIME = *(SLDataFormat_MIME *)pFormat;
4988db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            if (NULL != pDataFormat->mMIME.mimeType) {
4998db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                // NTH check address for validity
5008db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                size_t len = strlen((const char *) pDataFormat->mMIME.mimeType);
5018db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                SLchar *myMIME = (SLchar *) malloc(len + 1);
5028db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                if (NULL == myMIME) {
5038db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    result = SL_RESULT_MEMORY_FAILURE;
5048db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                } else {
5058db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    memcpy(myMIME, pDataFormat->mMIME.mimeType, len + 1);
5068db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    // make sure MIME string was not modified asynchronously
5078db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    if ('\0' != myMIME[len]) {
5088db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                        free(myMIME);
5098db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                        myMIME = NULL;
5108db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                        result = SL_RESULT_PRECONDITIONS_VIOLATED;
5118db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                    }
5128db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                }
5138db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                pDataFormat->mMIME.mimeType = myMIME;
5148db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            }
5158db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            break;
5168db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
5178b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten        case XA_DATAFORMAT_RAWIMAGE:
5188b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            pDataFormat->mRawImage = *(XADataFormat_RawImage *)pFormat;
5198b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            switch (pDataFormat->mRawImage.colorFormat) {
5208b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_MONOCHROME:
5218b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_8BITRGB332:
5228b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_12BITRGB444:
5238b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_16BITARGB4444:
5248b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_16BITARGB1555:
5258b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_16BITRGB565:
5268b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_16BITBGR565:
5278b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_18BITRGB666:
5288b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_18BITARGB1665:
5298b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_19BITARGB1666:
5308b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_24BITRGB888:
5318b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_24BITBGR888:
5328b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_24BITARGB1887:
5338b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_25BITARGB1888:
5348b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_32BITBGRA8888:
5358b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_32BITARGB8888:
5368b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_YUV411PLANAR:
5378b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_YUV420PLANAR:
5388b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_YUV420SEMIPLANAR:
5398b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_YUV422PLANAR:
5408b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_YUV422SEMIPLANAR:
5418b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_YCBYCR:
5428b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_YCRYCB:
5438b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_CBYCRY:
5448b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_CRYCBY:
5458b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_YUV444INTERLEAVED:
5468b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_RAWBAYER8BIT:
5478b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_RAWBAYER10BIT:
5488b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_RAWBAYER8BITCOMPRESSED:
5498b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_L2:
5508b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_L4:
5518b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_L8:
5528b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_L16:
5538b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_L24:
5548b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_L32:
5558b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_18BITBGR666:
5568b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_24BITARGB6666:
5578b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_24BITABGR6666:
5588b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten                break;
5598b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            case XA_COLORFORMAT_UNUSED:
5608b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            default:
5618b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten                result = XA_RESULT_PARAMETER_INVALID;
562a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten                SL_LOGE("%s: unsupported color format %d", name,
5631d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten                    pDataFormat->mRawImage.colorFormat);
5648b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten                break;
5658b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            }
5668b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            // no checks for height, width, or stride
5678b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten            break;
5688b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten
5698db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        default:
5708db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
5711d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten            SL_LOGE("%s: formatType=%u", name, (unsigned) formatType);
5728db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            break;
5738db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
5748db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        }
5758db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
5768db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        // make sure format type was not modified asynchronously
5778db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        if ((SL_RESULT_SUCCESS == result) && (formatType != pDataFormat->mFormatType)) {
578a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten            SL_LOGE("%s: formatType changed from %u to %u", name, formatType,
57994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                    pDataFormat->mFormatType);
5808db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            result = SL_RESULT_PRECONDITIONS_VIOLATED;
5818db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        }
5828db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
5838db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    }
5848db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
58594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    // Verify that the data format type is allowed in this context
58694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    if (SL_RESULT_SUCCESS == result) {
58794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        SLuint32 actualMask;
58894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        switch (formatType) {
58994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATAFORMAT_NULL:
59094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATAFORMAT_MIME:
59194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case SL_DATAFORMAT_PCM:
592e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung        case SL_ANDROID_DATAFORMAT_PCM_EX:
59394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        case XA_DATAFORMAT_RAWIMAGE:
59494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            actualMask = 1L << formatType;
59594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            break;
59694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        default:
59794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            assert(false);
59894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            actualMask = 0L;
59994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            break;
60094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        }
60194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        if (!(allowedDataFormatMask & actualMask)) {
602a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten            SL_LOGE("%s: data format %d not allowed", name, formatType);
60394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            result = SL_RESULT_CONTENT_UNSUPPORTED;
60494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        }
60594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    }
60694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten
6078db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    return result;
6088db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten}
6098db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
6108db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
61113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi/** \brief Check interface ID compatibility with respect to a particular source
6127965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten *         and sink data locator format
61313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi */
6148db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
6157965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn KastenSLresult checkSourceSinkVsInterfacesCompatibility(const DataLocatorFormat *pSrcDataLocatorFormat,
6167965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten        const DataLocatorFormat *pSinkDataLocatorFormat,
61705c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten        const ClassTable *clazz, unsigned requiredMask) {
6188db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    int index;
61913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    switch (pSrcDataLocatorFormat->mLocator.mLocatorType) {
62013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    case SL_DATALOCATOR_URI:
62113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#ifdef ANDROID
62213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi    case SL_DATALOCATOR_ANDROIDFD:
62313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#endif
62413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        // URIs and FD can be sources when "playing" to an OutputMix or a Buffer Queue for decode
62513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        // so we don't prevent the retrieval of the BufferQueue interfaces for those sources
6267965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten        switch (pSinkDataLocatorFormat->mLocator.mLocatorType) {
6277965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten        case SL_DATALOCATOR_BUFFERQUEUE:
6287965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten#ifdef ANDROID
6297965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten        case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
6307965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten#endif
6317965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten            break;
6327965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten        default:
63305c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten            // can't require SLBufferQueueItf or its alias SLAndroidSimpleBufferQueueItf
6347965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten            // if the data sink is not a buffer queue
6357965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten            index = clazz->mMPH_to_index[MPH_BUFFERQUEUE];
6367965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten#ifdef ANDROID
6377965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten            assert(index == clazz->mMPH_to_index[MPH_ANDROIDSIMPLEBUFFERQUEUE]);
6387965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten#endif
6397965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten            if (0 <= index) {
64005c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten                if (requiredMask & (1 << index)) {
64105c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten                    SL_LOGE("can't require SL_IID_BUFFERQUEUE "
6427965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten#ifdef ANDROID
6437965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten                            "or SL_IID_ANDROIDSIMPLEBUFFERQUEUE "
6447965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten#endif
6457965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten                            "with a non-buffer queue data sink");
6467965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten                    return SL_RESULT_FEATURE_UNSUPPORTED;
6477965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten                }
6487965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten            }
6497965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten            break;
6507965455f86c21d6e1f788b284f5fc829e82ff2b5Glenn Kasten        }
65113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi        break;
65213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
6538db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    case SL_DATALOCATOR_BUFFERQUEUE:
6548db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten#ifdef ANDROID
6558db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
6568db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten#endif
65705c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten        // can't require SLSeekItf if data source is a buffer queue
658bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        index = clazz->mMPH_to_index[MPH_SEEK];
6598db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        if (0 <= index) {
66005c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten            if (requiredMask & (1 << index)) {
66105c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten                SL_LOGE("can't require SL_IID_SEEK with a buffer queue data source");
6628db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                return SL_RESULT_FEATURE_UNSUPPORTED;
6638db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            }
6648db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        }
66505c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten        // can't require SLMuteSoloItf if data source is a mono buffer queue
666bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        index = clazz->mMPH_to_index[MPH_MUTESOLO];
6678db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        if (0 <= index) {
66805c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten            if ((requiredMask & (1 << index)) &&
66913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    (SL_DATAFORMAT_PCM == pSrcDataLocatorFormat->mFormat.mFormatType) &&
67013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi                    (1 == pSrcDataLocatorFormat->mFormat.mPCM.numChannels)) {
67105c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten                SL_LOGE("can't require SL_IID_MUTESOLO with a mono buffer queue data source");
6728db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                return SL_RESULT_FEATURE_UNSUPPORTED;
6738db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            }
6748db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        }
6758db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        break;
67613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi
6778b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten#ifdef ANDROID
6788b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten    case SL_DATALOCATOR_ANDROIDBUFFERQUEUE:
679779a533785a4b8d2521123bc3c0a035b93ba078dJean-Michel Trivi        // can't require SLSeekItf if data source is an Android buffer queue
680779a533785a4b8d2521123bc3c0a035b93ba078dJean-Michel Trivi        index = clazz->mMPH_to_index[MPH_SEEK];
681779a533785a4b8d2521123bc3c0a035b93ba078dJean-Michel Trivi        if (0 <= index) {
682779a533785a4b8d2521123bc3c0a035b93ba078dJean-Michel Trivi            if (requiredMask & (1 << index)) {
683779a533785a4b8d2521123bc3c0a035b93ba078dJean-Michel Trivi                SL_LOGE("can't require SL_IID_SEEK with a SL_DATALOCATOR_ANDROIDBUFFERQUEUE "\
684779a533785a4b8d2521123bc3c0a035b93ba078dJean-Michel Trivi                        "source");
685779a533785a4b8d2521123bc3c0a035b93ba078dJean-Michel Trivi                return SL_RESULT_FEATURE_UNSUPPORTED;
686779a533785a4b8d2521123bc3c0a035b93ba078dJean-Michel Trivi            }
687779a533785a4b8d2521123bc3c0a035b93ba078dJean-Michel Trivi        }
688bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi        switch (pSinkDataLocatorFormat->mLocator.mLocatorType) {
689779a533785a4b8d2521123bc3c0a035b93ba078dJean-Michel Trivi        // for use-case AAC decode from SLAndroidBufferQueueItf with AAC ADTS data
690bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi        case SL_DATALOCATOR_BUFFERQUEUE:
691bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi        case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
692bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi            break;
693779a533785a4b8d2521123bc3c0a035b93ba078dJean-Michel Trivi        // for use-case audio playback from SLAndroidBufferQueueItf with MP2TS data
694779a533785a4b8d2521123bc3c0a035b93ba078dJean-Michel Trivi        case SL_DATALOCATOR_OUTPUTMIX:
695779a533785a4b8d2521123bc3c0a035b93ba078dJean-Michel Trivi            break;
696bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi        default:
697779a533785a4b8d2521123bc3c0a035b93ba078dJean-Michel Trivi            SL_LOGE("Invalid sink for SL_DATALOCATOR_ANDROIDBUFFERQUEUE source");
698bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi            return SL_RESULT_FEATURE_UNSUPPORTED;
699bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi            break;
700bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi        }
701bb832e853d4afb11b0a3287b2eb0cad87696d631Jean-Michel Trivi        break;
7028b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten#endif
7038b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten    case SL_DATALOCATOR_ADDRESS:
7048b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten    case SL_DATALOCATOR_MIDIBUFFERQUEUE:
7058b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten    case XA_DATALOCATOR_NATIVEDISPLAY:
7068b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten        // any special checks here???
7078db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    default:
70805c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten        // can't require SLBufferQueueItf or its alias SLAndroidSimpleBufferQueueItf
7098db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        // if the data source is not a buffer queue
710bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        index = clazz->mMPH_to_index[MPH_BUFFERQUEUE];
7118db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten#ifdef ANDROID
712bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        assert(index == clazz->mMPH_to_index[MPH_ANDROIDSIMPLEBUFFERQUEUE]);
7138db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten#endif
7148db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        if (0 <= index) {
71505c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten            if (requiredMask & (1 << index)) {
71605c7b2d09d54b9260ff7f3f5e491f38d0097c406Glenn Kasten                SL_LOGE("can't require SL_IID_BUFFERQUEUE "
7178db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten#ifdef ANDROID
7188db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                        "or SL_IID_ANDROIDSIMPLEBUFFERQUEUE "
7198db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten#endif
7208db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                        "with a non-buffer queue data source");
7218db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten                return SL_RESULT_FEATURE_UNSUPPORTED;
7228db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            }
7238db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        }
7248db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        break;
7258db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    }
7268db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    return SL_RESULT_SUCCESS;
7278db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten}
7288db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
7298db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
7308db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten/** \brief Free the local deep copy of a data format */
7318db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
7328db0b106cdce5f5216b1535492de7930ad738aedGlenn Kastenstatic void freeDataFormat(DataFormat *pDataFormat)
7338db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten{
7348db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    switch (pDataFormat->mFormatType) {
7358db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    case SL_DATAFORMAT_MIME:
7368db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        if (NULL != pDataFormat->mMIME.mimeType) {
7378db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            free(pDataFormat->mMIME.mimeType);
7388db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten            pDataFormat->mMIME.mimeType = NULL;
7398db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        }
7408db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        break;
741e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung    case SL_ANDROID_DATAFORMAT_PCM_EX:
7428b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten    case SL_DATAFORMAT_PCM:
7438b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten    case XA_DATAFORMAT_RAWIMAGE:
7448b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten    case SL_DATAFORMAT_NULL:
7458b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten        break;
7468db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    default:
7478b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten        // an invalid data format is caught earlier during the copy
7488b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten        assert(false);
7498db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        break;
7508db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    }
7518db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten}
7528db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
7538db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
7548db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten/** \brief Check a data source and make local deep copy */
7558db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
75694a37e8117fb72790882dfb815f99e2365754c74Glenn KastenSLresult checkDataSource(const char *name, const SLDataSource *pDataSrc,
75794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        DataLocatorFormat *pDataLocatorFormat, SLuint32 allowedDataLocatorMask,
75894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        SLuint32 allowedDataFormatMask)
7598db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten{
76094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    assert(NULL != name && NULL != pDataLocatorFormat);
76194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    pDataLocatorFormat->u.mSource.pLocator = &pDataLocatorFormat->mLocator;
76294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    pDataLocatorFormat->u.mSource.pFormat = &pDataLocatorFormat->mFormat;
76394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten
7648db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    if (NULL == pDataSrc) {
76594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        pDataLocatorFormat->mLocator.mLocatorType = SL_DATALOCATOR_NULL;
76694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        pDataLocatorFormat->mFormat.mFormatType = SL_DATAFORMAT_NULL;
76794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        if ((allowedDataLocatorMask & DATALOCATOR_MASK_NULL) &&
76894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                (allowedDataFormatMask & DATAFORMAT_MASK_NULL)) {
76994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            return SL_RESULT_SUCCESS;
77094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        }
7711d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten        SL_LOGE("%s: data source cannot be NULL", name);
7728db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
7738db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    }
7748db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    SLDataSource myDataSrc = *pDataSrc;
7758db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    SLresult result;
77694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    result = checkDataLocator(name, myDataSrc.pLocator, &pDataLocatorFormat->mLocator,
77794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            allowedDataLocatorMask);
7788db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    if (SL_RESULT_SUCCESS != result) {
7798db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        return result;
7808db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    }
7818db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
78294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    switch (pDataLocatorFormat->mLocator.mLocatorType) {
7838db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    case SL_DATALOCATOR_URI:
78494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        allowedDataFormatMask &= DATAFORMAT_MASK_MIME;
78594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        break;
7868db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    case SL_DATALOCATOR_ADDRESS:
7878db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    case SL_DATALOCATOR_BUFFERQUEUE:
788e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung        allowedDataFormatMask &= DATAFORMAT_MASK_PCM | DATAFORMAT_MASK_PCM_EX;
78994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        break;
790e670554ea199eef745740eaccc176ff283b0cd10Glenn Kasten    // Per the spec, the pFormat field is ignored in some cases
79194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    case SL_DATALOCATOR_IODEVICE:
792e670554ea199eef745740eaccc176ff283b0cd10Glenn Kasten        myDataSrc.pFormat = NULL;
793e670554ea199eef745740eaccc176ff283b0cd10Glenn Kasten        // fall through
794e670554ea199eef745740eaccc176ff283b0cd10Glenn Kasten    case SL_DATALOCATOR_NULL:
7958db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    case SL_DATALOCATOR_MIDIBUFFERQUEUE:
79694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        allowedDataFormatMask &= DATAFORMAT_MASK_NULL;
79794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        break;
79894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    case SL_DATALOCATOR_OUTPUTMIX:
79994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    case XA_DATALOCATOR_NATIVEDISPLAY:
80094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        allowedDataFormatMask = DATAFORMAT_MASK_NONE;
80194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        break;
8028db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten#ifdef ANDROID
8038db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    case SL_DATALOCATOR_ANDROIDFD:
80494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        allowedDataFormatMask &= DATAFORMAT_MASK_MIME;
80594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        break;
8068db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
807e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung        allowedDataFormatMask &= DATAFORMAT_MASK_PCM | DATAFORMAT_MASK_PCM_EX;
80894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        break;
809fa62f9f2c20b446178c05e3e92407fe5dfdbf8a1Jean-Michel Trivi    case SL_DATALOCATOR_ANDROIDBUFFERQUEUE:
810c869defb7c0dd6f4e45ad26abb0f8ccc960152deJean-Michel Trivi        allowedDataFormatMask &= DATAFORMAT_MASK_MIME;;
8118db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        break;
81294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten#endif
8138db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    default:
81494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        // invalid data locator type is caught earlier
81594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        assert(false);
81694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        allowedDataFormatMask = DATAFORMAT_MASK_NONE;
8178b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten        break;
8188db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    }
8198db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
8204e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    result = checkDataFormat(name,
8214e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                             myDataSrc.pFormat,
8224e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                             &pDataLocatorFormat->mFormat,
8234e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                             allowedDataFormatMask,
8244e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean                             SL_BOOLEAN_TRUE /*isOutputFormat*/);
82594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    if (SL_RESULT_SUCCESS != result) {
82694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        freeDataLocator(&pDataLocatorFormat->mLocator);
82794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        return result;
82894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    }
82994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten
8308db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    return SL_RESULT_SUCCESS;
8318db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten}
8328db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
8338db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
8348db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten/** \brief Check a data sink and make local deep copy */
8358db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
83694a37e8117fb72790882dfb815f99e2365754c74Glenn KastenSLresult checkDataSink(const char *name, const SLDataSink *pDataSink,
83794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        DataLocatorFormat *pDataLocatorFormat, SLuint32 allowedDataLocatorMask,
83894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        SLuint32 allowedDataFormatMask)
8398db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten{
84094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    assert(NULL != name && NULL != pDataLocatorFormat);
84194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    pDataLocatorFormat->u.mSink.pLocator = &pDataLocatorFormat->mLocator;
84294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    pDataLocatorFormat->u.mSink.pFormat = &pDataLocatorFormat->mFormat;
84394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten
8448db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    if (NULL == pDataSink) {
84594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        pDataLocatorFormat->mLocator.mLocatorType = SL_DATALOCATOR_NULL;
84694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        pDataLocatorFormat->mFormat.mFormatType = SL_DATAFORMAT_NULL;
84794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        if ((allowedDataLocatorMask & DATALOCATOR_MASK_NULL) &&
84894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten                (allowedDataFormatMask & DATAFORMAT_MASK_NULL)) {
84994a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            return SL_RESULT_SUCCESS;
85094a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        }
8511d081e49a10543018e1ae33792bd3d30504719baGlenn Kasten        SL_LOGE("%s: data sink cannot be NULL", name);
8528db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
8538db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    }
8548db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    SLDataSink myDataSink = *pDataSink;
8558db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    SLresult result;
85694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    result = checkDataLocator(name, myDataSink.pLocator, &pDataLocatorFormat->mLocator,
85794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten            allowedDataLocatorMask);
8588db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    if (SL_RESULT_SUCCESS != result) {
8598db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        return result;
8608db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    }
8618db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
86294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    switch (pDataLocatorFormat->mLocator.mLocatorType) {
8638db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    case SL_DATALOCATOR_URI:
86494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        allowedDataFormatMask &= DATAFORMAT_MASK_MIME;
8658db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        break;
86694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    case SL_DATALOCATOR_ADDRESS:
8678db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    case SL_DATALOCATOR_BUFFERQUEUE:
868e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung        allowedDataFormatMask &= DATAFORMAT_MASK_PCM | DATAFORMAT_MASK_PCM_EX;
8698db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten        break;
870e670554ea199eef745740eaccc176ff283b0cd10Glenn Kasten    // Per the spec, the pFormat field is ignored in some cases
8718db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    case SL_DATALOCATOR_IODEVICE:
8728db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    case SL_DATALOCATOR_OUTPUTMIX:
8738b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten    case XA_DATALOCATOR_NATIVEDISPLAY:
874e670554ea199eef745740eaccc176ff283b0cd10Glenn Kasten        myDataSink.pFormat = NULL;
875e670554ea199eef745740eaccc176ff283b0cd10Glenn Kasten        // fall through
876e670554ea199eef745740eaccc176ff283b0cd10Glenn Kasten    case SL_DATALOCATOR_NULL:
877e670554ea199eef745740eaccc176ff283b0cd10Glenn Kasten    case SL_DATALOCATOR_MIDIBUFFERQUEUE:
87894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        allowedDataFormatMask &= DATAFORMAT_MASK_NULL;
8798b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten        break;
8808b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten#ifdef ANDROID
88194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    case SL_DATALOCATOR_ANDROIDFD:
88294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        allowedDataFormatMask = DATAFORMAT_MASK_NONE;
88394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        break;
88494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
885e57c13397185f9ad0f162855e9a8ebeb0c94bfc4Andy Hung        allowedDataFormatMask &= DATAFORMAT_MASK_PCM | DATAFORMAT_MASK_PCM_EX;
88694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        break;
8878b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten    case SL_DATALOCATOR_ANDROIDBUFFERQUEUE:
88894a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        allowedDataFormatMask = DATAFORMAT_MASK_NONE;
8898b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten        break;
8908b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten#endif
89194a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    default:
89294a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        // invalid data locator type is caught earlier
89394a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        assert(false);
89494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        allowedDataFormatMask = DATAFORMAT_MASK_NONE;
89594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        break;
89694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    }
89794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten
8984e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    result = checkDataFormat(name,
8994e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean            myDataSink.pFormat,
9004e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean            &pDataLocatorFormat->mFormat,
9014e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean            allowedDataFormatMask,
9024e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean            SL_BOOLEAN_FALSE /*isOutputFormat*/);
9034e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
90494a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    if (SL_RESULT_SUCCESS != result) {
90594a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        freeDataLocator(&pDataLocatorFormat->mLocator);
90694a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten        return result;
9078db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    }
9088db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
9098db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    return SL_RESULT_SUCCESS;
9108db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten}
9118db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
9128db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
9138db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten/** \brief Free the local deep copy of a data locator format */
9148db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten
9158db0b106cdce5f5216b1535492de7930ad738aedGlenn Kastenvoid freeDataLocatorFormat(DataLocatorFormat *dlf)
9168db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten{
91794a37e8117fb72790882dfb815f99e2365754c74Glenn Kasten    assert(NULL != dlf);
9188db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    freeDataLocator(&dlf->mLocator);
9198db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten    freeDataFormat(&dlf->mFormat);
9208db0b106cdce5f5216b1535492de7930ad738aedGlenn Kasten}
921