Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix: Reset gap-controller nudgeRetry #5879

Merged
merged 1 commit into from
Oct 11, 2023
Merged

Conversation

robwalch
Copy link
Collaborator

@robwalch robwalch commented Oct 4, 2023

This PR will...

Reset gap-controller nudgeRetry count after playhead moves, pauses, or ends while not seeking.

Why is this Pull Request needed?

When nudgeRetry reaches nudgeMaxRetry, the error is escalated to fatal (expected):

private _tryNudgeBuffer() {
const { config, hls, media, nudgeRetry } = this;
if (media === null) {
return;
}
const currentTime = media.currentTime;
this.nudgeRetry++;
if (nudgeRetry < config.nudgeMaxRetry) {
const targetTime = currentTime + (nudgeRetry + 1) * config.nudgeOffset;
// playback stalled in buffered area ... let's nudge currentTime to try to overcome this
const error = new Error(
`Nudging 'currentTime' from ${currentTime} to ${targetTime}`,
);
logger.warn(error.message);
media.currentTime = targetTime;
hls.trigger(Events.ERROR, {
type: ErrorTypes.MEDIA_ERROR,
details: ErrorDetails.BUFFER_NUDGE_ON_STALL,
error,
fatal: false,
});
} else {
const error = new Error(
`Playhead still not moving while enough data buffered @${currentTime} after ${config.nudgeMaxRetry} nudges`,
);
logger.error(error.message);
hls.trigger(Events.ERROR, {
type: ErrorTypes.MEDIA_ERROR,
details: ErrorDetails.BUFFER_STALLED_ERROR,
error,
fatal: true,

nudgeRetry is reset when polling currentTime. The expectation is that this runs after currentTime has advanced naturally. Note that stalled must not be null - the think here is that this is reset when exiting a stall, but this does not work if stalled is reset before reaching this point:

public poll(lastCurrentTime: number, activeFrag: Fragment | null) {
const { config, media, stalled } = this;
if (media === null) {
return;
}
const { currentTime, seeking } = media;
const seeked = this.seeking && !seeking;
const beginSeek = !this.seeking && seeking;
this.seeking = seeking;
// The playhead is moving, no-op
if (currentTime !== lastCurrentTime) {
this.moved = true;
if (stalled !== null) {
// The playhead is now moving, but was previously stalled
if (this.stallReported) {
const stalledDuration = self.performance.now() - stalled;
logger.warn(
`playback not stuck anymore @${currentTime}, after ${Math.round(
stalledDuration,
)}ms`,
);
this.stallReported = false;
}
this.stalled = null;
this.nudgeRetry = 0;

And here we see that stalled is reset to null before nudging, so nudgeRetry will never be reset:

logger.warn('Trying to nudge playhead over buffer-hole');
// Try to nudge currentTime over a buffer hole if we've been stalling for the configured amount of seconds
// We only try to jump the hole if it's under the configured size
// Reset stalled so to rearm watchdog timer
this.stalled = null;
this._tryNudgeBuffer();

Are there any points in the code the reviewer needs to double check?

Resolves issues:

Resolves #5873

Checklist

  • changes have been done against master branch, and PR does not conflict
  • new unit / functional tests have been added (whenever applicable)
  • API or design changes are documented in API.md

@robwalch robwalch added this to the 1.5.0 milestone Oct 4, 2023
@robwalch robwalch merged commit 53a1505 into master Oct 11, 2023
15 of 16 checks passed
@robwalch robwalch deleted the bugfix/nudge-retry-reset branch October 11, 2023 18:38
@robwalch
Copy link
Collaborator Author

Also related to #5904

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Stall detector possibly not resetting after consecutive head nudges
1 participant