diff --git a/src/inheritAttributes.js b/src/inheritAttributes.js
index c20429e7..534dbee0 100644
--- a/src/inheritAttributes.js
+++ b/src/inheritAttributes.js
@@ -175,6 +175,14 @@ export const inheritBaseUrls =
const generateKeySystemInformation = (contentProtectionNodes) => {
return contentProtectionNodes.reduce((acc, node) => {
const attributes = parseAttributes(node);
+
+ // Although it could be argued that according to the UUID RFC spec the UUID string (a-f chars) should be generated
+ // as a lowercase string it also mentions it should be treated as case-insensitive on input. Since the key system
+ // UUIDs in the keySystemsMap are hardcoded as lowercase in the codebase there isn't any reason not to do
+ // .toLowerCase() on the input UUID string from the manifest (at least I could not think of one).
+ if (attributes.schemeIdUri) {
+ attributes.schemeIdUri = attributes.schemeIdUri.toLowerCase();
+ }
const keySystem = keySystemsMap[attributes.schemeIdUri];
if (keySystem) {
@@ -184,9 +192,8 @@ const generateKeySystemInformation = (contentProtectionNodes) => {
if (psshNode) {
const pssh = getContent(psshNode);
- const psshBuffer = pssh && decodeB64ToUint8Array(pssh);
- acc[keySystem].pssh = psshBuffer;
+ acc[keySystem].pssh = pssh && decodeB64ToUint8Array(pssh);
}
}
diff --git a/test/inheritAttributes.test.js b/test/inheritAttributes.test.js
index 9eca5e9f..c630b034 100644
--- a/test/inheritAttributes.test.js
+++ b/test/inheritAttributes.test.js
@@ -9,6 +9,7 @@ import { stringToMpdXml } from '../src/stringToMpdXml';
import errors from '../src/errors';
import QUnit from 'qunit';
import { toPlaylists } from '../src/toPlaylists';
+import decodeB64ToUint8Array from '@videojs/vhs-utils/es/decode-b64-to-uint8-array';
QUnit.module('buildBaseUrls');
@@ -2065,3 +2066,175 @@ QUnit.test('Test to check use of either Segment Template or Segment List when bo
assert.equal(actual.length, 1);
assert.deepEqual(actual, expected);
});
+
+QUnit.test('keySystem info for representation - lowercase UUIDs', function(assert) {
+ const NOW = Date.now();
+
+ const widevinePsshB64 = 'AAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARIQCHJ4bvnnRl+jok5bDvj6RQ==';
+ const playreadyPsshB64 = 'AAAB5HBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAcTEAQAAAQABALoBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBiAG4AaAB5AEMATwBmADUAWAAwAGEAagBvAGsANQBiAEQAdgBqADYAUgBRAD0APQA8AC8ASwBJAEQAPgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==';
+
+ const widevinePsshBytes = decodeB64ToUint8Array(widevinePsshB64);
+ const playreadyPsshBytes = decodeB64ToUint8Array(playreadyPsshB64);
+
+ // Content protection info from dash.js demo
+ const actual = inheritAttributes(stringToMpdXml(`
+
+ https://www.example.com/base/
+
+
+
+
+ AAAB5HBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAcTEAQAAAQABALoBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBiAG4AaAB5AEMATwBmADUAWAAwAGEAagBvAGsANQBiAEQAdgBqADYAUgBRAD0APQA8AC8ASwBJAEQAPgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==
+ xAEAAAEAAQC6ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4AYgBuAGgAeQBDAE8AZgA1AFgAMABhAGoAbwBrADUAYgBEAHYAagA2AFIAUQA9AD0APAAvAEsASQBEAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA=
+
+
+ AAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARIQCHJ4bvnnRl+jok5bDvj6RQ==
+
+
+
+
+
+
+
+
+ `), { NOW });
+
+ // inconsistent quoting because of quote-props
+ const expected = {
+ locations: undefined,
+ representationInfo: [{
+ attributes: {
+ 'bandwidth': 5000000,
+ 'baseUrl': 'https://www.example.com/base/',
+ 'codecs': 'avc1.64001e',
+ 'contentProtection': {
+ 'com.microsoft.playready': {
+ attributes: {
+ schemeIdUri: 'urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95',
+ value: 'MSPR 2.0'
+ },
+ pssh: playreadyPsshBytes
+ },
+ 'com.widevine.alpha': {
+ attributes: {
+ schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed',
+ value: 'Widevine'
+ },
+ pssh: widevinePsshBytes
+ }
+ },
+ 'height': 404,
+ 'id': 'test',
+ 'mediaPresentationDuration': 30,
+ 'mimeType': 'video/mp4',
+ 'periodStart': 0,
+ 'role': {
+ value: 'main'
+ },
+ 'sourceDuration': 30,
+ 'type': 'static',
+ 'width': 720,
+ NOW,
+ 'clientOffset': 0,
+ 'xmlns:cenc': 'urn:mpeg:cenc:2013'
+ },
+ segmentInfo: {
+ template: {}
+ }
+ }]
+ };
+
+ assert.equal(actual.representationInfo.length, 1);
+ assert.deepEqual(actual, expected);
+});
+
+QUnit.test('keySystem info for representation - uppercase UUIDs', function(assert) {
+ const NOW = Date.now();
+
+ const widevinePsshB64 = 'AAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARIQCHJ4bvnnRl+jok5bDvj6RQ==';
+ const playreadyPsshB64 = 'AAAB5HBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAcTEAQAAAQABALoBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBiAG4AaAB5AEMATwBmADUAWAAwAGEAagBvAGsANQBiAEQAdgBqADYAUgBRAD0APQA8AC8ASwBJAEQAPgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==';
+
+ const widevinePsshBytes = decodeB64ToUint8Array(widevinePsshB64);
+ const playreadyPsshBytes = decodeB64ToUint8Array(playreadyPsshB64);
+
+ // Content protection info from dash.js demo
+ const actual = inheritAttributes(stringToMpdXml(`
+
+ https://www.example.com/base/
+
+
+
+
+ AAAB5HBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAcTEAQAAAQABALoBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBiAG4AaAB5AEMATwBmADUAWAAwAGEAagBvAGsANQBiAEQAdgBqADYAUgBRAD0APQA8AC8ASwBJAEQAPgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==
+ xAEAAAEAAQC6ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4AYgBuAGgAeQBDAE8AZgA1AFgAMABhAGoAbwBrADUAYgBEAHYAagA2AFIAUQA9AD0APAAvAEsASQBEAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA=
+
+
+ AAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARIQCHJ4bvnnRl+jok5bDvj6RQ==
+
+
+
+
+
+
+
+
+ `), { NOW });
+
+ // inconsistent quoting because of quote-props
+ const expected = {
+ locations: undefined,
+ representationInfo: [{
+ attributes: {
+ 'bandwidth': 5000000,
+ 'baseUrl': 'https://www.example.com/base/',
+ 'codecs': 'avc1.64001e',
+ 'contentProtection': {
+ 'com.microsoft.playready': {
+ attributes: {
+ schemeIdUri: 'urn:uuid:9a04f079-9840-4286-ab92-e65be0885f95',
+ value: 'MSPR 2.0'
+ },
+ pssh: playreadyPsshBytes
+ },
+ 'com.widevine.alpha': {
+ attributes: {
+ schemeIdUri: 'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed',
+ value: 'Widevine'
+ },
+ pssh: widevinePsshBytes
+ }
+ },
+ 'height': 404,
+ 'id': 'test',
+ 'mediaPresentationDuration': 30,
+ 'mimeType': 'video/mp4',
+ 'periodStart': 0,
+ 'role': {
+ value: 'main'
+ },
+ 'sourceDuration': 30,
+ 'type': 'static',
+ 'width': 720,
+ NOW,
+ 'clientOffset': 0,
+ 'xmlns:cenc': 'urn:mpeg:cenc:2013'
+ },
+ segmentInfo: {
+ template: {}
+ }
+ }]
+ };
+
+ assert.equal(actual.representationInfo.length, 1);
+ assert.deepEqual(actual, expected);
+});