diff --git a/src/playlist-controller.js b/src/playlist-controller.js index c37425f52..87e2fc5fb 100644 --- a/src/playlist-controller.js +++ b/src/playlist-controller.js @@ -192,6 +192,7 @@ export class PlaylistController extends videojs.EventTarget { this.playlistExclusionDuration = playlistExclusionDuration; this.maxPlaylistRetries = maxPlaylistRetries; this.enableLowInitialPlaylist = enableLowInitialPlaylist; + this.hasManagedMediaSource_ = false; if (this.useCueTags_) { this.cueTagsTrack_ = this.tech_.addTextTrack( @@ -215,6 +216,8 @@ export class PlaylistController extends videojs.EventTarget { // Airplay source not yet implemented. Remote playback must be disabled. this.tech_.el_.disableRemotePlayback = true; this.mediaSource = new window.ManagedMediaSource(); + this.hasManagedMediaSource_ = true; + videojs.log('Using ManagedMediaSource'); } else if (window.MediaSource) { this.mediaSource = new window.MediaSource(); @@ -232,6 +235,14 @@ export class PlaylistController extends videojs.EventTarget { // we don't have to handle sourceclose since dispose will handle termination of // everything, and the MediaSource should not be detached without a proper disposal + if (this.hasManagedMediaSource_) { + this.handleStartStreaming_ = this.handleStartStreaming_.bind(this); + this.handleEndStreaming_ = this.handleEndStreaming_.bind(this); + + this.mediaSource.addEventListener('startstreaming', this.handleStartStreaming_); + this.mediaSource.addEventListener('endstreaming', this.handleEndStreaming_); + } + this.seekable_ = createTimeRanges(); this.hasPlayed_ = false; @@ -1056,14 +1067,31 @@ export class PlaylistController extends videojs.EventTarget { */ load() { this.mainSegmentLoader_.load(); + if (this.mediaTypes_.AUDIO.activePlaylistLoader) { this.audioSegmentLoader_.load(); } + if (this.mediaTypes_.SUBTITLES.activePlaylistLoader) { this.subtitleSegmentLoader_.load(); } } + /** + * Call pause on our SegmentLoaders + */ + pause() { + this.mainSegmentLoader_.pause(); + + if (this.mediaTypes_.AUDIO.activePlaylistLoader) { + this.audioSegmentLoader_.pause(); + } + + if (this.mediaTypes_.SUBTITLES.activePlaylistLoader) { + this.subtitleSegmentLoader_.pause(); + } + } + /** * Re-tune playback quality level for the current player * conditions. This method will perform destructive actions like removing @@ -1223,6 +1251,26 @@ export class PlaylistController extends videojs.EventTarget { Number.MAX_VALUE : duration; } + /** + * Handle the startstreaming event on the ManagedMediaSource. + * This event indicates that segment loading should be started/resumed. + * + * @private + */ + handleStartStreaming_() { + this.load(); + } + + /** + * Handle the endstreaming event on the ManagedMediaSource. + * This event indicates that segment loading should be paused. + * + * @private + */ + handleEndStreaming_() { + this.pause(); + } + /** * handle the durationchange event on the MediaSource * diff --git a/test/playlist-controller.test.js b/test/playlist-controller.test.js index 9cbe9391c..39cb38db5 100644 --- a/test/playlist-controller.test.js +++ b/test/playlist-controller.test.js @@ -7693,3 +7693,30 @@ QUnit.test('uses ManagedMediaSource only when opted in', function(assert) { mmsSpy.restore(); mms.restore(); }); + +QUnit.test('ManagedMediaSource startstreaming and endstreaming events start and pause segment loading respectively', function(assert) { + const mms = useFakeManagedMediaSource(); + const options = { + src: 'test.m3u8', + tech: this.player.tech_, + player_: this.player, + experimentalUseMMS: true + }; + + const controller = new PlaylistController(options); + const loadSpy = sinon.spy(controller, 'load'); + const pauseSpy = sinon.spy(controller, 'pause'); + + assert.ok(loadSpy.notCalled, 'Segment loading not started yet'); + assert.ok(pauseSpy.notCalled, 'Segment loading has not been paused'); + + controller.mediaSource.trigger('startstreaming'); + + assert.ok(loadSpy.calledOnce, 'Segment loading started on startstreaming event'); + + controller.mediaSource.trigger('endstreaming'); + + assert.ok(pauseSpy.calledOnce, 'Segment loading paused on endstreaming event'); + + mms.restore(); +});