Commit ddd2d004 by Oliver Woodman

Make SmoothStreaming manifest more robust.

- Skips unrecognized elements rather than crashing.
- FourCC treated as required for video and optional elsewhere,
  as per the SmoothStreaming spec.
- Only parse initData text when we're actually in the ProtectionHeader element
parent 181eceaf
...@@ -105,6 +105,7 @@ public class SmoothStreamingManifestParser { ...@@ -105,6 +105,7 @@ public class SmoothStreamingManifestParser {
ParserException { ParserException {
String tagName; String tagName;
boolean foundStartTag = false; boolean foundStartTag = false;
int skippingElementDepth = 0;
while (true) { while (true) {
int eventType = xmlParser.getEventType(); int eventType = xmlParser.getEventType();
switch (eventType) { switch (eventType) {
...@@ -114,24 +115,35 @@ public class SmoothStreamingManifestParser { ...@@ -114,24 +115,35 @@ public class SmoothStreamingManifestParser {
foundStartTag = true; foundStartTag = true;
parseStartTag(xmlParser); parseStartTag(xmlParser);
} else if (foundStartTag) { } else if (foundStartTag) {
if (handleChildInline(tagName)) { if (skippingElementDepth > 0) {
skippingElementDepth++;
} else if (handleChildInline(tagName)) {
parseStartTag(xmlParser); parseStartTag(xmlParser);
} else { } else {
addChild(newChildParser(this, tagName).parse(xmlParser)); ElementParser childElementParser = newChildParser(this, tagName);
if (childElementParser == null) {
skippingElementDepth = 1;
} else {
addChild(childElementParser.parse(xmlParser));
}
} }
} }
break; break;
case XmlPullParser.TEXT: case XmlPullParser.TEXT:
if (foundStartTag) { if (foundStartTag && skippingElementDepth == 0) {
parseText(xmlParser); parseText(xmlParser);
} }
break; break;
case XmlPullParser.END_TAG: case XmlPullParser.END_TAG:
if (foundStartTag) { if (foundStartTag) {
tagName = xmlParser.getName(); if (skippingElementDepth > 0) {
parseEndTag(xmlParser); skippingElementDepth--;
if (!handleChildInline(tagName)) { } else {
return build(); tagName = xmlParser.getName();
parseEndTag(xmlParser);
if (!handleChildInline(tagName)) {
return build();
}
} }
} }
break; break;
...@@ -360,6 +372,7 @@ public class SmoothStreamingManifestParser { ...@@ -360,6 +372,7 @@ public class SmoothStreamingManifestParser {
public static final String KEY_SYSTEM_ID = "SystemID"; public static final String KEY_SYSTEM_ID = "SystemID";
private boolean inProtectionHeader;
private UUID uuid; private UUID uuid;
private byte[] initData; private byte[] initData;
...@@ -374,16 +387,25 @@ public class SmoothStreamingManifestParser { ...@@ -374,16 +387,25 @@ public class SmoothStreamingManifestParser {
@Override @Override
public void parseStartTag(XmlPullParser parser) { public void parseStartTag(XmlPullParser parser) {
if (!TAG_PROTECTION_HEADER.equals(parser.getName())) { if (TAG_PROTECTION_HEADER.equals(parser.getName())) {
return; inProtectionHeader = true;
String uuidString = parser.getAttributeValue(null, KEY_SYSTEM_ID);
uuid = UUID.fromString(uuidString);
} }
String uuidString = parser.getAttributeValue(null, KEY_SYSTEM_ID);
uuid = UUID.fromString(uuidString);
} }
@Override @Override
public void parseText(XmlPullParser parser) { public void parseText(XmlPullParser parser) {
initData = Base64.decode(parser.getText(), Base64.DEFAULT); if (inProtectionHeader) {
initData = Base64.decode(parser.getText(), Base64.DEFAULT);
}
}
@Override
public void parseEndTag(XmlPullParser parser) {
if (TAG_PROTECTION_HEADER.equals(parser.getName())) {
inProtectionHeader = false;
}
} }
@Override @Override
...@@ -582,9 +604,11 @@ public class SmoothStreamingManifestParser { ...@@ -582,9 +604,11 @@ public class SmoothStreamingManifestParser {
if (type == StreamElement.TYPE_VIDEO) { if (type == StreamElement.TYPE_VIDEO) {
maxHeight = parseRequiredInt(parser, KEY_MAX_HEIGHT); maxHeight = parseRequiredInt(parser, KEY_MAX_HEIGHT);
maxWidth = parseRequiredInt(parser, KEY_MAX_WIDTH); maxWidth = parseRequiredInt(parser, KEY_MAX_WIDTH);
fourCC = parseRequiredString(parser, KEY_FOUR_CC);
} else { } else {
maxHeight = -1; maxHeight = -1;
maxWidth = -1; maxWidth = -1;
fourCC = parser.getAttributeValue(null, KEY_FOUR_CC);
} }
if (type == StreamElement.TYPE_AUDIO) { if (type == StreamElement.TYPE_AUDIO) {
...@@ -593,14 +617,12 @@ public class SmoothStreamingManifestParser { ...@@ -593,14 +617,12 @@ public class SmoothStreamingManifestParser {
bitPerSample = parseRequiredInt(parser, KEY_BITS_PER_SAMPLE); bitPerSample = parseRequiredInt(parser, KEY_BITS_PER_SAMPLE);
packetSize = parseRequiredInt(parser, KEY_PACKET_SIZE); packetSize = parseRequiredInt(parser, KEY_PACKET_SIZE);
audioTag = parseRequiredInt(parser, KEY_AUDIO_TAG); audioTag = parseRequiredInt(parser, KEY_AUDIO_TAG);
fourCC = parseRequiredString(parser, KEY_FOUR_CC);
} else { } else {
samplingRate = -1; samplingRate = -1;
channels = -1; channels = -1;
bitPerSample = -1; bitPerSample = -1;
packetSize = -1; packetSize = -1;
audioTag = -1; audioTag = -1;
fourCC = parser.getAttributeValue(null, KEY_FOUR_CC);
} }
value = parser.getAttributeValue(null, KEY_CODEC_PRIVATE_DATA); value = parser.getAttributeValue(null, KEY_CODEC_PRIVATE_DATA);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment