Skip to content

Commit c46963f

Browse files
authored
fix: Improve boundary gap mitigation at DASH period transitions (#8344)
With resetting MSE on boundary crossing, we might seek into a gap. This would cause MSE not to reset properly, and playback will stall. The following changes are made: - We rely on `seeking` to check if we need to start the boundary timer. The timer assumes we will cross a boundary in a short period of time, and is built to handle edge cases like misalignment & subtle gaps. We first relied on `seeked` but that event might never come when MSE does not reset. Thus seeking into a gap near a boundary end would have never spawned the timer in the first place, leaving the player endlessly stalling. - When crossing a boundary, the MSE resets but never completes (as explained earlier). In this case, the timer will advance the playhead. However, due to the incomplete MSE reset, the video element remains paused. Since the previous state was paused, playback does not resume automatically after crossing the boundary. I now keep a variable that indicates we need to resume playback when MSE reset completes.
1 parent 922dfee commit c46963f

File tree

3 files changed

+21
-5
lines changed

3 files changed

+21
-5
lines changed

lib/media/media_source_engine.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ shaka.media.MediaSourceEngine = class {
145145
/** @private {boolean} */
146146
this.reloadingMediaSource_ = false;
147147

148+
/** @private {boolean} */
149+
this.playAfterReset_ = false;
150+
148151
/** @type {!shaka.util.Destroyer} */
149152
this.destroyer_ = new shaka.util.Destroyer(() => this.doDestroy_());
150153

@@ -2254,7 +2257,9 @@ shaka.media.MediaSourceEngine = class {
22542257
// Playing can also end up in a paused state after a codec switch
22552258
// so we need to remember the current states.
22562259
const previousAutoPlayState = this.video_.autoplay;
2257-
const previousPausedState = this.video_.paused;
2260+
if (!this.video_.paused) {
2261+
this.playAfterReset_ = true;
2262+
}
22582263
if (this.playbackHasBegun_) {
22592264
// Only set autoplay to false if the video playback has already begun.
22602265
// When a codec switch happens before playback has begun this can cause
@@ -2337,7 +2342,8 @@ shaka.media.MediaSourceEngine = class {
23372342
}
23382343

23392344
this.video_.autoplay = previousAutoPlayState;
2340-
if (!previousPausedState) {
2345+
if (this.playAfterReset_) {
2346+
this.playAfterReset_ = false;
23412347
this.video_.play();
23422348
}
23432349
});

lib/media/streaming_engine.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,13 @@ shaka.media.StreamingEngine = class {
917917
}
918918
}
919919

920+
const CrossBoundaryStrategy = shaka.config.CrossBoundaryStrategy;
921+
if (this.config_.crossBoundaryStrategy !== CrossBoundaryStrategy.KEEP) {
922+
// We might have seeked near a boundary, forward time in case MSE does not
923+
// recover due to segment misalignment near the boundary.
924+
this.forwardTimeForCrossBoundary();
925+
}
926+
920927
if (!streamCleared) {
921928
shaka.log.debug(
922929
'(all): seeked: buffered seek: presentationTime=' + presentationTime);
@@ -3045,7 +3052,7 @@ shaka.media.StreamingEngine = class {
30453052
const mediaState = this.mediaStates_.get(ContentType.VIDEO) ||
30463053
this.mediaStates_.get(ContentType.AUDIO);
30473054

3048-
if (!mediaState || mediaState.clearingBuffer) {
3055+
if (!mediaState) {
30493056
return;
30503057
}
30513058

@@ -3131,9 +3138,14 @@ shaka.media.StreamingEngine = class {
31313138
'from=', mediaState.lastInitSegmentReference,
31323139
'to=', reference.initSegmentReference);
31333140

3141+
const video = this.playerInterface_.video;
3142+
const pausedBeforeReset = video.paused;
31343143
this.resetMediaSource(/* force= */ true).then(() => {
31353144
const eventName = shaka.util.FakeEvent.EventName.BoundaryCrossed;
31363145
this.playerInterface_.onEvent(new shaka.util.FakeEvent(eventName));
3146+
if (!pausedBeforeReset) {
3147+
video.play();
3148+
}
31373149
});
31383150
}
31393151
return discard;

lib/player.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2625,8 +2625,6 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
26252625
() => forwardTimeForCrossBoundary(/* immediate= */ true));
26262626
this.loadEventManager_.listen(mediaElement, 'timeupdate',
26272627
() => forwardTimeForCrossBoundary());
2628-
this.loadEventManager_.listen(mediaElement, 'seeked',
2629-
() => forwardTimeForCrossBoundary());
26302628
}
26312629
}
26322630

0 commit comments

Comments
 (0)