From e078fdef6524f733c0a39f435eeca80d22bd221a Mon Sep 17 00:00:00 2001 From: dsilhavy Date: Wed, 15 Jul 2020 15:04:09 +0200 Subject: [PATCH 1/2] Move the logic whether to postpone the update of representations to the playback controller. This allows us to consider the current playback position for multiperiod streams. --- .../controllers/RepresentationController.js | 13 +++++----- .../controllers/PlaybackController.js | 25 +++++++++++++++++-- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/dash/controllers/RepresentationController.js b/src/dash/controllers/RepresentationController.js index 4b365f1a8a..75dbad5305 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 = playbackController.getRepresentationUpdatePostponeTimePeriod(r, streamInfo); } if (postponeTimePeriod > 0) { diff --git a/src/streaming/controllers/PlaybackController.js b/src/streaming/controllers/PlaybackController.js index c24f7e04ff..642a94c3e7 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() { @@ -670,6 +670,26 @@ function PlaybackController() { } } + function getRepresentationUpdatePostponeTimePeriod(representation, streamInfo) { + try { + const streamController = 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(getTime(), startTimeAnchor); + } + + let segmentAvailabilityTimePeriod = representation.segmentAvailabilityRange.end - startTimeAnchor; + let liveDelay = getLiveDelay(); + + return (liveDelay - segmentAvailabilityTimePeriod) * 1000; + } catch (e) { + return 0; + } + } + function onFragmentLoadProgress(e) { // If using fetch and stream mode is not available, readjust live latency so it is 20% higher than segment duration if (e.stream === false && settings.get().streaming.lowLatencyEnabled && !isNaN(e.request.duration)) { @@ -803,7 +823,8 @@ function PlaybackController() { pause: pause, isSeeking: isSeeking, seek: seek, - reset: reset + reset: reset, + getRepresentationUpdatePostponeTimePeriod }; setup(); From 51f691205c8ce20840f50b3c78d031bb393517be Mon Sep 17 00:00:00 2001 From: dsilhavy Date: Wed, 15 Jul 2020 15:09:47 +0200 Subject: [PATCH 2/2] Keep logic for representation updates in RepresentationController but use playback controller and schedule controller to determine current period --- .../controllers/RepresentationController.js | 22 +++++++++++++++++- .../controllers/PlaybackController.js | 23 +------------------ 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/dash/controllers/RepresentationController.js b/src/dash/controllers/RepresentationController.js index 75dbad5305..073d9a6686 100644 --- a/src/dash/controllers/RepresentationController.js +++ b/src/dash/controllers/RepresentationController.js @@ -241,7 +241,7 @@ function RepresentationController(config) { if (r.adaptation.period.mpd.manifest.type === dashConstants.DYNAMIC && !r.adaptation.period.mpd.manifest.ignorePostponeTimePeriod) { // We must put things to sleep unless till e.g. the startTime calculation in ScheduleController.onLiveEdgeSearchCompleted fall after the segmentAvailabilityRange.start - postponeTimePeriod = playbackController.getRepresentationUpdatePostponeTimePeriod(r, streamInfo); + postponeTimePeriod = getRepresentationUpdatePostponeTimePeriod(r, streamInfo); } if (postponeTimePeriod > 0) { @@ -278,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 642a94c3e7..221b31dc4f 100644 --- a/src/streaming/controllers/PlaybackController.js +++ b/src/streaming/controllers/PlaybackController.js @@ -670,26 +670,6 @@ function PlaybackController() { } } - function getRepresentationUpdatePostponeTimePeriod(representation, streamInfo) { - try { - const streamController = 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(getTime(), startTimeAnchor); - } - - let segmentAvailabilityTimePeriod = representation.segmentAvailabilityRange.end - startTimeAnchor; - let liveDelay = getLiveDelay(); - - return (liveDelay - segmentAvailabilityTimePeriod) * 1000; - } catch (e) { - return 0; - } - } - function onFragmentLoadProgress(e) { // If using fetch and stream mode is not available, readjust live latency so it is 20% higher than segment duration if (e.stream === false && settings.get().streaming.lowLatencyEnabled && !isNaN(e.request.duration)) { @@ -823,8 +803,7 @@ function PlaybackController() { pause: pause, isSeeking: isSeeking, seek: seek, - reset: reset, - getRepresentationUpdatePostponeTimePeriod + reset: reset }; setup();