Commit 4fd8e791 by olly Committed by marcbaechinger

HLS: Fix incorrect handling of byte ranges for EXT-X-MAP tags

Issue: #8783
#minor-release
PiperOrigin-RevId: 366265419
parent 10629415
...@@ -39,6 +39,8 @@ ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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.
......
...@@ -155,6 +155,52 @@ public class HlsMediaPlaylistParserTest { ...@@ -155,6 +155,52 @@ public class HlsMediaPlaylistParserTest {
} }
@Test @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
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");
String playlistString = String playlistString =
......
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