MediaCodecList.cpp revision 513d967dae82cd03e67bff17b927cf869d9bc43e
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
21afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#include <media/stagefright/MediaCodecList.h>
22afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
23afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#include <media/stagefright/foundation/ADebug.h>
24513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar#include <media/stagefright/foundation/AMessage.h>
25afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#include <media/stagefright/MediaErrors.h>
2669829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber#include <media/stagefright/OMXClient.h>
2769829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber#include <media/stagefright/OMXCodec.h>
28afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#include <utils/threads.h>
29afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
30e8057dd8208f0a185109992339a995c518b12780Elliott Hughes#include <libexpat/expat.h>
31afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
32afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubernamespace android {
33afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
34afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberstatic Mutex sInitMutex;
35afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
36afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber// static
37afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas HuberMediaCodecList *MediaCodecList::sCodecList;
38afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
39afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber// static
40afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberconst MediaCodecList *MediaCodecList::getInstance() {
41afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    Mutex::Autolock autoLock(sInitMutex);
42afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
43afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (sCodecList == NULL) {
44afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        sCodecList = new MediaCodecList;
45afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
46afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
47afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    return sCodecList->initCheck() == OK ? sCodecList : NULL;
48afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
49afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
50afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas HuberMediaCodecList::MediaCodecList()
51afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    : mInitCheck(NO_INIT) {
52d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    parseTopLevelXMLFile("/etc/media_codecs.xml");
53d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar}
54afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
55d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnarvoid MediaCodecList::parseTopLevelXMLFile(const char *codecs_xml) {
56d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    // get href_base
57d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    char *href_base_end = strrchr(codecs_xml, '/');
58d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    if (href_base_end != NULL) {
59d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        mHrefBase = AString(codecs_xml, href_base_end - codecs_xml + 1);
60d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    }
61d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
62d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    mInitCheck = OK;
63d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    mCurrentSection = SECTION_TOPLEVEL;
64d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    mDepth = 0;
65d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
66d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    parseXMLFile(codecs_xml);
67d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
68d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    if (mInitCheck != OK) {
69d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        mCodecInfos.clear();
70d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        mCodecQuirks.clear();
71afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return;
72afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
73afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
74d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    for (size_t i = mCodecInfos.size(); i-- > 0;) {
75d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        CodecInfo *info = &mCodecInfos.editItemAt(i);
76afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
77d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        if (info->mTypes == 0) {
78d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            // No types supported by this component???
79d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            ALOGW("Component %s does not support any type of media?",
80d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar                  info->mName.c_str());
81ecdd39c5af016e2fa57cbfd837aa670b706dabd3Andreas Huber
82d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            mCodecInfos.removeAt(i);
83513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar#if LOG_NDEBUG == 0
84513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else {
85513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            for (size_t type_ix = 0; type_ix < mTypes.size(); ++type_ix) {
86513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                uint32_t typeMask = 1ul << mTypes.valueAt(type_ix);
87513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                if (info->mTypes & typeMask) {
88513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                    AString mime = mTypes.keyAt(type_ix);
89513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                    uint32_t bit = mTypes.valueAt(type_ix);
90513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
91513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                    ALOGV("%s codec info for %s: %s", info->mName.c_str(), mime.c_str(),
92513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                            info->mCaps.editValueFor(bit)->debugString().c_str());
93513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                }
94513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
95513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar#endif
96d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        }
97afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
98afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
99afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#if 0
100afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    for (size_t i = 0; i < mCodecInfos.size(); ++i) {
101afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        const CodecInfo &info = mCodecInfos.itemAt(i);
102afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
103afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        AString line = info.mName;
104afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        line.append(" supports ");
105afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        for (size_t j = 0; j < mTypes.size(); ++j) {
106afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            uint32_t value = mTypes.valueAt(j);
107afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
108afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (info.mTypes & (1ul << value)) {
109afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                line.append(mTypes.keyAt(j));
110afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                line.append(" ");
111afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
112afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
113afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
114afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        ALOGI("%s", line.c_str());
115afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
116afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#endif
117afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
118afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
119afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas HuberMediaCodecList::~MediaCodecList() {
120afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
121afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
122afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberstatus_t MediaCodecList::initCheck() const {
123afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    return mInitCheck;
124afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
125afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
126d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnarvoid MediaCodecList::parseXMLFile(const char *path) {
127d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    FILE *file = fopen(path, "r");
128d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
129d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    if (file == NULL) {
130d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        ALOGW("unable to open media codecs configuration xml file: %s", path);
131d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        mInitCheck = NAME_NOT_FOUND;
132d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        return;
133d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    }
134afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
135afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    XML_Parser parser = ::XML_ParserCreate(NULL);
136afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    CHECK(parser != NULL);
137afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
138afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    ::XML_SetUserData(parser, this);
139afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    ::XML_SetElementHandler(
140afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            parser, StartElementHandlerWrapper, EndElementHandlerWrapper);
141afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
142afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    const int BUFF_SIZE = 512;
143afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    while (mInitCheck == OK) {
144afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        void *buff = ::XML_GetBuffer(parser, BUFF_SIZE);
145afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (buff == NULL) {
146d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            ALOGE("failed in call to XML_GetBuffer()");
147afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            mInitCheck = UNKNOWN_ERROR;
148afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
149afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
150afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
151afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        int bytes_read = ::fread(buff, 1, BUFF_SIZE, file);
152afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (bytes_read < 0) {
153afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            ALOGE("failed in call to read");
154afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            mInitCheck = ERROR_IO;
155afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
156afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
157afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
158d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        XML_Status status = ::XML_ParseBuffer(parser, bytes_read, bytes_read == 0);
159d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        if (status != XML_STATUS_OK) {
160d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            ALOGE("malformed (%s)", ::XML_ErrorString(::XML_GetErrorCode(parser)));
161afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            mInitCheck = ERROR_MALFORMED;
162afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
163afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
164afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
165afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (bytes_read == 0) {
166afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
167afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
168afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
169afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
170afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    ::XML_ParserFree(parser);
171afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
172d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    fclose(file);
173d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    file = NULL;
174afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
175afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
176afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber// static
177afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubervoid MediaCodecList::StartElementHandlerWrapper(
178afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        void *me, const char *name, const char **attrs) {
179afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    static_cast<MediaCodecList *>(me)->startElementHandler(name, attrs);
180afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
181afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
182afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber// static
183afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubervoid MediaCodecList::EndElementHandlerWrapper(void *me, const char *name) {
184afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    static_cast<MediaCodecList *>(me)->endElementHandler(name);
185afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
186afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
187d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnarstatus_t MediaCodecList::includeXMLFile(const char **attrs) {
188d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    const char *href = NULL;
189d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    size_t i = 0;
190d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    while (attrs[i] != NULL) {
191d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        if (!strcmp(attrs[i], "href")) {
192d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            if (attrs[i + 1] == NULL) {
193d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar                return -EINVAL;
194d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            }
195d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            href = attrs[i + 1];
196d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            ++i;
197d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        } else {
198d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            return -EINVAL;
199d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        }
200d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        ++i;
201d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    }
202d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
203d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    // For security reasons and for simplicity, file names can only contain
204d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    // [a-zA-Z0-9_.] and must start with  media_codecs_ and end with .xml
205d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    for (i = 0; href[i] != '\0'; i++) {
206d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        if (href[i] == '.' || href[i] == '_' ||
207d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar                (href[i] >= '0' && href[i] <= '9') ||
208d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar                (href[i] >= 'A' && href[i] <= 'Z') ||
209d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar                (href[i] >= 'a' && href[i] <= 'z')) {
210d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            continue;
211d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        }
212d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        ALOGE("invalid include file name: %s", href);
213d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        return -EINVAL;
214d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    }
215d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
216d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    AString filename = href;
217d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    if (!filename.startsWith("media_codecs_") ||
218d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        !filename.endsWith(".xml")) {
219d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        ALOGE("invalid include file name: %s", href);
220d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        return -EINVAL;
221d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    }
222d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    filename.insert(mHrefBase, 0);
223d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
224d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    parseXMLFile(filename.c_str());
225d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    return mInitCheck;
226d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar}
227d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
228afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubervoid MediaCodecList::startElementHandler(
229afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        const char *name, const char **attrs) {
230afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (mInitCheck != OK) {
231afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return;
232afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
233afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
234513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    bool inType = true;
235513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
236d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    if (!strcmp(name, "Include")) {
237d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        mInitCheck = includeXMLFile(attrs);
238d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        if (mInitCheck == OK) {
239d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            mPastSections.push(mCurrentSection);
240d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            mCurrentSection = SECTION_INCLUDE;
241d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        }
242d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        ++mDepth;
243d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        return;
244d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar    }
245d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
246afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    switch (mCurrentSection) {
247afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_TOPLEVEL:
248afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
249afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "Decoders")) {
250afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_DECODERS;
251afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            } else if (!strcmp(name, "Encoders")) {
252afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_ENCODERS;
253afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
254afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
255afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
256afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
257afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_DECODERS:
258afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
259afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "MediaCodec")) {
260afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mInitCheck =
261afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                    addMediaCodecFromAttributes(false /* encoder */, attrs);
262afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
263afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_DECODER;
264afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
265afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
266afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
267afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
268afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_ENCODERS:
269afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
270afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "MediaCodec")) {
271afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mInitCheck =
272afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                    addMediaCodecFromAttributes(true /* encoder */, attrs);
273afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
274afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_ENCODER;
275afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
276afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
277afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
278afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
279afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_DECODER:
280afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_ENCODER:
281afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
282afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "Quirk")) {
283afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mInitCheck = addQuirk(attrs);
284afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            } else if (!strcmp(name, "Type")) {
285afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mInitCheck = addTypeFromAttributes(attrs);
286513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                mCurrentSection =
287513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                    (mCurrentSection == SECTION_DECODER
288513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                            ? SECTION_DECODER_TYPE : SECTION_ENCODER_TYPE);
289513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
290513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
291513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        inType = false;
292513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        // fall through
293513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
294513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        case SECTION_DECODER_TYPE:
295513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        case SECTION_ENCODER_TYPE:
296513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        {
297513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
298513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            // ignore limits and features specified outside of type
299513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            bool outside = !inType && info->mSoleType == 0;
300513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            if (outside && (!strcmp(name, "Limit") || !strcmp(name, "Feature"))) {
301513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                ALOGW("ignoring %s specified outside of a Type", name);
302513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            } else if (!strcmp(name, "Limit")) {
303513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                mInitCheck = addLimit(attrs);
304513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            } else if (!strcmp(name, "Feature")) {
305513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                mInitCheck = addFeature(attrs);
306afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
307afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
308afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
309afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
310afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        default:
311afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
312afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
313afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
314afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    ++mDepth;
315afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
316afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
317afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubervoid MediaCodecList::endElementHandler(const char *name) {
318afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (mInitCheck != OK) {
319afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return;
320afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
321afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
322afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    switch (mCurrentSection) {
323afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_DECODERS:
324afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
325afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "Decoders")) {
326afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_TOPLEVEL;
327afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
328afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
329afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
330afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
331afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_ENCODERS:
332afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
333afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "Encoders")) {
334afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_TOPLEVEL;
335afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
336afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
337afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
338afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
339513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        case SECTION_DECODER_TYPE:
340513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        case SECTION_ENCODER_TYPE:
341513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        {
342513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            if (!strcmp(name, "Type")) {
343513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                mCurrentSection =
344513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                    (mCurrentSection == SECTION_DECODER_TYPE
345513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                            ? SECTION_DECODER : SECTION_ENCODER);
346513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
347513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
348513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                info->mCurrentCaps = NULL;
349513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
350513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            break;
351513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
352513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
353afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_DECODER:
354afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
355afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "MediaCodec")) {
356afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_DECODERS;
357513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
358513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
359513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                info->mCurrentCaps = NULL;
360afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
361afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
362afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
363afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
364afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        case SECTION_ENCODER:
365afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        {
366afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (!strcmp(name, "MediaCodec")) {
367afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                mCurrentSection = SECTION_ENCODERS;
368513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
369513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
370513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                info->mCurrentCaps = NULL;
371afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
372afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
373afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
374afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
375d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        case SECTION_INCLUDE:
376d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        {
377d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            if (!strcmp(name, "Include") && mPastSections.size() > 0) {
378d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar                mCurrentSection = mPastSections.top();
379d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar                mPastSections.pop();
380d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            }
381d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar            break;
382d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar        }
383d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar
384afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        default:
385afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            break;
386afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
387afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
388afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    --mDepth;
389afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
390afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
391afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberstatus_t MediaCodecList::addMediaCodecFromAttributes(
392afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        bool encoder, const char **attrs) {
393afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    const char *name = NULL;
394afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    const char *type = NULL;
395afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
396afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    size_t i = 0;
397afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    while (attrs[i] != NULL) {
398afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (!strcmp(attrs[i], "name")) {
399afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (attrs[i + 1] == NULL) {
400afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                return -EINVAL;
401afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
402afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            name = attrs[i + 1];
403afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            ++i;
404afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        } else if (!strcmp(attrs[i], "type")) {
405afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (attrs[i + 1] == NULL) {
406afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                return -EINVAL;
407afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
408afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            type = attrs[i + 1];
409afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            ++i;
410afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        } else {
411afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            return -EINVAL;
412afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
413afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
414afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        ++i;
415afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
416afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
417afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (name == NULL) {
418afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return -EINVAL;
419afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
420afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
421afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    addMediaCodec(encoder, name, type);
422afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
423afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    return OK;
424afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
425afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
426afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubervoid MediaCodecList::addMediaCodec(
427afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        bool encoder, const char *name, const char *type) {
428afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    mCodecInfos.push();
429afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
430afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    info->mName = name;
431afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    info->mIsEncoder = encoder;
432513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    info->mSoleType = 0;
433afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    info->mTypes = 0;
434afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    info->mQuirks = 0;
435513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    info->mCurrentCaps = NULL;
436afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
437afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (type != NULL) {
438afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        addType(type);
439513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        // if type was specified in attributes, we do not allow
440513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        // subsequent types
441513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        info->mSoleType = info->mTypes;
442afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
443afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
444afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
445afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberstatus_t MediaCodecList::addQuirk(const char **attrs) {
446afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    const char *name = NULL;
447afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
448afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    size_t i = 0;
449afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    while (attrs[i] != NULL) {
450afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (!strcmp(attrs[i], "name")) {
451afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (attrs[i + 1] == NULL) {
452afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                return -EINVAL;
453afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
454afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            name = attrs[i + 1];
455afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            ++i;
456afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        } else {
457afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            return -EINVAL;
458afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
459afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
460afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        ++i;
461afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
462afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
463afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (name == NULL) {
464afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return -EINVAL;
465afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
466afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
467afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    uint32_t bit;
468afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    ssize_t index = mCodecQuirks.indexOfKey(name);
469afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (index < 0) {
470afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        bit = mCodecQuirks.size();
471afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
472afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (bit == 32) {
473afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            ALOGW("Too many distinct quirk names in configuration.");
474afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            return OK;
475afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
476afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
477afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        mCodecQuirks.add(name, bit);
478afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    } else {
479afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        bit = mCodecQuirks.valueAt(index);
480afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
481afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
482afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
483afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    info->mQuirks |= 1ul << bit;
484afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
485afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    return OK;
486afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
487afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
488afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberstatus_t MediaCodecList::addTypeFromAttributes(const char **attrs) {
489afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    const char *name = NULL;
490afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
491513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
492513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    if (info->mSoleType != 0) {
493513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        ALOGE("Codec '%s' already had its type specified", info->mName.c_str());
494513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        return -EINVAL;
495513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
496513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
497afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    size_t i = 0;
498afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    while (attrs[i] != NULL) {
499afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (!strcmp(attrs[i], "name")) {
500afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            if (attrs[i + 1] == NULL) {
501afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber                return -EINVAL;
502afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            }
503afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            name = attrs[i + 1];
504afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            ++i;
505afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        } else {
506afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            return -EINVAL;
507afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
508afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
509afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        ++i;
510afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
511afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
512afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (name == NULL) {
513afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return -EINVAL;
514afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
515afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
516afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    addType(name);
517afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
518afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    return OK;
519afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
520afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
521afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubervoid MediaCodecList::addType(const char *name) {
522afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    uint32_t bit;
523afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    ssize_t index = mTypes.indexOfKey(name);
524afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (index < 0) {
525afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        bit = mTypes.size();
526afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
527afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (bit == 32) {
528afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            ALOGW("Too many distinct type names in configuration.");
529afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            return;
530afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
531afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
532afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        mTypes.add(name, bit);
533afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    } else {
534afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        bit = mTypes.valueAt(index);
535afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
536afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
537afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
538afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    info->mTypes |= 1ul << bit;
539513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    if (info->mCaps.indexOfKey(bit) < 0) {
540513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        AMessage *msg = new AMessage();
541513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        info->mCaps.add(bit, msg);
542513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
543513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    info->mCurrentCaps = info->mCaps.editValueFor(bit);
544afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
545afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
546afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberssize_t MediaCodecList::findCodecByType(
547afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        const char *type, bool encoder, size_t startIndex) const {
548afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    ssize_t typeIndex = mTypes.indexOfKey(type);
549afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
550afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (typeIndex < 0) {
551afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return -ENOENT;
552afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
553afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
554afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    uint32_t typeMask = 1ul << mTypes.valueAt(typeIndex);
555afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
556afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    while (startIndex < mCodecInfos.size()) {
557afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        const CodecInfo &info = mCodecInfos.itemAt(startIndex);
558afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
559afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (info.mIsEncoder == encoder && (info.mTypes & typeMask)) {
560afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            return startIndex;
561afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
562afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
563afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        ++startIndex;
564afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
565afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
566afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    return -ENOENT;
567afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
568afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
569513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatic status_t limitFoundMissingAttr(AString name, const char *attr, bool found = true) {
570513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    ALOGE("limit '%s' with %s'%s' attribute", name.c_str(),
571513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            (found ? "" : "no "), attr);
572513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    return -EINVAL;
573513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar}
574513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
575513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatic status_t limitError(AString name, const char *msg) {
576513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    ALOGE("limit '%s' %s", name.c_str(), msg);
577513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    return -EINVAL;
578513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar}
579513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
580513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatic status_t limitInvalidAttr(AString name, const char *attr, AString value) {
581513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    ALOGE("limit '%s' with invalid '%s' attribute (%s)", name.c_str(),
582513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            attr, value.c_str());
583513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    return -EINVAL;
584513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar}
585513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
586513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatus_t MediaCodecList::addLimit(const char **attrs) {
587513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    sp<AMessage> msg = new AMessage();
588513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
589513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    size_t i = 0;
590513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    while (attrs[i] != NULL) {
591513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (attrs[i + 1] == NULL) {
592513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return -EINVAL;
593513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
594513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
595513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        // attributes with values
596513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (!strcmp(attrs[i], "name")
597513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "default")
598513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "in")
599513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "max")
600513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "min")
601513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "range")
602513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "ranges")
603513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "scale")
604513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                || !strcmp(attrs[i], "value")) {
605513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            msg->setString(attrs[i], attrs[i + 1]);
606513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            ++i;
607513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else {
608513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return -EINVAL;
609513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
610513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        ++i;
611513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
612513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
613513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    AString name;
614513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    if (!msg->findString("name", &name)) {
615513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        ALOGE("limit with no 'name' attribute");
616513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        return -EINVAL;
617513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
618513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
619513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
620513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
621513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    // size, blocks, bitrate, frame-rate, blocks-per-second, aspect-ratio: range
622513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    // quality: range + default + [scale]
623513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    // complexity: range + default
624513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    bool found;
625513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    if (name == "aspect-ratio" || name == "bitrate" || name == "block-count"
626513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            || name == "blocks-per-second" || name == "complexity"
627513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            || name == "frame-rate" || name == "quality" || name == "size") {
628513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        AString min, max;
629513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (msg->findString("min", &min) && msg->findString("max", &max)) {
630513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            min.append("-");
631513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            min.append(max);
632513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            if (msg->contains("range") || msg->contains("value")) {
633513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                return limitError(name, "has 'min' and 'max' as well as 'range' or "
634513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                        "'value' attributes");
635513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
636513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            msg->setString("range", min);
637513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (msg->contains("min") || msg->contains("max")) {
638513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitError(name, "has only 'min' or 'max' attribute");
639513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (msg->findString("value", &max)) {
640513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            min = max;
641513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            min.append("-");
642513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            min.append(max);
643513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            if (msg->contains("range")) {
644513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                return limitError(name, "has both 'range' and 'value' attributes");
645513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
646513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            msg->setString("range", min);
647513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
648513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
649513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        AString range, scale = "linear", def, in_;
650513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (!msg->findString("range", &range)) {
651513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitError(name, "with no 'range', 'value' or 'min'/'max' attributes");
652513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
653513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
654513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if ((name == "quality" || name == "complexity") ^
655513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                (found = msg->findString("default", &def))) {
656513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "default", found);
657513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
658513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (name != "quality" && msg->findString("scale", &scale)) {
659513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "scale");
660513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
661513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if ((name == "aspect-ratio") ^ (found = msg->findString("in", &in_))) {
662513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "in", found);
663513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
664513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
665513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (name == "aspect-ratio") {
666513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            if (!(in_ == "pixels") && !(in_ == "blocks")) {
667513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                return limitInvalidAttr(name, "in", in_);
668513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
669513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            in_.erase(5, 1); // (pixel|block)-aspect-ratio
670513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            in_.append("-");
671513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            in_.append(name);
672513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            name = in_;
673513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
674513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (name == "quality") {
675513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            info->mCurrentCaps->setString("quality-scale", scale);
676513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
677513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (name == "quality" || name == "complexity") {
678513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            AString tag = name;
679513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            tag.append("-default");
680513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            info->mCurrentCaps->setString(tag.c_str(), def);
681513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
682513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        AString tag = name;
683513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        tag.append("-range");
684513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        info->mCurrentCaps->setString(tag.c_str(), range);
685513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    } else {
686513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        AString max, value, ranges;
687513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (msg->contains("default")) {
688513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "default");
689513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (msg->contains("in")) {
690513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "in");
691513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if ((name == "channel-count") ^
692513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                (found = msg->findString("max", &max))) {
693513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "max", found);
694513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (msg->contains("min")) {
695513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "min");
696513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (msg->contains("range")) {
697513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "range");
698513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if ((name == "sample-rate") ^
699513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                (found = msg->findString("ranges", &ranges))) {
700513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "ranges", found);
701513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (msg->contains("scale")) {
702513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "scale");
703513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if ((name == "alignment" || name == "block-size") ^
704513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                (found = msg->findString("value", &value))) {
705513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return limitFoundMissingAttr(name, "value", found);
706513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
707513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
708513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (max.size()) {
709513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            AString tag = "max-";
710513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            tag.append(name);
711513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            info->mCurrentCaps->setString(tag.c_str(), max);
712513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (value.size()) {
713513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            info->mCurrentCaps->setString(name.c_str(), value);
714513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (ranges.size()) {
715513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            AString tag = name;
716513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            tag.append("-ranges");
717513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            info->mCurrentCaps->setString(tag.c_str(), ranges);
718513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else {
719513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            ALOGW("Ignoring unrecognized limit '%s'", name.c_str());
720513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
721513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
722513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    return OK;
723513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar}
724513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
725513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatic bool parseBoolean(const char *s) {
726513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    if (!strcasecmp(s, "true") || !strcasecmp(s, "yes") || !strcasecmp(s, "y")) {
727513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        return true;
728513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
729513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    char *end;
730513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    unsigned long res = strtoul(s, &end, 10);
731513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    return *s != '\0' && *end == '\0' && res > 0;
732513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar}
733513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
734513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatus_t MediaCodecList::addFeature(const char **attrs) {
735513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    size_t i = 0;
736513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    const char *name = NULL;
737513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    int32_t optional = -1;
738513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    int32_t required = -1;
739513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
740513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    while (attrs[i] != NULL) {
741513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (attrs[i + 1] == NULL) {
742513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return -EINVAL;
743513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
744513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
745513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        // attributes with values
746513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        if (!strcmp(attrs[i], "name")) {
747513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            name = attrs[i + 1];
748513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            ++i;
749513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else if (!strcmp(attrs[i], "optional") || !strcmp(attrs[i], "required")) {
750513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            int value = (int)parseBoolean(attrs[i + 1]);
751513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            if (!strcmp(attrs[i], "optional")) {
752513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                optional = value;
753513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            } else {
754513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar                required = value;
755513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            }
756513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            ++i;
757513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        } else {
758513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar            return -EINVAL;
759513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        }
760513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        ++i;
761513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
762513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    if (name == NULL) {
763513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        ALOGE("feature with no 'name' attribute");
764513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        return -EINVAL;
765513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
766513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
767513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    if (optional == required && optional != -1) {
768513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        ALOGE("feature '%s' is both/neither optional and required", name);
769513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        return -EINVAL;
770513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
771513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
772513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
773513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    AString tag = "feature-";
774513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    tag.append(name);
775513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    info->mCurrentCaps->setInt32(tag.c_str(), (required == 1) || (optional == 0));
776513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    return OK;
777513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar}
778513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
779afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberssize_t MediaCodecList::findCodecByName(const char *name) const {
780afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    for (size_t i = 0; i < mCodecInfos.size(); ++i) {
781afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        const CodecInfo &info = mCodecInfos.itemAt(i);
782afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
783afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (info.mName == name) {
784afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            return i;
785afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
786afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
787afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
788afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    return -ENOENT;
789afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
790afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
79169829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Hubersize_t MediaCodecList::countCodecs() const {
79269829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    return mCodecInfos.size();
79369829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber}
79469829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
795afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberconst char *MediaCodecList::getCodecName(size_t index) const {
796afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (index >= mCodecInfos.size()) {
797afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return NULL;
798afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
799afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
800afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    const CodecInfo &info = mCodecInfos.itemAt(index);
801afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    return info.mName.c_str();
802afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
803afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
80469829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huberbool MediaCodecList::isEncoder(size_t index) const {
80569829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    if (index >= mCodecInfos.size()) {
80669829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber        return NULL;
80769829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    }
80869829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
80969829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    const CodecInfo &info = mCodecInfos.itemAt(index);
81069829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    return info.mIsEncoder;
81169829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber}
81269829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
813afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberbool MediaCodecList::codecHasQuirk(
814afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        size_t index, const char *quirkName) const {
815afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (index >= mCodecInfos.size()) {
816afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        return NULL;
817afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
818afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
819afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    const CodecInfo &info = mCodecInfos.itemAt(index);
820afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
821afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    if (info.mQuirks != 0) {
822afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        ssize_t index = mCodecQuirks.indexOfKey(quirkName);
823afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        if (index >= 0 && info.mQuirks & (1ul << mCodecQuirks.valueAt(index))) {
824afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber            return true;
825afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber        }
826afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    }
827afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
828afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber    return false;
829afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}
830afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber
83169829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huberstatus_t MediaCodecList::getSupportedTypes(
83269829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber        size_t index, Vector<AString> *types) const {
83369829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    types->clear();
83469829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
83569829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    if (index >= mCodecInfos.size()) {
83669829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber        return -ERANGE;
83769829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    }
83869829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
83969829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    const CodecInfo &info = mCodecInfos.itemAt(index);
84069829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
84169829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    for (size_t i = 0; i < mTypes.size(); ++i) {
84269829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber        uint32_t typeMask = 1ul << mTypes.valueAt(i);
84369829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
84469829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber        if (info.mTypes & typeMask) {
84569829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber            types->push(mTypes.keyAt(i));
84669829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber        }
84769829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    }
84869829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
84969829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    return OK;
85069829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber}
85169829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
85269829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huberstatus_t MediaCodecList::getCodecCapabilities(
85369829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber        size_t index, const char *type,
85469829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber        Vector<ProfileLevel> *profileLevels,
8552ee14000a38683220fb250d9e7300e1d71ccdaa0Lajos Molnar        Vector<uint32_t> *colorFormats,
856513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        uint32_t *flags,
857513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        sp<AMessage> *capabilities) const {
85869829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    profileLevels->clear();
85969829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    colorFormats->clear();
86069829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
86169829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    if (index >= mCodecInfos.size()) {
86269829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber        return -ERANGE;
86369829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    }
86469829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
86569829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    const CodecInfo &info = mCodecInfos.itemAt(index);
86669829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
867513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    ssize_t typeIndex = mTypes.indexOfKey(type);
868513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    if (typeIndex < 0) {
869513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        return -EINVAL;
870513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
871513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
87269829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    OMXClient client;
87369829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    status_t err = client.connect();
87469829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    if (err != OK) {
87569829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber        return err;
87669829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    }
87769829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
87869829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    CodecCapabilities caps;
87969829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    err = QueryCodec(
88069829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber            client.interface(),
88169829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber            info.mName.c_str(), type, info.mIsEncoder, &caps);
88269829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
88369829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    if (err != OK) {
88469829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber        return err;
88569829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    }
88669829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
88769829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    for (size_t i = 0; i < caps.mProfileLevels.size(); ++i) {
88869829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber        const CodecProfileLevel &src = caps.mProfileLevels.itemAt(i);
88969829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
89069829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber        ProfileLevel profileLevel;
89169829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber        profileLevel.mProfile = src.mProfile;
89269829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber        profileLevel.mLevel = src.mLevel;
89369829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber        profileLevels->push(profileLevel);
89469829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    }
89569829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
89669829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    for (size_t i = 0; i < caps.mColorFormats.size(); ++i) {
89769829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber        colorFormats->push(caps.mColorFormats.itemAt(i));
89869829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    }
89969829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
9002ee14000a38683220fb250d9e7300e1d71ccdaa0Lajos Molnar    *flags = caps.mFlags;
9012ee14000a38683220fb250d9e7300e1d71ccdaa0Lajos Molnar
902513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    // TODO this check will be removed once JNI side is merged
903513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    if (capabilities != NULL) {
904513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar        *capabilities = info.mCaps.valueFor(typeIndex);
905513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar    }
906513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar
90769829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber    return OK;
90869829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber}
90969829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber
910afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber}  // namespace android
911