From 215fc3dfba8817c4b4b1be39f73ed94b9536c476 Mon Sep 17 00:00:00 2001 From: Daniel Silhavy Date: Fri, 28 May 2021 08:56:33 +0200 Subject: [PATCH] Add settings attribute to enable/disable MediaCapabilities API --- index.d.ts | 5 ++- src/core/Settings.js | 21 ++++++++-- src/streaming/MediaPlayer.js | 3 ++ src/streaming/utils/Capabilities.js | 14 ++++++- src/streaming/utils/CapabilitiesFilter.js | 2 +- .../streaming.utils.CapabilitiesFilter.js | 41 ++++++++++--------- 6 files changed, 59 insertions(+), 27 deletions(-) diff --git a/index.d.ts b/index.d.ts index 0188fa155f..b4abe030f7 100644 --- a/index.d.ts +++ b/index.d.ts @@ -146,9 +146,12 @@ declare namespace dashjs { wallclockTimeUpdateInterval?: number, lowLatencyEnabled?: boolean, manifestUpdateRetryInterval?: number, - filterUnsupportedEssentialProperties?: boolean, cacheInitSegments?: boolean, eventControllerRefreshDelay?: number, + capabilities?: { + filterUnsupportedEssentialProperties?: boolean, + useMediaCapabilitiesApi?: boolean + }, timeShiftBuffer?: { calcFromSegmentTimeline?: boolean fallbackToSegmentTimeline?: boolean diff --git a/src/core/Settings.js b/src/core/Settings.js index 4b56d41f16..ef755834e8 100644 --- a/src/core/Settings.js +++ b/src/core/Settings.js @@ -59,9 +59,12 @@ import {HTTPRequest} from '../streaming/vo/metrics/HTTPRequest'; * wallclockTimeUpdateInterval: 100, * lowLatencyEnabled: false, * manifestUpdateRetryInterval: 100, - * filterUnsupportedEssentialProperties: true, * cacheInitSegments: true, * eventControllerRefreshDelay: 100, + * capabilities: { + * filterUnsupportedEssentialProperties: true, + * useMediaCapabilitiesApi: false + * }, * timeShiftBuffer: { * calcFromSegmentTimeline: false, * fallbackToSegmentTimeline: true @@ -477,6 +480,14 @@ import {HTTPRequest} from '../streaming/vo/metrics/HTTPRequest'; * If true, the ProtectionController and then created MediaKeys and MediaKeySessions will be preserved during the MediaPlayer lifetime. */ +/** + * @typedef {Object} Capabilities + * @property {boolean} [filterUnsupportedEssentialProperties=true] + * Enable to filter all the AdaptationSets and Representations which contain an unsupported \ element. + * @property {boolean} [useMediaCapabilitiesApi=false] + * Enable to use the MediaCapabilities API to check whether codecs are supported. If disabled MSE.isTypeSupported will be used instead. + */ + /** * @typedef {Object} AbrSettings * @property {string} [movingAverageMethod="slidingWindow"] @@ -594,8 +605,6 @@ import {HTTPRequest} from '../streaming/vo/metrics/HTTPRequest'; * The use of the date header will happen only after the other timing source that take precedence fail or are omitted as described. * @property {number} [manifestUpdateRetryInterval=100] * For live streams, set the interval-frequency in milliseconds at which dash.js will check if the current manifest is still processed before downloading the next manifest once the minimumUpdatePeriod time has. - * @property {boolean} [filterUnsupportedEssentialProperties=true] - * Enable to filter all the AdaptationSets and Representations which contain an unsupported \ element. * @property {boolean} [cacheInitSegments=true] * Enables the caching of init segments to avoid requesting the init segments before each representation switch. * @property {number} [eventControllerRefreshDelay=100] @@ -603,6 +612,7 @@ import {HTTPRequest} from '../streaming/vo/metrics/HTTPRequest'; * @property {module:Settings~LiveDelay} delay Live Delay settings * @property {module:Settings~TimeShiftBuffer} timeShiftBuffer TimeShiftBuffer settings * @property {module:Settings~Protection} protection DRM related settings + * @property {module:Settings~Capabilities} capabilities Capability related settings * @property {module:Settings~Buffer} buffer Buffer related settings * @property {module:Settings~Gaps} gaps Gap related settings * @property {module:Settings~UtcSynchronizationSettings} utcSynchronization Settings related to UTC clock synchronization @@ -686,9 +696,12 @@ function Settings() { wallclockTimeUpdateInterval: 100, lowLatencyEnabled: false, manifestUpdateRetryInterval: 100, - filterUnsupportedEssentialProperties: true, cacheInitSegments: true, eventControllerRefreshDelay: 150, + capabilities: { + filterUnsupportedEssentialProperties: true, + useMediaCapabilitiesApi: false + }, timeShiftBuffer: { calcFromSegmentTimeline: false, fallbackToSegmentTimeline: true diff --git a/src/streaming/MediaPlayer.js b/src/streaming/MediaPlayer.js index 54ac96d484..c82af6350e 100644 --- a/src/streaming/MediaPlayer.js +++ b/src/streaming/MediaPlayer.js @@ -252,6 +252,9 @@ function MediaPlayer() { function initialize(view, source, AutoPlay) { if (!capabilities) { capabilities = Capabilities(context).getInstance(); + capabilities.setConfig({ + settings + }) } errHandler = ErrorHandler(context).getInstance(); diff --git a/src/streaming/utils/Capabilities.js b/src/streaming/utils/Capabilities.js index 289451f2f8..b4e9c07c83 100644 --- a/src/streaming/utils/Capabilities.js +++ b/src/streaming/utils/Capabilities.js @@ -53,12 +53,23 @@ export function supportsMediaSource() { function Capabilities() { let instance, + settings, encryptedMediaSupported; function setup() { encryptedMediaSupported = false; } + function setConfig(config) { + if (!config) { + return; + } + + if (config.settings) { + settings = config.settings; + } + } + /** * Returns whether Encrypted Media Extensions are supported on this * user agent @@ -105,7 +116,7 @@ function Capabilities() { */ function _canUseMediaCapabilitiesApi(config, type) { - return navigator.mediaCapabilities && navigator.mediaCapabilities.decodingInfo && ((config.codec && type === Constants.AUDIO) || (type === Constants.VIDEO && config.codec && config.width && config.height && config.bitrate && config.framerate)); + return settings.get().streaming.capabilities.useMediaCapabilitiesApi && navigator.mediaCapabilities && navigator.mediaCapabilities.decodingInfo && ((config.codec && type === Constants.AUDIO) || (type === Constants.VIDEO && config.codec && config.width && config.height && config.bitrate && config.framerate)); } /** @@ -211,6 +222,7 @@ function Capabilities() { } instance = { + setConfig, supportsMediaSource, supportsEncryptedMedia, supportsCodec, diff --git a/src/streaming/utils/CapabilitiesFilter.js b/src/streaming/utils/CapabilitiesFilter.js index cc15153b9e..0bf684c4c7 100644 --- a/src/streaming/utils/CapabilitiesFilter.js +++ b/src/streaming/utils/CapabilitiesFilter.js @@ -44,7 +44,7 @@ function CapabilitiesFilter() { Promise.all(promises) .then(() => { - if (settings.get().streaming.filterUnsupportedEssentialProperties) { + if (settings.get().streaming.capabilities.filterUnsupportedEssentialProperties) { _filterUnsupportedEssentialProperties(manifest); } _applyCustomFilters(manifest); diff --git a/test/unit/streaming.utils.CapabilitiesFilter.js b/test/unit/streaming.utils.CapabilitiesFilter.js index f96f045729..404c8e1257 100644 --- a/test/unit/streaming.utils.CapabilitiesFilter.js +++ b/test/unit/streaming.utils.CapabilitiesFilter.js @@ -33,7 +33,7 @@ describe('CapabilitiesFilter', function () { describe('filter codecs', function () { beforeEach(function () { - settings.update({ streaming: { filterUnsupportedEssentialProperties: false } }); + settings.update({ streaming: { capabilities: { filterUnsupportedEssentialProperties: false } } }); }); it('should not filter AdaptationSets and Representations', function (done) { @@ -147,11 +147,11 @@ describe('CapabilitiesFilter', function () { describe('filter EssentialProperty values', function () { beforeEach(function () { - settings.update({ streaming: { filterUnsupportedEssentialProperties: true } }); + settings.update({ streaming: { capabilities: { filterUnsupportedEssentialProperties: true }} }); }); it('should not filter AdaptationSets and Representations if filterUnsupportedEssentialProperties is disabled', function (done) { - settings.update({ streaming: { filterUnsupportedEssentialProperties: false } }); + settings.update({ streaming: { capabilities: {filterUnsupportedEssentialProperties: false }} }); const manifest = { Period_asArray: [{ AdaptationSet_asArray: [{ @@ -337,24 +337,25 @@ describe('CapabilitiesFilter', function () { it('should use provided custom filters', function (done) { const manifest = { Period_asArray: [{ - AdaptationSet_asArray: [{ - mimeType: 'video/mp4', - Representation_asArray: [ - { - mimeType: 'video/mp4', - height: 1080 - }, - { - mimeType: 'video/mp4', - height: 720 - }, - { - mimeType: 'video/mp4', - height: 480 - } - ] + AdaptationSet_asArray: [{ + mimeType: 'video/mp4', + Representation_asArray: [ + { + mimeType: 'video/mp4', + height: 1080 + }, + { + mimeType: 'video/mp4', + height: 720 + }, + { + mimeType: 'video/mp4', + height: 480 + } + ] + }] }] - }]}; + }; capabilitiesFilter.setCustomCapabilitiesFilters([function (representation) { return representation.height <= 720;