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.
Files changed (44) hide show
  1. package/dist/hls-demo.js +0 -5
  2. package/dist/hls-demo.js.map +1 -1
  3. package/dist/hls.js +379 -431
  4. package/dist/hls.js.d.ts +14 -14
  5. package/dist/hls.js.map +1 -1
  6. package/dist/hls.light.js +217 -275
  7. package/dist/hls.light.js.map +1 -1
  8. package/dist/hls.light.min.js +1 -1
  9. package/dist/hls.light.min.js.map +1 -1
  10. package/dist/hls.light.mjs +219 -278
  11. package/dist/hls.light.mjs.map +1 -1
  12. package/dist/hls.min.js +1 -1
  13. package/dist/hls.min.js.map +1 -1
  14. package/dist/hls.mjs +350 -401
  15. package/dist/hls.mjs.map +1 -1
  16. package/dist/hls.worker.js +1 -1
  17. package/dist/hls.worker.js.map +1 -1
  18. package/package.json +9 -9
  19. package/src/controller/abr-controller.ts +2 -2
  20. package/src/controller/base-stream-controller.ts +16 -16
  21. package/src/controller/buffer-controller.ts +0 -6
  22. package/src/controller/eme-controller.ts +12 -6
  23. package/src/controller/latency-controller.ts +8 -7
  24. package/src/controller/level-controller.ts +18 -7
  25. package/src/controller/stream-controller.ts +14 -11
  26. package/src/controller/subtitle-stream-controller.ts +1 -6
  27. package/src/controller/subtitle-track-controller.ts +2 -4
  28. package/src/controller/timeline-controller.ts +26 -20
  29. package/src/crypt/aes-crypto.ts +2 -21
  30. package/src/crypt/decrypter.ts +18 -32
  31. package/src/crypt/fast-aes-key.ts +5 -24
  32. package/src/demux/audio/adts.ts +4 -9
  33. package/src/demux/sample-aes.ts +0 -2
  34. package/src/demux/transmuxer-interface.ts +12 -4
  35. package/src/demux/transmuxer.ts +3 -16
  36. package/src/demux/tsdemuxer.ts +17 -12
  37. package/src/loader/fragment-loader.ts +2 -9
  38. package/src/loader/key-loader.ts +0 -2
  39. package/src/loader/level-key.ts +9 -10
  40. package/src/remux/mp4-remuxer.ts +3 -4
  41. package/src/types/demuxer.ts +0 -1
  42. package/src/utils/codecs.ts +4 -33
  43. package/src/crypt/decrypter-aes-mode.ts +0 -4
  44. 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-0.canary.9923");
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 && !isFullSegmentEncryption(method);
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 (isFullSegmentEncryption(this.method) || this.method === 'NONE') {
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 (isFullSegmentEncryption(this.method) && this.uri && !this.iv) {
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/256
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
- logger.warn("missing IV for initialization segment with method=\"" + this.method + "\" - compliance issue");
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|mp4a\.40\.34/i;
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.onTimeupdate = function () {
4987
- var media = _this.media,
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.onTimeupdate = null;
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.onTimeupdate);
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.onTimeupdate);
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.onTimeupdate();
4998
+ this.timeupdate();
5070
4999
  }
5071
5000
  if (!details.live && this.media) {
5072
- this.media.removeEventListener('timeupdate', this.onTimeupdate);
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.maxBitrate / 8));
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].bitrate;
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' && isMethodFullSegmentAesCbc((_frag$decryptdata = frag.decryptdata) == null ? void 0 : _frag$decryptdata.method)) {
8944
- // MAP segment encrypted with method 'AES-128' or 'AES-256' (cbc), when served with HTTP Range,
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, aesMode) {
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
- switch (this.aesMode) {
9004
- case DecrypterAesMode.cbc:
9005
- return this.subtle.decrypt({
9006
- name: 'AES-CBC',
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, aesMode) {
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: subtleAlgoName
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.enableSoftwareAES = void 0;
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
- this.useSoftware = this.subtle === null;
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, aesMode) {
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, aesMode);
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, aesMode);
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, aesMode) {
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, aesMode) {
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, aesMode);
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), aesMode);
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, aesMode);
9364
+ return _this2.onWebCryptoError(data, key, iv);
9432
9365
  });
9433
9366
  };
9434
- _proto.onWebCryptoError = function onWebCryptoError(data, key, iv, aesMode) {
9435
- var enableSoftwareAES = this.enableSoftwareAES;
9436
- if (enableSoftwareAES) {
9437
- this.useSoftware = true;
9438
- this.logEnabled = true;
9439
- this.softwareDecrypt(data, key, iv, aesMode);
9440
- var decryptResult = this.flush();
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' + (enableSoftwareAES ? ' and softwareDecrypt' : '') + ': failed to decrypt data');
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
- media.addEventListener('seeking', this.onMediaSeeking);
9644
- media.addEventListener('ended', this.onMediaEnded);
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.onMediaSeeking);
9660
- media.removeEventListener('ended', this.onMediaEnded);
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 = this.onMediaSeeking = this.onMediaEnded = null;
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 && isFullSegmentEncryption(decryptData.method)) {
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, getAesModeFromFullSegmentMethod(decryptData.method)).catch(function (err) {
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 = originalAdtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1;
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
- // Firefox and Pale Moon: freq less than 24kHz = AAC SBR (HE-AAC)
10976
- if (/firefox|palemoon/i.test(userAgent)) {
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.parsedCodec = config.parsedCodec;
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, DecrypterAesMode.cbc);
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.parsedCodec || track.manifestCodec || track.codec, track.channelCount);
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.parsedCodec || track.manifestCodec || track.codec, track.channelCount);
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 && isFullSegmentEncryption(keyData.method)) {
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, aesMode);
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, aesMode).then(function (decryptedData) {
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 m2tsTypeSupported = getM2TSSupportedAudioTypes(config.preferManagedMediaSource);
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 && isFullSegmentEncryption(decryptData.method)) {
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, getAesModeFromFullSegmentMethod(decryptData.method)).catch(function (err) {
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
- var channel1 = new OutputFilter(this, 'textTrack1');
21639
- var channel2 = new OutputFilter(this, 'textTrack2');
21640
- var channel3 = new OutputFilter(this, 'textTrack3');
21641
- var channel4 = new OutputFilter(this, 'textTrack4');
21642
- this.cea608Parser1 = new Cea608Parser(1, channel1, channel2);
21643
- this.cea608Parser2 = new Cea608Parser(3, channel3, channel4);
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 (this.enabled && data.frag.type === PlaylistLevelType.MAIN) {
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 === this.lastPartIndex + 1 || cc === this.lastCc)) {
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
- if (!this.enabled || !this.config.enableCEA708Captions) {
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
- this.cea608Parser1.addData(samples[i].pts, ccdatas[0]);
22111
- this.cea608Parser2.addData(samples[i].pts, ccdatas[1]);
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.config = this.keyIdToKeySessionPromise = null;
22504
+ this.hls = this.onMediaEncrypted = this.onWaitingForKey = this.keyIdToKeySessionPromise = null;
22665
22505
  // @ts-ignore
22666
- this.onMediaEncrypted = this.onWaitingForKey = null;
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 _this2 = this;
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
- _this2.getMediaKeysPromise(keySystem, audioCodecs, videoCodecs).then(function (mediaKeys) {
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 _this3 = this;
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
- _this3.log("Failed to obtain access to key-system \"" + keySystem + "\": " + error);
22609
+ _this2.log("Failed to obtain access to key-system \"" + keySystem + "\": " + error);
22770
22610
  });
22771
22611
  return keySystemAccess.then(function (mediaKeySystemAccess) {
22772
- _this3.log("Access for key-system \"" + mediaKeySystemAccess.keySystem + "\" obtained");
22773
- var certificateRequest = _this3.fetchServerCertificate(keySystem);
22774
- _this3.log("Create media-keys for \"" + keySystem + "\"");
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
- _this3.log("Media-keys created for \"" + keySystem + "\"");
22616
+ _this2.log("Media-keys created for \"" + keySystem + "\"");
22777
22617
  return certificateRequest.then(function (certificate) {
22778
22618
  if (certificate) {
22779
- return _this3.setMediaKeysServerCertificate(mediaKeys, keySystem, certificate);
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
- _this3.error("Failed to create media-keys for \"" + keySystem + "\"}: " + error);
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(_ref2) {
22795
- var decryptdata = _ref2.decryptdata,
22796
- keySystem = _ref2.keySystem,
22797
- mediaKeys = _ref2.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 _this4 = this;
22686
+ var _this3 = this;
22847
22687
  return new Promise(function (resolve, reject) {
22848
- var keySystemsInConfig = getKeySystemsForConfig(_this4.config);
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 _this4.getKeySystemSelectionPromise(keySystemsToAttempt).then(function (_ref3) {
22853
- var keySystem = _ref3.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 _this5 = this;
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 (_ref4) {
22872
- var keySystem = _ref4.keySystem,
22873
- mediaKeys = _ref4.mediaKeys;
22874
- _this5.throwIfDestroyed();
22875
- _this5.log("Handle encrypted media sn: " + data.frag.sn + " " + data.frag.type + ": " + data.frag.level + " using key " + keyDetails);
22876
- return _this5.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
22877
- _this5.throwIfDestroyed();
22878
- var keySessionContext = _this5.createMediaKeySessionContext({
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 _this5.generateRequestWithPreferredKeySession(keySessionContext, scheme, decryptdata.pssh, 'playlist-key');
22724
+ return _this4.generateRequestWithPreferredKeySession(keySessionContext, scheme, decryptdata.pssh, 'playlist-key');
22885
22725
  });
22886
22726
  });
22887
22727
  keySessionContextPromise.catch(function (error) {
22888
- return _this5.handleError(error);
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
- // Returns empty and set to undefined for 'mp4a.40.34' with fallback to 'audio/mpeg' SourceBuffer
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.bitrate !== b.bitrate) {
26303
- return a.bitrate - b.bitrate;
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
- media.addEventListener('playing', this.onMediaPlaying);
27631
- media.addEventListener('seeked', this.onMediaSeeked);
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.onMediaPlaying);
27638
- media.removeEventListener('seeked', this.onMediaSeeked);
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-0.canary.9923";
29169
+ return "1.5.2";
29222
29170
  }
29223
29171
  }, {
29224
29172
  key: "Events",