Skip to content

Commit

Permalink
WIP: Proper(?) handling of multiple BaseUrls
Browse files Browse the repository at this point in the history
  • Loading branch information
pakerfeldt committed Feb 11, 2016
1 parent 56ac28c commit 191b674
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -118,23 +118,21 @@ protected MediaPresentationDescription parseMediaPresentationDescription(XmlPull
UtcTimingElement utcTiming = null;
String location = null;

List<String> baseUrls = new ArrayList<>();
List<Period> periods = new ArrayList<>();
long nextPeriodStartMs = dynamic ? -1 : 0;
boolean seenEarlyAccessPeriod = false;
boolean seenFirstBaseUrl = false;
do {
xpp.next();
if (ParserUtil.isStartTag(xpp, "BaseURL")) {
if (!seenFirstBaseUrl) {
baseUrl = parseBaseUrl(xpp, baseUrl);
seenFirstBaseUrl = true;
}
baseUrls.add(parseBaseUrl(xpp, baseUrl));
} else if (ParserUtil.isStartTag(xpp, "UTCTiming")) {
utcTiming = parseUtcTiming(xpp);
} else if (ParserUtil.isStartTag(xpp, "Location")) {
location = xpp.nextText();
} else if (ParserUtil.isStartTag(xpp, "Period") && !seenEarlyAccessPeriod) {
Pair<Period, Long> periodWithDurationMs = parsePeriod(xpp, baseUrl, nextPeriodStartMs);
Pair<Period, Long> periodWithDurationMs = parsePeriod(xpp, baseUrls, nextPeriodStartMs);
Period period = periodWithDurationMs.first;
if (period.startMs == -1) {
if (dynamic) {
Expand Down Expand Up @@ -187,7 +185,7 @@ protected UtcTimingElement buildUtcTimingElement(String schemeIdUri, String valu
return new UtcTimingElement(schemeIdUri, value);
}

protected Pair<Period, Long> parsePeriod(XmlPullParser xpp, String baseUrl, long defaultStartMs)
protected Pair<Period, Long> parsePeriod(XmlPullParser xpp, List<String> parentBaseUrls, long defaultStartMs)
throws XmlPullParserException, IOException {
String id = xpp.getAttributeValue(null, "id");
long startMs = parseDuration(xpp, "start", defaultStartMs);
Expand All @@ -198,15 +196,15 @@ protected Pair<Period, Long> parsePeriod(XmlPullParser xpp, String baseUrl, long
do {
xpp.next();
if (ParserUtil.isStartTag(xpp, "BaseURL")) {
baseUrls.add(parseBaseUrl(xpp, baseUrl)); // TODO: What baseUrl to use for relative resolutions?
baseUrls.addAll(parseBaseUrls(xpp, parentBaseUrls));
} else if (ParserUtil.isStartTag(xpp, "AdaptationSet")) {
adaptationSets.add(parseAdaptationSet(xpp, baseUrls, segmentBase));
adaptationSets.add(parseAdaptationSet(xpp, baseUrls.isEmpty() ? parentBaseUrls : baseUrls, segmentBase));
} else if (ParserUtil.isStartTag(xpp, "SegmentBase")) {
segmentBase = parseSegmentBase(xpp, baseUrls, null);
segmentBase = parseSegmentBase(xpp, baseUrls.isEmpty() ? parentBaseUrls : baseUrls, null);
} else if (ParserUtil.isStartTag(xpp, "SegmentList")) {
segmentBase = parseSegmentList(xpp, baseUrls, null);
segmentBase = parseSegmentList(xpp, baseUrls.isEmpty() ? parentBaseUrls : baseUrls, null);
} else if (ParserUtil.isStartTag(xpp, "SegmentTemplate")) {
segmentBase = parseSegmentTemplate(xpp, baseUrls, null);
segmentBase = parseSegmentTemplate(xpp, baseUrls.isEmpty() ? parentBaseUrls : baseUrls, null);
}
} while (!ParserUtil.isEndTag(xpp, "Period"));

Expand All @@ -219,7 +217,7 @@ protected Period buildPeriod(String id, long startMs, List<AdaptationSet> adapta

// AdaptationSet parsing.

protected AdaptationSet parseAdaptationSet(XmlPullParser xpp, List<String> baseUrls,
protected AdaptationSet parseAdaptationSet(XmlPullParser xpp, List<String> parentBaseUrls,
SegmentBase segmentBase) throws XmlPullParserException, IOException {
int id = parseInt(xpp, "id", -1);
int contentType = parseContentType(xpp);
Expand All @@ -232,17 +230,14 @@ protected AdaptationSet parseAdaptationSet(XmlPullParser xpp, List<String> baseU
int audioChannels = -1;
int audioSamplingRate = parseInt(xpp, "audioSamplingRate", -1);
String language = xpp.getAttributeValue(null, "lang");
List<String> baseUrls = new ArrayList<>();

ContentProtectionsBuilder contentProtectionsBuilder = new ContentProtectionsBuilder();
List<Representation> representations = new ArrayList<>();
boolean seenFirstBaseUrl = false;
do {
xpp.next();
if (ParserUtil.isStartTag(xpp, "BaseURL")) {
if (!seenFirstBaseUrl) {
baseUrls.add(parseBaseUrl(xpp, "")); // TODO: Again, what to use for relative resolution?
seenFirstBaseUrl = true;
}
baseUrls.addAll(parseBaseUrls(xpp, parentBaseUrls));
} else if (ParserUtil.isStartTag(xpp, "ContentProtection")) {
ContentProtection contentProtection = parseContentProtection(xpp);
if (contentProtection != null) {
Expand All @@ -252,7 +247,7 @@ protected AdaptationSet parseAdaptationSet(XmlPullParser xpp, List<String> baseU
language = checkLanguageConsistency(language, xpp.getAttributeValue(null, "lang"));
contentType = checkContentTypeConsistency(contentType, parseContentType(xpp));
} else if (ParserUtil.isStartTag(xpp, "Representation")) {
Representation representation = parseRepresentation(xpp, baseUrls, mimeType, codecs, width,
Representation representation = parseRepresentation(xpp, baseUrls.isEmpty() ? parentBaseUrls : baseUrls, mimeType, codecs, width,
height, frameRate, audioChannels, audioSamplingRate, language, segmentBase,
contentProtectionsBuilder);
contentProtectionsBuilder.endRepresentation();
Expand All @@ -261,11 +256,11 @@ protected AdaptationSet parseAdaptationSet(XmlPullParser xpp, List<String> baseU
} else if (ParserUtil.isStartTag(xpp, "AudioChannelConfiguration")) {
audioChannels = parseAudioChannelConfiguration(xpp);
} else if (ParserUtil.isStartTag(xpp, "SegmentBase")) {
segmentBase = parseSegmentBase(xpp, baseUrls, (SingleSegmentBase) segmentBase);
segmentBase = parseSegmentBase(xpp, baseUrls.isEmpty() ? parentBaseUrls : baseUrls, (SingleSegmentBase) segmentBase);
} else if (ParserUtil.isStartTag(xpp, "SegmentList")) {
segmentBase = parseSegmentList(xpp, baseUrls, (SegmentList) segmentBase);
segmentBase = parseSegmentList(xpp, baseUrls.isEmpty() ? parentBaseUrls : baseUrls, (SegmentList) segmentBase);
} else if (ParserUtil.isStartTag(xpp, "SegmentTemplate")) {
segmentBase = parseSegmentTemplate(xpp, baseUrls, (SegmentTemplate) segmentBase);
segmentBase = parseSegmentTemplate(xpp, baseUrls.isEmpty() ? parentBaseUrls : baseUrls, (SegmentTemplate) segmentBase);
} else if (ParserUtil.isStartTag(xpp)) {
parseAdaptationSetChild(xpp);
}
Expand Down Expand Up @@ -356,7 +351,7 @@ protected void parseAdaptationSetChild(XmlPullParser xpp)

// Representation parsing.

protected Representation parseRepresentation(XmlPullParser xpp, List<String> baseUrls,
protected Representation parseRepresentation(XmlPullParser xpp, List<String> parentBaseUrls,
String adaptationSetMimeType, String adaptationSetCodecs, int adaptationSetWidth,
int adaptationSetHeight, float adaptationSetFrameRate, int adaptationSetAudioChannels,
int adaptationSetAudioSamplingRate, String adaptationSetLanguage, SegmentBase segmentBase,
Expand All @@ -373,23 +368,20 @@ protected Representation parseRepresentation(XmlPullParser xpp, List<String> bas
int audioChannels = adaptationSetAudioChannels;
int audioSamplingRate = parseInt(xpp, "audioSamplingRate", adaptationSetAudioSamplingRate);
String language = adaptationSetLanguage;
List<String> baseUrls = new ArrayList<>();

boolean seenFirstBaseUrl = false;
do {
xpp.next();
if (ParserUtil.isStartTag(xpp, "BaseURL")) {
if (!seenFirstBaseUrl) {
baseUrls.add(parseBaseUrl(xpp, "")); // TODO: What to use for relative resolution?
seenFirstBaseUrl = true;
}
baseUrls.addAll(parseBaseUrls(xpp, parentBaseUrls));
} else if (ParserUtil.isStartTag(xpp, "AudioChannelConfiguration")) {
audioChannels = parseAudioChannelConfiguration(xpp);
} else if (ParserUtil.isStartTag(xpp, "SegmentBase")) {
segmentBase = parseSegmentBase(xpp, baseUrls, (SingleSegmentBase) segmentBase);
segmentBase = parseSegmentBase(xpp, baseUrls.isEmpty() ? parentBaseUrls : baseUrls, (SingleSegmentBase) segmentBase);
} else if (ParserUtil.isStartTag(xpp, "SegmentList")) {
segmentBase = parseSegmentList(xpp, baseUrls, (SegmentList) segmentBase);
segmentBase = parseSegmentList(xpp, baseUrls.isEmpty() ? parentBaseUrls : baseUrls, (SegmentList) segmentBase);
} else if (ParserUtil.isStartTag(xpp, "SegmentTemplate")) {
segmentBase = parseSegmentTemplate(xpp, baseUrls, (SegmentTemplate) segmentBase);
segmentBase = parseSegmentTemplate(xpp, baseUrls.isEmpty() ? parentBaseUrls : baseUrls, (SegmentTemplate) segmentBase);
} else if (ParserUtil.isStartTag(xpp, "ContentProtection")) {
ContentProtection contentProtection = parseContentProtection(xpp);
if (contentProtection != null) {
Expand All @@ -401,7 +393,7 @@ protected Representation parseRepresentation(XmlPullParser xpp, List<String> bas
Format format = buildFormat(id, mimeType, width, height, frameRate, audioChannels,
audioSamplingRate, bandwidth, language, codecs);
return buildRepresentation(contentId, -1, format,
segmentBase != null ? segmentBase : new SingleSegmentBase(baseUrls));
segmentBase != null ? segmentBase : new SingleSegmentBase(baseUrls.isEmpty() ? parentBaseUrls : baseUrls));
}

protected Format buildFormat(String id, String mimeType, int width, int height, float frameRate,
Expand Down Expand Up @@ -697,6 +689,12 @@ protected static long parseDateTime(XmlPullParser xpp, String name, long default
}
}

protected static List<String> parseBaseUrls(XmlPullParser xpp, List<String> parentBaseUrls)
throws XmlPullParserException, IOException {
xpp.next();
return UriUtil.resolve(parentBaseUrls, xpp.getText());
}

protected static String parseBaseUrl(XmlPullParser xpp, String parentBaseUrl)
throws XmlPullParserException, IOException {
xpp.next();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
import android.net.Uri;
import android.text.TextUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
* Utility methods for manipulating URIs.
*/
Expand Down Expand Up @@ -73,6 +77,33 @@ public static Uri resolveToUri(String baseUri, String referenceUri) {
return Uri.parse(resolve(baseUri, referenceUri));
}

/**
* Performs relative resolution of a {@code referenceUri} with respect to a {@code List} of
* {@code baseUri}s.
*
* @param baseUris A {@code List} of base URIs.
* @param referenceUri The reference URI to resolve.
*/
public static List<String> resolve(List<String> baseUris, String referenceUri) {
referenceUri = referenceUri == null ? "" : referenceUri;

int[] refIndices = getUriIndices(referenceUri);
if (refIndices[SCHEME_COLON] != -1) {
// The reference is absolute. No need to go through all baseUris.
StringBuilder uri = new StringBuilder();
uri.append(referenceUri);
removeDotSegments(uri, refIndices[PATH], refIndices[QUERY]);
return Arrays.asList(uri.toString());
} else {
// The reference is relative. Resolve using all baseUris.
ArrayList<String> resolvedUris = new ArrayList<>();
for (String baseUri : baseUris) {
resolvedUris.add(resolve(baseUri, referenceUri));
}
return resolvedUris;
}
}

/**
* Performs relative resolution of a {@code referenceUri} with respect to a {@code baseUri}.
* <p>
Expand Down

0 comments on commit 191b674

Please sign in to comment.