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.
529e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wustatic bool getMeasureSize(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
759e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wustatic void getMeasureBitrate(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(
939e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        bool isEncoder, AString mime, 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
13079608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhangstatic size_t doProfileEncoderInputBuffers(
13179608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang        AString name, AString mime, sp<MediaCodecInfo::Capabilities> caps) {
13279608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    ALOGV("doProfileEncoderInputBuffers: name %s, mime %s", name.c_str(), mime.c_str());
13379608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang
13479608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    sp<AMessage> format = getMeasureFormat(true /* isEncoder */, mime, caps);
13579608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    if (format == NULL) {
13679608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang        return 0;
13779608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    }
13879608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang
13979608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    format->setInt32("color-format", OMX_COLOR_FormatAndroidOpaque);
14079608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    ALOGV("doProfileEncoderInputBuffers: format %s", format->debugString().c_str());
14179608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang
14279608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    status_t err = OK;
14379608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    sp<ALooper> looper = new ALooper;
14479608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    looper->setName("MediaCodec_looper");
14579608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    looper->start(
14679608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang            false /* runOnCallingThread */, false /* canCallJava */, ANDROID_PRIORITY_AUDIO);
14779608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang
14879608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    sp<MediaCodec> codec = MediaCodec::CreateByComponentName(looper, name.c_str(), &err);
14979608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    if (err != OK) {
15079608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang        ALOGE("Failed to create codec: %s", name.c_str());
15179608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang        return 0;
15279608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    }
15379608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang
15479608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    err = codec->configure(format, NULL, NULL, MediaCodec::CONFIGURE_FLAG_ENCODE);
15579608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    if (err != OK) {
15679608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang        ALOGE("Failed to configure codec: %s with mime: %s", name.c_str(), mime.c_str());
15779608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang        codec->release();
15879608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang        return 0;
15979608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    }
16079608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang
16179608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    sp<IGraphicBufferProducer> bufferProducer;
16279608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    err = codec->createInputSurface(&bufferProducer);
16379608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    if (err != OK) {
16479608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang        ALOGE("Failed to create surface: %s with mime: %s", name.c_str(), mime.c_str());
16579608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang        codec->release();
16679608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang        return 0;
16779608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    }
16879608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang
16979608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    int minUndequeued = 0;
17079608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    err = bufferProducer->query(
17179608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeued);
17279608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    if (err != OK) {
17379608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang        ALOGE("Failed to query NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS");
17479608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang        minUndequeued = 0;
17579608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    }
17679608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang
17779608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    err = codec->release();
17879608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    if (err != OK) {
17979608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang        ALOGW("Failed to release codec: %s with mime: %s", name.c_str(), mime.c_str());
18079608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    }
18179608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang
18279608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    return minUndequeued;
18379608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang}
18479608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang
1859e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wustatic size_t doProfileCodecs(
1869e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        bool isEncoder, AString name, AString mime, sp<MediaCodecInfo::Capabilities> caps) {
1879e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    sp<AMessage> format = getMeasureFormat(isEncoder, mime, caps);
1889e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    if (format == NULL) {
1899e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        return 0;
1909e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    }
1919e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    ALOGV("doProfileCodecs %s %s %s %s",
1929e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu            name.c_str(), mime.c_str(), isEncoder ? "encoder" : "decoder",
1939e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu            format->debugString().c_str());
1949e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu
1959e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    status_t err = OK;
1969e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    Vector<sp<MediaCodec>> codecs;
1979e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    while (err == OK && codecs.size() < kMaxInstances) {
1989e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        sp<ALooper> looper = new ALooper;
1999e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        looper->setName("MediaCodec_looper");
200ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar        ALOGV("doProfileCodecs for codec #%zu", codecs.size());
2019e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        ALOGV("doProfileCodecs start looper");
2029e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        looper->start(
2039e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu                false /* runOnCallingThread */, false /* canCallJava */, ANDROID_PRIORITY_AUDIO);
2049e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        ALOGV("doProfileCodecs CreateByComponentName");
2059e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        sp<MediaCodec> codec = MediaCodec::CreateByComponentName(looper, name.c_str(), &err);
2069e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        if (err != OK) {
2079e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu            ALOGV("Failed to create codec: %s", name.c_str());
2089e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu            break;
2099e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        }
2109e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        const sp<Surface> nativeWindow;
2119e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        const sp<ICrypto> crypto;
21279608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang        uint32_t flags = isEncoder ? MediaCodec::CONFIGURE_FLAG_ENCODE : 0;
2139e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        ALOGV("doProfileCodecs configure");
2149e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        err = codec->configure(format, nativeWindow, crypto, flags);
2159e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        if (err != OK) {
2169e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu            ALOGV("Failed to configure codec: %s with mime: %s", name.c_str(), mime.c_str());
2179e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu            codec->release();
2189e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu            break;
2199e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        }
2209e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        ALOGV("doProfileCodecs start");
2219e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        err = codec->start();
2229e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        if (err != OK) {
2239e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu            ALOGV("Failed to start codec: %s with mime: %s", name.c_str(), mime.c_str());
2249e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu            codec->release();
2259e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu            break;
2269e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        }
2279e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        codecs.push_back(codec);
2289e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    }
2299e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu
2309e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    for (size_t i = 0; i < codecs.size(); ++i) {
2319e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        ALOGV("doProfileCodecs release %s", name.c_str());
2329e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        err = codecs[i]->release();
2339e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        if (err != OK) {
2349e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu            ALOGE("Failed to release codec: %s with mime: %s", name.c_str(), mime.c_str());
2359e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        }
2369e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    }
2379e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu
2389e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    return codecs.size();
2399e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu}
2409e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu
2419e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wubool splitString(const AString &s, const AString &delimiter, AString *s1, AString *s2) {
2429e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    ssize_t pos = s.find(delimiter.c_str());
2439e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    if (pos < 0) {
2449e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        return false;
2459e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    }
2469e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    *s1 = AString(s, 0, pos);
2479e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    *s2 = AString(s, pos + 1, s.size() - pos - 1);
2489e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    return true;
2499e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu}
2509e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu
2519e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wubool splitString(
2529e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        const AString &s, const AString &delimiter, AString *s1, AString *s2, AString *s3) {
2539e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    AString temp;
2549e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    if (!splitString(s, delimiter, s1, &temp)) {
2559e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        return false;
2569e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    }
2579e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    if (!splitString(temp, delimiter, s2, s3)) {
2589e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        return false;
2599e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    }
2609e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    return true;
2619e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu}
2629e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu
26365c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wuvoid profileCodecs(const Vector<sp<MediaCodecInfo>> &infos) {
2649ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu    CodecSettings global_results;
26565c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu    KeyedVector<AString, CodecSettings> encoder_results;
26665c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu    KeyedVector<AString, CodecSettings> decoder_results;
2679ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu    profileCodecs(infos, &global_results, &encoder_results, &decoder_results);
26865c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu    exportResultsToXML(kProfilingResults, global_results, encoder_results, decoder_results);
26965c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu}
27065c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu
2719e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wuvoid profileCodecs(
2729e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        const Vector<sp<MediaCodecInfo>> &infos,
2739ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu        CodecSettings *global_results,
27465c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        KeyedVector<AString, CodecSettings> *encoder_results,
27565c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        KeyedVector<AString, CodecSettings> *decoder_results,
2769e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        bool forceToMeasure) {
2779e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    KeyedVector<AString, sp<MediaCodecInfo::Capabilities>> codecsNeedMeasure;
2789ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu    AString supportMultipleSecureCodecs = "true";
27979608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    size_t maxEncoderInputBuffers = 0;
2809e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    for (size_t i = 0; i < infos.size(); ++i) {
2819e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        const sp<MediaCodecInfo> info = infos[i];
2829e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        AString name = info->getCodecName();
2839e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        if (name.startsWith("OMX.google.") ||
2849e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu                // TODO: reenable below codecs once fixed
2859e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu                name == "OMX.Intel.VideoDecoder.VP9.hybrid") {
2869e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu            continue;
2879e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        }
2889e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu
2899e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        Vector<AString> mimes;
2909e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        info->getSupportedMimes(&mimes);
2919e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        for (size_t i = 0; i < mimes.size(); ++i) {
2929e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu            const sp<MediaCodecInfo::Capabilities> &caps =
2939e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu                    info->getCapabilitiesFor(mimes[i].c_str());
2940f29c9d205ff03286da629d30fddd5dd5ca020dbRonghua Wu            if (!forceToMeasure &&
2950f29c9d205ff03286da629d30fddd5dd5ca020dbRonghua Wu                (caps->getDetails()->contains("max-supported-instances") ||
2960f29c9d205ff03286da629d30fddd5dd5ca020dbRonghua Wu                 caps->getDetails()->contains("max-concurrent-instances"))) {
2979e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu                continue;
2989e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu            }
2999e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu
3009e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu            size_t max = doProfileCodecs(info->isEncoder(), name, mimes[i], caps);
3019e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu            if (max > 0) {
3029e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu                CodecSettings settings;
3039e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu                char maxStr[32];
304ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar                sprintf(maxStr, "%zu", max);
3059e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu                settings.add("max-supported-instances", maxStr);
3069e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu
3079e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu                AString key = name;
3089e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu                key.append(" ");
3099e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu                key.append(mimes[i]);
3109e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu
31165c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu                if (info->isEncoder()) {
31265c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu                    encoder_results->add(key, settings);
31365c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu                } else {
31465c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu                    decoder_results->add(key, settings);
31565c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu                }
3169ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu
3179ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu                if (name.endsWith(".secure")) {
3189ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu                    if (max <= 1) {
3199ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu                        supportMultipleSecureCodecs = "false";
3209ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu                    }
3219ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu                }
32279608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang                if (info->isEncoder() && mimes[i].startsWith("video/")) {
32379608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang                    size_t encoderInputBuffers =
32479608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang                        doProfileEncoderInputBuffers(name, mimes[i], caps);
32579608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang                    if (encoderInputBuffers > maxEncoderInputBuffers) {
32679608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang                        maxEncoderInputBuffers = encoderInputBuffers;
32779608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang                    }
32879608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang                }
3299e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu            }
3309e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        }
3319e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    }
33279608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    if (maxEncoderInputBuffers > 0) {
33379608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang        char tmp[32];
33479608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang        sprintf(tmp, "%zu", maxEncoderInputBuffers);
33579608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang        global_results->add(kMaxEncoderInputBuffers, tmp);
33679608158c2254fe1357959157f2d0c1560a8a6c6Chong Zhang    }
3379ba21b9418d10ddcc39f08901e24fbf43d82b2bcRonghua Wu    global_results->add(kPolicySupportsMultipleSecureCodecs, supportMultipleSecureCodecs);
3389e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu}
3399e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu
34065c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wustatic AString globalResultsToXml(const CodecSettings& results) {
34165c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu    AString ret;
3429e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    for (size_t i = 0; i < results.size(); ++i) {
34365c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        AString setting = AStringPrintf(
34465c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu                "        <Setting name=\"%s\" value=\"%s\" />\n",
34565c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu                results.keyAt(i).c_str(),
34665c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu                results.valueAt(i).c_str());
34765c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        ret.append(setting);
3489e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    }
34965c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu    return ret;
35065c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu}
3519e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu
35265c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wustatic AString codecResultsToXml(const KeyedVector<AString, CodecSettings>& results) {
35365c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu    AString ret;
3549e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    for (size_t i = 0; i < results.size(); ++i) {
3559e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        AString name;
3569e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        AString mime;
35765c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        if (!splitString(results.keyAt(i), " ", &name, &mime)) {
3589e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu            continue;
3599e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        }
36065c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        AString codec =
36165c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu                AStringPrintf("        <MediaCodec name=\"%s\" type=\"%s\" update=\"true\" >\n",
36265c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu                              name.c_str(),
36365c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu                              mime.c_str());
36465c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        ret.append(codec);
3659e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        CodecSettings settings = results.valueAt(i);
3669e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        for (size_t i = 0; i < settings.size(); ++i) {
3679e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu            // WARNING: we assume all the settings are "Limit". Currently we have only one type
3689e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu            // of setting in this case, which is "max-supported-instances".
36965c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu            AString setting = AStringPrintf(
37065c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu                    "            <Limit name=\"%s\" value=\"%s\" />\n",
3719e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu                    settings.keyAt(i).c_str(),
3729e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu                    settings.valueAt(i).c_str());
37365c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu            ret.append(setting);
3749e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        }
37565c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        ret.append("        </MediaCodec>\n");
37665c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu    }
37765c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu    return ret;
37865c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu}
37965c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu
38065c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wuvoid exportResultsToXML(
38165c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        const char *fileName,
38265c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        const CodecSettings& global_results,
38365c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        const KeyedVector<AString, CodecSettings>& encoder_results,
38465c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        const KeyedVector<AString, CodecSettings>& decoder_results) {
38565c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu    if (global_results.size() == 0 && encoder_results.size() == 0 && decoder_results.size() == 0) {
38665c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        return;
3879e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    }
3889e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu
38965c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu    AString overrides;
39019352b3287480394aa9963276305d5168a7adf85Ronghua Wu    overrides.append(getProfilingVersionString());
39119352b3287480394aa9963276305d5168a7adf85Ronghua Wu    overrides.append("\n");
39265c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu    overrides.append("<MediaCodecs>\n");
39365c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu    if (global_results.size() > 0) {
39465c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        overrides.append("    <Settings>\n");
39565c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        overrides.append(globalResultsToXml(global_results));
39665c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        overrides.append("    </Settings>\n");
39765c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu    }
39865c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu    if (encoder_results.size() > 0) {
39965c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        overrides.append("    <Encoders>\n");
40065c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        overrides.append(codecResultsToXml(encoder_results));
40165c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        overrides.append("    </Encoders>\n");
40265c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu    }
40365c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu    if (decoder_results.size() > 0) {
40465c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        overrides.append("    <Decoders>\n");
40565c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        overrides.append(codecResultsToXml(decoder_results));
40665c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu        overrides.append("    </Decoders>\n");
4073b0da19c78f6a61ed343a07f2448b94faafe4c02Lajos Molnar    }
40865c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu    overrides.append("</MediaCodecs>\n");
4099e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu
41065c8fbcf91f0f0b5f60a45d2777c36d396c4ba16Ronghua Wu    FILE *f = fopen(fileName, "wb");
4119e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    if (f == NULL) {
4129e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        ALOGE("Failed to open %s for writing.", fileName);
4139e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        return;
4149e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    }
4159e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    if (fwrite(overrides.c_str(), 1, overrides.size(), f) != overrides.size()) {
4169e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu        ALOGE("Failed to write to %s.", fileName);
4179e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    }
4189e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu    fclose(f);
4199e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu}
4209e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu
4219e6955a19bf77ebf27b770e910efbe1ebf1ceac0Ronghua Wu}  // namespace android
422