Skip to content

Commit

Permalink
Merge pull request #1061 from canalplus/feat/singleLicensePer_periods3
Browse files Browse the repository at this point in the history
feat: implement singleLicensePer: periods
  • Loading branch information
peaBerberian authored Mar 17, 2022
2 parents 3d1aa34 + fb2fb03 commit 90ed273
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 7 deletions.
66 changes: 59 additions & 7 deletions src/core/decrypt/content_decryptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import {
areAllKeyIdsContainedIn,
areKeyIdsEqual,
areSomeKeyIdsContainedIn,
isKeyIdContainedIn,
} from "./utils/key_id_comparison";
import KeySessionRecord from "./utils/key_session_record";

Expand Down Expand Up @@ -396,6 +397,37 @@ export default class ContentDecryptor extends EventEmitter<IContentDecryptorEven
}
return ;
}
} else if (options.singleLicensePer === "periods" &&
initializationData.content !== undefined)
{
const { period } = initializationData.content;
const createdSessions = this._currentSessions
.filter(x => x.source === MediaKeySessionLoadingType.Created);
const periodKeys = new Set<Uint8Array>();
addKeyIdsFromPeriod(periodKeys, period);
for (const createdSess of createdSessions) {
const periodKeysArr = Array.from(periodKeys);
for (const kid of periodKeysArr) {
if (createdSess.record.isAssociatedWithKeyId(kid)) {
createdSess.record.associateKeyIds(periodKeys.values());

// Re-loop through the Period's key ids to blacklist ones that are missing
// from `createdSess`'s `keyStatuses` and to update the content's
// decipherability.
for (const innerKid of periodKeysArr) {
if (!isKeyIdContainedIn(innerKid, createdSess.keyStatuses.whitelisted) &&
!isKeyIdContainedIn(innerKid, createdSess.keyStatuses.blacklisted))
{
createdSess.keyStatuses.blacklisted.push(innerKid);
}
}
updateDecipherability(initializationData.content.manifest,
createdSess.keyStatuses.whitelisted,
createdSess.keyStatuses.blacklisted);
return;
}
}
}
}

// /!\ Do not forget to unlock when done
Expand Down Expand Up @@ -1022,7 +1054,7 @@ interface IAttachedMediaKeysData {
*/
function getFetchedLicenseKeysInfo(
initializationData : IProcessedProtectionData,
singleLicensePer : undefined | "init-data" | "content",
singleLicensePer : undefined | "init-data" | "content" | "periods",
usableKeyIds : Uint8Array[],
unusableKeyIds : Uint8Array[]
) : { whitelisted : Uint8Array[];
Expand Down Expand Up @@ -1061,13 +1093,33 @@ function getFetchedLicenseKeysInfo(
}

if (content !== undefined) {
// Put it in a Set to automatically filter out duplicates (by ref)
const contentKeys = new Set<Uint8Array>();
const { manifest } = content;
for (const period of manifest.periods) {
addKeyIdsFromPeriod(contentKeys, period);
if (singleLicensePer === "content") {
// Put it in a Set to automatically filter out duplicates (by ref)
const contentKeys = new Set<Uint8Array>();
const { manifest } = content;
for (const period of manifest.periods) {
addKeyIdsFromPeriod(contentKeys, period);
}
mergeKeyIdSetIntoArray(contentKeys, associatedKeyIds);
} else if (singleLicensePer === "periods") {
const { manifest } = content;
for (const period of manifest.periods) {
const periodKeys = new Set<Uint8Array>();
addKeyIdsFromPeriod(periodKeys, period);
if (initializationData.content?.period.id === period.id) {
mergeKeyIdSetIntoArray(periodKeys, associatedKeyIds);
} else {
const periodKeysArr = Array.from(periodKeys);
for (const kid of periodKeysArr) {
const isFound = associatedKeyIds.some(k => areKeyIdsEqual(k, kid));
if (isFound) {
mergeKeyIdSetIntoArray(periodKeys, associatedKeyIds);
break;
}
}
}
}
}
mergeKeyIdSetIntoArray(contentKeys, associatedKeyIds);
}
}
return { whitelisted: usableKeyIds,
Expand Down
1 change: 1 addition & 0 deletions src/core/decrypt/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ export interface IKeySystemOption {
closeSessionsOnStop? : boolean;

singleLicensePer? : "content" |
"periods" |
"init-data";
/**
* Maximum number of `MediaKeySession` that should be created on the same
Expand Down
12 changes: 12 additions & 0 deletions src/core/decrypt/utils/key_id_comparison.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ export function areKeyIdsEqual(
return keyId1 === keyId2 || areArraysOfNumbersEqual(keyId1, keyId2);
}

/**
* @param {Uint8Array} wantedKeyId
* @param {Array.<Uint8Array>} keyIdsArr
* @returns {boolean}
*/
export function isKeyIdContainedIn(
wantedKeyId : Uint8Array,
keyIdsArr : Uint8Array[]
) : boolean {
return keyIdsArr.some(k => areKeyIdsEqual(k, wantedKeyId));
}

/**
* Returns `true` if all key ids in `wantedKeyIds` are present in the
* `keyIdsArr` array.
Expand Down

0 comments on commit 90ed273

Please sign in to comment.