1afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber/*
2afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * Copyright 2012, The Android Open Source Project
3afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber *
4afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * you may not use this file except in compliance with the License.
6afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * You may obtain a copy of the License at
7afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber *
8afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber *     http://www.apache.org/licenses/LICENSE-2.0
9afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber *
10afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * Unless required by applicable law or agreed to in writing, software
11afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * See the License for the specific language governing permissions and
14afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * limitations under the License.
15afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber */
16afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
17afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber//#define LOG_NDEBUG 0
18afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#define LOG_TAG "MediaCodecList"
19afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#include <utils/Log.h>
20afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
2160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar#include <binder/IServiceManager.h>
2260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar
2360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar#include <media/IMediaCodecList.h>
2460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar#include <media/IMediaPlayerService.h>
2560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar#include <media/MediaCodecInfo.h>
26afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
27afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#include <media/stagefright/foundation/ADebug.h>
28513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar#include <media/stagefright/foundation/AMessage.h>
2960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar#include <media/stagefright/MediaCodecList.h>
30afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#include <media/stagefright/MediaErrors.h>
3169829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber#include <media/stagefright/OMXClient.h>
3269829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber#include <media/stagefright/OMXCodec.h>
3360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar
34afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#include <utils/threads.h>
35afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
36e8057dd8208f0a185109992339a995c518b12780Elliott Hughes#include <libexpat/expat.h>
37afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
38afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubernamespace android {
39afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
40afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberstatic Mutex sInitMutex;
41afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
4260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnarstatic MediaCodecList *gCodecList = NULL;
4360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar
44afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber// static
4560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnarsp<IMediaCodecList> MediaCodecList::sCodecList;
46afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
47afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber// static
4860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnarsp<IMediaCodecList> MediaCodecList::getLocalInstance() {
49afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    Mutex::Autolock autoLock(sInitMutex);
50afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
5160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    if (gCodecList == NULL) {
5260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        gCodecList = new MediaCodecList;
5360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        if (gCodecList->initCheck() == OK) {
5460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            sCodecList = gCodecList;
5560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        }
56afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
57afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
5860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    return sCodecList;
5960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar}
6060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar
6160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnarstatic Mutex sRemoteInitMutex;
6260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar
6360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnarsp<IMediaCodecList> MediaCodecList::sRemoteList;
6460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar
65eee82e44548f17253c2e06b25725f91c7b549ec2Lajos Molnarsp<MediaCodecList::BinderDeathObserver> MediaCodecList::sBinderDeathObserver;
66eee82e44548f17253c2e06b25725f91c7b549ec2Lajos Molnar
67eee82e44548f17253c2e06b25725f91c7b549ec2Lajos Molnarvoid MediaCodecList::BinderDeathObserver::binderDied(const wp<IBinder> &who __unused) {
68eee82e44548f17253c2e06b25725f91c7b549ec2Lajos Molnar    Mutex::Autolock _l(sRemoteInitMutex);
69eee82e44548f17253c2e06b25725f91c7b549ec2Lajos Molnar    sRemoteList.clear();
70eee82e44548f17253c2e06b25725f91c7b549ec2Lajos Molnar    sBinderDeathObserver.clear();
71eee82e44548f17253c2e06b25725f91c7b549ec2Lajos Molnar}
72eee82e44548f17253c2e06b25725f91c7b549ec2Lajos Molnar
7360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar// static
7460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnarsp<IMediaCodecList> MediaCodecList::getInstance() {
751381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar    Mutex::Autolock _l(sRemoteInitMutex);
761381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar    if (sRemoteList == NULL) {
771381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar        sp<IBinder> binder =
781381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar            defaultServiceManager()->getService(String16("media.player"));
791381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar        sp<IMediaPlayerService> service =
801381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar            interface_cast<IMediaPlayerService>(binder);
811381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar        if (service.get() != NULL) {
821381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar            sRemoteList = service->getCodecList();
83eee82e44548f17253c2e06b25725f91c7b549ec2Lajos Molnar            if (sRemoteList != NULL) {
84eee82e44548f17253c2e06b25725f91c7b549ec2Lajos Molnar                sBinderDeathObserver = new BinderDeathObserver();
85eee82e44548f17253c2e06b25725f91c7b549ec2Lajos Molnar                binder->linkToDeath(sBinderDeathObserver.get());
86eee82e44548f17253c2e06b25725f91c7b549ec2Lajos Molnar            }
871381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar        }
881381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar        if (sRemoteList == NULL) {
891381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar            // if failed to get remote list, create local list
901381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar            sRemoteList = getLocalInstance();
911381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar        }
921381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar    }
931381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar    return sRemoteList;
94afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
95afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
96afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas HuberMediaCodecList::MediaCodecList()
97afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    : mInitCheck(NO_INIT) {
98d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    parseTopLevelXMLFile("/etc/media_codecs.xml");
99d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar}
100afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
101d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnarvoid MediaCodecList::parseTopLevelXMLFile(const char *codecs_xml) {
102d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    // get href_base
103d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    char *href_base_end = strrchr(codecs_xml, '/');
104d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    if (href_base_end != NULL) {
105d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        mHrefBase = AString(codecs_xml, href_base_end - codecs_xml + 1);
106d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    }
107d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
10860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    mInitCheck = OK; // keeping this here for safety
109d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    mCurrentSection = SECTION_TOPLEVEL;
110d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    mDepth = 0;
111d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
11260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    OMXClient client;
11360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    mInitCheck = client.connect();
11460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    if (mInitCheck != OK) {
11560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        return;
11660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    }
11760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    mOMX = client.interface();
118d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    parseXMLFile(codecs_xml);
11960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    mOMX.clear();
120d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
121d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    if (mInitCheck != OK) {
122d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        mCodecInfos.clear();
123afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return;
124afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
125afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
126d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    for (size_t i = mCodecInfos.size(); i-- > 0;) {
12760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        const MediaCodecInfo &info = *mCodecInfos.itemAt(i).get();
128afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
12960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        if (info.mCaps.size() == 0) {
130d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            // No types supported by this component???
131d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            ALOGW("Component %s does not support any type of media?",
13260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                  info.mName.c_str());
133ecdd39c5af016e2fa57cbfd837aa670b706dabd3Andreas Huber
134d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            mCodecInfos.removeAt(i);
135513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar#if LOG_NDEBUG == 0
136513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else {
13760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            for (size_t type_ix = 0; type_ix < info.mCaps.size(); ++type_ix) {
13860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                AString mime = info.mCaps.keyAt(type_ix);
13960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                const sp<MediaCodecInfo::Capabilities> &caps = info.mCaps.valueAt(type_ix);
14060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar
14160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                ALOGV("%s codec info for %s: %s", info.mName.c_str(), mime.c_str(),
14260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                        caps->getDetails()->debugString().c_str());
14360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                ALOGV("    flags=%d", caps->getFlags());
14460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                {
14560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    Vector<uint32_t> colorFormats;
14660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    caps->getSupportedColorFormats(&colorFormats);
14760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    AString nice;
14860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    for (size_t ix = 0; ix < colorFormats.size(); ix++) {
14960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                        if (ix > 0) {
15060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                            nice.append(", ");
15160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                        }
15260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                        nice.append(colorFormats.itemAt(ix));
15360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    }
15460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    ALOGV("    colors=[%s]", nice.c_str());
15560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                }
15660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                {
15760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    Vector<MediaCodecInfo::ProfileLevel> profileLevels;
15860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    caps->getSupportedProfileLevels(&profileLevels);
15960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    AString nice;
16060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    for (size_t ix = 0; ix < profileLevels.size(); ix++) {
16160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                        if (ix > 0) {
16260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                            nice.append(", ");
16360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                        }
16460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                        const MediaCodecInfo::ProfileLevel &pl =
16560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                            profileLevels.itemAt(ix);
16660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                        nice.append(pl.mProfile);
16760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                        nice.append("/");
16860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                        nice.append(pl.mLevel);
16960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    }
17060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    ALOGV("    levels=[%s]", nice.c_str());
171513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                }
172513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
173513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar#endif
174d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        }
175afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
176afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
177afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#if 0
178afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    for (size_t i = 0; i < mCodecInfos.size(); ++i) {
179afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        const CodecInfo &info = mCodecInfos.itemAt(i);
180afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
181afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        AString line = info.mName;
182afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        line.append(" supports ");
183afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        for (size_t j = 0; j < mTypes.size(); ++j) {
184afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            uint32_t value = mTypes.valueAt(j);
185afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
186afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (info.mTypes & (1ul << value)) {
187afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                line.append(mTypes.keyAt(j));
188afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                line.append(" ");
189afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
190afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
191afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
192afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        ALOGI("%s", line.c_str());
193afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
194afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#endif
195afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
196afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
197afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas HuberMediaCodecList::~MediaCodecList() {
198afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
199afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
200afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberstatus_t MediaCodecList::initCheck() const {
201afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    return mInitCheck;
202afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
203afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
204d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnarvoid MediaCodecList::parseXMLFile(const char *path) {
205d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    FILE *file = fopen(path, "r");
206d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
207d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    if (file == NULL) {
208d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        ALOGW("unable to open media codecs configuration xml file: %s", path);
209d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        mInitCheck = NAME_NOT_FOUND;
210d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        return;
211d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    }
212afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
213afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    XML_Parser parser = ::XML_ParserCreate(NULL);
214afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    CHECK(parser != NULL);
215afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
216afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    ::XML_SetUserData(parser, this);
217afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    ::XML_SetElementHandler(
218afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            parser, StartElementHandlerWrapper, EndElementHandlerWrapper);
219afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
220afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    const int BUFF_SIZE = 512;
221afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    while (mInitCheck == OK) {
222afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        void *buff = ::XML_GetBuffer(parser, BUFF_SIZE);
223afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (buff == NULL) {
224d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            ALOGE("failed in call to XML_GetBuffer()");
225afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            mInitCheck = UNKNOWN_ERROR;
226afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
227afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
228afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
229afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        int bytes_read = ::fread(buff, 1, BUFF_SIZE, file);
230afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (bytes_read < 0) {
231afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            ALOGE("failed in call to read");
232afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            mInitCheck = ERROR_IO;
233afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
234afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
235afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
236d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        XML_Status status = ::XML_ParseBuffer(parser, bytes_read, bytes_read == 0);
237d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        if (status != XML_STATUS_OK) {
238d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            ALOGE("malformed (%s)", ::XML_ErrorString(::XML_GetErrorCode(parser)));
239afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            mInitCheck = ERROR_MALFORMED;
240afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
241afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
242afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
243afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (bytes_read == 0) {
244afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
245afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
246afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
247afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
248afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    ::XML_ParserFree(parser);
249afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
250d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    fclose(file);
251d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    file = NULL;
252afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
253afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
254afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber// static
255afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubervoid MediaCodecList::StartElementHandlerWrapper(
256afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        void *me, const char *name, const char **attrs) {
257afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    static_cast<MediaCodecList *>(me)->startElementHandler(name, attrs);
258afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
259afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
260afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber// static
261afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubervoid MediaCodecList::EndElementHandlerWrapper(void *me, const char *name) {
262afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    static_cast<MediaCodecList *>(me)->endElementHandler(name);
263afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
264afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
265d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnarstatus_t MediaCodecList::includeXMLFile(const char **attrs) {
266d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    const char *href = NULL;
267d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    size_t i = 0;
268d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    while (attrs[i] != NULL) {
269d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        if (!strcmp(attrs[i], "href")) {
270d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            if (attrs[i + 1] == NULL) {
271d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar                return -EINVAL;
272d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            }
273d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            href = attrs[i + 1];
274d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            ++i;
275d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        } else {
276d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            return -EINVAL;
277d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        }
278d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        ++i;
279d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    }
280d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
281d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    // For security reasons and for simplicity, file names can only contain
282d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    // [a-zA-Z0-9_.] and must start with  media_codecs_ and end with .xml
283d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    for (i = 0; href[i] != '\0'; i++) {
284d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        if (href[i] == '.' || href[i] == '_' ||
285d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar                (href[i] >= '0' && href[i] <= '9') ||
286d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar                (href[i] >= 'A' && href[i] <= 'Z') ||
287d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar                (href[i] >= 'a' && href[i] <= 'z')) {
288d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            continue;
289d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        }
290d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        ALOGE("invalid include file name: %s", href);
291d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        return -EINVAL;
292d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    }
293d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
294d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    AString filename = href;
295d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    if (!filename.startsWith("media_codecs_") ||
296d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        !filename.endsWith(".xml")) {
297d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        ALOGE("invalid include file name: %s", href);
298d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        return -EINVAL;
299d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    }
300d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    filename.insert(mHrefBase, 0);
301d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
302d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    parseXMLFile(filename.c_str());
303d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    return mInitCheck;
304d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar}
305d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
306afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubervoid MediaCodecList::startElementHandler(
307afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        const char *name, const char **attrs) {
308afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (mInitCheck != OK) {
309afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return;
310afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
311afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
312513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    bool inType = true;
313513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
314d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    if (!strcmp(name, "Include")) {
315d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        mInitCheck = includeXMLFile(attrs);
316d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        if (mInitCheck == OK) {
317d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            mPastSections.push(mCurrentSection);
318d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            mCurrentSection = SECTION_INCLUDE;
319d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        }
320d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        ++mDepth;
321d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        return;
322d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    }
323d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
324afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    switch (mCurrentSection) {
325afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_TOPLEVEL:
326afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
327afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "Decoders")) {
328afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_DECODERS;
329afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            } else if (!strcmp(name, "Encoders")) {
330afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_ENCODERS;
331afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
332afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
333afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
334afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
335afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_DECODERS:
336afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
337afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "MediaCodec")) {
338afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mInitCheck =
339afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                    addMediaCodecFromAttributes(false /* encoder */, attrs);
340afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
341afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_DECODER;
342afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
343afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
344afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
345afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
346afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_ENCODERS:
347afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
348afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "MediaCodec")) {
349afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mInitCheck =
350afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                    addMediaCodecFromAttributes(true /* encoder */, attrs);
351afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
352afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_ENCODER;
353afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
354afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
355afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
356afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
357afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_DECODER:
358afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_ENCODER:
359afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
360afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "Quirk")) {
361afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mInitCheck = addQuirk(attrs);
362afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            } else if (!strcmp(name, "Type")) {
363afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mInitCheck = addTypeFromAttributes(attrs);
364513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                mCurrentSection =
365513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                    (mCurrentSection == SECTION_DECODER
366513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                            ? SECTION_DECODER_TYPE : SECTION_ENCODER_TYPE);
367513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
368513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
369513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        inType = false;
370513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        // fall through
371513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
372513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        case SECTION_DECODER_TYPE:
373513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        case SECTION_ENCODER_TYPE:
374513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        {
375513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            // ignore limits and features specified outside of type
37660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            bool outside = !inType && !mCurrentInfo->mHasSoleMime;
377513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            if (outside && (!strcmp(name, "Limit") || !strcmp(name, "Feature"))) {
378513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                ALOGW("ignoring %s specified outside of a Type", name);
379513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            } else if (!strcmp(name, "Limit")) {
380513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                mInitCheck = addLimit(attrs);
381513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            } else if (!strcmp(name, "Feature")) {
382513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                mInitCheck = addFeature(attrs);
383afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
384afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
385afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
386afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
387afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        default:
388afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
389afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
390afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
391afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    ++mDepth;
392afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
393afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
394afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubervoid MediaCodecList::endElementHandler(const char *name) {
395afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (mInitCheck != OK) {
396afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return;
397afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
398afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
399afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    switch (mCurrentSection) {
400afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_DECODERS:
401afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
402afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "Decoders")) {
403afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_TOPLEVEL;
404afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
405afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
406afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
407afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
408afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_ENCODERS:
409afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
410afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "Encoders")) {
411afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_TOPLEVEL;
412afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
413afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
414afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
415afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
416513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        case SECTION_DECODER_TYPE:
417513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        case SECTION_ENCODER_TYPE:
418513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        {
419513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            if (!strcmp(name, "Type")) {
420513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                mCurrentSection =
421513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                    (mCurrentSection == SECTION_DECODER_TYPE
422513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                            ? SECTION_DECODER : SECTION_ENCODER);
423513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
42460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                mCurrentInfo->complete();
425513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
426513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            break;
427513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
428513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
429afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_DECODER:
430afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
431afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "MediaCodec")) {
432afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_DECODERS;
43360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                mCurrentInfo->complete();
43460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                mCurrentInfo = NULL;
435afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
436afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
437afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
438afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
439afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_ENCODER:
440afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
441afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "MediaCodec")) {
442afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_ENCODERS;
44360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                mCurrentInfo->complete();;
44460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                mCurrentInfo = NULL;
445afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
446afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
447afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
448afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
449d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        case SECTION_INCLUDE:
450d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        {
451d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            if (!strcmp(name, "Include") && mPastSections.size() > 0) {
452d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar                mCurrentSection = mPastSections.top();
453d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar                mPastSections.pop();
454d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            }
455d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            break;
456d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        }
457d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
458afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        default:
459afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
460afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
461afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
462afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    --mDepth;
463afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
464afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
465afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberstatus_t MediaCodecList::addMediaCodecFromAttributes(
466afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        bool encoder, const char **attrs) {
467afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    const char *name = NULL;
468afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    const char *type = NULL;
469afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
470afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    size_t i = 0;
471afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    while (attrs[i] != NULL) {
472afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (!strcmp(attrs[i], "name")) {
473afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (attrs[i + 1] == NULL) {
474afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                return -EINVAL;
475afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
476afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            name = attrs[i + 1];
477afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            ++i;
478afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        } else if (!strcmp(attrs[i], "type")) {
479afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (attrs[i + 1] == NULL) {
480afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                return -EINVAL;
481afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
482afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            type = attrs[i + 1];
483afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            ++i;
484afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        } else {
485afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            return -EINVAL;
486afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
487afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
488afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        ++i;
489afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
490afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
491afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (name == NULL) {
492afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return -EINVAL;
493afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
494afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
49560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    mCurrentInfo = new MediaCodecInfo(name, encoder, type);
4966ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar    // The next step involves trying to load the codec, which may
4976ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar    // fail.  Only list the codec if this succeeds.
4986ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar    // However, keep mCurrentInfo object around until parsing
4996ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar    // of full codec info is completed.
5006ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar    if (initializeCapabilities(type) == OK) {
5016ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar        mCodecInfos.push_back(mCurrentInfo);
5026ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar    }
5036ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar    return OK;
504afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
505afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
50660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnarstatus_t MediaCodecList::initializeCapabilities(const char *type) {
5076ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar    if (type == NULL) {
5086ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar        return OK;
5096ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar    }
5106ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar
51160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    ALOGV("initializeCapabilities %s:%s",
51260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            mCurrentInfo->mName.c_str(), type);
51360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar
51460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    CodecCapabilities caps;
51560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    status_t err = QueryCodec(
51660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            mOMX,
51760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            mCurrentInfo->mName.c_str(),
51860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            type,
51960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            mCurrentInfo->mIsEncoder,
52060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            &caps);
52160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    if (err != OK) {
52260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        return err;
523afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
52460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar
52560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    return mCurrentInfo->initializeCapabilities(caps);
526afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
527afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
528afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberstatus_t MediaCodecList::addQuirk(const char **attrs) {
529afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    const char *name = NULL;
530afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
531afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    size_t i = 0;
532afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    while (attrs[i] != NULL) {
533afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (!strcmp(attrs[i], "name")) {
534afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (attrs[i + 1] == NULL) {
535afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                return -EINVAL;
536afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
537afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            name = attrs[i + 1];
538afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            ++i;
539afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        } else {
540afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            return -EINVAL;
541afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
542afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
543afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        ++i;
544afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
545afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
546afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (name == NULL) {
547afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return -EINVAL;
548afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
549afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
55060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    mCurrentInfo->addQuirk(name);
551afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    return OK;
552afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
553afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
554afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberstatus_t MediaCodecList::addTypeFromAttributes(const char **attrs) {
555afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    const char *name = NULL;
556afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
557afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    size_t i = 0;
558afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    while (attrs[i] != NULL) {
559afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (!strcmp(attrs[i], "name")) {
560afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (attrs[i + 1] == NULL) {
561afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                return -EINVAL;
562afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
563afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            name = attrs[i + 1];
564afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            ++i;
565afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        } else {
566afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            return -EINVAL;
567afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
568afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
569afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        ++i;
570afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
571afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
572afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (name == NULL) {
573afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return -EINVAL;
574afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
575afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
57660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    status_t ret = mCurrentInfo->addMime(name);
5776ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar    if (ret != OK) {
5786ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar        return ret;
579513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
5806ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar
5816ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar    // The next step involves trying to load the codec, which may
5826ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar    // fail.  Handle this gracefully (by not reporting such mime).
5836ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar    if (initializeCapabilities(name) != OK) {
5846ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar        mCurrentInfo->removeMime(name);
5856ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar    }
5866ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar    return OK;
587afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
588afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
58960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar// legacy method for non-advanced codecs
590afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberssize_t MediaCodecList::findCodecByType(
591afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        const char *type, bool encoder, size_t startIndex) const {
59260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    static const char *advancedFeatures[] = {
59360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        "feature-secure-playback",
59460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        "feature-tunneled-playback",
59560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    };
596afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
59760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    size_t numCodecs = mCodecInfos.size();
59860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    for (; startIndex < numCodecs; ++startIndex) {
59960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        const MediaCodecInfo &info = *mCodecInfos.itemAt(startIndex).get();
600afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
60160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        if (info.isEncoder() != encoder) {
60260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            continue;
60360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        }
60460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        sp<MediaCodecInfo::Capabilities> capabilities = info.getCapabilitiesFor(type);
60560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        if (capabilities == NULL) {
60660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            continue;
60760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        }
60860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        const sp<AMessage> &details = capabilities->getDetails();
609afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
61060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        int32_t required;
61160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        bool isAdvanced = false;
61260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        for (size_t ix = 0; ix < ARRAY_SIZE(advancedFeatures); ix++) {
61360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            if (details->findInt32(advancedFeatures[ix], &required) &&
61460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    required != 0) {
61560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                isAdvanced = true;
61660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                break;
61760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            }
61860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        }
619afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
62060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        if (!isAdvanced) {
621afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            return startIndex;
622afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
623afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
624afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
625afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    return -ENOENT;
626afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
627afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
628513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatic status_t limitFoundMissingAttr(AString name, const char *attr, bool found = true) {
629513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    ALOGE("limit '%s' with %s'%s' attribute", name.c_str(),
630513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            (found ? "" : "no "), attr);
631513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    return -EINVAL;
632513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar}
633513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
634513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatic status_t limitError(AString name, const char *msg) {
635513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    ALOGE("limit '%s' %s", name.c_str(), msg);
636513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    return -EINVAL;
637513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar}
638513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
639513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatic status_t limitInvalidAttr(AString name, const char *attr, AString value) {
640513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    ALOGE("limit '%s' with invalid '%s' attribute (%s)", name.c_str(),
641513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            attr, value.c_str());
642513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    return -EINVAL;
643513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar}
644513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
645513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatus_t MediaCodecList::addLimit(const char **attrs) {
646513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    sp<AMessage> msg = new AMessage();
647513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
648513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    size_t i = 0;
649513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    while (attrs[i] != NULL) {
650513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (attrs[i + 1] == NULL) {
651513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return -EINVAL;
652513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
653513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
654513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        // attributes with values
655513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (!strcmp(attrs[i], "name")
656513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "default")
657513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "in")
658513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "max")
659513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "min")
660513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "range")
661513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "ranges")
662513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "scale")
663513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "value")) {
664513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            msg->setString(attrs[i], attrs[i + 1]);
665513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            ++i;
666513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else {
667513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return -EINVAL;
668513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
669513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        ++i;
670513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
671513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
672513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    AString name;
673513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    if (!msg->findString("name", &name)) {
674513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        ALOGE("limit with no 'name' attribute");
675513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        return -EINVAL;
676513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
677513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
678513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    // size, blocks, bitrate, frame-rate, blocks-per-second, aspect-ratio: range
679513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    // quality: range + default + [scale]
680513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    // complexity: range + default
681513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    bool found;
68260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar
683513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    if (name == "aspect-ratio" || name == "bitrate" || name == "block-count"
684513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            || name == "blocks-per-second" || name == "complexity"
685513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            || name == "frame-rate" || name == "quality" || name == "size") {
686513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        AString min, max;
687513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (msg->findString("min", &min) && msg->findString("max", &max)) {
688513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            min.append("-");
689513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            min.append(max);
690513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            if (msg->contains("range") || msg->contains("value")) {
691513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                return limitError(name, "has 'min' and 'max' as well as 'range' or "
692513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                        "'value' attributes");
693513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
694513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            msg->setString("range", min);
695513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (msg->contains("min") || msg->contains("max")) {
696513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitError(name, "has only 'min' or 'max' attribute");
697513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (msg->findString("value", &max)) {
698513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            min = max;
699513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            min.append("-");
700513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            min.append(max);
701513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            if (msg->contains("range")) {
702513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                return limitError(name, "has both 'range' and 'value' attributes");
703513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
704513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            msg->setString("range", min);
705513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
706513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
707513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        AString range, scale = "linear", def, in_;
708513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (!msg->findString("range", &range)) {
709513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitError(name, "with no 'range', 'value' or 'min'/'max' attributes");
710513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
711513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
712513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if ((name == "quality" || name == "complexity") ^
713513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                (found = msg->findString("default", &def))) {
714513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "default", found);
715513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
716513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (name != "quality" && msg->findString("scale", &scale)) {
717513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "scale");
718513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
719513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if ((name == "aspect-ratio") ^ (found = msg->findString("in", &in_))) {
720513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "in", found);
721513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
722513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
723513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (name == "aspect-ratio") {
724513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            if (!(in_ == "pixels") && !(in_ == "blocks")) {
725513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                return limitInvalidAttr(name, "in", in_);
726513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
727513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            in_.erase(5, 1); // (pixel|block)-aspect-ratio
728513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            in_.append("-");
729513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            in_.append(name);
730513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            name = in_;
731513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
732513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (name == "quality") {
73360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            mCurrentInfo->addDetail("quality-scale", scale);
734513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
735513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (name == "quality" || name == "complexity") {
736513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            AString tag = name;
737513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            tag.append("-default");
73860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            mCurrentInfo->addDetail(tag, def);
739513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
740513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        AString tag = name;
741513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        tag.append("-range");
74260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        mCurrentInfo->addDetail(tag, range);
743513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    } else {
744513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        AString max, value, ranges;
745513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (msg->contains("default")) {
746513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "default");
747513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (msg->contains("in")) {
748513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "in");
749513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if ((name == "channel-count") ^
750513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                (found = msg->findString("max", &max))) {
751513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "max", found);
752513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (msg->contains("min")) {
753513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "min");
754513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (msg->contains("range")) {
755513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "range");
756513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if ((name == "sample-rate") ^
757513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                (found = msg->findString("ranges", &ranges))) {
758513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "ranges", found);
759513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (msg->contains("scale")) {
760513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "scale");
761513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if ((name == "alignment" || name == "block-size") ^
762513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                (found = msg->findString("value", &value))) {
763513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "value", found);
764513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
765513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
766513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (max.size()) {
767513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            AString tag = "max-";
768513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            tag.append(name);
76960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            mCurrentInfo->addDetail(tag, max);
770513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (value.size()) {
77160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            mCurrentInfo->addDetail(name, value);
772513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (ranges.size()) {
773513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            AString tag = name;
774513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            tag.append("-ranges");
77560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            mCurrentInfo->addDetail(tag, ranges);
776513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else {
777513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            ALOGW("Ignoring unrecognized limit '%s'", name.c_str());
778513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
779513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
780513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    return OK;
781513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar}
782513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
783513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatic bool parseBoolean(const char *s) {
784513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    if (!strcasecmp(s, "true") || !strcasecmp(s, "yes") || !strcasecmp(s, "y")) {
785513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        return true;
786513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
787513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    char *end;
788513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    unsigned long res = strtoul(s, &end, 10);
789513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    return *s != '\0' && *end == '\0' && res > 0;
790513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar}
791513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
792513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatus_t MediaCodecList::addFeature(const char **attrs) {
793513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    size_t i = 0;
794513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    const char *name = NULL;
795513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    int32_t optional = -1;
796513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    int32_t required = -1;
797732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar    const char *value = NULL;
798513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
799513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    while (attrs[i] != NULL) {
800513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (attrs[i + 1] == NULL) {
801513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return -EINVAL;
802513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
803513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
804513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        // attributes with values
805513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (!strcmp(attrs[i], "name")) {
806513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            name = attrs[i + 1];
807513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            ++i;
808513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (!strcmp(attrs[i], "optional") || !strcmp(attrs[i], "required")) {
809513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            int value = (int)parseBoolean(attrs[i + 1]);
810513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            if (!strcmp(attrs[i], "optional")) {
811513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                optional = value;
812513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            } else {
813513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                required = value;
814513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
815513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            ++i;
816732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar        } else if (!strcmp(attrs[i], "value")) {
817732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar            value = attrs[i + 1];
818732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar            ++i;
819513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else {
820513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return -EINVAL;
821513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
822513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        ++i;
823513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
824513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    if (name == NULL) {
825513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        ALOGE("feature with no 'name' attribute");
826513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        return -EINVAL;
827513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
828513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
829513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    if (optional == required && optional != -1) {
830513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        ALOGE("feature '%s' is both/neither optional and required", name);
831513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        return -EINVAL;
832513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
833513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
834732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar    if ((optional != -1 || required != -1) && (value != NULL)) {
835732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar        ALOGE("feature '%s' has both a value and optional/required attribute", name);
836732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar        return -EINVAL;
837732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar    }
838732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar
839732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar    if (value != NULL) {
840732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar        mCurrentInfo->addFeature(name, value);
841732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar    } else {
842732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar        mCurrentInfo->addFeature(name, (required == 1) || (optional == 0));
843732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar    }
844513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    return OK;
845513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar}
846513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
847afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberssize_t MediaCodecList::findCodecByName(const char *name) const {
848afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    for (size_t i = 0; i < mCodecInfos.size(); ++i) {
84960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        const MediaCodecInfo &info = *mCodecInfos.itemAt(i).get();
850afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
851afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (info.mName == name) {
852afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            return i;
853afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
854afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
855afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
856afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    return -ENOENT;
857afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
858afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
85969829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Hubersize_t MediaCodecList::countCodecs() const {
86069829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    return mCodecInfos.size();
86169829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber}
86269829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
863afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}  // namespace android
864