DashManifestParser extends DefaultHandler implements ParsingLoadable.Parser<DashManifest> { protected DashManifest parseMediaPresentationDescription(XmlPullParser xpp, String baseUrl) throws XmlPullParserException, IOException { long availabilityStartTime = parseDateTime(xpp, "availabilityStartTime", C.TIME_UNSET); long durationMs = parseDuration(xpp, "mediaPresentationDuration", C.TIME_UNSET); long minBufferTimeMs = parseDuration(xpp, "minBufferTime", C.TIME_UNSET); String typeString = xpp.getAttributeValue(null, "type"); boolean dynamic = "dynamic".equals(typeString); long minUpdateTimeMs = dynamic ? parseDuration(xpp, "minimumUpdatePeriod", C.TIME_UNSET) : C.TIME_UNSET; long timeShiftBufferDepthMs = dynamic ? parseDuration(xpp, "timeShiftBufferDepth", C.TIME_UNSET) : C.TIME_UNSET; long suggestedPresentationDelayMs = dynamic ? parseDuration(xpp, "suggestedPresentationDelay", C.TIME_UNSET) : C.TIME_UNSET; long publishTimeMs = parseDateTime(xpp, "publishTime", C.TIME_UNSET); ProgramInformation programInformation = null; UtcTimingElement utcTiming = null; Uri location = null; List<Period> periods = new ArrayList<>(); long nextPeriodStartMs = dynamic ? C.TIME_UNSET : 0; boolean seenEarlyAccessPeriod = false; boolean seenFirstBaseUrl = false; do { xpp.next(); if (XmlPullParserUtil.isStartTag(xpp, "BaseURL")) { if (!seenFirstBaseUrl) { baseUrl = parseBaseUrl(xpp, baseUrl); seenFirstBaseUrl = true; } } else if (XmlPullParserUtil.isStartTag(xpp, "ProgramInformation")) { programInformation = parseProgramInformation(xpp); } else if (XmlPullParserUtil.isStartTag(xpp, "UTCTiming")) { utcTiming = parseUtcTiming(xpp); } else if (XmlPullParserUtil.isStartTag(xpp, "Location")) { location = Uri.parse(xpp.nextText()); } else if (XmlPullParserUtil.isStartTag(xpp, "Period") && !seenEarlyAccessPeriod) { Pair<Period, Long> periodWithDurationMs = parsePeriod(xpp, baseUrl, nextPeriodStartMs); Period period = periodWithDurationMs.first; if (period.startMs == C.TIME_UNSET) { if (dynamic) { seenEarlyAccessPeriod = true; } else { throw new ParserException("Unable to determine start of period " + periods.size()); } } else { long periodDurationMs = periodWithDurationMs.second; nextPeriodStartMs = periodDurationMs == C.TIME_UNSET ? C.TIME_UNSET : (period.startMs + periodDurationMs); periods.add(period); } } else { maybeSkipTag(xpp); } } while (!XmlPullParserUtil.isEndTag(xpp, "MPD")); if (durationMs == C.TIME_UNSET) { if (nextPeriodStartMs != C.TIME_UNSET) { durationMs = nextPeriodStartMs; } else if (!dynamic) { throw new ParserException("Unable to determine duration of static manifest."); } } if (periods.isEmpty()) { throw new ParserException("No periods found."); } return buildMediaPresentationDescription( availabilityStartTime, durationMs, minBufferTimeMs, dynamic, minUpdateTimeMs, timeShiftBufferDepthMs, suggestedPresentationDelayMs, publishTimeMs, programInformation, utcTiming, location, periods); } DashManifestParser(); @Override DashManifest parse(Uri uri, InputStream inputStream); static void maybeSkipTag(XmlPullParser xpp);  }
@Test public void parseMediaPresentationDescription() throws IOException { DashManifestParser parser = new DashManifestParser(); parser.parse( Uri.parse("https: TestUtil.getInputStream(ApplicationProvider.getApplicationContext(), SAMPLE_MPD)); parser.parse( Uri.parse("https: TestUtil.getInputStream( ApplicationProvider.getApplicationContext(), SAMPLE_MPD_UNKNOWN_MIME_TYPE)); }