hls.js 1.5.2-0.canary.9923 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hls-demo.js +0 -5
- package/dist/hls-demo.js.map +1 -1
- package/dist/hls.js +379 -431
- package/dist/hls.js.d.ts +14 -14
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +217 -275
- package/dist/hls.light.js.map +1 -1
- package/dist/hls.light.min.js +1 -1
- package/dist/hls.light.min.js.map +1 -1
- package/dist/hls.light.mjs +219 -278
- package/dist/hls.light.mjs.map +1 -1
- package/dist/hls.min.js +1 -1
- package/dist/hls.min.js.map +1 -1
- package/dist/hls.mjs +350 -401
- package/dist/hls.mjs.map +1 -1
- package/dist/hls.worker.js +1 -1
- package/dist/hls.worker.js.map +1 -1
- package/package.json +9 -9
- package/src/controller/abr-controller.ts +2 -2
- package/src/controller/base-stream-controller.ts +16 -16
- package/src/controller/buffer-controller.ts +0 -6
- package/src/controller/eme-controller.ts +12 -6
- package/src/controller/latency-controller.ts +8 -7
- package/src/controller/level-controller.ts +18 -7
- package/src/controller/stream-controller.ts +14 -11
- package/src/controller/subtitle-stream-controller.ts +1 -6
- package/src/controller/subtitle-track-controller.ts +2 -4
- package/src/controller/timeline-controller.ts +26 -20
- package/src/crypt/aes-crypto.ts +2 -21
- package/src/crypt/decrypter.ts +18 -32
- package/src/crypt/fast-aes-key.ts +5 -24
- package/src/demux/audio/adts.ts +4 -9
- package/src/demux/sample-aes.ts +0 -2
- package/src/demux/transmuxer-interface.ts +12 -4
- package/src/demux/transmuxer.ts +3 -16
- package/src/demux/tsdemuxer.ts +17 -12
- package/src/loader/fragment-loader.ts +2 -9
- package/src/loader/key-loader.ts +0 -2
- package/src/loader/level-key.ts +9 -10
- package/src/remux/mp4-remuxer.ts +3 -4
- package/src/types/demuxer.ts +0 -1
- package/src/utils/codecs.ts +4 -33
- package/src/crypt/decrypter-aes-mode.ts +0 -4
- package/src/utils/encryption-methods-util.ts +0 -21
package/dist/hls.js
CHANGED
@@ -552,7 +552,7 @@
|
|
552
552
|
// Some browsers don't allow to use bind on console object anyway
|
553
553
|
// fallback to default if needed
|
554
554
|
try {
|
555
|
-
exportedLogger.log("Debug logs enabled for \"" + id + "\" in hls.js version " + "1.5.2
|
555
|
+
exportedLogger.log("Debug logs enabled for \"" + id + "\" in hls.js version " + "1.5.2");
|
556
556
|
} catch (e) {
|
557
557
|
exportedLogger = fakeLogger;
|
558
558
|
}
|
@@ -1253,26 +1253,6 @@
|
|
1253
1253
|
});
|
1254
1254
|
}
|
1255
1255
|
|
1256
|
-
var DecrypterAesMode = {
|
1257
|
-
cbc: 0,
|
1258
|
-
ctr: 1
|
1259
|
-
};
|
1260
|
-
|
1261
|
-
function isFullSegmentEncryption(method) {
|
1262
|
-
return method === 'AES-128' || method === 'AES-256' || method === 'AES-256-CTR';
|
1263
|
-
}
|
1264
|
-
function getAesModeFromFullSegmentMethod(method) {
|
1265
|
-
switch (method) {
|
1266
|
-
case 'AES-128':
|
1267
|
-
case 'AES-256':
|
1268
|
-
return DecrypterAesMode.cbc;
|
1269
|
-
case 'AES-256-CTR':
|
1270
|
-
return DecrypterAesMode.ctr;
|
1271
|
-
default:
|
1272
|
-
throw new Error("invalid full segment method " + method);
|
1273
|
-
}
|
1274
|
-
}
|
1275
|
-
|
1276
1256
|
/** returns `undefined` is `self` is missing, e.g. in node */
|
1277
1257
|
var optionalSelf = typeof self !== 'undefined' ? self : undefined;
|
1278
1258
|
|
@@ -2931,13 +2911,13 @@
|
|
2931
2911
|
this.keyFormatVersions = formatversions;
|
2932
2912
|
this.iv = iv;
|
2933
2913
|
this.encrypted = method ? method !== 'NONE' : false;
|
2934
|
-
this.isCommonEncryption = this.encrypted &&
|
2914
|
+
this.isCommonEncryption = this.encrypted && method !== 'AES-128';
|
2935
2915
|
}
|
2936
2916
|
var _proto = LevelKey.prototype;
|
2937
2917
|
_proto.isSupported = function isSupported() {
|
2938
2918
|
// If it's Segment encryption or No encryption, just select that key system
|
2939
2919
|
if (this.method) {
|
2940
|
-
if (
|
2920
|
+
if (this.method === 'AES-128' || this.method === 'NONE') {
|
2941
2921
|
return true;
|
2942
2922
|
}
|
2943
2923
|
if (this.keyFormat === 'identity') {
|
@@ -2959,13 +2939,14 @@
|
|
2959
2939
|
if (!this.encrypted || !this.uri) {
|
2960
2940
|
return null;
|
2961
2941
|
}
|
2962
|
-
if (
|
2942
|
+
if (this.method === 'AES-128' && this.uri && !this.iv) {
|
2963
2943
|
if (typeof sn !== 'number') {
|
2964
2944
|
// We are fetching decryption data for a initialization segment
|
2965
|
-
// If the segment was encrypted with AES-128
|
2945
|
+
// If the segment was encrypted with AES-128
|
2966
2946
|
// It must have an IV defined. We cannot substitute the Segment Number in.
|
2967
|
-
|
2968
|
-
|
2947
|
+
if (this.method === 'AES-128' && !this.iv) {
|
2948
|
+
logger.warn("missing IV for initialization segment with method=\"" + this.method + "\" - compliance issue");
|
2949
|
+
}
|
2969
2950
|
// Explicitly set sn to resulting value from implicit conversions 'initSegment' values for IV generation.
|
2970
2951
|
sn = 0;
|
2971
2952
|
}
|
@@ -3259,28 +3240,23 @@
|
|
3259
3240
|
if (CODEC_COMPATIBLE_NAMES[lowerCaseCodec]) {
|
3260
3241
|
return CODEC_COMPATIBLE_NAMES[lowerCaseCodec];
|
3261
3242
|
}
|
3243
|
+
|
3244
|
+
// Idealy fLaC and Opus would be first (spec-compliant) but
|
3245
|
+
// some browsers will report that fLaC is supported then fail.
|
3246
|
+
// see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
|
3262
3247
|
var codecsToCheck = {
|
3263
|
-
// Idealy fLaC and Opus would be first (spec-compliant) but
|
3264
|
-
// some browsers will report that fLaC is supported then fail.
|
3265
|
-
// see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
|
3266
3248
|
flac: ['flac', 'fLaC', 'FLAC'],
|
3267
|
-
opus: ['opus', 'Opus']
|
3268
|
-
// Replace audio codec info if browser does not support mp4a.40.34,
|
3269
|
-
// and demuxer can fallback to 'audio/mpeg' or 'audio/mp4;codecs="mp3"'
|
3270
|
-
'mp4a.40.34': ['mp3']
|
3249
|
+
opus: ['opus', 'Opus']
|
3271
3250
|
}[lowerCaseCodec];
|
3272
3251
|
for (var i = 0; i < codecsToCheck.length; i++) {
|
3273
|
-
var _getMediaSource;
|
3274
3252
|
if (isCodecMediaSourceSupported(codecsToCheck[i], 'audio', preferManagedMediaSource)) {
|
3275
3253
|
CODEC_COMPATIBLE_NAMES[lowerCaseCodec] = codecsToCheck[i];
|
3276
3254
|
return codecsToCheck[i];
|
3277
|
-
} else if (codecsToCheck[i] === 'mp3' && (_getMediaSource = getMediaSource(preferManagedMediaSource)) != null && _getMediaSource.isTypeSupported('audio/mpeg')) {
|
3278
|
-
return '';
|
3279
3255
|
}
|
3280
3256
|
}
|
3281
3257
|
return lowerCaseCodec;
|
3282
3258
|
}
|
3283
|
-
var AUDIO_CODEC_REGEXP = /flac|opus
|
3259
|
+
var AUDIO_CODEC_REGEXP = /flac|opus/i;
|
3284
3260
|
function getCodecCompatibleName(codec, preferManagedMediaSource) {
|
3285
3261
|
if (preferManagedMediaSource === void 0) {
|
3286
3262
|
preferManagedMediaSource = true;
|
@@ -3308,18 +3284,6 @@
|
|
3308
3284
|
}
|
3309
3285
|
return codec;
|
3310
3286
|
}
|
3311
|
-
function getM2TSSupportedAudioTypes(preferManagedMediaSource) {
|
3312
|
-
var MediaSource = getMediaSource(preferManagedMediaSource) || {
|
3313
|
-
isTypeSupported: function isTypeSupported() {
|
3314
|
-
return false;
|
3315
|
-
}
|
3316
|
-
};
|
3317
|
-
return {
|
3318
|
-
mpeg: MediaSource.isTypeSupported('audio/mpeg'),
|
3319
|
-
mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
|
3320
|
-
ac3: MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"')
|
3321
|
-
};
|
3322
|
-
}
|
3323
3287
|
|
3324
3288
|
var MASTER_PLAYLIST_REGEX = /#EXT-X-STREAM-INF:([^\r\n]*)(?:[\r\n](?:#[^\r\n]*)?)*([^\r\n]+)|#EXT-X-(SESSION-DATA|SESSION-KEY|DEFINE|CONTENT-STEERING|START):([^\r\n]*)[\r\n]+/g;
|
3325
3289
|
var MASTER_PLAYLIST_MEDIA_REGEX = /#EXT-X-MEDIA:(.*)/g;
|
@@ -4983,43 +4947,8 @@
|
|
4983
4947
|
this.currentTime = 0;
|
4984
4948
|
this.stallCount = 0;
|
4985
4949
|
this._latency = null;
|
4986
|
-
this.
|
4987
|
-
|
4988
|
-
levelDetails = _this.levelDetails;
|
4989
|
-
if (!media || !levelDetails) {
|
4990
|
-
return;
|
4991
|
-
}
|
4992
|
-
_this.currentTime = media.currentTime;
|
4993
|
-
var latency = _this.computeLatency();
|
4994
|
-
if (latency === null) {
|
4995
|
-
return;
|
4996
|
-
}
|
4997
|
-
_this._latency = latency;
|
4998
|
-
|
4999
|
-
// Adapt playbackRate to meet target latency in low-latency mode
|
5000
|
-
var _this$config = _this.config,
|
5001
|
-
lowLatencyMode = _this$config.lowLatencyMode,
|
5002
|
-
maxLiveSyncPlaybackRate = _this$config.maxLiveSyncPlaybackRate;
|
5003
|
-
if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1 || !levelDetails.live) {
|
5004
|
-
return;
|
5005
|
-
}
|
5006
|
-
var targetLatency = _this.targetLatency;
|
5007
|
-
if (targetLatency === null) {
|
5008
|
-
return;
|
5009
|
-
}
|
5010
|
-
var distanceFromTarget = latency - targetLatency;
|
5011
|
-
// Only adjust playbackRate when within one target duration of targetLatency
|
5012
|
-
// and more than one second from under-buffering.
|
5013
|
-
// Playback further than one target duration from target can be considered DVR playback.
|
5014
|
-
var liveMinLatencyDuration = Math.min(_this.maxLatency, targetLatency + levelDetails.targetduration);
|
5015
|
-
var inLiveRange = distanceFromTarget < liveMinLatencyDuration;
|
5016
|
-
if (inLiveRange && distanceFromTarget > 0.05 && _this.forwardBufferLength > 1) {
|
5017
|
-
var max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));
|
5018
|
-
var rate = Math.round(2 / (1 + Math.exp(-0.75 * distanceFromTarget - _this.edgeStalled)) * 20) / 20;
|
5019
|
-
media.playbackRate = Math.min(max, Math.max(1, rate));
|
5020
|
-
} else if (media.playbackRate !== 1 && media.playbackRate !== 0) {
|
5021
|
-
media.playbackRate = 1;
|
5022
|
-
}
|
4950
|
+
this.timeupdateHandler = function () {
|
4951
|
+
return _this.timeupdate();
|
5023
4952
|
};
|
5024
4953
|
this.hls = hls;
|
5025
4954
|
this.config = hls.config;
|
@@ -5031,7 +4960,7 @@
|
|
5031
4960
|
this.onMediaDetaching();
|
5032
4961
|
this.levelDetails = null;
|
5033
4962
|
// @ts-ignore
|
5034
|
-
this.hls = this.
|
4963
|
+
this.hls = this.timeupdateHandler = null;
|
5035
4964
|
};
|
5036
4965
|
_proto.registerListeners = function registerListeners() {
|
5037
4966
|
this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
@@ -5049,11 +4978,11 @@
|
|
5049
4978
|
};
|
5050
4979
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
5051
4980
|
this.media = data.media;
|
5052
|
-
this.media.addEventListener('timeupdate', this.
|
4981
|
+
this.media.addEventListener('timeupdate', this.timeupdateHandler);
|
5053
4982
|
};
|
5054
4983
|
_proto.onMediaDetaching = function onMediaDetaching() {
|
5055
4984
|
if (this.media) {
|
5056
|
-
this.media.removeEventListener('timeupdate', this.
|
4985
|
+
this.media.removeEventListener('timeupdate', this.timeupdateHandler);
|
5057
4986
|
this.media = null;
|
5058
4987
|
}
|
5059
4988
|
};
|
@@ -5066,10 +4995,10 @@
|
|
5066
4995
|
var details = _ref.details;
|
5067
4996
|
this.levelDetails = details;
|
5068
4997
|
if (details.advanced) {
|
5069
|
-
this.
|
4998
|
+
this.timeupdate();
|
5070
4999
|
}
|
5071
5000
|
if (!details.live && this.media) {
|
5072
|
-
this.media.removeEventListener('timeupdate', this.
|
5001
|
+
this.media.removeEventListener('timeupdate', this.timeupdateHandler);
|
5073
5002
|
}
|
5074
5003
|
};
|
5075
5004
|
_proto.onError = function onError(event, data) {
|
@@ -5082,6 +5011,44 @@
|
|
5082
5011
|
logger.warn('[playback-rate-controller]: Stall detected, adjusting target latency');
|
5083
5012
|
}
|
5084
5013
|
};
|
5014
|
+
_proto.timeupdate = function timeupdate() {
|
5015
|
+
var media = this.media,
|
5016
|
+
levelDetails = this.levelDetails;
|
5017
|
+
if (!media || !levelDetails) {
|
5018
|
+
return;
|
5019
|
+
}
|
5020
|
+
this.currentTime = media.currentTime;
|
5021
|
+
var latency = this.computeLatency();
|
5022
|
+
if (latency === null) {
|
5023
|
+
return;
|
5024
|
+
}
|
5025
|
+
this._latency = latency;
|
5026
|
+
|
5027
|
+
// Adapt playbackRate to meet target latency in low-latency mode
|
5028
|
+
var _this$config = this.config,
|
5029
|
+
lowLatencyMode = _this$config.lowLatencyMode,
|
5030
|
+
maxLiveSyncPlaybackRate = _this$config.maxLiveSyncPlaybackRate;
|
5031
|
+
if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1 || !levelDetails.live) {
|
5032
|
+
return;
|
5033
|
+
}
|
5034
|
+
var targetLatency = this.targetLatency;
|
5035
|
+
if (targetLatency === null) {
|
5036
|
+
return;
|
5037
|
+
}
|
5038
|
+
var distanceFromTarget = latency - targetLatency;
|
5039
|
+
// Only adjust playbackRate when within one target duration of targetLatency
|
5040
|
+
// and more than one second from under-buffering.
|
5041
|
+
// Playback further than one target duration from target can be considered DVR playback.
|
5042
|
+
var liveMinLatencyDuration = Math.min(this.maxLatency, targetLatency + levelDetails.targetduration);
|
5043
|
+
var inLiveRange = distanceFromTarget < liveMinLatencyDuration;
|
5044
|
+
if (inLiveRange && distanceFromTarget > 0.05 && this.forwardBufferLength > 1) {
|
5045
|
+
var max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));
|
5046
|
+
var rate = Math.round(2 / (1 + Math.exp(-0.75 * distanceFromTarget - this.edgeStalled)) * 20) / 20;
|
5047
|
+
media.playbackRate = Math.min(max, Math.max(1, rate));
|
5048
|
+
} else if (media.playbackRate !== 1 && media.playbackRate !== 0) {
|
5049
|
+
media.playbackRate = 1;
|
5050
|
+
}
|
5051
|
+
};
|
5085
5052
|
_proto.estimateLiveEdge = function estimateLiveEdge() {
|
5086
5053
|
var levelDetails = this.levelDetails;
|
5087
5054
|
if (levelDetails === null) {
|
@@ -7261,7 +7228,7 @@
|
|
7261
7228
|
var bwEstimate = _this.getBwEstimate();
|
7262
7229
|
var levels = hls.levels;
|
7263
7230
|
var level = levels[frag.level];
|
7264
|
-
var expectedLen = stats.total || Math.max(stats.loaded, Math.round(duration * level.
|
7231
|
+
var expectedLen = stats.total || Math.max(stats.loaded, Math.round(duration * level.averageBitrate / 8));
|
7265
7232
|
var timeStreaming = loadedFirstByte ? timeLoading - ttfb : timeLoading;
|
7266
7233
|
if (timeStreaming < 1 && loadedFirstByte) {
|
7267
7234
|
timeStreaming = Math.min(timeLoading, stats.loaded * 8 / bwEstimate);
|
@@ -7304,7 +7271,7 @@
|
|
7304
7271
|
// If there has been no loading progress, sample TTFB
|
7305
7272
|
_this.bwEstimator.sampleTTFB(timeLoading);
|
7306
7273
|
}
|
7307
|
-
var nextLoadLevelBitrate = levels[nextLoadLevel].
|
7274
|
+
var nextLoadLevelBitrate = levels[nextLoadLevel].maxBitrate;
|
7308
7275
|
if (_this.getBwEstimate() * _this.hls.config.abrBandWidthUpFactor > nextLoadLevelBitrate) {
|
7309
7276
|
_this.resetEstimator(nextLoadLevelBitrate);
|
7310
7277
|
}
|
@@ -8940,8 +8907,8 @@
|
|
8940
8907
|
var _frag$decryptdata;
|
8941
8908
|
var byteRangeStart = start;
|
8942
8909
|
var byteRangeEnd = end;
|
8943
|
-
if (frag.sn === 'initSegment' &&
|
8944
|
-
// MAP segment encrypted with method 'AES-128'
|
8910
|
+
if (frag.sn === 'initSegment' && ((_frag$decryptdata = frag.decryptdata) == null ? void 0 : _frag$decryptdata.method) === 'AES-128') {
|
8911
|
+
// MAP segment encrypted with method 'AES-128', when served with HTTP Range,
|
8945
8912
|
// has the unencrypted size specified in the range.
|
8946
8913
|
// Ref: https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-6.3.6
|
8947
8914
|
var fragmentLen = end - start;
|
@@ -8974,9 +8941,6 @@
|
|
8974
8941
|
(part ? part : frag).stats.aborted = true;
|
8975
8942
|
return new LoadError(errorData);
|
8976
8943
|
}
|
8977
|
-
function isMethodFullSegmentAesCbc(method) {
|
8978
|
-
return method === 'AES-128' || method === 'AES-256';
|
8979
|
-
}
|
8980
8944
|
var LoadError = /*#__PURE__*/function (_Error) {
|
8981
8945
|
_inheritsLoose(LoadError, _Error);
|
8982
8946
|
function LoadError(data) {
|
@@ -8990,65 +8954,37 @@
|
|
8990
8954
|
}( /*#__PURE__*/_wrapNativeSuper(Error));
|
8991
8955
|
|
8992
8956
|
var AESCrypto = /*#__PURE__*/function () {
|
8993
|
-
function AESCrypto(subtle, iv
|
8957
|
+
function AESCrypto(subtle, iv) {
|
8994
8958
|
this.subtle = void 0;
|
8995
8959
|
this.aesIV = void 0;
|
8996
|
-
this.aesMode = void 0;
|
8997
8960
|
this.subtle = subtle;
|
8998
8961
|
this.aesIV = iv;
|
8999
|
-
this.aesMode = aesMode;
|
9000
8962
|
}
|
9001
8963
|
var _proto = AESCrypto.prototype;
|
9002
8964
|
_proto.decrypt = function decrypt(data, key) {
|
9003
|
-
|
9004
|
-
|
9005
|
-
|
9006
|
-
|
9007
|
-
iv: this.aesIV
|
9008
|
-
}, key, data);
|
9009
|
-
case DecrypterAesMode.ctr:
|
9010
|
-
return this.subtle.decrypt({
|
9011
|
-
name: 'AES-CTR',
|
9012
|
-
counter: this.aesIV,
|
9013
|
-
length: 64
|
9014
|
-
},
|
9015
|
-
//64 : NIST SP800-38A standard suggests that the counter should occupy half of the counter block
|
9016
|
-
key, data);
|
9017
|
-
default:
|
9018
|
-
throw new Error("[AESCrypto] invalid aes mode " + this.aesMode);
|
9019
|
-
}
|
8965
|
+
return this.subtle.decrypt({
|
8966
|
+
name: 'AES-CBC',
|
8967
|
+
iv: this.aesIV
|
8968
|
+
}, key, data);
|
9020
8969
|
};
|
9021
8970
|
return AESCrypto;
|
9022
8971
|
}();
|
9023
8972
|
|
9024
8973
|
var FastAESKey = /*#__PURE__*/function () {
|
9025
|
-
function FastAESKey(subtle, key
|
8974
|
+
function FastAESKey(subtle, key) {
|
9026
8975
|
this.subtle = void 0;
|
9027
8976
|
this.key = void 0;
|
9028
|
-
this.aesMode = void 0;
|
9029
8977
|
this.subtle = subtle;
|
9030
8978
|
this.key = key;
|
9031
|
-
this.aesMode = aesMode;
|
9032
8979
|
}
|
9033
8980
|
var _proto = FastAESKey.prototype;
|
9034
8981
|
_proto.expandKey = function expandKey() {
|
9035
|
-
var subtleAlgoName = getSubtleAlgoName(this.aesMode);
|
9036
8982
|
return this.subtle.importKey('raw', this.key, {
|
9037
|
-
name:
|
8983
|
+
name: 'AES-CBC'
|
9038
8984
|
}, false, ['encrypt', 'decrypt']);
|
9039
8985
|
};
|
9040
8986
|
return FastAESKey;
|
9041
8987
|
}();
|
9042
|
-
function getSubtleAlgoName(aesMode) {
|
9043
|
-
switch (aesMode) {
|
9044
|
-
case DecrypterAesMode.cbc:
|
9045
|
-
return 'AES-CBC';
|
9046
|
-
case DecrypterAesMode.ctr:
|
9047
|
-
return 'AES-CTR';
|
9048
|
-
default:
|
9049
|
-
throw new Error("[FastAESKey] invalid aes mode " + aesMode);
|
9050
|
-
}
|
9051
|
-
}
|
9052
8988
|
|
9053
8989
|
// PKCS7
|
9054
8990
|
function removePadding(array) {
|
@@ -9301,8 +9237,7 @@
|
|
9301
9237
|
this.currentIV = null;
|
9302
9238
|
this.currentResult = null;
|
9303
9239
|
this.useSoftware = void 0;
|
9304
|
-
this.
|
9305
|
-
this.enableSoftwareAES = config.enableSoftwareAES;
|
9240
|
+
this.useSoftware = config.enableSoftwareAES;
|
9306
9241
|
this.removePKCS7Padding = removePKCS7Padding;
|
9307
9242
|
// built in decryptor expects PKCS7 padding
|
9308
9243
|
if (removePKCS7Padding) {
|
@@ -9315,7 +9250,9 @@
|
|
9315
9250
|
/* no-op */
|
9316
9251
|
}
|
9317
9252
|
}
|
9318
|
-
|
9253
|
+
if (this.subtle === null) {
|
9254
|
+
this.useSoftware = true;
|
9255
|
+
}
|
9319
9256
|
}
|
9320
9257
|
var _proto = Decrypter.prototype;
|
9321
9258
|
_proto.destroy = function destroy() {
|
@@ -9352,11 +9289,11 @@
|
|
9352
9289
|
this.softwareDecrypter = null;
|
9353
9290
|
}
|
9354
9291
|
};
|
9355
|
-
_proto.decrypt = function decrypt(data, key, iv
|
9292
|
+
_proto.decrypt = function decrypt(data, key, iv) {
|
9356
9293
|
var _this = this;
|
9357
9294
|
if (this.useSoftware) {
|
9358
9295
|
return new Promise(function (resolve, reject) {
|
9359
|
-
_this.softwareDecrypt(new Uint8Array(data), key, iv
|
9296
|
+
_this.softwareDecrypt(new Uint8Array(data), key, iv);
|
9360
9297
|
var decryptResult = _this.flush();
|
9361
9298
|
if (decryptResult) {
|
9362
9299
|
resolve(decryptResult.buffer);
|
@@ -9365,20 +9302,16 @@
|
|
9365
9302
|
}
|
9366
9303
|
});
|
9367
9304
|
}
|
9368
|
-
return this.webCryptoDecrypt(new Uint8Array(data), key, iv
|
9305
|
+
return this.webCryptoDecrypt(new Uint8Array(data), key, iv);
|
9369
9306
|
}
|
9370
9307
|
|
9371
9308
|
// Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
|
9372
9309
|
// data is handled in the flush() call
|
9373
9310
|
;
|
9374
|
-
_proto.softwareDecrypt = function softwareDecrypt(data, key, iv
|
9311
|
+
_proto.softwareDecrypt = function softwareDecrypt(data, key, iv) {
|
9375
9312
|
var currentIV = this.currentIV,
|
9376
9313
|
currentResult = this.currentResult,
|
9377
9314
|
remainderData = this.remainderData;
|
9378
|
-
if (aesMode !== DecrypterAesMode.cbc || key.byteLength !== 16) {
|
9379
|
-
logger.warn('SoftwareDecrypt: can only handle AES-128-CBC');
|
9380
|
-
return null;
|
9381
|
-
}
|
9382
9315
|
this.logOnce('JS AES decrypt');
|
9383
9316
|
// The output is staggered during progressive parsing - the current result is cached, and emitted on the next call
|
9384
9317
|
// This is done in order to strip PKCS7 padding, which is found at the end of each segment. We only know we've reached
|
@@ -9411,12 +9344,12 @@
|
|
9411
9344
|
}
|
9412
9345
|
return result;
|
9413
9346
|
};
|
9414
|
-
_proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv
|
9347
|
+
_proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv) {
|
9415
9348
|
var _this2 = this;
|
9416
9349
|
var subtle = this.subtle;
|
9417
9350
|
if (this.key !== key || !this.fastAesKey) {
|
9418
9351
|
this.key = key;
|
9419
|
-
this.fastAesKey = new FastAESKey(subtle, key
|
9352
|
+
this.fastAesKey = new FastAESKey(subtle, key);
|
9420
9353
|
}
|
9421
9354
|
return this.fastAesKey.expandKey().then(function (aesKey) {
|
9422
9355
|
// decrypt using web crypto
|
@@ -9424,25 +9357,22 @@
|
|
9424
9357
|
return Promise.reject(new Error('web crypto not initialized'));
|
9425
9358
|
}
|
9426
9359
|
_this2.logOnce('WebCrypto AES decrypt');
|
9427
|
-
var crypto = new AESCrypto(subtle, new Uint8Array(iv)
|
9360
|
+
var crypto = new AESCrypto(subtle, new Uint8Array(iv));
|
9428
9361
|
return crypto.decrypt(data.buffer, aesKey);
|
9429
9362
|
}).catch(function (err) {
|
9430
9363
|
logger.warn("[decrypter]: WebCrypto Error, disable WebCrypto API, " + err.name + ": " + err.message);
|
9431
|
-
return _this2.onWebCryptoError(data, key, iv
|
9364
|
+
return _this2.onWebCryptoError(data, key, iv);
|
9432
9365
|
});
|
9433
9366
|
};
|
9434
|
-
_proto.onWebCryptoError = function onWebCryptoError(data, key, iv
|
9435
|
-
|
9436
|
-
|
9437
|
-
|
9438
|
-
|
9439
|
-
|
9440
|
-
|
9441
|
-
if (decryptResult) {
|
9442
|
-
return decryptResult.buffer;
|
9443
|
-
}
|
9367
|
+
_proto.onWebCryptoError = function onWebCryptoError(data, key, iv) {
|
9368
|
+
this.useSoftware = true;
|
9369
|
+
this.logEnabled = true;
|
9370
|
+
this.softwareDecrypt(data, key, iv);
|
9371
|
+
var decryptResult = this.flush();
|
9372
|
+
if (decryptResult) {
|
9373
|
+
return decryptResult.buffer;
|
9444
9374
|
}
|
9445
|
-
throw new Error('WebCrypto
|
9375
|
+
throw new Error('WebCrypto and softwareDecrypt: failed to decrypt data');
|
9446
9376
|
};
|
9447
9377
|
_proto.getValidChunk = function getValidChunk(data) {
|
9448
9378
|
var currentChunk = data;
|
@@ -9521,58 +9451,11 @@
|
|
9521
9451
|
_this.startFragRequested = false;
|
9522
9452
|
_this.decrypter = void 0;
|
9523
9453
|
_this.initPTS = [];
|
9454
|
+
_this.onvseeking = null;
|
9455
|
+
_this.onvended = null;
|
9524
9456
|
_this.logPrefix = '';
|
9525
9457
|
_this.log = void 0;
|
9526
9458
|
_this.warn = void 0;
|
9527
|
-
_this.onMediaSeeking = function () {
|
9528
|
-
var _assertThisInitialize = _assertThisInitialized(_this),
|
9529
|
-
config = _assertThisInitialize.config,
|
9530
|
-
fragCurrent = _assertThisInitialize.fragCurrent,
|
9531
|
-
media = _assertThisInitialize.media,
|
9532
|
-
mediaBuffer = _assertThisInitialize.mediaBuffer,
|
9533
|
-
state = _assertThisInitialize.state;
|
9534
|
-
var currentTime = media ? media.currentTime : 0;
|
9535
|
-
var bufferInfo = BufferHelper.bufferInfo(mediaBuffer ? mediaBuffer : media, currentTime, config.maxBufferHole);
|
9536
|
-
_this.log("media seeking to " + (isFiniteNumber(currentTime) ? currentTime.toFixed(3) : currentTime) + ", state: " + state);
|
9537
|
-
if (_this.state === State.ENDED) {
|
9538
|
-
_this.resetLoadingState();
|
9539
|
-
} else if (fragCurrent) {
|
9540
|
-
// Seeking while frag load is in progress
|
9541
|
-
var tolerance = config.maxFragLookUpTolerance;
|
9542
|
-
var fragStartOffset = fragCurrent.start - tolerance;
|
9543
|
-
var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance;
|
9544
|
-
// if seeking out of buffered range or into new one
|
9545
|
-
if (!bufferInfo.len || fragEndOffset < bufferInfo.start || fragStartOffset > bufferInfo.end) {
|
9546
|
-
var pastFragment = currentTime > fragEndOffset;
|
9547
|
-
// if the seek position is outside the current fragment range
|
9548
|
-
if (currentTime < fragStartOffset || pastFragment) {
|
9549
|
-
if (pastFragment && fragCurrent.loader) {
|
9550
|
-
_this.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
|
9551
|
-
fragCurrent.abortRequests();
|
9552
|
-
_this.resetLoadingState();
|
9553
|
-
}
|
9554
|
-
_this.fragPrevious = null;
|
9555
|
-
}
|
9556
|
-
}
|
9557
|
-
}
|
9558
|
-
if (media) {
|
9559
|
-
// Remove gap fragments
|
9560
|
-
_this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, _this.playlistType, true);
|
9561
|
-
_this.lastCurrentTime = currentTime;
|
9562
|
-
}
|
9563
|
-
|
9564
|
-
// in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
|
9565
|
-
if (!_this.loadedmetadata && !bufferInfo.len) {
|
9566
|
-
_this.nextLoadPosition = _this.startPosition = currentTime;
|
9567
|
-
}
|
9568
|
-
|
9569
|
-
// Async tick to speed up processing
|
9570
|
-
_this.tickImmediate();
|
9571
|
-
};
|
9572
|
-
_this.onMediaEnded = function () {
|
9573
|
-
// reset startPosition and lastCurrentTime to restart playback @ stream beginning
|
9574
|
-
_this.startPosition = _this.lastCurrentTime = 0;
|
9575
|
-
};
|
9576
9459
|
_this.playlistType = playlistType;
|
9577
9460
|
_this.logPrefix = logPrefix;
|
9578
9461
|
_this.log = logger.log.bind(logger, logPrefix + ":");
|
@@ -9640,8 +9523,10 @@
|
|
9640
9523
|
};
|
9641
9524
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
9642
9525
|
var media = this.media = this.mediaBuffer = data.media;
|
9643
|
-
|
9644
|
-
|
9526
|
+
this.onvseeking = this.onMediaSeeking.bind(this);
|
9527
|
+
this.onvended = this.onMediaEnded.bind(this);
|
9528
|
+
media.addEventListener('seeking', this.onvseeking);
|
9529
|
+
media.addEventListener('ended', this.onvended);
|
9645
9530
|
var config = this.config;
|
9646
9531
|
if (this.levels && config.autoStartLoad && this.state === State.STOPPED) {
|
9647
9532
|
this.startLoad(config.startPosition);
|
@@ -9655,9 +9540,10 @@
|
|
9655
9540
|
}
|
9656
9541
|
|
9657
9542
|
// remove video listeners
|
9658
|
-
if (media) {
|
9659
|
-
media.removeEventListener('seeking', this.
|
9660
|
-
media.removeEventListener('ended', this.
|
9543
|
+
if (media && this.onvseeking && this.onvended) {
|
9544
|
+
media.removeEventListener('seeking', this.onvseeking);
|
9545
|
+
media.removeEventListener('ended', this.onvended);
|
9546
|
+
this.onvseeking = this.onvended = null;
|
9661
9547
|
}
|
9662
9548
|
if (this.keyLoader) {
|
9663
9549
|
this.keyLoader.detach();
|
@@ -9667,6 +9553,54 @@
|
|
9667
9553
|
this.fragmentTracker.removeAllFragments();
|
9668
9554
|
this.stopLoad();
|
9669
9555
|
};
|
9556
|
+
_proto.onMediaSeeking = function onMediaSeeking() {
|
9557
|
+
var config = this.config,
|
9558
|
+
fragCurrent = this.fragCurrent,
|
9559
|
+
media = this.media,
|
9560
|
+
mediaBuffer = this.mediaBuffer,
|
9561
|
+
state = this.state;
|
9562
|
+
var currentTime = media ? media.currentTime : 0;
|
9563
|
+
var bufferInfo = BufferHelper.bufferInfo(mediaBuffer ? mediaBuffer : media, currentTime, config.maxBufferHole);
|
9564
|
+
this.log("media seeking to " + (isFiniteNumber(currentTime) ? currentTime.toFixed(3) : currentTime) + ", state: " + state);
|
9565
|
+
if (this.state === State.ENDED) {
|
9566
|
+
this.resetLoadingState();
|
9567
|
+
} else if (fragCurrent) {
|
9568
|
+
// Seeking while frag load is in progress
|
9569
|
+
var tolerance = config.maxFragLookUpTolerance;
|
9570
|
+
var fragStartOffset = fragCurrent.start - tolerance;
|
9571
|
+
var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance;
|
9572
|
+
// if seeking out of buffered range or into new one
|
9573
|
+
if (!bufferInfo.len || fragEndOffset < bufferInfo.start || fragStartOffset > bufferInfo.end) {
|
9574
|
+
var pastFragment = currentTime > fragEndOffset;
|
9575
|
+
// if the seek position is outside the current fragment range
|
9576
|
+
if (currentTime < fragStartOffset || pastFragment) {
|
9577
|
+
if (pastFragment && fragCurrent.loader) {
|
9578
|
+
this.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
|
9579
|
+
fragCurrent.abortRequests();
|
9580
|
+
this.resetLoadingState();
|
9581
|
+
}
|
9582
|
+
this.fragPrevious = null;
|
9583
|
+
}
|
9584
|
+
}
|
9585
|
+
}
|
9586
|
+
if (media) {
|
9587
|
+
// Remove gap fragments
|
9588
|
+
this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, this.playlistType, true);
|
9589
|
+
this.lastCurrentTime = currentTime;
|
9590
|
+
}
|
9591
|
+
|
9592
|
+
// in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
|
9593
|
+
if (!this.loadedmetadata && !bufferInfo.len) {
|
9594
|
+
this.nextLoadPosition = this.startPosition = currentTime;
|
9595
|
+
}
|
9596
|
+
|
9597
|
+
// Async tick to speed up processing
|
9598
|
+
this.tickImmediate();
|
9599
|
+
};
|
9600
|
+
_proto.onMediaEnded = function onMediaEnded() {
|
9601
|
+
// reset startPosition and lastCurrentTime to restart playback @ stream beginning
|
9602
|
+
this.startPosition = this.lastCurrentTime = 0;
|
9603
|
+
};
|
9670
9604
|
_proto.onManifestLoaded = function onManifestLoaded(event, data) {
|
9671
9605
|
this.startTimeOffset = data.startTimeOffset;
|
9672
9606
|
this.initPTS = [];
|
@@ -9676,7 +9610,7 @@
|
|
9676
9610
|
this.stopLoad();
|
9677
9611
|
_TaskLoop.prototype.onHandlerDestroying.call(this);
|
9678
9612
|
// @ts-ignore
|
9679
|
-
this.hls =
|
9613
|
+
this.hls = null;
|
9680
9614
|
};
|
9681
9615
|
_proto.onHandlerDestroyed = function onHandlerDestroyed() {
|
9682
9616
|
this.state = State.STOPPED;
|
@@ -9806,10 +9740,10 @@
|
|
9806
9740
|
var decryptData = frag.decryptdata;
|
9807
9741
|
|
9808
9742
|
// check to see if the payload needs to be decrypted
|
9809
|
-
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv &&
|
9743
|
+
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && decryptData.method === 'AES-128') {
|
9810
9744
|
var startTime = self.performance.now();
|
9811
9745
|
// decrypt init segment data
|
9812
|
-
return _this3.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer
|
9746
|
+
return _this3.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).catch(function (err) {
|
9813
9747
|
hls.trigger(Events.ERROR, {
|
9814
9748
|
type: ErrorTypes.MEDIA_ERROR,
|
9815
9749
|
details: ErrorDetails.FRAG_DECRYPT_ERROR,
|
@@ -10947,7 +10881,6 @@
|
|
10947
10881
|
*/
|
10948
10882
|
function getAudioConfig(observer, data, offset, audioCodec) {
|
10949
10883
|
var adtsObjectType;
|
10950
|
-
var originalAdtsObjectType;
|
10951
10884
|
var adtsExtensionSamplingIndex;
|
10952
10885
|
var adtsChannelConfig;
|
10953
10886
|
var config;
|
@@ -10955,7 +10888,7 @@
|
|
10955
10888
|
var manifestCodec = audioCodec;
|
10956
10889
|
var adtsSamplingRates = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];
|
10957
10890
|
// byte 2
|
10958
|
-
adtsObjectType =
|
10891
|
+
adtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1;
|
10959
10892
|
var adtsSamplingIndex = (data[offset + 2] & 0x3c) >>> 2;
|
10960
10893
|
if (adtsSamplingIndex > adtsSamplingRates.length - 1) {
|
10961
10894
|
var error = new Error("invalid ADTS sampling index:" + adtsSamplingIndex);
|
@@ -10972,8 +10905,8 @@
|
|
10972
10905
|
// byte 3
|
10973
10906
|
adtsChannelConfig |= (data[offset + 3] & 0xc0) >>> 6;
|
10974
10907
|
logger.log("manifest codec:" + audioCodec + ", ADTS type:" + adtsObjectType + ", samplingIndex:" + adtsSamplingIndex);
|
10975
|
-
//
|
10976
|
-
if (/firefox
|
10908
|
+
// firefox: freq less than 24kHz = AAC SBR (HE-AAC)
|
10909
|
+
if (/firefox/i.test(userAgent)) {
|
10977
10910
|
if (adtsSamplingIndex >= 6) {
|
10978
10911
|
adtsObjectType = 5;
|
10979
10912
|
config = new Array(4);
|
@@ -11067,7 +11000,6 @@
|
|
11067
11000
|
samplerate: adtsSamplingRates[adtsSamplingIndex],
|
11068
11001
|
channelCount: adtsChannelConfig,
|
11069
11002
|
codec: 'mp4a.40.' + adtsObjectType,
|
11070
|
-
parsedCodec: 'mp4a.40.' + originalAdtsObjectType,
|
11071
11003
|
manifestCodec: manifestCodec
|
11072
11004
|
};
|
11073
11005
|
}
|
@@ -11122,8 +11054,7 @@
|
|
11122
11054
|
track.channelCount = config.channelCount;
|
11123
11055
|
track.codec = config.codec;
|
11124
11056
|
track.manifestCodec = config.manifestCodec;
|
11125
|
-
track.
|
11126
|
-
logger.log("parsed codec:" + track.parsedCodec + ", codec:" + track.codec + ", rate:" + config.samplerate + ", channels:" + config.channelCount);
|
11057
|
+
logger.log("parsed codec:" + track.codec + ", rate:" + config.samplerate + ", channels:" + config.channelCount);
|
11127
11058
|
}
|
11128
11059
|
}
|
11129
11060
|
function getFrameDuration(samplerate) {
|
@@ -12328,7 +12259,7 @@
|
|
12328
12259
|
}
|
12329
12260
|
var _proto = SampleAesDecrypter.prototype;
|
12330
12261
|
_proto.decryptBuffer = function decryptBuffer(encryptedData) {
|
12331
|
-
return this.decrypter.decrypt(encryptedData, this.keyData.key.buffer, this.keyData.iv.buffer
|
12262
|
+
return this.decrypter.decrypt(encryptedData, this.keyData.key.buffer, this.keyData.iv.buffer);
|
12332
12263
|
}
|
12333
12264
|
|
12334
12265
|
// AAC - encrypt all full 16 bytes blocks starting from offset 16
|
@@ -14607,7 +14538,7 @@
|
|
14607
14538
|
logger.warn("[mp4-remuxer]: Injecting " + missing + " audio frame @ " + (nextPts / inputTimeScale).toFixed(3) + "s due to " + Math.round(1000 * delta / inputTimeScale) + " ms gap.");
|
14608
14539
|
for (var j = 0; j < missing; j++) {
|
14609
14540
|
var newStamp = Math.max(nextPts, 0);
|
14610
|
-
var fillFrame = AAC.getSilentFrame(track.
|
14541
|
+
var fillFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
|
14611
14542
|
if (!fillFrame) {
|
14612
14543
|
logger.log('[mp4-remuxer]: Unable to get silent frame for given audio codec; duplicating last frame instead.');
|
14613
14544
|
fillFrame = sample.unit.subarray();
|
@@ -14735,7 +14666,7 @@
|
|
14735
14666
|
// samples count of this segment's duration
|
14736
14667
|
var nbSamples = Math.ceil((endDTS - startDTS) / frameDuration);
|
14737
14668
|
// silent frame
|
14738
|
-
var silentFrame = AAC.getSilentFrame(track.
|
14669
|
+
var silentFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
|
14739
14670
|
logger.warn('[mp4-remuxer]: remux empty Audio');
|
14740
14671
|
// Can't remux if we can't generate a silent frame...
|
14741
14672
|
if (!silentFrame) {
|
@@ -15125,15 +15056,13 @@
|
|
15125
15056
|
duration = transmuxConfig.duration,
|
15126
15057
|
initSegmentData = transmuxConfig.initSegmentData;
|
15127
15058
|
var keyData = getEncryptionType(uintData, decryptdata);
|
15128
|
-
if (keyData &&
|
15059
|
+
if (keyData && keyData.method === 'AES-128') {
|
15129
15060
|
var decrypter = this.getDecrypter();
|
15130
|
-
var aesMode = getAesModeFromFullSegmentMethod(keyData.method);
|
15131
|
-
|
15132
15061
|
// Software decryption is synchronous; webCrypto is not
|
15133
15062
|
if (decrypter.isSync()) {
|
15134
15063
|
// Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
|
15135
15064
|
// data is handled in the flush() call
|
15136
|
-
var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer
|
15065
|
+
var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer);
|
15137
15066
|
// For Low-Latency HLS Parts, decrypt in place, since part parsing is expected on push progress
|
15138
15067
|
var loadingParts = chunkMeta.part > -1;
|
15139
15068
|
if (loadingParts) {
|
@@ -15145,7 +15074,7 @@
|
|
15145
15074
|
}
|
15146
15075
|
uintData = new Uint8Array(decryptedData);
|
15147
15076
|
} else {
|
15148
|
-
this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer
|
15077
|
+
this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer).then(function (decryptedData) {
|
15149
15078
|
// Calling push here is important; if flush() is called while this is still resolving, this ensures that
|
15150
15079
|
// the decrypted data has been transmuxed
|
15151
15080
|
var result = _this.push(decryptedData, null, chunkMeta);
|
@@ -15962,7 +15891,16 @@
|
|
15962
15891
|
this.observer = new EventEmitter();
|
15963
15892
|
this.observer.on(Events.FRAG_DECRYPTED, forwardMessage);
|
15964
15893
|
this.observer.on(Events.ERROR, forwardMessage);
|
15965
|
-
var
|
15894
|
+
var MediaSource = getMediaSource(config.preferManagedMediaSource) || {
|
15895
|
+
isTypeSupported: function isTypeSupported() {
|
15896
|
+
return false;
|
15897
|
+
}
|
15898
|
+
};
|
15899
|
+
var m2tsTypeSupported = {
|
15900
|
+
mpeg: MediaSource.isTypeSupported('audio/mpeg'),
|
15901
|
+
mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
|
15902
|
+
ac3: MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"')
|
15903
|
+
};
|
15966
15904
|
|
15967
15905
|
// navigator.vendor is not always available in Web Worker
|
15968
15906
|
// refer to https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/navigator
|
@@ -17573,10 +17511,10 @@
|
|
17573
17511
|
return;
|
17574
17512
|
}
|
17575
17513
|
// check to see if the payload needs to be decrypted
|
17576
|
-
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv &&
|
17514
|
+
if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && decryptData.method === 'AES-128') {
|
17577
17515
|
var startTime = performance.now();
|
17578
17516
|
// decrypt the subtitles
|
17579
|
-
this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer
|
17517
|
+
this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).catch(function (err) {
|
17580
17518
|
hls.trigger(Events.ERROR, {
|
17581
17519
|
type: ErrorTypes.MEDIA_ERROR,
|
17582
17520
|
details: ErrorDetails.FRAG_DECRYPT_ERROR,
|
@@ -17717,12 +17655,12 @@
|
|
17717
17655
|
_this.currentTrack = null;
|
17718
17656
|
_this.selectDefaultTrack = true;
|
17719
17657
|
_this.queuedDefaultTrack = -1;
|
17720
|
-
_this.useTextTrackPolling = false;
|
17721
|
-
_this.subtitlePollingInterval = -1;
|
17722
|
-
_this._subtitleDisplay = true;
|
17723
17658
|
_this.asyncPollTrackChange = function () {
|
17724
17659
|
return _this.pollTrackChange(0);
|
17725
17660
|
};
|
17661
|
+
_this.useTextTrackPolling = false;
|
17662
|
+
_this.subtitlePollingInterval = -1;
|
17663
|
+
_this._subtitleDisplay = true;
|
17726
17664
|
_this.onTextTracksChanged = function () {
|
17727
17665
|
if (!_this.useTextTrackPolling) {
|
17728
17666
|
self.clearInterval(_this.subtitlePollingInterval);
|
@@ -17758,7 +17696,6 @@
|
|
17758
17696
|
this.tracks.length = 0;
|
17759
17697
|
this.tracksInGroup.length = 0;
|
17760
17698
|
this.currentTrack = null;
|
17761
|
-
// @ts-ignore
|
17762
17699
|
this.onTextTracksChanged = this.asyncPollTrackChange = null;
|
17763
17700
|
_BasePlaylistControll.prototype.destroy.call(this);
|
17764
17701
|
};
|
@@ -18330,12 +18267,6 @@
|
|
18330
18267
|
this.lastMpegAudioChunk = null;
|
18331
18268
|
// @ts-ignore
|
18332
18269
|
this.hls = null;
|
18333
|
-
// @ts-ignore
|
18334
|
-
this._onMediaSourceOpen = this._onMediaSourceClose = null;
|
18335
|
-
// @ts-ignore
|
18336
|
-
this._onMediaSourceEnded = null;
|
18337
|
-
// @ts-ignore
|
18338
|
-
this._onStartStreaming = this._onEndStreaming = null;
|
18339
18270
|
};
|
18340
18271
|
_proto.registerListeners = function registerListeners() {
|
18341
18272
|
var hls = this.hls;
|
@@ -21635,12 +21566,14 @@
|
|
21635
21566
|
this.cea608Parser1 = this.cea608Parser2 = undefined;
|
21636
21567
|
};
|
21637
21568
|
_proto.initCea608Parsers = function initCea608Parsers() {
|
21638
|
-
|
21639
|
-
|
21640
|
-
|
21641
|
-
|
21642
|
-
|
21643
|
-
|
21569
|
+
if (this.config.enableCEA708Captions && (!this.cea608Parser1 || !this.cea608Parser2)) {
|
21570
|
+
var channel1 = new OutputFilter(this, 'textTrack1');
|
21571
|
+
var channel2 = new OutputFilter(this, 'textTrack2');
|
21572
|
+
var channel3 = new OutputFilter(this, 'textTrack3');
|
21573
|
+
var channel4 = new OutputFilter(this, 'textTrack4');
|
21574
|
+
this.cea608Parser1 = new Cea608Parser(1, channel1, channel2);
|
21575
|
+
this.cea608Parser2 = new Cea608Parser(3, channel3, channel4);
|
21576
|
+
}
|
21644
21577
|
};
|
21645
21578
|
_proto.addCues = function addCues(trackName, startTime, endTime, screen, cueRanges) {
|
21646
21579
|
// skip cues which overlap more than 50% with previously parsed time ranges
|
@@ -21921,20 +21854,23 @@
|
|
21921
21854
|
return level == null ? void 0 : level.attrs['CLOSED-CAPTIONS'];
|
21922
21855
|
};
|
21923
21856
|
_proto.onFragLoading = function onFragLoading(event, data) {
|
21857
|
+
this.initCea608Parsers();
|
21858
|
+
var cea608Parser1 = this.cea608Parser1,
|
21859
|
+
cea608Parser2 = this.cea608Parser2,
|
21860
|
+
lastCc = this.lastCc,
|
21861
|
+
lastSn = this.lastSn,
|
21862
|
+
lastPartIndex = this.lastPartIndex;
|
21863
|
+
if (!this.enabled || !cea608Parser1 || !cea608Parser2) {
|
21864
|
+
return;
|
21865
|
+
}
|
21924
21866
|
// if this frag isn't contiguous, clear the parser so cues with bad start/end times aren't added to the textTrack
|
21925
|
-
if (
|
21867
|
+
if (data.frag.type === PlaylistLevelType.MAIN) {
|
21926
21868
|
var _data$part$index, _data$part;
|
21927
|
-
var cea608Parser1 = this.cea608Parser1,
|
21928
|
-
cea608Parser2 = this.cea608Parser2,
|
21929
|
-
lastSn = this.lastSn;
|
21930
|
-
if (!cea608Parser1 || !cea608Parser2) {
|
21931
|
-
return;
|
21932
|
-
}
|
21933
21869
|
var _data$frag = data.frag,
|
21934
21870
|
cc = _data$frag.cc,
|
21935
21871
|
sn = _data$frag.sn;
|
21936
|
-
var partIndex = (_data$part$index = (_data$part = data.part) == null ? void 0 : _data$part.index) != null ? _data$part$index : -1;
|
21937
|
-
if (!(sn === lastSn + 1 || sn === lastSn && partIndex ===
|
21872
|
+
var partIndex = (_data$part$index = data == null ? void 0 : (_data$part = data.part) == null ? void 0 : _data$part.index) != null ? _data$part$index : -1;
|
21873
|
+
if (!(sn === lastSn + 1 || sn === lastSn && partIndex === lastPartIndex + 1 || cc === lastCc)) {
|
21938
21874
|
cea608Parser1.reset();
|
21939
21875
|
cea608Parser2.reset();
|
21940
21876
|
}
|
@@ -22090,7 +22026,10 @@
|
|
22090
22026
|
this.captionsTracks = {};
|
22091
22027
|
};
|
22092
22028
|
_proto.onFragParsingUserdata = function onFragParsingUserdata(event, data) {
|
22093
|
-
|
22029
|
+
this.initCea608Parsers();
|
22030
|
+
var cea608Parser1 = this.cea608Parser1,
|
22031
|
+
cea608Parser2 = this.cea608Parser2;
|
22032
|
+
if (!this.enabled || !cea608Parser1 || !cea608Parser2) {
|
22094
22033
|
return;
|
22095
22034
|
}
|
22096
22035
|
var frag = data.frag,
|
@@ -22103,12 +22042,9 @@
|
|
22103
22042
|
for (var i = 0; i < samples.length; i++) {
|
22104
22043
|
var ccBytes = samples[i].bytes;
|
22105
22044
|
if (ccBytes) {
|
22106
|
-
if (!this.cea608Parser1) {
|
22107
|
-
this.initCea608Parsers();
|
22108
|
-
}
|
22109
22045
|
var ccdatas = this.extractCea608Data(ccBytes);
|
22110
|
-
|
22111
|
-
|
22046
|
+
cea608Parser1.addData(samples[i].pts, ccdatas[0]);
|
22047
|
+
cea608Parser2.addData(samples[i].pts, ccdatas[1]);
|
22112
22048
|
}
|
22113
22049
|
}
|
22114
22050
|
};
|
@@ -22536,7 +22472,6 @@
|
|
22536
22472
|
*/
|
22537
22473
|
var EMEController = /*#__PURE__*/function () {
|
22538
22474
|
function EMEController(hls) {
|
22539
|
-
var _this = this;
|
22540
22475
|
this.hls = void 0;
|
22541
22476
|
this.config = void 0;
|
22542
22477
|
this.media = null;
|
@@ -22546,107 +22481,12 @@
|
|
22546
22481
|
this.mediaKeySessions = [];
|
22547
22482
|
this.keyIdToKeySessionPromise = {};
|
22548
22483
|
this.setMediaKeysQueue = EMEController.CDMCleanupPromise ? [EMEController.CDMCleanupPromise] : [];
|
22484
|
+
this.onMediaEncrypted = this._onMediaEncrypted.bind(this);
|
22485
|
+
this.onWaitingForKey = this._onWaitingForKey.bind(this);
|
22549
22486
|
this.debug = logger.debug.bind(logger, LOGGER_PREFIX);
|
22550
22487
|
this.log = logger.log.bind(logger, LOGGER_PREFIX);
|
22551
22488
|
this.warn = logger.warn.bind(logger, LOGGER_PREFIX);
|
22552
22489
|
this.error = logger.error.bind(logger, LOGGER_PREFIX);
|
22553
|
-
this.onMediaEncrypted = function (event) {
|
22554
|
-
var initDataType = event.initDataType,
|
22555
|
-
initData = event.initData;
|
22556
|
-
_this.debug("\"" + event.type + "\" event: init data type: \"" + initDataType + "\"");
|
22557
|
-
|
22558
|
-
// Ignore event when initData is null
|
22559
|
-
if (initData === null) {
|
22560
|
-
return;
|
22561
|
-
}
|
22562
|
-
var keyId;
|
22563
|
-
var keySystemDomain;
|
22564
|
-
if (initDataType === 'sinf' && _this.config.drmSystems[KeySystems.FAIRPLAY]) {
|
22565
|
-
// Match sinf keyId to playlist skd://keyId=
|
22566
|
-
var json = bin2str(new Uint8Array(initData));
|
22567
|
-
try {
|
22568
|
-
var sinf = base64Decode(JSON.parse(json).sinf);
|
22569
|
-
var tenc = parseSinf(new Uint8Array(sinf));
|
22570
|
-
if (!tenc) {
|
22571
|
-
return;
|
22572
|
-
}
|
22573
|
-
keyId = tenc.subarray(8, 24);
|
22574
|
-
keySystemDomain = KeySystems.FAIRPLAY;
|
22575
|
-
} catch (error) {
|
22576
|
-
_this.warn('Failed to parse sinf "encrypted" event message initData');
|
22577
|
-
return;
|
22578
|
-
}
|
22579
|
-
} else {
|
22580
|
-
// Support clear-lead key-session creation (otherwise depend on playlist keys)
|
22581
|
-
var psshInfo = parsePssh(initData);
|
22582
|
-
if (psshInfo === null) {
|
22583
|
-
return;
|
22584
|
-
}
|
22585
|
-
if (psshInfo.version === 0 && psshInfo.systemId === KeySystemIds.WIDEVINE && psshInfo.data) {
|
22586
|
-
keyId = psshInfo.data.subarray(8, 24);
|
22587
|
-
}
|
22588
|
-
keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
|
22589
|
-
}
|
22590
|
-
if (!keySystemDomain || !keyId) {
|
22591
|
-
return;
|
22592
|
-
}
|
22593
|
-
var keyIdHex = Hex.hexDump(keyId);
|
22594
|
-
var keyIdToKeySessionPromise = _this.keyIdToKeySessionPromise,
|
22595
|
-
mediaKeySessions = _this.mediaKeySessions;
|
22596
|
-
var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
|
22597
|
-
var _loop = function _loop() {
|
22598
|
-
// Match playlist key
|
22599
|
-
var keyContext = mediaKeySessions[i];
|
22600
|
-
var decryptdata = keyContext.decryptdata;
|
22601
|
-
if (decryptdata.pssh || !decryptdata.keyId) {
|
22602
|
-
return 0; // continue
|
22603
|
-
}
|
22604
|
-
var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
|
22605
|
-
if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
|
22606
|
-
keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
|
22607
|
-
delete keyIdToKeySessionPromise[oldKeyIdHex];
|
22608
|
-
decryptdata.pssh = new Uint8Array(initData);
|
22609
|
-
decryptdata.keyId = keyId;
|
22610
|
-
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
|
22611
|
-
return _this.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
|
22612
|
-
});
|
22613
|
-
return 1; // break
|
22614
|
-
}
|
22615
|
-
},
|
22616
|
-
_ret;
|
22617
|
-
for (var i = 0; i < mediaKeySessions.length; i++) {
|
22618
|
-
_ret = _loop();
|
22619
|
-
if (_ret === 0) continue;
|
22620
|
-
if (_ret === 1) break;
|
22621
|
-
}
|
22622
|
-
if (!keySessionContextPromise) {
|
22623
|
-
// Clear-lead key (not encountered in playlist)
|
22624
|
-
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = _this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref) {
|
22625
|
-
var _keySystemToKeySystem;
|
22626
|
-
var keySystem = _ref.keySystem,
|
22627
|
-
mediaKeys = _ref.mediaKeys;
|
22628
|
-
_this.throwIfDestroyed();
|
22629
|
-
var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
|
22630
|
-
decryptdata.pssh = new Uint8Array(initData);
|
22631
|
-
decryptdata.keyId = keyId;
|
22632
|
-
return _this.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
22633
|
-
_this.throwIfDestroyed();
|
22634
|
-
var keySessionContext = _this.createMediaKeySessionContext({
|
22635
|
-
decryptdata: decryptdata,
|
22636
|
-
keySystem: keySystem,
|
22637
|
-
mediaKeys: mediaKeys
|
22638
|
-
});
|
22639
|
-
return _this.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
|
22640
|
-
});
|
22641
|
-
});
|
22642
|
-
}
|
22643
|
-
keySessionContextPromise.catch(function (error) {
|
22644
|
-
return _this.handleError(error);
|
22645
|
-
});
|
22646
|
-
};
|
22647
|
-
this.onWaitingForKey = function (event) {
|
22648
|
-
_this.log("\"" + event.type + "\" event");
|
22649
|
-
};
|
22650
22490
|
this.hls = hls;
|
22651
22491
|
this.config = hls.config;
|
22652
22492
|
this.registerListeners();
|
@@ -22661,9 +22501,9 @@
|
|
22661
22501
|
config.licenseXhrSetup = config.licenseResponseCallback = undefined;
|
22662
22502
|
config.drmSystems = config.drmSystemOptions = {};
|
22663
22503
|
// @ts-ignore
|
22664
|
-
this.hls = this.
|
22504
|
+
this.hls = this.onMediaEncrypted = this.onWaitingForKey = this.keyIdToKeySessionPromise = null;
|
22665
22505
|
// @ts-ignore
|
22666
|
-
this.
|
22506
|
+
this.config = null;
|
22667
22507
|
};
|
22668
22508
|
_proto.registerListeners = function registerListeners() {
|
22669
22509
|
this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
|
@@ -22702,7 +22542,7 @@
|
|
22702
22542
|
}
|
22703
22543
|
};
|
22704
22544
|
_proto.attemptKeySystemAccess = function attemptKeySystemAccess(keySystemsToAttempt) {
|
22705
|
-
var
|
22545
|
+
var _this = this;
|
22706
22546
|
var levels = this.hls.levels;
|
22707
22547
|
var uniqueCodec = function uniqueCodec(value, i, a) {
|
22708
22548
|
return !!value && a.indexOf(value) === i;
|
@@ -22719,7 +22559,7 @@
|
|
22719
22559
|
return new Promise(function (resolve, reject) {
|
22720
22560
|
var attempt = function attempt(keySystems) {
|
22721
22561
|
var keySystem = keySystems.shift();
|
22722
|
-
|
22562
|
+
_this.getMediaKeysPromise(keySystem, audioCodecs, videoCodecs).then(function (mediaKeys) {
|
22723
22563
|
return resolve({
|
22724
22564
|
keySystem: keySystem,
|
22725
22565
|
mediaKeys: mediaKeys
|
@@ -22754,7 +22594,7 @@
|
|
22754
22594
|
return requestMediaKeySystemAccessFunc(keySystem, supportedConfigurations);
|
22755
22595
|
};
|
22756
22596
|
_proto.getMediaKeysPromise = function getMediaKeysPromise(keySystem, audioCodecs, videoCodecs) {
|
22757
|
-
var
|
22597
|
+
var _this2 = this;
|
22758
22598
|
// This can throw, but is caught in event handler callpath
|
22759
22599
|
var mediaKeySystemConfigs = getSupportedMediaKeySystemConfigurations(keySystem, audioCodecs, videoCodecs, this.config.drmSystemOptions);
|
22760
22600
|
var keySystemAccessPromises = this.keySystemAccessPromises[keySystem];
|
@@ -22766,23 +22606,23 @@
|
|
22766
22606
|
keySystemAccess: keySystemAccess
|
22767
22607
|
};
|
22768
22608
|
keySystemAccess.catch(function (error) {
|
22769
|
-
|
22609
|
+
_this2.log("Failed to obtain access to key-system \"" + keySystem + "\": " + error);
|
22770
22610
|
});
|
22771
22611
|
return keySystemAccess.then(function (mediaKeySystemAccess) {
|
22772
|
-
|
22773
|
-
var certificateRequest =
|
22774
|
-
|
22612
|
+
_this2.log("Access for key-system \"" + mediaKeySystemAccess.keySystem + "\" obtained");
|
22613
|
+
var certificateRequest = _this2.fetchServerCertificate(keySystem);
|
22614
|
+
_this2.log("Create media-keys for \"" + keySystem + "\"");
|
22775
22615
|
_keySystemAccessPromises.mediaKeys = mediaKeySystemAccess.createMediaKeys().then(function (mediaKeys) {
|
22776
|
-
|
22616
|
+
_this2.log("Media-keys created for \"" + keySystem + "\"");
|
22777
22617
|
return certificateRequest.then(function (certificate) {
|
22778
22618
|
if (certificate) {
|
22779
|
-
return
|
22619
|
+
return _this2.setMediaKeysServerCertificate(mediaKeys, keySystem, certificate);
|
22780
22620
|
}
|
22781
22621
|
return mediaKeys;
|
22782
22622
|
});
|
22783
22623
|
});
|
22784
22624
|
_keySystemAccessPromises.mediaKeys.catch(function (error) {
|
22785
|
-
|
22625
|
+
_this2.error("Failed to create media-keys for \"" + keySystem + "\"}: " + error);
|
22786
22626
|
});
|
22787
22627
|
return _keySystemAccessPromises.mediaKeys;
|
22788
22628
|
});
|
@@ -22791,10 +22631,10 @@
|
|
22791
22631
|
return keySystemAccessPromises.mediaKeys;
|
22792
22632
|
});
|
22793
22633
|
};
|
22794
|
-
_proto.createMediaKeySessionContext = function createMediaKeySessionContext(
|
22795
|
-
var decryptdata =
|
22796
|
-
keySystem =
|
22797
|
-
mediaKeys =
|
22634
|
+
_proto.createMediaKeySessionContext = function createMediaKeySessionContext(_ref) {
|
22635
|
+
var decryptdata = _ref.decryptdata,
|
22636
|
+
keySystem = _ref.keySystem,
|
22637
|
+
mediaKeys = _ref.mediaKeys;
|
22798
22638
|
this.log("Creating key-system session \"" + keySystem + "\" keyId: " + Hex.hexDump(decryptdata.keyId || []));
|
22799
22639
|
var mediaKeysSession = mediaKeys.createSession();
|
22800
22640
|
var mediaKeySessionContext = {
|
@@ -22843,14 +22683,14 @@
|
|
22843
22683
|
return this.keyFormatPromise;
|
22844
22684
|
};
|
22845
22685
|
_proto.getKeyFormatPromise = function getKeyFormatPromise(keyFormats) {
|
22846
|
-
var
|
22686
|
+
var _this3 = this;
|
22847
22687
|
return new Promise(function (resolve, reject) {
|
22848
|
-
var keySystemsInConfig = getKeySystemsForConfig(
|
22688
|
+
var keySystemsInConfig = getKeySystemsForConfig(_this3.config);
|
22849
22689
|
var keySystemsToAttempt = keyFormats.map(keySystemFormatToKeySystemDomain).filter(function (value) {
|
22850
22690
|
return !!value && keySystemsInConfig.indexOf(value) !== -1;
|
22851
22691
|
});
|
22852
|
-
return
|
22853
|
-
var keySystem =
|
22692
|
+
return _this3.getKeySystemSelectionPromise(keySystemsToAttempt).then(function (_ref2) {
|
22693
|
+
var keySystem = _ref2.keySystem;
|
22854
22694
|
var keySystemFormat = keySystemDomainToKeySystemFormat(keySystem);
|
22855
22695
|
if (keySystemFormat) {
|
22856
22696
|
resolve(keySystemFormat);
|
@@ -22861,31 +22701,31 @@
|
|
22861
22701
|
});
|
22862
22702
|
};
|
22863
22703
|
_proto.loadKey = function loadKey(data) {
|
22864
|
-
var
|
22704
|
+
var _this4 = this;
|
22865
22705
|
var decryptdata = data.keyInfo.decryptdata;
|
22866
22706
|
var keyId = this.getKeyIdString(decryptdata);
|
22867
22707
|
var keyDetails = "(keyId: " + keyId + " format: \"" + decryptdata.keyFormat + "\" method: " + decryptdata.method + " uri: " + decryptdata.uri + ")";
|
22868
22708
|
this.log("Starting session for key " + keyDetails);
|
22869
22709
|
var keySessionContextPromise = this.keyIdToKeySessionPromise[keyId];
|
22870
22710
|
if (!keySessionContextPromise) {
|
22871
|
-
keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (
|
22872
|
-
var keySystem =
|
22873
|
-
mediaKeys =
|
22874
|
-
|
22875
|
-
|
22876
|
-
return
|
22877
|
-
|
22878
|
-
var keySessionContext =
|
22711
|
+
keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (_ref3) {
|
22712
|
+
var keySystem = _ref3.keySystem,
|
22713
|
+
mediaKeys = _ref3.mediaKeys;
|
22714
|
+
_this4.throwIfDestroyed();
|
22715
|
+
_this4.log("Handle encrypted media sn: " + data.frag.sn + " " + data.frag.type + ": " + data.frag.level + " using key " + keyDetails);
|
22716
|
+
return _this4.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
22717
|
+
_this4.throwIfDestroyed();
|
22718
|
+
var keySessionContext = _this4.createMediaKeySessionContext({
|
22879
22719
|
keySystem: keySystem,
|
22880
22720
|
mediaKeys: mediaKeys,
|
22881
22721
|
decryptdata: decryptdata
|
22882
22722
|
});
|
22883
22723
|
var scheme = 'cenc';
|
22884
|
-
return
|
22724
|
+
return _this4.generateRequestWithPreferredKeySession(keySessionContext, scheme, decryptdata.pssh, 'playlist-key');
|
22885
22725
|
});
|
22886
22726
|
});
|
22887
22727
|
keySessionContextPromise.catch(function (error) {
|
22888
|
-
return
|
22728
|
+
return _this4.handleError(error);
|
22889
22729
|
});
|
22890
22730
|
}
|
22891
22731
|
return keySessionContextPromise;
|
@@ -22936,6 +22776,104 @@
|
|
22936
22776
|
}
|
22937
22777
|
return this.attemptKeySystemAccess(keySystemsToAttempt);
|
22938
22778
|
};
|
22779
|
+
_proto._onMediaEncrypted = function _onMediaEncrypted(event) {
|
22780
|
+
var _this5 = this;
|
22781
|
+
var initDataType = event.initDataType,
|
22782
|
+
initData = event.initData;
|
22783
|
+
this.debug("\"" + event.type + "\" event: init data type: \"" + initDataType + "\"");
|
22784
|
+
|
22785
|
+
// Ignore event when initData is null
|
22786
|
+
if (initData === null) {
|
22787
|
+
return;
|
22788
|
+
}
|
22789
|
+
var keyId;
|
22790
|
+
var keySystemDomain;
|
22791
|
+
if (initDataType === 'sinf' && this.config.drmSystems[KeySystems.FAIRPLAY]) {
|
22792
|
+
// Match sinf keyId to playlist skd://keyId=
|
22793
|
+
var json = bin2str(new Uint8Array(initData));
|
22794
|
+
try {
|
22795
|
+
var sinf = base64Decode(JSON.parse(json).sinf);
|
22796
|
+
var tenc = parseSinf(new Uint8Array(sinf));
|
22797
|
+
if (!tenc) {
|
22798
|
+
return;
|
22799
|
+
}
|
22800
|
+
keyId = tenc.subarray(8, 24);
|
22801
|
+
keySystemDomain = KeySystems.FAIRPLAY;
|
22802
|
+
} catch (error) {
|
22803
|
+
this.warn('Failed to parse sinf "encrypted" event message initData');
|
22804
|
+
return;
|
22805
|
+
}
|
22806
|
+
} else {
|
22807
|
+
// Support clear-lead key-session creation (otherwise depend on playlist keys)
|
22808
|
+
var psshInfo = parsePssh(initData);
|
22809
|
+
if (psshInfo === null) {
|
22810
|
+
return;
|
22811
|
+
}
|
22812
|
+
if (psshInfo.version === 0 && psshInfo.systemId === KeySystemIds.WIDEVINE && psshInfo.data) {
|
22813
|
+
keyId = psshInfo.data.subarray(8, 24);
|
22814
|
+
}
|
22815
|
+
keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
|
22816
|
+
}
|
22817
|
+
if (!keySystemDomain || !keyId) {
|
22818
|
+
return;
|
22819
|
+
}
|
22820
|
+
var keyIdHex = Hex.hexDump(keyId);
|
22821
|
+
var keyIdToKeySessionPromise = this.keyIdToKeySessionPromise,
|
22822
|
+
mediaKeySessions = this.mediaKeySessions;
|
22823
|
+
var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
|
22824
|
+
var _loop = function _loop() {
|
22825
|
+
// Match playlist key
|
22826
|
+
var keyContext = mediaKeySessions[i];
|
22827
|
+
var decryptdata = keyContext.decryptdata;
|
22828
|
+
if (decryptdata.pssh || !decryptdata.keyId) {
|
22829
|
+
return 0; // continue
|
22830
|
+
}
|
22831
|
+
var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
|
22832
|
+
if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
|
22833
|
+
keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
|
22834
|
+
delete keyIdToKeySessionPromise[oldKeyIdHex];
|
22835
|
+
decryptdata.pssh = new Uint8Array(initData);
|
22836
|
+
decryptdata.keyId = keyId;
|
22837
|
+
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
|
22838
|
+
return _this5.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
|
22839
|
+
});
|
22840
|
+
return 1; // break
|
22841
|
+
}
|
22842
|
+
},
|
22843
|
+
_ret;
|
22844
|
+
for (var i = 0; i < mediaKeySessions.length; i++) {
|
22845
|
+
_ret = _loop();
|
22846
|
+
if (_ret === 0) continue;
|
22847
|
+
if (_ret === 1) break;
|
22848
|
+
}
|
22849
|
+
if (!keySessionContextPromise) {
|
22850
|
+
// Clear-lead key (not encountered in playlist)
|
22851
|
+
keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref4) {
|
22852
|
+
var _keySystemToKeySystem;
|
22853
|
+
var keySystem = _ref4.keySystem,
|
22854
|
+
mediaKeys = _ref4.mediaKeys;
|
22855
|
+
_this5.throwIfDestroyed();
|
22856
|
+
var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
|
22857
|
+
decryptdata.pssh = new Uint8Array(initData);
|
22858
|
+
decryptdata.keyId = keyId;
|
22859
|
+
return _this5.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
|
22860
|
+
_this5.throwIfDestroyed();
|
22861
|
+
var keySessionContext = _this5.createMediaKeySessionContext({
|
22862
|
+
decryptdata: decryptdata,
|
22863
|
+
keySystem: keySystem,
|
22864
|
+
mediaKeys: mediaKeys
|
22865
|
+
});
|
22866
|
+
return _this5.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
|
22867
|
+
});
|
22868
|
+
});
|
22869
|
+
}
|
22870
|
+
keySessionContextPromise.catch(function (error) {
|
22871
|
+
return _this5.handleError(error);
|
22872
|
+
});
|
22873
|
+
};
|
22874
|
+
_proto._onWaitingForKey = function _onWaitingForKey(event) {
|
22875
|
+
this.log("\"" + event.type + "\" event");
|
22876
|
+
};
|
22939
22877
|
_proto.attemptSetMediaKeys = function attemptSetMediaKeys(keySystem, mediaKeys) {
|
22940
22878
|
var _this6 = this;
|
22941
22879
|
var queue = this.setMediaKeysQueue.slice();
|
@@ -26097,6 +26035,7 @@
|
|
26097
26035
|
}
|
26098
26036
|
}
|
26099
26037
|
|
26038
|
+
var chromeOrFirefox;
|
26100
26039
|
var LevelController = /*#__PURE__*/function (_BasePlaylistControll) {
|
26101
26040
|
_inheritsLoose(LevelController, _BasePlaylistControll);
|
26102
26041
|
function LevelController(hls, contentSteeringController) {
|
@@ -26170,13 +26109,21 @@
|
|
26170
26109
|
var videoCodecFound = false;
|
26171
26110
|
var audioCodecFound = false;
|
26172
26111
|
data.levels.forEach(function (levelParsed) {
|
26173
|
-
var _videoCodec;
|
26112
|
+
var _audioCodec, _videoCodec;
|
26174
26113
|
var attributes = levelParsed.attrs;
|
26114
|
+
|
26115
|
+
// erase audio codec info if browser does not support mp4a.40.34.
|
26116
|
+
// demuxer will autodetect codec and fallback to mpeg/audio
|
26175
26117
|
var audioCodec = levelParsed.audioCodec,
|
26176
26118
|
videoCodec = levelParsed.videoCodec;
|
26119
|
+
if (((_audioCodec = audioCodec) == null ? void 0 : _audioCodec.indexOf('mp4a.40.34')) !== -1) {
|
26120
|
+
chromeOrFirefox || (chromeOrFirefox = /chrome|firefox/i.test(navigator.userAgent));
|
26121
|
+
if (chromeOrFirefox) {
|
26122
|
+
levelParsed.audioCodec = audioCodec = undefined;
|
26123
|
+
}
|
26124
|
+
}
|
26177
26125
|
if (audioCodec) {
|
26178
|
-
|
26179
|
-
levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource) || undefined;
|
26126
|
+
levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource);
|
26180
26127
|
}
|
26181
26128
|
if (((_videoCodec = videoCodec) == null ? void 0 : _videoCodec.indexOf('avc1')) === 0) {
|
26182
26129
|
videoCodec = levelParsed.videoCodec = convertAVC1ToAVCOTI(videoCodec);
|
@@ -26299,8 +26246,8 @@
|
|
26299
26246
|
return _valueB - _valueA;
|
26300
26247
|
}
|
26301
26248
|
}
|
26302
|
-
if (a.
|
26303
|
-
return a.
|
26249
|
+
if (a.averageBitrate !== b.averageBitrate) {
|
26250
|
+
return a.averageBitrate - b.averageBitrate;
|
26304
26251
|
}
|
26305
26252
|
return 0;
|
26306
26253
|
});
|
@@ -26784,8 +26731,6 @@
|
|
26784
26731
|
}
|
26785
26732
|
return this.loadKeyEME(keyInfo, frag);
|
26786
26733
|
case 'AES-128':
|
26787
|
-
case 'AES-256':
|
26788
|
-
case 'AES-256-CTR':
|
26789
26734
|
return this.loadKeyHTTP(keyInfo, frag);
|
26790
26735
|
default:
|
26791
26736
|
return Promise.reject(this.createKeyLoadError(frag, ErrorDetails.KEY_LOAD_ERROR, new Error("Key supplied with unsupported METHOD: \"" + decryptdata.method + "\"")));
|
@@ -27246,32 +27191,13 @@
|
|
27246
27191
|
_this.altAudio = false;
|
27247
27192
|
_this.audioOnly = false;
|
27248
27193
|
_this.fragPlaying = null;
|
27194
|
+
_this.onvplaying = null;
|
27195
|
+
_this.onvseeked = null;
|
27249
27196
|
_this.fragLastKbps = 0;
|
27250
27197
|
_this.couldBacktrack = false;
|
27251
27198
|
_this.backtrackFragment = null;
|
27252
27199
|
_this.audioCodecSwitch = false;
|
27253
27200
|
_this.videoBuffer = null;
|
27254
|
-
_this.onMediaPlaying = function () {
|
27255
|
-
// tick to speed up FRAG_CHANGED triggering
|
27256
|
-
_this.tick();
|
27257
|
-
};
|
27258
|
-
_this.onMediaSeeked = function () {
|
27259
|
-
var media = _this.media;
|
27260
|
-
var currentTime = media ? media.currentTime : null;
|
27261
|
-
if (isFiniteNumber(currentTime)) {
|
27262
|
-
_this.log("Media seeked to " + currentTime.toFixed(3));
|
27263
|
-
}
|
27264
|
-
|
27265
|
-
// If seeked was issued before buffer was appended do not tick immediately
|
27266
|
-
var bufferInfo = _this.getMainFwdBufferInfo();
|
27267
|
-
if (bufferInfo === null || bufferInfo.len === 0) {
|
27268
|
-
_this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
|
27269
|
-
return;
|
27270
|
-
}
|
27271
|
-
|
27272
|
-
// tick to speed up FRAG_CHANGED triggering
|
27273
|
-
_this.tick();
|
27274
|
-
};
|
27275
27201
|
_this._registerListeners();
|
27276
27202
|
return _this;
|
27277
27203
|
}
|
@@ -27311,8 +27237,6 @@
|
|
27311
27237
|
};
|
27312
27238
|
_proto.onHandlerDestroying = function onHandlerDestroying() {
|
27313
27239
|
this._unregisterListeners();
|
27314
|
-
// @ts-ignore
|
27315
|
-
this.onMediaPlaying = this.onMediaSeeked = null;
|
27316
27240
|
_BaseStreamController.prototype.onHandlerDestroying.call(this);
|
27317
27241
|
};
|
27318
27242
|
_proto.startLoad = function startLoad(startPosition) {
|
@@ -27627,15 +27551,18 @@
|
|
27627
27551
|
_proto.onMediaAttached = function onMediaAttached(event, data) {
|
27628
27552
|
_BaseStreamController.prototype.onMediaAttached.call(this, event, data);
|
27629
27553
|
var media = data.media;
|
27630
|
-
|
27631
|
-
|
27554
|
+
this.onvplaying = this.onMediaPlaying.bind(this);
|
27555
|
+
this.onvseeked = this.onMediaSeeked.bind(this);
|
27556
|
+
media.addEventListener('playing', this.onvplaying);
|
27557
|
+
media.addEventListener('seeked', this.onvseeked);
|
27632
27558
|
this.gapController = new GapController(this.config, media, this.fragmentTracker, this.hls);
|
27633
27559
|
};
|
27634
27560
|
_proto.onMediaDetaching = function onMediaDetaching() {
|
27635
27561
|
var media = this.media;
|
27636
|
-
if (media) {
|
27637
|
-
media.removeEventListener('playing', this.
|
27638
|
-
media.removeEventListener('seeked', this.
|
27562
|
+
if (media && this.onvplaying && this.onvseeked) {
|
27563
|
+
media.removeEventListener('playing', this.onvplaying);
|
27564
|
+
media.removeEventListener('seeked', this.onvseeked);
|
27565
|
+
this.onvplaying = this.onvseeked = null;
|
27639
27566
|
this.videoBuffer = null;
|
27640
27567
|
}
|
27641
27568
|
this.fragPlaying = null;
|
@@ -27645,6 +27572,27 @@
|
|
27645
27572
|
}
|
27646
27573
|
_BaseStreamController.prototype.onMediaDetaching.call(this);
|
27647
27574
|
};
|
27575
|
+
_proto.onMediaPlaying = function onMediaPlaying() {
|
27576
|
+
// tick to speed up FRAG_CHANGED triggering
|
27577
|
+
this.tick();
|
27578
|
+
};
|
27579
|
+
_proto.onMediaSeeked = function onMediaSeeked() {
|
27580
|
+
var media = this.media;
|
27581
|
+
var currentTime = media ? media.currentTime : null;
|
27582
|
+
if (isFiniteNumber(currentTime)) {
|
27583
|
+
this.log("Media seeked to " + currentTime.toFixed(3));
|
27584
|
+
}
|
27585
|
+
|
27586
|
+
// If seeked was issued before buffer was appended do not tick immediately
|
27587
|
+
var bufferInfo = this.getMainFwdBufferInfo();
|
27588
|
+
if (bufferInfo === null || bufferInfo.len === 0) {
|
27589
|
+
this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
|
27590
|
+
return;
|
27591
|
+
}
|
27592
|
+
|
27593
|
+
// tick to speed up FRAG_CHANGED triggering
|
27594
|
+
this.tick();
|
27595
|
+
};
|
27648
27596
|
_proto.onManifestLoading = function onManifestLoading() {
|
27649
27597
|
// reset buffer on manifest loading
|
27650
27598
|
this.log('Trigger BUFFER_RESET');
|
@@ -29218,7 +29166,7 @@
|
|
29218
29166
|
* Get the video-dev/hls.js package version.
|
29219
29167
|
*/
|
29220
29168
|
function get() {
|
29221
|
-
return "1.5.2
|
29169
|
+
return "1.5.2";
|
29222
29170
|
}
|
29223
29171
|
}, {
|
29224
29172
|
key: "Events",
|