From 161c66ce77f84192007037dc4d2ffb51998e8fb8 Mon Sep 17 00:00:00 2001 From: OrenMe Date: Mon, 15 Jul 2019 16:58:30 +0300 Subject: [PATCH 1/9] fix: calling detatchMedia() followed by attachMedia() causes audio to not play On re-attch the context of altAudio is not saved in buffer control so it doesn't know to create two source buffers. Also, in context of stream controller it doesn't reset the `altAudio` flag. I also noticed that stream controller is reloading the entire frags it has in `fragmentTracker` and it seems it needs to be reset on detach, otherwise there's a very long start delay where unncessery buffering occurs. based on #2110 and fixes #2099. --- src/controller/buffer-controller.ts | 5 +++++ src/controller/stream-controller.js | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/controller/buffer-controller.ts b/src/controller/buffer-controller.ts index b914a4e7bfe..62307836599 100644 --- a/src/controller/buffer-controller.ts +++ b/src/controller/buffer-controller.ts @@ -47,6 +47,9 @@ class BufferController extends EventHandler { // signals that mediaSource should have endOfStream called private _needsEos: boolean = false; + // Track whether the parsed manifest signaled alternate audio + // private _altAudio: boolean = false; + private config: BufferControllerConfig; // this is optional because this property is removed from the class sometimes @@ -143,6 +146,7 @@ class BufferController extends EventHandler { // sourcebuffers will be created all at once when the expected nb of tracks will be reached // in case alt audio is not used, only one BUFFER_CODEC event will be fired from main stream controller // it will contain the expected nb of source buffers, no need to compute it + // this._altAudio = data.altAudio; this.bufferCodecEventsExpected = data.altAudio ? 2 : 1; logger.log(`${this.bufferCodecEventsExpected} bufferCodec event(s) expected`); } @@ -202,6 +206,7 @@ class BufferController extends EventHandler { this.mediaSource = null; this.media = null; this._objectUrl = null; + // this.bufferCodecEventsExpected = this._altAudio ? 2 : 1; this.pendingTracks = {}; this.tracks = {}; this.sourceBuffer = {}; diff --git a/src/controller/stream-controller.js b/src/controller/stream-controller.js index 092a55bcc77..6c27585539d 100644 --- a/src/controller/stream-controller.js +++ b/src/controller/stream-controller.js @@ -691,7 +691,8 @@ class StreamController extends BaseStreamController { media.removeEventListener('ended', this.onvended); this.onvseeking = this.onvseeked = this.onvended = null; } - this.media = this.mediaBuffer = null; + this.fragmentTracker.removeAllFragments(); + this.media = this.mediaBuffer = this.altAudio = null; this.loadedmetadata = false; this.stopLoad(); } From eb26c310d77ad968477e98faecf0629d4fc0ed77 Mon Sep 17 00:00:00 2001 From: OrenMe Date: Mon, 15 Jul 2019 17:13:52 +0300 Subject: [PATCH 2/9] fix commented code --- src/controller/buffer-controller.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/controller/buffer-controller.ts b/src/controller/buffer-controller.ts index 62307836599..137d26625a8 100644 --- a/src/controller/buffer-controller.ts +++ b/src/controller/buffer-controller.ts @@ -48,7 +48,7 @@ class BufferController extends EventHandler { private _needsEos: boolean = false; // Track whether the parsed manifest signaled alternate audio - // private _altAudio: boolean = false; + private _altAudio: boolean = false; private config: BufferControllerConfig; @@ -146,7 +146,7 @@ class BufferController extends EventHandler { // sourcebuffers will be created all at once when the expected nb of tracks will be reached // in case alt audio is not used, only one BUFFER_CODEC event will be fired from main stream controller // it will contain the expected nb of source buffers, no need to compute it - // this._altAudio = data.altAudio; + this._altAudio = data.altAudio; this.bufferCodecEventsExpected = data.altAudio ? 2 : 1; logger.log(`${this.bufferCodecEventsExpected} bufferCodec event(s) expected`); } @@ -206,7 +206,7 @@ class BufferController extends EventHandler { this.mediaSource = null; this.media = null; this._objectUrl = null; - // this.bufferCodecEventsExpected = this._altAudio ? 2 : 1; + this.bufferCodecEventsExpected = this._altAudio ? 2 : 1; this.pendingTracks = {}; this.tracks = {}; this.sourceBuffer = {}; From 8bcd7b10c18a65f2c85759674dcf1dc4313d6fe2 Mon Sep 17 00:00:00 2001 From: OrenMe Date: Mon, 15 Jul 2019 23:30:39 +0300 Subject: [PATCH 3/9] also reaset fragmentTracker for audio on detach --- src/controller/audio-stream-controller.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/controller/audio-stream-controller.js b/src/controller/audio-stream-controller.js index b12e53cc0ae..9959dd1a9cc 100644 --- a/src/controller/audio-stream-controller.js +++ b/src/controller/audio-stream-controller.js @@ -381,6 +381,7 @@ class AudioStreamController extends BaseStreamController { } this.media = this.mediaBuffer = this.videoBuffer = null; this.loadedmetadata = false; + this.fragmentTracker.removeAllFragments(); this.stopLoad(); } From 1c3baeda5cadbfaa8f363c67c899bd5b23c056bb Mon Sep 17 00:00:00 2001 From: OrenMe Date: Tue, 16 Jul 2019 13:08:27 +0300 Subject: [PATCH 4/9] handle altAudio when main elementry stream has muxed AV save altAudio flag in stream controer from the manifest parsed --- src/controller/stream-controller.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/controller/stream-controller.js b/src/controller/stream-controller.js index 6c27585539d..4fa5ba02abf 100644 --- a/src/controller/stream-controller.js +++ b/src/controller/stream-controller.js @@ -692,7 +692,7 @@ class StreamController extends BaseStreamController { this.onvseeking = this.onvseeked = this.onvended = null; } this.fragmentTracker.removeAllFragments(); - this.media = this.mediaBuffer = this.altAudio = null; + this.media = this.mediaBuffer = null; this.loadedmetadata = false; this.stopLoad(); } @@ -736,6 +736,7 @@ class StreamController extends BaseStreamController { logger.log('both AAC/HE-AAC audio found in levels; declaring level codec as HE-AAC'); } + this.altAudio = data.altAudio; this.levels = data.levels; this.startFragRequested = false; let config = this.config; From 18955e20b058f8bf166c544c128976a001927eda Mon Sep 17 00:00:00 2001 From: OrenMe Date: Sun, 22 Sep 2019 09:15:37 +0300 Subject: [PATCH 5/9] CR fixes --- src/controller/stream-controller.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/controller/stream-controller.js b/src/controller/stream-controller.js index 4fa5ba02abf..2c663f9dcba 100644 --- a/src/controller/stream-controller.js +++ b/src/controller/stream-controller.js @@ -47,6 +47,7 @@ class StreamController extends BaseStreamController { this._state = State.STOPPED; this.stallReported = false; this.gapController = null; + this.altAudio = false; } startLoad (startPosition) { From af51c039a39fb9c79521b538ad35f39100e04c6a Mon Sep 17 00:00:00 2001 From: OrenMe Date: Sun, 6 Oct 2019 10:45:13 +0300 Subject: [PATCH 6/9] buffer-controller CR fixes --- src/controller/buffer-controller.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/controller/buffer-controller.ts b/src/controller/buffer-controller.ts index 137d26625a8..ec0c342ae09 100644 --- a/src/controller/buffer-controller.ts +++ b/src/controller/buffer-controller.ts @@ -47,9 +47,6 @@ class BufferController extends EventHandler { // signals that mediaSource should have endOfStream called private _needsEos: boolean = false; - // Track whether the parsed manifest signaled alternate audio - private _altAudio: boolean = false; - private config: BufferControllerConfig; // this is optional because this property is removed from the class sometimes @@ -58,6 +55,9 @@ class BufferController extends EventHandler { // The number of BUFFER_CODEC events received before any sourceBuffers are created public bufferCodecEventsExpected: number = 0; + // The total number of BUFFER_CODEC events received + private _bufferCodecEventsTotal: number = 0; + // A reference to the attached media element public media: HTMLMediaElement | null = null; @@ -146,8 +146,7 @@ class BufferController extends EventHandler { // sourcebuffers will be created all at once when the expected nb of tracks will be reached // in case alt audio is not used, only one BUFFER_CODEC event will be fired from main stream controller // it will contain the expected nb of source buffers, no need to compute it - this._altAudio = data.altAudio; - this.bufferCodecEventsExpected = data.altAudio ? 2 : 1; + this.bufferCodecEventsExpected = this._bufferCodecEventsTotal = data.altAudio ? 2 : 1; logger.log(`${this.bufferCodecEventsExpected} bufferCodec event(s) expected`); } @@ -206,7 +205,7 @@ class BufferController extends EventHandler { this.mediaSource = null; this.media = null; this._objectUrl = null; - this.bufferCodecEventsExpected = this._altAudio ? 2 : 1; + this.bufferCodecEventsExpected = this._bufferCodecEventsTotal; this.pendingTracks = {}; this.tracks = {}; this.sourceBuffer = {}; From 10bf1b86a623b36c8cbf3fe9fb3fbde89bebf4ea Mon Sep 17 00:00:00 2001 From: OrenMe Date: Sun, 6 Oct 2019 10:48:57 +0300 Subject: [PATCH 7/9] reset subtitle tracks state --- src/controller/subtitle-stream-controller.js | 5 +++++ src/controller/subtitle-track-controller.js | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/controller/subtitle-stream-controller.js b/src/controller/subtitle-stream-controller.js index ac8e0b872ab..57024a9ac9f 100644 --- a/src/controller/subtitle-stream-controller.js +++ b/src/controller/subtitle-stream-controller.js @@ -84,6 +84,11 @@ export class SubtitleStreamController extends BaseStreamController { onMediaDetaching () { this.media.removeEventListener('seeking', this._onMediaSeeking); + this.fragmentTracker.removeAllFragments(); + this.currentTrackId = -1; + this.tracks.forEach((track) => { + this.tracksBuffered[track.id] = []; + }); this.media = null; this.state = State.STOPPED; } diff --git a/src/controller/subtitle-track-controller.js b/src/controller/subtitle-track-controller.js index 9da39317b04..717c16e0e21 100644 --- a/src/controller/subtitle-track-controller.js +++ b/src/controller/subtitle-track-controller.js @@ -66,6 +66,11 @@ class SubtitleTrackController extends EventHandler { this.media.textTracks.removeEventListener('change', this.trackChangeListener); } + if (Number.isFinite(this.subtitleTrack)) { + this.queuedDefaultTrack = this.subtitleTrack; + } + + this.trackId = -1; this.media = null; } From eb35560259cb6d3d9830c56c607999d6ebebc164 Mon Sep 17 00:00:00 2001 From: OrenMe Date: Tue, 8 Oct 2019 01:12:51 +0300 Subject: [PATCH 8/9] fix test --- tests/unit/controller/subtitle-stream-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/controller/subtitle-stream-controller.js b/tests/unit/controller/subtitle-stream-controller.js index 1dc281b7fe4..37c33a13887 100644 --- a/tests/unit/controller/subtitle-stream-controller.js +++ b/tests/unit/controller/subtitle-stream-controller.js @@ -61,7 +61,7 @@ describe('SubtitleStreamController', function () { }); it('should call clearInterval if no tracks present', function () { - subtitleStreamController.tracks = null; + subtitleStreamController.tracks = []; hls.trigger(Event.SUBTITLE_TRACK_SWITCH, { id: 0 }); From cb263f9906a0e33406afa4c0a6ff6cc5b04d1cf7 Mon Sep 17 00:00:00 2001 From: OrenMe Date: Tue, 8 Oct 2019 01:13:36 +0300 Subject: [PATCH 9/9] add additional check for no subtitle tracks --- src/controller/subtitle-stream-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controller/subtitle-stream-controller.js b/src/controller/subtitle-stream-controller.js index 57024a9ac9f..8e313d9d8b9 100644 --- a/src/controller/subtitle-stream-controller.js +++ b/src/controller/subtitle-stream-controller.js @@ -116,7 +116,7 @@ export class SubtitleStreamController extends BaseStreamController { onSubtitleTrackSwitch (data) { this.currentTrackId = data.id; - if (!this.tracks || this.currentTrackId === -1) { + if (!this.tracks || !this.tracks.length || this.currentTrackId === -1) { this.clearInterval(); return; }