Add EXT-X-BYTERANGE support #139

This commit is contained in:
Andrey Udovenko 2014-11-18 14:05:34 -05:00
parent 360d452dad
commit 3abcefa00c
4 changed files with 32 additions and 3 deletions

View File

@ -138,6 +138,9 @@ package com.google.android.exoplayer.demo;
new Sample("Apple master playlist", "uid:hls:applemaster",
"https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/"
+ "bipbop_4x3_variant.m3u8", DemoUtil.TYPE_HLS_MASTER, false, true),
new Sample("Apple master playlist advanced", "uid:hls:applemasteradvanced",
"https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_16x9/"
+ "bipbop_16x9_variant.m3u8", DemoUtil.TYPE_HLS_MASTER, false, true),
new Sample("Apple single media playlist", "uid:hls:applesinglemedia",
"https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear1/"
+ "prog_index.m3u8", DemoUtil.TYPE_HLS_MEDIA, false, true),

View File

@ -239,7 +239,8 @@ public class HlsChunkSource {
} else {
dataSource = upstreamDataSource;
}
DataSpec dataSpec = new DataSpec(chunkUri, 0, C.LENGTH_UNBOUNDED, null);
DataSpec dataSpec = new DataSpec(chunkUri, segment.byterangeOffset, segment.byterangeLength,
null);
// Configure the extractor that will read the chunk.
TsExtractor extractor;

View File

@ -35,9 +35,12 @@ public final class HlsMediaPlaylist {
public final String encryptionMethod;
public final String encryptionKeyUri;
public final String encryptionIV;
public final int byterangeOffset;
public final int byterangeLength;
public Segment(String uri, double durationSecs, boolean discontinuity, long startTimeUs,
String encryptionMethod, String encryptionKeyUri, String encryptionIV) {
String encryptionMethod, String encryptionKeyUri, String encryptionIV,
int byterangeOffset, int byterangeLength) {
this.url = uri;
this.durationSecs = durationSecs;
this.discontinuity = discontinuity;
@ -45,6 +48,8 @@ public final class HlsMediaPlaylist {
this.encryptionMethod = encryptionMethod;
this.encryptionKeyUri = encryptionKeyUri;
this.encryptionIV = encryptionIV;
this.byterangeOffset = byterangeOffset;
this.byterangeLength = byterangeLength;
}
@Override

View File

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer.hls;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.hls.HlsMediaPlaylist.Segment;
import com.google.android.exoplayer.util.ManifestParser;
@ -41,6 +42,7 @@ public final class HlsMediaPlaylistParser implements ManifestParser<HlsMediaPlay
private static final String VERSION_TAG = "#EXT-X-VERSION";
private static final String ENDLIST_TAG = "#EXT-X-ENDLIST";
private static final String KEY_TAG = "#EXT-X-KEY";
private static final String BYTERANGE_TAG = "#EXT-X-BYTERANGE";
private static final String METHOD_ATTR = "METHOD";
private static final String URI_ATTR = "URI";
@ -54,6 +56,8 @@ public final class HlsMediaPlaylistParser implements ManifestParser<HlsMediaPlay
Pattern.compile(TARGET_DURATION_TAG + ":(\\d+)\\b");
private static final Pattern VERSION_REGEX =
Pattern.compile(VERSION_TAG + ":(\\d+)\\b");
private static final Pattern BYTERANGE_REGEX =
Pattern.compile(BYTERANGE_TAG + ":(\\d+(?:@\\d+)?)\\b");
private static final Pattern METHOD_ATTR_REGEX =
Pattern.compile(METHOD_ATTR + "=([^,.*]+)");
@ -85,6 +89,8 @@ public final class HlsMediaPlaylistParser implements ManifestParser<HlsMediaPlay
String segmentEncryptionMethod = null;
String segmentEncryptionKeyUri = null;
String segmentEncryptionIV = null;
int segmentByterangeOffset = 0;
int segmentByterangeLength = C.LENGTH_UNBOUNDED;
int segmentMediaSequence = 0;
@ -119,16 +125,30 @@ public final class HlsMediaPlaylistParser implements ManifestParser<HlsMediaPlay
segmentEncryptionIV = Integer.toHexString(segmentMediaSequence);
}
}
} else if (line.startsWith(BYTERANGE_TAG)) {
String byteRange = HlsParserUtil.parseStringAttr(line, BYTERANGE_REGEX, BYTERANGE_TAG);
String[] splitByteRange = byteRange.split("@");
segmentByterangeLength = Integer.parseInt(splitByteRange[0]);
if (splitByteRange.length > 1) {
segmentByterangeOffset = Integer.parseInt(splitByteRange[1]);
}
} else if (line.equals(DISCONTINUITY_TAG)) {
segmentDiscontinuity = true;
} else if (!line.startsWith("#")) {
segmentMediaSequence++;
if (segmentByterangeLength == C.LENGTH_UNBOUNDED) {
segmentByterangeOffset = 0;
}
segments.add(new Segment(line, segmentDurationSecs, segmentDiscontinuity,
segmentStartTimeUs, segmentEncryptionMethod, segmentEncryptionKeyUri,
segmentEncryptionIV));
segmentEncryptionIV, segmentByterangeOffset, segmentByterangeLength));
segmentStartTimeUs += (long) (segmentDurationSecs * 1000000);
segmentDiscontinuity = false;
segmentDurationSecs = 0.0;
if (segmentByterangeLength != C.LENGTH_UNBOUNDED) {
segmentByterangeOffset += segmentByterangeLength;
}
segmentByterangeLength = C.LENGTH_UNBOUNDED;
} else if (line.equals(ENDLIST_TAG)) {
live = false;
break;