-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve EME Controller: parse PSSH box in manifest #1915
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -73,6 +73,18 @@ const getSupportedMediaKeySystemConfigurations = function (keySystem, audioCodec | |
} | ||
}; | ||
|
||
function base64ToArrayBuffer (base64String) { | ||
let binaryString = window.atob(base64String); | ||
let len = binaryString.length; | ||
let bytes = new Uint8Array(len); | ||
|
||
for (let i = 0; i < len; i++) { | ||
bytes[i] = binaryString.charCodeAt(i); | ||
} | ||
|
||
return bytes; | ||
} | ||
|
||
/** | ||
* Controller to deal with encrypted media extensions (EME) | ||
* @see https://developer.mozilla.org/en-US/docs/Web/API/Encrypted_Media_Extensions_API | ||
|
@@ -88,7 +100,9 @@ class EMEController extends EventHandler { | |
constructor (hls) { | ||
super(hls, | ||
Event.MEDIA_ATTACHED, | ||
Event.MANIFEST_PARSED | ||
Event.MANIFEST_PARSED, | ||
Event.LEVEL_LOADED, | ||
Event.FRAG_LOADED | ||
); | ||
|
||
this._widevineLicenseUrl = hls.config.widevineLicenseUrl; | ||
|
@@ -195,7 +209,6 @@ class EMEController extends EventHandler { | |
mediaKeysListItem.mediaKeys = mediaKeys; | ||
|
||
logger.log(`Media-keys created for key-system "${keySystem}"`); | ||
|
||
this._onMediaKeysCreated(); | ||
}) | ||
.catch((err) => { | ||
|
@@ -240,7 +253,6 @@ class EMEController extends EventHandler { | |
|
||
_onMediaEncrypted (initDataType, initData) { | ||
logger.log(`Media is encrypted using "${initDataType}" init data type`); | ||
|
||
this._isMediaEncrypted = true; | ||
this._mediaEncryptionInitDataType = initDataType; | ||
this._mediaEncryptionInitData = initData; | ||
|
@@ -356,7 +368,7 @@ class EMEController extends EventHandler { | |
|
||
xhr.responseType = 'arraybuffer'; | ||
xhr.onreadystatechange = | ||
this._onLicenseRequestReadyStageChange.bind(this, xhr, url, keyMessage, callback); | ||
this._onLicenseRequestReadyStageChange.bind(this, xhr, url, keyMessage, callback); | ||
return xhr; | ||
} | ||
|
||
|
@@ -469,10 +481,11 @@ class EMEController extends EventHandler { | |
this._media = media; | ||
|
||
// FIXME: also handle detaching media ! | ||
|
||
media.addEventListener('encrypted', (e) => { | ||
this._onMediaEncrypted(e.initDataType, e.initData); | ||
}); | ||
if (!this._hasSetMediaKeys) { | ||
media.addEventListener('encrypted', (e) => { | ||
this._onMediaEncrypted(e.initDataType, e.initData); | ||
}); | ||
} | ||
} | ||
|
||
onManifestParsed (data) { | ||
|
@@ -485,6 +498,35 @@ class EMEController extends EventHandler { | |
|
||
this._attemptKeySystemAccess(KeySystems.WIDEVINE, audioCodecs, videoCodecs); | ||
} | ||
|
||
onFragLoaded (data) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please add jsdoc on function params |
||
if (!this._emeEnabled) { | ||
return; | ||
} | ||
|
||
// add initData and type if they are not included in playlist | ||
if (this.initData && !this._hasSetMediaKeys) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. first of all, please document member types in the constructor, and make sure to pre-initialize them with a certain value ( please look at how things are already set up when you add things. for example, private members are prefixed with underscore. that is our coding style-guide, which we are strict about for newly added code. |
||
this._onMediaEncrypted(this.initDataType, this.initData); | ||
} | ||
} | ||
|
||
onLevelLoaded (data) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please add jsdoc on the data-type you are receiving here |
||
if (!this._emeEnabled) { | ||
return; | ||
} | ||
|
||
if (data.details && data.details.levelkey) { | ||
const levelkey = data.details.levelkey; | ||
const details = levelkey.reluri.split(','); | ||
const encoding = details[0]; | ||
const pssh = details[1]; | ||
|
||
if (encoding.includes('base64')) { | ||
this.initDataType = 'cenc'; | ||
this.initData = base64ToArrayBuffer(pssh); | ||
} | ||
} | ||
} | ||
} | ||
|
||
export default EMEController; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -166,7 +166,7 @@ export default class M3U8Parser { | |
// avoid sliced strings https://github.com/video-dev/hls.js/issues/939 | ||
const title = (' ' + result[2]).slice(1); | ||
frag.title = title || null; | ||
frag.tagList.push(title ? [ 'INF', duration, title ] : [ 'INF', duration ]); | ||
frag.tagList.push(title ? ['INF', duration, title] : ['INF', duration]); | ||
} else if (result[3]) { // url | ||
if (Number.isFinite(frag.duration)) { | ||
const sn = currentSN++; | ||
|
@@ -217,7 +217,7 @@ export default class M3U8Parser { | |
|
||
switch (result[i]) { | ||
case '#': | ||
frag.tagList.push(value2 ? [ value1, value2 ] : [ value1 ]); | ||
frag.tagList.push(value2 ? [value1, value2] : [value1]); | ||
break; | ||
case 'PLAYLIST-TYPE': | ||
level.type = value1.toUpperCase(); | ||
|
@@ -252,7 +252,7 @@ export default class M3U8Parser { | |
decryptiv = keyAttrs.hexadecimalInteger('IV'); | ||
if (decryptmethod) { | ||
levelkey = new LevelKey(); | ||
if ((decrypturi) && (['AES-128', 'SAMPLE-AES', 'SAMPLE-AES-CENC'].indexOf(decryptmethod) >= 0)) { | ||
if ((decrypturi) && (['AES-128', 'SAMPLE-AES', 'SAMPLE-AES-CENC', 'SAMPLE-AES-CTR'].indexOf(decryptmethod) >= 0)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. great |
||
levelkey.method = decryptmethod; | ||
// URI to get the key | ||
levelkey.baseuri = baseurl; | ||
|
@@ -302,6 +302,7 @@ export default class M3U8Parser { | |
level.endSN = currentSN - 1; | ||
level.startCC = level.fragments[0] ? level.fragments[0].cc : 0; | ||
level.endCC = cc; | ||
level.levelkey = levelkey; | ||
|
||
if (!level.initSegment && level.fragments.length) { | ||
// this is a bit lurky but HLS really has no other way to tell us | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please make a util module (seperate file) for this :)