Skip to content

Commit 9e33ff0

Browse files
authored
Support AES-128 Encrypted Low-Latency HLS Parts (#5214)
1 parent 7a10ef6 commit 9e33ff0

File tree

4 files changed

+32
-21
lines changed

4 files changed

+32
-21
lines changed

src/controller/base-stream-controller.ts

+3
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,9 @@ export default class BaseStreamController
581581
keyLoadingPromise = this.keyLoader.load(frag).then((keyLoadedData) => {
582582
if (!this.fragContextChanged(keyLoadedData.frag)) {
583583
this.hls.trigger(Events.KEY_LOADED, keyLoadedData);
584+
if (this.state === State.KEY_LOADING) {
585+
this.state = State.IDLE;
586+
}
584587
return keyLoadedData;
585588
}
586589
});

src/crypt/decrypter.ts

-7
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,6 @@ export default class Decrypter {
5858
public flush(): Uint8Array | null {
5959
const { currentResult, remainderData } = this;
6060
if (!currentResult || remainderData) {
61-
logger.error(
62-
`[softwareDecrypt] ${
63-
remainderData
64-
? 'overflow bytes: ' + remainderData.byteLength
65-
: 'no result'
66-
}`
67-
);
6861
this.reset();
6962
return null;
7063
}

src/demux/transmuxer.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,16 @@ export default class Transmuxer {
112112
if (decrypter.isSync()) {
113113
// Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
114114
// data is handled in the flush() call
115-
const decryptedData = decrypter.softwareDecrypt(
115+
let decryptedData = decrypter.softwareDecrypt(
116116
uintData,
117117
keyData.key.buffer,
118118
keyData.iv.buffer
119119
);
120+
// For Low-Latency HLS Parts, decrypt in place, since part parsing is expected on push progress
121+
const loadingParts = chunkMeta.part > -1;
122+
if (loadingParts) {
123+
decryptedData = decrypter.flush();
124+
}
120125
if (!decryptedData) {
121126
stats.executeEnd = now();
122127
return emptyResult(chunkMeta);

src/loader/m3u8-parser.ts

+23-13
Original file line numberDiff line numberDiff line change
@@ -258,19 +258,7 @@ export default class M3U8Parser {
258258
if (Number.isFinite(frag.duration)) {
259259
frag.start = totalduration;
260260
if (levelkeys) {
261-
frag.levelkeys = levelkeys;
262-
const { encryptedFragments } = level;
263-
if (
264-
frag.levelkeys &&
265-
Object.keys(frag.levelkeys).some(
266-
(format) => frag.levelkeys![format].isCommonEncryption
267-
) &&
268-
(!encryptedFragments.length ||
269-
encryptedFragments[encryptedFragments.length - 1].levelkeys !==
270-
levelkeys)
271-
) {
272-
encryptedFragments.push(frag);
273-
}
261+
setFragLevelKeys(frag, levelkeys, level);
274262
}
275263
frag.sn = currentSN;
276264
frag.level = id;
@@ -512,6 +500,9 @@ export default class M3U8Parser {
512500
assignProgramDateTime(frag, prevFrag);
513501
frag.cc = discontinuityCounter;
514502
level.fragmentHint = frag;
503+
if (levelkeys) {
504+
setFragLevelKeys(frag, levelkeys, level);
505+
}
515506
}
516507
const fragmentLength = fragments.length;
517508
const firstFragment = fragments[0];
@@ -661,3 +652,22 @@ function setInitSegment(
661652
}
662653
frag.initSegment = null;
663654
}
655+
656+
function setFragLevelKeys(
657+
frag: Fragment,
658+
levelkeys: { [key: string]: LevelKey },
659+
level: LevelDetails
660+
) {
661+
frag.levelkeys = levelkeys;
662+
const { encryptedFragments } = level;
663+
if (
664+
(!encryptedFragments.length ||
665+
encryptedFragments[encryptedFragments.length - 1].levelkeys !==
666+
levelkeys) &&
667+
Object.keys(levelkeys).some(
668+
(format) => levelkeys![format].isCommonEncryption
669+
)
670+
) {
671+
encryptedFragments.push(frag);
672+
}
673+
}

0 commit comments

Comments
 (0)