Skip to content

Commit

Permalink
feat(MediaCap): Add polyfill for MediaCapabilities
Browse files Browse the repository at this point in the history
If navigator.mediaCapabilties is not supported by the browser, use
MediaSource.isTypeSupported to check if the stream is supported.

Issue shaka-project#1391

Change-Id: Iee0c7e339add2a07028ed14a03df14e4d36a203e
  • Loading branch information
michellezhuogg committed Mar 12, 2021
1 parent 57ee238 commit f4c6063
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 48 deletions.
1 change: 1 addition & 0 deletions build/types/polyfill
Expand Up @@ -7,6 +7,7 @@
+../../lib/polyfill/languages.js
+../../lib/polyfill/mathround.js
+../../lib/polyfill/mediasource.js
+../../lib/polyfill/media_capabilities.js
+../../lib/polyfill/orientation.js
+../../lib/polyfill/patchedmediakeys_apple.js
+../../lib/polyfill/patchedmediakeys_ms.js
Expand Down
77 changes: 77 additions & 0 deletions lib/polyfill/media_capabilities.js
@@ -0,0 +1,77 @@
/*! @license
* Shaka Player
* Copyright 2016 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

goog.provide('shaka.polyfill.MediaCapabilities');

goog.require('shaka.log');
goog.require('shaka.polyfill');


/**
* @summary A polyfill to provide navigator.mediaCapabilities on all browsers.
* This is necessary for Tizen 3, Xbox One and possibly others we have yet to
* discover.
*/
shaka.polyfill.MediaCapabilities = class {
/**
* Install the polyfill if needed.
*/
static install() {
shaka.log.debug('MediaCapabilities: install');

if (navigator.mediaCapabilities) {
shaka.log.debug(
'MediaCapabilities: Native mediaCapabilities support found.');
return;
}

navigator.mediaCapabilities = /** @type {!MediaCapabilities} */ ({});
navigator.mediaCapabilities.decodingInfo =
shaka.polyfill.MediaCapabilities.decodingInfo_;
}

/**
* @param {!MediaDecodingConfiguration} mediaDecodingConfig
* @return {!Promise.<!MediaCapabilitiesDecodingInfo>}
* @private
*/
static decodingInfo_(mediaDecodingConfig) {
const res = {
supported: false,
powerEfficient: true,
smooth: true,
keySystemAccess: null,
configuration: mediaDecodingConfig,
};

if (!mediaDecodingConfig) {
return Promise.resolve(res);
}

// Use 'MediaSource.isTypeSupported' to check if the stream is supported.
if (mediaDecodingConfig['video']) {
const contentType = mediaDecodingConfig['video'].contentType;
const isSupported = MediaSource.isTypeSupported(contentType);
if (!isSupported) {
return Promise.resolve(res);
}
}

if (mediaDecodingConfig['audio']) {
const contentType = mediaDecodingConfig['audio'].contentType;
const isSupported = MediaSource.isTypeSupported(contentType);
if (!isSupported) {
return Promise.resolve(res);
}
}

res.supported = true;
return Promise.resolve(res);
}
};


shaka.polyfill.register(shaka.polyfill.MediaCapabilities.install);
75 changes: 27 additions & 48 deletions lib/util/stream_utils.js
Expand Up @@ -9,7 +9,6 @@ goog.provide('shaka.util.StreamUtils');
goog.require('goog.asserts');
goog.require('shaka.log');
goog.require('shaka.media.DrmEngine');
goog.require('shaka.media.MediaSourceEngine');
goog.require('shaka.text.TextEngine');
goog.require('shaka.util.Functional');
goog.require('shaka.util.LanguageUtils');
Expand Down Expand Up @@ -308,57 +307,37 @@ shaka.util.StreamUtils = class {
* @private
*/
static async filterManifestByMediaCapabilities_(manifest) {
if ('mediaCapabilities' in navigator) {
const MediaCapabilities = navigator.mediaCapabilities;
const getVariantDecodingInfo = (async (variant) => {
/** @type {!MediaDecodingConfiguration} */
const decodingConfig =
shaka.util.StreamUtils.prepareDecodingConfiguration_(variant);
const result = await MediaCapabilities.decodingInfo(decodingConfig);
variant.decodingInfos.push(result);
});
goog.asserts.assert(navigator.mediaCapabilities,
'MediaCapabilities should be valid.');

const MediaCapabilities = navigator.mediaCapabilities;
const getVariantDecodingInfo = (async (variant) => {
/** @type {!MediaDecodingConfiguration} */
const decodingConfig =
shaka.util.StreamUtils.prepareDecodingConfiguration_(variant);
const result = await MediaCapabilities.decodingInfo(decodingConfig);
variant.decodingInfos.push(result);
});

const operations = [];
for (const variant of manifest.variants) {
if (!variant.decodingInfos.length) {
operations.push(getVariantDecodingInfo(variant));
}
const operations = [];
for (const variant of manifest.variants) {
if (!variant.decodingInfos.length) {
operations.push(getVariantDecodingInfo(variant));
}
await Promise.all(operations);

manifest.variants = manifest.variants.filter((variant) => {
const supported = variant.decodingInfos.some((decodingInfo) => {
return decodingInfo.supported;
});
// Filter out all unsupported variants.
if (!supported) {
shaka.log.debug('Dropping variant - not compatible with platform',
shaka.util.StreamUtils.getVariantSummaryString_(variant));
}
return supported;
});
} else {
// TODO: move to MediaCapabilities polyfill.
manifest.variants = manifest.variants.filter((variant) => {
const audio = variant.audio;
const video = variant.video;

if (audio && !shaka.media.MediaSourceEngine.isStreamSupported(audio)) {
shaka.log.debug(
'Dropping variant - audio not compatible with platform',
shaka.util.StreamUtils.getStreamSummaryString_(audio));
return false;
}
}
await Promise.all(operations);

if (video && !shaka.media.MediaSourceEngine.isStreamSupported(video)) {
shaka.log.debug(
'Dropping variant - video not compatible with platform',
shaka.util.StreamUtils.getStreamSummaryString_(video));
return false;
}
return true;
manifest.variants = manifest.variants.filter((variant) => {
const supported = variant.decodingInfos.some((decodingInfo) => {
return decodingInfo.supported;
});
}
// Filter out all unsupported variants.
if (!supported) {
shaka.log.debug('Dropping variant - not compatible with platform',
shaka.util.StreamUtils.getVariantSummaryString_(variant));
}
return supported;
});
}


Expand Down

0 comments on commit f4c6063

Please sign in to comment.