Skip to content

Commit

Permalink
Force auto level on emergency switch down and update estimates on fra…
Browse files Browse the repository at this point in the history
…g load timeout

Resolves #6079
  • Loading branch information
robwalch committed Jan 8, 2024
1 parent 0b0c98a commit a5f64fc
Showing 1 changed file with 40 additions and 7 deletions.
47 changes: 40 additions & 7 deletions src/controller/abr-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ class AbrController implements AbrComponentAPI {
private audioTracksByGroup: AudioTracksByGroup | null = null;
private codecTiers: Record<string, CodecSetTier> | null = null;
private timer: number = -1;
private onCheck: Function = this._abandonRulesCheck.bind(this);
private fragCurrent: Fragment | null = null;
private partCurrent: Part | null = null;
private bitrateTestDelay: number = 0;
Expand Down Expand Up @@ -105,7 +104,7 @@ class AbrController implements AbrComponentAPI {
this.unregisterListeners();
this.clearTimer();
// @ts-ignore
this.hls = this.onCheck = null;
this.hls = this._abandonRulesCheck = null;
this.fragCurrent = this.partCurrent = null;
}

Expand Down Expand Up @@ -146,7 +145,7 @@ class AbrController implements AbrComponentAPI {
this.partCurrent = data.part ?? null;
}
this.clearTimer();
this.timer = self.setInterval(this.onCheck, 100);
this.timer = self.setInterval(this._abandonRulesCheck, 100);
}

protected onLevelSwitching(
Expand All @@ -166,6 +165,36 @@ class AbrController implements AbrComponentAPI {
// Reset last loaded level so that a new selection can be made after calling recoverMediaError
this.lastLoadedFragLevel = -1;
this.firstSelection = -1;
break;
case ErrorDetails.FRAG_LOAD_TIMEOUT: {
const frag = data.frag;
const { fragCurrent, partCurrent: part } = this;
if (
frag &&
fragCurrent &&
frag.sn === fragCurrent.sn &&
frag.level === fragCurrent.level
) {
const now = performance.now();
const stats: LoaderStats = part ? part.stats : frag.stats;
const timeLoading = now - stats.loading.start;
const ttfb = stats.loading.first
? stats.loading.first - stats.loading.start
: -1;
const loadedFirstByte = stats.loaded && ttfb > -1;
if (loadedFirstByte) {
const ttfbEstimate = this.bwEstimator.getEstimateTTFB();
this.bwEstimator.sample(
timeLoading - Math.min(ttfbEstimate, ttfb),
stats.loaded,
);
this.bwEstimator.sampleTTFB(ttfb);
} else {
this.bwEstimator.sampleTTFB(timeLoading);
}
}
break;
}
}
}

Expand Down Expand Up @@ -198,7 +227,7 @@ class AbrController implements AbrComponentAPI {
This method monitors the download rate of the current fragment, and will downswitch if that fragment will not load
quickly enough to prevent underbuffering
*/
private _abandonRulesCheck() {
private _abandonRulesCheck = () => {
const { fragCurrent: frag, partCurrent: part, hls } = this;
const { autoLevelEnabled, media } = hls;
if (!frag || !media) {
Expand Down Expand Up @@ -312,7 +341,7 @@ class AbrController implements AbrComponentAPI {
if (fragLevelNextLoadedDelay > duration * 10) {
return;
}
hls.nextLoadLevel = nextLoadLevel;
hls.nextLoadLevel = hls.nextAutoLevel = nextLoadLevel;
if (loadedFirstByte) {
// If there has been loading progress, sample bandwidth using loading time offset by minimum TTFB time
this.bwEstimator.sample(
Expand Down Expand Up @@ -344,7 +373,7 @@ class AbrController implements AbrComponentAPI {
frag.abortRequests();
}
hls.trigger(Events.FRAG_LOAD_EMERGENCY_ABORTED, { frag, part, stats });
}
};

protected onFragLoaded(
event: Events.FRAG_LOADED,
Expand Down Expand Up @@ -799,7 +828,11 @@ class AbrController implements AbrComponentAPI {
(live && !this.bitrateTestDelay) ||
fetchDuration < maxFetchDuration);
if (canSwitchWithinTolerance) {
if (i !== loadLevel) {
const forcedAutoLevel = this.forcedAutoLevel;
if (
i !== loadLevel &&
(forcedAutoLevel === -1 || forcedAutoLevel !== loadLevel)
) {
if (levelsSkipped.length) {
logger.trace(
`[abr] Skipped level(s) ${levelsSkipped.join(
Expand Down

0 comments on commit a5f64fc

Please sign in to comment.