MediaCodecList.cpp revision 60b1c0e79d12a1c70758bc8d060156924635f8ba
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
6560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar// static
6660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnarsp<IMediaCodecList> MediaCodecList::getInstance() {
6760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    return getLocalInstance();
68afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
69afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
70afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas HuberMediaCodecList::MediaCodecList()
71afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    : mInitCheck(NO_INIT) {
72d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    parseTopLevelXMLFile("/etc/media_codecs.xml");
73d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar}
74afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
75d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnarvoid MediaCodecList::parseTopLevelXMLFile(const char *codecs_xml) {
76d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    // get href_base
77d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    char *href_base_end = strrchr(codecs_xml, '/');
78d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    if (href_base_end != NULL) {
79d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        mHrefBase = AString(codecs_xml, href_base_end - codecs_xml + 1);
80d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    }
81d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
8260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    mInitCheck = OK; // keeping this here for safety
83d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    mCurrentSection = SECTION_TOPLEVEL;
84d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    mDepth = 0;
85d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
8660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    OMXClient client;
8760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    mInitCheck = client.connect();
8860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    if (mInitCheck != OK) {
8960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        return;
9060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    }
9160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    mOMX = client.interface();
92d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    parseXMLFile(codecs_xml);
9360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    mOMX.clear();
94d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
95d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    if (mInitCheck != OK) {
96d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        mCodecInfos.clear();
97afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return;
98afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
99afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
100d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    for (size_t i = mCodecInfos.size(); i-- > 0;) {
10160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        const MediaCodecInfo &info = *mCodecInfos.itemAt(i).get();
102afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
10360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        if (info.mCaps.size() == 0) {
104d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            // No types supported by this component???
105d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            ALOGW("Component %s does not support any type of media?",
10660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                  info.mName.c_str());
107ecdd39c5af016e2fa57cbfd837aa670b706dabd3Andreas Huber
108d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            mCodecInfos.removeAt(i);
109513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar#if LOG_NDEBUG == 0
110513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else {
11160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            for (size_t type_ix = 0; type_ix < info.mCaps.size(); ++type_ix) {
11260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                AString mime = info.mCaps.keyAt(type_ix);
11360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                const sp<MediaCodecInfo::Capabilities> &caps = info.mCaps.valueAt(type_ix);
11460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar
11560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                ALOGV("%s codec info for %s: %s", info.mName.c_str(), mime.c_str(),
11660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                        caps->getDetails()->debugString().c_str());
11760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                ALOGV("    flags=%d", caps->getFlags());
11860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                {
11960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    Vector<uint32_t> colorFormats;
12060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    caps->getSupportedColorFormats(&colorFormats);
12160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    AString nice;
12260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    for (size_t ix = 0; ix < colorFormats.size(); ix++) {
12360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                        if (ix > 0) {
12460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                            nice.append(", ");
12560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                        }
12660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                        nice.append(colorFormats.itemAt(ix));
12760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    }
12860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    ALOGV("    colors=[%s]", nice.c_str());
12960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                }
13060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                {
13160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    Vector<MediaCodecInfo::ProfileLevel> profileLevels;
13260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    caps->getSupportedProfileLevels(&profileLevels);
13360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    AString nice;
13460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    for (size_t ix = 0; ix < profileLevels.size(); ix++) {
13560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                        if (ix > 0) {
13660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                            nice.append(", ");
13760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                        }
13860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                        const MediaCodecInfo::ProfileLevel &pl =
13960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                            profileLevels.itemAt(ix);
14060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                        nice.append(pl.mProfile);
14160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                        nice.append("/");
14260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                        nice.append(pl.mLevel);
14360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    }
14460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    ALOGV("    levels=[%s]", nice.c_str());
145513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                }
146513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
147513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar#endif
148d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        }
149afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
150afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
151afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#if 0
152afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    for (size_t i = 0; i < mCodecInfos.size(); ++i) {
153afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        const CodecInfo &info = mCodecInfos.itemAt(i);
154afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
155afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        AString line = info.mName;
156afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        line.append(" supports ");
157afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        for (size_t j = 0; j < mTypes.size(); ++j) {
158afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            uint32_t value = mTypes.valueAt(j);
159afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
160afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (info.mTypes & (1ul << value)) {
161afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                line.append(mTypes.keyAt(j));
162afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                line.append(" ");
163afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
164afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
165afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
166afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        ALOGI("%s", line.c_str());
167afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
168afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#endif
169afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
170afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
171afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas HuberMediaCodecList::~MediaCodecList() {
172afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
173afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
174afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberstatus_t MediaCodecList::initCheck() const {
175afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    return mInitCheck;
176afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
177afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
178d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnarvoid MediaCodecList::parseXMLFile(const char *path) {
179d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    FILE *file = fopen(path, "r");
180d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
181d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    if (file == NULL) {
182d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        ALOGW("unable to open media codecs configuration xml file: %s", path);
183d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        mInitCheck = NAME_NOT_FOUND;
184d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        return;
185d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    }
186afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
187afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    XML_Parser parser = ::XML_ParserCreate(NULL);
188afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    CHECK(parser != NULL);
189afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
190afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    ::XML_SetUserData(parser, this);
191afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    ::XML_SetElementHandler(
192afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            parser, StartElementHandlerWrapper, EndElementHandlerWrapper);
193afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
194afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    const int BUFF_SIZE = 512;
195afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    while (mInitCheck == OK) {
196afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        void *buff = ::XML_GetBuffer(parser, BUFF_SIZE);
197afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (buff == NULL) {
198d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            ALOGE("failed in call to XML_GetBuffer()");
199afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            mInitCheck = UNKNOWN_ERROR;
200afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
201afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
202afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
203afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        int bytes_read = ::fread(buff, 1, BUFF_SIZE, file);
204afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (bytes_read < 0) {
205afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            ALOGE("failed in call to read");
206afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            mInitCheck = ERROR_IO;
207afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
208afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
209afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
210d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        XML_Status status = ::XML_ParseBuffer(parser, bytes_read, bytes_read == 0);
211d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        if (status != XML_STATUS_OK) {
212d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            ALOGE("malformed (%s)", ::XML_ErrorString(::XML_GetErrorCode(parser)));
213afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            mInitCheck = ERROR_MALFORMED;
214afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
215afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
216afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
217afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (bytes_read == 0) {
218afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
219afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
220afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
221afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
222afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    ::XML_ParserFree(parser);
223afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
224d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    fclose(file);
225d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    file = NULL;
226afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
227afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
228afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber// static
229afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubervoid MediaCodecList::StartElementHandlerWrapper(
230afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        void *me, const char *name, const char **attrs) {
231afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    static_cast<MediaCodecList *>(me)->startElementHandler(name, attrs);
232afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
233afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
234afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber// static
235afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubervoid MediaCodecList::EndElementHandlerWrapper(void *me, const char *name) {
236afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    static_cast<MediaCodecList *>(me)->endElementHandler(name);
237afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
238afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
239d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnarstatus_t MediaCodecList::includeXMLFile(const char **attrs) {
240d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    const char *href = NULL;
241d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    size_t i = 0;
242d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    while (attrs[i] != NULL) {
243d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        if (!strcmp(attrs[i], "href")) {
244d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            if (attrs[i + 1] == NULL) {
245d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar                return -EINVAL;
246d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            }
247d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            href = attrs[i + 1];
248d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            ++i;
249d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        } else {
250d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            return -EINVAL;
251d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        }
252d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        ++i;
253d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    }
254d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
255d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    // For security reasons and for simplicity, file names can only contain
256d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    // [a-zA-Z0-9_.] and must start with  media_codecs_ and end with .xml
257d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    for (i = 0; href[i] != '\0'; i++) {
258d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        if (href[i] == '.' || href[i] == '_' ||
259d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar                (href[i] >= '0' && href[i] <= '9') ||
260d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar                (href[i] >= 'A' && href[i] <= 'Z') ||
261d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar                (href[i] >= 'a' && href[i] <= 'z')) {
262d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            continue;
263d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        }
264d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        ALOGE("invalid include file name: %s", href);
265d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        return -EINVAL;
266d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    }
267d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
268d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    AString filename = href;
269d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    if (!filename.startsWith("media_codecs_") ||
270d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        !filename.endsWith(".xml")) {
271d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        ALOGE("invalid include file name: %s", href);
272d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        return -EINVAL;
273d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    }
274d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    filename.insert(mHrefBase, 0);
275d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
276d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    parseXMLFile(filename.c_str());
277d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    return mInitCheck;
278d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar}
279d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
280afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubervoid MediaCodecList::startElementHandler(
281afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        const char *name, const char **attrs) {
282afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (mInitCheck != OK) {
283afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return;
284afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
285afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
286513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    bool inType = true;
287513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
288d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    if (!strcmp(name, "Include")) {
289d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        mInitCheck = includeXMLFile(attrs);
290d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        if (mInitCheck == OK) {
291d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            mPastSections.push(mCurrentSection);
292d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            mCurrentSection = SECTION_INCLUDE;
293d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        }
294d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        ++mDepth;
295d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        return;
296d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    }
297d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
298afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    switch (mCurrentSection) {
299afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_TOPLEVEL:
300afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
301afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "Decoders")) {
302afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_DECODERS;
303afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            } else if (!strcmp(name, "Encoders")) {
304afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_ENCODERS;
305afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
306afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
307afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
308afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
309afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_DECODERS:
310afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
311afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "MediaCodec")) {
312afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mInitCheck =
313afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                    addMediaCodecFromAttributes(false /* encoder */, attrs);
314afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
315afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_DECODER;
316afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
317afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
318afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
319afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
320afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_ENCODERS:
321afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
322afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "MediaCodec")) {
323afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mInitCheck =
324afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                    addMediaCodecFromAttributes(true /* encoder */, attrs);
325afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
326afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_ENCODER;
327afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
328afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
329afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
330afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
331afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_DECODER:
332afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_ENCODER:
333afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
334afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "Quirk")) {
335afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mInitCheck = addQuirk(attrs);
336afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            } else if (!strcmp(name, "Type")) {
337afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mInitCheck = addTypeFromAttributes(attrs);
338513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                mCurrentSection =
339513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                    (mCurrentSection == SECTION_DECODER
340513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                            ? SECTION_DECODER_TYPE : SECTION_ENCODER_TYPE);
341513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
342513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
343513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        inType = false;
344513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        // fall through
345513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
346513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        case SECTION_DECODER_TYPE:
347513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        case SECTION_ENCODER_TYPE:
348513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        {
349513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            // ignore limits and features specified outside of type
35060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            bool outside = !inType && !mCurrentInfo->mHasSoleMime;
351513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            if (outside && (!strcmp(name, "Limit") || !strcmp(name, "Feature"))) {
352513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                ALOGW("ignoring %s specified outside of a Type", name);
353513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            } else if (!strcmp(name, "Limit")) {
354513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                mInitCheck = addLimit(attrs);
355513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            } else if (!strcmp(name, "Feature")) {
356513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                mInitCheck = addFeature(attrs);
357afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
358afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
359afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
360afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
361afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        default:
362afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
363afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
364afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
365afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    ++mDepth;
366afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
367afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
368afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubervoid MediaCodecList::endElementHandler(const char *name) {
369afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (mInitCheck != OK) {
370afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return;
371afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
372afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
373afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    switch (mCurrentSection) {
374afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_DECODERS:
375afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
376afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "Decoders")) {
377afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_TOPLEVEL;
378afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
379afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
380afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
381afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
382afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_ENCODERS:
383afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
384afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "Encoders")) {
385afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_TOPLEVEL;
386afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
387afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
388afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
389afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
390513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        case SECTION_DECODER_TYPE:
391513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        case SECTION_ENCODER_TYPE:
392513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        {
393513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            if (!strcmp(name, "Type")) {
394513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                mCurrentSection =
395513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                    (mCurrentSection == SECTION_DECODER_TYPE
396513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                            ? SECTION_DECODER : SECTION_ENCODER);
397513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
39860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                mCurrentInfo->complete();
399513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
400513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            break;
401513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
402513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
403afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_DECODER:
404afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
405afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "MediaCodec")) {
406afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_DECODERS;
40760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                mCurrentInfo->complete();
40860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                mCurrentInfo = NULL;
409afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
410afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
411afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
412afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
413afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_ENCODER:
414afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
415afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "MediaCodec")) {
416afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_ENCODERS;
41760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                mCurrentInfo->complete();;
41860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                mCurrentInfo = NULL;
419afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
420afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
421afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
422afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
423d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        case SECTION_INCLUDE:
424d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        {
425d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            if (!strcmp(name, "Include") && mPastSections.size() > 0) {
426d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar                mCurrentSection = mPastSections.top();
427d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar                mPastSections.pop();
428d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            }
429d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            break;
430d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        }
431d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
432afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        default:
433afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
434afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
435afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
436afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    --mDepth;
437afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
438afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
439afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberstatus_t MediaCodecList::addMediaCodecFromAttributes(
440afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        bool encoder, const char **attrs) {
441afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    const char *name = NULL;
442afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    const char *type = NULL;
443afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
444afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    size_t i = 0;
445afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    while (attrs[i] != NULL) {
446afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (!strcmp(attrs[i], "name")) {
447afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (attrs[i + 1] == NULL) {
448afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                return -EINVAL;
449afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
450afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            name = attrs[i + 1];
451afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            ++i;
452afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        } else if (!strcmp(attrs[i], "type")) {
453afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (attrs[i + 1] == NULL) {
454afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                return -EINVAL;
455afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
456afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            type = attrs[i + 1];
457afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            ++i;
458afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        } else {
459afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            return -EINVAL;
460afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
461afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
462afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        ++i;
463afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
464afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
465afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (name == NULL) {
466afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return -EINVAL;
467afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
468afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
46960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    mCurrentInfo = new MediaCodecInfo(name, encoder, type);
47060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    mCodecInfos.push_back(mCurrentInfo);
47160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    return initializeCapabilities(type);
472afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
473afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
47460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnarstatus_t MediaCodecList::initializeCapabilities(const char *type) {
47560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    ALOGV("initializeCapabilities %s:%s",
47660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            mCurrentInfo->mName.c_str(), type);
47760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar
47860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    CodecCapabilities caps;
47960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    status_t err = QueryCodec(
48060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            mOMX,
48160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            mCurrentInfo->mName.c_str(),
48260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            type,
48360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            mCurrentInfo->mIsEncoder,
48460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            &caps);
48560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    if (err != OK) {
48660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        return err;
487afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
48860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar
48960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    return mCurrentInfo->initializeCapabilities(caps);
490afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
491afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
492afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberstatus_t MediaCodecList::addQuirk(const char **attrs) {
493afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    const char *name = NULL;
494afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
495afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    size_t i = 0;
496afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    while (attrs[i] != NULL) {
497afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (!strcmp(attrs[i], "name")) {
498afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (attrs[i + 1] == NULL) {
499afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                return -EINVAL;
500afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
501afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            name = attrs[i + 1];
502afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            ++i;
503afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        } else {
504afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            return -EINVAL;
505afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
506afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
507afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        ++i;
508afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
509afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
510afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (name == NULL) {
511afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return -EINVAL;
512afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
513afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
51460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    mCurrentInfo->addQuirk(name);
515afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    return OK;
516afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
517afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
518afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberstatus_t MediaCodecList::addTypeFromAttributes(const char **attrs) {
519afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    const char *name = NULL;
520afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
521afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    size_t i = 0;
522afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    while (attrs[i] != NULL) {
523afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (!strcmp(attrs[i], "name")) {
524afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (attrs[i + 1] == NULL) {
525afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                return -EINVAL;
526afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
527afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            name = attrs[i + 1];
528afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            ++i;
529afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        } else {
530afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            return -EINVAL;
531afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
532afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
533afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        ++i;
534afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
535afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
536afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (name == NULL) {
537afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return -EINVAL;
538afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
539afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
54060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    status_t ret = mCurrentInfo->addMime(name);
54160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    if (ret == OK) {
54260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        ret = initializeCapabilities(name);
543513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
54460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    return ret;
545afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
546afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
54760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar// legacy method for non-advanced codecs
548afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberssize_t MediaCodecList::findCodecByType(
549afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        const char *type, bool encoder, size_t startIndex) const {
55060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    static const char *advancedFeatures[] = {
55160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        "feature-secure-playback",
55260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        "feature-tunneled-playback",
55360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    };
554afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
55560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    size_t numCodecs = mCodecInfos.size();
55660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    for (; startIndex < numCodecs; ++startIndex) {
55760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        const MediaCodecInfo &info = *mCodecInfos.itemAt(startIndex).get();
558afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
55960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        if (info.isEncoder() != encoder) {
56060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            continue;
56160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        }
56260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        sp<MediaCodecInfo::Capabilities> capabilities = info.getCapabilitiesFor(type);
56360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        if (capabilities == NULL) {
56460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            continue;
56560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        }
56660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        const sp<AMessage> &details = capabilities->getDetails();
567afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
56860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        int32_t required;
56960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        bool isAdvanced = false;
57060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        for (size_t ix = 0; ix < ARRAY_SIZE(advancedFeatures); ix++) {
57160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            if (details->findInt32(advancedFeatures[ix], &required) &&
57260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                    required != 0) {
57360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                isAdvanced = true;
57460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar                break;
57560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            }
57660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        }
577afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
57860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        if (!isAdvanced) {
579afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            return startIndex;
580afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
581afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
582afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
583afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    return -ENOENT;
584afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
585afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
586513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatic status_t limitFoundMissingAttr(AString name, const char *attr, bool found = true) {
587513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    ALOGE("limit '%s' with %s'%s' attribute", name.c_str(),
588513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            (found ? "" : "no "), attr);
589513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    return -EINVAL;
590513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar}
591513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
592513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatic status_t limitError(AString name, const char *msg) {
593513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    ALOGE("limit '%s' %s", name.c_str(), msg);
594513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    return -EINVAL;
595513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar}
596513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
597513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatic status_t limitInvalidAttr(AString name, const char *attr, AString value) {
598513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    ALOGE("limit '%s' with invalid '%s' attribute (%s)", name.c_str(),
599513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            attr, value.c_str());
600513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    return -EINVAL;
601513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar}
602513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
603513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatus_t MediaCodecList::addLimit(const char **attrs) {
604513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    sp<AMessage> msg = new AMessage();
605513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
606513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    size_t i = 0;
607513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    while (attrs[i] != NULL) {
608513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (attrs[i + 1] == NULL) {
609513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return -EINVAL;
610513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
611513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
612513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        // attributes with values
613513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (!strcmp(attrs[i], "name")
614513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "default")
615513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "in")
616513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "max")
617513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "min")
618513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "range")
619513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "ranges")
620513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "scale")
621513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "value")) {
622513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            msg->setString(attrs[i], attrs[i + 1]);
623513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            ++i;
624513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else {
625513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return -EINVAL;
626513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
627513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        ++i;
628513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
629513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
630513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    AString name;
631513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    if (!msg->findString("name", &name)) {
632513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        ALOGE("limit with no 'name' attribute");
633513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        return -EINVAL;
634513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
635513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
636513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    // size, blocks, bitrate, frame-rate, blocks-per-second, aspect-ratio: range
637513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    // quality: range + default + [scale]
638513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    // complexity: range + default
639513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    bool found;
64060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar
641513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    if (name == "aspect-ratio" || name == "bitrate" || name == "block-count"
642513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            || name == "blocks-per-second" || name == "complexity"
643513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            || name == "frame-rate" || name == "quality" || name == "size") {
644513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        AString min, max;
645513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (msg->findString("min", &min) && msg->findString("max", &max)) {
646513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            min.append("-");
647513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            min.append(max);
648513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            if (msg->contains("range") || msg->contains("value")) {
649513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                return limitError(name, "has 'min' and 'max' as well as 'range' or "
650513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                        "'value' attributes");
651513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
652513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            msg->setString("range", min);
653513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (msg->contains("min") || msg->contains("max")) {
654513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitError(name, "has only 'min' or 'max' attribute");
655513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (msg->findString("value", &max)) {
656513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            min = max;
657513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            min.append("-");
658513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            min.append(max);
659513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            if (msg->contains("range")) {
660513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                return limitError(name, "has both 'range' and 'value' attributes");
661513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
662513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            msg->setString("range", min);
663513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
664513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
665513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        AString range, scale = "linear", def, in_;
666513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (!msg->findString("range", &range)) {
667513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitError(name, "with no 'range', 'value' or 'min'/'max' attributes");
668513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
669513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
670513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if ((name == "quality" || name == "complexity") ^
671513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                (found = msg->findString("default", &def))) {
672513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "default", found);
673513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
674513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (name != "quality" && msg->findString("scale", &scale)) {
675513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "scale");
676513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
677513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if ((name == "aspect-ratio") ^ (found = msg->findString("in", &in_))) {
678513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "in", found);
679513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
680513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
681513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (name == "aspect-ratio") {
682513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            if (!(in_ == "pixels") && !(in_ == "blocks")) {
683513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                return limitInvalidAttr(name, "in", in_);
684513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
685513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            in_.erase(5, 1); // (pixel|block)-aspect-ratio
686513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            in_.append("-");
687513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            in_.append(name);
688513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            name = in_;
689513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
690513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (name == "quality") {
69160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            mCurrentInfo->addDetail("quality-scale", scale);
692513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
693513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (name == "quality" || name == "complexity") {
694513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            AString tag = name;
695513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            tag.append("-default");
69660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            mCurrentInfo->addDetail(tag, def);
697513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
698513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        AString tag = name;
699513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        tag.append("-range");
70060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        mCurrentInfo->addDetail(tag, range);
701513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    } else {
702513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        AString max, value, ranges;
703513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (msg->contains("default")) {
704513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "default");
705513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (msg->contains("in")) {
706513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "in");
707513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if ((name == "channel-count") ^
708513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                (found = msg->findString("max", &max))) {
709513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "max", found);
710513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (msg->contains("min")) {
711513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "min");
712513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (msg->contains("range")) {
713513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "range");
714513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if ((name == "sample-rate") ^
715513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                (found = msg->findString("ranges", &ranges))) {
716513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "ranges", found);
717513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (msg->contains("scale")) {
718513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "scale");
719513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if ((name == "alignment" || name == "block-size") ^
720513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                (found = msg->findString("value", &value))) {
721513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "value", found);
722513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
723513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
724513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (max.size()) {
725513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            AString tag = "max-";
726513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            tag.append(name);
72760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            mCurrentInfo->addDetail(tag, max);
728513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (value.size()) {
72960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            mCurrentInfo->addDetail(name, value);
730513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (ranges.size()) {
731513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            AString tag = name;
732513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            tag.append("-ranges");
73360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar            mCurrentInfo->addDetail(tag, ranges);
734513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else {
735513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            ALOGW("Ignoring unrecognized limit '%s'", name.c_str());
736513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
737513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
738513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    return OK;
739513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar}
740513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
741513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatic bool parseBoolean(const char *s) {
742513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    if (!strcasecmp(s, "true") || !strcasecmp(s, "yes") || !strcasecmp(s, "y")) {
743513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        return true;
744513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
745513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    char *end;
746513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    unsigned long res = strtoul(s, &end, 10);
747513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    return *s != '\0' && *end == '\0' && res > 0;
748513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar}
749513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
750513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatus_t MediaCodecList::addFeature(const char **attrs) {
751513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    size_t i = 0;
752513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    const char *name = NULL;
753513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    int32_t optional = -1;
754513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    int32_t required = -1;
755513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
756513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    while (attrs[i] != NULL) {
757513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (attrs[i + 1] == NULL) {
758513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return -EINVAL;
759513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
760513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
761513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        // attributes with values
762513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (!strcmp(attrs[i], "name")) {
763513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            name = attrs[i + 1];
764513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            ++i;
765513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (!strcmp(attrs[i], "optional") || !strcmp(attrs[i], "required")) {
766513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            int value = (int)parseBoolean(attrs[i + 1]);
767513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            if (!strcmp(attrs[i], "optional")) {
768513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                optional = value;
769513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            } else {
770513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                required = value;
771513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
772513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            ++i;
773513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else {
774513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return -EINVAL;
775513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
776513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        ++i;
777513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
778513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    if (name == NULL) {
779513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        ALOGE("feature with no 'name' attribute");
780513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        return -EINVAL;
781513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
782513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
783513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    if (optional == required && optional != -1) {
784513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        ALOGE("feature '%s' is both/neither optional and required", name);
785513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        return -EINVAL;
786513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
787513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
78860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar    mCurrentInfo->addFeature(name, (required == 1) || (optional == 0));
789513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    return OK;
790513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar}
791513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
792afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberssize_t MediaCodecList::findCodecByName(const char *name) const {
793afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    for (size_t i = 0; i < mCodecInfos.size(); ++i) {
79460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar        const MediaCodecInfo &info = *mCodecInfos.itemAt(i).get();
795afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
796afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (info.mName == name) {
797afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            return i;
798afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
799afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
800afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
801afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    return -ENOENT;
802afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
803afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
80469829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Hubersize_t MediaCodecList::countCodecs() const {
80569829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    return mCodecInfos.size();
80669829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber}
80769829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
808afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}  // namespace android
809