From a9468138aff112a6d5bfa4b1b17c9454c0d706cc Mon Sep 17 00:00:00 2001 From: Rob Walch Date: Thu, 2 Feb 2023 19:10:23 -0800 Subject: [PATCH 1/2] Log error and detach if MediaSource 'sourceopen' is interrupted Resolves #4952 --- src/controller/buffer-controller.ts | 17 +++++++++++++++-- .../controller/buffer-controller-operations.ts | 2 ++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/controller/buffer-controller.ts b/src/controller/buffer-controller.ts index 8223f351504..d317533bd5a 100644 --- a/src/controller/buffer-controller.ts +++ b/src/controller/buffer-controller.ts @@ -159,6 +159,7 @@ export default class BufferController implements ComponentAPI { media.src = self.URL.createObjectURL(ms); // cache the locally generated object url this._objectUrl = media.src; + media.addEventListener('emptied', this._onMediaEmptied); } } @@ -188,6 +189,7 @@ export default class BufferController implements ComponentAPI { // Detach properly the MediaSource from the HTMLMediaElement as // suggested in https://github.com/w3c/media-source/issues/53. if (media) { + media.removeEventListener('emptied', this._onMediaEmptied); if (_objectUrl) { self.URL.revokeObjectURL(_objectUrl); } @@ -785,11 +787,12 @@ export default class BufferController implements ComponentAPI { // Keep as arrow functions so that we can directly reference these functions directly as event listeners private _onMediaSourceOpen = () => { - const { hls, media, mediaSource } = this; + const { media, mediaSource } = this; logger.log('[buffer-controller]: Media source opened'); if (media) { + media.removeEventListener('emptied', this._onMediaEmptied); this.updateMediaElementDuration(); - hls.trigger(Events.MEDIA_ATTACHED, { media }); + this.hls.trigger(Events.MEDIA_ATTACHED, { media }); } if (mediaSource) { @@ -807,6 +810,16 @@ export default class BufferController implements ComponentAPI { logger.log('[buffer-controller]: Media source ended'); }; + private _onMediaEmptied = () => { + const { media, _objectUrl } = this; + if (media && media.src !== _objectUrl) { + logger.error( + `Media reset while attaching MediaSource, detaching media (${_objectUrl} > ${media.src})` + ); + this.hls.detachMedia(); + } + }; + private _onSBUpdateStart(type: SourceBufferName) { const { operationQueue } = this; const operation = operationQueue.current(type); diff --git a/tests/unit/controller/buffer-controller-operations.ts b/tests/unit/controller/buffer-controller-operations.ts index 31631b2773c..66b99dc6aac 100644 --- a/tests/unit/controller/buffer-controller-operations.ts +++ b/tests/unit/controller/buffer-controller-operations.ts @@ -61,6 +61,8 @@ class MockMediaElement { public currentTime: number = 0; public duration: number = Infinity; public textTracks: any[] = []; + addEventListener() {} + removeEventListener() {} } const queueNames: Array = ['audio', 'video']; From 4fdda6cf1d3a586e0dd8b60707dfa276555f28fb Mon Sep 17 00:00:00 2001 From: Rob Walch Date: Tue, 7 Feb 2023 13:18:23 -0800 Subject: [PATCH 2/2] Update src/controller/buffer-controller.ts --- src/controller/buffer-controller.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/controller/buffer-controller.ts b/src/controller/buffer-controller.ts index d317533bd5a..7e42aa8a5b0 100644 --- a/src/controller/buffer-controller.ts +++ b/src/controller/buffer-controller.ts @@ -814,9 +814,8 @@ export default class BufferController implements ComponentAPI { const { media, _objectUrl } = this; if (media && media.src !== _objectUrl) { logger.error( - `Media reset while attaching MediaSource, detaching media (${_objectUrl} > ${media.src})` + `Media element src was set while attaching MediaSource (${_objectUrl} > ${media.src})` ); - this.hls.detachMedia(); } };