blob: 170cde3298fa930f5ee000b31a52765a666fcafa [file] [log] [blame]
/*
* Copyright 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// #define LOG_NDEBUG 0
#define LOG_TAG "MediaCodecListOverrides_test"
#include <utils/Log.h>
#include <gtest/gtest.h>
#include "MediaCodecListOverrides.h"
#include <media/MediaCodecInfo.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/MediaCodecList.h>
namespace android {
static const char kTestOverridesStr[] =
"<MediaCodecs>\n"
" <Settings>\n"
" <Setting name=\"max-max-supported-instances\" value=\"8\" update=\"true\" />\n"
" </Settings>\n"
" <Encoders>\n"
" <MediaCodec name=\"OMX.qcom.video.encoder.mpeg4\" type=\"video/mp4v-es\" update=\"true\" >\n"
" <Quirk name=\"requires-allocate-on-input-ports\" />\n"
" <Limit name=\"bitrate\" range=\"1-20000000\" />\n"
" <Feature name=\"can-swap-width-height\" />\n"
" </MediaCodec>\n"
" </Encoders>\n"
" <Decoders>\n"
" <MediaCodec name=\"OMX.qcom.video.decoder.avc\" type=\"video/avc\" update=\"true\" >\n"
" <Quirk name=\"requires-allocate-on-input-ports\" />\n"
" <Limit name=\"size\" min=\"64x64\" max=\"1920x1088\" />\n"
" </MediaCodec>\n"
" <MediaCodec name=\"OMX.qcom.video.decoder.mpeg2\" type=\"different_mime\" update=\"true\" >\n"
" </MediaCodec>\n"
" </Decoders>\n"
"</MediaCodecs>\n";
static const char kTestOverridesStrNew1[] =
"<MediaCodecs>\n"
" <Settings>\n"
" <Setting name=\"max-max-supported-instances\" value=\"8\" update=\"true\" />\n"
" </Settings>\n"
" <Encoders>\n"
" <MediaCodec name=\"OMX.qcom.video.encoder.avc\" type=\"video/avc\" update=\"true\" >\n"
" <Limit name=\"max-supported-instances\" value=\"4\" />\n"
" </MediaCodec>\n"
" <MediaCodec name=\"OMX.qcom.video.encoder.mpeg4\" type=\"video/mp4v-es\" update=\"true\" >\n"
" <Limit name=\"max-supported-instances\" value=\"4\" />\n"
" <Quirk name=\"requires-allocate-on-input-ports\" />\n"
" <Limit name=\"bitrate\" range=\"1-20000000\" />\n"
" <Feature name=\"can-swap-width-height\" />\n"
" </MediaCodec>\n"
" </Encoders>\n"
" <Decoders>\n"
" <MediaCodec name=\"OMX.qcom.video.decoder.mpeg4\" type=\"video/mp4v-es\" update=\"true\" >\n"
" <Limit name=\"max-supported-instances\" value=\"3\" />\n"
" </MediaCodec>\n"
" <MediaCodec name=\"OMX.qcom.video.decoder.h263\" type=\"video/3gpp\" update=\"true\" >\n"
" <Limit name=\"max-supported-instances\" value=\"4\" />\n"
" </MediaCodec>\n"
" <MediaCodec name=\"OMX.qcom.video.decoder.avc.secure\" type=\"video/avc\" update=\"true\" >\n"
" <Limit name=\"max-supported-instances\" value=\"1\" />\n"
" </MediaCodec>\n"
" <MediaCodec name=\"OMX.qcom.video.decoder.avc\" type=\"video/avc\" update=\"true\" >\n"
" <Quirk name=\"requires-allocate-on-input-ports\" />\n"
" <Limit name=\"size\" min=\"64x64\" max=\"1920x1088\" />\n"
" </MediaCodec>\n"
" <MediaCodec name=\"OMX.qcom.video.decoder.mpeg2\" type=\"different_mime\" update=\"true\" >\n"
" </MediaCodec>\n"
" <MediaCodec name=\"OMX.qcom.video.decoder.mpeg2\" type=\"video/mpeg2\" update=\"true\" >\n"
" <Limit name=\"max-supported-instances\" value=\"3\" />\n"
" </MediaCodec>\n"
" </Decoders>\n"
"</MediaCodecs>\n";
static const char kTestOverridesStrNew2[] =
"\n"
"<MediaCodecs>\n"
" <Encoders>\n"
" <MediaCodec name=\"OMX.qcom.video.encoder.mpeg4\" type=\"video/mp4v-es\" update=\"true\" >\n"
" <Limit name=\"max-supported-instances\" value=\"4\" />\n"
" </MediaCodec>\n"
" <MediaCodec name=\"OMX.qcom.video.encoder.avc\" type=\"video/avc\" update=\"true\" >\n"
" <Limit name=\"max-supported-instances\" value=\"4\" />\n"
" </MediaCodec>\n"
" </Encoders>\n"
" <Decoders>\n"
" <MediaCodec name=\"OMX.qcom.video.decoder.mpeg4\" type=\"video/mp4v-es\" update=\"true\" >\n"
" <Limit name=\"max-supported-instances\" value=\"3\" />\n"
" </MediaCodec>\n"
" <MediaCodec name=\"OMX.qcom.video.decoder.mpeg2\" type=\"video/mpeg2\" update=\"true\" >\n"
" <Limit name=\"max-supported-instances\" value=\"3\" />\n"
" </MediaCodec>\n"
" <MediaCodec name=\"OMX.qcom.video.decoder.h263\" type=\"video/3gpp\" update=\"true\" >\n"
" <Limit name=\"max-supported-instances\" value=\"4\" />\n"
" </MediaCodec>\n"
" <MediaCodec name=\"OMX.qcom.video.decoder.avc.secure\" type=\"video/avc\" update=\"true\" >\n"
" <Limit name=\"max-supported-instances\" value=\"1\" />\n"
" </MediaCodec>\n"
" </Decoders>\n"
"</MediaCodecs>\n";
class MediaCodecListOverridesTest : public ::testing::Test {
public:
MediaCodecListOverridesTest() {}
void verifyOverrides(const KeyedVector<AString, CodecSettings> &overrides) {
EXPECT_EQ(3u, overrides.size());
EXPECT_TRUE(overrides.keyAt(0) == "OMX.qcom.video.decoder.avc video/avc decoder");
const CodecSettings &settings0 = overrides.valueAt(0);
EXPECT_EQ(1u, settings0.size());
EXPECT_TRUE(settings0.keyAt(0) == "max-supported-instances");
EXPECT_TRUE(settings0.valueAt(0) == "4");
EXPECT_TRUE(overrides.keyAt(1) == "OMX.qcom.video.encoder.avc video/avc encoder");
const CodecSettings &settings1 = overrides.valueAt(1);
EXPECT_EQ(1u, settings1.size());
EXPECT_TRUE(settings1.keyAt(0) == "max-supported-instances");
EXPECT_TRUE(settings1.valueAt(0) == "3");
EXPECT_TRUE(overrides.keyAt(2) == "global");
const CodecSettings &settings2 = overrides.valueAt(2);
EXPECT_EQ(3u, settings2.size());
EXPECT_TRUE(settings2.keyAt(0) == "max-max-supported-instances");
EXPECT_TRUE(settings2.valueAt(0) == "8");
EXPECT_TRUE(settings2.keyAt(1) == "supports-multiple-secure-codecs");
EXPECT_TRUE(settings2.valueAt(1) == "false");
EXPECT_TRUE(settings2.keyAt(2) == "supports-secure-with-non-secure-codec");
EXPECT_TRUE(settings2.valueAt(2) == "true");
}
void verifySetting(const sp<AMessage> &details, const char *name, const char *value) {
AString value1;
EXPECT_TRUE(details->findString(name, &value1));
EXPECT_TRUE(value1 == value);
}
void createTestInfos(Vector<sp<MediaCodecInfo>> *infos) {
const char *name = "OMX.qcom.video.decoder.avc";
const bool encoder = false;
const char *mime = "video/avc";
sp<MediaCodecInfo> info = new MediaCodecInfo(name, encoder, mime);
infos->push_back(info);
const sp<MediaCodecInfo::Capabilities> caps = info->getCapabilitiesFor(mime);
const sp<AMessage> details = caps->getDetails();
details->setString("cap1", "value1");
details->setString("max-max-supported-instances", "16");
info = new MediaCodecInfo("anothercodec", true, "anothermime");
infos->push_back(info);
}
void addMaxInstancesSetting(
const AString &key,
const AString &value,
KeyedVector<AString, CodecSettings> *results) {
CodecSettings settings;
settings.add("max-supported-instances", value);
results->add(key, settings);
}
void exportTestResultsToXML(const char *fileName) {
KeyedVector<AString, CodecSettings> r;
addMaxInstancesSetting("OMX.qcom.video.decoder.avc.secure video/avc decoder", "1", &r);
addMaxInstancesSetting("OMX.qcom.video.decoder.h263 video/3gpp decoder", "4", &r);
addMaxInstancesSetting("OMX.qcom.video.decoder.mpeg2 video/mpeg2 decoder", "3", &r);
addMaxInstancesSetting("OMX.qcom.video.decoder.mpeg4 video/mp4v-es decoder", "3", &r);
addMaxInstancesSetting("OMX.qcom.video.encoder.avc video/avc encoder", "4", &r);
addMaxInstancesSetting("OMX.qcom.video.encoder.mpeg4 video/mp4v-es encoder", "4", &r);
exportResultsToXML(fileName, r);
}
};
TEST_F(MediaCodecListOverridesTest, splitString) {
AString s = "abc123";
AString delimiter = " ";
AString s1;
AString s2;
EXPECT_FALSE(splitString(s, delimiter, &s1, &s2));
s = "abc 123";
EXPECT_TRUE(splitString(s, delimiter, &s1, &s2));
EXPECT_TRUE(s1 == "abc");
EXPECT_TRUE(s2 == "123");
s = "abc123xyz";
delimiter = ",";
AString s3;
EXPECT_FALSE(splitString(s, delimiter, &s1, &s2, &s3));
s = "abc,123xyz";
EXPECT_FALSE(splitString(s, delimiter, &s1, &s2, &s3));
s = "abc,123,xyz";
EXPECT_TRUE(splitString(s, delimiter, &s1, &s2, &s3));
EXPECT_TRUE(s1 == "abc");
EXPECT_TRUE(s2 == "123" );
EXPECT_TRUE(s3 == "xyz");
}
// TODO: the codec component never returns OMX_EventCmdComplete in unit test.
TEST_F(MediaCodecListOverridesTest, DISABLED_profileCodecs) {
sp<IMediaCodecList> list = MediaCodecList::getInstance();
Vector<sp<MediaCodecInfo>> infos;
for (size_t i = 0; i < list->countCodecs(); ++i) {
infos.push_back(list->getCodecInfo(i));
}
KeyedVector<AString, CodecSettings> results;
profileCodecs(infos, &results, true /* forceToMeasure */);
EXPECT_LT(0u, results.size());
for (size_t i = 0; i < results.size(); ++i) {
AString key = results.keyAt(i);
CodecSettings settings = results.valueAt(i);
EXPECT_EQ(1u, settings.size());
EXPECT_TRUE(settings.keyAt(0) == "max-supported-instances");
AString valueS = settings.valueAt(0);
int32_t value = strtol(valueS.c_str(), NULL, 10);
EXPECT_LT(0, value);
ALOGV("profileCodecs results %s %s", key.c_str(), valueS.c_str());
}
}
TEST_F(MediaCodecListOverridesTest, applyCodecSettings) {
AString codecInfo = "OMX.qcom.video.decoder.avc video/avc decoder";
Vector<sp<MediaCodecInfo>> infos;
createTestInfos(&infos);
CodecSettings settings;
settings.add("max-supported-instances", "3");
settings.add("max-max-supported-instances", "8");
applyCodecSettings(codecInfo, settings, &infos);
EXPECT_EQ(2u, infos.size());
EXPECT_TRUE(AString(infos[0]->getCodecName()) == "OMX.qcom.video.decoder.avc");
const sp<AMessage> details = infos[0]->getCapabilitiesFor("video/avc")->getDetails();
verifySetting(details, "max-supported-instances", "3");
verifySetting(details, "max-max-supported-instances", "8");
EXPECT_TRUE(AString(infos[1]->getCodecName()) == "anothercodec");
EXPECT_EQ(0u, infos[1]->getCapabilitiesFor("anothermime")->getDetails()->countEntries());
}
TEST_F(MediaCodecListOverridesTest, exportResultsToExistingFile) {
const char *fileName = "/sdcard/mediacodec_list_overrides_test.xml";
remove(fileName);
FILE *f = fopen(fileName, "wb");
if (f == NULL) {
ALOGW("Failed to open %s for writing.", fileName);
return;
}
EXPECT_EQ(
strlen(kTestOverridesStr),
fwrite(kTestOverridesStr, 1, strlen(kTestOverridesStr), f));
fclose(f);
exportTestResultsToXML(fileName);
// verify
AString overrides;
f = fopen(fileName, "rb");
ASSERT_TRUE(f != NULL);
fseek(f, 0, SEEK_END);
long size = ftell(f);
rewind(f);
char *buf = (char *)malloc(size);
EXPECT_EQ((size_t)1, fread(buf, size, 1, f));
overrides.setTo(buf, size);
fclose(f);
free(buf);
EXPECT_TRUE(overrides == kTestOverridesStrNew1);
remove(fileName);
}
TEST_F(MediaCodecListOverridesTest, exportResultsToEmptyFile) {
const char *fileName = "/sdcard/mediacodec_list_overrides_test.xml";
remove(fileName);
exportTestResultsToXML(fileName);
// verify
AString overrides;
FILE *f = fopen(fileName, "rb");
ASSERT_TRUE(f != NULL);
fseek(f, 0, SEEK_END);
long size = ftell(f);
rewind(f);
char *buf = (char *)malloc(size);
EXPECT_EQ((size_t)1, fread(buf, size, 1, f));
overrides.setTo(buf, size);
fclose(f);
free(buf);
EXPECT_TRUE(overrides == kTestOverridesStrNew2);
remove(fileName);
}
} // namespace android