diff --git a/api-extractor/report/hls.js.api.md b/api-extractor/report/hls.js.api.md index cd816fb972e..dbcfa740111 100644 --- a/api-extractor/report/hls.js.api.md +++ b/api-extractor/report/hls.js.api.md @@ -477,7 +477,7 @@ export class BaseStreamController extends TaskLoop implements NetworkComponentAP // (undocumented) protected decrypter: Decrypter; // (undocumented) - protected _doFragLoad(frag: Fragment, level: Level, targetBufferTime?: number | null, progressCallback?: FragmentLoadProgressCallback): Promise; + protected _doFragLoad(frag: MediaFragment, level: Level, targetBufferTime?: number | null, progressCallback?: FragmentLoadProgressCallback): Promise; // (undocumented) protected doTick(): void; // (undocumented) diff --git a/src/controller/base-stream-controller.ts b/src/controller/base-stream-controller.ts index 33511340fff..8fa5e75ebec 100644 --- a/src/controller/base-stream-controller.ts +++ b/src/controller/base-stream-controller.ts @@ -927,20 +927,10 @@ export default class BaseStreamController frag: PartsLoadedData | FragLoadedData, ) {} - protected _doFragLoad( - frag: Fragment, - level: Level, - targetBufferTime: number | null = null, - progressCallback?: FragmentLoadProgressCallback, - ): Promise { - this.fragCurrent = frag; - const details = level.details; - if (!this.levels || !details) { - throw new Error( - `frag load aborted, missing level${details ? '' : ' detail'}s`, - ); - } - + private loadKeyFor( + frag: MediaFragment, + details: LevelDetails, + ): Promise | null { let keyLoadingPromise: Promise | null = null; if (frag.encrypted && !frag.decryptdata?.key) { this.log( @@ -957,10 +947,6 @@ export default class BaseStreamController } }); this.hls.trigger(Events.KEY_LOADING, { frag }); - if ((this.fragCurrent as Fragment | null) === null) { - this.log(`context changed in KEY_LOADING`); - return Promise.resolve(null); - } } else if (!frag.encrypted) { keyLoadingPromise = this.keyLoader.loadClear( frag, @@ -968,12 +954,30 @@ export default class BaseStreamController this.startFragRequested, ); if (keyLoadingPromise) { - this.log(`[eme] blocking frag load until media-keys acquired`); + this.log( + `[eme] blocking frag sn: ${frag.sn} load until media-keys acquired`, + ); } } + return keyLoadingPromise; + } + + protected _doFragLoad( + frag: MediaFragment, + level: Level, + targetBufferTime: number | null = null, + progressCallback?: FragmentLoadProgressCallback, + ): Promise { + this.fragCurrent = frag; + const details = level.details; + if (!this.levels || !details) { + throw new Error( + `frag load aborted, missing level${details ? '' : ' detail'}s`, + ); + } const fragPrevious = this.fragPrevious; - if (isMediaFragment(frag) && !mediaFragmentsAreEqual(frag, fragPrevious)) { + if (!mediaFragmentsAreEqual(frag, fragPrevious)) { const shouldLoadParts = this.shouldLoadParts(level.details, frag.end); if (shouldLoadParts !== this.loadingParts) { this.log( @@ -985,7 +989,7 @@ export default class BaseStreamController } } targetBufferTime = Math.max(frag.start, targetBufferTime || 0); - if (this.loadingParts && isMediaFragment(frag)) { + if (this.loadingParts) { const partList = details.partList; if (partList && progressCallback) { if (targetBufferTime > details.fragmentEnd && details.fragmentHint) { @@ -1005,6 +1009,10 @@ export default class BaseStreamController this.loadingParts = false; return Promise.resolve(null); } + const keyLoadingPromise = this.loadKeyFor(frag, details); + if (this.fragContextChanged(frag)) { + return Promise.resolve(null); + } this.log( `Loading ${frag.type} sn: ${frag.sn} part: ${part.index} (${partIndex}/${partList.length - 1}) of ${this.fragInfo(frag, false, part)} cc: ${ frag.cc @@ -1066,7 +1074,7 @@ export default class BaseStreamController } } - if (isMediaFragment(frag) && this.loadingParts) { + if (this.loadingParts) { this.log( `LL-Part loading OFF after next part miss @${targetBufferTime} Check buffer at sn: ${frag.sn} loaded parts: ${details.partList?.filter((p) => p.loaded).map((p) => `[${p.start}-${p.end}]`)}`, ); @@ -1076,6 +1084,13 @@ export default class BaseStreamController return Promise.resolve(null); } + const keyLoadingPromise = this.loadKeyFor(frag, details); + if (this.fragContextChanged(frag)) { + this.log( + `Context changed in KEY_LOADING sn: ${frag.sn} ${frag.relurl} > ${this.fragCurrent?.relurl}`, + ); + return Promise.resolve(null); + } this.log( `Loading ${frag.type} sn: ${frag.sn} of ${this.fragInfo(frag, false)} cc: ${frag.cc} ${ '[' + details.startSN + '-' + details.endSN + ']' @@ -1094,7 +1109,6 @@ export default class BaseStreamController this.config.progressive && frag.type !== PlaylistLevelType.SUBTITLE; const initDataPromise = this.loadInitSegmentIfNeeded(frag); - let result: Promise; if (dataOnProgress && keyLoadingPromise) { result = keyLoadingPromise @@ -2073,7 +2087,7 @@ export default class BaseStreamController } if (this.fragContextChanged(frag)) { this.warn( - `Frag load error must match current frag to retry ${frag.url} > ${this.fragCurrent?.url}`, + `Frag load error must match current frag to retry ${frag.relurl} > ${this.fragCurrent?.relurl}`, ); return; } diff --git a/src/controller/stream-controller.ts b/src/controller/stream-controller.ts index a0338adf022..26895ba7868 100644 --- a/src/controller/stream-controller.ts +++ b/src/controller/stream-controller.ts @@ -1163,7 +1163,7 @@ export default class StreamController return audioCodec; } - private _loadBitrateTestFrag(fragment: Fragment, level: Level) { + private _loadBitrateTestFrag(fragment: MediaFragment, level: Level) { fragment.bitrateTest = true; this._doFragLoad(fragment, level) .then((data) => {