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