Skip to content

Commit

Permalink
feat: Use ManagedMediaSource when available (#5683)
Browse files Browse the repository at this point in the history
The spec can be seen at w3c/media-source#320

Closes #5271
  • Loading branch information
avelad committed Oct 11, 2023
1 parent 2a35579 commit 01da5fa
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 20 deletions.
24 changes: 24 additions & 0 deletions externs/managedmediasource.js
@@ -0,0 +1,24 @@
/*! @license
* Shaka Player
* Copyright 2016 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

/**
* @fileoverview Externs for ManagedMediaSource which were missing in the
* Closure compiler.
*
* @externs
*/

/**
* @constructor
* @extends {MediaSource}
*/
function ManagedMediaSource() {}

/**
* @param {string} type
* @return {boolean}
*/
ManagedMediaSource.isTypeSupported = function(type) {};
13 changes: 10 additions & 3 deletions lib/media/media_source_capabilities.js
Expand Up @@ -23,9 +23,16 @@ shaka.media.Capabilities = class {
if (supportMap.has(type)) {
return supportMap.get(type);
}
const currentSupport = MediaSource.isTypeSupported(type);
supportMap.set(type, currentSupport);
return currentSupport;
if (window.ManagedMediaSource) {
const currentSupport = ManagedMediaSource.isTypeSupported(type);
supportMap.set(type, currentSupport);
return currentSupport;
} else if (window.MediaSource) {
const currentSupport = MediaSource.isTypeSupported(type);
supportMap.set(type, currentSupport);
return currentSupport;
}
return false;
}

/**
Expand Down
73 changes: 58 additions & 15 deletions lib/media/media_source_engine.js
Expand Up @@ -119,7 +119,7 @@ shaka.media.MediaSourceEngine = class {
/** @private {boolean} */
this.playbackHasBegun_ = false;

/** @private {MediaSource} */
/** @private {(MediaSource|ManagedMediaSource)} */
this.mediaSource_ = this.createMediaSource(this.mediaSourceOpen_);

/** @private {boolean} */
Expand All @@ -145,6 +145,9 @@ shaka.media.MediaSourceEngine = class {

/** @private {boolean} */
this.needSplitMuxedContent_ = false;

/** @private {boolean} */
this.streamingAllowed_ = true;
}

/**
Expand All @@ -154,30 +157,60 @@ shaka.media.MediaSourceEngine = class {
* Replaced by unit tests.
*
* @param {!shaka.util.PublicPromise} p
* @return {!MediaSource}
* @return {!(MediaSource|ManagedMediaSource)}
*/
createMediaSource(p) {
const mediaSource = new MediaSource();
if (window.ManagedMediaSource) {
this.video_.disableRemotePlayback = true;

// Set up MediaSource on the video element.
this.eventManager_.listenOnce(
mediaSource, 'sourceopen', () => this.onSourceOpen_(p));
const mediaSource = new ManagedMediaSource();

// Correctly set when playback has begun.
this.eventManager_.listenOnce(this.video_, 'playing', () => {
this.playbackHasBegun_ = true;
});
this.eventManager_.listenOnce(
mediaSource, 'sourceopen', () => this.onSourceOpen_(p));

this.eventManager_.listen(
mediaSource, 'startstreaming', () => {
this.streamingAllowed_ = true;
});

this.eventManager_.listen(
mediaSource, 'endstreaming', () => {
this.streamingAllowed_ = false;
});

// Correctly set when playback has begun.
this.eventManager_.listenOnce(this.video_, 'playing', () => {
this.playbackHasBegun_ = true;
});

this.url_ = shaka.media.MediaSourceEngine.createObjectURL(mediaSource);

this.video_.src = this.url_;

return mediaSource;
} else {
const mediaSource = new MediaSource();

// Set up MediaSource on the video element.
this.eventManager_.listenOnce(
mediaSource, 'sourceopen', () => this.onSourceOpen_(p));

// Correctly set when playback has begun.
this.eventManager_.listenOnce(this.video_, 'playing', () => {
this.playbackHasBegun_ = true;
});

// Store the object URL for releasing it later.
this.url_ = shaka.media.MediaSourceEngine.createObjectURL(mediaSource);
// Store the object URL for releasing it later.
this.url_ = shaka.media.MediaSourceEngine.createObjectURL(mediaSource);

this.video_.src = this.url_;
this.video_.src = this.url_;

return mediaSource;
return mediaSource;
}
}

/**
* @param {!shaka.util.PublicPromise} p
* @param {shaka.util.PublicPromise} p
* @private
*/
onSourceOpen_(p) {
Expand Down Expand Up @@ -511,6 +544,16 @@ shaka.media.MediaSourceEngine = class {
this.config_ = config;
}

/**
* Indicate if the streaming is allowed by MediaSourceEngine.
* If we using MediaSource we allways returns true.
*
* @return {boolean}
*/
isStreamingAllowed() {
return this.streamingAllowed_;
}

/**
* Reinitialize the TextEngine for a new text type.
* @param {string} mimeType
Expand Down
8 changes: 8 additions & 0 deletions lib/media/streaming_engine.js
Expand Up @@ -1054,6 +1054,14 @@ shaka.media.StreamingEngine = class {
this.playerInterface_.mediaSourceEngine.clearSelectedClosedCaptionId();
}

if (!this.playerInterface_.mediaSourceEngine.isStreamingAllowed() &&
mediaState.type != ContentType.TEXT) {
// It is not allowed to add segments yet, so we schedule an update to
// check again later. So any prediction we make now could be terribly
// invalid soon.
return this.config_.updateIntervalSeconds / 2;
}

const logPrefix = shaka.media.StreamingEngine.logPrefix_(mediaState);

// Compute how far we've buffered ahead of the playhead.
Expand Down
5 changes: 3 additions & 2 deletions lib/util/platform.js
Expand Up @@ -23,15 +23,16 @@ shaka.util.Platform = class {
* @return {boolean}
*/
static supportsMediaSource() {
const mediaSource = window.ManagedMediaSource || window.MediaSource;
// Browsers that lack a media source implementation will have no reference
// to |window.MediaSource|. Platforms that we see having problematic media
// source implementations will have this reference removed via a polyfill.
if (!window.MediaSource) {
if (!mediaSource) {
return false;
}

// Some very old MediaSource implementations didn't have isTypeSupported.
if (!MediaSource.isTypeSupported) {
if (!mediaSource.isTypeSupported) {
return false;
}

Expand Down
5 changes: 5 additions & 0 deletions test/test/util/fake_media_source_engine.js
Expand Up @@ -147,6 +147,11 @@ shaka.test.FakeMediaSourceEngine = class {
return Promise.resolve();
}

/** @override */
isStreamingAllowed() {
return true;
}

/**
* @param {string} type
* @return {?number}
Expand Down

0 comments on commit 01da5fa

Please sign in to comment.