From c6cee8a64ca91c6d03a1b583a185e28e13880925 Mon Sep 17 00:00:00 2001 From: Theodore Abshire Date: Wed, 12 Oct 2022 10:36:35 -0700 Subject: [PATCH] fix(hls): Fix single-variant HLS streams The changes to implement lazy-loading broke the previous functionality to load media playlists directly, as they are not lazy loaded. This fixes that case, so that lazy-loaded media playlists will correctly set their duration and presentation type. Issue #1936 Issue #3536 --- lib/hls/hls_parser.js | 27 +++++++++++++++++++++------ test/hls/hls_parser_unit.js | 4 +++- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/lib/hls/hls_parser.js b/lib/hls/hls_parser.js index 0f5334d56d..7af81724ec 100644 --- a/lib/hls/hls_parser.js +++ b/lib/hls/hls_parser.js @@ -710,6 +710,19 @@ shaka.hls.HlsParser = class { /* presentationStartTime= */ null, /* delay= */ 0); this.presentationTimeline_.setStatic(true); + // Single-variant streams aren't lazy-loaded, so for them we already have + // enough info here to determine the presentation type and duration. + if (playlist.type == shaka.hls.PlaylistType.MEDIA) { + if (this.isLive_()) { + this.changePresentationTimelineToLive_(); + const delay = this.updatePlaylistDelay_; + this.updatePlaylistTimer_.tickAfter(/* seconds= */ delay); + } + const streamInfos = Array.from(this.uriToStreamInfosMap_.values()); + this.finalizeStreams_(streamInfos); + this.determineDuration_(); + } + this.manifest_ = { presentationTimeline: this.presentationTimeline_, variants, @@ -1604,11 +1617,6 @@ shaka.hls.HlsParser = class { stream.roles = realStream.roles; stream.mimeType = realStream.mimeType; - // MediaSource expects no codec strings combined with raw formats. - if (shaka.media.MediaSourceEngine.RAW_FORMATS.includes(stream.mimeType)) { - stream.codecs = ''; - } - // Add finishing touches to the stream that can only be done once we have // more full context on the media as a whole. if (this.hasEnoughInfoToFinalizeStreams_()) { @@ -1692,6 +1700,13 @@ shaka.hls.HlsParser = class { streamInfo.stream.segmentIndex.fit(/* periodStart= */ 0, minDuration); } } + // MediaSource expects no codec strings combined with raw formats. + for (const streamInfo of streamInfos) { + const stream = streamInfo.stream; + if (shaka.media.MediaSourceEngine.RAW_FORMATS.includes(stream.mimeType)) { + stream.codecs = ''; + } + } this.notifySegmentsForStreams_(streamInfos.map((s) => s.stream)); if (this.config_.hls.ignoreManifestProgramDateTime) { this.syncStreamsWithSequenceNumber_(streamInfos); @@ -1872,7 +1887,7 @@ shaka.hls.HlsParser = class { return { stream, - type: '', // Not set here + type, verbatimMediaPlaylistUri, absoluteMediaPlaylistUri, maxTimestamp: lastEndTime, diff --git a/test/hls/hls_parser_unit.js b/test/hls/hls_parser_unit.js index 0418dab067..b35d7d453d 100644 --- a/test/hls/hls_parser_unit.js +++ b/test/hls/hls_parser_unit.js @@ -3841,7 +3841,9 @@ describe('HlsParser', () => { }); }); - await testHlsParser(media, '', manifest); + const actualManifest = await testHlsParser(media, '', manifest); + + expect(actualManifest.presentationTimeline.getDuration()).toBe(5); }); it('honors hls.mediaPlaylistFullMimeType', async () => {