Merge pull request #82 from google/dev

Pull dev -> dev-hls
This commit is contained in:
ojw28 2014-10-20 16:59:18 +01:00
commit c2c7a75681
7 changed files with 118 additions and 43 deletions

View file

@ -294,6 +294,9 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer {
case 6:
channelConfig = AudioFormat.CHANNEL_OUT_5POINT1;
break;
case 8:
channelConfig = AudioFormat.CHANNEL_OUT_7POINT1;
break;
default:
throw new IllegalArgumentException("Unsupported channel count: " + channelCount);
}

View file

@ -21,7 +21,7 @@ import java.util.List;
/**
* Represents a set of interchangeable encoded versions of a media content component.
*/
public final class AdaptationSet {
public class AdaptationSet {
public static final int TYPE_UNKNOWN = -1;
public static final int TYPE_VIDEO = 0;

View file

@ -15,36 +15,21 @@
*/
package com.google.android.exoplayer.dash.mpd;
import java.util.Collections;
import java.util.Map;
/**
* Represents a ContentProtection tag in an AdaptationSet. Holds arbitrary data for various DRM
* schemes.
* Represents a ContentProtection tag in an AdaptationSet.
*/
public final class ContentProtection {
public class ContentProtection {
/**
* Identifies the content protection scheme.
*/
public final String schemeUriId;
/**
* Protection scheme specific data.
*/
public final Map<String, String> keyedData;
/**
* @param schemeUriId Identifies the content protection scheme.
* @param keyedData Data specific to the scheme.
*/
public ContentProtection(String schemeUriId, Map<String, String> keyedData) {
public ContentProtection(String schemeUriId) {
this.schemeUriId = schemeUriId;
if (keyedData != null) {
this.keyedData = Collections.unmodifiableMap(keyedData);
} else {
this.keyedData = Collections.emptyMap();
}
}
}

View file

@ -21,7 +21,7 @@ import java.util.List;
/**
* Represents a DASH media presentation description (mpd).
*/
public final class MediaPresentationDescription {
public class MediaPresentationDescription {
public final long availabilityStartTime;

View file

@ -77,7 +77,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
}
}
private MediaPresentationDescription parseMediaPresentationDescription(XmlPullParser xpp,
protected MediaPresentationDescription parseMediaPresentationDescription(XmlPullParser xpp,
String contentId, Uri baseUrl) throws XmlPullParserException, IOException, ParseException {
long availabilityStartTime = parseDateTime(xpp, "availabilityStartTime", -1);
long durationMs = parseDuration(xpp, "mediaPresentationDuration", -1);
@ -101,17 +101,29 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
}
} while (!isEndTag(xpp, "MPD"));
return buildMediaPresentationDescription(availabilityStartTime, durationMs, minBufferTimeMs,
dynamic, minUpdateTimeMs, timeShiftBufferDepthMs, utcTiming, periods);
}
protected MediaPresentationDescription buildMediaPresentationDescription(
long availabilityStartTime, long durationMs, long minBufferTimeMs, boolean dynamic,
long minUpdateTimeMs, long timeShiftBufferDepthMs, UtcTimingElement utcTiming,
List<Period> periods) {
return new MediaPresentationDescription(availabilityStartTime, durationMs, minBufferTimeMs,
dynamic, minUpdateTimeMs, timeShiftBufferDepthMs, utcTiming, periods);
}
private UtcTimingElement parseUtcTiming(XmlPullParser xpp) {
protected UtcTimingElement parseUtcTiming(XmlPullParser xpp) {
String schemeIdUri = xpp.getAttributeValue(null, "schemeIdUri");
String value = xpp.getAttributeValue(null, "value");
return buildUtcTimingElement(schemeIdUri, value);
}
protected UtcTimingElement buildUtcTimingElement(String schemeIdUri, String value) {
return new UtcTimingElement(schemeIdUri, value);
}
private Period parsePeriod(XmlPullParser xpp, String contentId, Uri baseUrl, long mpdDurationMs)
protected Period parsePeriod(XmlPullParser xpp, String contentId, Uri baseUrl, long mpdDurationMs)
throws XmlPullParserException, IOException {
String id = xpp.getAttributeValue(null, "id");
long startMs = parseDuration(xpp, "start", 0);
@ -134,12 +146,17 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
}
} while (!isEndTag(xpp, "Period"));
return buildPeriod(id, startMs, durationMs, adaptationSets);
}
protected Period buildPeriod(
String id, long startMs, long durationMs, List<AdaptationSet> adaptationSets) {
return new Period(id, startMs, durationMs, adaptationSets);
}
// AdaptationSet parsing.
private AdaptationSet parseAdaptationSet(XmlPullParser xpp, String contentId, Uri baseUrl,
protected AdaptationSet parseAdaptationSet(XmlPullParser xpp, String contentId, Uri baseUrl,
long periodStartMs, long periodDurationMs, SegmentBase segmentBase)
throws XmlPullParserException, IOException {
@ -176,13 +193,20 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
} else if (isStartTag(xpp, "SegmentTemplate")) {
segmentBase = parseSegmentTemplate(xpp, baseUrl, (SegmentTemplate) segmentBase,
periodDurationMs);
} else if (isStartTag(xpp)) {
parseAdaptationSetChild(xpp);
}
} while (!isEndTag(xpp, "AdaptationSet"));
return buildAdaptationSet(id, contentType, representations, contentProtections);
}
protected AdaptationSet buildAdaptationSet(int id, int contentType,
List<Representation> representations, List<ContentProtection> contentProtections) {
return new AdaptationSet(id, contentType, representations, contentProtections);
}
private int parseAdaptationSetType(String contentType) {
protected int parseAdaptationSetType(String contentType) {
return TextUtils.isEmpty(contentType) ? AdaptationSet.TYPE_UNKNOWN
: MimeTypes.BASE_TYPE_AUDIO.equals(contentType) ? AdaptationSet.TYPE_AUDIO
: MimeTypes.BASE_TYPE_VIDEO.equals(contentType) ? AdaptationSet.TYPE_VIDEO
@ -190,7 +214,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
: AdaptationSet.TYPE_UNKNOWN;
}
private int parseAdaptationSetTypeFromMimeType(String mimeType) {
protected int parseAdaptationSetTypeFromMimeType(String mimeType) {
return TextUtils.isEmpty(mimeType) ? AdaptationSet.TYPE_UNKNOWN
: MimeTypes.isAudio(mimeType) ? AdaptationSet.TYPE_AUDIO
: MimeTypes.isVideo(mimeType) ? AdaptationSet.TYPE_VIDEO
@ -228,13 +252,29 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
**/
protected ContentProtection parseContentProtection(XmlPullParser xpp)
throws XmlPullParserException, IOException {
String schemeUriId = xpp.getAttributeValue(null, "schemeUriId");
return new ContentProtection(schemeUriId, null);
String schemeIdUri = xpp.getAttributeValue(null, "schemeIdUri");
return buildContentProtection(schemeIdUri);
}
protected ContentProtection buildContentProtection(String schemeIdUri) {
return new ContentProtection(schemeIdUri);
}
/**
* Parses children of AdaptationSet elements not specifically parsed elsewhere.
*
* @param xpp The XmpPullParser from which the AdaptationSet child should be parsed.
* @throws XmlPullParserException If an error occurs parsing the element.
* @throws IOException If an error occurs reading the element.
**/
protected void parseAdaptationSetChild(XmlPullParser xpp)
throws XmlPullParserException, IOException {
// pass
}
// Representation parsing.
private Representation parseRepresentation(XmlPullParser xpp, String contentId, Uri baseUrl,
protected Representation parseRepresentation(XmlPullParser xpp, String contentId, Uri baseUrl,
long periodStartMs, long periodDurationMs, String mimeType, String language,
SegmentBase segmentBase) throws XmlPullParserException, IOException {
String id = xpp.getAttributeValue(null, "id");
@ -261,15 +301,27 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
}
} while (!isEndTag(xpp, "Representation"));
Format format = new Format(id, mimeType, width, height, numChannels, audioSamplingRate,
Format format = buildFormat(id, mimeType, width, height, numChannels, audioSamplingRate,
bandwidth, language);
return Representation.newInstance(periodStartMs, periodDurationMs, contentId, -1, format,
return buildRepresentation(periodStartMs, periodDurationMs, contentId, -1, format,
segmentBase);
}
protected Format buildFormat(String id, String mimeType, int width, int height, int numChannels,
int audioSamplingRate, int bandwidth, String language) {
return new Format(id, mimeType, width, height, numChannels, audioSamplingRate,
bandwidth, language);
}
protected Representation buildRepresentation(long periodStartMs, long periodDurationMs,
String contentId, int revisionId, Format format, SegmentBase segmentBase) {
return Representation.newInstance(periodStartMs, periodDurationMs, contentId, revisionId,
format, segmentBase);
}
// SegmentBase, SegmentList and SegmentTemplate parsing.
private SingleSegmentBase parseSegmentBase(XmlPullParser xpp, Uri baseUrl,
protected SingleSegmentBase parseSegmentBase(XmlPullParser xpp, Uri baseUrl,
SingleSegmentBase parent) throws XmlPullParserException, IOException {
long timescale = parseLong(xpp, "timescale", parent != null ? parent.timescale : 1);
@ -293,11 +345,17 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
}
} while (!isEndTag(xpp, "SegmentBase"));
return buildSingleSegmentBase(initialization, timescale, presentationTimeOffset, baseUrl,
indexStart, indexLength);
}
protected SingleSegmentBase buildSingleSegmentBase(RangedUri initialization, long timescale,
long presentationTimeOffset, Uri baseUrl, long indexStart, long indexLength) {
return new SingleSegmentBase(initialization, timescale, presentationTimeOffset, baseUrl,
indexStart, indexLength);
}
private SegmentList parseSegmentList(XmlPullParser xpp, Uri baseUrl, SegmentList parent,
protected SegmentList parseSegmentList(XmlPullParser xpp, Uri baseUrl, SegmentList parent,
long periodDuration) throws XmlPullParserException, IOException {
long timescale = parseLong(xpp, "timescale", parent != null ? parent.timescale : 1);
@ -330,11 +388,18 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
segments = segments != null ? segments : parent.mediaSegments;
}
return buildSegmentList(initialization, timescale, presentationTimeOffset, periodDuration,
startNumber, duration, timeline, segments);
}
protected SegmentList buildSegmentList(RangedUri initialization, long timescale,
long presentationTimeOffset, long periodDuration, int startNumber, long duration,
List<SegmentTimelineElement> timeline, List<RangedUri> segments) {
return new SegmentList(initialization, timescale, presentationTimeOffset, periodDuration,
startNumber, duration, timeline, segments);
}
private SegmentTemplate parseSegmentTemplate(XmlPullParser xpp, Uri baseUrl,
protected SegmentTemplate parseSegmentTemplate(XmlPullParser xpp, Uri baseUrl,
SegmentTemplate parent, long periodDuration) throws XmlPullParserException, IOException {
long timescale = parseLong(xpp, "timescale", parent != null ? parent.timescale : 1);
@ -364,11 +429,19 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
timeline = timeline != null ? timeline : parent.segmentTimeline;
}
return buildSegmentTemplate(initialization, timescale, presentationTimeOffset, periodDuration,
startNumber, duration, timeline, initializationTemplate, mediaTemplate, baseUrl);
}
protected SegmentTemplate buildSegmentTemplate(RangedUri initialization, long timescale,
long presentationTimeOffset, long periodDuration, int startNumber, long duration,
List<SegmentTimelineElement> timeline, UrlTemplate initializationTemplate,
UrlTemplate mediaTemplate, Uri baseUrl) {
return new SegmentTemplate(initialization, timescale, presentationTimeOffset, periodDuration,
startNumber, duration, timeline, initializationTemplate, mediaTemplate, baseUrl);
}
private List<SegmentTimelineElement> parseSegmentTimeline(XmlPullParser xpp)
protected List<SegmentTimelineElement> parseSegmentTimeline(XmlPullParser xpp)
throws XmlPullParserException, IOException {
List<SegmentTimelineElement> segmentTimeline = new ArrayList<SegmentTimelineElement>();
long elapsedTime = 0;
@ -379,7 +452,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
long duration = parseLong(xpp, "d");
int count = 1 + parseInt(xpp, "r", 0);
for (int i = 0; i < count; i++) {
segmentTimeline.add(new SegmentTimelineElement(elapsedTime, duration));
segmentTimeline.add(buildSegmentTimelineElement(elapsedTime, duration));
elapsedTime += duration;
}
}
@ -387,7 +460,11 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
return segmentTimeline;
}
private UrlTemplate parseUrlTemplate(XmlPullParser xpp, String name,
protected SegmentTimelineElement buildSegmentTimelineElement(long elapsedTime, long duration) {
return new SegmentTimelineElement(elapsedTime, duration);
}
protected UrlTemplate parseUrlTemplate(XmlPullParser xpp, String name,
UrlTemplate defaultValue) {
String valueString = xpp.getAttributeValue(null, name);
if (valueString != null) {
@ -396,15 +473,15 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
return defaultValue;
}
private RangedUri parseInitialization(XmlPullParser xpp, Uri baseUrl) {
protected RangedUri parseInitialization(XmlPullParser xpp, Uri baseUrl) {
return parseRangedUrl(xpp, baseUrl, "sourceURL", "range");
}
private RangedUri parseSegmentUrl(XmlPullParser xpp, Uri baseUrl) {
protected RangedUri parseSegmentUrl(XmlPullParser xpp, Uri baseUrl) {
return parseRangedUrl(xpp, baseUrl, "media", "mediaRange");
}
private RangedUri parseRangedUrl(XmlPullParser xpp, Uri baseUrl, String urlAttribute,
protected RangedUri parseRangedUrl(XmlPullParser xpp, Uri baseUrl, String urlAttribute,
String rangeAttribute) {
String urlText = xpp.getAttributeValue(null, urlAttribute);
long rangeStart = 0;
@ -415,6 +492,11 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
rangeStart = Long.parseLong(rangeTextArray[0]);
rangeLength = Long.parseLong(rangeTextArray[1]) - rangeStart + 1;
}
return buildRangedUri(baseUrl, urlText, rangeStart, rangeLength);
}
protected RangedUri buildRangedUri(Uri baseUrl, String urlText, long rangeStart,
long rangeLength) {
return new RangedUri(baseUrl, urlText, rangeStart, rangeLength);
}
@ -429,7 +511,11 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
return xpp.getEventType() == XmlPullParser.START_TAG && name.equals(xpp.getName());
}
private static long parseDuration(XmlPullParser xpp, String name, long defaultValue) {
protected static boolean isStartTag(XmlPullParser xpp) throws XmlPullParserException {
return xpp.getEventType() == XmlPullParser.START_TAG;
}
protected static long parseDuration(XmlPullParser xpp, String name, long defaultValue) {
String value = xpp.getAttributeValue(null, name);
if (value == null) {
return defaultValue;
@ -438,7 +524,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
}
}
private static long parseDateTime(XmlPullParser xpp, String name, long defaultValue)
protected static long parseDateTime(XmlPullParser xpp, String name, long defaultValue)
throws ParseException {
String value = xpp.getAttributeValue(null, name);
if (value == null) {

View file

@ -21,7 +21,7 @@ import java.util.List;
/**
* Encapsulates media content components over a contiguous period of time.
*/
public final class Period {
public class Period {
/**
* The period identifier, if one exists.

View file

@ -167,6 +167,7 @@ public final class Util {
return Uri.parse(stringUri);
}
if (stringUri.startsWith("/")) {
stringUri = stringUri.substring(1);
return new Uri.Builder()
.scheme(baseUri.getScheme())
.authority(baseUri.getAuthority())