From 32cd04b87935a14977e16b3d7f0102a4e48a4ac2 Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Wed, 19 Mar 2025 16:58:46 -0700 Subject: [PATCH 01/29] Delete CommonEncryption.js Everything from here is being imported from CML now. So this file can be entirely deleted. --- src/streaming/protection/CommonEncryption.js | 275 ------------------- 1 file changed, 275 deletions(-) delete mode 100644 src/streaming/protection/CommonEncryption.js diff --git a/src/streaming/protection/CommonEncryption.js b/src/streaming/protection/CommonEncryption.js deleted file mode 100644 index c6bbc22f68..0000000000 --- a/src/streaming/protection/CommonEncryption.js +++ /dev/null @@ -1,275 +0,0 @@ -/** - * The copyright in this software is being made available under the BSD License, - * included below. This software may be subject to other third party and contributor - * rights, including patent rights, and no such rights are granted under this license. - * - * Copyright (c) 2013, Dash Industry Forum. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * * Neither the name of Dash Industry Forum nor the names of its - * contributors may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -import DashConstants from '../../dash/constants/DashConstants.js'; -import ProtectionConstants from '../constants/ProtectionConstants.js'; - -const LICENSE_SERVER_MANIFEST_CONFIGURATIONS = { - prefixes: ['clearkey', 'dashif', 'ck'] -}; - -/** - * @class - * @ignore - */ -class CommonEncryption { - /** - * Find and return the ContentProtection element in the given array - * that indicates support for MP4 Common Encryption - * - * @param {Array} cpArray array of content protection elements - * @returns {Object|null} the Common Encryption content protection element or - * null if one was not found - */ - static findMp4ProtectionElement(cpArray) { - let retVal = null; - for (let i = 0; i < cpArray.length; ++i) { - let cp = cpArray[i]; - if (cp.schemeIdUri && cp.schemeIdUri.toLowerCase() === DashConstants.MP4_PROTECTION_SCHEME && cp.value && - (cp.value.toLowerCase() === ProtectionConstants.ENCRYPTION_SCHEME_CENC || cp.value.toLowerCase() === ProtectionConstants.ENCRYPTION_SCHEME_CBCS)) { - retVal = cp; - } - } - return retVal; - } - - /** - * Returns just the data portion of a single PSSH - * - * @param {ArrayBuffer} pssh - the PSSH - * @return {ArrayBuffer} data portion of the PSSH - */ - static getPSSHData(pssh) { - let offset = 8; // Box size and type fields - let view = new DataView(pssh); - - // Read version - let version = view.getUint8(offset); - - offset += 20; // Version (1), flags (3), system ID (16) - - if (version > 0) { - offset += 4 + (16 * view.getUint32(offset)); // Key ID count (4) and All key IDs (16*count) - } - - offset += 4; // Data size - return pssh.slice(offset); - } - - /** - * Returns the PSSH associated with the given key system from the concatenated - * list of PSSH boxes in the given initData - * - * @param {KeySystem} keySystem the desired - * key system - * @param {ArrayBuffer} initData 'cenc' initialization data. Concatenated list of PSSH. - * @returns {ArrayBuffer|null} The PSSH box data corresponding to the given key system, null if not found - * or null if a valid association could not be found. - */ - static getPSSHForKeySystem(keySystem, initData) { - let psshList = CommonEncryption.parsePSSHList(initData); - if (keySystem && psshList.hasOwnProperty(keySystem.uuid.toLowerCase())) { - return psshList[keySystem.uuid.toLowerCase()]; - } - return null; - } - - /** - * Parse a standard common encryption PSSH which contains a simple - * base64-encoding of the init data - * - * @param {Object} cpData the ContentProtection element - * @param {BASE64} BASE64 reference - * @returns {ArrayBuffer|null} the init data or null if not found - */ - static parseInitDataFromContentProtection(cpData, BASE64) { - if ('pssh' in cpData && cpData.pssh) { - - // Remove whitespaces and newlines from pssh text - cpData.pssh.__text = cpData.pssh.__text.replace(/\r?\n|\r/g, '').replace(/\s+/g, ''); - - return BASE64.decodeArray(cpData.pssh.__text).buffer; - } - return null; - } - - /** - * Parses list of PSSH boxes into keysystem-specific PSSH data - * - * @param {ArrayBuffer} data - the concatenated list of PSSH boxes as provided by - * CDM as initialization data when CommonEncryption content is detected - * @returns {Object|Array} an object that has a property named according to each of - * the detected key system UUIDs (e.g. 00000000-0000-0000-0000-0000000000) - * and a ArrayBuffer (the entire PSSH box) as the property value - */ - static parsePSSHList(data) { - - if (data === null || data === undefined) { - return []; - } - - let dv = new DataView(data.buffer || data); // data.buffer first for Uint8Array support - let done = false; - let pssh = {}; - - // TODO: Need to check every data read for end of buffer - let byteCursor = 0; - while (!done) { - - let size, - nextBox, - version, - systemID; - let boxStart = byteCursor; - - if (byteCursor >= dv.buffer.byteLength) { - break; - } - - /* Box size */ - size = dv.getUint32(byteCursor); - nextBox = byteCursor + size; - byteCursor += 4; - - /* Verify PSSH */ - if (dv.getUint32(byteCursor) !== 0x70737368) { - byteCursor = nextBox; - continue; - } - byteCursor += 4; - - /* Version must be 0 or 1 */ - version = dv.getUint8(byteCursor); - if (version !== 0 && version !== 1) { - byteCursor = nextBox; - continue; - } - byteCursor++; - - byteCursor += 3; /* skip flags */ - - // 16-byte UUID/SystemID - systemID = ''; - let i, val; - for (i = 0; i < 4; i++) { - val = dv.getUint8(byteCursor + i).toString(16); - systemID += (val.length === 1) ? '0' + val : val; - } - byteCursor += 4; - systemID += '-'; - for (i = 0; i < 2; i++) { - val = dv.getUint8(byteCursor + i).toString(16); - systemID += (val.length === 1) ? '0' + val : val; - } - byteCursor += 2; - systemID += '-'; - for (i = 0; i < 2; i++) { - val = dv.getUint8(byteCursor + i).toString(16); - systemID += (val.length === 1) ? '0' + val : val; - } - byteCursor += 2; - systemID += '-'; - for (i = 0; i < 2; i++) { - val = dv.getUint8(byteCursor + i).toString(16); - systemID += (val.length === 1) ? '0' + val : val; - } - byteCursor += 2; - systemID += '-'; - for (i = 0; i < 6; i++) { - val = dv.getUint8(byteCursor + i).toString(16); - systemID += (val.length === 1) ? '0' + val : val; - } - byteCursor += 6; - - systemID = systemID.toLowerCase(); - - /* PSSH Data Size */ - byteCursor += 4; - - /* PSSH Data */ - pssh[systemID] = dv.buffer.slice(boxStart, nextBox); - byteCursor = nextBox; - } - - return pssh; - } - - static getLicenseServerUrlFromMediaInfo(mediaInfoArr, schemeIdUri) { - try { - - if (!mediaInfoArr || mediaInfoArr.length === 0) { - return null; - } - - let i = 0; - let licenseServer = null; - - while (i < mediaInfoArr.length && !licenseServer) { - const mediaInfo = mediaInfoArr[i]; - - if (mediaInfo && mediaInfo.contentProtection && mediaInfo.contentProtection.length > 0) { - const targetProtectionData = mediaInfo.contentProtection.filter((cp) => { - return cp.schemeIdUri && cp.schemeIdUri === schemeIdUri; - }); - - if (targetProtectionData && targetProtectionData.length > 0) { - let j = 0; - while (j < targetProtectionData.length && !licenseServer) { - const contentProtection = targetProtectionData[j]; - if (contentProtection.laUrl - && contentProtection.laUrl.__prefix - && LICENSE_SERVER_MANIFEST_CONFIGURATIONS.prefixes.includes(contentProtection.laUrl.__prefix) - && contentProtection.laUrl.__text) { - licenseServer = contentProtection.laUrl.__text; - } - j += 1; - } - } - } - i += 1; - } - return licenseServer; - } catch (e) { - return null; - } - } - - static hexKidToBufferSource(hexKid) { - const cleanedHexKid = hexKid.replace(/-/g, ''); - - const typedArray = new Uint8Array(cleanedHexKid.match(/[\da-f]{2}/gi).map(function (h) { - return parseInt(h, 16) - })) - - return typedArray.buffer - } -} - -export default CommonEncryption; From 5e9a24c9eaa33b32a1803e530dfcaf26f40bbf9a Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Wed, 19 Mar 2025 16:59:42 -0700 Subject: [PATCH 02/29] Update ProtectionController.js import and use the 3 functions from CML --- .../controllers/ProtectionController.js | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/streaming/protection/controllers/ProtectionController.js b/src/streaming/protection/controllers/ProtectionController.js index 64dd9f656a..7398d2700e 100644 --- a/src/streaming/protection/controllers/ProtectionController.js +++ b/src/streaming/protection/controllers/ProtectionController.js @@ -29,7 +29,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -import CommonEncryption from '../CommonEncryption.js'; import MediaCapability from '../vo/MediaCapability.js'; import KeySystemConfiguration from '../vo/KeySystemConfiguration.js'; import ProtectionErrors from '../errors/ProtectionErrors.js'; @@ -42,6 +41,10 @@ import Constants from '../../constants/Constants.js'; import FactoryMaker from '../../../core/FactoryMaker.js'; import ProtectionConstants from '../../constants/ProtectionConstants.js'; +import { getPSSHData } from '@svta/common-media-library/drm/common-encryption/getPSSHData.js'; +import { getPSSHForKeySystem } from '@svta/common-media-library/drm/common-encryption/getPSSHForKeySystem.js'; +import { getLicenseServerUrlFromContentProtection } from '@svta/common-media-library/drm/common-encryption/getLicenseServerUrlFromContentProtection.js'; + const NEEDKEY_BEFORE_INITIALIZE_RETRIES = 5; const NEEDKEY_BEFORE_INITIALIZE_TIMEOUT = 500; @@ -384,7 +387,9 @@ function ProtectionController(config) { return; } - const initDataForKS = CommonEncryption.getPSSHForKeySystem(selectedKeySystem, keySystemMetadata ? keySystemMetadata.initData : null); + const initDataForKS = getPSSHForKeySystem(selectedKeySystem, keySystemMetadata ? keySystemMetadata.initData : null); + console.log('XXX - initDataForKS from createKeySession: ', initDataForKS); + if (initDataForKS) { // Check for duplicate initData @@ -966,11 +971,22 @@ function ProtectionController(config) { // No url provided by the app. Check the manifest and the pssh else { // Check for url defined in the manifest - url = CommonEncryption.getLicenseServerUrlFromMediaInfo(mediaInfoArr, selectedKeySystem.schemeIdURI); + if (Array.isArray(mediaInfoArr) && mediaInfoArr.length > 0) { + for (const mediaInfo of mediaInfoArr) { + const contentProtection = mediaInfo.contentProtection; + + if (Array.isArray(contentProtection)) { + url = getLicenseServerUrlFromContentProtection(contentProtection, selectedKeySystem.schemeIdURI); + if (url) { + break; + } + } + } + } // In case we are not using Clearky we can still get a url from the pssh. if (!url && !protectionKeyController.isClearKey(selectedKeySystem)) { - const psshData = CommonEncryption.getPSSHData(sessionToken.initData); + const psshData = getPSSHData(sessionToken.initData); url = selectedKeySystem.getLicenseServerURLFromInitData(psshData); // Still no url, check the keymessage @@ -1082,7 +1098,8 @@ function ProtectionController(config) { // If key system has already been selected and initData already seen, then do nothing if (selectedKeySystem) { - const initDataForKS = CommonEncryption.getPSSHForKeySystem(selectedKeySystem, abInitData); + const initDataForKS = getPSSHForKeySystem(selectedKeySystem, abInitData); + console.log('XXX - initDataForKS from _onNeedKey: ', initDataForKS); if (initDataForKS) { // Check for duplicate initData if (_isInitDataDuplicate(initDataForKS)) { From a8d52689fa9a3391e49ad1b3da4b79396be20f21 Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Wed, 19 Mar 2025 17:00:23 -0700 Subject: [PATCH 03/29] Update ProtectionKeyController.js Import and call CML equivalent of these 2 functions --- .../protection/controllers/ProtectionKeyController.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/streaming/protection/controllers/ProtectionKeyController.js b/src/streaming/protection/controllers/ProtectionKeyController.js index 2d06c7a4ff..2e9a23217e 100644 --- a/src/streaming/protection/controllers/ProtectionKeyController.js +++ b/src/streaming/protection/controllers/ProtectionKeyController.js @@ -28,7 +28,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -import CommonEncryption from './../CommonEncryption.js'; import KeySystemClearKey from './../drm/KeySystemClearKey.js'; import KeySystemW3CClearKey from './../drm/KeySystemW3CClearKey.js'; import KeySystemWidevine from './../drm/KeySystemWidevine.js'; @@ -41,6 +40,9 @@ import ProtectionConstants from '../../constants/ProtectionConstants.js'; import FactoryMaker from '../../../core/FactoryMaker.js'; import KeySystemMetadata from '../vo/KeySystemMetadata.js'; +import { findCencContentProtection } from '@svta/common-media-library/drm/common-encryption/findCencContentProtection.js'; +import { parsePSSHList } from '@svta/common-media-library/drm/common-encryption/parsePSSHList.js'; + /** * @module ProtectionKeyController * @ignore @@ -216,7 +218,7 @@ function ProtectionKeyController() { return supportedKS } - const mp4ProtectionElement = CommonEncryption.findMp4ProtectionElement(contentProtectionElements); + const mp4ProtectionElement = findCencContentProtection(contentProtectionElements); for (ksIdx = 0; ksIdx < keySystems.length; ksIdx++) { keySystem = keySystems[ksIdx]; @@ -268,7 +270,9 @@ function ProtectionKeyController() { */ function getSupportedKeySystemsFromSegmentPssh(initData, protDataSet, sessionType) { let supportedKS = []; - let pssh = CommonEncryption.parsePSSHList(initData); + console.log('XXX - getSupportedKeySystemsFromSegmentPssh', initData); + let pssh = parsePSSHList(initData); + console.log('XXX - pssh', pssh); let ks, keySystemString; for (let ksIdx = 0; ksIdx < keySystems.length; ++ksIdx) { From ad81972988920f29ae552c404ef7daf780a2d271 Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Wed, 19 Mar 2025 17:00:57 -0700 Subject: [PATCH 04/29] Update KeySystemClearKey.js Call CML's parseInitDataFromContentProtection --- src/streaming/protection/drm/KeySystemClearKey.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/streaming/protection/drm/KeySystemClearKey.js b/src/streaming/protection/drm/KeySystemClearKey.js index d0bb323ec6..24b77ae778 100644 --- a/src/streaming/protection/drm/KeySystemClearKey.js +++ b/src/streaming/protection/drm/KeySystemClearKey.js @@ -31,7 +31,6 @@ import KeyPair from '../vo/KeyPair.js'; import ClearKeyKeySet from '../vo/ClearKeyKeySet.js'; -import CommonEncryption from '../CommonEncryption.js'; import ProtectionConstants from '../../constants/ProtectionConstants.js'; import FactoryMaker from '../../../core/FactoryMaker.js'; @@ -39,6 +38,8 @@ const uuid = ProtectionConstants.CLEARKEY_UUID; const systemString = ProtectionConstants.CLEARKEY_KEYSTEM_STRING; const schemeIdURI = 'urn:uuid:' + uuid; +import { parseInitDataFromContentProtection } from '@svta/common-media-library/drm/common-encryption/parseInitDataFromContentProtection.js'; + function KeySystemClearKey(config) { config = config || {}; @@ -78,7 +79,7 @@ function KeySystemClearKey(config) { function getInitData(cp, cencContentProtection) { try { - let initData = CommonEncryption.parseInitDataFromContentProtection(cp, BASE64); + let initData = parseInitDataFromContentProtection(cp, BASE64); if (!initData && cencContentProtection) { const cencDefaultKid = cencDefaultKidToBase64Representation(cencContentProtection.cencDefaultKid); From a41512fbeb4bb7bbf44dfd5ba44af5bd16b768a8 Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Wed, 19 Mar 2025 17:01:10 -0700 Subject: [PATCH 05/29] Update KeySystemPlayReady.js Call CML's parseInitDataFromContentProtection --- src/streaming/protection/drm/KeySystemPlayReady.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/streaming/protection/drm/KeySystemPlayReady.js b/src/streaming/protection/drm/KeySystemPlayReady.js index 62f6a58805..23c410bec3 100644 --- a/src/streaming/protection/drm/KeySystemPlayReady.js +++ b/src/streaming/protection/drm/KeySystemPlayReady.js @@ -35,10 +35,9 @@ * @class * @implements KeySystem */ -import CommonEncryption from '../CommonEncryption.js'; import ProtectionConstants from '../../constants/ProtectionConstants.js'; import FactoryMaker from '../../../core/FactoryMaker.js'; - +import { parseInitDataFromContentProtection } from '@svta/common-media-library/drm/common-encryption/parseInitDataFromContentProtection.js'; const uuid = ProtectionConstants.PLAYREADY_UUID; const systemString = ProtectionConstants.PLAYREADY_KEYSTEM_STRING; const schemeIdURI = 'urn:uuid:' + uuid; @@ -199,7 +198,7 @@ function KeySystemPlayReady(config) { } // Handle common encryption PSSH if ('pssh' in cpData && cpData.pssh) { - return CommonEncryption.parseInitDataFromContentProtection(cpData, BASE64); + return parseInitDataFromContentProtection(cpData, BASE64); } // Handle native MS PlayReady ContentProtection elements if ('pro' in cpData && cpData.pro) { From bac404705da5bfbca56f4a3c39b349a5e5355bd2 Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Wed, 19 Mar 2025 17:01:22 -0700 Subject: [PATCH 06/29] Update KeySystemW3CClearKey.js Call CML's parseInitDataFromContentProtection --- src/streaming/protection/drm/KeySystemW3CClearKey.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/streaming/protection/drm/KeySystemW3CClearKey.js b/src/streaming/protection/drm/KeySystemW3CClearKey.js index c4b8780bcd..8c6ac2ae7d 100644 --- a/src/streaming/protection/drm/KeySystemW3CClearKey.js +++ b/src/streaming/protection/drm/KeySystemW3CClearKey.js @@ -31,9 +31,9 @@ import KeyPair from '../vo/KeyPair.js'; import ClearKeyKeySet from '../vo/ClearKeyKeySet.js'; -import CommonEncryption from '../CommonEncryption.js'; import ProtectionConstants from '../../constants/ProtectionConstants.js'; import FactoryMaker from '../../../core/FactoryMaker.js'; +import { parseInitDataFromContentProtection } from '@svta/common-media-library/drm/common-encryption/parseInitDataFromContentProtection.js'; const uuid = ProtectionConstants.W3C_CLEARKEY_UUID; const systemString = ProtectionConstants.CLEARKEY_KEYSTEM_STRING; @@ -77,7 +77,7 @@ function KeySystemW3CClearKey(config) { } function getInitData(cp) { - return CommonEncryption.parseInitDataFromContentProtection(cp, BASE64); + return parseInitDataFromContentProtection(cp, BASE64); } function getRequestHeadersFromMessage(/*message*/) { From 258a83e408e39483a66f428b4a78c06d89fb2c9b Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Wed, 19 Mar 2025 17:01:37 -0700 Subject: [PATCH 07/29] Update KeySystemWidevine.js Call CML's parseInitDataFromContentProtection --- src/streaming/protection/drm/KeySystemWidevine.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/streaming/protection/drm/KeySystemWidevine.js b/src/streaming/protection/drm/KeySystemWidevine.js index 0bc77ec49f..f01815c30f 100644 --- a/src/streaming/protection/drm/KeySystemWidevine.js +++ b/src/streaming/protection/drm/KeySystemWidevine.js @@ -36,9 +36,9 @@ * @implements MediaPlayer.dependencies.protection.KeySystem */ -import CommonEncryption from '../CommonEncryption.js'; import ProtectionConstants from '../../constants/ProtectionConstants.js'; import FactoryMaker from '../../../core/FactoryMaker.js'; +import { parseInitDataFromContentProtection } from '@svta/common-media-library/drm/common-encryption/parseInitDataFromContentProtection.js'; const uuid = ProtectionConstants.WIDEVINE_UUID; const systemString = ProtectionConstants.WIDEVINE_KEYSTEM_STRING; @@ -51,7 +51,7 @@ function KeySystemWidevine(config) { const BASE64 = config.BASE64; function getInitData(cp) { - return CommonEncryption.parseInitDataFromContentProtection(cp, BASE64); + return parseInitDataFromContentProtection(cp, BASE64); } function getRequestHeadersFromMessage( /*message*/ ) { From 44ff2f650cde7ca9f6aea1c7d7ad1ed76d80fa44 Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Wed, 19 Mar 2025 17:01:55 -0700 Subject: [PATCH 08/29] Delete streaming.protection.CommonEncryption.js These tests are no longer needed --- .../streaming.protection.CommonEncryption.js | 139 ------------------ 1 file changed, 139 deletions(-) delete mode 100644 test/unit/test/streaming/streaming.protection.CommonEncryption.js diff --git a/test/unit/test/streaming/streaming.protection.CommonEncryption.js b/test/unit/test/streaming/streaming.protection.CommonEncryption.js deleted file mode 100644 index 54b6c4ce1c..0000000000 --- a/test/unit/test/streaming/streaming.protection.CommonEncryption.js +++ /dev/null @@ -1,139 +0,0 @@ -import CommonEncryption from '../../../../src/streaming/protection/CommonEncryption.js'; -import Base64 from '../../../../externals/base64.js'; - -import {expect} from 'chai'; - -let cpData; - -describe('CommonEncryption', () => { - - beforeEach(() => { - cpData = { - 'pssh': { - '__text': 'AAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARABGgZlbHV2aW8iBmVsdXZpbw==' - }, - 'value': 'Widevine', - 'schemeIdUri': 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed', - 'KID': null - }; - }); - - describe('parseInitDataFromContentProtection', () => { - - it('should return null if no init data is available in the ContentProtection element', () => { - cpData = {}; - const result = CommonEncryption.parseInitDataFromContentProtection(cpData, Base64); - - expect(result).to.be.null; // jshint ignore:line - }); - - it('should return base64 decoded string if init data is available in the ContentProtection element', () => { - const result = CommonEncryption.parseInitDataFromContentProtection(cpData, Base64); - const expectedByteLength = Base64.decodeArray(cpData.pssh.__text).buffer.byteLength; - - expect(result.byteLength).to.equal(expectedByteLength); - }); - - it('should remove newlines and return base64 decoded string if init data is available in the ContentProtection element', () => { - const expectedByteLength = Base64.decodeArray(cpData.pssh.__text).buffer.byteLength; - cpData.pssh.__text = '\nAAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARABGgZlbHV2aW8iBmVsdXZpbw==\n'; - const originalByteLength = Base64.decodeArray(cpData.pssh.__text).buffer.byteLength; - const result = CommonEncryption.parseInitDataFromContentProtection(cpData, Base64); - - expect(originalByteLength).to.not.equal(result.byteLength); - expect(result.byteLength).to.equal(expectedByteLength); - }); - - it('should remove whitespaces and return base64 decoded string if init data is available in the ContentProtection element', () => { - const expectedByteLength = Base64.decodeArray(cpData.pssh.__text).buffer.byteLength; - cpData.pssh.__text = 'AAAANHBzc2gAAAAA7e+LqXnWSs6jy Cfc1R0h7QAAABQIARABGgZlbHV2aW8iBmVsdXZpbw=='; - const originalByteLength = Base64.decodeArray(cpData.pssh.__text).buffer.byteLength; - const result = CommonEncryption.parseInitDataFromContentProtection(cpData, Base64); - - expect(originalByteLength).to.not.equal(result.byteLength); - expect(result.byteLength).to.equal(expectedByteLength); - }); - - it('should remove whitespaces and newlines and return base64 decoded string if init data is available in the ContentProtection element', () => { - const expectedByteLength = Base64.decodeArray(cpData.pssh.__text).buffer.byteLength; - cpData.pssh.__text = '\n\n\nAAAANHBzc2gAAAAA7e+LqXnWSs6jy Cfc1R0h7QAAABQIARABGgZlbHV2aW8iBmVsdXZpbw==\n\n'; - const originalByteLength = Base64.decodeArray(cpData.pssh.__text).buffer.byteLength; - const result = CommonEncryption.parseInitDataFromContentProtection(cpData, Base64); - - expect(originalByteLength).to.not.equal(result.byteLength); - expect(result.byteLength).to.equal(expectedByteLength); - }); - - }); - - describe('getLicenseServerUrlFromMediaInfo', () => { - let mediaInfo; - let schemeIdUri = 'abcd-efgh'; - - beforeEach(() => { - mediaInfo = [{ - contentProtection: [ - { - schemeIdUri: schemeIdUri, - laUrl: { - __prefix: 'dashif', - __text: 'license-server-url' - } - } - ] - }] - }); - - afterEach(() => { - mediaInfo = null; - }) - - it('should return null in case the schemeIdUri does not match', () => { - const result = CommonEncryption.getLicenseServerUrlFromMediaInfo(mediaInfo, 'nomatch'); - - expect(result).to.be.null; - }); - - it('should return null if license server url is empty', () => { - mediaInfo[0].contentProtection[0].laUrl.__text = ''; - const result = CommonEncryption.getLicenseServerUrlFromMediaInfo(mediaInfo, schemeIdUri); - - expect(result).to.be.null; - }) - - it('should return null if wrong prefix', () => { - mediaInfo[0].contentProtection[0].laUrl.__prefix = 'wrongprefix'; - const result = CommonEncryption.getLicenseServerUrlFromMediaInfo(mediaInfo, schemeIdUri); - - expect(result).to.be.null; - }) - - it('should return null if wrong attribute', () => { - delete mediaInfo[0].contentProtection[0].laUrl; - const result = CommonEncryption.getLicenseServerUrlFromMediaInfo(mediaInfo, schemeIdUri); - - expect(result).to.be.null; - }) - - it('should return valid license server for dashif:laurl', () => { - const result = CommonEncryption.getLicenseServerUrlFromMediaInfo(mediaInfo, schemeIdUri); - - expect(result).to.be.equal('license-server-url'); - }) - - it('should return valid license server for clearkey:laurl', () => { - mediaInfo[0].contentProtection[0].__prefix = 'clearkey' - const result = CommonEncryption.getLicenseServerUrlFromMediaInfo(mediaInfo, schemeIdUri); - - expect(result).to.be.equal('license-server-url'); - }) - - it('should return valid license server for ck:laurl', () => { - mediaInfo[0].contentProtection[0].__prefix = 'ck' - const result = CommonEncryption.getLicenseServerUrlFromMediaInfo(mediaInfo, schemeIdUri); - - expect(result).to.be.equal('license-server-url'); - }) - - }); -}) From 01d4fe0a44c8662db8b04feca99ab4408015e4ea Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Wed, 19 Mar 2025 17:03:01 -0700 Subject: [PATCH 09/29] Update package.json Needed to update core-js, because CML library depends on it --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2d0408dcf2..2fc92d1842 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "chai": "^4.4.1", "chai-spies": "^1.1.0", "clean-jsdoc-theme": "^4.2.17", - "core-js": "^3.39.0", + "core-js": "^3.41.0", "eslint": "^9.13.0", "eslint-webpack-plugin": "^4.2.0", "globals": "^15.11.0", From 8d4f1cb2ddc4877b825ce79660b71616e87e6d12 Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Wed, 19 Mar 2025 17:03:15 -0700 Subject: [PATCH 10/29] Update package-lock.json Needed to update core-js, because CML library depends on it --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 36f585f4d3..dae7e43306 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "dashjs", - "version": "5.0.0", + "version": "5.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "dashjs", - "version": "5.0.0", + "version": "5.0.1", "license": "BSD-3-Clause", "dependencies": { "@svta/common-media-library": "^0.7.4", @@ -33,7 +33,7 @@ "chai": "^4.4.1", "chai-spies": "^1.1.0", "clean-jsdoc-theme": "^4.2.17", - "core-js": "^3.39.0", + "core-js": "^3.41.0", "eslint": "^9.13.0", "eslint-webpack-plugin": "^4.2.0", "globals": "^15.11.0", @@ -4190,9 +4190,9 @@ "dev": true }, "node_modules/core-js": { - "version": "3.39.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.39.0.tgz", - "integrity": "sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==", + "version": "3.41.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.41.0.tgz", + "integrity": "sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA==", "dev": true, "hasInstallScript": true, "funding": { From dcc729f8a08e420d910334e1ae65f93901e04c19 Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Wed, 19 Mar 2025 17:19:18 -0700 Subject: [PATCH 11/29] Update index.d.ts --- index.d.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/index.d.ts b/index.d.ts index 38716dde55..8673cec0f1 100644 --- a/index.d.ts +++ b/index.d.ts @@ -4636,10 +4636,6 @@ declare namespace dashjs { VIDEO_ELEMENT_SELECTED: 'videoElementSelected'; } - export interface CommonEncryption { - // Does not export anything - } - export interface Protection { createProtectionSystem(config: object): void; } From e6017d23d77817d99a60934c187c3e1347e15938 Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Wed, 19 Mar 2025 17:19:42 -0700 Subject: [PATCH 12/29] Revert "Delete streaming.protection.CommonEncryption.js" This reverts commit 44ff2f650cde7ca9f6aea1c7d7ad1ed76d80fa44. --- .../streaming.protection.CommonEncryption.js | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 test/unit/test/streaming/streaming.protection.CommonEncryption.js diff --git a/test/unit/test/streaming/streaming.protection.CommonEncryption.js b/test/unit/test/streaming/streaming.protection.CommonEncryption.js new file mode 100644 index 0000000000..54b6c4ce1c --- /dev/null +++ b/test/unit/test/streaming/streaming.protection.CommonEncryption.js @@ -0,0 +1,139 @@ +import CommonEncryption from '../../../../src/streaming/protection/CommonEncryption.js'; +import Base64 from '../../../../externals/base64.js'; + +import {expect} from 'chai'; + +let cpData; + +describe('CommonEncryption', () => { + + beforeEach(() => { + cpData = { + 'pssh': { + '__text': 'AAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARABGgZlbHV2aW8iBmVsdXZpbw==' + }, + 'value': 'Widevine', + 'schemeIdUri': 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed', + 'KID': null + }; + }); + + describe('parseInitDataFromContentProtection', () => { + + it('should return null if no init data is available in the ContentProtection element', () => { + cpData = {}; + const result = CommonEncryption.parseInitDataFromContentProtection(cpData, Base64); + + expect(result).to.be.null; // jshint ignore:line + }); + + it('should return base64 decoded string if init data is available in the ContentProtection element', () => { + const result = CommonEncryption.parseInitDataFromContentProtection(cpData, Base64); + const expectedByteLength = Base64.decodeArray(cpData.pssh.__text).buffer.byteLength; + + expect(result.byteLength).to.equal(expectedByteLength); + }); + + it('should remove newlines and return base64 decoded string if init data is available in the ContentProtection element', () => { + const expectedByteLength = Base64.decodeArray(cpData.pssh.__text).buffer.byteLength; + cpData.pssh.__text = '\nAAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARABGgZlbHV2aW8iBmVsdXZpbw==\n'; + const originalByteLength = Base64.decodeArray(cpData.pssh.__text).buffer.byteLength; + const result = CommonEncryption.parseInitDataFromContentProtection(cpData, Base64); + + expect(originalByteLength).to.not.equal(result.byteLength); + expect(result.byteLength).to.equal(expectedByteLength); + }); + + it('should remove whitespaces and return base64 decoded string if init data is available in the ContentProtection element', () => { + const expectedByteLength = Base64.decodeArray(cpData.pssh.__text).buffer.byteLength; + cpData.pssh.__text = 'AAAANHBzc2gAAAAA7e+LqXnWSs6jy Cfc1R0h7QAAABQIARABGgZlbHV2aW8iBmVsdXZpbw=='; + const originalByteLength = Base64.decodeArray(cpData.pssh.__text).buffer.byteLength; + const result = CommonEncryption.parseInitDataFromContentProtection(cpData, Base64); + + expect(originalByteLength).to.not.equal(result.byteLength); + expect(result.byteLength).to.equal(expectedByteLength); + }); + + it('should remove whitespaces and newlines and return base64 decoded string if init data is available in the ContentProtection element', () => { + const expectedByteLength = Base64.decodeArray(cpData.pssh.__text).buffer.byteLength; + cpData.pssh.__text = '\n\n\nAAAANHBzc2gAAAAA7e+LqXnWSs6jy Cfc1R0h7QAAABQIARABGgZlbHV2aW8iBmVsdXZpbw==\n\n'; + const originalByteLength = Base64.decodeArray(cpData.pssh.__text).buffer.byteLength; + const result = CommonEncryption.parseInitDataFromContentProtection(cpData, Base64); + + expect(originalByteLength).to.not.equal(result.byteLength); + expect(result.byteLength).to.equal(expectedByteLength); + }); + + }); + + describe('getLicenseServerUrlFromMediaInfo', () => { + let mediaInfo; + let schemeIdUri = 'abcd-efgh'; + + beforeEach(() => { + mediaInfo = [{ + contentProtection: [ + { + schemeIdUri: schemeIdUri, + laUrl: { + __prefix: 'dashif', + __text: 'license-server-url' + } + } + ] + }] + }); + + afterEach(() => { + mediaInfo = null; + }) + + it('should return null in case the schemeIdUri does not match', () => { + const result = CommonEncryption.getLicenseServerUrlFromMediaInfo(mediaInfo, 'nomatch'); + + expect(result).to.be.null; + }); + + it('should return null if license server url is empty', () => { + mediaInfo[0].contentProtection[0].laUrl.__text = ''; + const result = CommonEncryption.getLicenseServerUrlFromMediaInfo(mediaInfo, schemeIdUri); + + expect(result).to.be.null; + }) + + it('should return null if wrong prefix', () => { + mediaInfo[0].contentProtection[0].laUrl.__prefix = 'wrongprefix'; + const result = CommonEncryption.getLicenseServerUrlFromMediaInfo(mediaInfo, schemeIdUri); + + expect(result).to.be.null; + }) + + it('should return null if wrong attribute', () => { + delete mediaInfo[0].contentProtection[0].laUrl; + const result = CommonEncryption.getLicenseServerUrlFromMediaInfo(mediaInfo, schemeIdUri); + + expect(result).to.be.null; + }) + + it('should return valid license server for dashif:laurl', () => { + const result = CommonEncryption.getLicenseServerUrlFromMediaInfo(mediaInfo, schemeIdUri); + + expect(result).to.be.equal('license-server-url'); + }) + + it('should return valid license server for clearkey:laurl', () => { + mediaInfo[0].contentProtection[0].__prefix = 'clearkey' + const result = CommonEncryption.getLicenseServerUrlFromMediaInfo(mediaInfo, schemeIdUri); + + expect(result).to.be.equal('license-server-url'); + }) + + it('should return valid license server for ck:laurl', () => { + mediaInfo[0].contentProtection[0].__prefix = 'ck' + const result = CommonEncryption.getLicenseServerUrlFromMediaInfo(mediaInfo, schemeIdUri); + + expect(result).to.be.equal('license-server-url'); + }) + + }); +}) From fe1a15675d01883c804d2e10a2f04cd5dd383d9a Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Thu, 20 Mar 2025 17:29:04 -0700 Subject: [PATCH 13/29] Update MssParser.js --- src/mss/parser/MssParser.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/mss/parser/MssParser.js b/src/mss/parser/MssParser.js index efcd799b02..fd818cf45f 100644 --- a/src/mss/parser/MssParser.js +++ b/src/mss/parser/MssParser.js @@ -37,7 +37,12 @@ import BigInt from '../../../externals/BigInteger.js'; import FactoryMaker from '../../core/FactoryMaker.js'; -import ProtectionConstants from '../../streaming/constants/ProtectionConstants.js'; + +// imports from common-media-library +import { PLAYREADY_UUID } from '@svta/common-media-library/drm/common/const/PLAYREADY_UUID.js'; +import { WIDEVINE_UUID } from '@svta/common-media-library/drm/common/const/WIDEVINE_UUID.js'; +import { WIDEVINE_KEY_SYSTEM } from '@svta/common-media-library/drm/common/const/WIDEVINE_KEY_SYSTEM.js'; +import { PLAYREADY_KEY_SYSTEM } from '@svta/common-media-library/drm/common/const/PLAYREADY_KEY_SYSTEM.js'; function MssParser(config) { config = config || {}; @@ -532,16 +537,16 @@ function MssParser(config) { __prefix: 'mspr' }; return { - schemeIdUri: 'urn:uuid:' + ProtectionConstants.PLAYREADY_UUID, - value: ProtectionConstants.PLAYREADY_KEYSTEM_STRING, + schemeIdUri: 'urn:uuid:' + PLAYREADY_UUID, + value: PLAYREADY_KEY_SYSTEM, pro: pro }; } function createWidevineContentProtection(KID) { let widevineCP = { - schemeIdUri: 'urn:uuid:' + ProtectionConstants.WIDEVINE_UUID, - value: ProtectionConstants.WIDEVINE_KEYSTEM_STRING + schemeIdUri: 'urn:uuid:' + WIDEVINE_UUID, + value: WIDEVINE_KEY_SYSTEM }; if (!KID) { return widevineCP; From bc65a84e80e3b271a6e310b0a93fd230da58f7d8 Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Thu, 20 Mar 2025 17:29:21 -0700 Subject: [PATCH 14/29] Update ProtectionKeyController.js --- .../controllers/ProtectionKeyController.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/streaming/protection/controllers/ProtectionKeyController.js b/src/streaming/protection/controllers/ProtectionKeyController.js index 2e9a23217e..1ec0ce9863 100644 --- a/src/streaming/protection/controllers/ProtectionKeyController.js +++ b/src/streaming/protection/controllers/ProtectionKeyController.js @@ -36,12 +36,16 @@ import DRMToday from './../servers/DRMToday.js'; import PlayReady from './../servers/PlayReady.js'; import Widevine from './../servers/Widevine.js'; import ClearKey from './../servers/ClearKey.js'; -import ProtectionConstants from '../../constants/ProtectionConstants.js'; import FactoryMaker from '../../../core/FactoryMaker.js'; import KeySystemMetadata from '../vo/KeySystemMetadata.js'; +// imports from common-media-library import { findCencContentProtection } from '@svta/common-media-library/drm/common-encryption/findCencContentProtection.js'; import { parsePSSHList } from '@svta/common-media-library/drm/common-encryption/parsePSSHList.js'; +import { MEDIA_KEY_MESSAGE_TYPES } from '@svta/common-media-library/drm/common/const/MEDIA_KEY_MESSAGE_TYPES.js'; +import { WIDEVINE_KEY_SYSTEM } from '@svta/common-media-library/drm/common/const/WIDEVINE_KEY_SYSTEM.js'; +import { PLAYREADY_KEY_SYSTEM } from '@svta/common-media-library/drm/common/const/PLAYREADY_KEY_SYSTEM.js'; +import { CLEAR_KEY_SYSTEM } from '@svta/common-media-library/drm/common/const/CLEAR_KEY_SYSTEM.js'; /** * @module ProtectionKeyController @@ -317,18 +321,18 @@ function ProtectionKeyController() { // Our default server implementations do not do anything with "license-release" or // "individualization-request" messages, so we just send a success event - if (messageType === ProtectionConstants.MEDIA_KEY_MESSAGE_TYPES.LICENSE_RELEASE || messageType === ProtectionConstants.MEDIA_KEY_MESSAGE_TYPES.INDIVIDUALIZATION_REQUEST) { + if (messageType === MEDIA_KEY_MESSAGE_TYPES.LICENSE_RELEASE || messageType === MEDIA_KEY_MESSAGE_TYPES.INDIVIDUALIZATION_REQUEST) { return null; } let licenseServerData = null; if (protData && protData.hasOwnProperty('drmtoday')) { licenseServerData = DRMToday(context).getInstance({BASE64: BASE64}); - } else if (keySystem.systemString === ProtectionConstants.WIDEVINE_KEYSTEM_STRING) { + } else if (keySystem.systemString === WIDEVINE_KEY_SYSTEM) { licenseServerData = Widevine(context).getInstance(); - } else if (keySystem.systemString === ProtectionConstants.PLAYREADY_KEYSTEM_STRING) { + } else if (keySystem.systemString === PLAYREADY_KEY_SYSTEM) { licenseServerData = PlayReady(context).getInstance(); - } else if (keySystem.systemString === ProtectionConstants.CLEARKEY_KEYSTEM_STRING) { + } else if (keySystem.systemString === CLEAR_KEY_SYSTEM) { licenseServerData = ClearKey(context).getInstance(); } From 0e36109e76a3293e769cf961eb960801ffa445cb Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Thu, 20 Mar 2025 17:29:44 -0700 Subject: [PATCH 15/29] Update KeySystemClearKey.js --- src/streaming/protection/drm/KeySystemClearKey.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/streaming/protection/drm/KeySystemClearKey.js b/src/streaming/protection/drm/KeySystemClearKey.js index 24b77ae778..52b5a878d1 100644 --- a/src/streaming/protection/drm/KeySystemClearKey.js +++ b/src/streaming/protection/drm/KeySystemClearKey.js @@ -31,11 +31,14 @@ import KeyPair from '../vo/KeyPair.js'; import ClearKeyKeySet from '../vo/ClearKeyKeySet.js'; -import ProtectionConstants from '../../constants/ProtectionConstants.js'; import FactoryMaker from '../../../core/FactoryMaker.js'; -const uuid = ProtectionConstants.CLEARKEY_UUID; -const systemString = ProtectionConstants.CLEARKEY_KEYSTEM_STRING; +// imports from common-media-library +import { CLEAR_KEY_SYSTEM } from '@svta/common-media-library/drm/common/const/CLEAR_KEY_SYSTEM.js'; +import { CLEAR_KEY_UUID } from '@svta/common-media-library/drm/common/const/CLEAR_KEY_UUID.js'; + +const uuid = CLEAR_KEY_UUID; +const systemString = CLEAR_KEY_SYSTEM; const schemeIdURI = 'urn:uuid:' + uuid; import { parseInitDataFromContentProtection } from '@svta/common-media-library/drm/common-encryption/parseInitDataFromContentProtection.js'; From 6b3e21d89653d650a68eb665ec355e8a28b99809 Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Thu, 20 Mar 2025 17:29:54 -0700 Subject: [PATCH 16/29] Update KeySystemPlayReady.js --- src/streaming/protection/drm/KeySystemPlayReady.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/streaming/protection/drm/KeySystemPlayReady.js b/src/streaming/protection/drm/KeySystemPlayReady.js index 23c410bec3..cf8e96c5b6 100644 --- a/src/streaming/protection/drm/KeySystemPlayReady.js +++ b/src/streaming/protection/drm/KeySystemPlayReady.js @@ -35,11 +35,14 @@ * @class * @implements KeySystem */ -import ProtectionConstants from '../../constants/ProtectionConstants.js'; + import FactoryMaker from '../../../core/FactoryMaker.js'; import { parseInitDataFromContentProtection } from '@svta/common-media-library/drm/common-encryption/parseInitDataFromContentProtection.js'; -const uuid = ProtectionConstants.PLAYREADY_UUID; -const systemString = ProtectionConstants.PLAYREADY_KEYSTEM_STRING; +import { PLAYREADY_UUID } from '@svta/common-media-library/drm/common/const/PLAYREADY_UUID.js'; +import { PLAYREADY_KEY_SYSTEM } from '@svta/common-media-library/drm/common/const/PLAYREADY_KEY_SYSTEM.js'; + +const uuid = PLAYREADY_UUID; +const systemString = PLAYREADY_KEY_SYSTEM; const schemeIdURI = 'urn:uuid:' + uuid; const PRCDMData = '%CUSTOMDATA%'; From 34c87bc65eae1ff63a9295fc4942bc1ead18bceb Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Thu, 20 Mar 2025 17:30:49 -0700 Subject: [PATCH 17/29] Update KeySystemW3CClearKey.js --- src/streaming/protection/drm/KeySystemW3CClearKey.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/streaming/protection/drm/KeySystemW3CClearKey.js b/src/streaming/protection/drm/KeySystemW3CClearKey.js index 8c6ac2ae7d..e1692b3ca6 100644 --- a/src/streaming/protection/drm/KeySystemW3CClearKey.js +++ b/src/streaming/protection/drm/KeySystemW3CClearKey.js @@ -31,12 +31,15 @@ import KeyPair from '../vo/KeyPair.js'; import ClearKeyKeySet from '../vo/ClearKeyKeySet.js'; -import ProtectionConstants from '../../constants/ProtectionConstants.js'; import FactoryMaker from '../../../core/FactoryMaker.js'; import { parseInitDataFromContentProtection } from '@svta/common-media-library/drm/common-encryption/parseInitDataFromContentProtection.js'; -const uuid = ProtectionConstants.W3C_CLEARKEY_UUID; -const systemString = ProtectionConstants.CLEARKEY_KEYSTEM_STRING; +// imports from common-media-library +import { CLEAR_KEY_UUID } from '@svta/common-media-library/drm/common/const/CLEAR_KEY_UUID.js'; +import { CLEAR_KEY_SYSTEM } from '@svta/common-media-library/drm/common/const/CLEAR_KEY_SYSTEM.js'; + +const uuid = CLEAR_KEY_UUID; +const systemString = CLEAR_KEY_SYSTEM; const schemeIdURI = 'urn:uuid:' + uuid; function KeySystemW3CClearKey(config) { From d20f23d8a46eb1a00ea999d4898862c33865441b Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Thu, 20 Mar 2025 17:30:58 -0700 Subject: [PATCH 18/29] Update KeySystemWidevine.js --- src/streaming/protection/drm/KeySystemWidevine.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/streaming/protection/drm/KeySystemWidevine.js b/src/streaming/protection/drm/KeySystemWidevine.js index f01815c30f..23f5b8c64c 100644 --- a/src/streaming/protection/drm/KeySystemWidevine.js +++ b/src/streaming/protection/drm/KeySystemWidevine.js @@ -36,12 +36,15 @@ * @implements MediaPlayer.dependencies.protection.KeySystem */ -import ProtectionConstants from '../../constants/ProtectionConstants.js'; import FactoryMaker from '../../../core/FactoryMaker.js'; import { parseInitDataFromContentProtection } from '@svta/common-media-library/drm/common-encryption/parseInitDataFromContentProtection.js'; -const uuid = ProtectionConstants.WIDEVINE_UUID; -const systemString = ProtectionConstants.WIDEVINE_KEYSTEM_STRING; +// imports from common-media-library +import { WIDEVINE_UUID } from '@svta/common-media-library/drm/common/const/WIDEVINE_UUID.js'; +import { WIDEVINE_KEY_SYSTEM } from '@svta/common-media-library/drm/common/const/WIDEVINE_KEY_SYSTEM.js'; + +const uuid = WIDEVINE_UUID; +const systemString = WIDEVINE_KEY_SYSTEM; const schemeIdURI = 'urn:uuid:' + uuid; function KeySystemWidevine(config) { From 882ab9b020dac03297e964e2ef3c6865a14fd531 Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Thu, 20 Mar 2025 17:31:27 -0700 Subject: [PATCH 19/29] Update ProtectionModel_01b.js --- src/streaming/protection/models/ProtectionModel_01b.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/streaming/protection/models/ProtectionModel_01b.js b/src/streaming/protection/models/ProtectionModel_01b.js index 7529573e81..b4502bf608 100644 --- a/src/streaming/protection/models/ProtectionModel_01b.js +++ b/src/streaming/protection/models/ProtectionModel_01b.js @@ -45,7 +45,9 @@ import KeySystemConfiguration from '../vo/KeySystemConfiguration.js'; import KeySystemAccess from '../vo/KeySystemAccess.js'; import ProtectionErrors from '../errors/ProtectionErrors.js'; import FactoryMaker from '../../../core/FactoryMaker.js'; -import ProtectionConstants from '../../constants/ProtectionConstants.js'; + +// imports from common-media-library +import { INITIALIZATION_DATA_TYPE } from '@svta/common-media-library/drm/common/const/INITIALIZATION_DATA_TYPE.js'; function ProtectionModel_01b(config) { @@ -311,7 +313,7 @@ function ProtectionModel_01b(config) { switch (event.type) { case api.needkey: let initData = ArrayBuffer.isView(event.initData) ? event.initData.buffer : event.initData; - eventBus.trigger(events.NEED_KEY, { key: new NeedKey(initData, ProtectionConstants.INITIALIZATION_DATA_TYPE_CENC) }); + eventBus.trigger(events.NEED_KEY, { key: new NeedKey(initData, INITIALIZATION_DATA_TYPE.CENC) }); break; case api.keyerror: From dc8f86841c25441f0f67ce9517f781d7a32d3d10 Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Thu, 20 Mar 2025 17:31:36 -0700 Subject: [PATCH 20/29] Update DRMToday.js --- src/streaming/protection/servers/DRMToday.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/streaming/protection/servers/DRMToday.js b/src/streaming/protection/servers/DRMToday.js index 9c28e19afe..9fc9a38be0 100644 --- a/src/streaming/protection/servers/DRMToday.js +++ b/src/streaming/protection/servers/DRMToday.js @@ -36,16 +36,19 @@ * @class */ -import ProtectionConstants from '../../constants/ProtectionConstants.js'; import FactoryMaker from '../../../core/FactoryMaker.js'; +// imports from common-media-library +import { WIDEVINE_KEY_SYSTEM } from '@svta/common-media-library/drm/common/const/WIDEVINE_KEY_SYSTEM.js'; +import { PLAYREADY_KEY_SYSTEM } from '@svta/common-media-library/drm/common/const/PLAYREADY_KEY_SYSTEM.js'; + function DRMToday(config) { config = config || {}; const BASE64 = config.BASE64; const keySystems = {}; - keySystems[ProtectionConstants.WIDEVINE_KEYSTEM_STRING] = { + keySystems[WIDEVINE_KEY_SYSTEM] = { responseType: 'json', getLicenseMessage: function (response) { return BASE64.decodeArray(response.license); @@ -54,7 +57,7 @@ function DRMToday(config) { return response; } }; - keySystems[ProtectionConstants.PLAYREADY_KEYSTEM_STRING] = { + keySystems[PLAYREADY_KEY_SYSTEM] = { responseType: 'arraybuffer', getLicenseMessage: function (response) { return response; From a1587fbece0a28288ec99279a955f7e38b4cf0ad Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Thu, 20 Mar 2025 17:31:51 -0700 Subject: [PATCH 21/29] Update LicenseRequestComplete.js --- src/streaming/protection/vo/LicenseRequestComplete.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/streaming/protection/vo/LicenseRequestComplete.js b/src/streaming/protection/vo/LicenseRequestComplete.js index 869aee8235..3984860755 100644 --- a/src/streaming/protection/vo/LicenseRequestComplete.js +++ b/src/streaming/protection/vo/LicenseRequestComplete.js @@ -28,7 +28,9 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -import ProtectionConstants from '../../constants/ProtectionConstants.js'; + +// imports from common-media-library +import { MEDIA_KEY_MESSAGE_TYPES } from '@svta/common-media-library/drm/common/const/MEDIA_KEY_MESSAGE_TYPES.js'; /** * @classdesc Event indicating the receipt of a response from a license server @@ -49,7 +51,7 @@ class LicenseRequestComplete { constructor(message, sessionToken, messageType) { this.message = message; this.sessionToken = sessionToken; - this.messageType = messageType ? messageType : ProtectionConstants.MEDIA_KEY_MESSAGE_TYPES.LICENSE_REQUEST; + this.messageType = messageType ? messageType : MEDIA_KEY_MESSAGE_TYPES.LICENSE_REQUEST; } } From 8d6df809760f98de9c9f180c4c02f4e202b29811 Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Thu, 20 Mar 2025 17:32:04 -0700 Subject: [PATCH 22/29] Update Capabilities.js --- src/streaming/utils/Capabilities.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/streaming/utils/Capabilities.js b/src/streaming/utils/Capabilities.js index df5bdb9f9f..c57bc12b2f 100644 --- a/src/streaming/utils/Capabilities.js +++ b/src/streaming/utils/Capabilities.js @@ -30,10 +30,13 @@ */ import FactoryMaker from '../../core/FactoryMaker.js'; import Constants from '../constants/Constants.js'; -import ProtectionConstants from '../constants/ProtectionConstants.js'; import ObjectUtils from './ObjectUtils.js'; import Debug from '../../core/Debug.js'; +// imports from common-media-library +import { SW_SECURE_CRYPTO } from '@svta/common-media-library/drm/common/const/SW_SECURE_CRYPTO.js'; +import { WIDEVINE_KEY_SYSTEM } from '@svta/common-media-library/drm/common/const/WIDEVINE_KEY_SYSTEM.js'; + export function supportsMediaSource() { let hasManagedMediaSource = ('ManagedMediaSource' in window) let hasWebKit = ('WebKitMediaSource' in window); @@ -292,8 +295,8 @@ function Capabilities() { } let robustnessLevel = '' - if (keySystemMetadata.ks.systemString === ProtectionConstants.WIDEVINE_KEYSTEM_STRING) { - robustnessLevel = ProtectionConstants.ROBUSTNESS_STRINGS.WIDEVINE.SW_SECURE_CRYPTO; + if (keySystemMetadata.ks.systemString === WIDEVINE_KEY_SYSTEM) { + robustnessLevel = SW_SECURE_CRYPTO; } const protData = keySystemMetadata.protData const audioRobustness = (protData && protData.audioRobustness && protData.audioRobustness.length > 0) ? protData.audioRobustness : robustnessLevel; From 3c7a347c6cef69d96271a952d31ed121d6527544 Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Thu, 20 Mar 2025 17:32:36 -0700 Subject: [PATCH 23/29] Update ProtectionModel_3Feb2014.js --- .../models/ProtectionModel_3Feb2014.js | 137 ++++++++++-------- 1 file changed, 76 insertions(+), 61 deletions(-) diff --git a/src/streaming/protection/models/ProtectionModel_3Feb2014.js b/src/streaming/protection/models/ProtectionModel_3Feb2014.js index a4b8afcf36..5e9acf9ac8 100644 --- a/src/streaming/protection/models/ProtectionModel_3Feb2014.js +++ b/src/streaming/protection/models/ProtectionModel_3Feb2014.js @@ -43,10 +43,11 @@ import NeedKey from '../vo/NeedKey.js'; import DashJSError from '../../vo/DashJSError.js'; import ProtectionErrors from '../errors/ProtectionErrors.js'; import KeyMessage from '../vo/KeyMessage.js'; -import KeySystemConfiguration from '../vo/KeySystemConfiguration.js'; -import KeySystemAccess from '../vo/KeySystemAccess.js'; import FactoryMaker from '../../../core/FactoryMaker.js'; -import ProtectionConstants from '../../constants/ProtectionConstants.js'; + +// imports from common-media-library +import { getCompatibleKeySystemAccess } from '@svta/common-media-library/drm/key-system/getCompatibleKeySystemAccess.js'; +import { INITIALIZATION_DATA_TYPE } from '@svta/common-media-library/drm/common/const/INITIALIZATION_DATA_TYPE.js'; function ProtectionModel_3Feb2014(config) { @@ -105,68 +106,82 @@ function ProtectionModel_3Feb2014(config) { } function requestKeySystemAccess(ksConfigurations) { - return new Promise((resolve, reject) => { - // Try key systems in order, first one with supported key system configuration - // is used - let found = false; - for (let ksIdx = 0; ksIdx < ksConfigurations.length; ksIdx++) { - const systemString = ksConfigurations[ksIdx].ks.systemString; - const configs = ksConfigurations[ksIdx].configs; - let supportedAudio = null; - let supportedVideo = null; - - // Try key system configs in order, first one with supported audio/video - // is used - for (let configIdx = 0; configIdx < configs.length; configIdx++) { - const audios = configs[configIdx].audioCapabilities; - const videos = configs[configIdx].videoCapabilities; - - // Look for supported audio container/codecs - if (audios && audios.length !== 0) { - supportedAudio = []; // Indicates that we have a requested audio config - for (let audioIdx = 0; audioIdx < audios.length; audioIdx++) { - if (window[api.MediaKeys].isTypeSupported(systemString, audios[audioIdx].contentType)) { - supportedAudio.push(audios[audioIdx]); - } - } - } - - // Look for supported video container/codecs - if (videos && videos.length !== 0) { - supportedVideo = []; // Indicates that we have a requested video config - for (let videoIdx = 0; videoIdx < videos.length; videoIdx++) { - if (window[api.MediaKeys].isTypeSupported(systemString, videos[videoIdx].contentType)) { - supportedVideo.push(videos[videoIdx]); - } - } - } - - // No supported audio or video in this configuration OR we have - // requested audio or video configuration that is not supported - if ((!supportedAudio && !supportedVideo) || - (supportedAudio && supportedAudio.length === 0) || - (supportedVideo && supportedVideo.length === 0)) { - continue; - } - - // This configuration is supported - found = true; - const ksConfig = new KeySystemConfiguration(supportedAudio, supportedVideo); - const ks = protectionKeyController.getKeySystemBySystemString(systemString); - const keySystemAccess = new KeySystemAccess(ks, ksConfig); - eventBus.trigger(events.KEY_SYSTEM_ACCESS_COMPLETE, { data: keySystemAccess }); - resolve({ data: keySystemAccess }); - break; - } - } - if (!found) { + return getCompatibleKeySystemAccess(ksConfigurations).then((keySystemAccess) => { + if (keySystemAccess) { + eventBus.trigger(events.KEY_SYSTEM_ACCESS_COMPLETE, { data: keySystemAccess }); + return { data: keySystemAccess }; + } + else { const errorMessage = 'Key system access denied! -- No valid audio/video content configurations detected!'; eventBus.trigger(events.KEY_SYSTEM_ACCESS_COMPLETE, { error: errorMessage }); - reject({ error: errorMessage }); + throw { error: errorMessage }; } - }) + }); } + // function requestKeySystemAccess(ksConfigurations) { + // return new Promise((resolve, reject) => { + // // Try key systems in order, first one with supported key system configuration + // // is used + // let found = false; + // for (let ksIdx = 0; ksIdx < ksConfigurations.length; ksIdx++) { + // const systemString = ksConfigurations[ksIdx].ks.systemString; + // const configs = ksConfigurations[ksIdx].configs; + // let supportedAudio = null; + // let supportedVideo = null; + + // // Try key system configs in order, first one with supported audio/video + // // is used + // for (let configIdx = 0; configIdx < configs.length; configIdx++) { + // const audios = configs[configIdx].audioCapabilities; + // const videos = configs[configIdx].videoCapabilities; + + // // Look for supported audio container/codecs + // if (audios && audios.length !== 0) { + // supportedAudio = []; // Indicates that we have a requested audio config + // for (let audioIdx = 0; audioIdx < audios.length; audioIdx++) { + // if (window[api.MediaKeys].isTypeSupported(systemString, audios[audioIdx].contentType)) { + // supportedAudio.push(audios[audioIdx]); + // } + // } + // } + + // // Look for supported video container/codecs + // if (videos && videos.length !== 0) { + // supportedVideo = []; // Indicates that we have a requested video config + // for (let videoIdx = 0; videoIdx < videos.length; videoIdx++) { + // if (window[api.MediaKeys].isTypeSupported(systemString, videos[videoIdx].contentType)) { + // supportedVideo.push(videos[videoIdx]); + // } + // } + // } + + // // No supported audio or video in this configuration OR we have + // // requested audio or video configuration that is not supported + // if ((!supportedAudio && !supportedVideo) || + // (supportedAudio && supportedAudio.length === 0) || + // (supportedVideo && supportedVideo.length === 0)) { + // continue; + // } + + // // This configuration is supported + // found = true; + // const ksConfig = new KeySystemConfiguration(supportedAudio, supportedVideo); + // const ks = protectionKeyController.getKeySystemBySystemString(systemString); + // const keySystemAccess = new KeySystemAccess(ks, ksConfig); + // eventBus.trigger(events.KEY_SYSTEM_ACCESS_COMPLETE, { data: keySystemAccess }); + // resolve({ data: keySystemAccess }); + // break; + // } + // } + // if (!found) { + // const errorMessage = 'Key system access denied! -- No valid audio/video content configurations detected!'; + // eventBus.trigger(events.KEY_SYSTEM_ACCESS_COMPLETE, { error: errorMessage }); + // reject({ error: errorMessage }); + // } + // }) + // } + function selectKeySystem(ksAccess) { return new Promise((resolve, reject) => { try { @@ -301,7 +316,7 @@ function ProtectionModel_3Feb2014(config) { case api.needkey: if (event.initData) { const initData = ArrayBuffer.isView(event.initData) ? event.initData.buffer : event.initData; - eventBus.trigger(events.NEED_KEY, { key: new NeedKey(initData, ProtectionConstants.INITIALIZATION_DATA_TYPE_CENC) }); + eventBus.trigger(events.NEED_KEY, { key: new NeedKey(initData, INITIALIZATION_DATA_TYPE.CENC) }); } break; } From d9bffc8dd4766cd977962b4be3f96eef93e8295c Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Thu, 20 Mar 2025 17:35:43 -0700 Subject: [PATCH 24/29] Update DefaultProtectionModel.js --- .../models/DefaultProtectionModel.js | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/streaming/protection/models/DefaultProtectionModel.js b/src/streaming/protection/models/DefaultProtectionModel.js index 2c6f673df1..d67a1208a9 100644 --- a/src/streaming/protection/models/DefaultProtectionModel.js +++ b/src/streaming/protection/models/DefaultProtectionModel.js @@ -41,15 +41,22 @@ import ProtectionKeyController from '../controllers/ProtectionKeyController.js'; import NeedKey from '../vo/NeedKey.js'; import ProtectionErrors from '../errors/ProtectionErrors.js'; import DashJSError from '../../vo/DashJSError.js'; -import KeyMessage from '../vo/KeyMessage.js'; import KeySystemAccess from '../vo/KeySystemAccess.js'; -import ProtectionConstants from '../../constants/ProtectionConstants.js'; +import KeyMessage from '../vo/KeyMessage.js'; import FactoryMaker from '../../../core/FactoryMaker.js'; +// imports from common-media-library +import { PLAYREADY_KEY_SYSTEM } from '@svta/common-media-library/drm/common/const/PLAYREADY_KEY_SYSTEM.js'; +import { PLAYREADY_RECOMMENDATION_KEY_SYSTEM } from '@svta/common-media-library/drm/common/const/PLAYREADY_RECOMMENDATION_KEY_SYSTEM.js'; +import { WIDEVINE_KEY_SYSTEM } from '@svta/common-media-library/drm/common/const/WIDEVINE_KEY_SYSTEM.js'; +import { CLEAR_KEY_SYSTEM } from '@svta/common-media-library/drm/common/const/CLEAR_KEY_SYSTEM.js'; +import { INITIALIZATION_DATA_TYPE } from '@svta/common-media-library/drm/common/const/INITIALIZATION_DATA_TYPE.js'; +import { MEDIA_KEY_STATUSES } from '@svta/common-media-library/drm/common/const/MEDIA_KEY_STATUSES.js'; + const SYSTEM_STRING_PRIORITY = {}; -SYSTEM_STRING_PRIORITY[ProtectionConstants.PLAYREADY_KEYSTEM_STRING] = [ProtectionConstants.PLAYREADY_KEYSTEM_STRING, ProtectionConstants.PLAYREADY_RECOMMENDATION_KEYSTEM_STRING]; -SYSTEM_STRING_PRIORITY[ProtectionConstants.WIDEVINE_KEYSTEM_STRING] = [ProtectionConstants.WIDEVINE_KEYSTEM_STRING]; -SYSTEM_STRING_PRIORITY[ProtectionConstants.CLEARKEY_KEYSTEM_STRING] = [ProtectionConstants.CLEARKEY_KEYSTEM_STRING]; +SYSTEM_STRING_PRIORITY[PLAYREADY_KEY_SYSTEM] = [PLAYREADY_KEY_SYSTEM, PLAYREADY_RECOMMENDATION_KEY_SYSTEM]; +SYSTEM_STRING_PRIORITY[WIDEVINE_KEY_SYSTEM] = [WIDEVINE_KEY_SYSTEM]; +SYSTEM_STRING_PRIORITY[CLEAR_KEY_SYSTEM] = [CLEAR_KEY_SYSTEM]; function DefaultProtectionModel(config) { @@ -310,7 +317,7 @@ function DefaultProtectionModel(config) { const sessionToken = _createSessionToken(mediaKeySession, keySystemMetadata); // The "keyids" type is used for Clearkey when keys are provided directly in the protection data and a request to a license server is not needed - const dataType = keySystem.systemString === ProtectionConstants.CLEARKEY_KEYSTEM_STRING && (keySystemMetadata.initData || (keySystemMetadata.protData && keySystemMetadata.protData.clearkeys)) ? ProtectionConstants.INITIALIZATION_DATA_TYPE_KEYIDS : ProtectionConstants.INITIALIZATION_DATA_TYPE_CENC; + const dataType = keySystem.systemString === CLEAR_KEY_SYSTEM && (keySystemMetadata.initData || (keySystemMetadata.protData && keySystemMetadata.protData.clearkeys)) ? INITIALIZATION_DATA_TYPE.KEYIDS : INITIALIZATION_DATA_TYPE.CENC; mediaKeySession.generateRequest(dataType, keySystemMetadata.initData) .then(function () { @@ -520,7 +527,7 @@ function DefaultProtectionModel(config) { let usable = false; session.keyStatuses.forEach(function () { let keyStatus = _parseKeyStatus(arguments); - if (keyStatus.status === ProtectionConstants.MEDIA_KEY_STATUSES.USABLE) { + if (keyStatus.status === MEDIA_KEY_STATUSES.USABLE) { usable = true; } }); From 4d90717999101b51d796bc8eea5dbd24bd23cd68 Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Thu, 20 Mar 2025 17:41:23 -0700 Subject: [PATCH 25/29] Update KeySystemConfiguration.js --- src/streaming/protection/vo/KeySystemConfiguration.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/streaming/protection/vo/KeySystemConfiguration.js b/src/streaming/protection/vo/KeySystemConfiguration.js index 523180f0ae..4b9737bb51 100644 --- a/src/streaming/protection/vo/KeySystemConfiguration.js +++ b/src/streaming/protection/vo/KeySystemConfiguration.js @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -import ProtectionConstants from '../../constants/ProtectionConstants.js'; +import { INITIALIZATION_DATA_TYPE } from '@svta/common-media-library/drm/common/const/INITIALIZATION_DATA_TYPE.js'; /** * @classdesc Represents a set of configurations that describe the capabilities desired for @@ -53,7 +53,7 @@ class KeySystemConfiguration { * @class */ constructor(audioCapabilities, videoCapabilities, distinctiveIdentifier, persistentState, sessionTypes, initDataTypes) { - this.initDataTypes = initDataTypes && initDataTypes.length > 0 ? initDataTypes : [ProtectionConstants.INITIALIZATION_DATA_TYPE_CENC]; + this.initDataTypes = initDataTypes && initDataTypes.length > 0 ? initDataTypes : [INITIALIZATION_DATA_TYPE.CENC]; if (audioCapabilities && audioCapabilities.length) { this.audioCapabilities = audioCapabilities; } From 5345b314448244d9410b16cc3495fcdfdaa9a1c0 Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Thu, 20 Mar 2025 17:41:32 -0700 Subject: [PATCH 26/29] Update KeyMessage.js --- src/streaming/protection/vo/KeyMessage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/streaming/protection/vo/KeyMessage.js b/src/streaming/protection/vo/KeyMessage.js index ae3baa6931..9f8c4dfa50 100644 --- a/src/streaming/protection/vo/KeyMessage.js +++ b/src/streaming/protection/vo/KeyMessage.js @@ -28,7 +28,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -import ProtectionConstants from '../../constants/ProtectionConstants.js'; +import { MEDIA_KEY_MESSAGE_TYPES } from '@svta/common-media-library/drm/common/const/MEDIA_KEY_MESSAGE_TYPES.js'; /** * @classdesc EME-independent KeyMessage @@ -48,7 +48,7 @@ class KeyMessage { this.sessionToken = sessionToken; this.message = message; this.defaultURL = defaultURL; - this.messageType = messageType ? messageType : ProtectionConstants.MEDIA_KEY_MESSAGE_TYPES.LICENSE_REQUEST; + this.messageType = messageType ? messageType : MEDIA_KEY_MESSAGE_TYPES.LICENSE_REQUEST; } } From becc754f62f0a568f5a6a78f4da90336262f650b Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Thu, 20 Mar 2025 17:41:44 -0700 Subject: [PATCH 27/29] Update ProtectionController.js --- .../controllers/ProtectionController.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/streaming/protection/controllers/ProtectionController.js b/src/streaming/protection/controllers/ProtectionController.js index 7398d2700e..f9a7135e0c 100644 --- a/src/streaming/protection/controllers/ProtectionController.js +++ b/src/streaming/protection/controllers/ProtectionController.js @@ -39,11 +39,14 @@ import {HTTPRequest} from '../../vo/metrics/HTTPRequest.js'; import Utils from '../../../core/Utils.js'; import Constants from '../../constants/Constants.js'; import FactoryMaker from '../../../core/FactoryMaker.js'; -import ProtectionConstants from '../../constants/ProtectionConstants.js'; import { getPSSHData } from '@svta/common-media-library/drm/common-encryption/getPSSHData.js'; import { getPSSHForKeySystem } from '@svta/common-media-library/drm/common-encryption/getPSSHForKeySystem.js'; import { getLicenseServerUrlFromContentProtection } from '@svta/common-media-library/drm/common-encryption/getLicenseServerUrlFromContentProtection.js'; +import { MEDIA_KEY_MESSAGE_TYPES } from '@svta/common-media-library/drm/common/const/MEDIA_KEY_MESSAGE_TYPES.js'; +import { INITIALIZATION_DATA_TYPE } from '@svta/common-media-library/drm/common/const/INITIALIZATION_DATA_TYPE.js'; +import { PLAYREADY_UUID } from '@svta/common-media-library/drm/common/const/PLAYREADY_UUID.js'; +import { MEDIA_KEY_STATUSES } from '@svta/common-media-library/drm/common/const/MEDIA_KEY_STATUSES.js'; const NEEDKEY_BEFORE_INITIALIZE_RETRIES = 5; const NEEDKEY_BEFORE_INITIALIZE_TIMEOUT = 500; @@ -306,7 +309,7 @@ function ProtectionController(config) { const protData = keySystemData.protData; const audioCapabilities = []; const videoCapabilities = []; - const initDataTypes = (protData && protData.initDataTypes && protData.initDataTypes.length > 0) ? protData.initDataTypes : [ProtectionConstants.INITIALIZATION_DATA_TYPE_CENC]; + const initDataTypes = (protData && protData.initDataTypes && protData.initDataTypes.length > 0) ? protData.initDataTypes : [INITIALIZATION_DATA_TYPE.CENC]; const audioRobustness = (protData && protData.audioRobustness && protData.audioRobustness.length > 0) ? protData.audioRobustness : robustnessLevel; const videoRobustness = (protData && protData.videoRobustness && protData.videoRobustness.length > 0) ? protData.videoRobustness : robustnessLevel; const ksSessionType = keySystemData.sessionType; @@ -681,7 +684,7 @@ function ProtectionController(config) { // Dispatch event to applications indicating we received a key message const keyMessage = e.data; eventBus.trigger(events.KEY_MESSAGE, { data: keyMessage }); - const messageType = (keyMessage.messageType) ? keyMessage.messageType : ProtectionConstants.MEDIA_KEY_MESSAGE_TYPES.LICENSE_REQUEST; + const messageType = (keyMessage.messageType) ? keyMessage.messageType : MEDIA_KEY_MESSAGE_TYPES.LICENSE_REQUEST; const message = keyMessage.message; const sessionToken = keyMessage.sessionToken; const protData = _getProtDataForKeySystem(selectedKeySystem); @@ -735,7 +738,7 @@ function ProtectionController(config) { */ function _issueLicenseRequest(keyMessage, licenseServerData, protData) { const sessionToken = keyMessage.sessionToken; - const messageType = (keyMessage.messageType) ? keyMessage.messageType : ProtectionConstants.MEDIA_KEY_MESSAGE_TYPES.LICENSE_REQUEST; + const messageType = (keyMessage.messageType) ? keyMessage.messageType : MEDIA_KEY_MESSAGE_TYPES.LICENSE_REQUEST; const eventData = { sessionToken: sessionToken, messageType: messageType }; const keySystemString = selectedKeySystem ? selectedKeySystem.systemString : null; @@ -1073,7 +1076,7 @@ function ProtectionController(config) { logger.debug('DRM: onNeedKey'); // Ignore non-cenc initData - if (event.key.initDataType !== ProtectionConstants.INITIALIZATION_DATA_TYPE_CENC) { + if (event.key.initDataType !== INITIALIZATION_DATA_TYPE.CENC) { logger.warn('DRM: Only \'cenc\' initData is supported! Ignoring initData of type: ' + event.key.initDataType); return; } @@ -1150,7 +1153,7 @@ function ProtectionController(config) { const isEdgeBrowser = ua && ua.browser && ua.browser.name && ua.browser.name.toLowerCase() === 'edge'; parsedKeyStatuses.forEach((keyStatus) => { if (isEdgeBrowser - && selectedKeySystem.uuid === ProtectionConstants.PLAYREADY_UUID + && selectedKeySystem.uuid === PLAYREADY_UUID && keyStatus.keyId && keyStatus.keyId.byteLength === 16) { _handlePlayreadyKeyId(keyStatus.keyId); } @@ -1185,7 +1188,7 @@ function ProtectionController(config) { return [...normalizedKeyIds].some((normalizedKeyId) => { const keyStatus = keyStatusMap.get(normalizedKeyId); - return keyStatus && keyStatus !== ProtectionConstants.MEDIA_KEY_STATUSES.INTERNAL_ERROR && keyStatus !== ProtectionConstants.MEDIA_KEY_STATUSES.OUTPUT_RESTRICTED; + return keyStatus && keyStatus !== MEDIA_KEY_STATUSES.INTERNAL_ERROR && keyStatus !== MEDIA_KEY_STATUSES.OUTPUT_RESTRICTED; }); } catch (error) { logger.error(error); @@ -1201,7 +1204,7 @@ function ProtectionController(config) { return [...normalizedKeyIds].every((normalizedKeyId) => { const keyStatus = keyStatusMap.get(normalizedKeyId); - return keyStatus === ProtectionConstants.MEDIA_KEY_STATUSES.EXPIRED; + return keyStatus === MEDIA_KEY_STATUSES.EXPIRED; }) } catch (error) { logger.error(error); From a8d75fe5b5000c8094d6912f2863878c96a85092 Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Thu, 20 Mar 2025 17:41:54 -0700 Subject: [PATCH 28/29] Delete ProtectionConstants.js --- .../constants/ProtectionConstants.js | 76 ------------------- 1 file changed, 76 deletions(-) delete mode 100644 src/streaming/constants/ProtectionConstants.js diff --git a/src/streaming/constants/ProtectionConstants.js b/src/streaming/constants/ProtectionConstants.js deleted file mode 100644 index dd9838286b..0000000000 --- a/src/streaming/constants/ProtectionConstants.js +++ /dev/null @@ -1,76 +0,0 @@ -/** - * The copyright in this software is being made available under the BSD License, - * included below. This software may be subject to other third party and contributor - * rights, including patent rights, and no such rights are granted under this license. - * - * Copyright (c) 2013, Dash Industry Forum. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * * Neither the name of Dash Industry Forum nor the names of its - * contributors may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF USE, DATA, OR - * PROFITS, OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * Protection Constants declaration - * @ignore - */ -export default { - CLEARKEY_KEYSTEM_STRING: 'org.w3.clearkey', - WIDEVINE_KEYSTEM_STRING: 'com.widevine.alpha', - PLAYREADY_KEYSTEM_STRING: 'com.microsoft.playready', - PLAYREADY_RECOMMENDATION_KEYSTEM_STRING: 'com.microsoft.playready.recommendation', - WIDEVINE_UUID: 'edef8ba9-79d6-4ace-a3c8-27dcd51d21ed', - PLAYREADY_UUID: '9a04f079-9840-4286-ab92-e65be0885f95', - CLEARKEY_UUID: 'e2719d58-a985-b3c9-781a-b030af78d30e', - W3C_CLEARKEY_UUID: '1077efec-c0b2-4d02-ace3-3c1e52e2fb4b', - INITIALIZATION_DATA_TYPE_CENC: 'cenc', - INITIALIZATION_DATA_TYPE_KEYIDS: 'keyids', - INITIALIZATION_DATA_TYPE_WEBM: 'webm', - ENCRYPTION_SCHEME_CENC: 'cenc', - ENCRYPTION_SCHEME_CBCS: 'cbcs', - MEDIA_KEY_MESSAGE_TYPES: { - LICENSE_REQUEST: 'license-request', - LICENSE_RENEWAL: 'license-renewal', - LICENSE_RELEASE: 'license-release', - INDIVIDUALIZATION_REQUEST: 'individualization-request', - }, - ROBUSTNESS_STRINGS: { - WIDEVINE: { - SW_SECURE_CRYPTO: 'SW_SECURE_CRYPTO', - SW_SECURE_DECODE: 'SW_SECURE_DECODE', - HW_SECURE_CRYPTO: 'HW_SECURE_CRYPTO', - HW_SECURE_DECODE: 'HW_SECURE_DECODE', - HW_SECURE_ALL: 'HW_SECURE_ALL' - } - }, - MEDIA_KEY_STATUSES: { - USABLE: 'usable', - EXPIRED: 'expired', - RELEASED: 'released', - OUTPUT_RESTRICTED: 'output-restricted', - OUTPUT_DOWNSCALED: 'output-downscaled', - STATUS_PENDING: 'status-pending', - INTERNAL_ERROR: 'internal-error', - } -} - - From 69980fb813bb5259fe5ee865a8ebbb92f9e90d18 Mon Sep 17 00:00:00 2001 From: Agajan Jumakuliyev Date: Thu, 20 Mar 2025 17:42:06 -0700 Subject: [PATCH 29/29] Update index.d.ts --- index.d.ts | 40 ---------------------------------------- 1 file changed, 40 deletions(-) diff --git a/index.d.ts b/index.d.ts index 8673cec0f1..075c5b56c3 100644 --- a/index.d.ts +++ b/index.d.ts @@ -2989,46 +2989,6 @@ declare namespace dashjs { HTTP_REQUEST_DVB_REPORTING_TYPE: 'DVBReporting', } - export interface ProtectionConstants { - CLEARKEY_KEYSTEM_STRING: 'org.w3.clearkey', - WIDEVINE_KEYSTEM_STRING: 'com.widevine.alpha', - PLAYREADY_KEYSTEM_STRING: 'com.microsoft.playready', - PLAYREADY_RECOMMENDATION_KEYSTEM_STRING: 'com.microsoft.playready.recommendation', - WIDEVINE_UUID: 'edef8ba9-79d6-4ace-a3c8-27dcd51d21ed', - PLAYREADY_UUID: '9a04f079-9840-4286-ab92-e65be0885f95', - CLEARKEY_UUID: 'e2719d58-a985-b3c9-781a-b030af78d30e', - W3C_CLEARKEY_UUID: '1077efec-c0b2-4d02-ace3-3c1e52e2fb4b', - INITIALIZATION_DATA_TYPE_CENC: 'cenc', - INITIALIZATION_DATA_TYPE_KEYIDS: 'keyids', - INITIALIZATION_DATA_TYPE_WEBM: 'webm', - ENCRYPTION_SCHEME_CENC: 'cenc', - ENCRYPTION_SCHEME_CBCS: 'cbcs', - MEDIA_KEY_MESSAGE_TYPES: { - LICENSE_REQUEST: 'license-request', - LICENSE_RENEWAL: 'license-renewal', - LICENSE_RELEASE: 'license-release', - INDIVIDUALIZATION_REQUEST: 'individualization-request', - }, - ROBUSTNESS_STRINGS: { - WIDEVINE: { - SW_SECURE_CRYPTO: 'SW_SECURE_CRYPTO', - SW_SECURE_DECODE: 'SW_SECURE_DECODE', - HW_SECURE_CRYPTO: 'HW_SECURE_CRYPTO', - HW_SECURE_DECODE: 'HW_SECURE_DECODE', - HW_SECURE_ALL: 'HW_SECURE_ALL' - } - }, - MEDIA_KEY_STATUSES: { - USABLE: 'usable', - EXPIRED: 'expired', - RELEASED: 'released', - OUTPUT_RESTRICTED: 'output-restricted', - OUTPUT_DOWNSCALED: 'output-downscaled', - STATUS_PENDING: 'status-pending', - INTERNAL_ERROR: 'internal-error', - } - } - /** * Streaming - Controllers **/