diff --git a/lib/util/stream_utils.js b/lib/util/stream_utils.js index 483f56a5b2..230f5ec568 100644 --- a/lib/util/stream_utils.js +++ b/lib/util/stream_utils.js @@ -704,10 +704,11 @@ shaka.util.StreamUtils = class { } // for (const preferredKeySystem of preferredKeySystems) /** - * For LR devices, polyfill is used, which calls isTypeSupported and + * For platforms which use the MediaCapabilities polyfill, calls to media + * capabilities are replaced with isTypeSupported and * requestMediaKeySystemAccess instead. - * Group similar variants, and share results. - * Helpful for video with a lot of variants on LR. + * By grouping similar variants, we can improve performance for manifests + * with lots of variants. */ const enableCache = enableMediaCapabilitiesCache && !srcEquals && !shaka.util.Platform.isChromecast(); @@ -733,11 +734,7 @@ shaka.util.StreamUtils = class { for (const videoFullMimeType of video.fullMimeTypes) { for (const audioFullMimeType of audio.fullMimeTypes) { cacheKeys.push( - `${videoFullMimeType}#${video.hdr} - #${audioFullMimeType}#${audio.spatialAudio} - #${audio.channelsCount} - #${keySystem}`); - // video.hdr + audio.spatialAudio + audio.channelsCount + `${videoFullMimeType}#${audioFullMimeType}#${keySystem}`); } } } @@ -747,52 +744,27 @@ shaka.util.StreamUtils = class { // sort variants, so that high bandwidth checked first. // High bandwidth tends to be less likely to be supported, or smooth const sortedVariants = variants.sort((a, b) => b.bandwidth - a.bandwidth); - const keyToCheck = 'supported'; for (const variant of sortedVariants) { const cacheKeys = buildCacheKey(variant); const useCache = cacheKeys && cacheKeys.length && - cacheKeys.reduce((hasCache, key) => - (hasCache && decodeInfoCache[key] && - // If not meet criteria, won't use cache. - decodeInfoCache[key][keyToCheck]) - , true); - shaka.log.info('getDecodingInfosForVariants used cache.', - useCache, cacheKeys, variant); + cacheKeys.every((key) => { + return decodeInfoCache[key] && decodeInfoCache[key].supported; + }); if (useCache) { variant.decodingInfos = cacheKeys.map((key) => decodeInfoCache[key]); continue; } - /** @type {!Array.>} */ - const decodingConfigs = shaka.util.StreamUtils.getDecodingConfigs_( - variant, usePersistentLicenses, srcEquals) - .filter((configs) => { - // All configs in a batch will have the same keySystem. - const config = configs[0]; - const keySystem = config.keySystemConfiguration && - config.keySystemConfiguration.keySystem; - // Avoid checking preferred systems twice. - return !keySystem || !preferredKeySystems.includes(keySystem); - }); - - // The reason we are performing this await in a loop rather than - // batching into a `promise.all` is performance related. - // https://github.com/shaka-project/shaka-player/pull/4708#discussion_r1022581178 - for (let i = 0; i < decodingConfigs.length; i++) { - const configs = decodingConfigs[i]; - // eslint-disable-next-line no-await-in-loop - await shaka.util.StreamUtils.getDecodingInfosForVariant_( - variant, configs); + // eslint-disable-next-line no-await-in-loop + await shaka.util.StreamUtils.getAndApplyDecodingInfosForVariant_( + variant, usePersistentLicenses, srcEquals, preferredKeySystems); - // getDecodingInfosForVariant_ could fail. - const result = variant.decodingInfos.length ? - variant.decodingInfos[i] : null; - if (cacheKeys && result) { + if (cacheKeys) { + for (let i = 0; i < variant.decodingInfos.length; i++) { const cacheKey = cacheKeys[i]; - - decodeInfoCache[cacheKey] = result; + decodeInfoCache[cacheKey] = variant.decodingInfos[i]; delete decodeInfoCache[cacheKey]['configuration']; } } @@ -801,26 +773,42 @@ shaka.util.StreamUtils = class { } for (const variant of variants) { - /** @type {!Array.>} */ - const decodingConfigs = shaka.util.StreamUtils.getDecodingConfigs_( - variant, usePersistentLicenses, srcEquals) - .filter((configs) => { - // All configs in a batch will have the same keySystem. - const config = configs[0]; - const keySystem = config.keySystemConfiguration && + // eslint-disable-next-line no-await-in-loop + await shaka.util.StreamUtils.getAndApplyDecodingInfosForVariant_( + variant, usePersistentLicenses, srcEquals, preferredKeySystems); + } + } + + /** + * Call mediaCapabilities + * Generate input for querying mediaCapabilities and call the API . + * @param {!shaka.extern.Variant} variant + * @param {boolean} usePersistentLicenses + * @param {boolean} srcEquals + * @param {!Array=} preferredKeySystems + * @private + */ + static async getAndApplyDecodingInfosForVariant_( + variant, usePersistentLicenses, srcEquals, preferredKeySystems = []) { + /** @type {!Array.>} */ + const decodingConfigs = shaka.util.StreamUtils.getDecodingConfigs_( + variant, usePersistentLicenses, srcEquals) + .filter((configs) => { + // All configs in a batch will have the same keySystem. + const config = configs[0]; + const keySystem = config.keySystemConfiguration && config.keySystemConfiguration.keySystem; - // Avoid checking preferred systems twice. - return !keySystem || !preferredKeySystems.includes(keySystem); - }); + // Avoid checking preferred systems twice. + return !keySystem || !preferredKeySystems.includes(keySystem); + }); - // The reason we are performing this await in a loop rather than - // batching into a `promise.all` is performance related. - // https://github.com/shaka-project/shaka-player/pull/4708#discussion_r1022581178 - for (const configs of decodingConfigs) { - // eslint-disable-next-line no-await-in-loop - await shaka.util.StreamUtils.getDecodingInfosForVariant_( - variant, configs); - } + // The reason we are performing this await in a loop rather than + // batching into a `promise.all` is performance related. + // https://github.com/shaka-project/shaka-player/pull/4708#discussion_r1022581178 + for (const configs of decodingConfigs) { + // eslint-disable-next-line no-await-in-loop + await shaka.util.StreamUtils.getDecodingInfosForVariant_( + variant, configs); } }