diff --git a/api-extractor/report/hls.js.api.md b/api-extractor/report/hls.js.api.md index c02b5fe0eb2..c93b5f7a6d7 100644 --- a/api-extractor/report/hls.js.api.md +++ b/api-extractor/report/hls.js.api.md @@ -404,6 +404,8 @@ export class BaseStreamController extends TaskLoop implements NetworkComponentAP // (undocumented) protected onvseeking: EventListener | null; // (undocumented) + protected recoverWorkerError(data: ErrorData): void; + // (undocumented) protected reduceMaxBufferLength(threshold?: number): boolean; // (undocumented) protected resetFragmentErrors(filterType: PlaylistLevelType): void; diff --git a/src/controller/audio-stream-controller.ts b/src/controller/audio-stream-controller.ts index 14f3ba60e08..2e13cf43ec2 100644 --- a/src/controller/audio-stream-controller.ts +++ b/src/controller/audio-stream-controller.ts @@ -693,6 +693,9 @@ class AudioStreamController this.resetLoadingState(); } break; + case ErrorDetails.INTERNAL_EXCEPTION: + this.recoverWorkerError(data); + break; default: break; } diff --git a/src/controller/base-stream-controller.ts b/src/controller/base-stream-controller.ts index 59de94bdb28..17254386d75 100644 --- a/src/controller/base-stream-controller.ts +++ b/src/controller/base-stream-controller.ts @@ -1551,6 +1551,13 @@ export default class BaseStreamController } } + protected recoverWorkerError(data: ErrorData) { + if (data.event === 'demuxerWorker') { + this.resetTransmuxer(); + this.resetLoadingState(); + } + } + set state(nextState) { const previousState = this._state; if (previousState !== nextState) { diff --git a/src/controller/stream-controller.ts b/src/controller/stream-controller.ts index f427cf317d3..6dc0c754aff 100644 --- a/src/controller/stream-controller.ts +++ b/src/controller/stream-controller.ts @@ -904,6 +904,9 @@ export default class StreamController this.resetLoadingState(); } break; + case ErrorDetails.INTERNAL_EXCEPTION: + this.recoverWorkerError(data); + break; default: break; } diff --git a/src/demux/transmuxer-interface.ts b/src/demux/transmuxer-interface.ts index 1f321103684..5d05ef5211f 100644 --- a/src/demux/transmuxer-interface.ts +++ b/src/demux/transmuxer-interface.ts @@ -82,8 +82,7 @@ export default class TransmuxerInterface { const error = new Error( `${event.message} (${event.filename}:${event.lineno})` ); - this.useWorker = false; - this.error = null; + config.enableWorker = false; logger.warn('Exception in webworker, fallback to inline'); this.hls.trigger(Events.ERROR, { type: ErrorTypes.OTHER_ERROR, @@ -105,10 +104,7 @@ export default class TransmuxerInterface { logger.error( 'Error while initializing DemuxerWorker, fallback to inline' ); - if (worker) { - // revoke the Object URL that was used to create transmuxer worker, so as not to leak it - self.URL.revokeObjectURL(worker.objectURL); - } + this.resetWorker(); this.error = null; this.transmuxer = new Transmuxer( this.observer, @@ -117,7 +113,6 @@ export default class TransmuxerInterface { vendor, id ); - this.worker = null; } } else { this.transmuxer = new Transmuxer( @@ -130,12 +125,24 @@ export default class TransmuxerInterface { } } + resetWorker(): void { + const worker = this.worker; + if (worker) { + if (worker?.objectURL) { + // revoke the Object URL that was used to create transmuxer worker, so as not to leak it + self.URL.revokeObjectURL(worker.objectURL); + } + worker.removeEventListener('message', this.onwmsg); + worker.onerror = null; + worker.terminate(); + this.worker = null; + } + } + destroy(): void { const w = this.worker; if (w) { - w.removeEventListener('message', this.onwmsg); - w.terminate(); - this.worker = null; + this.resetWorker(); this.onwmsg = undefined; } else { const transmuxer = this.transmuxer;