diff --git a/src/controller/abr-controller.ts b/src/controller/abr-controller.ts index 3fe07074279..90709a27e5d 100644 --- a/src/controller/abr-controller.ts +++ b/src/controller/abr-controller.ts @@ -533,27 +533,20 @@ class AbrController implements AbrComponentAPI { } private getAutoLevelKey(): string { - return `${this.getBwEstimate()}_${this.hls.mainForwardBufferInfo?.len}`; + return `${this.getBwEstimate()}_${this.getStarvationDelay().toFixed(2)}`; } private getNextABRAutoLevel(): number { const { fragCurrent, partCurrent, hls } = this; - const { maxAutoLevel, config, minAutoLevel, media } = hls; + const { maxAutoLevel, config, minAutoLevel } = hls; const currentFragDuration = partCurrent ? partCurrent.duration : fragCurrent ? fragCurrent.duration : 0; - - // playbackRate is the absolute value of the playback rate; if media.playbackRate is 0, we use 1 to load as - // if we're playing back at the normal rate. - const playbackRate = - media && media.playbackRate !== 0 ? Math.abs(media.playbackRate) : 1.0; const avgbw = this.getBwEstimate(); // bufferStarvationDelay is the wall-clock time left until the playback buffer is exhausted. - const bufferInfo = hls.mainForwardBufferInfo; - const bufferStarvationDelay = - (bufferInfo ? bufferInfo.len : 0) / playbackRate; + const bufferStarvationDelay = this.getStarvationDelay(); let bwFactor = config.abrBandWidthFactor; let bwUpFactor = config.abrBandWidthUpFactor; @@ -629,6 +622,20 @@ class AbrController implements AbrComponentAPI { return hls.loadLevel; } + private getStarvationDelay(): number { + const hls = this.hls; + const media = hls.media; + if (!media) { + return Infinity; + } + // playbackRate is the absolute value of the playback rate; if media.playbackRate is 0, we use 1 to load as + // if we're playing back at the normal rate. + const playbackRate = + media && media.playbackRate !== 0 ? Math.abs(media.playbackRate) : 1.0; + const bufferInfo = hls.mainForwardBufferInfo; + return (bufferInfo ? bufferInfo.len : 0) / playbackRate; + } + private getBwEstimate(): number { return this.bwEstimator.canEstimate() ? this.bwEstimator.getEstimate() @@ -737,6 +744,9 @@ class AbrController implements AbrComponentAPI { mediaCapabilities, ); levelInfo.supportedPromise.then((decodingInfo) => { + if (!this.hls) { + return; + } levelInfo.supportedResult = decodingInfo; const levels = this.hls.levels; const index = levels.indexOf(levelInfo); diff --git a/src/controller/stream-controller.ts b/src/controller/stream-controller.ts index b8d4d60be86..b1a2a1fadce 100644 --- a/src/controller/stream-controller.ts +++ b/src/controller/stream-controller.ts @@ -221,14 +221,13 @@ export default class StreamController private doTickIdle() { const { hls, levelLastLoaded, levels, media } = this; - const { config, nextLoadLevel: level } = hls; // if start level not parsed yet OR // if video not attached AND start fragment already requested OR start frag prefetch not enabled // exit loop, as we either need more info (level not parsed) or we need media to be attached to load new fragment if ( levelLastLoaded === null || - (!media && (this.startFragRequested || !config.startFragPrefetch)) + (!media && (this.startFragRequested || !hls.config.startFragPrefetch)) ) { return; } @@ -238,6 +237,7 @@ export default class StreamController return; } + const level = hls.nextLoadLevel; if (!levels?.[level]) { return; }