Minimal fix for non-default cenc name prefixes in DASH manifests

For now, just allow any prefix (and don't check the namespace).
Checking the namespace requires turning on the XmlPullParser
namespace awareness feature, but this can only be done before
parsing, and I think requires us to specify the namespace when
querying other attributes. This would also risk breaking services
who currently don't set namespaces correctly.

It's possible we'll run into similar issues with the few other
tags (e.g. mspr:pro). We should revisit enabling namespace
awareness if/when we see this.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=207526883
This commit is contained in:
olly 2018-08-06 05:01:42 -07:00 committed by Oliver Woodman
parent 18d2a2ea2a
commit 7fcd6b6d65
2 changed files with 43 additions and 6 deletions

View File

@ -56,8 +56,7 @@ public final class XmlPullParserUtil {
* @return Whether the current event is a start tag with the specified name. * @return Whether the current event is a start tag with the specified name.
* @throws XmlPullParserException If an error occurs querying the parser. * @throws XmlPullParserException If an error occurs querying the parser.
*/ */
public static boolean isStartTag(XmlPullParser xpp, String name) public static boolean isStartTag(XmlPullParser xpp, String name) throws XmlPullParserException {
throws XmlPullParserException {
return isStartTag(xpp) && xpp.getName().equals(name); return isStartTag(xpp) && xpp.getName().equals(name);
} }
@ -72,22 +71,59 @@ public final class XmlPullParserUtil {
return xpp.getEventType() == XmlPullParser.START_TAG; return xpp.getEventType() == XmlPullParser.START_TAG;
} }
/**
* Returns whether the current event is a start tag with the specified name. If the current event
* has a raw name then its prefix is stripped before matching.
*
* @param xpp The {@link XmlPullParser} to query.
* @param name The specified name.
* @return Whether the current event is a start tag with the specified name.
* @throws XmlPullParserException If an error occurs querying the parser.
*/
public static boolean isStartTagIgnorePrefix(XmlPullParser xpp, String name)
throws XmlPullParserException {
return isStartTag(xpp) && stripPrefix(xpp.getName()).equals(name);
}
/** /**
* Returns the value of an attribute of the current start tag. * Returns the value of an attribute of the current start tag.
* *
* @param xpp The {@link XmlPullParser} to query. * @param xpp The {@link XmlPullParser} to query.
* @param attributeName The name of the attribute. * @param attributeName The name of the attribute.
* @return The value of the attribute, or null if the current event is not a start tag or if no * @return The value of the attribute, or null if the current event is not a start tag or if no
* no such attribute was found. * such attribute was found.
*/ */
public static String getAttributeValue(XmlPullParser xpp, String attributeName) { public static String getAttributeValue(XmlPullParser xpp, String attributeName) {
int attributeCount = xpp.getAttributeCount(); int attributeCount = xpp.getAttributeCount();
for (int i = 0; i < attributeCount; i++) { for (int i = 0; i < attributeCount; i++) {
if (attributeName.equals(xpp.getAttributeName(i))) { if (xpp.getAttributeName(i).equals(attributeName)) {
return xpp.getAttributeValue(i); return xpp.getAttributeValue(i);
} }
} }
return null; return null;
} }
/**
* Returns the value of an attribute of the current start tag. Any raw attribute names in the
* current start tag have their prefixes stripped before matching.
*
* @param xpp The {@link XmlPullParser} to query.
* @param attributeName The name of the attribute.
* @return The value of the attribute, or null if the current event is not a start tag or if no
* such attribute was found.
*/
public static String getAttributeValueIgnorePrefix(XmlPullParser xpp, String attributeName) {
int attributeCount = xpp.getAttributeCount();
for (int i = 0; i < attributeCount; i++) {
if (stripPrefix(xpp.getAttributeName(i)).equals(attributeName)) {
return xpp.getAttributeValue(i);
}
}
return null;
}
private static String stripPrefix(String name) {
int prefixSeparatorIndex = name.indexOf(':');
return prefixSeparatorIndex == -1 ? name : name.substring(prefixSeparatorIndex + 1);
}
} }

View File

@ -379,7 +379,7 @@ public class DashManifestParser extends DefaultHandler
switch (Util.toLowerInvariant(schemeIdUri)) { switch (Util.toLowerInvariant(schemeIdUri)) {
case "urn:mpeg:dash:mp4protection:2011": case "urn:mpeg:dash:mp4protection:2011":
schemeType = xpp.getAttributeValue(null, "value"); schemeType = xpp.getAttributeValue(null, "value");
String defaultKid = xpp.getAttributeValue(null, "cenc:default_KID"); String defaultKid = XmlPullParserUtil.getAttributeValueIgnorePrefix(xpp, "default_KID");
if (!TextUtils.isEmpty(defaultKid) if (!TextUtils.isEmpty(defaultKid)
&& !"00000000-0000-0000-0000-000000000000".equals(defaultKid)) { && !"00000000-0000-0000-0000-000000000000".equals(defaultKid)) {
String[] defaultKidStrings = defaultKid.split("\\s+"); String[] defaultKidStrings = defaultKid.split("\\s+");
@ -410,7 +410,8 @@ public class DashManifestParser extends DefaultHandler
String robustnessLevel = xpp.getAttributeValue(null, "robustness_level"); String robustnessLevel = xpp.getAttributeValue(null, "robustness_level");
requiresSecureDecoder = robustnessLevel != null && robustnessLevel.startsWith("HW"); requiresSecureDecoder = robustnessLevel != null && robustnessLevel.startsWith("HW");
} else if (data == null) { } else if (data == null) {
if (XmlPullParserUtil.isStartTag(xpp, "cenc:pssh") && xpp.next() == XmlPullParser.TEXT) { if (XmlPullParserUtil.isStartTagIgnorePrefix(xpp, "pssh")
&& xpp.next() == XmlPullParser.TEXT) {
// The cenc:pssh element is defined in 23001-7:2015. // The cenc:pssh element is defined in 23001-7:2015.
data = Base64.decode(xpp.getText(), Base64.DEFAULT); data = Base64.decode(xpp.getText(), Base64.DEFAULT);
uuid = PsshAtomUtil.parseUuid(data); uuid = PsshAtomUtil.parseUuid(data);