From d7e26ec0f065de8866886575cc5d2bbdd0492865 Mon Sep 17 00:00:00 2001 From: Rob Walch Date: Fri, 4 Jun 2021 12:09:34 -0400 Subject: [PATCH] Align live audio and subtitle playlists with main playlist after main is loaded Resync subs when there no fragment can be found to load in live #3987 --- src/controller/audio-stream-controller.ts | 26 ++------- src/controller/subtitle-stream-controller.ts | 55 +++++++++++--------- 2 files changed, 34 insertions(+), 47 deletions(-) diff --git a/src/controller/audio-stream-controller.ts b/src/controller/audio-stream-controller.ts index e675f873f02..6c8b872c9a1 100644 --- a/src/controller/audio-stream-controller.ts +++ b/src/controller/audio-stream-controller.ts @@ -411,24 +411,7 @@ class AudioStreamController } onLevelLoaded(event: Events.LEVEL_LOADED, data: LevelLoadedData) { - if (this.mainDetails === null) { - const mainDetails = (this.mainDetails = data.details); - // compute start position if we haven't already - const trackId = this.levelLastLoaded; - if ( - trackId !== null && - this.levels && - this.startPosition === -1 && - mainDetails.live - ) { - const track = this.levels[trackId]; - if (!track.details || !track.details.fragments[0]) { - return; - } - alignPDT(track.details, mainDetails); - this.setStartPosition(track.details, track.details.fragments[0].start); - } - } + this.mainDetails = data.details; } onAudioTrackLoaded(event: Events.AUDIO_TRACK_LOADED, data: TrackLoadedData) { @@ -445,18 +428,19 @@ class AudioStreamController const track = levels[trackId]; let sliding = 0; if (newDetails.live || track.details?.live) { + const mainDetails = this.mainDetails; if (!newDetails.fragments[0]) { newDetails.deltaUpdateFailed = true; } - if (newDetails.deltaUpdateFailed) { + if (newDetails.deltaUpdateFailed || !mainDetails) { return; } if ( !track.details && newDetails.hasProgramDateTime && - this.mainDetails?.hasProgramDateTime + mainDetails.hasProgramDateTime ) { - alignPDT(newDetails, this.mainDetails); + alignPDT(newDetails, mainDetails); sliding = newDetails.fragments[0].start; } else { sliding = this.alignPlaylists(newDetails, track.details); diff --git a/src/controller/subtitle-stream-controller.ts b/src/controller/subtitle-stream-controller.ts index 18de4f9f5ba..380ead58776 100644 --- a/src/controller/subtitle-stream-controller.ts +++ b/src/controller/subtitle-stream-controller.ts @@ -93,18 +93,7 @@ export class SubtitleStreamController } onLevelLoaded(event: Events.LEVEL_LOADED, data: LevelLoadedData) { - const mainDetails = data.details; - if (this.mainDetails === null) { - const trackId = this.levelLastLoaded; - if (trackId !== null && this.levels && mainDetails.live) { - const track = this.levels[trackId]; - if (!track.details || !track.details.fragments[0]) { - return; - } - alignPDT(track.details, mainDetails); - } - } - this.mainDetails = mainDetails; + this.mainDetails = data.details; } onSubtitleFragProcessed( @@ -255,21 +244,17 @@ export class SubtitleStreamController } this.mediaBuffer = this.mediaBufferTimeRanges; if (newDetails.live || track.details?.live) { - if (newDetails.deltaUpdateFailed) { + const mainDetails = this.mainDetails; + if (newDetails.deltaUpdateFailed || !mainDetails) { return; } - const mainDetails = this.mainDetails; - const mainSlidingStartFragment = mainDetails - ? mainDetails.fragments[0] - : null; + const mainSlidingStartFragment = mainDetails.fragments[0]; if (!track.details) { - if (mainDetails) { - if (newDetails.hasProgramDateTime && mainDetails.hasProgramDateTime) { - alignPDT(newDetails, mainDetails); - } else if (mainSlidingStartFragment) { - // line up live playlist with main so that fragments in range are loaded - addSliding(newDetails, mainSlidingStartFragment.start); - } + if (newDetails.hasProgramDateTime && mainDetails.hasProgramDateTime) { + alignPDT(newDetails, mainDetails); + } else if (mainSlidingStartFragment) { + // line up live playlist with main so that fragments in range are loaded + addSliding(newDetails, mainSlidingStartFragment.start); } } else { const sliding = this.alignPlaylists(newDetails, track.details); @@ -284,6 +269,25 @@ export class SubtitleStreamController // trigger handler right now this.tick(); + + // If playlist is misaligned because of bad PDT or drift, delete details to resync with main on reload + if ( + newDetails.live && + !this.fragCurrent && + this.media && + this.state === State.IDLE + ) { + const foundFrag = findFragmentByPTS( + null, + newDetails.fragments, + this.media.currentTime, + 0 + ); + if (!foundFrag) { + console.warn('Subtitle playlist not aligned with playback'); + track.details = undefined; + } + } } _handleFragmentLoadComplete(fragLoadedData: FragLoadedData) { @@ -364,8 +368,7 @@ export class SubtitleStreamController ); const fragments = trackDetails.fragments; const fragLen = fragments.length; - const end = - fragments[fragLen - 1].start + fragments[fragLen - 1].duration; + const end = trackDetails.edge; let foundFrag; const fragPrevious = this.fragPrevious;