Commit 28e117d2 by aquilescanta Committed by Oliver Woodman

Add support for #EXT-X-START tag

This overrides the start position relative to the window.

Issue:#1544

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=144434903
parent 63123f45
...@@ -104,17 +104,23 @@ public final class HlsMediaSource implements MediaSource, ...@@ -104,17 +104,23 @@ public final class HlsMediaSource implements MediaSource,
@Override @Override
public void onPrimaryPlaylistRefreshed(HlsMediaPlaylist playlist) { public void onPrimaryPlaylistRefreshed(HlsMediaPlaylist playlist) {
SinglePeriodTimeline timeline; SinglePeriodTimeline timeline;
long windowDefaultStartPositionUs = playlist.startOffsetUs;
if (playlistTracker.isLive()) { if (playlistTracker.isLive()) {
long periodDurationUs = playlist.hasEndTag ? (playlist.startTimeUs + playlist.durationUs) long periodDurationUs = playlist.hasEndTag ? (playlist.startTimeUs + playlist.durationUs)
: C.TIME_UNSET; : C.TIME_UNSET;
List<HlsMediaPlaylist.Segment> segments = playlist.segments; List<HlsMediaPlaylist.Segment> segments = playlist.segments;
long windowDefaultStartPositionUs = segments.isEmpty() ? 0 if (windowDefaultStartPositionUs == C.TIME_UNSET) {
: segments.get(Math.max(0, segments.size() - 3)).relativeStartTimeUs; windowDefaultStartPositionUs = segments.isEmpty() ? 0
: segments.get(Math.max(0, segments.size() - 3)).relativeStartTimeUs;
}
timeline = new SinglePeriodTimeline(periodDurationUs, playlist.durationUs, timeline = new SinglePeriodTimeline(periodDurationUs, playlist.durationUs,
playlist.startTimeUs, windowDefaultStartPositionUs, true, !playlist.hasEndTag); playlist.startTimeUs, windowDefaultStartPositionUs, true, !playlist.hasEndTag);
} else /* not live */ { } else /* not live */ {
if (windowDefaultStartPositionUs == C.TIME_UNSET) {
windowDefaultStartPositionUs = 0;
}
timeline = new SinglePeriodTimeline(playlist.startTimeUs + playlist.durationUs, timeline = new SinglePeriodTimeline(playlist.startTimeUs + playlist.durationUs,
playlist.durationUs, playlist.startTimeUs, 0, true, false); playlist.durationUs, playlist.startTimeUs, windowDefaultStartPositionUs, true, false);
} }
sourceListener.onSourceInfoRefreshed(timeline, playlist); sourceListener.onSourceInfoRefreshed(timeline, playlist);
} }
......
...@@ -65,6 +65,7 @@ public final class HlsMediaPlaylist extends HlsPlaylist { ...@@ -65,6 +65,7 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
} }
public final long startOffsetUs;
public final long startTimeUs; public final long startTimeUs;
public final int mediaSequence; public final int mediaSequence;
public final int version; public final int version;
...@@ -75,7 +76,7 @@ public final class HlsMediaPlaylist extends HlsPlaylist { ...@@ -75,7 +76,7 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
public final List<Segment> segments; public final List<Segment> segments;
public final long durationUs; public final long durationUs;
public HlsMediaPlaylist(String baseUri, long startTimeUs, int mediaSequence, public HlsMediaPlaylist(String baseUri, long startOffsetUs, long startTimeUs, int mediaSequence,
int version, long targetDurationUs, boolean hasEndTag, boolean hasProgramDateTime, int version, long targetDurationUs, boolean hasEndTag, boolean hasProgramDateTime,
Segment initializationSegment, List<Segment> segments) { Segment initializationSegment, List<Segment> segments) {
super(baseUri, HlsPlaylist.TYPE_MEDIA); super(baseUri, HlsPlaylist.TYPE_MEDIA);
...@@ -87,13 +88,14 @@ public final class HlsMediaPlaylist extends HlsPlaylist { ...@@ -87,13 +88,14 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
this.hasProgramDateTime = hasProgramDateTime; this.hasProgramDateTime = hasProgramDateTime;
this.initializationSegment = initializationSegment; this.initializationSegment = initializationSegment;
this.segments = Collections.unmodifiableList(segments); this.segments = Collections.unmodifiableList(segments);
if (!segments.isEmpty()) { if (!segments.isEmpty()) {
Segment last = segments.get(segments.size() - 1); Segment last = segments.get(segments.size() - 1);
durationUs = last.relativeStartTimeUs + last.durationUs; durationUs = last.relativeStartTimeUs + last.durationUs;
} else { } else {
durationUs = 0; durationUs = 0;
} }
this.startOffsetUs = startOffsetUs == C.TIME_UNSET ? C.TIME_UNSET
: startOffsetUs >= 0 ? startOffsetUs : durationUs + startOffsetUs;
} }
/** /**
...@@ -132,8 +134,8 @@ public final class HlsMediaPlaylist extends HlsPlaylist { ...@@ -132,8 +134,8 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
if (this.startTimeUs == startTimeUs) { if (this.startTimeUs == startTimeUs) {
return this; return this;
} }
return new HlsMediaPlaylist(baseUri, startTimeUs, mediaSequence, version, targetDurationUs, return new HlsMediaPlaylist(baseUri, startOffsetUs, startTimeUs, mediaSequence, version,
hasEndTag, hasProgramDateTime, initializationSegment, segments); targetDurationUs, hasEndTag, hasProgramDateTime, initializationSegment, segments);
} }
/** /**
...@@ -146,8 +148,8 @@ public final class HlsMediaPlaylist extends HlsPlaylist { ...@@ -146,8 +148,8 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
if (this.hasEndTag) { if (this.hasEndTag) {
return this; return this;
} }
return new HlsMediaPlaylist(baseUri, startTimeUs, mediaSequence, version, targetDurationUs, return new HlsMediaPlaylist(baseUri, startOffsetUs, startTimeUs, mediaSequence, version,
true, hasProgramDateTime, initializationSegment, segments); targetDurationUs, true, hasProgramDateTime, initializationSegment, segments);
} }
} }
...@@ -58,13 +58,14 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli ...@@ -58,13 +58,14 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
private static final String TAG_VERSION = "#EXT-X-VERSION"; private static final String TAG_VERSION = "#EXT-X-VERSION";
private static final String TAG_STREAM_INF = "#EXT-X-STREAM-INF"; private static final String TAG_STREAM_INF = "#EXT-X-STREAM-INF";
private static final String TAG_MEDIA = "#EXT-X-MEDIA"; private static final String TAG_MEDIA = "#EXT-X-MEDIA";
private static final String TAG_TARGET_DURATION = "#EXT-X-TARGETDURATION";
private static final String TAG_DISCONTINUITY = "#EXT-X-DISCONTINUITY"; private static final String TAG_DISCONTINUITY = "#EXT-X-DISCONTINUITY";
private static final String TAG_DISCONTINUITY_SEQUENCE = "#EXT-X-DISCONTINUITY-SEQUENCE"; private static final String TAG_DISCONTINUITY_SEQUENCE = "#EXT-X-DISCONTINUITY-SEQUENCE";
private static final String TAG_PROGRAM_DATE_TIME = "#EXT-X-PROGRAM-DATE-TIME"; private static final String TAG_PROGRAM_DATE_TIME = "#EXT-X-PROGRAM-DATE-TIME";
private static final String TAG_INIT_SEGMENT = "#EXT-X-MAP"; private static final String TAG_INIT_SEGMENT = "#EXT-X-MAP";
private static final String TAG_MEDIA_DURATION = "#EXTINF"; private static final String TAG_MEDIA_DURATION = "#EXTINF";
private static final String TAG_MEDIA_SEQUENCE = "#EXT-X-MEDIA-SEQUENCE"; private static final String TAG_MEDIA_SEQUENCE = "#EXT-X-MEDIA-SEQUENCE";
private static final String TAG_TARGET_DURATION = "#EXT-X-TARGETDURATION"; private static final String TAG_START = "#EXT-X-START";
private static final String TAG_ENDLIST = "#EXT-X-ENDLIST"; private static final String TAG_ENDLIST = "#EXT-X-ENDLIST";
private static final String TAG_KEY = "#EXT-X-KEY"; private static final String TAG_KEY = "#EXT-X-KEY";
private static final String TAG_BYTERANGE = "#EXT-X-BYTERANGE"; private static final String TAG_BYTERANGE = "#EXT-X-BYTERANGE";
...@@ -90,6 +91,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli ...@@ -90,6 +91,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
+ ":(\\d+)\\b"); + ":(\\d+)\\b");
private static final Pattern REGEX_MEDIA_DURATION = Pattern.compile(TAG_MEDIA_DURATION private static final Pattern REGEX_MEDIA_DURATION = Pattern.compile(TAG_MEDIA_DURATION
+ ":([\\d\\.]+)\\b"); + ":([\\d\\.]+)\\b");
private static final Pattern REGEX_TIME_OFFSET = Pattern.compile("TIME-OFFSET=([\\d\\.]+)\\b");
private static final Pattern REGEX_BYTERANGE = Pattern.compile(TAG_BYTERANGE private static final Pattern REGEX_BYTERANGE = Pattern.compile(TAG_BYTERANGE
+ ":(\\d+(?:@\\d+)?)\\b"); + ":(\\d+(?:@\\d+)?)\\b");
private static final Pattern REGEX_ATTR_BYTERANGE = private static final Pattern REGEX_ATTR_BYTERANGE =
...@@ -255,6 +257,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli ...@@ -255,6 +257,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
private static HlsMediaPlaylist parseMediaPlaylist(LineIterator iterator, String baseUri) private static HlsMediaPlaylist parseMediaPlaylist(LineIterator iterator, String baseUri)
throws IOException { throws IOException {
long startOffsetUs = C.TIME_UNSET;
int mediaSequence = 0; int mediaSequence = 0;
int version = 1; // Default version == 1. int version = 1; // Default version == 1.
long targetDurationUs = C.TIME_UNSET; long targetDurationUs = C.TIME_UNSET;
...@@ -277,7 +280,9 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli ...@@ -277,7 +280,9 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
String line; String line;
while (iterator.hasNext()) { while (iterator.hasNext()) {
line = iterator.next(); line = iterator.next();
if (line.startsWith(TAG_INIT_SEGMENT)) { if (line.startsWith(TAG_START)) {
startOffsetUs = (long) (parseDoubleAttr(line, REGEX_TIME_OFFSET) * C.MICROS_PER_SECOND);
} else if (line.startsWith(TAG_INIT_SEGMENT)) {
String uri = parseStringAttr(line, REGEX_URI); String uri = parseStringAttr(line, REGEX_URI);
String byteRange = parseOptionalStringAttr(line, REGEX_ATTR_BYTERANGE); String byteRange = parseOptionalStringAttr(line, REGEX_ATTR_BYTERANGE);
if (byteRange != null) { if (byteRange != null) {
...@@ -353,7 +358,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli ...@@ -353,7 +358,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
hasEndTag = true; hasEndTag = true;
} }
} }
return new HlsMediaPlaylist(baseUri, playlistStartTimeUs, mediaSequence, version, return new HlsMediaPlaylist(baseUri, startOffsetUs, playlistStartTimeUs, mediaSequence, version,
targetDurationUs, hasEndTag, playlistStartTimeUs != 0, initializationSegment, segments); targetDurationUs, hasEndTag, playlistStartTimeUs != 0, initializationSegment, segments);
} }
......
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