Support multiple EXT-X-MAP tags
Issue:#4182 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=194223312
This commit is contained in:
parent
dcff063709
commit
ddef32c9e2
@ -77,6 +77,8 @@
|
||||
([#4145](https://github.com/google/ExoPlayer/issues/4145)).
|
||||
* Preeptively declare an ID3 track in chunkless preparation
|
||||
([#4016](https://github.com/google/ExoPlayer/issues/4016)).
|
||||
* Add support for multiple #EXT-X-MAP tags in a media playlist
|
||||
([#4164](https://github.com/google/ExoPlayer/issues/4182)).
|
||||
* Fix ClearKey decryption error if the key contains a forward slash
|
||||
([#4075](https://github.com/google/ExoPlayer/issues/4075)).
|
||||
* Fix crash when switching surface on Huawei P9 Lite
|
||||
|
@ -320,7 +320,7 @@ import java.util.List;
|
||||
}
|
||||
|
||||
DataSpec initDataSpec = null;
|
||||
Segment initSegment = mediaPlaylist.initializationSegment;
|
||||
Segment initSegment = segment.initializationSegment;
|
||||
if (initSegment != null) {
|
||||
Uri initSegmentUri = UriUtil.resolveToUri(mediaPlaylist.baseUri, initSegment.url);
|
||||
initDataSpec = new DataSpec(initSegmentUri, initSegment.byterangeOffset,
|
||||
|
@ -94,14 +94,16 @@ public final class HlsDownloader extends SegmentDownloader<HlsMasterPlaylist, Re
|
||||
continue;
|
||||
}
|
||||
|
||||
HlsMediaPlaylist.Segment initSegment = mediaPlaylist.initializationSegment;
|
||||
if (initSegment != null) {
|
||||
addSegment(segments, mediaPlaylist, initSegment, encryptionKeyUris);
|
||||
}
|
||||
|
||||
HlsMediaPlaylist.Segment lastInitSegment = null;
|
||||
List<HlsMediaPlaylist.Segment> hlsSegments = mediaPlaylist.segments;
|
||||
for (int i = 0; i < hlsSegments.size(); i++) {
|
||||
addSegment(segments, mediaPlaylist, hlsSegments.get(i), encryptionKeyUris);
|
||||
HlsMediaPlaylist.Segment segment = hlsSegments.get(i);
|
||||
HlsMediaPlaylist.Segment initSegment = segment.initializationSegment;
|
||||
if (initSegment != null && initSegment != lastInitSegment) {
|
||||
lastInitSegment = initSegment;
|
||||
addSegment(segments, mediaPlaylist, initSegment, encryptionKeyUris);
|
||||
}
|
||||
addSegment(segments, mediaPlaylist, segment, encryptionKeyUris);
|
||||
}
|
||||
}
|
||||
return segments;
|
||||
|
@ -17,6 +17,7 @@ package com.google.android.exoplayer2.source.hls.playlist;
|
||||
|
||||
import android.support.annotation.IntDef;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.drm.DrmInitData;
|
||||
import java.lang.annotation.Retention;
|
||||
@ -38,8 +39,12 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
|
||||
*/
|
||||
public final String url;
|
||||
/**
|
||||
* The duration of the segment in microseconds, as defined by #EXTINF.
|
||||
* The media initialization section for this segment, as defined by #EXT-X-MAP. May be null if
|
||||
* the media playlist does not define a media section for this segment. The same instance is
|
||||
* used for all segments that share an EXT-X-MAP tag.
|
||||
*/
|
||||
@Nullable public final Segment initializationSegment;
|
||||
/** The duration of the segment in microseconds, as defined by #EXTINF. */
|
||||
public final long durationUs;
|
||||
/**
|
||||
* The number of #EXT-X-DISCONTINUITY tags in the playlist before the segment.
|
||||
@ -78,11 +83,12 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
|
||||
* @param byterangeLength See {@link #byterangeLength}.
|
||||
*/
|
||||
public Segment(String uri, long byterangeOffset, long byterangeLength) {
|
||||
this(uri, 0, -1, C.TIME_UNSET, null, null, byterangeOffset, byterangeLength, false);
|
||||
this(uri, null, 0, -1, C.TIME_UNSET, null, null, byterangeOffset, byterangeLength, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param url See {@link #url}.
|
||||
* @param initializationSegment See {@link #initializationSegment}.
|
||||
* @param durationUs See {@link #durationUs}.
|
||||
* @param relativeDiscontinuitySequence See {@link #relativeDiscontinuitySequence}.
|
||||
* @param relativeStartTimeUs See {@link #relativeStartTimeUs}.
|
||||
@ -94,6 +100,7 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
|
||||
*/
|
||||
public Segment(
|
||||
String url,
|
||||
Segment initializationSegment,
|
||||
long durationUs,
|
||||
int relativeDiscontinuitySequence,
|
||||
long relativeStartTimeUs,
|
||||
@ -103,6 +110,7 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
|
||||
long byterangeLength,
|
||||
boolean hasGapTag) {
|
||||
this.url = url;
|
||||
this.initializationSegment = initializationSegment;
|
||||
this.durationUs = durationUs;
|
||||
this.relativeDiscontinuitySequence = relativeDiscontinuitySequence;
|
||||
this.relativeStartTimeUs = relativeStartTimeUs;
|
||||
@ -182,10 +190,6 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
|
||||
* encryption.
|
||||
*/
|
||||
public final DrmInitData drmInitData;
|
||||
/**
|
||||
* The initialization segment, as defined by #EXT-X-MAP.
|
||||
*/
|
||||
public final Segment initializationSegment;
|
||||
/**
|
||||
* The list of segments in the playlist.
|
||||
*/
|
||||
@ -210,7 +214,6 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
|
||||
* @param hasEndTag See {@link #hasEndTag}.
|
||||
* @param hasProgramDateTime See {@link #hasProgramDateTime}.
|
||||
* @param drmInitData See {@link #drmInitData}.
|
||||
* @param initializationSegment See {@link #initializationSegment}.
|
||||
* @param segments See {@link #segments}.
|
||||
*/
|
||||
public HlsMediaPlaylist(
|
||||
@ -228,7 +231,6 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
|
||||
boolean hasEndTag,
|
||||
boolean hasProgramDateTime,
|
||||
DrmInitData drmInitData,
|
||||
Segment initializationSegment,
|
||||
List<Segment> segments) {
|
||||
super(baseUri, tags);
|
||||
this.playlistType = playlistType;
|
||||
@ -242,7 +244,6 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
|
||||
this.hasEndTag = hasEndTag;
|
||||
this.hasProgramDateTime = hasProgramDateTime;
|
||||
this.drmInitData = drmInitData;
|
||||
this.initializationSegment = initializationSegment;
|
||||
this.segments = Collections.unmodifiableList(segments);
|
||||
if (!segments.isEmpty()) {
|
||||
Segment last = segments.get(segments.size() - 1);
|
||||
@ -296,9 +297,22 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
|
||||
* @return The playlist.
|
||||
*/
|
||||
public HlsMediaPlaylist copyWith(long startTimeUs, int discontinuitySequence) {
|
||||
return new HlsMediaPlaylist(playlistType, baseUri, tags, startOffsetUs, startTimeUs, true,
|
||||
discontinuitySequence, mediaSequence, version, targetDurationUs, hasIndependentSegmentsTag,
|
||||
hasEndTag, hasProgramDateTime, drmInitData, initializationSegment, segments);
|
||||
return new HlsMediaPlaylist(
|
||||
playlistType,
|
||||
baseUri,
|
||||
tags,
|
||||
startOffsetUs,
|
||||
startTimeUs,
|
||||
/* hasDiscontinuitySequence= */ true,
|
||||
discontinuitySequence,
|
||||
mediaSequence,
|
||||
version,
|
||||
targetDurationUs,
|
||||
hasIndependentSegmentsTag,
|
||||
hasEndTag,
|
||||
hasProgramDateTime,
|
||||
drmInitData,
|
||||
segments);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -311,9 +325,21 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
|
||||
if (this.hasEndTag) {
|
||||
return this;
|
||||
}
|
||||
return new HlsMediaPlaylist(playlistType, baseUri, tags, startOffsetUs, startTimeUs,
|
||||
hasDiscontinuitySequence, discontinuitySequence, mediaSequence, version, targetDurationUs,
|
||||
hasIndependentSegmentsTag, true, hasProgramDateTime, drmInitData, initializationSegment,
|
||||
return new HlsMediaPlaylist(
|
||||
playlistType,
|
||||
baseUri,
|
||||
tags,
|
||||
startOffsetUs,
|
||||
startTimeUs,
|
||||
hasDiscontinuitySequence,
|
||||
discontinuitySequence,
|
||||
mediaSequence,
|
||||
version,
|
||||
targetDurationUs,
|
||||
hasIndependentSegmentsTag,
|
||||
/* hasEndTag= */ true,
|
||||
hasProgramDateTime,
|
||||
drmInitData,
|
||||
segments);
|
||||
}
|
||||
|
||||
|
@ -474,6 +474,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||
segments.add(
|
||||
new Segment(
|
||||
line,
|
||||
initializationSegment,
|
||||
segmentDurationUs,
|
||||
relativeDiscontinuitySequence,
|
||||
segmentStartTimeUs,
|
||||
@ -491,10 +492,22 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||
hasGapTag = false;
|
||||
}
|
||||
}
|
||||
return new HlsMediaPlaylist(playlistType, baseUri, tags, startOffsetUs, playlistStartTimeUs,
|
||||
hasDiscontinuitySequence, playlistDiscontinuitySequence, mediaSequence, version,
|
||||
targetDurationUs, hasIndependentSegmentsTag, hasEndTag, playlistStartTimeUs != 0,
|
||||
drmInitData, initializationSegment, segments);
|
||||
return new HlsMediaPlaylist(
|
||||
playlistType,
|
||||
baseUri,
|
||||
tags,
|
||||
startOffsetUs,
|
||||
playlistStartTimeUs,
|
||||
hasDiscontinuitySequence,
|
||||
playlistDiscontinuitySequence,
|
||||
mediaSequence,
|
||||
version,
|
||||
targetDurationUs,
|
||||
hasIndependentSegmentsTag,
|
||||
hasEndTag,
|
||||
/* hasProgramDateTime= */ playlistStartTimeUs != 0,
|
||||
drmInitData,
|
||||
segments);
|
||||
}
|
||||
|
||||
private static SchemeData parseWidevineSchemeData(String line, String keyFormat)
|
||||
|
@ -247,4 +247,35 @@ public class HlsMediaPlaylistParserTest {
|
||||
assertThat(playlist.segments.get(2).hasGapTag).isTrue();
|
||||
assertThat(playlist.segments.get(3).hasGapTag).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMapTag() throws IOException {
|
||||
Uri playlistUri = Uri.parse("https://example.com/test3.m3u8");
|
||||
String playlistString =
|
||||
"#EXTM3U\n"
|
||||
+ "#EXT-X-VERSION:3\n"
|
||||
+ "#EXT-X-TARGETDURATION:5\n"
|
||||
+ "#EXT-X-MEDIA-SEQUENCE:10\n"
|
||||
+ "#EXTINF:5.005,\n"
|
||||
+ "02/00/27.ts\n"
|
||||
+ "#EXT-X-MAP:URI=\"init1.ts\""
|
||||
+ "#EXTINF:5.005,\n"
|
||||
+ "02/00/32.ts\n"
|
||||
+ "#EXTINF:5.005,\n"
|
||||
+ "02/00/42.ts\n"
|
||||
+ "#EXT-X-MAP:URI=\"init2.ts\""
|
||||
+ "#EXTINF:5.005,\n"
|
||||
+ "02/00/47.ts\n";
|
||||
InputStream inputStream =
|
||||
new ByteArrayInputStream(playlistString.getBytes(Charset.forName(C.UTF8_NAME)));
|
||||
HlsMediaPlaylist playlist =
|
||||
(HlsMediaPlaylist) new HlsPlaylistParser().parse(playlistUri, inputStream);
|
||||
|
||||
List<Segment> segments = playlist.segments;
|
||||
assertThat(segments.get(0).initializationSegment).isNull();
|
||||
assertThat(segments.get(1).initializationSegment)
|
||||
.isSameAs(segments.get(2).initializationSegment);
|
||||
assertThat(segments.get(1).initializationSegment.url).isEqualTo("init1.ts");
|
||||
assertThat(segments.get(3).initializationSegment.url).isEqualTo("init2.ts");
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user