UNPKG

rx-player

Version:
225 lines (209 loc) 7 kB
/** * Copyright 2015 CANAL+ Group * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { canRelyOnRequestMediaKeySystemAccess } from "../../../compat/can_rely_on_request_media_key_system_access"; import getEmeApiImplementation from "../../../compat/eme"; import { DUMMY_PLAY_READY_HEADER, generatePlayReadyInitData, } from "../../../compat/generate_init_data"; import log from "./log"; import probeDecodingInfos from "./probers/decodingInfo"; import probeHDCPPolicy from "./probers/HDCPPolicy"; import probeTypeWithFeatures from "./probers/isTypeSupportedWithFeatures"; import probeContentType from "./probers/mediaContentType"; import probeMatchMedia from "./probers/mediaDisplayInfos"; import type { IDisplayConfiguration, IMediaConfiguration, IMediaKeySystemConfiguration, } from "./types"; /** * A set of API to probe media capabilites. * Each API allow to evalute a specific feature (HDCP support, decoding infos, etc) * and relies on different browser API to probe capabilites. */ const mediaCapabilitiesProber = { /** * Set logger level * @param {string} level */ set LogLevel(level: string) { log.setLevel(level, log.getFormat()); }, /** * Get logger level * @returns {string} */ get LogLevel(): string { return log.getLevel(); }, /** * @param {string} keySystemType - Reverse domain name of the wanted key * system. * @param {Array.<MediaKeySystemConfiguration>} keySystemConfiguration - DRM * configuration wanted. * @returns {Promise.<MediaKeySystemConfiguration>} - Resolved the * MediaKeySystemConfiguration actually obtained if the given configuration is * compatible or a rejected Promise if not. */ async checkDrmConfiguration( keySystemType: string, keySystemConfiguration: IMediaKeySystemConfiguration[], ): Promise<MediaKeySystemConfiguration> { const eme = getEmeApiImplementation("auto"); if (eme === null) { const error = new Error("EME not supported in current environment"); throw error; } const mksa = await eme.requestMediaKeySystemAccess( keySystemType, keySystemConfiguration, ); if (!canRelyOnRequestMediaKeySystemAccess(keySystemType)) { try { const mediaKeys = await mksa.createMediaKeys(); const session = mediaKeys.createSession(); const initData = generatePlayReadyInitData(DUMMY_PLAY_READY_HEADER); await session.generateRequest("cenc", initData); session.close().catch(() => { log.warn("MediaCapabilitiesProber", "Failed to close the dummy session"); }); return mksa.getConfiguration(); } catch (err) { log.debug( "MediaCapabilitiesProber", "KeySystemAccess was granted but it is not usable", ); return Promise.reject( new Error( "Failed to generare a license-request with this keySystem: " + (err instanceof Error ? err.toString() : "Unknown Error"), ), ); } } else { return mksa.getConfiguration(); } }, /** * Get HDCP status. Evaluates if current equipement support given * HDCP revision. * @param {string} hdcpVersion - The wanted HDCP version to test (e.g. * `"1.1"`). * @returns {Promise.<string>} - Returns a Promise which rejects if the * browser API we need to rely on unexpectedly fail. * * If they resolve, resolve with one of the following string: * * - `"Supported"`: The HDCP version is probably supported * * - `"NotSupported"`: The HDCP version is probably not supported * * - `"Unknown"`: It is unknown if the HDCP version may be supported or not. */ async getStatusForHDCP(hdcpVersion: string): Promise<string> { if (hdcpVersion === undefined || hdcpVersion.length === 0) { throw new Error("Bad Arguments: No HDCP Policy specified."); } try { const res = await probeTypeWithFeatures({ hdcp: hdcpVersion }); switch (res) { case "NotSupported": case "Supported": return res; case "Unknown": // continue break; } } catch { // We do not care about this call erroring } return probeHDCPPolicy(hdcpVersion); }, /** * Get decoding capabilities from a given video and/or audio * configuration. * TODO check alongside key system. * @param {Object} mediaConfig * @returns {Promise.<string>} */ async getDecodingCapabilities( mediaConfig: IMediaConfiguration, ): Promise<"Supported" | "Unknown" | "NotSupported"> { const config = { type: mediaConfig.type, video: mediaConfig.video, audio: mediaConfig.audio, }; let isCodecSupported = false; try { const status = probeContentType(config); if (status === "Supported") { isCodecSupported = true; } else if (status === "NotSupported") { return "NotSupported"; } } catch (err) { const error = err instanceof Error ? err : new Error("Unknown error"); log.error("MediaCapabilitiesProber", "probeContentType failed", error); } try { const res = await probeTypeWithFeatures(config); if (res === "NotSupported") { return "NotSupported"; } } catch { // We do not care here } try { const res = await probeDecodingInfos(config); return res; } catch { return isCodecSupported ? "Supported" : "Unknown"; } }, /** * Get display capabilites. Tells if display can output * with specific video and/or audio constrains. * TODO I'm sure there's now newer APIs we can use for this (e.g. CSS etc.) * @param {Object} displayConfig * @returns {Promise.<string>} */ async getDisplayCapabilities(displayConfig: IDisplayConfiguration): Promise<string> { const config = { display: displayConfig }; let matchMediaSupported: boolean | undefined; try { const status = probeMatchMedia(config); if (status === "Supported") { matchMediaSupported = true; } else { return "NotSupported"; } } catch { // We do not care here } try { const res = await probeTypeWithFeatures(config); if (res === "NotSupported") { return "NotSupported"; } } catch { // We do not care here } return matchMediaSupported === true ? "Supported" : "Unknown"; }, }; export default mediaCapabilitiesProber;