1afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber/* 2afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * Copyright 2012, The Android Open Source Project 3afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * 4afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * you may not use this file except in compliance with the License. 6afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * You may obtain a copy of the License at 7afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * 8afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * 10afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * Unless required by applicable law or agreed to in writing, software 11afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * See the License for the specific language governing permissions and 14afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber * limitations under the License. 15afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber */ 16afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 17afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber//#define LOG_NDEBUG 0 18afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#define LOG_TAG "MediaCodecList" 19afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#include <utils/Log.h> 20afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 2160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar#include <binder/IServiceManager.h> 2260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar 2360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar#include <media/IMediaCodecList.h> 2460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar#include <media/IMediaPlayerService.h> 2560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar#include <media/MediaCodecInfo.h> 26afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 27afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#include <media/stagefright/foundation/ADebug.h> 28513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar#include <media/stagefright/foundation/AMessage.h> 2960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar#include <media/stagefright/MediaCodecList.h> 30afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#include <media/stagefright/MediaErrors.h> 3169829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber#include <media/stagefright/OMXClient.h> 3269829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber#include <media/stagefright/OMXCodec.h> 3360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar 34afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#include <utils/threads.h> 35afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 36e8057dd8208f0a185109992339a995c518b12780Elliott Hughes#include <libexpat/expat.h> 37afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 38afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubernamespace android { 39afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 40afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberstatic Mutex sInitMutex; 41afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 4260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnarstatic MediaCodecList *gCodecList = NULL; 4360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar 44afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber// static 4560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnarsp<IMediaCodecList> MediaCodecList::sCodecList; 46afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 47afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber// static 4860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnarsp<IMediaCodecList> MediaCodecList::getLocalInstance() { 49afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber Mutex::Autolock autoLock(sInitMutex); 50afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 5160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar if (gCodecList == NULL) { 5260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar gCodecList = new MediaCodecList; 5360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar if (gCodecList->initCheck() == OK) { 5460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar sCodecList = gCodecList; 5560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar } 56afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 57afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 5860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar return sCodecList; 5960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar} 6060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar 6160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnarstatic Mutex sRemoteInitMutex; 6260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar 6360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnarsp<IMediaCodecList> MediaCodecList::sRemoteList; 6460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar 6560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar// static 6660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnarsp<IMediaCodecList> MediaCodecList::getInstance() { 671381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar Mutex::Autolock _l(sRemoteInitMutex); 681381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar if (sRemoteList == NULL) { 691381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar sp<IBinder> binder = 701381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar defaultServiceManager()->getService(String16("media.player")); 711381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar sp<IMediaPlayerService> service = 721381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar interface_cast<IMediaPlayerService>(binder); 731381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar if (service.get() != NULL) { 741381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar sRemoteList = service->getCodecList(); 751381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar } 761381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar 771381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar if (sRemoteList == NULL) { 781381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar // if failed to get remote list, create local list 791381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar sRemoteList = getLocalInstance(); 801381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar } 811381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar } 821381d4b5c0385aec3741073e5998773b064c1fb0Lajos Molnar return sRemoteList; 83afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber} 84afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 85afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas HuberMediaCodecList::MediaCodecList() 86afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber : mInitCheck(NO_INIT) { 87d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar parseTopLevelXMLFile("/etc/media_codecs.xml"); 88d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar} 89afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 90d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnarvoid MediaCodecList::parseTopLevelXMLFile(const char *codecs_xml) { 91d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar // get href_base 92d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar char *href_base_end = strrchr(codecs_xml, '/'); 93d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar if (href_base_end != NULL) { 94d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar mHrefBase = AString(codecs_xml, href_base_end - codecs_xml + 1); 95d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar } 96d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar 9760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mInitCheck = OK; // keeping this here for safety 98d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar mCurrentSection = SECTION_TOPLEVEL; 99d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar mDepth = 0; 100d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar 10160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar OMXClient client; 10260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mInitCheck = client.connect(); 10360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar if (mInitCheck != OK) { 10460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar return; 10560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar } 10660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mOMX = client.interface(); 107d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar parseXMLFile(codecs_xml); 10860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mOMX.clear(); 109d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar 110d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar if (mInitCheck != OK) { 111d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar mCodecInfos.clear(); 112afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber return; 113afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 114afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 115d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar for (size_t i = mCodecInfos.size(); i-- > 0;) { 11660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar const MediaCodecInfo &info = *mCodecInfos.itemAt(i).get(); 117afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 11860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar if (info.mCaps.size() == 0) { 119d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar // No types supported by this component??? 120d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar ALOGW("Component %s does not support any type of media?", 12160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar info.mName.c_str()); 122ecdd39c5af016e2fa57cbfd837aa670b706dabd3Andreas Huber 123d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar mCodecInfos.removeAt(i); 124513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar#if LOG_NDEBUG == 0 125513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } else { 12660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar for (size_t type_ix = 0; type_ix < info.mCaps.size(); ++type_ix) { 12760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar AString mime = info.mCaps.keyAt(type_ix); 12860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar const sp<MediaCodecInfo::Capabilities> &caps = info.mCaps.valueAt(type_ix); 12960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar 13060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar ALOGV("%s codec info for %s: %s", info.mName.c_str(), mime.c_str(), 13160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar caps->getDetails()->debugString().c_str()); 13260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar ALOGV(" flags=%d", caps->getFlags()); 13360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar { 13460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar Vector<uint32_t> colorFormats; 13560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar caps->getSupportedColorFormats(&colorFormats); 13660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar AString nice; 13760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar for (size_t ix = 0; ix < colorFormats.size(); ix++) { 13860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar if (ix > 0) { 13960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar nice.append(", "); 14060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar } 14160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar nice.append(colorFormats.itemAt(ix)); 14260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar } 14360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar ALOGV(" colors=[%s]", nice.c_str()); 14460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar } 14560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar { 14660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar Vector<MediaCodecInfo::ProfileLevel> profileLevels; 14760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar caps->getSupportedProfileLevels(&profileLevels); 14860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar AString nice; 14960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar for (size_t ix = 0; ix < profileLevels.size(); ix++) { 15060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar if (ix > 0) { 15160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar nice.append(", "); 15260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar } 15360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar const MediaCodecInfo::ProfileLevel &pl = 15460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar profileLevels.itemAt(ix); 15560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar nice.append(pl.mProfile); 15660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar nice.append("/"); 15760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar nice.append(pl.mLevel); 15860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar } 15960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar ALOGV(" levels=[%s]", nice.c_str()); 160513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 161513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 162513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar#endif 163d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar } 164afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 165afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 166afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#if 0 167afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber for (size_t i = 0; i < mCodecInfos.size(); ++i) { 168afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber const CodecInfo &info = mCodecInfos.itemAt(i); 169afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 170afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber AString line = info.mName; 171afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber line.append(" supports "); 172afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber for (size_t j = 0; j < mTypes.size(); ++j) { 173afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber uint32_t value = mTypes.valueAt(j); 174afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 175afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (info.mTypes & (1ul << value)) { 176afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber line.append(mTypes.keyAt(j)); 177afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber line.append(" "); 178afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 179afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 180afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 181afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber ALOGI("%s", line.c_str()); 182afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 183afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber#endif 184afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber} 185afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 186afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas HuberMediaCodecList::~MediaCodecList() { 187afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber} 188afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 189afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberstatus_t MediaCodecList::initCheck() const { 190afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber return mInitCheck; 191afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber} 192afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 193d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnarvoid MediaCodecList::parseXMLFile(const char *path) { 194d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar FILE *file = fopen(path, "r"); 195d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar 196d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar if (file == NULL) { 197d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar ALOGW("unable to open media codecs configuration xml file: %s", path); 198d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar mInitCheck = NAME_NOT_FOUND; 199d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar return; 200d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar } 201afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 202afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber XML_Parser parser = ::XML_ParserCreate(NULL); 203afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber CHECK(parser != NULL); 204afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 205afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber ::XML_SetUserData(parser, this); 206afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber ::XML_SetElementHandler( 207afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber parser, StartElementHandlerWrapper, EndElementHandlerWrapper); 208afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 209afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber const int BUFF_SIZE = 512; 210afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber while (mInitCheck == OK) { 211afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber void *buff = ::XML_GetBuffer(parser, BUFF_SIZE); 212afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (buff == NULL) { 213d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar ALOGE("failed in call to XML_GetBuffer()"); 214afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber mInitCheck = UNKNOWN_ERROR; 215afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber break; 216afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 217afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 218afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber int bytes_read = ::fread(buff, 1, BUFF_SIZE, file); 219afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (bytes_read < 0) { 220afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber ALOGE("failed in call to read"); 221afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber mInitCheck = ERROR_IO; 222afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber break; 223afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 224afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 225d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar XML_Status status = ::XML_ParseBuffer(parser, bytes_read, bytes_read == 0); 226d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar if (status != XML_STATUS_OK) { 227d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar ALOGE("malformed (%s)", ::XML_ErrorString(::XML_GetErrorCode(parser))); 228afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber mInitCheck = ERROR_MALFORMED; 229afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber break; 230afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 231afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 232afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (bytes_read == 0) { 233afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber break; 234afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 235afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 236afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 237afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber ::XML_ParserFree(parser); 238afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 239d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar fclose(file); 240d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar file = NULL; 241afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber} 242afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 243afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber// static 244afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubervoid MediaCodecList::StartElementHandlerWrapper( 245afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber void *me, const char *name, const char **attrs) { 246afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber static_cast<MediaCodecList *>(me)->startElementHandler(name, attrs); 247afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber} 248afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 249afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber// static 250afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubervoid MediaCodecList::EndElementHandlerWrapper(void *me, const char *name) { 251afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber static_cast<MediaCodecList *>(me)->endElementHandler(name); 252afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber} 253afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 254d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnarstatus_t MediaCodecList::includeXMLFile(const char **attrs) { 255d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar const char *href = NULL; 256d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar size_t i = 0; 257d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar while (attrs[i] != NULL) { 258d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar if (!strcmp(attrs[i], "href")) { 259d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar if (attrs[i + 1] == NULL) { 260d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar return -EINVAL; 261d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar } 262d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar href = attrs[i + 1]; 263d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar ++i; 264d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar } else { 265d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar return -EINVAL; 266d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar } 267d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar ++i; 268d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar } 269d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar 270d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar // For security reasons and for simplicity, file names can only contain 271d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar // [a-zA-Z0-9_.] and must start with media_codecs_ and end with .xml 272d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar for (i = 0; href[i] != '\0'; i++) { 273d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar if (href[i] == '.' || href[i] == '_' || 274d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar (href[i] >= '0' && href[i] <= '9') || 275d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar (href[i] >= 'A' && href[i] <= 'Z') || 276d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar (href[i] >= 'a' && href[i] <= 'z')) { 277d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar continue; 278d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar } 279d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar ALOGE("invalid include file name: %s", href); 280d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar return -EINVAL; 281d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar } 282d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar 283d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar AString filename = href; 284d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar if (!filename.startsWith("media_codecs_") || 285d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar !filename.endsWith(".xml")) { 286d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar ALOGE("invalid include file name: %s", href); 287d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar return -EINVAL; 288d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar } 289d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar filename.insert(mHrefBase, 0); 290d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar 291d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar parseXMLFile(filename.c_str()); 292d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar return mInitCheck; 293d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar} 294d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar 295afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubervoid MediaCodecList::startElementHandler( 296afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber const char *name, const char **attrs) { 297afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (mInitCheck != OK) { 298afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber return; 299afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 300afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 301513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar bool inType = true; 302513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 303d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar if (!strcmp(name, "Include")) { 304d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar mInitCheck = includeXMLFile(attrs); 305d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar if (mInitCheck == OK) { 306d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar mPastSections.push(mCurrentSection); 307d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar mCurrentSection = SECTION_INCLUDE; 308d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar } 309d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar ++mDepth; 310d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar return; 311d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar } 312d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar 313afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber switch (mCurrentSection) { 314afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber case SECTION_TOPLEVEL: 315afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber { 316afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (!strcmp(name, "Decoders")) { 317afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber mCurrentSection = SECTION_DECODERS; 318afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } else if (!strcmp(name, "Encoders")) { 319afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber mCurrentSection = SECTION_ENCODERS; 320afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 321afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber break; 322afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 323afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 324afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber case SECTION_DECODERS: 325afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber { 326afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (!strcmp(name, "MediaCodec")) { 327afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber mInitCheck = 328afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber addMediaCodecFromAttributes(false /* encoder */, attrs); 329afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 330afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber mCurrentSection = SECTION_DECODER; 331afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 332afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber break; 333afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 334afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 335afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber case SECTION_ENCODERS: 336afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber { 337afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (!strcmp(name, "MediaCodec")) { 338afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber mInitCheck = 339afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber addMediaCodecFromAttributes(true /* encoder */, attrs); 340afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 341afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber mCurrentSection = SECTION_ENCODER; 342afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 343afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber break; 344afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 345afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 346afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber case SECTION_DECODER: 347afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber case SECTION_ENCODER: 348afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber { 349afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (!strcmp(name, "Quirk")) { 350afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber mInitCheck = addQuirk(attrs); 351afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } else if (!strcmp(name, "Type")) { 352afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber mInitCheck = addTypeFromAttributes(attrs); 353513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar mCurrentSection = 354513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar (mCurrentSection == SECTION_DECODER 355513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar ? SECTION_DECODER_TYPE : SECTION_ENCODER_TYPE); 356513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 357513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 358513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar inType = false; 359513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar // fall through 360513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 361513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar case SECTION_DECODER_TYPE: 362513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar case SECTION_ENCODER_TYPE: 363513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar { 364513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar // ignore limits and features specified outside of type 36560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar bool outside = !inType && !mCurrentInfo->mHasSoleMime; 366513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (outside && (!strcmp(name, "Limit") || !strcmp(name, "Feature"))) { 367513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar ALOGW("ignoring %s specified outside of a Type", name); 368513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } else if (!strcmp(name, "Limit")) { 369513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar mInitCheck = addLimit(attrs); 370513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } else if (!strcmp(name, "Feature")) { 371513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar mInitCheck = addFeature(attrs); 372afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 373afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber break; 374afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 375afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 376afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber default: 377afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber break; 378afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 379afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 380afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber ++mDepth; 381afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber} 382afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 383afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Hubervoid MediaCodecList::endElementHandler(const char *name) { 384afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (mInitCheck != OK) { 385afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber return; 386afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 387afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 388afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber switch (mCurrentSection) { 389afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber case SECTION_DECODERS: 390afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber { 391afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (!strcmp(name, "Decoders")) { 392afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber mCurrentSection = SECTION_TOPLEVEL; 393afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 394afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber break; 395afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 396afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 397afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber case SECTION_ENCODERS: 398afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber { 399afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (!strcmp(name, "Encoders")) { 400afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber mCurrentSection = SECTION_TOPLEVEL; 401afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 402afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber break; 403afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 404afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 405513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar case SECTION_DECODER_TYPE: 406513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar case SECTION_ENCODER_TYPE: 407513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar { 408513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (!strcmp(name, "Type")) { 409513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar mCurrentSection = 410513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar (mCurrentSection == SECTION_DECODER_TYPE 411513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar ? SECTION_DECODER : SECTION_ENCODER); 412513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 41360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mCurrentInfo->complete(); 414513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 415513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar break; 416513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 417513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 418afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber case SECTION_DECODER: 419afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber { 420afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (!strcmp(name, "MediaCodec")) { 421afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber mCurrentSection = SECTION_DECODERS; 42260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mCurrentInfo->complete(); 42360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mCurrentInfo = NULL; 424afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 425afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber break; 426afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 427afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 428afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber case SECTION_ENCODER: 429afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber { 430afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (!strcmp(name, "MediaCodec")) { 431afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber mCurrentSection = SECTION_ENCODERS; 43260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mCurrentInfo->complete();; 43360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mCurrentInfo = NULL; 434afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 435afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber break; 436afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 437afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 438d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar case SECTION_INCLUDE: 439d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar { 440d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar if (!strcmp(name, "Include") && mPastSections.size() > 0) { 441d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar mCurrentSection = mPastSections.top(); 442d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar mPastSections.pop(); 443d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar } 444d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar break; 445d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar } 446d74110cdef2becd4f7fd2334c34c3ca73f56b355Lajos Molnar 447afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber default: 448afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber break; 449afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 450afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 451afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber --mDepth; 452afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber} 453afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 454afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberstatus_t MediaCodecList::addMediaCodecFromAttributes( 455afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber bool encoder, const char **attrs) { 456afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber const char *name = NULL; 457afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber const char *type = NULL; 458afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 459afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber size_t i = 0; 460afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber while (attrs[i] != NULL) { 461afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (!strcmp(attrs[i], "name")) { 462afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (attrs[i + 1] == NULL) { 463afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber return -EINVAL; 464afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 465afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber name = attrs[i + 1]; 466afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber ++i; 467afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } else if (!strcmp(attrs[i], "type")) { 468afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (attrs[i + 1] == NULL) { 469afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber return -EINVAL; 470afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 471afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber type = attrs[i + 1]; 472afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber ++i; 473afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } else { 474afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber return -EINVAL; 475afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 476afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 477afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber ++i; 478afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 479afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 480afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (name == NULL) { 481afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber return -EINVAL; 482afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 483afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 48460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mCurrentInfo = new MediaCodecInfo(name, encoder, type); 4856ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar // The next step involves trying to load the codec, which may 4866ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar // fail. Only list the codec if this succeeds. 4876ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar // However, keep mCurrentInfo object around until parsing 4886ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar // of full codec info is completed. 4896ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar if (initializeCapabilities(type) == OK) { 4906ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar mCodecInfos.push_back(mCurrentInfo); 4916ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar } 4926ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar return OK; 493afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber} 494afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 49560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnarstatus_t MediaCodecList::initializeCapabilities(const char *type) { 4966ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar if (type == NULL) { 4976ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar return OK; 4986ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar } 4996ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar 50060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar ALOGV("initializeCapabilities %s:%s", 50160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mCurrentInfo->mName.c_str(), type); 50260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar 50360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar CodecCapabilities caps; 50460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar status_t err = QueryCodec( 50560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mOMX, 50660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mCurrentInfo->mName.c_str(), 50760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar type, 50860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mCurrentInfo->mIsEncoder, 50960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar &caps); 51060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar if (err != OK) { 51160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar return err; 512afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 51360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar 51460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar return mCurrentInfo->initializeCapabilities(caps); 515afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber} 516afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 517afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberstatus_t MediaCodecList::addQuirk(const char **attrs) { 518afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber const char *name = NULL; 519afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 520afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber size_t i = 0; 521afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber while (attrs[i] != NULL) { 522afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (!strcmp(attrs[i], "name")) { 523afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (attrs[i + 1] == NULL) { 524afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber return -EINVAL; 525afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 526afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber name = attrs[i + 1]; 527afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber ++i; 528afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } else { 529afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber return -EINVAL; 530afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 531afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 532afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber ++i; 533afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 534afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 535afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (name == NULL) { 536afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber return -EINVAL; 537afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 538afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 53960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mCurrentInfo->addQuirk(name); 540afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber return OK; 541afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber} 542afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 543afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberstatus_t MediaCodecList::addTypeFromAttributes(const char **attrs) { 544afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber const char *name = NULL; 545afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 546afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber size_t i = 0; 547afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber while (attrs[i] != NULL) { 548afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (!strcmp(attrs[i], "name")) { 549afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (attrs[i + 1] == NULL) { 550afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber return -EINVAL; 551afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 552afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber name = attrs[i + 1]; 553afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber ++i; 554afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } else { 555afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber return -EINVAL; 556afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 557afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 558afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber ++i; 559afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 560afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 561afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (name == NULL) { 562afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber return -EINVAL; 563afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 564afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 56560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar status_t ret = mCurrentInfo->addMime(name); 5666ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar if (ret != OK) { 5676ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar return ret; 568513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 5696ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar 5706ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar // The next step involves trying to load the codec, which may 5716ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar // fail. Handle this gracefully (by not reporting such mime). 5726ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar if (initializeCapabilities(name) != OK) { 5736ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar mCurrentInfo->removeMime(name); 5746ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar } 5756ff58f04f78886b07c72c0118eb71a78d08f5651Lajos Molnar return OK; 576afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber} 577afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 57860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar// legacy method for non-advanced codecs 579afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberssize_t MediaCodecList::findCodecByType( 580afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber const char *type, bool encoder, size_t startIndex) const { 58160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar static const char *advancedFeatures[] = { 58260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar "feature-secure-playback", 58360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar "feature-tunneled-playback", 58460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar }; 585afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 58660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar size_t numCodecs = mCodecInfos.size(); 58760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar for (; startIndex < numCodecs; ++startIndex) { 58860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar const MediaCodecInfo &info = *mCodecInfos.itemAt(startIndex).get(); 589afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 59060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar if (info.isEncoder() != encoder) { 59160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar continue; 59260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar } 59360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar sp<MediaCodecInfo::Capabilities> capabilities = info.getCapabilitiesFor(type); 59460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar if (capabilities == NULL) { 59560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar continue; 59660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar } 59760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar const sp<AMessage> &details = capabilities->getDetails(); 598afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 59960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar int32_t required; 60060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar bool isAdvanced = false; 60160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar for (size_t ix = 0; ix < ARRAY_SIZE(advancedFeatures); ix++) { 60260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar if (details->findInt32(advancedFeatures[ix], &required) && 60360b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar required != 0) { 60460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar isAdvanced = true; 60560b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar break; 60660b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar } 60760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar } 608afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 60960b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar if (!isAdvanced) { 610afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber return startIndex; 611afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 612afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 613afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 614afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber return -ENOENT; 615afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber} 616afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 617513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatic status_t limitFoundMissingAttr(AString name, const char *attr, bool found = true) { 618513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar ALOGE("limit '%s' with %s'%s' attribute", name.c_str(), 619513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar (found ? "" : "no "), attr); 620513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return -EINVAL; 621513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar} 622513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 623513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatic status_t limitError(AString name, const char *msg) { 624513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar ALOGE("limit '%s' %s", name.c_str(), msg); 625513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return -EINVAL; 626513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar} 627513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 628513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatic status_t limitInvalidAttr(AString name, const char *attr, AString value) { 629513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar ALOGE("limit '%s' with invalid '%s' attribute (%s)", name.c_str(), 630513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar attr, value.c_str()); 631513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return -EINVAL; 632513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar} 633513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 634513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatus_t MediaCodecList::addLimit(const char **attrs) { 635513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar sp<AMessage> msg = new AMessage(); 636513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 637513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar size_t i = 0; 638513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar while (attrs[i] != NULL) { 639513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (attrs[i + 1] == NULL) { 640513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return -EINVAL; 641513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 642513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 643513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar // attributes with values 644513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (!strcmp(attrs[i], "name") 645513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar || !strcmp(attrs[i], "default") 646513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar || !strcmp(attrs[i], "in") 647513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar || !strcmp(attrs[i], "max") 648513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar || !strcmp(attrs[i], "min") 649513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar || !strcmp(attrs[i], "range") 650513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar || !strcmp(attrs[i], "ranges") 651513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar || !strcmp(attrs[i], "scale") 652513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar || !strcmp(attrs[i], "value")) { 653513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar msg->setString(attrs[i], attrs[i + 1]); 654513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar ++i; 655513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } else { 656513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return -EINVAL; 657513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 658513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar ++i; 659513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 660513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 661513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar AString name; 662513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (!msg->findString("name", &name)) { 663513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar ALOGE("limit with no 'name' attribute"); 664513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return -EINVAL; 665513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 666513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 667513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar // size, blocks, bitrate, frame-rate, blocks-per-second, aspect-ratio: range 668513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar // quality: range + default + [scale] 669513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar // complexity: range + default 670513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar bool found; 67160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar 672513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (name == "aspect-ratio" || name == "bitrate" || name == "block-count" 673513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar || name == "blocks-per-second" || name == "complexity" 674513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar || name == "frame-rate" || name == "quality" || name == "size") { 675513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar AString min, max; 676513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (msg->findString("min", &min) && msg->findString("max", &max)) { 677513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar min.append("-"); 678513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar min.append(max); 679513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (msg->contains("range") || msg->contains("value")) { 680513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return limitError(name, "has 'min' and 'max' as well as 'range' or " 681513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar "'value' attributes"); 682513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 683513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar msg->setString("range", min); 684513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } else if (msg->contains("min") || msg->contains("max")) { 685513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return limitError(name, "has only 'min' or 'max' attribute"); 686513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } else if (msg->findString("value", &max)) { 687513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar min = max; 688513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar min.append("-"); 689513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar min.append(max); 690513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (msg->contains("range")) { 691513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return limitError(name, "has both 'range' and 'value' attributes"); 692513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 693513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar msg->setString("range", min); 694513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 695513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 696513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar AString range, scale = "linear", def, in_; 697513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (!msg->findString("range", &range)) { 698513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return limitError(name, "with no 'range', 'value' or 'min'/'max' attributes"); 699513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 700513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 701513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if ((name == "quality" || name == "complexity") ^ 702513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar (found = msg->findString("default", &def))) { 703513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return limitFoundMissingAttr(name, "default", found); 704513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 705513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (name != "quality" && msg->findString("scale", &scale)) { 706513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return limitFoundMissingAttr(name, "scale"); 707513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 708513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if ((name == "aspect-ratio") ^ (found = msg->findString("in", &in_))) { 709513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return limitFoundMissingAttr(name, "in", found); 710513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 711513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 712513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (name == "aspect-ratio") { 713513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (!(in_ == "pixels") && !(in_ == "blocks")) { 714513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return limitInvalidAttr(name, "in", in_); 715513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 716513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar in_.erase(5, 1); // (pixel|block)-aspect-ratio 717513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar in_.append("-"); 718513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar in_.append(name); 719513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar name = in_; 720513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 721513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (name == "quality") { 72260b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mCurrentInfo->addDetail("quality-scale", scale); 723513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 724513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (name == "quality" || name == "complexity") { 725513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar AString tag = name; 726513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar tag.append("-default"); 72760b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mCurrentInfo->addDetail(tag, def); 728513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 729513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar AString tag = name; 730513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar tag.append("-range"); 73160b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mCurrentInfo->addDetail(tag, range); 732513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } else { 733513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar AString max, value, ranges; 734513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (msg->contains("default")) { 735513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return limitFoundMissingAttr(name, "default"); 736513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } else if (msg->contains("in")) { 737513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return limitFoundMissingAttr(name, "in"); 738513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } else if ((name == "channel-count") ^ 739513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar (found = msg->findString("max", &max))) { 740513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return limitFoundMissingAttr(name, "max", found); 741513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } else if (msg->contains("min")) { 742513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return limitFoundMissingAttr(name, "min"); 743513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } else if (msg->contains("range")) { 744513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return limitFoundMissingAttr(name, "range"); 745513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } else if ((name == "sample-rate") ^ 746513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar (found = msg->findString("ranges", &ranges))) { 747513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return limitFoundMissingAttr(name, "ranges", found); 748513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } else if (msg->contains("scale")) { 749513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return limitFoundMissingAttr(name, "scale"); 750513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } else if ((name == "alignment" || name == "block-size") ^ 751513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar (found = msg->findString("value", &value))) { 752513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return limitFoundMissingAttr(name, "value", found); 753513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 754513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 755513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (max.size()) { 756513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar AString tag = "max-"; 757513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar tag.append(name); 75860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mCurrentInfo->addDetail(tag, max); 759513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } else if (value.size()) { 76060b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mCurrentInfo->addDetail(name, value); 761513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } else if (ranges.size()) { 762513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar AString tag = name; 763513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar tag.append("-ranges"); 76460b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar mCurrentInfo->addDetail(tag, ranges); 765513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } else { 766513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar ALOGW("Ignoring unrecognized limit '%s'", name.c_str()); 767513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 768513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 769513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return OK; 770513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar} 771513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 772513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatic bool parseBoolean(const char *s) { 773513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (!strcasecmp(s, "true") || !strcasecmp(s, "yes") || !strcasecmp(s, "y")) { 774513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return true; 775513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 776513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar char *end; 777513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar unsigned long res = strtoul(s, &end, 10); 778513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return *s != '\0' && *end == '\0' && res > 0; 779513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar} 780513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 781513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnarstatus_t MediaCodecList::addFeature(const char **attrs) { 782513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar size_t i = 0; 783513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar const char *name = NULL; 784513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar int32_t optional = -1; 785513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar int32_t required = -1; 786732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar const char *value = NULL; 787513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 788513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar while (attrs[i] != NULL) { 789513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (attrs[i + 1] == NULL) { 790513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return -EINVAL; 791513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 792513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 793513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar // attributes with values 794513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (!strcmp(attrs[i], "name")) { 795513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar name = attrs[i + 1]; 796513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar ++i; 797513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } else if (!strcmp(attrs[i], "optional") || !strcmp(attrs[i], "required")) { 798513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar int value = (int)parseBoolean(attrs[i + 1]); 799513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (!strcmp(attrs[i], "optional")) { 800513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar optional = value; 801513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } else { 802513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar required = value; 803513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 804513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar ++i; 805732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar } else if (!strcmp(attrs[i], "value")) { 806732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar value = attrs[i + 1]; 807732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar ++i; 808513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } else { 809513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return -EINVAL; 810513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 811513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar ++i; 812513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 813513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (name == NULL) { 814513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar ALOGE("feature with no 'name' attribute"); 815513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return -EINVAL; 816513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 817513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 818513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar if (optional == required && optional != -1) { 819513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar ALOGE("feature '%s' is both/neither optional and required", name); 820513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return -EINVAL; 821513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar } 822513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 823732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar if ((optional != -1 || required != -1) && (value != NULL)) { 824732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar ALOGE("feature '%s' has both a value and optional/required attribute", name); 825732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar return -EINVAL; 826732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar } 827732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar 828732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar if (value != NULL) { 829732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar mCurrentInfo->addFeature(name, value); 830732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar } else { 831732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar mCurrentInfo->addFeature(name, (required == 1) || (optional == 0)); 832732c6d955524ead6c31e6e1bafbd41ea4cee525dLajos Molnar } 833513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar return OK; 834513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar} 835513d967dae82cd03e67bff17b927cf869d9bc43eLajos Molnar 836afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huberssize_t MediaCodecList::findCodecByName(const char *name) const { 837afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber for (size_t i = 0; i < mCodecInfos.size(); ++i) { 83860b1c0e79d12a1c70758bc8d060156924635f8baLajos Molnar const MediaCodecInfo &info = *mCodecInfos.itemAt(i).get(); 839afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 840afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber if (info.mName == name) { 841afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber return i; 842afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 843afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber } 844afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 845afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber return -ENOENT; 846afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber} 847afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber 84869829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Hubersize_t MediaCodecList::countCodecs() const { 84969829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber return mCodecInfos.size(); 85069829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber} 85169829f3bd09ee4e6be49fee8795c5df24c4da70eAndreas Huber 852afc16d667afa23f5aa00154ccad62f8c45cf5419Andreas Huber} // namespace android 853