Skip to content

Commit

Permalink
Filter duplicate initData from manifest by key ID
Browse files Browse the repository at this point in the history
Adds a new field to initDataOverride, key Id, that contains the
default key Id corresponding to this initData. This is used to filter
initDatas by their key Ids, hopefully cutting down on unnecessary
license requests.

Closes #580

Change-Id: Ie228d6c0f4c693b19b4119ec4f72a85d555215c1
  • Loading branch information
theodab committed Feb 10, 2017
1 parent 916245f commit 5707e16
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 59 deletions.
5 changes: 4 additions & 1 deletion externs/shaka/manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ shakaExtern.Period;
/**
* @typedef {{
* initData: !Uint8Array,
* initDataType: string
* initDataType: string,
* keyId: ?string
* }}
*
* @description
Expand All @@ -125,6 +126,8 @@ shakaExtern.Period;
* Initialization data in the format indicated by initDataType.
* @property {string} initDataType
* A string to indicate what format initData is in.
* @property {?string} keyId
* The key Id that corresponds to this initData.
*
* @exportDoc
*/
Expand Down
12 changes: 11 additions & 1 deletion lib/dash/content_protection.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,15 @@ shaka.dash.ContentProtection.parseFromAdaptationSet = function(
});
}

// attach the default keyId, if it exists, to every initData
if (defaultKeyId) {
drmInfos.forEach(function(drmInfo) {
drmInfo.initData.forEach(function(initData) {
initData.keyId = defaultKeyId;
});
});
}

return {
defaultKeyId: defaultKeyId,
defaultInit: defaultInit,
Expand Down Expand Up @@ -334,7 +343,8 @@ shaka.dash.ContentProtection.parseElements_ = function(elems) {
/** @type {shakaExtern.InitDataOverride} */
var ret = {
initDataType: 'cenc',
initData: shaka.util.Uint8ArrayUtils.fromBase64(pssh)
initData: shaka.util.Uint8ArrayUtils.fromBase64(pssh),
keyId: null
};
return ret;
});
Expand Down
5 changes: 5 additions & 0 deletions lib/media/drm_engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,11 @@ shaka.media.DrmEngine.prototype.processDrmInfos_ =
* @return {boolean}
*/
function initDataOverrideEqual(a, b) {
if (a.keyId && a.keyId == b.keyId) {
// Two initDatas with the same keyId are considered to be the same,
// unless that "same keyId" is null.
return true;
}
return a.initDataType == b.initDataType &&
shaka.util.Uint8ArrayUtils.equal(a.initData, b.initData);
}
Expand Down
65 changes: 44 additions & 21 deletions test/dash/dash_parser_content_protection_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,34 +91,31 @@ describe('DashParser ContentProtection', function() {
* Build an expected manifest which checks DRM-related fields.
*
* @param {!Array.<!Object>} drmInfos A list of DrmInfo-like objects.
* @param {number=} opt_numVariants The number of variants, default 2.
* @return {Object} A Manifest-like object.
*/
function buildExpectedManifest(drmInfos) {
function buildExpectedManifest(drmInfos, opt_numVariants) {
var numVariants = opt_numVariants || 2;
var keyIds = [];
if (drmInfos.length > 0) {
keyIds = drmInfos[0].sample.keyIds;
}
if (keyIds.length == 0) {
keyIds = [null, null];

var variants = [];
for (var i = 0; i < numVariants; i++) {
var variant = jasmine.objectContaining({
drmInfos: drmInfos,
video: jasmine.objectContaining({
keyId: keyIds[i] || null
})
});
variants.push(variant);
}

return jasmine.objectContaining({
periods: [
jasmine.objectContaining({
variants: [
jasmine.objectContaining({
drmInfos: drmInfos,
video: jasmine.objectContaining({
keyId: keyIds[0]
})
}),
jasmine.objectContaining({
drmInfos: drmInfos,
video: jasmine.objectContaining({
keyId: keyIds[1]
})
})
], // variants
variants: variants,
textStreams: []
})
] // periods
Expand All @@ -131,15 +128,20 @@ describe('DashParser ContentProtection', function() {
* @param {string} keySystem
* @param {Array.<string>=} opt_keyIds
* @param {Array.<string>=} opt_base64Psshs
* @param {Array.<string>=} opt_initDataKeyIds
* @return {Object} A DrmInfo-like object.
*/
function buildDrmInfo(keySystem, opt_keyIds, opt_base64Psshs) {
function buildDrmInfo(keySystem, opt_keyIds,
opt_base64Psshs, opt_initDataKeyIds) {
var base64Psshs = opt_base64Psshs || [];
var initData = base64Psshs.map(function(base64) {
return {
var initData = base64Psshs.map(function(base64, index) {
/** @type {shakaExtern.InitDataOverride} */
var initData = {
initDataType: 'cenc',
initData: shaka.util.Uint8ArrayUtils.fromBase64(base64)
initData: shaka.util.Uint8ArrayUtils.fromBase64(base64),
keyId: opt_initDataKeyIds ? opt_initDataKeyIds[index] : null
};
return initData;
});
var keyIds = opt_keyIds || [];
var containing = {keySystem: keySystem, initData: initData, keyIds: keyIds};
Expand Down Expand Up @@ -223,6 +225,27 @@ describe('DashParser ContentProtection', function() {
testDashParser(done, source, expected);
});

it('sets key IDs for the init data', function(done) {
var source = buildManifestText([
// AdaptationSet lines
], [
// Representation 1 lines
'<ContentProtection',
' schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"',
' value="cenc"',
' cenc:default_KID="DEADBEEF-FEED-BAAD-F00D-000008675309">',
' <cenc:pssh>bm8gaHVtYW4gY2FuIHJlYWQgYmFzZTY0IGRpcmVjdGx5</cenc:pssh>',
'</ContentProtection'
], []);
var expected = buildExpectedManifest([
buildDrmInfo('com.widevine.alpha',
['deadbeeffeedbaadf00d000008675309'], // key Id
['bm8gaHVtYW4gY2FuIHJlYWQgYmFzZTY0IGRpcmVjdGx5'], // initData
['deadbeeffeedbaadf00d000008675309'])], // key Id for initData
1); // one variant
testDashParser(done, source, expected);
});

it('lets Representations override key IDs', function(done) {
var source = buildManifestText([
// AdaptationSet lines
Expand Down
Loading

0 comments on commit 5707e16

Please sign in to comment.