From a5c6e62b698caee07c3e76590524fe788117e279 Mon Sep 17 00:00:00 2001 From: Paul Berberian Date: Wed, 20 Mar 2024 17:58:40 +0100 Subject: [PATCH 1/2] Rename and factorize some methods of the MediaSourceContentInitializer Some private methods of the `MediaSourceContentInitializer` were difficult to follow due to the heavy usage of inner functions with unclear names (such as `recursivelyLoadOnMediaSource`). I now tried to isolate some of those and rename the different methods called at content load so it makes more sense. Methods in order are: ``` start > _setupInitialMediaSourceAndDecryption > _onInitialMediaSourceReady > _setupContentWithNewMediaSource > _startLoadingContentOnMediaSource ``` Note: `_setupContentWithNewMediaSource` and `_startLoadingContentOnMediaSource` are still similarly named, though the former just has the task of setting up a reloading logic and then calling the latter. Note2: `_startLoadingContentOnMediaSource` is still a huge and complex method that we might improve on in the future. --- .../init/media_source_content_initializer.ts | 134 +++++++++--------- 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/src/main_thread/init/media_source_content_initializer.ts b/src/main_thread/init/media_source_content_initializer.ts index 5a8d88b30b..562a71c53e 100644 --- a/src/main_thread/init/media_source_content_initializer.ts +++ b/src/main_thread/init/media_source_content_initializer.ts @@ -204,7 +204,7 @@ export default class MediaSourceContentInitializer extends ContentInitializer { this._initCanceller.signal, ); - this._initializeMediaSourceAndDecryption(mediaElement) + this._setupInitialMediaSourceAndDecryption(mediaElement) .then((initResult) => this._onInitialMediaSourceReady( mediaElement, @@ -230,6 +230,10 @@ export default class MediaSourceContentInitializer extends ContentInitializer { this._manifestFetcher.updateContentUrls(urls, refreshNow); } + /** + * Stop content and free all resources linked to this + * `MediaSourceContentInitializer`. + */ public dispose(): void { this._initCanceller.cancel(); } @@ -252,7 +256,7 @@ export default class MediaSourceContentInitializer extends ContentInitializer { * @param {HTMLMediaElement|null} mediaElement * @returns {Promise.} */ - private _initializeMediaSourceAndDecryption(mediaElement: IMediaElement): Promise<{ + private _setupInitialMediaSourceAndDecryption(mediaElement: IMediaElement): Promise<{ mediaSource: MainMediaSourceInterface; drmSystemId: string | undefined; unlinkMediaSource: TaskCanceller; @@ -452,80 +456,76 @@ export default class MediaSourceContentInitializer extends ContentInitializer { return; } - const bufferOnMediaSource = this._startBufferingOnMediaSource.bind(this); - const triggerEvent = this.trigger.bind(this); - const onFatalError = this._onFatalError.bind(this); - // handle initial load and reloads - recursivelyLoadOnMediaSource( - initialMediaSource, - initialTime, - autoPlay, - initialMediaSourceCanceller, - ); - - /** - * Load the content defined by the Manifest in the mediaSource given at the - * given position and playing status. - * This function recursively re-call itself when a MediaSource reload is - * wanted. - * @param {MediaSource} mediaSource - * @param {number} startingPos - * @param {Object} currentCanceller - * @param {boolean} shouldPlay - */ - function recursivelyLoadOnMediaSource( - mediaSource: MainMediaSourceInterface, - startingPos: number, - shouldPlay: boolean, - currentCanceller: TaskCanceller, - ): void { - const opts = { + this._setupContentWithNewMediaSource( + { mediaElement, playbackObserver, - mediaSource, - initialTime: startingPos, - autoPlay: shouldPlay, + mediaSource: initialMediaSource, + initialTime, + autoPlay, manifest, representationEstimator, segmentQueueCreator, speed, bufferOptions: subBufferOptions, - }; - bufferOnMediaSource(opts, onReloadMediaSource, currentCanceller.signal); - - function onReloadMediaSource(reloadOrder: { - position: number; - autoPlay: boolean; - }): void { - currentCanceller.cancel(); - if (initCanceller.isUsed()) { - return; - } - triggerEvent("reloadingMediaSource", reloadOrder); - if (initCanceller.isUsed()) { - return; - } + }, + initialMediaSourceCanceller, + ); + } - const newCanceller = new TaskCanceller(); - newCanceller.linkToSignal(initCanceller.signal); - createMediaSource(mediaElement, newCanceller.signal) - .then((newMediaSource) => { - recursivelyLoadOnMediaSource( - newMediaSource, - reloadOrder.position, - reloadOrder.autoPlay, - newCanceller, - ); - }) - .catch((err) => { - if (newCanceller.isUsed()) { - return; - } - onFatalError(err); - }); + /** + * Load the content defined by the Manifest in the mediaSource given at the + * given position and playing status. + * This function recursively re-call itself when a MediaSource reload is + * wanted. + * @param {Object} args + * @param {Object} currentCanceller + */ + private _setupContentWithNewMediaSource( + args: IBufferingMediaSettings, + currentCanceller: TaskCanceller, + ): void { + const initCanceller = this._initCanceller; + const onReloadMediaSource: IReloadMediaSourceCallback = (reloadOrder: { + position: number; + autoPlay: boolean; + }): void => { + currentCanceller.cancel(); + if (initCanceller.isUsed()) { + return; } - } + this.trigger("reloadingMediaSource", reloadOrder); + if (initCanceller.isUsed()) { + return; + } + + const newCanceller = new TaskCanceller(); + newCanceller.linkToSignal(initCanceller.signal); + createMediaSource(args.mediaElement, newCanceller.signal) + .then((newMediaSource) => { + this._setupContentWithNewMediaSource( + { + ...args, + mediaSource: newMediaSource, + initialTime: reloadOrder.position, + autoPlay: reloadOrder.autoPlay, + }, + newCanceller, + ); + }) + .catch((err) => { + if (newCanceller.isUsed()) { + return; + } + this._onFatalError(err); + }); + }; + this._startLoadingContentOnMediaSource( + args, + onReloadMediaSource, + currentCanceller.signal, + ); } /** @@ -534,7 +534,7 @@ export default class MediaSourceContentInitializer extends ContentInitializer { * @param {function} onReloadOrder * @param {Object} cancelSignal */ - private _startBufferingOnMediaSource( + private _startLoadingContentOnMediaSource( args: IBufferingMediaSettings, onReloadOrder: IReloadMediaSourceCallback, cancelSignal: CancellationSignal, From c64452338823ce8352c956ea2fd145756fe1e3c7 Mon Sep 17 00:00:00 2001 From: Paul Berberian Date: Tue, 22 Oct 2024 15:18:44 +0200 Subject: [PATCH 2/2] init: add _createReloadMediaSourceCallback method --- .../init/media_source_content_initializer.ts | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/main_thread/init/media_source_content_initializer.ts b/src/main_thread/init/media_source_content_initializer.ts index 562a71c53e..81767de45c 100644 --- a/src/main_thread/init/media_source_content_initializer.ts +++ b/src/main_thread/init/media_source_content_initializer.ts @@ -486,11 +486,24 @@ export default class MediaSourceContentInitializer extends ContentInitializer { args: IBufferingMediaSettings, currentCanceller: TaskCanceller, ): void { + this._startLoadingContentOnMediaSource( + args, + this._createReloadMediaSourceCallback(args, currentCanceller), + currentCanceller.signal, + ); + } + + /** + * Create `IReloadMediaSourceCallback` allowing to handle reload orders. + * @param {Object} args + * @param {Object} currentCanceller + */ + private _createReloadMediaSourceCallback( + args: IBufferingMediaSettings, + currentCanceller: TaskCanceller, + ): IReloadMediaSourceCallback { const initCanceller = this._initCanceller; - const onReloadMediaSource: IReloadMediaSourceCallback = (reloadOrder: { - position: number; - autoPlay: boolean; - }): void => { + return (reloadOrder: { position: number; autoPlay: boolean }): void => { currentCanceller.cancel(); if (initCanceller.isUsed()) { return; @@ -521,11 +534,6 @@ export default class MediaSourceContentInitializer extends ContentInitializer { this._onFatalError(err); }); }; - this._startLoadingContentOnMediaSource( - args, - onReloadMediaSource, - currentCanceller.signal, - ); } /**