diff --git a/src/dash/controllers/RepresentationController.js b/src/dash/controllers/RepresentationController.js index 4b365f1a8a..073d9a6686 100644 --- a/src/dash/controllers/RepresentationController.js +++ b/src/dash/controllers/RepresentationController.js @@ -177,7 +177,10 @@ function RepresentationController(config) { for (let i = 0, ln = voAvailableRepresentations.length; i < ln; i++) { updateRepresentation(voAvailableRepresentations[i], isDynamic); if (notifyUpdate) { - eventBus.trigger(events.REPRESENTATION_UPDATE_STARTED, { sender: instance, representation: voAvailableRepresentations[i]}); + eventBus.trigger(events.REPRESENTATION_UPDATE_STARTED, { + sender: instance, + representation: voAvailableRepresentations[i] + }); } } } @@ -190,7 +193,7 @@ function RepresentationController(config) { function startDataUpdate() { updating = true; - eventBus.trigger(events.DATA_UPDATE_STARTED, { sender: instance }); + eventBus.trigger(events.DATA_UPDATE_STARTED, {sender: instance}); } function endDataUpdate(error) { @@ -215,7 +218,7 @@ function RepresentationController(config) { updateAvailabilityWindow(playbackController.getIsDynamic(), true); }; - eventBus.trigger(events.AST_IN_FUTURE, { delay: delay }); + eventBus.trigger(events.AST_IN_FUTURE, {delay: delay}); setTimeout(update, delay); } @@ -237,10 +240,8 @@ function RepresentationController(config) { repSwitch; if (r.adaptation.period.mpd.manifest.type === dashConstants.DYNAMIC && !r.adaptation.period.mpd.manifest.ignorePostponeTimePeriod) { - let segmentAvailabilityTimePeriod = r.segmentAvailabilityRange.end - r.segmentAvailabilityRange.start; // We must put things to sleep unless till e.g. the startTime calculation in ScheduleController.onLiveEdgeSearchCompleted fall after the segmentAvailabilityRange.start - let liveDelay = playbackController.getLiveDelay(); - postponeTimePeriod = (liveDelay - segmentAvailabilityTimePeriod) * 1000; + postponeTimePeriod = getRepresentationUpdatePostponeTimePeriod(r, streamInfo); } if (postponeTimePeriod > 0) { @@ -277,6 +278,26 @@ function RepresentationController(config) { } } + function getRepresentationUpdatePostponeTimePeriod(representation, streamInfo) { + try { + const streamController = playbackController.getStreamController(); + const activeStreamInfo = streamController.getActiveStreamInfo(); + let startTimeAnchor = representation.segmentAvailabilityRange.start; + + if (activeStreamInfo && activeStreamInfo.id && activeStreamInfo.id !== streamInfo.id) { + // We need to consider the currently playing period if a period switch is performed. + startTimeAnchor = Math.min(playbackController.getTime(), startTimeAnchor); + } + + let segmentAvailabilityTimePeriod = representation.segmentAvailabilityRange.end - startTimeAnchor; + let liveDelay = playbackController.getLiveDelay(); + + return (liveDelay - segmentAvailabilityTimePeriod) * 1000; + } catch (e) { + return 0; + } + } + function onWallclockTimeUpdated(e) { if (e.isDynamic) { updateAvailabilityWindow(e.isDynamic); diff --git a/src/streaming/controllers/PlaybackController.js b/src/streaming/controllers/PlaybackController.js index c24f7e04ff..221b31dc4f 100644 --- a/src/streaming/controllers/PlaybackController.js +++ b/src/streaming/controllers/PlaybackController.js @@ -623,7 +623,7 @@ function PlaybackController() { const liveCatchupLatencyThreshold = mediaPlayerModel.getLiveCatchupLatencyThreshold(); return settings.get().streaming.lowLatencyEnabled && settings.get().streaming.liveCatchUpPlaybackRate > 0 && getTime() > 0 && - latencyDrift > settings.get().streaming.liveCatchUpMinDrift && (isNaN(liveCatchupLatencyThreshold) || currentLiveLatency <= liveCatchupLatencyThreshold ) ; + latencyDrift > settings.get().streaming.liveCatchUpMinDrift && (isNaN(liveCatchupLatencyThreshold) || currentLiveLatency <= liveCatchupLatencyThreshold); } function startPlaybackCatchUp() {