Skip to content

Commit

Permalink
fix(hls): Fix X-PRELOAD-HINT failure with LL mode off (#4212)
Browse files Browse the repository at this point in the history
When LL mode was off, the HLS parser would throw on X-PRELOAD-HINT
segments.  The logic for requiring EXTINF has been corrected so that
this will not happen.

Closes #4185
  • Loading branch information
joeyparrish committed May 17, 2022
1 parent 12e6d1d commit ae84aac
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 11 deletions.
31 changes: 20 additions & 11 deletions lib/hls/hls_parser.js
Expand Up @@ -1825,7 +1825,7 @@ shaka.hls.HlsParser = class {
* @param {!Map.<string, string>} variables
* @param {string} absoluteMediaPlaylistUri
* @param {string} type
* @return {!shaka.media.SegmentReference}
* @return {shaka.media.SegmentReference}
* @private
*/
createSegmentReference_(
Expand Down Expand Up @@ -1870,9 +1870,23 @@ shaka.hls.HlsParser = class {
status = shaka.media.SegmentReference.Status.MISSING;
}

if (!extinfTag) {
if (hlsSegment.partialSegments.length == 0) {
// EXTINF tag must be available if the segment has no partial segments.
throw new shaka.util.Error(
shaka.util.Error.Severity.CRITICAL,
shaka.util.Error.Category.MANIFEST,
shaka.util.Error.Code.HLS_REQUIRED_TAG_MISSING, 'EXTINF');
} else if (!this.lowLatencyMode_) {
// Without EXTINF and without low-latency mode, partial segments get
// ignored.
return null;
}
}

// Create SegmentReferences for the partial segments.
const partialSegmentRefs = [];
if (this.lowLatencyMode_ && hlsSegment.partialSegments.length) {
if (this.lowLatencyMode_) {
for (let i = 0; i < hlsSegment.partialSegments.length; i++) {
const item = hlsSegment.partialSegments[i];
const pPreviousReference = i == 0 ?
Expand Down Expand Up @@ -1913,14 +1927,6 @@ shaka.hls.HlsParser = class {
/* appendWindowEnd= */ Infinity);
partialSegmentRefs.push(partial);
} // for-loop of hlsSegment.partialSegments
} else {
// EXTINF tag must be available if the segment has no partial segments.
if (!extinfTag) {
throw new shaka.util.Error(
shaka.util.Error.Severity.CRITICAL,
shaka.util.Error.Category.MANIFEST,
shaka.util.Error.Code.HLS_REQUIRED_TAG_MISSING, 'EXTINF');
}
}

// If the segment has EXTINF tag, set the segment's end time, start byte
Expand All @@ -1939,6 +1945,7 @@ shaka.hls.HlsParser = class {
} else {
endTime = partialSegmentRefs[partialSegmentRefs.length - 1].endTime;
}

// If the segment has EXT-X-BYTERANGE tag, set the start byte and end byte
// base on the byterange information. If segment has no EXT-X-BYTERANGE tag
// and has partial segments, set the start byte and end byte base on the
Expand Down Expand Up @@ -2107,7 +2114,9 @@ shaka.hls.HlsParser = class {
playlist.absoluteUri,
type);

references.push(reference);
if (reference) {
references.push(reference);
}
}

// If some segments have sync times, but not all, extrapolate the sync
Expand Down
22 changes: 22 additions & 0 deletions test/hls/hls_live_unit.js
Expand Up @@ -603,6 +603,28 @@ describe('HlsParser live', () => {
ManifestParser.verifySegmentIndex(video, [ref, ref2]);
});

// Test for https://github.com/shaka-project/shaka-player/issues/4185
it('does not fail on preload hints with LL mode off', async () => {
// LL mode must be off for this test!
playerInterface.isLowLatencyMode = () => false;

const mediaWithPartialSegments = [
'#EXTM3U\n',
'#EXT-X-TARGETDURATION:5\n',
'#EXTINF:4,\n',
'main.mp4\n',
'#EXT-X-PART:DURATION=2,URI="partial.mp4",BYTERANGE=210@0\n',
'#EXT-X-PRELOAD-HINT:TYPE=PART,URI="partial.mp4",BYTERANGE-START=210\n',
].join('');

fakeNetEngine
.setResponseText('test:/master', master)
.setResponseText('test:/video', mediaWithPartialSegments);

// If this throws, the test fails. Otherwise, it passes.
await parser.start('test:/master', playerInterface);
});

describe('update', () => {
it('adds new segments when they appear', async () => {
const ref1 = makeReference(
Expand Down

0 comments on commit ae84aac

Please sign in to comment.