mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
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
This commit is contained in:
parent
63123f455c
commit
28e117d25f
3 changed files with 25 additions and 12 deletions
|
|
@ -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 {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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
|
||||||
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
|
||||||
+ ":(\\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
|
||||||
|
|
||||||
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
|
||||||
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
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue