From 1df4bff2998d1103b22543abb697637526e218fd Mon Sep 17 00:00:00 2001 From: Joey Parrish Date: Wed, 2 Nov 2022 17:55:47 -0700 Subject: [PATCH 1/3] fix: Fix HLS lazy-loading exception during update If a stream switch occurs during a playlist update, that update may need to be cancelled. This handles this edge case to prevent an exception trying to access stream.segmentIndex. Closes #4647 --- lib/hls/hls_parser.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/hls/hls_parser.js b/lib/hls/hls_parser.js index f2e8166681..83fe98fd6a 100644 --- a/lib/hls/hls_parser.js +++ b/lib/hls/hls_parser.js @@ -347,6 +347,10 @@ shaka.hls.HlsParser = class { uriObj.setQueryData(new goog.Uri.QueryData('_HLS_skip=YES')); } const response = await this.requestManifest_(uriObj.toString()); + if (!streamInfo.stream.segmentIndex) { + // The stream was closed since the update was first requested. + return; + } /** @type {shaka.hls.Playlist} */ const playlist = this.manifestTextParser_.parsePlaylist( From bdaa88a1da6b8b42262e7c31f820184bb69c83eb Mon Sep 17 00:00:00 2001 From: Joey Parrish Date: Thu, 3 Nov 2022 19:02:51 -0700 Subject: [PATCH 2/3] New test case --- test/hls/hls_live_unit.js | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/test/hls/hls_live_unit.js b/test/hls/hls_live_unit.js index 18ab0919ed..319b3bb3ad 100644 --- a/test/hls/hls_live_unit.js +++ b/test/hls/hls_live_unit.js @@ -736,6 +736,54 @@ describe('HlsParser live', () => { manifest.variants[1].video, [ref4]); }); + it('handles switching during update', async () => { + const ref1 = makeReference( + 'test:/main.mp4', 0, 2, /* syncTime= */ null); + const ref2 = makeReference( + 'test:/main2.mp4', 2, 4, /* syncTime= */ null); + const ref4 = makeReference( + 'test:/main4.mp4', 2, 4, /* syncTime= */ null); + + const secondVariant = [ + '#EXT-X-STREAM-INF:BANDWIDTH=300,CODECS="avc1",', + 'RESOLUTION=1200x940,FRAME-RATE=60\n', + 'video2', + ].join(''); + const masterWithTwoVariants = master + secondVariant; + configureNetEngineForInitialManifest(masterWithTwoVariants, + mediaWithAdditionalSegment, mediaWithAdditionalSegment2); + + const manifest = await parser.start('test:/master', playerInterface); + await manifest.variants[0].video.createSegmentIndex(); + ManifestParser.verifySegmentIndex( + manifest.variants[0].video, [ref1, ref2]); + expect(manifest.variants[1].video.segmentIndex).toBe(null); + + // Update. + fakeNetEngine + .setResponseText('test:/video', mediaWithRemovedSegment) + .setResponseText('test:/video2', mediaWithRemovedSegment2); + + const updatePromise = parser.update(); + + // Verify that the update is not yet complete. + expect(manifest.variants[0].video.segmentIndex).not.toBe(null); + ManifestParser.verifySegmentIndex( + manifest.variants[0].video, [ref1, ref2]); + + // Mid-update, switch. + await manifest.variants[0].video.closeSegmentIndex(); + await manifest.variants[1].video.createSegmentIndex(); + + // Finish the update. + await updatePromise; + + // Check for variants to be as expected. + expect(manifest.variants[0].video.segmentIndex).toBe(null); + ManifestParser.verifySegmentIndex( + manifest.variants[1].video, [ref4]); + }); + it('handles updates with redirects', async () => { const oldRef1 = makeReference( 'test:/main.mp4', 0, 2, /* syncTime= */ null); From 5078c179d94a150e457507b1a6a5a8681d4dbecd Mon Sep 17 00:00:00 2001 From: Joey Parrish Date: Thu, 3 Nov 2022 19:03:00 -0700 Subject: [PATCH 3/3] Additional fix for issue exposed by test case --- lib/hls/hls_parser.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/hls/hls_parser.js b/lib/hls/hls_parser.js index 83fe98fd6a..008ada5af2 100644 --- a/lib/hls/hls_parser.js +++ b/lib/hls/hls_parser.js @@ -1687,6 +1687,10 @@ shaka.hls.HlsParser = class { notifySegmentsForStreams_(streams) { const references = []; for (const stream of streams) { + if (!stream.segmentIndex) { + // The stream was closed since the list of streams was built. + continue; + } stream.segmentIndex.forEachTopLevelReference((reference) => { references.push(reference); });