19e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu/* 29e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu * Copyright 2015 The Android Open Source Project 39e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu * 49e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu * Licensed under the Apache License, Version 2.0 (the "License"); 59e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu * you may not use this file except in compliance with the License. 69e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu * You may obtain a copy of the License at 79e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu * 89e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu * http://www.apache.org/licenses/LICENSE-2.0 99e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu * 109e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu * Unless required by applicable law or agreed to in writing, software 119e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu * distributed under the License is distributed on an "AS IS" BASIS, 129e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu * See the License for the specific language governing permissions and 149e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu * limitations under the License. 159e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu */ 169e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 179e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu//#define LOG_NDEBUG 0 189e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu#define LOG_TAG "MediaCodecListOverrides" 199e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu#include <utils/Log.h> 209e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 219e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu#include "MediaCodecListOverrides.h" 229e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 2319352b3287480394aa9963276305d5168a7adf85Ronghua Wu#include <cutils/properties.h> 249e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu#include <gui/Surface.h> 259e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu#include <media/ICrypto.h> 269e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu#include <media/IMediaCodecList.h> 279e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu#include <media/MediaCodecInfo.h> 289ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu#include <media/MediaResourcePolicy.h> 2979608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang#include <media/openmax/OMX_IVCommon.h> 309e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu#include <media/stagefright/foundation/AMessage.h> 319e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu#include <media/stagefright/MediaCodec.h> 3279608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang#include <media/stagefright/MediaCodecList.h> 339e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 349e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wunamespace android { 359e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 3665c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wuconst char *kProfilingResults = "/data/misc/media/media_codecs_profiling_results.xml"; 3765c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu 3819352b3287480394aa9963276305d5168a7adf85Ronghua WuAString getProfilingVersionString() { 3919352b3287480394aa9963276305d5168a7adf85Ronghua Wu char val[PROPERTY_VALUE_MAX]; 4019352b3287480394aa9963276305d5168a7adf85Ronghua Wu if (property_get("ro.build.display.id", val, NULL) && (strlen(val) > 0)) { 4119352b3287480394aa9963276305d5168a7adf85Ronghua Wu return AStringPrintf("<!-- Profiled-with: %s -->", val); 4219352b3287480394aa9963276305d5168a7adf85Ronghua Wu } 4319352b3287480394aa9963276305d5168a7adf85Ronghua Wu 4419352b3287480394aa9963276305d5168a7adf85Ronghua Wu return "<!-- Profiled-with: UNKNOWN_BUILD_ID -->"; 4519352b3287480394aa9963276305d5168a7adf85Ronghua Wu} 4619352b3287480394aa9963276305d5168a7adf85Ronghua Wu 479e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu// a limit to avoid allocating unreasonable number of codec instances in the measurement. 489e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu// this should be in sync with the MAX_SUPPORTED_INSTANCES defined in MediaCodecInfo.java. 499e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wustatic const int kMaxInstances = 32; 509e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 519e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu// TODO: move MediaCodecInfo to C++. Until then, some temp methods to parse out info. 5240d8899f60c5212af9d727ba0ffaaecf676ebd1dChih-Hung Hsiehstatic bool getMeasureSize(const sp<MediaCodecInfo::Capabilities> &caps, int32_t *width, int32_t *height) { 539e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu AString sizeRange; 549e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (!caps->getDetails()->findString("size-range", &sizeRange)) { 559e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu return false; 569e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 579e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu AString minSize; 589e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu AString maxSize; 599e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (!splitString(sizeRange, "-", &minSize, &maxSize)) { 609e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu return false; 619e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 629e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu AString sWidth; 639e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu AString sHeight; 649e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (!splitString(minSize, "x", &sWidth, &sHeight)) { 659e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (!splitString(minSize, "*", &sWidth, &sHeight)) { 669e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu return false; 679e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 689e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 699e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 709e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu *width = strtol(sWidth.c_str(), NULL, 10); 719e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu *height = strtol(sHeight.c_str(), NULL, 10); 729e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu return (*width > 0) && (*height > 0); 739e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu} 749e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 7540d8899f60c5212af9d727ba0ffaaecf676ebd1dChih-Hung Hsiehstatic void getMeasureBitrate(const sp<MediaCodecInfo::Capabilities> &caps, int32_t *bitrate) { 769e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu // Until have native MediaCodecInfo, we cannot get bitrates based on profile/levels. 779e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu // We use 200000 as default value for our measurement. 789e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu *bitrate = 200000; 799e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu AString bitrateRange; 809e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (!caps->getDetails()->findString("bitrate-range", &bitrateRange)) { 819e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu return; 829e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 839e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu AString minBitrate; 849e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu AString maxBitrate; 859e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (!splitString(bitrateRange, "-", &minBitrate, &maxBitrate)) { 869e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu return; 879e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 889e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 899e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu *bitrate = strtol(minBitrate.c_str(), NULL, 10); 909e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu} 919e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 929e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wustatic sp<AMessage> getMeasureFormat( 9340d8899f60c5212af9d727ba0ffaaecf676ebd1dChih-Hung Hsieh bool isEncoder, const AString &mime, const sp<MediaCodecInfo::Capabilities> &caps) { 949e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu sp<AMessage> format = new AMessage(); 959e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu format->setString("mime", mime); 969e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 979e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (isEncoder) { 989e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu int32_t bitrate = 0; 999e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu getMeasureBitrate(caps, &bitrate); 1009e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu format->setInt32("bitrate", bitrate); 10179608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang format->setInt32("encoder", 1); 1029e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 1039e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 1049e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (mime.startsWith("video/")) { 1059e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu int32_t width = 0; 1069e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu int32_t height = 0; 1079e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (!getMeasureSize(caps, &width, &height)) { 1089e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu return NULL; 1099e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 1109e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu format->setInt32("width", width); 1119e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu format->setInt32("height", height); 1129e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 1139e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu Vector<uint32_t> colorFormats; 1149e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu caps->getSupportedColorFormats(&colorFormats); 1159e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (colorFormats.size() == 0) { 1169e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu return NULL; 1179e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 1189e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu format->setInt32("color-format", colorFormats[0]); 1199e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 1209e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu format->setFloat("frame-rate", 10.0); 1219e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu format->setInt32("i-frame-interval", 10); 1229e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } else { 1239e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu // TODO: profile hw audio 1249e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu return NULL; 1259e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 1269e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 1279e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu return format; 1289e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu} 1299e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 1309e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wustatic size_t doProfileCodecs( 13140d8899f60c5212af9d727ba0ffaaecf676ebd1dChih-Hung Hsieh bool isEncoder, const AString &name, const AString &mime, const sp<MediaCodecInfo::Capabilities> &caps) { 1329e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu sp<AMessage> format = getMeasureFormat(isEncoder, mime, caps); 1339e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (format == NULL) { 1349e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu return 0; 1359e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 1369e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu ALOGV("doProfileCodecs %s %s %s %s", 1379e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu name.c_str(), mime.c_str(), isEncoder ? "encoder" : "decoder", 1389e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu format->debugString().c_str()); 1399e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 1409e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu status_t err = OK; 1419e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu Vector<sp<MediaCodec>> codecs; 1429e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu while (err == OK && codecs.size() < kMaxInstances) { 1439e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu sp<ALooper> looper = new ALooper; 1449e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu looper->setName("MediaCodec_looper"); 145ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar ALOGV("doProfileCodecs for codec #%zu", codecs.size()); 1469e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu ALOGV("doProfileCodecs start looper"); 1479e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu looper->start( 1489e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu false /* runOnCallingThread */, false /* canCallJava */, ANDROID_PRIORITY_AUDIO); 1499e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu ALOGV("doProfileCodecs CreateByComponentName"); 1509e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu sp<MediaCodec> codec = MediaCodec::CreateByComponentName(looper, name.c_str(), &err); 1519e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (err != OK) { 1529e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu ALOGV("Failed to create codec: %s", name.c_str()); 1539e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu break; 1549e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 1559e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu const sp<Surface> nativeWindow; 1569e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu const sp<ICrypto> crypto; 15779608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang uint32_t flags = isEncoder ? MediaCodec::CONFIGURE_FLAG_ENCODE : 0; 1589e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu ALOGV("doProfileCodecs configure"); 1599e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu err = codec->configure(format, nativeWindow, crypto, flags); 1609e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (err != OK) { 1619e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu ALOGV("Failed to configure codec: %s with mime: %s", name.c_str(), mime.c_str()); 1629e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu codec->release(); 1639e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu break; 1649e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 1659e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu ALOGV("doProfileCodecs start"); 1669e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu err = codec->start(); 1679e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (err != OK) { 1689e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu ALOGV("Failed to start codec: %s with mime: %s", name.c_str(), mime.c_str()); 1699e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu codec->release(); 1709e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu break; 1719e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 1729e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu codecs.push_back(codec); 1739e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 1749e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 1759e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu for (size_t i = 0; i < codecs.size(); ++i) { 1769e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu ALOGV("doProfileCodecs release %s", name.c_str()); 1779e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu err = codecs[i]->release(); 1789e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (err != OK) { 1799e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu ALOGE("Failed to release codec: %s with mime: %s", name.c_str(), mime.c_str()); 1809e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 1819e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 1829e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 1839e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu return codecs.size(); 1849e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu} 1859e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 1869e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wubool splitString(const AString &s, const AString &delimiter, AString *s1, AString *s2) { 1879e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu ssize_t pos = s.find(delimiter.c_str()); 1889e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (pos < 0) { 1899e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu return false; 1909e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 1919e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu *s1 = AString(s, 0, pos); 1929e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu *s2 = AString(s, pos + 1, s.size() - pos - 1); 1939e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu return true; 1949e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu} 1959e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 1969e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wubool splitString( 1979e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu const AString &s, const AString &delimiter, AString *s1, AString *s2, AString *s3) { 1989e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu AString temp; 1999e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (!splitString(s, delimiter, s1, &temp)) { 2009e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu return false; 2019e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 2029e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (!splitString(temp, delimiter, s2, s3)) { 2039e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu return false; 2049e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 2059e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu return true; 2069e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu} 2079e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 20865c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wuvoid profileCodecs(const Vector<sp<MediaCodecInfo>> &infos) { 2099ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu CodecSettings global_results; 21065c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu KeyedVector<AString, CodecSettings> encoder_results; 21165c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu KeyedVector<AString, CodecSettings> decoder_results; 2129ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu profileCodecs(infos, &global_results, &encoder_results, &decoder_results); 21365c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu exportResultsToXML(kProfilingResults, global_results, encoder_results, decoder_results); 21465c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu} 21565c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu 2169e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wuvoid profileCodecs( 2179e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu const Vector<sp<MediaCodecInfo>> &infos, 2189ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu CodecSettings *global_results, 21965c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu KeyedVector<AString, CodecSettings> *encoder_results, 22065c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu KeyedVector<AString, CodecSettings> *decoder_results, 2219e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu bool forceToMeasure) { 2229e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu KeyedVector<AString, sp<MediaCodecInfo::Capabilities>> codecsNeedMeasure; 2239ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu AString supportMultipleSecureCodecs = "true"; 2249e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu for (size_t i = 0; i < infos.size(); ++i) { 2259e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu const sp<MediaCodecInfo> info = infos[i]; 2269e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu AString name = info->getCodecName(); 2279e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (name.startsWith("OMX.google.") || 2289e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu // TODO: reenable below codecs once fixed 2299e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu name == "OMX.Intel.VideoDecoder.VP9.hybrid") { 2309e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu continue; 2319e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 2329e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 2339e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu Vector<AString> mimes; 2349e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu info->getSupportedMimes(&mimes); 2359e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu for (size_t i = 0; i < mimes.size(); ++i) { 2369e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu const sp<MediaCodecInfo::Capabilities> &caps = 2379e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu info->getCapabilitiesFor(mimes[i].c_str()); 2380f29c9d205ff03286da629d30fddd5dd5ca020dbRonghua Wu if (!forceToMeasure && 2390f29c9d205ff03286da629d30fddd5dd5ca020dbRonghua Wu (caps->getDetails()->contains("max-supported-instances") || 2400f29c9d205ff03286da629d30fddd5dd5ca020dbRonghua Wu caps->getDetails()->contains("max-concurrent-instances"))) { 2419e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu continue; 2429e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 2439e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 2449e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu size_t max = doProfileCodecs(info->isEncoder(), name, mimes[i], caps); 2459e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (max > 0) { 2469e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu CodecSettings settings; 2479e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu char maxStr[32]; 248ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar sprintf(maxStr, "%zu", max); 2499e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu settings.add("max-supported-instances", maxStr); 2509e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 2519e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu AString key = name; 2529e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu key.append(" "); 2539e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu key.append(mimes[i]); 2549e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 25565c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu if (info->isEncoder()) { 25665c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu encoder_results->add(key, settings); 25765c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu } else { 25865c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu decoder_results->add(key, settings); 25965c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu } 2609ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu 2619ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu if (name.endsWith(".secure")) { 2629ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu if (max <= 1) { 2639ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu supportMultipleSecureCodecs = "false"; 2649ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu } 2659ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu } 2669e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 2679e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 2689e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 2699ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu global_results->add(kPolicySupportsMultipleSecureCodecs, supportMultipleSecureCodecs); 2709e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu} 2719e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 27240d8899f60c5212af9d727ba0ffaaecf676ebd1dChih-Hung Hsiehstatic AString globalResultsToXml(const CodecSettings &results) { 27365c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu AString ret; 2749e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu for (size_t i = 0; i < results.size(); ++i) { 27565c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu AString setting = AStringPrintf( 27665c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu " <Setting name=\"%s\" value=\"%s\" />\n", 27765c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu results.keyAt(i).c_str(), 27865c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu results.valueAt(i).c_str()); 27965c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu ret.append(setting); 2809e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 28165c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu return ret; 28265c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu} 2839e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 28440d8899f60c5212af9d727ba0ffaaecf676ebd1dChih-Hung Hsiehstatic AString codecResultsToXml(const KeyedVector<AString, CodecSettings> &results) { 28565c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu AString ret; 2869e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu for (size_t i = 0; i < results.size(); ++i) { 2879e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu AString name; 2889e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu AString mime; 28965c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu if (!splitString(results.keyAt(i), " ", &name, &mime)) { 2909e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu continue; 2919e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 29265c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu AString codec = 29365c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu AStringPrintf(" <MediaCodec name=\"%s\" type=\"%s\" update=\"true\" >\n", 29465c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu name.c_str(), 29565c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu mime.c_str()); 29665c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu ret.append(codec); 29740d8899f60c5212af9d727ba0ffaaecf676ebd1dChih-Hung Hsieh const CodecSettings &settings = results.valueAt(i); 2989e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu for (size_t i = 0; i < settings.size(); ++i) { 2999e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu // WARNING: we assume all the settings are "Limit". Currently we have only one type 3009e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu // of setting in this case, which is "max-supported-instances". 30165c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu AString setting = AStringPrintf( 30265c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu " <Limit name=\"%s\" value=\"%s\" />\n", 3039e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu settings.keyAt(i).c_str(), 3049e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu settings.valueAt(i).c_str()); 30565c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu ret.append(setting); 3069e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 30765c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu ret.append(" </MediaCodec>\n"); 30865c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu } 30965c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu return ret; 31065c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu} 31165c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu 31265c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wuvoid exportResultsToXML( 31365c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu const char *fileName, 31440d8899f60c5212af9d727ba0ffaaecf676ebd1dChih-Hung Hsieh const CodecSettings &global_results, 31540d8899f60c5212af9d727ba0ffaaecf676ebd1dChih-Hung Hsieh const KeyedVector<AString, CodecSettings> &encoder_results, 31640d8899f60c5212af9d727ba0ffaaecf676ebd1dChih-Hung Hsieh const KeyedVector<AString, CodecSettings> &decoder_results) { 31765c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu if (global_results.size() == 0 && encoder_results.size() == 0 && decoder_results.size() == 0) { 31865c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu return; 3199e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 3209e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 32165c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu AString overrides; 32219352b3287480394aa9963276305d5168a7adf85Ronghua Wu overrides.append(getProfilingVersionString()); 32319352b3287480394aa9963276305d5168a7adf85Ronghua Wu overrides.append("\n"); 32465c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu overrides.append("<MediaCodecs>\n"); 32565c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu if (global_results.size() > 0) { 32665c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu overrides.append(" <Settings>\n"); 32765c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu overrides.append(globalResultsToXml(global_results)); 32865c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu overrides.append(" </Settings>\n"); 32965c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu } 33065c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu if (encoder_results.size() > 0) { 33165c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu overrides.append(" <Encoders>\n"); 33265c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu overrides.append(codecResultsToXml(encoder_results)); 33365c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu overrides.append(" </Encoders>\n"); 33465c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu } 33565c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu if (decoder_results.size() > 0) { 33665c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu overrides.append(" <Decoders>\n"); 33765c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu overrides.append(codecResultsToXml(decoder_results)); 33865c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu overrides.append(" </Decoders>\n"); 3393b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar } 34065c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu overrides.append("</MediaCodecs>\n"); 3419e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 34265c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu FILE *f = fopen(fileName, "wb"); 3439e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (f == NULL) { 3449e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu ALOGE("Failed to open %s for writing.", fileName); 3459e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu return; 3469e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 3479e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu if (fwrite(overrides.c_str(), 1, overrides.size(), f) != overrides.size()) { 3489e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu ALOGE("Failed to write to %s.", fileName); 3499e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu } 3509e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu fclose(f); 3519e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu} 3529e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu 3539e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu} // namespace android 354