Loading media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp +70 −3 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ #include <media/stagefright/xmlparser/MediaCodecsXmlParser.h> #include <android/api-level.h> #include <android-base/logging.h> #include <android-base/macros.h> #include <android-base/properties.h> Loading @@ -30,6 +32,7 @@ #include <expat.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> Loading Loading @@ -360,7 +363,7 @@ struct MediaCodecsXmlParser::Impl { status_t updateMediaCodec( const char *rank, const StringSet &domain, const StringSet &variants, const char *enabled); const char *enabled, const char *minsdk); }; status_t parseXmlFilesInSearchDirs( Loading Loading @@ -493,6 +496,9 @@ void MediaCodecsXmlParser::Impl::Parser::logAnyErrors(const Result &status) cons } } // current SDK for this device; filled in when initializing the parser. static int mysdk = 0; MediaCodecsXmlParser::Impl::Parser::Parser(State *state, std::string path) : mState(state), mPath(path), Loading @@ -502,6 +508,20 @@ MediaCodecsXmlParser::Impl::Parser::Parser(State *state, std::string path) if (end != std::string::npos) { mHrefBase = path.substr(0, end + 1); } #if defined(__ANDROID_API_U__) // this is sdk calculation is intended only for devices >= U static std::once_flag sCheckOnce; std::call_once(sCheckOnce, [&](){ mysdk = android_get_device_api_level(); // work around main development branch being on same SDK as the last dessert release. if (__ANDROID_API__ == __ANDROID_API_FUTURE__) { mysdk++; } }); #endif // __ANDROID_API_U__ } void MediaCodecsXmlParser::Impl::Parser::parseXmlFile() { Loading Loading @@ -930,6 +950,7 @@ status_t MediaCodecsXmlParser::Impl::Parser::enterMediaCodec( const char *a_domain = nullptr; const char *a_variant = nullptr; const char *a_enabled = nullptr; const char *a_minsdk = nullptr; size_t i = 0; while (attrs[i] != nullptr) { Loading @@ -953,6 +974,8 @@ status_t MediaCodecsXmlParser::Impl::Parser::enterMediaCodec( a_variant = attrs[++i]; } else if (strEq(attrs[i], "enabled")) { a_enabled = attrs[++i]; } else if (strEq(attrs[i], "minsdk")) { a_minsdk = attrs[++i]; } else { PLOGD("MediaCodec: ignoring unrecognized attribute '%s'", attrs[i]); ++i; Loading Loading @@ -981,7 +1004,7 @@ status_t MediaCodecsXmlParser::Impl::Parser::enterMediaCodec( return updateMediaCodec( a_rank, parseCommaSeparatedStringSet(a_domain), parseCommaSeparatedStringSet(a_variant), a_enabled); parseCommaSeparatedStringSet(a_variant), a_enabled, a_minsdk); } MediaCodecsXmlParser::Impl::Result Loading Loading @@ -1035,7 +1058,7 @@ MediaCodecsXmlParser::Impl::State::enterMediaCodec( status_t MediaCodecsXmlParser::Impl::Parser::updateMediaCodec( const char *rank, const StringSet &domains, const StringSet &variants, const char *enabled) { const char *enabled, const char *minsdk) { CHECK(mState->inCodec()); CodecProperties &codec = mState->codec(); Loading @@ -1048,6 +1071,7 @@ status_t MediaCodecsXmlParser::Impl::Parser::updateMediaCodec( codec.variantSet = variants; // we allow sets of domains... for (const std::string &domain : domains) { if (domain.size() && domain.at(0) == '!') { codec.domainSet.erase(domain.substr(1)); Loading @@ -1065,6 +1089,49 @@ status_t MediaCodecsXmlParser::Impl::Parser::updateMediaCodec( ALOGD("disabling %s", mState->codecName().c_str()); } } // evaluate against passed minsdk, with lots of logging to explain the logic // // if current sdk >= minsdk, we want to enable the codec // this OVERRIDES any enabled="true|false" setting on the codec. // (enabled=true minsdk=35 on a sdk 34 device results in a disabled codec) // // Although minsdk is not parsed before Android U, we can carry media_codecs.xml // using this to devices earlier (e.g. as part of mainline). An example is appropriate. // // we have a codec that we want enabled in Android V (sdk=35), so we use: // <MediaCodec ..... enabled="false" minsdk="35" > // // on Q/R/S/T: it sees enabled=false, but ignores the unrecognized minsdk // so the codec will be disabled // on U: it sees enabled=false, and sees minsdk=35, but U==34 and 34 < 35 // so the codec will be disabled // on V: it sees enabled=false, and sees minsdk=35, V==35 and 35 >= 35 // so the codec will be enabled // // if we know the XML files will be used only on devices >= U, we can skip the enabled=false // piece. Android mainline's support horizons say we will be using the enabled=false for // another 4-5 years after U. // if (minsdk != nullptr) { char *p = nullptr; int sdk = strtol(minsdk, &p, 0); if (p == minsdk || sdk < 0) { ALOGE("minsdk parsing '%s' yielded %d, mapping to 0", minsdk, sdk); sdk = 0; } // minsdk="#" means: "enable if sdk is >= #, disable otherwise" if (mysdk < sdk) { ALOGI("codec %s disabled, device sdk %d < required %d", mState->codecName().c_str(), mysdk, sdk); codec.quirkSet.emplace("attribute::disabled"); } else { ALOGI("codec %s enabled, device sdk %d >= required %d", mState->codecName().c_str(), mysdk, sdk); codec.quirkSet.erase("attribute::disabled"); } } return OK; } Loading media/libstagefright/xmlparser/api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -84,6 +84,7 @@ package media.codecs { method public java.util.List<media.codecs.Feature> getFeature_optional(); method public java.util.List<media.codecs.Limit> getLimit_optional(); method public java.util.List<media.codecs.Mapping> getMapping_optional(); method public String getMinsdk(); method public String getName(); method public java.util.List<media.codecs.Quirk> getQuirk_optional(); method public String getRank(); Loading @@ -95,6 +96,7 @@ package media.codecs { method public java.util.List<media.codecs.Variant> getVariant_optional(); method public void setDomain(String); method public void setEnabled(String); method public void setMinsdk(String); method public void setName(String); method public void setRank(String); method public void setType(String); Loading media/libstagefright/xmlparser/media_codecs.xsd +1 −0 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ <xs:attribute name="domain" type="xs:string"/> <xs:attribute name="variant" type="xs:string"/> <xs:attribute name="enabled" type="xs:string"/> <xs:attribute name="minsdk" type="xs:string"/> </xs:complexType> <xs:complexType name="Quirk"> <xs:attribute name="name" type="xs:string"/> Loading media/libstagefright/xmlparser/test/XMLParserTest.cpp +43 −0 Original line number Diff line number Diff line Loading @@ -145,6 +145,33 @@ void XMLParseTest::setUpDatabase() { }, {}, ""); // minsdk setCodecProperties("test12.encoder", true, 12, {"attribute::disabled"}, {}, {}, "video/t12", { pair<string, string>("tuning-enable-goal", "no"), }, {}, ""); setCodecProperties("test13.encoder", true, 13, {"attribute::disabled"}, {}, {}, "video/t13", { pair<string, string>("tuning-enable-goal", "no"), }, {}, ""); setCodecProperties("test14.encoder", true, 14, {"attribute::disabled"}, {}, {}, "video/t14", { pair<string, string>("tuning-enable-goal", "no"), }, {}, ""); setCodecProperties("test15.encoder", true, 15, {}, {}, {}, "video/t15", { pair<string, string>("tuning-enable-goal", "yes"), }, {}, ""); setCodecProperties("test16.encoder", true, 16, {}, {}, {}, "video/t16", { pair<string, string>("tuning-enable-goal", "yes"), }, {}, ""); setRoleProperties("audio_decoder.mp3", false, 1, "audio/mpeg", "test1.decoder", {pair<string, string>("attribute::disabled", "present"), pair<string, string>("rank", "4")}); Loading Loading @@ -191,6 +218,22 @@ void XMLParseTest::setUpDatabase() { pair<string, string>("tuning-pi", "3.1415") }); // minsdk setRoleProperties("video_encoder.t12", true, 12, "video/t12", "test12.encoder", {pair<string, string>("tuning-enable-goal", "no"), pair<string, string>("attribute::disabled", "present") }); setRoleProperties("video_encoder.t13", true, 13, "video/t13", "test13.encoder", {pair<string, string>("tuning-enable-goal", "no"), pair<string, string>("attribute::disabled", "present") }); setRoleProperties("video_encoder.t14", true, 14, "video/t14", "test14.encoder", {pair<string, string>("tuning-enable-goal", "no"), pair<string, string>("attribute::disabled", "present") }); setRoleProperties("video_encoder.t15", true, 15, "video/t15", "test15.encoder", {pair<string, string>("tuning-enable-goal", "yes")}); setRoleProperties("video_encoder.t16", true, 16, "video/t16", "test16.encoder", {pair<string, string>("tuning-enable-goal", "yes")}); setServiceAttribute( {pair<string, string>("domain-telephony", "0"), pair<string, string>("domain-tv", "0"), pair<string, string>("setting2", "0"), pair<string, string>("variant-variant1", "0")}); Loading media/libstagefright/xmlparser/test/testdata/media_codecs_unit_test.xml +16 −0 Original line number Diff line number Diff line Loading @@ -88,5 +88,21 @@ <Tuning name="hungry" value="yes"/> <Tuning name="pi" value="3.1415"/> </MediaCodec> <!-- test minsdk --> <MediaCodec name="test12.encoder" type="video/t12" minsdk="100"> <Tuning name="enable-goal" value="no"/> </MediaCodec> <MediaCodec name="test13.encoder" type="video/t13" enabled="false" minsdk="100"> <Tuning name="enable-goal" value="no"/> </MediaCodec> <MediaCodec name="test14.encoder" type="video/t14" enabled="true" minsdk="100"> <Tuning name="enable-goal" value="no"/> </MediaCodec> <MediaCodec name="test15.encoder" type="video/t15" minsdk="34"> <Tuning name="enable-goal" value="yes"/> </MediaCodec> <MediaCodec name="test16.encoder" type="video/t16" enabled="false" minsdk="34"> <Tuning name="enable-goal" value="yes"/> </MediaCodec> </Encoders> </Included> Loading
media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp +70 −3 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ #include <media/stagefright/xmlparser/MediaCodecsXmlParser.h> #include <android/api-level.h> #include <android-base/logging.h> #include <android-base/macros.h> #include <android-base/properties.h> Loading @@ -30,6 +32,7 @@ #include <expat.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> Loading Loading @@ -360,7 +363,7 @@ struct MediaCodecsXmlParser::Impl { status_t updateMediaCodec( const char *rank, const StringSet &domain, const StringSet &variants, const char *enabled); const char *enabled, const char *minsdk); }; status_t parseXmlFilesInSearchDirs( Loading Loading @@ -493,6 +496,9 @@ void MediaCodecsXmlParser::Impl::Parser::logAnyErrors(const Result &status) cons } } // current SDK for this device; filled in when initializing the parser. static int mysdk = 0; MediaCodecsXmlParser::Impl::Parser::Parser(State *state, std::string path) : mState(state), mPath(path), Loading @@ -502,6 +508,20 @@ MediaCodecsXmlParser::Impl::Parser::Parser(State *state, std::string path) if (end != std::string::npos) { mHrefBase = path.substr(0, end + 1); } #if defined(__ANDROID_API_U__) // this is sdk calculation is intended only for devices >= U static std::once_flag sCheckOnce; std::call_once(sCheckOnce, [&](){ mysdk = android_get_device_api_level(); // work around main development branch being on same SDK as the last dessert release. if (__ANDROID_API__ == __ANDROID_API_FUTURE__) { mysdk++; } }); #endif // __ANDROID_API_U__ } void MediaCodecsXmlParser::Impl::Parser::parseXmlFile() { Loading Loading @@ -930,6 +950,7 @@ status_t MediaCodecsXmlParser::Impl::Parser::enterMediaCodec( const char *a_domain = nullptr; const char *a_variant = nullptr; const char *a_enabled = nullptr; const char *a_minsdk = nullptr; size_t i = 0; while (attrs[i] != nullptr) { Loading @@ -953,6 +974,8 @@ status_t MediaCodecsXmlParser::Impl::Parser::enterMediaCodec( a_variant = attrs[++i]; } else if (strEq(attrs[i], "enabled")) { a_enabled = attrs[++i]; } else if (strEq(attrs[i], "minsdk")) { a_minsdk = attrs[++i]; } else { PLOGD("MediaCodec: ignoring unrecognized attribute '%s'", attrs[i]); ++i; Loading Loading @@ -981,7 +1004,7 @@ status_t MediaCodecsXmlParser::Impl::Parser::enterMediaCodec( return updateMediaCodec( a_rank, parseCommaSeparatedStringSet(a_domain), parseCommaSeparatedStringSet(a_variant), a_enabled); parseCommaSeparatedStringSet(a_variant), a_enabled, a_minsdk); } MediaCodecsXmlParser::Impl::Result Loading Loading @@ -1035,7 +1058,7 @@ MediaCodecsXmlParser::Impl::State::enterMediaCodec( status_t MediaCodecsXmlParser::Impl::Parser::updateMediaCodec( const char *rank, const StringSet &domains, const StringSet &variants, const char *enabled) { const char *enabled, const char *minsdk) { CHECK(mState->inCodec()); CodecProperties &codec = mState->codec(); Loading @@ -1048,6 +1071,7 @@ status_t MediaCodecsXmlParser::Impl::Parser::updateMediaCodec( codec.variantSet = variants; // we allow sets of domains... for (const std::string &domain : domains) { if (domain.size() && domain.at(0) == '!') { codec.domainSet.erase(domain.substr(1)); Loading @@ -1065,6 +1089,49 @@ status_t MediaCodecsXmlParser::Impl::Parser::updateMediaCodec( ALOGD("disabling %s", mState->codecName().c_str()); } } // evaluate against passed minsdk, with lots of logging to explain the logic // // if current sdk >= minsdk, we want to enable the codec // this OVERRIDES any enabled="true|false" setting on the codec. // (enabled=true minsdk=35 on a sdk 34 device results in a disabled codec) // // Although minsdk is not parsed before Android U, we can carry media_codecs.xml // using this to devices earlier (e.g. as part of mainline). An example is appropriate. // // we have a codec that we want enabled in Android V (sdk=35), so we use: // <MediaCodec ..... enabled="false" minsdk="35" > // // on Q/R/S/T: it sees enabled=false, but ignores the unrecognized minsdk // so the codec will be disabled // on U: it sees enabled=false, and sees minsdk=35, but U==34 and 34 < 35 // so the codec will be disabled // on V: it sees enabled=false, and sees minsdk=35, V==35 and 35 >= 35 // so the codec will be enabled // // if we know the XML files will be used only on devices >= U, we can skip the enabled=false // piece. Android mainline's support horizons say we will be using the enabled=false for // another 4-5 years after U. // if (minsdk != nullptr) { char *p = nullptr; int sdk = strtol(minsdk, &p, 0); if (p == minsdk || sdk < 0) { ALOGE("minsdk parsing '%s' yielded %d, mapping to 0", minsdk, sdk); sdk = 0; } // minsdk="#" means: "enable if sdk is >= #, disable otherwise" if (mysdk < sdk) { ALOGI("codec %s disabled, device sdk %d < required %d", mState->codecName().c_str(), mysdk, sdk); codec.quirkSet.emplace("attribute::disabled"); } else { ALOGI("codec %s enabled, device sdk %d >= required %d", mState->codecName().c_str(), mysdk, sdk); codec.quirkSet.erase("attribute::disabled"); } } return OK; } Loading
media/libstagefright/xmlparser/api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -84,6 +84,7 @@ package media.codecs { method public java.util.List<media.codecs.Feature> getFeature_optional(); method public java.util.List<media.codecs.Limit> getLimit_optional(); method public java.util.List<media.codecs.Mapping> getMapping_optional(); method public String getMinsdk(); method public String getName(); method public java.util.List<media.codecs.Quirk> getQuirk_optional(); method public String getRank(); Loading @@ -95,6 +96,7 @@ package media.codecs { method public java.util.List<media.codecs.Variant> getVariant_optional(); method public void setDomain(String); method public void setEnabled(String); method public void setMinsdk(String); method public void setName(String); method public void setRank(String); method public void setType(String); Loading
media/libstagefright/xmlparser/media_codecs.xsd +1 −0 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ <xs:attribute name="domain" type="xs:string"/> <xs:attribute name="variant" type="xs:string"/> <xs:attribute name="enabled" type="xs:string"/> <xs:attribute name="minsdk" type="xs:string"/> </xs:complexType> <xs:complexType name="Quirk"> <xs:attribute name="name" type="xs:string"/> Loading
media/libstagefright/xmlparser/test/XMLParserTest.cpp +43 −0 Original line number Diff line number Diff line Loading @@ -145,6 +145,33 @@ void XMLParseTest::setUpDatabase() { }, {}, ""); // minsdk setCodecProperties("test12.encoder", true, 12, {"attribute::disabled"}, {}, {}, "video/t12", { pair<string, string>("tuning-enable-goal", "no"), }, {}, ""); setCodecProperties("test13.encoder", true, 13, {"attribute::disabled"}, {}, {}, "video/t13", { pair<string, string>("tuning-enable-goal", "no"), }, {}, ""); setCodecProperties("test14.encoder", true, 14, {"attribute::disabled"}, {}, {}, "video/t14", { pair<string, string>("tuning-enable-goal", "no"), }, {}, ""); setCodecProperties("test15.encoder", true, 15, {}, {}, {}, "video/t15", { pair<string, string>("tuning-enable-goal", "yes"), }, {}, ""); setCodecProperties("test16.encoder", true, 16, {}, {}, {}, "video/t16", { pair<string, string>("tuning-enable-goal", "yes"), }, {}, ""); setRoleProperties("audio_decoder.mp3", false, 1, "audio/mpeg", "test1.decoder", {pair<string, string>("attribute::disabled", "present"), pair<string, string>("rank", "4")}); Loading Loading @@ -191,6 +218,22 @@ void XMLParseTest::setUpDatabase() { pair<string, string>("tuning-pi", "3.1415") }); // minsdk setRoleProperties("video_encoder.t12", true, 12, "video/t12", "test12.encoder", {pair<string, string>("tuning-enable-goal", "no"), pair<string, string>("attribute::disabled", "present") }); setRoleProperties("video_encoder.t13", true, 13, "video/t13", "test13.encoder", {pair<string, string>("tuning-enable-goal", "no"), pair<string, string>("attribute::disabled", "present") }); setRoleProperties("video_encoder.t14", true, 14, "video/t14", "test14.encoder", {pair<string, string>("tuning-enable-goal", "no"), pair<string, string>("attribute::disabled", "present") }); setRoleProperties("video_encoder.t15", true, 15, "video/t15", "test15.encoder", {pair<string, string>("tuning-enable-goal", "yes")}); setRoleProperties("video_encoder.t16", true, 16, "video/t16", "test16.encoder", {pair<string, string>("tuning-enable-goal", "yes")}); setServiceAttribute( {pair<string, string>("domain-telephony", "0"), pair<string, string>("domain-tv", "0"), pair<string, string>("setting2", "0"), pair<string, string>("variant-variant1", "0")}); Loading
media/libstagefright/xmlparser/test/testdata/media_codecs_unit_test.xml +16 −0 Original line number Diff line number Diff line Loading @@ -88,5 +88,21 @@ <Tuning name="hungry" value="yes"/> <Tuning name="pi" value="3.1415"/> </MediaCodec> <!-- test minsdk --> <MediaCodec name="test12.encoder" type="video/t12" minsdk="100"> <Tuning name="enable-goal" value="no"/> </MediaCodec> <MediaCodec name="test13.encoder" type="video/t13" enabled="false" minsdk="100"> <Tuning name="enable-goal" value="no"/> </MediaCodec> <MediaCodec name="test14.encoder" type="video/t14" enabled="true" minsdk="100"> <Tuning name="enable-goal" value="no"/> </MediaCodec> <MediaCodec name="test15.encoder" type="video/t15" minsdk="34"> <Tuning name="enable-goal" value="yes"/> </MediaCodec> <MediaCodec name="test16.encoder" type="video/t16" enabled="false" minsdk="34"> <Tuning name="enable-goal" value="yes"/> </MediaCodec> </Encoders> </Included>