Skip to content

Commit

Permalink
feat(hls): Add HLS PlayReady support (#2719)
Browse files Browse the repository at this point in the history
Resolves #1145
  • Loading branch information
Álvaro Velad Galván authored Aug 3, 2020
1 parent 6c85c8c commit 57ac167
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 0 deletions.
16 changes: 16 additions & 0 deletions demo/common/assets.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ shakaAssets.Source = {
UPLYNK: shakaDemo.MessageIds.UPLYNK,
APPLE: shakaDemo.MessageIds.APPLE,
IRT: shakaDemo.MessageIds.IRT,
MICROSOFT: shakaDemo.MessageIds.MICROSOFT,
};


Expand Down Expand Up @@ -1063,5 +1064,20 @@ shakaAssets.testAssets = [
.addFeature(shakaAssets.Feature.HIGH_DEFINITION)
.addFeature(shakaAssets.Feature.LIVE),
// }}}

// MICROSOFT assets {{{
// Src: http://subtitling.irt.de/cmaf/#urls
// Note: According to the website, these assets may not be available 24/7.
new ShakaDemoAssetInfo(
/* name= */ 'Big Buck Bunny: the Dark Truths of a Video Dev Cartoon (HLS - PlayReady)',
/* iconUri= */ 'https://storage.googleapis.com/shaka-asset-icons/dark_truth.png',
/* manifestUri= */ 'https://test.playready.microsoft.com/media/dash/APPLEENC_CBCS_BBB_1080p/1080p_alternate.m3u8',
/* source= */ shakaAssets.Source.MICROSOFT)
.addKeySystem(shakaAssets.KeySystem.PLAYREADY)
.addFeature(shakaAssets.Feature.HLS)
.addFeature(shakaAssets.Feature.MP4)
.addFeature(shakaAssets.Feature.HIGH_DEFINITION)
.addLicenseServer('com.microsoft.playready', 'http://test.playready.microsoft.com/service/rightsmanager.asmx?cfg=(persist:false,ck:W31bfVt9W31bfVt9W31bfQ==,ckt:aescbc)'),
// }}}
];
/* eslint-enable max-len */
1 change: 1 addition & 0 deletions demo/common/message_ids.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ shakaDemo.MessageIds = {
DASH_IF: 'DEMO_DASH_IF',
GPAC: 'DEMO_GPAC',
IRT: 'DEMO_IRT',
MICROSOFT: 'DEMO_MICROSOFT',
NIMBLE_STREAMER: 'DEMO_NIMBLE_STREAMER',
SHAKA: 'DEMO_SHAKA',
UNIFIED_STREAMING: 'DEMO_UNIFIED_STREAMING',
Expand Down
1 change: 1 addition & 0 deletions demo/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
"DEMO_MAX_PIXELS": "Max Pixels",
"DEMO_MAX_SMALL_GAP_SIZE": "Maximum Small Gap Size",
"DEMO_MAX_WIDTH": "Max Width",
"DEMO_MICROSOFT": "Microsoft",
"DEMO_MIN_BANDWIDTH": "Min Bandwidth",
"DEMO_MIN_FRAMERATE": "Min Framerate",
"DEMO_MIN_HEIGHT": "Min Height",
Expand Down
4 changes: 4 additions & 0 deletions demo/locales/source.json
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,10 @@
"description": "The name of a configuration value.",
"message": "Max Width"
},
"DEMO_MICROSOFT": {
"description": "Text that describes an asset that comes from the Microsoft.",
"message": "[PROPER_NAME:Microsoft]"
},
"DEMO_MIN_BANDWIDTH": {
"description": "The name of a configuration value.",
"message": "Min Bandwidth"
Expand Down
37 changes: 37 additions & 0 deletions lib/hls/hls_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -2536,6 +2536,41 @@ shaka.hls.HlsParser = class {
}
return drmInfo;
}

/**
* See: https://docs.microsoft.com/en-us/playready/packaging/mp4-based-formats-supported-by-playready-clients?tabs=case4
*
* @param {!shaka.hls.Tag} drmTag
* @return {?shaka.extern.DrmInfo}
* @private
*/
static playreadyDrmParser_(drmTag) {
const method = drmTag.getRequiredAttrValue('METHOD');
const VALID_METHODS = ['SAMPLE-AES', 'SAMPLE-AES-CTR'];
if (!VALID_METHODS.includes(method)) {
shaka.log.error('PlayReady in HLS is only supported with [',
VALID_METHODS.join(', '), '], not', method);
return null;
}

const uri = drmTag.getRequiredAttrValue('URI');
const parsedData = shaka.net.DataUriPlugin.parseRaw(uri);

// The data encoded in the URI is a PlayReady Pro Object, so we need
// convert it to pssh.
const data = shaka.util.BufferUtils.toUint8(parsedData.data);
const systemId = new Uint8Array([
0x9a, 0x04, 0xf0, 0x79, 0x98, 0x40, 0x42, 0x86,
0xab, 0x92, 0xe6, 0x5b, 0xe0, 0x88, 0x5f, 0x95,
]);
const pssh = shaka.util.Pssh.createPssh(data, systemId);
const drmInfo = shaka.util.ManifestParserUtils.createDrmInfo(
'com.microsoft.playready', [
{initDataType: 'cenc', initData: pssh},
]);

return drmInfo;
}
};


Expand Down Expand Up @@ -2732,6 +2767,8 @@ shaka.hls.HlsParser.KEYFORMATS_TO_DRM_PARSERS_ = {
*/
'urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed':
shaka.hls.HlsParser.widevineDrmParser_,
'com.microsoft.playready':
shaka.hls.HlsParser.playreadyDrmParser_,
};


Expand Down
39 changes: 39 additions & 0 deletions test/hls/hls_parser_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -1750,6 +1750,45 @@ describe('HlsParser', () => {
await testHlsParser(master, media, manifest);
});

it('constructs DrmInfo for PlayReady', async () => {
const master = [
'#EXTM3U\n',
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1",',
'RESOLUTION=960x540,FRAME-RATE=60\n',
'video\n',
].join('');

const initDataBase64 =
'AAAAKXBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAAlQbGF5cmVhZHk=';

const media = [
'#EXTM3U\n',
'#EXT-X-TARGETDURATION:6\n',
'#EXT-X-PLAYLIST-TYPE:VOD\n',
'#EXT-X-KEY:METHOD=SAMPLE-AES-CTR,',
'KEYFORMAT="com.microsoft.playready",',
'URI="data:text/plain;base64,UGxheXJlYWR5",\n',
'#EXT-X-MAP:URI="init.mp4"\n',
'#EXTINF:5,\n',
'#EXT-X-BYTERANGE:121090@616\n',
'main.mp4',
].join('');

const manifest = shaka.test.ManifestGenerator.generate((manifest) => {
manifest.anyTimeline();
manifest.addPartialVariant((variant) => {
variant.addPartialStream(ContentType.VIDEO, (stream) => {
stream.encrypted = true;
stream.addDrmInfo('com.microsoft.playready', (drmInfo) => {
drmInfo.addCencInitData(initDataBase64);
});
});
});
});

await testHlsParser(master, media, manifest);
});

describe('Errors out', () => {
const Code = shaka.util.Error.Code;

Expand Down

0 comments on commit 57ac167

Please sign in to comment.