mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
HLS: Fix incorrect handling of byte ranges for EXT-X-MAP tags
Issue: #8783 #minor-release PiperOrigin-RevId: 366265419
This commit is contained in:
parent
106294158a
commit
4fd8e791f6
3 changed files with 56 additions and 2 deletions
|
|
@ -39,6 +39,8 @@
|
||||||
codec input size
|
codec input size
|
||||||
([#8705](https://github.com/google/ExoPlayer/issues/8705)).
|
([#8705](https://github.com/google/ExoPlayer/issues/8705)).
|
||||||
* HLS:
|
* HLS:
|
||||||
|
* Fix incorrect application of byte ranges to `EXT-X-MAP` tags
|
||||||
|
([#8783](https://github.com/google/ExoPlayer/issues/8783)).
|
||||||
* Fix issue that could cause playback to become stuck if corresponding
|
* Fix issue that could cause playback to become stuck if corresponding
|
||||||
`EXT-X-DISCONTINUITY` tags in different media playlists occur at
|
`EXT-X-DISCONTINUITY` tags in different media playlists occur at
|
||||||
different positions in time
|
different positions in time
|
||||||
|
|
|
||||||
|
|
@ -702,6 +702,10 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||||
segmentByteRangeOffset = Long.parseLong(splitByteRange[1]);
|
segmentByteRangeOffset = Long.parseLong(splitByteRange[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (segmentByteRangeLength == C.LENGTH_UNSET) {
|
||||||
|
// The segment has no byte range defined.
|
||||||
|
segmentByteRangeOffset = 0;
|
||||||
|
}
|
||||||
if (fullSegmentEncryptionKeyUri != null && fullSegmentEncryptionIV == null) {
|
if (fullSegmentEncryptionKeyUri != null && fullSegmentEncryptionIV == null) {
|
||||||
// See RFC 8216, Section 4.3.2.5.
|
// See RFC 8216, Section 4.3.2.5.
|
||||||
throw new ParserException(
|
throw new ParserException(
|
||||||
|
|
@ -715,7 +719,9 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||||
segmentByteRangeLength,
|
segmentByteRangeLength,
|
||||||
fullSegmentEncryptionKeyUri,
|
fullSegmentEncryptionKeyUri,
|
||||||
fullSegmentEncryptionIV);
|
fullSegmentEncryptionIV);
|
||||||
segmentByteRangeOffset = 0;
|
if (segmentByteRangeLength != C.LENGTH_UNSET) {
|
||||||
|
segmentByteRangeOffset += segmentByteRangeLength;
|
||||||
|
}
|
||||||
segmentByteRangeLength = C.LENGTH_UNSET;
|
segmentByteRangeLength = C.LENGTH_UNSET;
|
||||||
} else if (line.startsWith(TAG_TARGET_DURATION)) {
|
} else if (line.startsWith(TAG_TARGET_DURATION)) {
|
||||||
targetDurationUs = parseIntAttr(line, REGEX_TARGET_DURATION) * C.MICROS_PER_SECOND;
|
targetDurationUs = parseIntAttr(line, REGEX_TARGET_DURATION) * C.MICROS_PER_SECOND;
|
||||||
|
|
@ -948,7 +954,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||||
String segmentUri = replaceVariableReferences(line, variableDefinitions);
|
String segmentUri = replaceVariableReferences(line, variableDefinitions);
|
||||||
@Nullable Segment inferredInitSegment = urlToInferredInitSegment.get(segmentUri);
|
@Nullable Segment inferredInitSegment = urlToInferredInitSegment.get(segmentUri);
|
||||||
if (segmentByteRangeLength == C.LENGTH_UNSET) {
|
if (segmentByteRangeLength == C.LENGTH_UNSET) {
|
||||||
// The segment is not byte range defined.
|
// The segment has no byte range defined.
|
||||||
segmentByteRangeOffset = 0;
|
segmentByteRangeOffset = 0;
|
||||||
} else if (isIFrameOnly && initializationSegment == null && inferredInitSegment == null) {
|
} else if (isIFrameOnly && initializationSegment == null && inferredInitSegment == null) {
|
||||||
// The segment is a resource byte range without an initialization segment.
|
// The segment is a resource byte range without an initialization segment.
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,52 @@ public class HlsMediaPlaylistParserTest {
|
||||||
assertThat(segment.url).isEqualTo("https://priv.example.com/fileSequence2683.ts");
|
assertThat(segment.url).isEqualTo("https://priv.example.com/fileSequence2683.ts");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseMediaPlaylist_withByteRanges() throws Exception {
|
||||||
|
Uri playlistUri = Uri.parse("https://example.com/test.m3u8");
|
||||||
|
String playlistString =
|
||||||
|
"#EXTM3U\n"
|
||||||
|
+ "#EXT-X-VERSION:3\n"
|
||||||
|
+ "#EXT-X-TARGETDURATION:5\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "#EXT-X-BYTERANGE:200@100\n"
|
||||||
|
+ "#EXT-X-MAP:URI=\"stream.mp4\"\n"
|
||||||
|
+ "#EXTINF:5,\n"
|
||||||
|
+ "#EXT-X-BYTERANGE:400\n"
|
||||||
|
+ "stream.mp4\n"
|
||||||
|
+ "#EXTINF:5,\n"
|
||||||
|
+ "#EXT-X-BYTERANGE:500\n"
|
||||||
|
+ "stream.mp4\n"
|
||||||
|
+ "#EXT-X-DISCONTINUITY\n"
|
||||||
|
+ "#EXT-X-MAP:URI=\"init.mp4\"\n"
|
||||||
|
+ "#EXTINF:5,\n"
|
||||||
|
+ "segment.mp4\n";
|
||||||
|
InputStream inputStream = new ByteArrayInputStream(Util.getUtf8Bytes(playlistString));
|
||||||
|
HlsPlaylist playlist = new HlsPlaylistParser().parse(playlistUri, inputStream);
|
||||||
|
|
||||||
|
HlsMediaPlaylist mediaPlaylist = (HlsMediaPlaylist) playlist;
|
||||||
|
List<Segment> segments = mediaPlaylist.segments;
|
||||||
|
|
||||||
|
assertThat(segments).isNotNull();
|
||||||
|
assertThat(segments).hasSize(3);
|
||||||
|
|
||||||
|
Segment segment = segments.get(0);
|
||||||
|
assertThat(segment.initializationSegment.byteRangeOffset).isEqualTo(100);
|
||||||
|
assertThat(segment.initializationSegment.byteRangeLength).isEqualTo(200);
|
||||||
|
assertThat(segment.byteRangeOffset).isEqualTo(300);
|
||||||
|
assertThat(segment.byteRangeLength).isEqualTo(400);
|
||||||
|
|
||||||
|
segment = segments.get(1);
|
||||||
|
assertThat(segment.byteRangeOffset).isEqualTo(700);
|
||||||
|
assertThat(segment.byteRangeLength).isEqualTo(500);
|
||||||
|
|
||||||
|
segment = segments.get(2);
|
||||||
|
assertThat(segment.initializationSegment.byteRangeOffset).isEqualTo(0);
|
||||||
|
assertThat(segment.initializationSegment.byteRangeLength).isEqualTo(C.LENGTH_UNSET);
|
||||||
|
assertThat(segment.byteRangeOffset).isEqualTo(0);
|
||||||
|
assertThat(segment.byteRangeLength).isEqualTo(C.LENGTH_UNSET);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseSampleAesMethod() throws Exception {
|
public void parseSampleAesMethod() throws Exception {
|
||||||
Uri playlistUri = Uri.parse("https://example.com/test.m3u8");
|
Uri playlistUri = Uri.parse("https://example.com/test.m3u8");
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue