hls.js 1.5.4 → 1.5.5-0.canary.9978

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 (67) hide show
  1. package/README.md +1 -0
  2. package/dist/hls-demo.js +10 -0
  3. package/dist/hls-demo.js.map +1 -1
  4. package/dist/hls.js +1935 -1094
  5. package/dist/hls.js.d.ts +63 -50
  6. package/dist/hls.js.map +1 -1
  7. package/dist/hls.light.js +1059 -838
  8. package/dist/hls.light.js.map +1 -1
  9. package/dist/hls.light.min.js +1 -1
  10. package/dist/hls.light.min.js.map +1 -1
  11. package/dist/hls.light.mjs +846 -626
  12. package/dist/hls.light.mjs.map +1 -1
  13. package/dist/hls.min.js +1 -1
  14. package/dist/hls.min.js.map +1 -1
  15. package/dist/hls.mjs +1640 -814
  16. package/dist/hls.mjs.map +1 -1
  17. package/dist/hls.worker.js +1 -1
  18. package/dist/hls.worker.js.map +1 -1
  19. package/package.json +18 -18
  20. package/src/config.ts +3 -2
  21. package/src/controller/abr-controller.ts +21 -20
  22. package/src/controller/audio-stream-controller.ts +15 -16
  23. package/src/controller/audio-track-controller.ts +1 -1
  24. package/src/controller/base-playlist-controller.ts +7 -7
  25. package/src/controller/base-stream-controller.ts +56 -29
  26. package/src/controller/buffer-controller.ts +11 -11
  27. package/src/controller/cap-level-controller.ts +1 -2
  28. package/src/controller/cmcd-controller.ts +25 -3
  29. package/src/controller/content-steering-controller.ts +8 -6
  30. package/src/controller/eme-controller.ts +9 -22
  31. package/src/controller/error-controller.ts +6 -8
  32. package/src/controller/fps-controller.ts +2 -3
  33. package/src/controller/gap-controller.ts +43 -16
  34. package/src/controller/latency-controller.ts +9 -11
  35. package/src/controller/level-controller.ts +5 -17
  36. package/src/controller/stream-controller.ts +25 -32
  37. package/src/controller/subtitle-stream-controller.ts +13 -14
  38. package/src/controller/subtitle-track-controller.ts +5 -3
  39. package/src/controller/timeline-controller.ts +23 -30
  40. package/src/crypt/aes-crypto.ts +21 -2
  41. package/src/crypt/decrypter-aes-mode.ts +4 -0
  42. package/src/crypt/decrypter.ts +32 -18
  43. package/src/crypt/fast-aes-key.ts +24 -5
  44. package/src/demux/audio/adts.ts +9 -4
  45. package/src/demux/sample-aes.ts +2 -0
  46. package/src/demux/transmuxer-interface.ts +4 -12
  47. package/src/demux/transmuxer-worker.ts +4 -4
  48. package/src/demux/transmuxer.ts +16 -3
  49. package/src/demux/tsdemuxer.ts +71 -37
  50. package/src/demux/video/avc-video-parser.ts +208 -119
  51. package/src/demux/video/base-video-parser.ts +134 -2
  52. package/src/demux/video/exp-golomb.ts +0 -208
  53. package/src/demux/video/hevc-video-parser.ts +746 -0
  54. package/src/events.ts +7 -0
  55. package/src/hls.ts +42 -34
  56. package/src/loader/fragment-loader.ts +9 -2
  57. package/src/loader/key-loader.ts +2 -0
  58. package/src/loader/level-key.ts +10 -9
  59. package/src/remux/mp4-generator.ts +196 -1
  60. package/src/remux/mp4-remuxer.ts +23 -7
  61. package/src/task-loop.ts +5 -2
  62. package/src/types/component-api.ts +2 -0
  63. package/src/types/demuxer.ts +3 -0
  64. package/src/types/events.ts +4 -0
  65. package/src/utils/codecs.ts +33 -4
  66. package/src/utils/encryption-methods-util.ts +21 -0
  67. package/src/utils/logger.ts +53 -24
package/dist/hls.js CHANGED
@@ -5,6 +5,21 @@
5
5
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Hls = factory());
6
6
  })(this, (function () { 'use strict';
7
7
 
8
+ function _construct(t, e, r) {
9
+ if (_isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments);
10
+ var o = [null];
11
+ o.push.apply(o, e);
12
+ var p = new (t.bind.apply(t, o))();
13
+ return r && _setPrototypeOf(p, r.prototype), p;
14
+ }
15
+ function _isNativeReflectConstruct() {
16
+ try {
17
+ var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
18
+ } catch (t) {}
19
+ return (_isNativeReflectConstruct = function () {
20
+ return !!t;
21
+ })();
22
+ }
8
23
  function ownKeys(e, r) {
9
24
  var t = Object.keys(e);
10
25
  if (Object.getOwnPropertySymbols) {
@@ -103,32 +118,6 @@
103
118
  };
104
119
  return _setPrototypeOf(o, p);
105
120
  }
106
- function _isNativeReflectConstruct() {
107
- if (typeof Reflect === "undefined" || !Reflect.construct) return false;
108
- if (Reflect.construct.sham) return false;
109
- if (typeof Proxy === "function") return true;
110
- try {
111
- Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
112
- return true;
113
- } catch (e) {
114
- return false;
115
- }
116
- }
117
- function _construct(Parent, args, Class) {
118
- if (_isNativeReflectConstruct()) {
119
- _construct = Reflect.construct.bind();
120
- } else {
121
- _construct = function _construct(Parent, args, Class) {
122
- var a = [null];
123
- a.push.apply(a, args);
124
- var Constructor = Function.bind.apply(Parent, a);
125
- var instance = new Constructor();
126
- if (Class) _setPrototypeOf(instance, Class.prototype);
127
- return instance;
128
- };
129
- }
130
- return _construct.apply(null, arguments);
131
- }
132
121
  function _isNativeFunction(fn) {
133
122
  try {
134
123
  return Function.toString.call(fn).indexOf("[native code]") !== -1;
@@ -394,6 +383,7 @@
394
383
  Events["MEDIA_ATTACHED"] = "hlsMediaAttached";
395
384
  Events["MEDIA_DETACHING"] = "hlsMediaDetaching";
396
385
  Events["MEDIA_DETACHED"] = "hlsMediaDetached";
386
+ Events["MEDIA_ENDED"] = "hlsMediaEnded";
397
387
  Events["BUFFER_RESET"] = "hlsBufferReset";
398
388
  Events["BUFFER_CODECS"] = "hlsBufferCodecs";
399
389
  Events["BUFFER_CREATED"] = "hlsBufferCreated";
@@ -507,6 +497,21 @@
507
497
  return ErrorDetails;
508
498
  }({});
509
499
 
500
+ var Logger = function Logger(label, logger) {
501
+ this.trace = void 0;
502
+ this.debug = void 0;
503
+ this.log = void 0;
504
+ this.warn = void 0;
505
+ this.info = void 0;
506
+ this.error = void 0;
507
+ var lb = "[" + label + "]:";
508
+ this.trace = noop;
509
+ this.debug = logger.debug.bind(null, lb);
510
+ this.log = logger.log.bind(null, lb);
511
+ this.warn = logger.warn.bind(null, lb);
512
+ this.info = logger.info.bind(null, lb);
513
+ this.error = logger.error.bind(null, lb);
514
+ };
510
515
  var noop = function noop() {};
511
516
  var fakeLogger = {
512
517
  trace: noop,
@@ -516,7 +521,9 @@
516
521
  info: noop,
517
522
  error: noop
518
523
  };
519
- var exportedLogger = fakeLogger;
524
+ function createLogger() {
525
+ return _extends({}, fakeLogger);
526
+ }
520
527
 
521
528
  // let lastCallTime;
522
529
  // function formatMsgWithTimeInfo(type, msg) {
@@ -527,38 +534,36 @@
527
534
  // return msg;
528
535
  // }
529
536
 
530
- function consolePrintFn(type) {
537
+ function consolePrintFn(type, id) {
531
538
  var func = self.console[type];
532
- if (func) {
533
- return func.bind(self.console, "[" + type + "] >");
534
- }
535
- return noop;
539
+ return func ? func.bind(self.console, (id ? '[' + id + '] ' : '') + "[" + type + "] >") : noop;
536
540
  }
537
- function exportLoggerFunctions(debugConfig) {
538
- for (var _len = arguments.length, functions = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
539
- functions[_key - 1] = arguments[_key];
540
- }
541
- functions.forEach(function (type) {
542
- exportedLogger[type] = debugConfig[type] ? debugConfig[type].bind(debugConfig) : consolePrintFn(type);
543
- });
541
+ function getLoggerFn(key, debugConfig, id) {
542
+ return debugConfig[key] ? debugConfig[key].bind(debugConfig) : consolePrintFn(key, id);
544
543
  }
545
- function enableLogs(debugConfig, id) {
544
+ var exportedLogger = createLogger();
545
+ function enableLogs(debugConfig, context, id) {
546
546
  // check that console is available
547
+ var newLogger = createLogger();
547
548
  if (typeof console === 'object' && debugConfig === true || typeof debugConfig === 'object') {
548
- exportLoggerFunctions(debugConfig,
549
+ var keys = [
549
550
  // Remove out from list here to hard-disable a log-level
550
551
  // 'trace',
551
- 'debug', 'log', 'info', 'warn', 'error');
552
+ 'debug', 'log', 'info', 'warn', 'error'];
553
+ keys.forEach(function (key) {
554
+ newLogger[key] = getLoggerFn(key, debugConfig, id);
555
+ });
552
556
  // Some browsers don't allow to use bind on console object anyway
553
557
  // fallback to default if needed
554
558
  try {
555
- exportedLogger.log("Debug logs enabled for \"" + id + "\" in hls.js version " + "1.5.4");
559
+ newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.5-0.canary.9978");
556
560
  } catch (e) {
557
- exportedLogger = fakeLogger;
561
+ /* log fn threw an exception. All logger methods are no-ops. */
562
+ return createLogger();
558
563
  }
559
- } else {
560
- exportedLogger = fakeLogger;
561
564
  }
565
+ exportedLogger = newLogger;
566
+ return newLogger;
562
567
  }
563
568
  var logger = exportedLogger;
564
569
 
@@ -1253,6 +1258,26 @@
1253
1258
  });
1254
1259
  }
1255
1260
 
1261
+ var DecrypterAesMode = {
1262
+ cbc: 0,
1263
+ ctr: 1
1264
+ };
1265
+
1266
+ function isFullSegmentEncryption(method) {
1267
+ return method === 'AES-128' || method === 'AES-256' || method === 'AES-256-CTR';
1268
+ }
1269
+ function getAesModeFromFullSegmentMethod(method) {
1270
+ switch (method) {
1271
+ case 'AES-128':
1272
+ case 'AES-256':
1273
+ return DecrypterAesMode.cbc;
1274
+ case 'AES-256-CTR':
1275
+ return DecrypterAesMode.ctr;
1276
+ default:
1277
+ throw new Error("invalid full segment method " + method);
1278
+ }
1279
+ }
1280
+
1256
1281
  /** returns `undefined` is `self` is missing, e.g. in node */
1257
1282
  var optionalSelf = typeof self !== 'undefined' ? self : undefined;
1258
1283
 
@@ -2923,13 +2948,13 @@
2923
2948
  this.keyFormatVersions = formatversions;
2924
2949
  this.iv = iv;
2925
2950
  this.encrypted = method ? method !== 'NONE' : false;
2926
- this.isCommonEncryption = this.encrypted && method !== 'AES-128';
2951
+ this.isCommonEncryption = this.encrypted && !isFullSegmentEncryption(method);
2927
2952
  }
2928
2953
  var _proto = LevelKey.prototype;
2929
2954
  _proto.isSupported = function isSupported() {
2930
2955
  // If it's Segment encryption or No encryption, just select that key system
2931
2956
  if (this.method) {
2932
- if (this.method === 'AES-128' || this.method === 'NONE') {
2957
+ if (isFullSegmentEncryption(this.method) || this.method === 'NONE') {
2933
2958
  return true;
2934
2959
  }
2935
2960
  if (this.keyFormat === 'identity') {
@@ -2951,14 +2976,13 @@
2951
2976
  if (!this.encrypted || !this.uri) {
2952
2977
  return null;
2953
2978
  }
2954
- if (this.method === 'AES-128' && this.uri && !this.iv) {
2979
+ if (isFullSegmentEncryption(this.method) && this.uri && !this.iv) {
2955
2980
  if (typeof sn !== 'number') {
2956
2981
  // We are fetching decryption data for a initialization segment
2957
- // If the segment was encrypted with AES-128
2982
+ // If the segment was encrypted with AES-128/256
2958
2983
  // It must have an IV defined. We cannot substitute the Segment Number in.
2959
- if (this.method === 'AES-128' && !this.iv) {
2960
- logger.warn("missing IV for initialization segment with method=\"" + this.method + "\" - compliance issue");
2961
- }
2984
+ logger.warn("missing IV for initialization segment with method=\"" + this.method + "\" - compliance issue");
2985
+
2962
2986
  // Explicitly set sn to resulting value from implicit conversions 'initSegment' values for IV generation.
2963
2987
  sn = 0;
2964
2988
  }
@@ -3252,23 +3276,28 @@
3252
3276
  if (CODEC_COMPATIBLE_NAMES[lowerCaseCodec]) {
3253
3277
  return CODEC_COMPATIBLE_NAMES[lowerCaseCodec];
3254
3278
  }
3255
-
3256
- // Idealy fLaC and Opus would be first (spec-compliant) but
3257
- // some browsers will report that fLaC is supported then fail.
3258
- // see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
3259
3279
  var codecsToCheck = {
3280
+ // Idealy fLaC and Opus would be first (spec-compliant) but
3281
+ // some browsers will report that fLaC is supported then fail.
3282
+ // see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
3260
3283
  flac: ['flac', 'fLaC', 'FLAC'],
3261
- opus: ['opus', 'Opus']
3284
+ opus: ['opus', 'Opus'],
3285
+ // Replace audio codec info if browser does not support mp4a.40.34,
3286
+ // and demuxer can fallback to 'audio/mpeg' or 'audio/mp4;codecs="mp3"'
3287
+ 'mp4a.40.34': ['mp3']
3262
3288
  }[lowerCaseCodec];
3263
3289
  for (var i = 0; i < codecsToCheck.length; i++) {
3290
+ var _getMediaSource;
3264
3291
  if (isCodecMediaSourceSupported(codecsToCheck[i], 'audio', preferManagedMediaSource)) {
3265
3292
  CODEC_COMPATIBLE_NAMES[lowerCaseCodec] = codecsToCheck[i];
3266
3293
  return codecsToCheck[i];
3294
+ } else if (codecsToCheck[i] === 'mp3' && (_getMediaSource = getMediaSource(preferManagedMediaSource)) != null && _getMediaSource.isTypeSupported('audio/mpeg')) {
3295
+ return '';
3267
3296
  }
3268
3297
  }
3269
3298
  return lowerCaseCodec;
3270
3299
  }
3271
- var AUDIO_CODEC_REGEXP = /flac|opus/i;
3300
+ var AUDIO_CODEC_REGEXP = /flac|opus|mp4a\.40\.34/i;
3272
3301
  function getCodecCompatibleName(codec, preferManagedMediaSource) {
3273
3302
  if (preferManagedMediaSource === void 0) {
3274
3303
  preferManagedMediaSource = true;
@@ -3296,6 +3325,18 @@
3296
3325
  }
3297
3326
  return codec;
3298
3327
  }
3328
+ function getM2TSSupportedAudioTypes(preferManagedMediaSource) {
3329
+ var MediaSource = getMediaSource(preferManagedMediaSource) || {
3330
+ isTypeSupported: function isTypeSupported() {
3331
+ return false;
3332
+ }
3333
+ };
3334
+ return {
3335
+ mpeg: MediaSource.isTypeSupported('audio/mpeg'),
3336
+ mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
3337
+ ac3: MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"')
3338
+ };
3339
+ }
3299
3340
 
3300
3341
  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;
3301
3342
  var MASTER_PLAYLIST_MEDIA_REGEX = /#EXT-X-MEDIA:(.*)/g;
@@ -4959,8 +5000,43 @@
4959
5000
  this.currentTime = 0;
4960
5001
  this.stallCount = 0;
4961
5002
  this._latency = null;
4962
- this.timeupdateHandler = function () {
4963
- return _this.timeupdate();
5003
+ this.onTimeupdate = function () {
5004
+ var media = _this.media,
5005
+ levelDetails = _this.levelDetails;
5006
+ if (!media || !levelDetails) {
5007
+ return;
5008
+ }
5009
+ _this.currentTime = media.currentTime;
5010
+ var latency = _this.computeLatency();
5011
+ if (latency === null) {
5012
+ return;
5013
+ }
5014
+ _this._latency = latency;
5015
+
5016
+ // Adapt playbackRate to meet target latency in low-latency mode
5017
+ var _this$config = _this.config,
5018
+ lowLatencyMode = _this$config.lowLatencyMode,
5019
+ maxLiveSyncPlaybackRate = _this$config.maxLiveSyncPlaybackRate;
5020
+ if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1 || !levelDetails.live) {
5021
+ return;
5022
+ }
5023
+ var targetLatency = _this.targetLatency;
5024
+ if (targetLatency === null) {
5025
+ return;
5026
+ }
5027
+ var distanceFromTarget = latency - targetLatency;
5028
+ // Only adjust playbackRate when within one target duration of targetLatency
5029
+ // and more than one second from under-buffering.
5030
+ // Playback further than one target duration from target can be considered DVR playback.
5031
+ var liveMinLatencyDuration = Math.min(_this.maxLatency, targetLatency + levelDetails.targetduration);
5032
+ var inLiveRange = distanceFromTarget < liveMinLatencyDuration;
5033
+ if (inLiveRange && distanceFromTarget > 0.05 && _this.forwardBufferLength > 1) {
5034
+ var max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));
5035
+ var rate = Math.round(2 / (1 + Math.exp(-0.75 * distanceFromTarget - _this.edgeStalled)) * 20) / 20;
5036
+ media.playbackRate = Math.min(max, Math.max(1, rate));
5037
+ } else if (media.playbackRate !== 1 && media.playbackRate !== 0) {
5038
+ media.playbackRate = 1;
5039
+ }
4964
5040
  };
4965
5041
  this.hls = hls;
4966
5042
  this.config = hls.config;
@@ -4972,7 +5048,7 @@
4972
5048
  this.onMediaDetaching();
4973
5049
  this.levelDetails = null;
4974
5050
  // @ts-ignore
4975
- this.hls = this.timeupdateHandler = null;
5051
+ this.hls = null;
4976
5052
  };
4977
5053
  _proto.registerListeners = function registerListeners() {
4978
5054
  this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
@@ -4990,11 +5066,11 @@
4990
5066
  };
4991
5067
  _proto.onMediaAttached = function onMediaAttached(event, data) {
4992
5068
  this.media = data.media;
4993
- this.media.addEventListener('timeupdate', this.timeupdateHandler);
5069
+ this.media.addEventListener('timeupdate', this.onTimeupdate);
4994
5070
  };
4995
5071
  _proto.onMediaDetaching = function onMediaDetaching() {
4996
5072
  if (this.media) {
4997
- this.media.removeEventListener('timeupdate', this.timeupdateHandler);
5073
+ this.media.removeEventListener('timeupdate', this.onTimeupdate);
4998
5074
  this.media = null;
4999
5075
  }
5000
5076
  };
@@ -5007,10 +5083,10 @@
5007
5083
  var details = _ref.details;
5008
5084
  this.levelDetails = details;
5009
5085
  if (details.advanced) {
5010
- this.timeupdate();
5086
+ this.onTimeupdate();
5011
5087
  }
5012
5088
  if (!details.live && this.media) {
5013
- this.media.removeEventListener('timeupdate', this.timeupdateHandler);
5089
+ this.media.removeEventListener('timeupdate', this.onTimeupdate);
5014
5090
  }
5015
5091
  };
5016
5092
  _proto.onError = function onError(event, data) {
@@ -5020,45 +5096,7 @@
5020
5096
  }
5021
5097
  this.stallCount++;
5022
5098
  if ((_this$levelDetails = this.levelDetails) != null && _this$levelDetails.live) {
5023
- logger.warn('[playback-rate-controller]: Stall detected, adjusting target latency');
5024
- }
5025
- };
5026
- _proto.timeupdate = function timeupdate() {
5027
- var media = this.media,
5028
- levelDetails = this.levelDetails;
5029
- if (!media || !levelDetails) {
5030
- return;
5031
- }
5032
- this.currentTime = media.currentTime;
5033
- var latency = this.computeLatency();
5034
- if (latency === null) {
5035
- return;
5036
- }
5037
- this._latency = latency;
5038
-
5039
- // Adapt playbackRate to meet target latency in low-latency mode
5040
- var _this$config = this.config,
5041
- lowLatencyMode = _this$config.lowLatencyMode,
5042
- maxLiveSyncPlaybackRate = _this$config.maxLiveSyncPlaybackRate;
5043
- if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1 || !levelDetails.live) {
5044
- return;
5045
- }
5046
- var targetLatency = this.targetLatency;
5047
- if (targetLatency === null) {
5048
- return;
5049
- }
5050
- var distanceFromTarget = latency - targetLatency;
5051
- // Only adjust playbackRate when within one target duration of targetLatency
5052
- // and more than one second from under-buffering.
5053
- // Playback further than one target duration from target can be considered DVR playback.
5054
- var liveMinLatencyDuration = Math.min(this.maxLatency, targetLatency + levelDetails.targetduration);
5055
- var inLiveRange = distanceFromTarget < liveMinLatencyDuration;
5056
- if (inLiveRange && distanceFromTarget > 0.05 && this.forwardBufferLength > 1) {
5057
- var max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));
5058
- var rate = Math.round(2 / (1 + Math.exp(-0.75 * distanceFromTarget - this.edgeStalled)) * 20) / 20;
5059
- media.playbackRate = Math.min(max, Math.max(1, rate));
5060
- } else if (media.playbackRate !== 1 && media.playbackRate !== 0) {
5061
- media.playbackRate = 1;
5099
+ this.hls.logger.warn('[latency-controller]: Stall detected, adjusting target latency');
5062
5100
  }
5063
5101
  };
5064
5102
  _proto.estimateLiveEdge = function estimateLiveEdge() {
@@ -5966,19 +6004,17 @@
5966
6004
  MoveAllAlternatesMatchingHDCP: 2,
5967
6005
  SwitchToSDR: 4
5968
6006
  }; // Reserved for future use
5969
- var ErrorController = /*#__PURE__*/function () {
6007
+ var ErrorController = /*#__PURE__*/function (_Logger) {
6008
+ _inheritsLoose(ErrorController, _Logger);
5970
6009
  function ErrorController(hls) {
5971
- this.hls = void 0;
5972
- this.playlistError = 0;
5973
- this.penalizedRenditions = {};
5974
- this.log = void 0;
5975
- this.warn = void 0;
5976
- this.error = void 0;
5977
- this.hls = hls;
5978
- this.log = logger.log.bind(logger, "[info]:");
5979
- this.warn = logger.warn.bind(logger, "[warning]:");
5980
- this.error = logger.error.bind(logger, "[error]:");
5981
- this.registerListeners();
6010
+ var _this;
6011
+ _this = _Logger.call(this, 'error-controller', hls.logger) || this;
6012
+ _this.hls = void 0;
6013
+ _this.playlistError = 0;
6014
+ _this.penalizedRenditions = {};
6015
+ _this.hls = hls;
6016
+ _this.registerListeners();
6017
+ return _this;
5982
6018
  }
5983
6019
  var _proto = ErrorController.prototype;
5984
6020
  _proto.registerListeners = function registerListeners() {
@@ -6334,19 +6370,19 @@
6334
6370
  }
6335
6371
  };
6336
6372
  return ErrorController;
6337
- }();
6373
+ }(Logger);
6338
6374
 
6339
- var BasePlaylistController = /*#__PURE__*/function () {
6375
+ var BasePlaylistController = /*#__PURE__*/function (_Logger) {
6376
+ _inheritsLoose(BasePlaylistController, _Logger);
6340
6377
  function BasePlaylistController(hls, logPrefix) {
6341
- this.hls = void 0;
6342
- this.timer = -1;
6343
- this.requestScheduled = -1;
6344
- this.canLoad = false;
6345
- this.log = void 0;
6346
- this.warn = void 0;
6347
- this.log = logger.log.bind(logger, logPrefix + ":");
6348
- this.warn = logger.warn.bind(logger, logPrefix + ":");
6349
- this.hls = hls;
6378
+ var _this;
6379
+ _this = _Logger.call(this, logPrefix, hls.logger) || this;
6380
+ _this.hls = void 0;
6381
+ _this.timer = -1;
6382
+ _this.requestScheduled = -1;
6383
+ _this.canLoad = false;
6384
+ _this.hls = hls;
6385
+ return _this;
6350
6386
  }
6351
6387
  var _proto = BasePlaylistController.prototype;
6352
6388
  _proto.destroy = function destroy() {
@@ -6379,7 +6415,7 @@
6379
6415
  try {
6380
6416
  uri = new self.URL(attr.URI, previous.url).href;
6381
6417
  } catch (error) {
6382
- logger.warn("Could not construct new URL for Rendition Report: " + error);
6418
+ this.warn("Could not construct new URL for Rendition Report: " + error);
6383
6419
  uri = attr.URI || '';
6384
6420
  }
6385
6421
  // Use exact match. Otherwise, the last partial match, if any, will be used
@@ -6418,7 +6454,7 @@
6418
6454
  return this.timer === -1 && this.requestScheduled === -1 && this.shouldLoadPlaylist(playlist);
6419
6455
  };
6420
6456
  _proto.playlistLoaded = function playlistLoaded(index, data, previousDetails) {
6421
- var _this = this;
6457
+ var _this2 = this;
6422
6458
  var details = data.details,
6423
6459
  stats = data.stats;
6424
6460
 
@@ -6523,7 +6559,7 @@
6523
6559
  // );
6524
6560
 
6525
6561
  this.timer = self.setTimeout(function () {
6526
- return _this.loadPlaylist(deliveryDirectives);
6562
+ return _this2.loadPlaylist(deliveryDirectives);
6527
6563
  }, estimatedTimeUntilUpdate);
6528
6564
  } else {
6529
6565
  this.clearTimer();
@@ -6539,7 +6575,7 @@
6539
6575
  return new HlsUrlParameters(msn, part, skip);
6540
6576
  };
6541
6577
  _proto.checkRetry = function checkRetry(errorEvent) {
6542
- var _this2 = this;
6578
+ var _this3 = this;
6543
6579
  var errorDetails = errorEvent.details;
6544
6580
  var isTimeout = isTimeoutError(errorEvent);
6545
6581
  var errorAction = errorEvent.errorAction;
@@ -6563,7 +6599,7 @@
6563
6599
  var delay = getRetryDelay(retryConfig, retryCount);
6564
6600
  // Schedule level/track reload
6565
6601
  this.timer = self.setTimeout(function () {
6566
- return _this2.loadPlaylist();
6602
+ return _this3.loadPlaylist();
6567
6603
  }, delay);
6568
6604
  this.warn("Retrying playlist loading " + (retryCount + 1) + "/" + retryConfig.maxNumRetry + " after \"" + errorDetails + "\" in " + delay + "ms");
6569
6605
  }
@@ -6574,7 +6610,7 @@
6574
6610
  return retry;
6575
6611
  };
6576
6612
  return BasePlaylistController;
6577
- }();
6613
+ }(Logger);
6578
6614
 
6579
6615
  /*
6580
6616
  * compute an Exponential Weighted moving average
@@ -7176,30 +7212,33 @@
7176
7212
  return -1;
7177
7213
  }
7178
7214
 
7179
- var AbrController = /*#__PURE__*/function () {
7215
+ var AbrController = /*#__PURE__*/function (_Logger) {
7216
+ _inheritsLoose(AbrController, _Logger);
7180
7217
  function AbrController(_hls) {
7181
- var _this = this;
7182
- this.hls = void 0;
7183
- this.lastLevelLoadSec = 0;
7184
- this.lastLoadedFragLevel = -1;
7185
- this.firstSelection = -1;
7186
- this._nextAutoLevel = -1;
7187
- this.nextAutoLevelKey = '';
7188
- this.audioTracksByGroup = null;
7189
- this.codecTiers = null;
7190
- this.timer = -1;
7191
- this.fragCurrent = null;
7192
- this.partCurrent = null;
7193
- this.bitrateTestDelay = 0;
7194
- this.bwEstimator = void 0;
7218
+ var _this;
7219
+ _this = _Logger.call(this, 'abr', _hls.logger) || this;
7220
+ _this.hls = void 0;
7221
+ _this.lastLevelLoadSec = 0;
7222
+ _this.lastLoadedFragLevel = -1;
7223
+ _this.firstSelection = -1;
7224
+ _this._nextAutoLevel = -1;
7225
+ _this.nextAutoLevelKey = '';
7226
+ _this.audioTracksByGroup = null;
7227
+ _this.codecTiers = null;
7228
+ _this.timer = -1;
7229
+ _this.fragCurrent = null;
7230
+ _this.partCurrent = null;
7231
+ _this.bitrateTestDelay = 0;
7232
+ _this.bwEstimator = void 0;
7195
7233
  /*
7196
7234
  This method monitors the download rate of the current fragment, and will downswitch if that fragment will not load
7197
7235
  quickly enough to prevent underbuffering
7198
7236
  */
7199
- this._abandonRulesCheck = function () {
7200
- var frag = _this.fragCurrent,
7201
- part = _this.partCurrent,
7202
- hls = _this.hls;
7237
+ _this._abandonRulesCheck = function () {
7238
+ var _assertThisInitialize = _assertThisInitialized(_this),
7239
+ frag = _assertThisInitialize.fragCurrent,
7240
+ part = _assertThisInitialize.partCurrent,
7241
+ hls = _assertThisInitialize.hls;
7203
7242
  var autoLevelEnabled = hls.autoLevelEnabled,
7204
7243
  media = hls.media;
7205
7244
  if (!frag || !media) {
@@ -7288,21 +7327,22 @@
7288
7327
  _this.resetEstimator(nextLoadLevelBitrate);
7289
7328
  }
7290
7329
  _this.clearTimer();
7291
- logger.warn("[abr] Fragment " + frag.sn + (part ? ' part ' + part.index : '') + " of level " + frag.level + " is loading too slowly;\n Time to underbuffer: " + bufferStarvationDelay.toFixed(3) + " s\n Estimated load time for current fragment: " + fragLoadedDelay.toFixed(3) + " s\n Estimated load time for down switch fragment: " + fragLevelNextLoadedDelay.toFixed(3) + " s\n TTFB estimate: " + (ttfb | 0) + " ms\n Current BW estimate: " + (isFiniteNumber(bwEstimate) ? bwEstimate | 0 : 'Unknown') + " bps\n New BW estimate: " + (_this.getBwEstimate() | 0) + " bps\n Switching to level " + nextLoadLevel + " @ " + (nextLoadLevelBitrate | 0) + " bps");
7330
+ _this.warn("Fragment " + frag.sn + (part ? ' part ' + part.index : '') + " of level " + frag.level + " is loading too slowly;\n Time to underbuffer: " + bufferStarvationDelay.toFixed(3) + " s\n Estimated load time for current fragment: " + fragLoadedDelay.toFixed(3) + " s\n Estimated load time for down switch fragment: " + fragLevelNextLoadedDelay.toFixed(3) + " s\n TTFB estimate: " + (ttfb | 0) + " ms\n Current BW estimate: " + (isFiniteNumber(bwEstimate) ? bwEstimate | 0 : 'Unknown') + " bps\n New BW estimate: " + (_this.getBwEstimate() | 0) + " bps\n Switching to level " + nextLoadLevel + " @ " + (nextLoadLevelBitrate | 0) + " bps");
7292
7331
  hls.trigger(Events.FRAG_LOAD_EMERGENCY_ABORTED, {
7293
7332
  frag: frag,
7294
7333
  part: part,
7295
7334
  stats: stats
7296
7335
  });
7297
7336
  };
7298
- this.hls = _hls;
7299
- this.bwEstimator = this.initEstimator();
7300
- this.registerListeners();
7337
+ _this.hls = _hls;
7338
+ _this.bwEstimator = _this.initEstimator();
7339
+ _this.registerListeners();
7340
+ return _this;
7301
7341
  }
7302
7342
  var _proto = AbrController.prototype;
7303
7343
  _proto.resetEstimator = function resetEstimator(abrEwmaDefaultEstimate) {
7304
7344
  if (abrEwmaDefaultEstimate) {
7305
- logger.log("setting initial bwe to " + abrEwmaDefaultEstimate);
7345
+ this.log("setting initial bwe to " + abrEwmaDefaultEstimate);
7306
7346
  this.hls.config.abrEwmaDefaultEstimate = abrEwmaDefaultEstimate;
7307
7347
  }
7308
7348
  this.firstSelection = -1;
@@ -7554,13 +7594,13 @@
7554
7594
  // cap maxLoadingDelay and ensure it is not bigger 'than bitrate test' frag duration
7555
7595
  var maxLoadingDelay = currentFragDuration ? Math.min(currentFragDuration, config.maxLoadingDelay) : config.maxLoadingDelay;
7556
7596
  maxStarvationDelay = maxLoadingDelay - bitrateTestDelay;
7557
- logger.info("[abr] bitrate test took " + Math.round(1000 * bitrateTestDelay) + "ms, set first fragment max fetchDuration to " + Math.round(1000 * maxStarvationDelay) + " ms");
7597
+ this.info("bitrate test took " + Math.round(1000 * bitrateTestDelay) + "ms, set first fragment max fetchDuration to " + Math.round(1000 * maxStarvationDelay) + " ms");
7558
7598
  // don't use conservative factor on bitrate test
7559
7599
  bwFactor = bwUpFactor = 1;
7560
7600
  }
7561
7601
  }
7562
7602
  var bestLevel = this.findBestLevel(avgbw, minAutoLevel, maxAutoLevel, bufferStarvationDelay, maxStarvationDelay, bwFactor, bwUpFactor);
7563
- logger.info("[abr] " + (bufferStarvationDelay ? 'rebuffering expected' : 'buffer is empty') + ", optimal quality level " + bestLevel);
7603
+ this.info((bufferStarvationDelay ? 'rebuffering expected' : 'buffer is empty') + ", optimal quality level " + bestLevel);
7564
7604
  if (bestLevel > -1) {
7565
7605
  return bestLevel;
7566
7606
  }
@@ -7616,7 +7656,7 @@
7616
7656
  currentVideoRange = preferHDR ? videoRanges[videoRanges.length - 1] : videoRanges[0];
7617
7657
  currentFrameRate = minFramerate;
7618
7658
  currentBw = Math.max(currentBw, minBitrate);
7619
- logger.log("[abr] picked start tier " + JSON.stringify(startTier));
7659
+ this.log("picked start tier " + JSON.stringify(startTier));
7620
7660
  } else {
7621
7661
  currentCodecSet = level == null ? void 0 : level.codecSet;
7622
7662
  currentVideoRange = level == null ? void 0 : level.videoRange;
@@ -7640,11 +7680,11 @@
7640
7680
  var levels = _this2.hls.levels;
7641
7681
  var index = levels.indexOf(levelInfo);
7642
7682
  if (decodingInfo.error) {
7643
- logger.warn("[abr] MediaCapabilities decodingInfo error: \"" + decodingInfo.error + "\" for level " + index + " " + JSON.stringify(decodingInfo));
7683
+ _this2.warn("MediaCapabilities decodingInfo error: \"" + decodingInfo.error + "\" for level " + index + " " + JSON.stringify(decodingInfo));
7644
7684
  } else if (!decodingInfo.supported) {
7645
- logger.warn("[abr] Unsupported MediaCapabilities decodingInfo result for level " + index + " " + JSON.stringify(decodingInfo));
7685
+ _this2.warn("Unsupported MediaCapabilities decodingInfo result for level " + index + " " + JSON.stringify(decodingInfo));
7646
7686
  if (index > -1 && levels.length > 1) {
7647
- logger.log("[abr] Removing unsupported level " + index);
7687
+ _this2.log("Removing unsupported level " + index);
7648
7688
  _this2.hls.removeLevel(index);
7649
7689
  }
7650
7690
  }
@@ -7691,9 +7731,9 @@
7691
7731
  var forcedAutoLevel = _this2.forcedAutoLevel;
7692
7732
  if (i !== loadLevel && (forcedAutoLevel === -1 || forcedAutoLevel !== loadLevel)) {
7693
7733
  if (levelsSkipped.length) {
7694
- logger.trace("[abr] Skipped level(s) " + levelsSkipped.join(',') + " of " + maxAutoLevel + " max with CODECS and VIDEO-RANGE:\"" + levels[levelsSkipped[0]].codecs + "\" " + levels[levelsSkipped[0]].videoRange + "; not compatible with \"" + level.codecs + "\" " + currentVideoRange);
7734
+ _this2.trace("Skipped level(s) " + levelsSkipped.join(',') + " of " + maxAutoLevel + " max with CODECS and VIDEO-RANGE:\"" + levels[levelsSkipped[0]].codecs + "\" " + levels[levelsSkipped[0]].videoRange + "; not compatible with \"" + level.codecs + "\" " + currentVideoRange);
7695
7735
  }
7696
- logger.info("[abr] switch candidate:" + selectionBaseLevel + "->" + i + " adjustedbw(" + Math.round(adjustedbw) + ")-bitrate=" + Math.round(adjustedbw - bitrate) + " ttfb:" + ttfbEstimateSec.toFixed(1) + " avgDuration:" + avgDuration.toFixed(1) + " maxFetchDuration:" + maxFetchDuration.toFixed(1) + " fetchDuration:" + fetchDuration.toFixed(1) + " firstSelection:" + firstSelection + " codecSet:" + currentCodecSet + " videoRange:" + currentVideoRange + " hls.loadLevel:" + loadLevel);
7736
+ _this2.info("switch candidate:" + selectionBaseLevel + "->" + i + " adjustedbw(" + Math.round(adjustedbw) + ")-bitrate=" + Math.round(adjustedbw - bitrate) + " ttfb:" + ttfbEstimateSec.toFixed(1) + " avgDuration:" + avgDuration.toFixed(1) + " maxFetchDuration:" + maxFetchDuration.toFixed(1) + " fetchDuration:" + fetchDuration.toFixed(1) + " firstSelection:" + firstSelection + " codecSet:" + currentCodecSet + " videoRange:" + currentVideoRange + " hls.loadLevel:" + loadLevel);
7697
7737
  }
7698
7738
  if (firstSelection) {
7699
7739
  _this2.firstSelection = i;
@@ -7727,7 +7767,7 @@
7727
7767
  }
7728
7768
  var firstLevel = this.hls.firstLevel;
7729
7769
  var clamped = Math.min(Math.max(firstLevel, minAutoLevel), maxAutoLevel);
7730
- logger.warn("[abr] Could not find best starting auto level. Defaulting to first in playlist " + firstLevel + " clamped to " + clamped);
7770
+ this.warn("Could not find best starting auto level. Defaulting to first in playlist " + firstLevel + " clamped to " + clamped);
7731
7771
  return clamped;
7732
7772
  }
7733
7773
  }, {
@@ -7780,7 +7820,7 @@
7780
7820
  }
7781
7821
  }]);
7782
7822
  return AbrController;
7783
- }();
7823
+ }(Logger);
7784
7824
 
7785
7825
  /**
7786
7826
  * @ignore
@@ -7811,13 +7851,17 @@
7811
7851
  * we are limiting the task execution per call stack to exactly one, but scheduling/post-poning further
7812
7852
  * task processing on the next main loop iteration (also known as "next tick" in the Node/JS runtime lingo).
7813
7853
  */
7814
- var TaskLoop = /*#__PURE__*/function () {
7815
- function TaskLoop() {
7816
- this._boundTick = void 0;
7817
- this._tickTimer = null;
7818
- this._tickInterval = null;
7819
- this._tickCallCount = 0;
7820
- this._boundTick = this.tick.bind(this);
7854
+ var TaskLoop = /*#__PURE__*/function (_Logger) {
7855
+ _inheritsLoose(TaskLoop, _Logger);
7856
+ function TaskLoop(label, logger) {
7857
+ var _this;
7858
+ _this = _Logger.call(this, label, logger) || this;
7859
+ _this._boundTick = void 0;
7860
+ _this._tickTimer = null;
7861
+ _this._tickInterval = null;
7862
+ _this._tickCallCount = 0;
7863
+ _this._boundTick = _this.tick.bind(_assertThisInitialized(_this));
7864
+ return _this;
7821
7865
  }
7822
7866
  var _proto = TaskLoop.prototype;
7823
7867
  _proto.destroy = function destroy() {
@@ -7903,7 +7947,7 @@
7903
7947
  */;
7904
7948
  _proto.doTick = function doTick() {};
7905
7949
  return TaskLoop;
7906
- }();
7950
+ }(Logger);
7907
7951
 
7908
7952
  var FragmentState = {
7909
7953
  NOT_LOADED: "NOT_LOADED",
@@ -8922,8 +8966,8 @@
8922
8966
  var _frag$decryptdata;
8923
8967
  var byteRangeStart = start;
8924
8968
  var byteRangeEnd = end;
8925
- if (frag.sn === 'initSegment' && ((_frag$decryptdata = frag.decryptdata) == null ? void 0 : _frag$decryptdata.method) === 'AES-128') {
8926
- // MAP segment encrypted with method 'AES-128', when served with HTTP Range,
8969
+ if (frag.sn === 'initSegment' && isMethodFullSegmentAesCbc((_frag$decryptdata = frag.decryptdata) == null ? void 0 : _frag$decryptdata.method)) {
8970
+ // MAP segment encrypted with method 'AES-128' or 'AES-256' (cbc), when served with HTTP Range,
8927
8971
  // has the unencrypted size specified in the range.
8928
8972
  // Ref: https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-6.3.6
8929
8973
  var fragmentLen = end - start;
@@ -8956,6 +9000,9 @@
8956
9000
  (part ? part : frag).stats.aborted = true;
8957
9001
  return new LoadError(errorData);
8958
9002
  }
9003
+ function isMethodFullSegmentAesCbc(method) {
9004
+ return method === 'AES-128' || method === 'AES-256';
9005
+ }
8959
9006
  var LoadError = /*#__PURE__*/function (_Error) {
8960
9007
  _inheritsLoose(LoadError, _Error);
8961
9008
  function LoadError(data) {
@@ -8969,37 +9016,65 @@
8969
9016
  }( /*#__PURE__*/_wrapNativeSuper(Error));
8970
9017
 
8971
9018
  var AESCrypto = /*#__PURE__*/function () {
8972
- function AESCrypto(subtle, iv) {
9019
+ function AESCrypto(subtle, iv, aesMode) {
8973
9020
  this.subtle = void 0;
8974
9021
  this.aesIV = void 0;
9022
+ this.aesMode = void 0;
8975
9023
  this.subtle = subtle;
8976
9024
  this.aesIV = iv;
9025
+ this.aesMode = aesMode;
8977
9026
  }
8978
9027
  var _proto = AESCrypto.prototype;
8979
9028
  _proto.decrypt = function decrypt(data, key) {
8980
- return this.subtle.decrypt({
8981
- name: 'AES-CBC',
8982
- iv: this.aesIV
8983
- }, key, data);
9029
+ switch (this.aesMode) {
9030
+ case DecrypterAesMode.cbc:
9031
+ return this.subtle.decrypt({
9032
+ name: 'AES-CBC',
9033
+ iv: this.aesIV
9034
+ }, key, data);
9035
+ case DecrypterAesMode.ctr:
9036
+ return this.subtle.decrypt({
9037
+ name: 'AES-CTR',
9038
+ counter: this.aesIV,
9039
+ length: 64
9040
+ },
9041
+ //64 : NIST SP800-38A standard suggests that the counter should occupy half of the counter block
9042
+ key, data);
9043
+ default:
9044
+ throw new Error("[AESCrypto] invalid aes mode " + this.aesMode);
9045
+ }
8984
9046
  };
8985
9047
  return AESCrypto;
8986
9048
  }();
8987
9049
 
8988
9050
  var FastAESKey = /*#__PURE__*/function () {
8989
- function FastAESKey(subtle, key) {
9051
+ function FastAESKey(subtle, key, aesMode) {
8990
9052
  this.subtle = void 0;
8991
9053
  this.key = void 0;
9054
+ this.aesMode = void 0;
8992
9055
  this.subtle = subtle;
8993
9056
  this.key = key;
9057
+ this.aesMode = aesMode;
8994
9058
  }
8995
9059
  var _proto = FastAESKey.prototype;
8996
9060
  _proto.expandKey = function expandKey() {
9061
+ var subtleAlgoName = getSubtleAlgoName(this.aesMode);
8997
9062
  return this.subtle.importKey('raw', this.key, {
8998
- name: 'AES-CBC'
9063
+ name: subtleAlgoName
8999
9064
  }, false, ['encrypt', 'decrypt']);
9000
9065
  };
9001
9066
  return FastAESKey;
9002
9067
  }();
9068
+ function getSubtleAlgoName(aesMode) {
9069
+ switch (aesMode) {
9070
+ case DecrypterAesMode.cbc:
9071
+ return 'AES-CBC';
9072
+ case DecrypterAesMode.ctr:
9073
+ return 'AES-CTR';
9074
+ default:
9075
+ throw new Error("[FastAESKey] invalid aes mode " + aesMode);
9076
+ }
9077
+ }
9003
9078
 
9004
9079
  // PKCS7
9005
9080
  function removePadding(array) {
@@ -9252,7 +9327,8 @@
9252
9327
  this.currentIV = null;
9253
9328
  this.currentResult = null;
9254
9329
  this.useSoftware = void 0;
9255
- this.useSoftware = config.enableSoftwareAES;
9330
+ this.enableSoftwareAES = void 0;
9331
+ this.enableSoftwareAES = config.enableSoftwareAES;
9256
9332
  this.removePKCS7Padding = removePKCS7Padding;
9257
9333
  // built in decryptor expects PKCS7 padding
9258
9334
  if (removePKCS7Padding) {
@@ -9265,9 +9341,7 @@
9265
9341
  /* no-op */
9266
9342
  }
9267
9343
  }
9268
- if (this.subtle === null) {
9269
- this.useSoftware = true;
9270
- }
9344
+ this.useSoftware = this.subtle === null;
9271
9345
  }
9272
9346
  var _proto = Decrypter.prototype;
9273
9347
  _proto.destroy = function destroy() {
@@ -9304,11 +9378,11 @@
9304
9378
  this.softwareDecrypter = null;
9305
9379
  }
9306
9380
  };
9307
- _proto.decrypt = function decrypt(data, key, iv) {
9381
+ _proto.decrypt = function decrypt(data, key, iv, aesMode) {
9308
9382
  var _this = this;
9309
9383
  if (this.useSoftware) {
9310
9384
  return new Promise(function (resolve, reject) {
9311
- _this.softwareDecrypt(new Uint8Array(data), key, iv);
9385
+ _this.softwareDecrypt(new Uint8Array(data), key, iv, aesMode);
9312
9386
  var decryptResult = _this.flush();
9313
9387
  if (decryptResult) {
9314
9388
  resolve(decryptResult.buffer);
@@ -9317,16 +9391,20 @@
9317
9391
  }
9318
9392
  });
9319
9393
  }
9320
- return this.webCryptoDecrypt(new Uint8Array(data), key, iv);
9394
+ return this.webCryptoDecrypt(new Uint8Array(data), key, iv, aesMode);
9321
9395
  }
9322
9396
 
9323
9397
  // Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
9324
9398
  // data is handled in the flush() call
9325
9399
  ;
9326
- _proto.softwareDecrypt = function softwareDecrypt(data, key, iv) {
9400
+ _proto.softwareDecrypt = function softwareDecrypt(data, key, iv, aesMode) {
9327
9401
  var currentIV = this.currentIV,
9328
9402
  currentResult = this.currentResult,
9329
9403
  remainderData = this.remainderData;
9404
+ if (aesMode !== DecrypterAesMode.cbc || key.byteLength !== 16) {
9405
+ logger.warn('SoftwareDecrypt: can only handle AES-128-CBC');
9406
+ return null;
9407
+ }
9330
9408
  this.logOnce('JS AES decrypt');
9331
9409
  // The output is staggered during progressive parsing - the current result is cached, and emitted on the next call
9332
9410
  // This is done in order to strip PKCS7 padding, which is found at the end of each segment. We only know we've reached
@@ -9359,12 +9437,12 @@
9359
9437
  }
9360
9438
  return result;
9361
9439
  };
9362
- _proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv) {
9440
+ _proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv, aesMode) {
9363
9441
  var _this2 = this;
9364
9442
  var subtle = this.subtle;
9365
9443
  if (this.key !== key || !this.fastAesKey) {
9366
9444
  this.key = key;
9367
- this.fastAesKey = new FastAESKey(subtle, key);
9445
+ this.fastAesKey = new FastAESKey(subtle, key, aesMode);
9368
9446
  }
9369
9447
  return this.fastAesKey.expandKey().then(function (aesKey) {
9370
9448
  // decrypt using web crypto
@@ -9372,22 +9450,25 @@
9372
9450
  return Promise.reject(new Error('web crypto not initialized'));
9373
9451
  }
9374
9452
  _this2.logOnce('WebCrypto AES decrypt');
9375
- var crypto = new AESCrypto(subtle, new Uint8Array(iv));
9453
+ var crypto = new AESCrypto(subtle, new Uint8Array(iv), aesMode);
9376
9454
  return crypto.decrypt(data.buffer, aesKey);
9377
9455
  }).catch(function (err) {
9378
9456
  logger.warn("[decrypter]: WebCrypto Error, disable WebCrypto API, " + err.name + ": " + err.message);
9379
- return _this2.onWebCryptoError(data, key, iv);
9457
+ return _this2.onWebCryptoError(data, key, iv, aesMode);
9380
9458
  });
9381
9459
  };
9382
- _proto.onWebCryptoError = function onWebCryptoError(data, key, iv) {
9383
- this.useSoftware = true;
9384
- this.logEnabled = true;
9385
- this.softwareDecrypt(data, key, iv);
9386
- var decryptResult = this.flush();
9387
- if (decryptResult) {
9388
- return decryptResult.buffer;
9460
+ _proto.onWebCryptoError = function onWebCryptoError(data, key, iv, aesMode) {
9461
+ var enableSoftwareAES = this.enableSoftwareAES;
9462
+ if (enableSoftwareAES) {
9463
+ this.useSoftware = true;
9464
+ this.logEnabled = true;
9465
+ this.softwareDecrypt(data, key, iv, aesMode);
9466
+ var decryptResult = this.flush();
9467
+ if (decryptResult) {
9468
+ return decryptResult.buffer;
9469
+ }
9389
9470
  }
9390
- throw new Error('WebCrypto and softwareDecrypt: failed to decrypt data');
9471
+ throw new Error('WebCrypto' + (enableSoftwareAES ? ' and softwareDecrypt' : '') + ': failed to decrypt data');
9391
9472
  };
9392
9473
  _proto.getValidChunk = function getValidChunk(data) {
9393
9474
  var currentChunk = data;
@@ -9441,7 +9522,7 @@
9441
9522
  _inheritsLoose(BaseStreamController, _TaskLoop);
9442
9523
  function BaseStreamController(hls, fragmentTracker, keyLoader, logPrefix, playlistType) {
9443
9524
  var _this;
9444
- _this = _TaskLoop.call(this) || this;
9525
+ _this = _TaskLoop.call(this, logPrefix, hls.logger) || this;
9445
9526
  _this.hls = void 0;
9446
9527
  _this.fragPrevious = null;
9447
9528
  _this.fragCurrent = null;
@@ -9466,25 +9547,87 @@
9466
9547
  _this.startFragRequested = false;
9467
9548
  _this.decrypter = void 0;
9468
9549
  _this.initPTS = [];
9469
- _this.onvseeking = null;
9470
- _this.onvended = null;
9471
- _this.logPrefix = '';
9472
- _this.log = void 0;
9473
- _this.warn = void 0;
9550
+ _this.buffering = true;
9551
+ _this.onMediaSeeking = function () {
9552
+ var _assertThisInitialize = _assertThisInitialized(_this),
9553
+ config = _assertThisInitialize.config,
9554
+ fragCurrent = _assertThisInitialize.fragCurrent,
9555
+ media = _assertThisInitialize.media,
9556
+ mediaBuffer = _assertThisInitialize.mediaBuffer,
9557
+ state = _assertThisInitialize.state;
9558
+ var currentTime = media ? media.currentTime : 0;
9559
+ var bufferInfo = BufferHelper.bufferInfo(mediaBuffer ? mediaBuffer : media, currentTime, config.maxBufferHole);
9560
+ _this.log("media seeking to " + (isFiniteNumber(currentTime) ? currentTime.toFixed(3) : currentTime) + ", state: " + state);
9561
+ if (_this.state === State.ENDED) {
9562
+ _this.resetLoadingState();
9563
+ } else if (fragCurrent) {
9564
+ // Seeking while frag load is in progress
9565
+ var tolerance = config.maxFragLookUpTolerance;
9566
+ var fragStartOffset = fragCurrent.start - tolerance;
9567
+ var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance;
9568
+ // if seeking out of buffered range or into new one
9569
+ if (!bufferInfo.len || fragEndOffset < bufferInfo.start || fragStartOffset > bufferInfo.end) {
9570
+ var pastFragment = currentTime > fragEndOffset;
9571
+ // if the seek position is outside the current fragment range
9572
+ if (currentTime < fragStartOffset || pastFragment) {
9573
+ if (pastFragment && fragCurrent.loader) {
9574
+ _this.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
9575
+ fragCurrent.abortRequests();
9576
+ _this.resetLoadingState();
9577
+ }
9578
+ _this.fragPrevious = null;
9579
+ }
9580
+ }
9581
+ }
9582
+ if (media) {
9583
+ // Remove gap fragments
9584
+ _this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, _this.playlistType, true);
9585
+ _this.lastCurrentTime = currentTime;
9586
+ }
9587
+
9588
+ // in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
9589
+ if (!_this.loadedmetadata && !bufferInfo.len) {
9590
+ _this.nextLoadPosition = _this.startPosition = currentTime;
9591
+ }
9592
+
9593
+ // Async tick to speed up processing
9594
+ _this.tickImmediate();
9595
+ };
9596
+ _this.onMediaEnded = function () {
9597
+ // reset startPosition and lastCurrentTime to restart playback @ stream beginning
9598
+ _this.startPosition = _this.lastCurrentTime = 0;
9599
+ if (_this.playlistType === PlaylistLevelType.MAIN) {
9600
+ _this.hls.trigger(Events.MEDIA_ENDED, {
9601
+ stalled: false
9602
+ });
9603
+ }
9604
+ };
9474
9605
  _this.playlistType = playlistType;
9475
- _this.logPrefix = logPrefix;
9476
- _this.log = logger.log.bind(logger, logPrefix + ":");
9477
- _this.warn = logger.warn.bind(logger, logPrefix + ":");
9478
9606
  _this.hls = hls;
9479
9607
  _this.fragmentLoader = new FragmentLoader(hls.config);
9480
9608
  _this.keyLoader = keyLoader;
9481
9609
  _this.fragmentTracker = fragmentTracker;
9482
9610
  _this.config = hls.config;
9483
9611
  _this.decrypter = new Decrypter(hls.config);
9484
- hls.on(Events.MANIFEST_LOADED, _this.onManifestLoaded, _assertThisInitialized(_this));
9485
9612
  return _this;
9486
9613
  }
9487
9614
  var _proto = BaseStreamController.prototype;
9615
+ _proto.registerListeners = function registerListeners() {
9616
+ var hls = this.hls;
9617
+ hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
9618
+ hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
9619
+ hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
9620
+ hls.on(Events.MANIFEST_LOADED, this.onManifestLoaded, this);
9621
+ hls.on(Events.ERROR, this.onError, this);
9622
+ };
9623
+ _proto.unregisterListeners = function unregisterListeners() {
9624
+ var hls = this.hls;
9625
+ hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
9626
+ hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
9627
+ hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
9628
+ hls.off(Events.MANIFEST_LOADED, this.onManifestLoaded, this);
9629
+ hls.off(Events.ERROR, this.onError, this);
9630
+ };
9488
9631
  _proto.doTick = function doTick() {
9489
9632
  this.onTickEnd();
9490
9633
  };
@@ -9508,6 +9651,12 @@
9508
9651
  this.clearNextTick();
9509
9652
  this.state = State.STOPPED;
9510
9653
  };
9654
+ _proto.pauseBuffering = function pauseBuffering() {
9655
+ this.buffering = false;
9656
+ };
9657
+ _proto.resumeBuffering = function resumeBuffering() {
9658
+ this.buffering = true;
9659
+ };
9511
9660
  _proto._streamEnded = function _streamEnded(bufferInfo, levelDetails) {
9512
9661
  // If playlist is live, there is another buffered range after the current range, nothing buffered, media is detached,
9513
9662
  // of nothing loading/loaded return false
@@ -9538,10 +9687,8 @@
9538
9687
  };
9539
9688
  _proto.onMediaAttached = function onMediaAttached(event, data) {
9540
9689
  var media = this.media = this.mediaBuffer = data.media;
9541
- this.onvseeking = this.onMediaSeeking.bind(this);
9542
- this.onvended = this.onMediaEnded.bind(this);
9543
- media.addEventListener('seeking', this.onvseeking);
9544
- media.addEventListener('ended', this.onvended);
9690
+ media.addEventListener('seeking', this.onMediaSeeking);
9691
+ media.addEventListener('ended', this.onMediaEnded);
9545
9692
  var config = this.config;
9546
9693
  if (this.levels && config.autoStartLoad && this.state === State.STOPPED) {
9547
9694
  this.startLoad(config.startPosition);
@@ -9555,10 +9702,9 @@
9555
9702
  }
9556
9703
 
9557
9704
  // remove video listeners
9558
- if (media && this.onvseeking && this.onvended) {
9559
- media.removeEventListener('seeking', this.onvseeking);
9560
- media.removeEventListener('ended', this.onvended);
9561
- this.onvseeking = this.onvended = null;
9705
+ if (media) {
9706
+ media.removeEventListener('seeking', this.onMediaSeeking);
9707
+ media.removeEventListener('ended', this.onMediaEnded);
9562
9708
  }
9563
9709
  if (this.keyLoader) {
9564
9710
  this.keyLoader.detach();
@@ -9568,54 +9714,8 @@
9568
9714
  this.fragmentTracker.removeAllFragments();
9569
9715
  this.stopLoad();
9570
9716
  };
9571
- _proto.onMediaSeeking = function onMediaSeeking() {
9572
- var config = this.config,
9573
- fragCurrent = this.fragCurrent,
9574
- media = this.media,
9575
- mediaBuffer = this.mediaBuffer,
9576
- state = this.state;
9577
- var currentTime = media ? media.currentTime : 0;
9578
- var bufferInfo = BufferHelper.bufferInfo(mediaBuffer ? mediaBuffer : media, currentTime, config.maxBufferHole);
9579
- this.log("media seeking to " + (isFiniteNumber(currentTime) ? currentTime.toFixed(3) : currentTime) + ", state: " + state);
9580
- if (this.state === State.ENDED) {
9581
- this.resetLoadingState();
9582
- } else if (fragCurrent) {
9583
- // Seeking while frag load is in progress
9584
- var tolerance = config.maxFragLookUpTolerance;
9585
- var fragStartOffset = fragCurrent.start - tolerance;
9586
- var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance;
9587
- // if seeking out of buffered range or into new one
9588
- if (!bufferInfo.len || fragEndOffset < bufferInfo.start || fragStartOffset > bufferInfo.end) {
9589
- var pastFragment = currentTime > fragEndOffset;
9590
- // if the seek position is outside the current fragment range
9591
- if (currentTime < fragStartOffset || pastFragment) {
9592
- if (pastFragment && fragCurrent.loader) {
9593
- this.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
9594
- fragCurrent.abortRequests();
9595
- this.resetLoadingState();
9596
- }
9597
- this.fragPrevious = null;
9598
- }
9599
- }
9600
- }
9601
- if (media) {
9602
- // Remove gap fragments
9603
- this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, this.playlistType, true);
9604
- this.lastCurrentTime = currentTime;
9605
- }
9606
-
9607
- // in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
9608
- if (!this.loadedmetadata && !bufferInfo.len) {
9609
- this.nextLoadPosition = this.startPosition = currentTime;
9610
- }
9611
-
9612
- // Async tick to speed up processing
9613
- this.tickImmediate();
9614
- };
9615
- _proto.onMediaEnded = function onMediaEnded() {
9616
- // reset startPosition and lastCurrentTime to restart playback @ stream beginning
9617
- this.startPosition = this.lastCurrentTime = 0;
9618
- };
9717
+ _proto.onManifestLoading = function onManifestLoading() {};
9718
+ _proto.onError = function onError(event, data) {};
9619
9719
  _proto.onManifestLoaded = function onManifestLoaded(event, data) {
9620
9720
  this.startTimeOffset = data.startTimeOffset;
9621
9721
  this.initPTS = [];
@@ -9625,7 +9725,7 @@
9625
9725
  this.stopLoad();
9626
9726
  _TaskLoop.prototype.onHandlerDestroying.call(this);
9627
9727
  // @ts-ignore
9628
- this.hls = null;
9728
+ this.hls = this.onMediaSeeking = this.onMediaEnded = null;
9629
9729
  };
9630
9730
  _proto.onHandlerDestroyed = function onHandlerDestroyed() {
9631
9731
  this.state = State.STOPPED;
@@ -9755,10 +9855,10 @@
9755
9855
  var decryptData = frag.decryptdata;
9756
9856
 
9757
9857
  // check to see if the payload needs to be decrypted
9758
- if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && decryptData.method === 'AES-128') {
9858
+ if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && isFullSegmentEncryption(decryptData.method)) {
9759
9859
  var startTime = self.performance.now();
9760
9860
  // decrypt init segment data
9761
- return _this3.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).catch(function (err) {
9861
+ return _this3.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer, getAesModeFromFullSegmentMethod(decryptData.method)).catch(function (err) {
9762
9862
  hls.trigger(Events.ERROR, {
9763
9863
  type: ErrorTypes.MEDIA_ERROR,
9764
9864
  details: ErrorDetails.FRAG_DECRYPT_ERROR,
@@ -9871,7 +9971,7 @@
9871
9971
  }
9872
9972
  var keyLoadingPromise = null;
9873
9973
  if (frag.encrypted && !((_frag$decryptdata = frag.decryptdata) != null && _frag$decryptdata.key)) {
9874
- this.log("Loading key for " + frag.sn + " of [" + details.startSN + "-" + details.endSN + "], " + (this.logPrefix === '[stream-controller]' ? 'level' : 'track') + " " + frag.level);
9974
+ this.log("Loading key for " + frag.sn + " of [" + details.startSN + "-" + details.endSN + "], " + (this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track') + " " + frag.level);
9875
9975
  this.state = State.KEY_LOADING;
9876
9976
  this.fragCurrent = frag;
9877
9977
  keyLoadingPromise = this.keyLoader.load(frag).then(function (keyLoadedData) {
@@ -9902,7 +10002,7 @@
9902
10002
  var partIndex = this.getNextPart(partList, frag, targetBufferTime);
9903
10003
  if (partIndex > -1) {
9904
10004
  var part = partList[partIndex];
9905
- this.log("Loading part sn: " + frag.sn + " p: " + part.index + " cc: " + frag.cc + " of playlist [" + details.startSN + "-" + details.endSN + "] parts [0-" + partIndex + "-" + (partList.length - 1) + "] " + (this.logPrefix === '[stream-controller]' ? 'level' : 'track') + ": " + frag.level + ", target: " + parseFloat(targetBufferTime.toFixed(3)));
10005
+ this.log("Loading part sn: " + frag.sn + " p: " + part.index + " cc: " + frag.cc + " of playlist [" + details.startSN + "-" + details.endSN + "] parts [0-" + partIndex + "-" + (partList.length - 1) + "] " + (this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track') + ": " + frag.level + ", target: " + parseFloat(targetBufferTime.toFixed(3)));
9906
10006
  this.nextLoadPosition = part.start + part.duration;
9907
10007
  this.state = State.FRAG_LOADING;
9908
10008
  var _result;
@@ -9935,7 +10035,7 @@
9935
10035
  }
9936
10036
  }
9937
10037
  }
9938
- this.log("Loading fragment " + frag.sn + " cc: " + frag.cc + " " + (details ? 'of [' + details.startSN + '-' + details.endSN + '] ' : '') + (this.logPrefix === '[stream-controller]' ? 'level' : 'track') + ": " + frag.level + ", target: " + parseFloat(targetBufferTime.toFixed(3)));
10038
+ this.log("Loading fragment " + frag.sn + " cc: " + frag.cc + " " + (details ? 'of [' + details.startSN + '-' + details.endSN + '] ' : '') + (this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track') + ": " + frag.level + ", target: " + parseFloat(targetBufferTime.toFixed(3)));
9939
10039
  // Don't update nextLoadPosition for fragments which are not buffered
9940
10040
  if (isFiniteNumber(frag.sn) && !this.bitrateTest) {
9941
10041
  this.nextLoadPosition = frag.start + frag.duration;
@@ -10496,7 +10596,7 @@
10496
10596
  errorAction.resolved = true;
10497
10597
  }
10498
10598
  } else {
10499
- logger.warn(data.details + " reached or exceeded max retry (" + retryCount + ")");
10599
+ this.warn(data.details + " reached or exceeded max retry (" + retryCount + ")");
10500
10600
  return;
10501
10601
  }
10502
10602
  } else if ((errorAction == null ? void 0 : errorAction.action) === NetworkErrorAction.SendAlternateToPenaltyBox) {
@@ -10896,6 +10996,7 @@
10896
10996
  */
10897
10997
  function getAudioConfig(observer, data, offset, audioCodec) {
10898
10998
  var adtsObjectType;
10999
+ var originalAdtsObjectType;
10899
11000
  var adtsExtensionSamplingIndex;
10900
11001
  var adtsChannelConfig;
10901
11002
  var config;
@@ -10903,7 +11004,7 @@
10903
11004
  var manifestCodec = audioCodec;
10904
11005
  var adtsSamplingRates = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];
10905
11006
  // byte 2
10906
- adtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1;
11007
+ adtsObjectType = originalAdtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1;
10907
11008
  var adtsSamplingIndex = (data[offset + 2] & 0x3c) >>> 2;
10908
11009
  if (adtsSamplingIndex > adtsSamplingRates.length - 1) {
10909
11010
  var error = new Error("invalid ADTS sampling index:" + adtsSamplingIndex);
@@ -10920,8 +11021,8 @@
10920
11021
  // byte 3
10921
11022
  adtsChannelConfig |= (data[offset + 3] & 0xc0) >>> 6;
10922
11023
  logger.log("manifest codec:" + audioCodec + ", ADTS type:" + adtsObjectType + ", samplingIndex:" + adtsSamplingIndex);
10923
- // firefox: freq less than 24kHz = AAC SBR (HE-AAC)
10924
- if (/firefox/i.test(userAgent)) {
11024
+ // Firefox and Pale Moon: freq less than 24kHz = AAC SBR (HE-AAC)
11025
+ if (/firefox|palemoon/i.test(userAgent)) {
10925
11026
  if (adtsSamplingIndex >= 6) {
10926
11027
  adtsObjectType = 5;
10927
11028
  config = new Array(4);
@@ -11015,6 +11116,7 @@
11015
11116
  samplerate: adtsSamplingRates[adtsSamplingIndex],
11016
11117
  channelCount: adtsChannelConfig,
11017
11118
  codec: 'mp4a.40.' + adtsObjectType,
11119
+ parsedCodec: 'mp4a.40.' + originalAdtsObjectType,
11018
11120
  manifestCodec: manifestCodec
11019
11121
  };
11020
11122
  }
@@ -11069,7 +11171,8 @@
11069
11171
  track.channelCount = config.channelCount;
11070
11172
  track.codec = config.codec;
11071
11173
  track.manifestCodec = config.manifestCodec;
11072
- logger.log("parsed codec:" + track.codec + ", rate:" + config.samplerate + ", channels:" + config.channelCount);
11174
+ track.parsedCodec = config.parsedCodec;
11175
+ logger.log("parsed codec:" + track.parsedCodec + ", codec:" + track.codec + ", rate:" + config.samplerate + ", channels:" + config.channelCount);
11073
11176
  }
11074
11177
  }
11075
11178
  function getFrameDuration(samplerate) {
@@ -11667,69 +11770,173 @@
11667
11770
  logger.log(VideoSample.pts + '/' + VideoSample.dts + ':' + VideoSample.debug);
11668
11771
  }
11669
11772
  };
11670
- return BaseVideoParser;
11671
- }();
11672
-
11673
- /**
11674
- * Parser for exponential Golomb codes, a variable-bitwidth number encoding scheme used by h264.
11675
- */
11676
-
11677
- var ExpGolomb = /*#__PURE__*/function () {
11678
- function ExpGolomb(data) {
11679
- this.data = void 0;
11680
- this.bytesAvailable = void 0;
11681
- this.word = void 0;
11682
- this.bitsAvailable = void 0;
11683
- this.data = data;
11684
- // the number of bytes left to examine in this.data
11685
- this.bytesAvailable = data.byteLength;
11686
- // the current word being examined
11687
- this.word = 0; // :uint
11688
- // the number of bits left to examine in the current word
11689
- this.bitsAvailable = 0; // :uint
11690
- }
11691
-
11692
- // ():void
11693
- var _proto = ExpGolomb.prototype;
11694
- _proto.loadWord = function loadWord() {
11695
- var data = this.data;
11696
- var bytesAvailable = this.bytesAvailable;
11697
- var position = data.byteLength - bytesAvailable;
11698
- var workingBytes = new Uint8Array(4);
11699
- var availableBytes = Math.min(4, bytesAvailable);
11700
- if (availableBytes === 0) {
11701
- throw new Error('no bytes available');
11702
- }
11703
- workingBytes.set(data.subarray(position, position + availableBytes));
11704
- this.word = new DataView(workingBytes.buffer).getUint32(0);
11705
- // track the amount of this.data that has been processed
11706
- this.bitsAvailable = availableBytes * 8;
11707
- this.bytesAvailable -= availableBytes;
11708
- }
11773
+ _proto.parseNALu = function parseNALu(track, array) {
11774
+ var len = array.byteLength;
11775
+ var state = track.naluState || 0;
11776
+ var lastState = state;
11777
+ var units = [];
11778
+ var i = 0;
11779
+ var value;
11780
+ var overflow;
11781
+ var unitType;
11782
+ var lastUnitStart = -1;
11783
+ var lastUnitType = 0;
11784
+ // logger.log('PES:' + Hex.hexDump(array));
11709
11785
 
11710
- // (count:int):void
11711
- ;
11712
- _proto.skipBits = function skipBits(count) {
11713
- var skipBytes; // :int
11714
- count = Math.min(count, this.bytesAvailable * 8 + this.bitsAvailable);
11715
- if (this.bitsAvailable > count) {
11716
- this.word <<= count;
11717
- this.bitsAvailable -= count;
11718
- } else {
11719
- count -= this.bitsAvailable;
11720
- skipBytes = count >> 3;
11721
- count -= skipBytes << 3;
11722
- this.bytesAvailable -= skipBytes;
11723
- this.loadWord();
11724
- this.word <<= count;
11725
- this.bitsAvailable -= count;
11786
+ if (state === -1) {
11787
+ // special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet
11788
+ lastUnitStart = 0;
11789
+ // NALu type is value read from offset 0
11790
+ lastUnitType = this.getNALuType(array, 0);
11791
+ state = 0;
11792
+ i = 1;
11726
11793
  }
11727
- }
11728
-
11729
- // (size:int):uint
11730
- ;
11731
- _proto.readBits = function readBits(size) {
11732
- var bits = Math.min(this.bitsAvailable, size); // :uint
11794
+ while (i < len) {
11795
+ value = array[i++];
11796
+ // optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case
11797
+ if (!state) {
11798
+ state = value ? 0 : 1;
11799
+ continue;
11800
+ }
11801
+ if (state === 1) {
11802
+ state = value ? 0 : 2;
11803
+ continue;
11804
+ }
11805
+ // here we have state either equal to 2 or 3
11806
+ if (!value) {
11807
+ state = 3;
11808
+ } else if (value === 1) {
11809
+ overflow = i - state - 1;
11810
+ if (lastUnitStart >= 0) {
11811
+ var unit = {
11812
+ data: array.subarray(lastUnitStart, overflow),
11813
+ type: lastUnitType
11814
+ };
11815
+ // logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);
11816
+ units.push(unit);
11817
+ } else {
11818
+ // lastUnitStart is undefined => this is the first start code found in this PES packet
11819
+ // first check if start code delimiter is overlapping between 2 PES packets,
11820
+ // ie it started in last packet (lastState not zero)
11821
+ // and ended at the beginning of this PES packet (i <= 4 - lastState)
11822
+ var lastUnit = this.getLastNalUnit(track.samples);
11823
+ if (lastUnit) {
11824
+ if (lastState && i <= 4 - lastState) {
11825
+ // start delimiter overlapping between PES packets
11826
+ // strip start delimiter bytes from the end of last NAL unit
11827
+ // check if lastUnit had a state different from zero
11828
+ if (lastUnit.state) {
11829
+ // strip last bytes
11830
+ lastUnit.data = lastUnit.data.subarray(0, lastUnit.data.byteLength - lastState);
11831
+ }
11832
+ }
11833
+ // If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.
11834
+
11835
+ if (overflow > 0) {
11836
+ // logger.log('first NALU found with overflow:' + overflow);
11837
+ lastUnit.data = appendUint8Array(lastUnit.data, array.subarray(0, overflow));
11838
+ lastUnit.state = 0;
11839
+ }
11840
+ }
11841
+ }
11842
+ // check if we can read unit type
11843
+ if (i < len) {
11844
+ unitType = this.getNALuType(array, i);
11845
+ // logger.log('find NALU @ offset:' + i + ',type:' + unitType);
11846
+ lastUnitStart = i;
11847
+ lastUnitType = unitType;
11848
+ state = 0;
11849
+ } else {
11850
+ // not enough byte to read unit type. let's read it on next PES parsing
11851
+ state = -1;
11852
+ }
11853
+ } else {
11854
+ state = 0;
11855
+ }
11856
+ }
11857
+ if (lastUnitStart >= 0 && state >= 0) {
11858
+ var _unit = {
11859
+ data: array.subarray(lastUnitStart, len),
11860
+ type: lastUnitType,
11861
+ state: state
11862
+ };
11863
+ units.push(_unit);
11864
+ // logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
11865
+ }
11866
+ // no NALu found
11867
+ if (units.length === 0) {
11868
+ // append pes.data to previous NAL unit
11869
+ var _lastUnit = this.getLastNalUnit(track.samples);
11870
+ if (_lastUnit) {
11871
+ _lastUnit.data = appendUint8Array(_lastUnit.data, array);
11872
+ }
11873
+ }
11874
+ track.naluState = state;
11875
+ return units;
11876
+ };
11877
+ return BaseVideoParser;
11878
+ }();
11879
+
11880
+ /**
11881
+ * Parser for exponential Golomb codes, a variable-bitwidth number encoding scheme used by h264.
11882
+ */
11883
+
11884
+ var ExpGolomb = /*#__PURE__*/function () {
11885
+ function ExpGolomb(data) {
11886
+ this.data = void 0;
11887
+ this.bytesAvailable = void 0;
11888
+ this.word = void 0;
11889
+ this.bitsAvailable = void 0;
11890
+ this.data = data;
11891
+ // the number of bytes left to examine in this.data
11892
+ this.bytesAvailable = data.byteLength;
11893
+ // the current word being examined
11894
+ this.word = 0; // :uint
11895
+ // the number of bits left to examine in the current word
11896
+ this.bitsAvailable = 0; // :uint
11897
+ }
11898
+
11899
+ // ():void
11900
+ var _proto = ExpGolomb.prototype;
11901
+ _proto.loadWord = function loadWord() {
11902
+ var data = this.data;
11903
+ var bytesAvailable = this.bytesAvailable;
11904
+ var position = data.byteLength - bytesAvailable;
11905
+ var workingBytes = new Uint8Array(4);
11906
+ var availableBytes = Math.min(4, bytesAvailable);
11907
+ if (availableBytes === 0) {
11908
+ throw new Error('no bytes available');
11909
+ }
11910
+ workingBytes.set(data.subarray(position, position + availableBytes));
11911
+ this.word = new DataView(workingBytes.buffer).getUint32(0);
11912
+ // track the amount of this.data that has been processed
11913
+ this.bitsAvailable = availableBytes * 8;
11914
+ this.bytesAvailable -= availableBytes;
11915
+ }
11916
+
11917
+ // (count:int):void
11918
+ ;
11919
+ _proto.skipBits = function skipBits(count) {
11920
+ var skipBytes; // :int
11921
+ count = Math.min(count, this.bytesAvailable * 8 + this.bitsAvailable);
11922
+ if (this.bitsAvailable > count) {
11923
+ this.word <<= count;
11924
+ this.bitsAvailable -= count;
11925
+ } else {
11926
+ count -= this.bitsAvailable;
11927
+ skipBytes = count >> 3;
11928
+ count -= skipBytes << 3;
11929
+ this.bytesAvailable -= skipBytes;
11930
+ this.loadWord();
11931
+ this.word <<= count;
11932
+ this.bitsAvailable -= count;
11933
+ }
11934
+ }
11935
+
11936
+ // (size:int):uint
11937
+ ;
11938
+ _proto.readBits = function readBits(size) {
11939
+ var bits = Math.min(this.bitsAvailable, size); // :uint
11733
11940
  var valu = this.word >>> 32 - bits; // :uint
11734
11941
  if (size > 32) {
11735
11942
  logger.error('Cannot read more than 32 bits at a time');
@@ -11821,22 +12028,179 @@
11821
12028
  ;
11822
12029
  _proto.readUInt = function readUInt() {
11823
12030
  return this.readBits(32);
12031
+ };
12032
+ return ExpGolomb;
12033
+ }();
12034
+
12035
+ var AvcVideoParser = /*#__PURE__*/function (_BaseVideoParser) {
12036
+ _inheritsLoose(AvcVideoParser, _BaseVideoParser);
12037
+ function AvcVideoParser() {
12038
+ return _BaseVideoParser.apply(this, arguments) || this;
12039
+ }
12040
+ var _proto = AvcVideoParser.prototype;
12041
+ _proto.parsePES = function parsePES(track, textTrack, pes, last, duration) {
12042
+ var _this = this;
12043
+ var units = this.parseNALu(track, pes.data);
12044
+ var VideoSample = this.VideoSample;
12045
+ var push;
12046
+ var spsfound = false;
12047
+ // free pes.data to save up some memory
12048
+ pes.data = null;
12049
+
12050
+ // if new NAL units found and last sample still there, let's push ...
12051
+ // this helps parsing streams with missing AUD (only do this if AUD never found)
12052
+ if (VideoSample && units.length && !track.audFound) {
12053
+ this.pushAccessUnit(VideoSample, track);
12054
+ VideoSample = this.VideoSample = this.createVideoSample(false, pes.pts, pes.dts, '');
12055
+ }
12056
+ units.forEach(function (unit) {
12057
+ var _VideoSample2;
12058
+ switch (unit.type) {
12059
+ // NDR
12060
+ case 1:
12061
+ {
12062
+ var iskey = false;
12063
+ push = true;
12064
+ var data = unit.data;
12065
+ // only check slice type to detect KF in case SPS found in same packet (any keyframe is preceded by SPS ...)
12066
+ if (spsfound && data.length > 4) {
12067
+ // retrieve slice type by parsing beginning of NAL unit (follow H264 spec, slice_header definition) to detect keyframe embedded in NDR
12068
+ var sliceType = _this.readSliceType(data);
12069
+ // 2 : I slice, 4 : SI slice, 7 : I slice, 9: SI slice
12070
+ // SI slice : A slice that is coded using intra prediction only and using quantisation of the prediction samples.
12071
+ // An SI slice can be coded such that its decoded samples can be constructed identically to an SP slice.
12072
+ // I slice: A slice that is not an SI slice that is decoded using intra prediction only.
12073
+ // if (sliceType === 2 || sliceType === 7) {
12074
+ if (sliceType === 2 || sliceType === 4 || sliceType === 7 || sliceType === 9) {
12075
+ iskey = true;
12076
+ }
12077
+ }
12078
+ if (iskey) {
12079
+ var _VideoSample;
12080
+ // if we have non-keyframe data already, that cannot belong to the same frame as a keyframe, so force a push
12081
+ if ((_VideoSample = VideoSample) != null && _VideoSample.frame && !VideoSample.key) {
12082
+ _this.pushAccessUnit(VideoSample, track);
12083
+ VideoSample = _this.VideoSample = null;
12084
+ }
12085
+ }
12086
+ if (!VideoSample) {
12087
+ VideoSample = _this.VideoSample = _this.createVideoSample(true, pes.pts, pes.dts, '');
12088
+ }
12089
+ VideoSample.frame = true;
12090
+ VideoSample.key = iskey;
12091
+ break;
12092
+ // IDR
12093
+ }
12094
+ case 5:
12095
+ push = true;
12096
+ // handle PES not starting with AUD
12097
+ // if we have frame data already, that cannot belong to the same frame, so force a push
12098
+ if ((_VideoSample2 = VideoSample) != null && _VideoSample2.frame && !VideoSample.key) {
12099
+ _this.pushAccessUnit(VideoSample, track);
12100
+ VideoSample = _this.VideoSample = null;
12101
+ }
12102
+ if (!VideoSample) {
12103
+ VideoSample = _this.VideoSample = _this.createVideoSample(true, pes.pts, pes.dts, '');
12104
+ }
12105
+ VideoSample.key = true;
12106
+ VideoSample.frame = true;
12107
+ break;
12108
+ // SEI
12109
+ case 6:
12110
+ {
12111
+ push = true;
12112
+ parseSEIMessageFromNALu(unit.data, 1, pes.pts, textTrack.samples);
12113
+ break;
12114
+ // SPS
12115
+ }
12116
+ case 7:
12117
+ {
12118
+ var _track$pixelRatio, _track$pixelRatio2;
12119
+ push = true;
12120
+ spsfound = true;
12121
+ var sps = unit.data;
12122
+ var config = _this.readSPS(sps);
12123
+ if (!track.sps || track.width !== config.width || track.height !== config.height || ((_track$pixelRatio = track.pixelRatio) == null ? void 0 : _track$pixelRatio[0]) !== config.pixelRatio[0] || ((_track$pixelRatio2 = track.pixelRatio) == null ? void 0 : _track$pixelRatio2[1]) !== config.pixelRatio[1]) {
12124
+ track.width = config.width;
12125
+ track.height = config.height;
12126
+ track.pixelRatio = config.pixelRatio;
12127
+ track.sps = [sps];
12128
+ track.duration = duration;
12129
+ var codecarray = sps.subarray(1, 4);
12130
+ var codecstring = 'avc1.';
12131
+ for (var i = 0; i < 3; i++) {
12132
+ var h = codecarray[i].toString(16);
12133
+ if (h.length < 2) {
12134
+ h = '0' + h;
12135
+ }
12136
+ codecstring += h;
12137
+ }
12138
+ track.codec = codecstring;
12139
+ }
12140
+ break;
12141
+ }
12142
+ // PPS
12143
+ case 8:
12144
+ push = true;
12145
+ track.pps = [unit.data];
12146
+ break;
12147
+ // AUD
12148
+ case 9:
12149
+ push = true;
12150
+ track.audFound = true;
12151
+ if (VideoSample) {
12152
+ _this.pushAccessUnit(VideoSample, track);
12153
+ }
12154
+ VideoSample = _this.VideoSample = _this.createVideoSample(false, pes.pts, pes.dts, '');
12155
+ break;
12156
+ // Filler Data
12157
+ case 12:
12158
+ push = true;
12159
+ break;
12160
+ default:
12161
+ push = false;
12162
+ if (VideoSample) {
12163
+ VideoSample.debug += 'unknown NAL ' + unit.type + ' ';
12164
+ }
12165
+ break;
12166
+ }
12167
+ if (VideoSample && push) {
12168
+ var _units = VideoSample.units;
12169
+ _units.push(unit);
12170
+ }
12171
+ });
12172
+ // if last PES packet, push samples
12173
+ if (last && VideoSample) {
12174
+ this.pushAccessUnit(VideoSample, track);
12175
+ this.VideoSample = null;
12176
+ }
12177
+ };
12178
+ _proto.getNALuType = function getNALuType(data, offset) {
12179
+ return data[offset] & 0x1f;
12180
+ };
12181
+ _proto.readSliceType = function readSliceType(data) {
12182
+ var eg = new ExpGolomb(data);
12183
+ // skip NALu type
12184
+ eg.readUByte();
12185
+ // discard first_mb_in_slice
12186
+ eg.readUEG();
12187
+ // return slice_type
12188
+ return eg.readUEG();
11824
12189
  }
11825
12190
 
11826
12191
  /**
11827
- * Advance the ExpGolomb decoder past a scaling list. The scaling
11828
- * list is optionally transmitted as part of a sequence parameter
12192
+ * The scaling list is optionally transmitted as part of a sequence parameter
11829
12193
  * set and is not relevant to transmuxing.
11830
12194
  * @param count the number of entries in this scaling list
11831
12195
  * @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
11832
12196
  */;
11833
- _proto.skipScalingList = function skipScalingList(count) {
12197
+ _proto.skipScalingList = function skipScalingList(count, reader) {
11834
12198
  var lastScale = 8;
11835
12199
  var nextScale = 8;
11836
12200
  var deltaScale;
11837
12201
  for (var j = 0; j < count; j++) {
11838
12202
  if (nextScale !== 0) {
11839
- deltaScale = this.readEG();
12203
+ deltaScale = reader.readEG();
11840
12204
  nextScale = (lastScale + deltaScale + 256) % 256;
11841
12205
  }
11842
12206
  lastScale = nextScale === 0 ? lastScale : nextScale;
@@ -11851,7 +12215,8 @@
11851
12215
  * sequence parameter set, including the dimensions of the
11852
12216
  * associated video frames.
11853
12217
  */;
11854
- _proto.readSPS = function readSPS() {
12218
+ _proto.readSPS = function readSPS(sps) {
12219
+ var eg = new ExpGolomb(sps);
11855
12220
  var frameCropLeftOffset = 0;
11856
12221
  var frameCropRightOffset = 0;
11857
12222
  var frameCropTopOffset = 0;
@@ -11859,13 +12224,13 @@
11859
12224
  var numRefFramesInPicOrderCntCycle;
11860
12225
  var scalingListCount;
11861
12226
  var i;
11862
- var readUByte = this.readUByte.bind(this);
11863
- var readBits = this.readBits.bind(this);
11864
- var readUEG = this.readUEG.bind(this);
11865
- var readBoolean = this.readBoolean.bind(this);
11866
- var skipBits = this.skipBits.bind(this);
11867
- var skipEG = this.skipEG.bind(this);
11868
- var skipUEG = this.skipUEG.bind(this);
12227
+ var readUByte = eg.readUByte.bind(eg);
12228
+ var readBits = eg.readBits.bind(eg);
12229
+ var readUEG = eg.readUEG.bind(eg);
12230
+ var readBoolean = eg.readBoolean.bind(eg);
12231
+ var skipBits = eg.skipBits.bind(eg);
12232
+ var skipEG = eg.skipEG.bind(eg);
12233
+ var skipUEG = eg.skipUEG.bind(eg);
11869
12234
  var skipScalingList = this.skipScalingList.bind(this);
11870
12235
  readUByte();
11871
12236
  var profileIdc = readUByte(); // profile_idc
@@ -11890,9 +12255,9 @@
11890
12255
  if (readBoolean()) {
11891
12256
  // seq_scaling_list_present_flag[ i ]
11892
12257
  if (i < 6) {
11893
- skipScalingList(16);
12258
+ skipScalingList(16, eg);
11894
12259
  } else {
11895
- skipScalingList(64);
12260
+ skipScalingList(64, eg);
11896
12261
  }
11897
12262
  }
11898
12263
  }
@@ -11997,26 +12362,24 @@
11997
12362
  pixelRatio: pixelRatio
11998
12363
  };
11999
12364
  };
12000
- _proto.readSliceType = function readSliceType() {
12001
- // skip NALu type
12002
- this.readUByte();
12003
- // discard first_mb_in_slice
12004
- this.readUEG();
12005
- // return slice_type
12006
- return this.readUEG();
12007
- };
12008
- return ExpGolomb;
12009
- }();
12365
+ return AvcVideoParser;
12366
+ }(BaseVideoParser);
12010
12367
 
12011
- var AvcVideoParser = /*#__PURE__*/function (_BaseVideoParser) {
12012
- _inheritsLoose(AvcVideoParser, _BaseVideoParser);
12013
- function AvcVideoParser() {
12014
- return _BaseVideoParser.apply(this, arguments) || this;
12368
+ var HevcVideoParser = /*#__PURE__*/function (_BaseVideoParser) {
12369
+ _inheritsLoose(HevcVideoParser, _BaseVideoParser);
12370
+ function HevcVideoParser() {
12371
+ var _this;
12372
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
12373
+ args[_key] = arguments[_key];
12374
+ }
12375
+ _this = _BaseVideoParser.call.apply(_BaseVideoParser, [this].concat(args)) || this;
12376
+ _this.initVPS = null;
12377
+ return _this;
12015
12378
  }
12016
- var _proto = AvcVideoParser.prototype;
12017
- _proto.parseAVCPES = function parseAVCPES(track, textTrack, pes, last, duration) {
12018
- var _this = this;
12019
- var units = this.parseAVCNALu(track, pes.data);
12379
+ var _proto = HevcVideoParser.prototype;
12380
+ _proto.parsePES = function parsePES(track, textTrack, pes, last, duration) {
12381
+ var _this2 = this;
12382
+ var units = this.parseNALu(track, pes.data);
12020
12383
  var VideoSample = this.VideoSample;
12021
12384
  var push;
12022
12385
  var spsfound = false;
@@ -12032,112 +12395,143 @@
12032
12395
  units.forEach(function (unit) {
12033
12396
  var _VideoSample2;
12034
12397
  switch (unit.type) {
12035
- // NDR
12398
+ // NON-IDR, NON RANDOM ACCESS SLICE
12399
+ case 0:
12036
12400
  case 1:
12037
- {
12038
- var iskey = false;
12039
- push = true;
12040
- var data = unit.data;
12041
- // only check slice type to detect KF in case SPS found in same packet (any keyframe is preceded by SPS ...)
12042
- if (spsfound && data.length > 4) {
12043
- // retrieve slice type by parsing beginning of NAL unit (follow H264 spec, slice_header definition) to detect keyframe embedded in NDR
12044
- var sliceType = new ExpGolomb(data).readSliceType();
12045
- // 2 : I slice, 4 : SI slice, 7 : I slice, 9: SI slice
12046
- // SI slice : A slice that is coded using intra prediction only and using quantisation of the prediction samples.
12047
- // An SI slice can be coded such that its decoded samples can be constructed identically to an SP slice.
12048
- // I slice: A slice that is not an SI slice that is decoded using intra prediction only.
12049
- // if (sliceType === 2 || sliceType === 7) {
12050
- if (sliceType === 2 || sliceType === 4 || sliceType === 7 || sliceType === 9) {
12051
- iskey = true;
12052
- }
12053
- }
12054
- if (iskey) {
12055
- var _VideoSample;
12056
- // if we have non-keyframe data already, that cannot belong to the same frame as a keyframe, so force a push
12057
- if ((_VideoSample = VideoSample) != null && _VideoSample.frame && !VideoSample.key) {
12058
- _this.pushAccessUnit(VideoSample, track);
12059
- VideoSample = _this.VideoSample = null;
12060
- }
12061
- }
12062
- if (!VideoSample) {
12063
- VideoSample = _this.VideoSample = _this.createVideoSample(true, pes.pts, pes.dts, '');
12401
+ case 2:
12402
+ case 3:
12403
+ case 4:
12404
+ case 5:
12405
+ case 6:
12406
+ case 7:
12407
+ case 8:
12408
+ case 9:
12409
+ if (!VideoSample) {
12410
+ VideoSample = _this2.VideoSample = _this2.createVideoSample(false, pes.pts, pes.dts, '');
12411
+ }
12412
+ VideoSample.frame = true;
12413
+ push = true;
12414
+ break;
12415
+
12416
+ // CRA, BLA (random access picture)
12417
+ case 16:
12418
+ case 17:
12419
+ case 18:
12420
+ case 21:
12421
+ push = true;
12422
+ if (spsfound) {
12423
+ var _VideoSample;
12424
+ // handle PES not starting with AUD
12425
+ // if we have frame data already, that cannot belong to the same frame, so force a push
12426
+ if ((_VideoSample = VideoSample) != null && _VideoSample.frame && !VideoSample.key) {
12427
+ _this2.pushAccessUnit(VideoSample, track);
12428
+ VideoSample = _this2.VideoSample = null;
12064
12429
  }
12065
- VideoSample.frame = true;
12066
- VideoSample.key = iskey;
12067
- break;
12068
- // IDR
12069
12430
  }
12070
- case 5:
12431
+ if (!VideoSample) {
12432
+ VideoSample = _this2.VideoSample = _this2.createVideoSample(true, pes.pts, pes.dts, '');
12433
+ }
12434
+ VideoSample.key = true;
12435
+ VideoSample.frame = true;
12436
+ break;
12437
+
12438
+ // IDR
12439
+ case 19:
12440
+ case 20:
12071
12441
  push = true;
12072
12442
  // handle PES not starting with AUD
12073
12443
  // if we have frame data already, that cannot belong to the same frame, so force a push
12074
12444
  if ((_VideoSample2 = VideoSample) != null && _VideoSample2.frame && !VideoSample.key) {
12075
- _this.pushAccessUnit(VideoSample, track);
12076
- VideoSample = _this.VideoSample = null;
12445
+ _this2.pushAccessUnit(VideoSample, track);
12446
+ VideoSample = _this2.VideoSample = null;
12077
12447
  }
12078
12448
  if (!VideoSample) {
12079
- VideoSample = _this.VideoSample = _this.createVideoSample(true, pes.pts, pes.dts, '');
12449
+ VideoSample = _this2.VideoSample = _this2.createVideoSample(true, pes.pts, pes.dts, '');
12080
12450
  }
12081
12451
  VideoSample.key = true;
12082
12452
  VideoSample.frame = true;
12083
12453
  break;
12454
+
12084
12455
  // SEI
12085
- case 6:
12086
- {
12087
- push = true;
12088
- parseSEIMessageFromNALu(unit.data, 1, pes.pts, textTrack.samples);
12089
- break;
12090
- // SPS
12456
+ case 39:
12457
+ push = true;
12458
+ parseSEIMessageFromNALu(unit.data, 2,
12459
+ // NALu header size
12460
+ pes.pts, textTrack.samples);
12461
+ break;
12462
+
12463
+ // VPS
12464
+ case 32:
12465
+ push = true;
12466
+ if (!track.vps) {
12467
+ var config = _this2.readVPS(unit.data);
12468
+ track.params = _objectSpread2({}, config);
12469
+ _this2.initVPS = unit.data;
12091
12470
  }
12092
- case 7:
12093
- {
12094
- var _track$pixelRatio, _track$pixelRatio2;
12095
- push = true;
12096
- spsfound = true;
12097
- var sps = unit.data;
12098
- var expGolombDecoder = new ExpGolomb(sps);
12099
- var config = expGolombDecoder.readSPS();
12100
- if (!track.sps || track.width !== config.width || track.height !== config.height || ((_track$pixelRatio = track.pixelRatio) == null ? void 0 : _track$pixelRatio[0]) !== config.pixelRatio[0] || ((_track$pixelRatio2 = track.pixelRatio) == null ? void 0 : _track$pixelRatio2[1]) !== config.pixelRatio[1]) {
12101
- track.width = config.width;
12102
- track.height = config.height;
12103
- track.pixelRatio = config.pixelRatio;
12104
- track.sps = [sps];
12471
+ track.vps = [unit.data];
12472
+ break;
12473
+
12474
+ // SPS
12475
+ case 33:
12476
+ push = true;
12477
+ spsfound = true;
12478
+ if (typeof track.params === 'object') {
12479
+ if (track.vps !== undefined && track.vps[0] !== _this2.initVPS && track.sps !== undefined && !_this2.matchSPS(track.sps[0], unit.data)) {
12480
+ _this2.initVPS = track.vps[0];
12481
+ track.sps = track.pps = undefined;
12482
+ }
12483
+ if (!track.sps) {
12484
+ var _config = _this2.readSPS(unit.data);
12485
+ track.width = _config.width;
12486
+ track.height = _config.height;
12487
+ track.pixelRatio = _config.pixelRatio;
12105
12488
  track.duration = duration;
12106
- var codecarray = sps.subarray(1, 4);
12107
- var codecstring = 'avc1.';
12108
- for (var i = 0; i < 3; i++) {
12109
- var h = codecarray[i].toString(16);
12110
- if (h.length < 2) {
12111
- h = '0' + h;
12112
- }
12113
- codecstring += h;
12489
+ track.codec = _config.codecString;
12490
+ track.sps = [];
12491
+ for (var prop in _config.params) {
12492
+ track.params[prop] = _config.params[prop];
12114
12493
  }
12115
- track.codec = codecstring;
12116
12494
  }
12117
- break;
12495
+ if (track.vps !== undefined && track.vps[0] === _this2.initVPS) {
12496
+ track.sps.push(unit.data);
12497
+ }
12498
+ }
12499
+ if (!VideoSample) {
12500
+ VideoSample = _this2.VideoSample = _this2.createVideoSample(true, pes.pts, pes.dts, '');
12118
12501
  }
12502
+ VideoSample.key = true;
12503
+ break;
12504
+
12119
12505
  // PPS
12120
- case 8:
12506
+ case 34:
12121
12507
  push = true;
12122
- track.pps = [unit.data];
12508
+ if (typeof track.params === 'object') {
12509
+ if (!track.pps) {
12510
+ track.pps = [];
12511
+ var _config2 = _this2.readPPS(unit.data);
12512
+ for (var _prop in _config2) {
12513
+ track.params[_prop] = _config2[_prop];
12514
+ }
12515
+ }
12516
+ if (_this2.initVPS !== null || track.pps.length === 0) {
12517
+ track.pps.push(unit.data);
12518
+ }
12519
+ }
12123
12520
  break;
12124
- // AUD
12125
- case 9:
12521
+
12522
+ // ACCESS UNIT DELIMITER
12523
+ case 35:
12126
12524
  push = true;
12127
12525
  track.audFound = true;
12128
12526
  if (VideoSample) {
12129
- _this.pushAccessUnit(VideoSample, track);
12527
+ _this2.pushAccessUnit(VideoSample, track);
12130
12528
  }
12131
- VideoSample = _this.VideoSample = _this.createVideoSample(false, pes.pts, pes.dts, '');
12132
- break;
12133
- // Filler Data
12134
- case 12:
12135
- push = true;
12529
+ VideoSample = _this2.VideoSample = _this2.createVideoSample(false, pes.pts, pes.dts, '');
12136
12530
  break;
12137
12531
  default:
12138
12532
  push = false;
12139
12533
  if (VideoSample) {
12140
- VideoSample.debug += 'unknown NAL ' + unit.type + ' ';
12534
+ VideoSample.debug += 'unknown or irrelevant NAL ' + unit.type + ' ';
12141
12535
  }
12142
12536
  break;
12143
12537
  }
@@ -12152,111 +12546,425 @@
12152
12546
  this.VideoSample = null;
12153
12547
  }
12154
12548
  };
12155
- _proto.parseAVCNALu = function parseAVCNALu(track, array) {
12156
- var len = array.byteLength;
12157
- var state = track.naluState || 0;
12158
- var lastState = state;
12159
- var units = [];
12160
- var i = 0;
12161
- var value;
12162
- var overflow;
12163
- var unitType;
12164
- var lastUnitStart = -1;
12165
- var lastUnitType = 0;
12166
- // logger.log('PES:' + Hex.hexDump(array));
12167
-
12168
- if (state === -1) {
12169
- // special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet
12170
- lastUnitStart = 0;
12171
- // NALu type is value read from offset 0
12172
- lastUnitType = array[0] & 0x1f;
12173
- state = 0;
12174
- i = 1;
12175
- }
12176
- while (i < len) {
12177
- value = array[i++];
12178
- // optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case
12179
- if (!state) {
12180
- state = value ? 0 : 1;
12181
- continue;
12182
- }
12183
- if (state === 1) {
12184
- state = value ? 0 : 2;
12185
- continue;
12549
+ _proto.getNALuType = function getNALuType(data, offset) {
12550
+ return (data[offset] & 0x7e) >>> 1;
12551
+ };
12552
+ _proto.ebsp2rbsp = function ebsp2rbsp(arr) {
12553
+ var dst = new Uint8Array(arr.byteLength);
12554
+ var dstIdx = 0;
12555
+ for (var i = 0; i < arr.byteLength; i++) {
12556
+ if (i >= 2) {
12557
+ // Unescape: Skip 0x03 after 00 00
12558
+ if (arr[i] === 0x03 && arr[i - 1] === 0x00 && arr[i - 2] === 0x00) {
12559
+ continue;
12560
+ }
12186
12561
  }
12187
- // here we have state either equal to 2 or 3
12188
- if (!value) {
12189
- state = 3;
12190
- } else if (value === 1) {
12191
- overflow = i - state - 1;
12192
- if (lastUnitStart >= 0) {
12193
- var unit = {
12194
- data: array.subarray(lastUnitStart, overflow),
12195
- type: lastUnitType
12196
- };
12197
- // logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);
12198
- units.push(unit);
12199
- } else {
12200
- // lastUnitStart is undefined => this is the first start code found in this PES packet
12201
- // first check if start code delimiter is overlapping between 2 PES packets,
12202
- // ie it started in last packet (lastState not zero)
12203
- // and ended at the beginning of this PES packet (i <= 4 - lastState)
12204
- var lastUnit = this.getLastNalUnit(track.samples);
12205
- if (lastUnit) {
12206
- if (lastState && i <= 4 - lastState) {
12207
- // start delimiter overlapping between PES packets
12208
- // strip start delimiter bytes from the end of last NAL unit
12209
- // check if lastUnit had a state different from zero
12210
- if (lastUnit.state) {
12211
- // strip last bytes
12212
- lastUnit.data = lastUnit.data.subarray(0, lastUnit.data.byteLength - lastState);
12213
- }
12214
- }
12215
- // If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.
12562
+ dst[dstIdx] = arr[i];
12563
+ dstIdx++;
12564
+ }
12565
+ return new Uint8Array(dst.buffer, 0, dstIdx);
12566
+ };
12567
+ _proto.readVPS = function readVPS(vps) {
12568
+ var eg = new ExpGolomb(vps);
12569
+ // remove header
12570
+ eg.readUByte();
12571
+ eg.readUByte();
12572
+ eg.readBits(4); // video_parameter_set_id
12573
+ eg.skipBits(2);
12574
+ eg.readBits(6); // max_layers_minus1
12575
+ var max_sub_layers_minus1 = eg.readBits(3);
12576
+ var temporal_id_nesting_flag = eg.readBoolean();
12577
+ // ...vui fps can be here, but empty fps value is not critical for metadata
12216
12578
 
12217
- if (overflow > 0) {
12218
- // logger.log('first NALU found with overflow:' + overflow);
12219
- lastUnit.data = appendUint8Array(lastUnit.data, array.subarray(0, overflow));
12220
- lastUnit.state = 0;
12579
+ return {
12580
+ numTemporalLayers: max_sub_layers_minus1 + 1,
12581
+ temporalIdNested: temporal_id_nesting_flag
12582
+ };
12583
+ };
12584
+ _proto.readSPS = function readSPS(sps) {
12585
+ var eg = new ExpGolomb(this.ebsp2rbsp(sps));
12586
+ eg.readUByte();
12587
+ eg.readUByte();
12588
+ eg.readBits(4); //video_parameter_set_id
12589
+ var max_sub_layers_minus1 = eg.readBits(3);
12590
+ eg.readBoolean(); // temporal_id_nesting_flag
12591
+
12592
+ // profile_tier_level
12593
+ var general_profile_space = eg.readBits(2);
12594
+ var general_tier_flag = eg.readBoolean();
12595
+ var general_profile_idc = eg.readBits(5);
12596
+ var general_profile_compatibility_flags_1 = eg.readUByte();
12597
+ var general_profile_compatibility_flags_2 = eg.readUByte();
12598
+ var general_profile_compatibility_flags_3 = eg.readUByte();
12599
+ var general_profile_compatibility_flags_4 = eg.readUByte();
12600
+ var general_constraint_indicator_flags_1 = eg.readUByte();
12601
+ var general_constraint_indicator_flags_2 = eg.readUByte();
12602
+ var general_constraint_indicator_flags_3 = eg.readUByte();
12603
+ var general_constraint_indicator_flags_4 = eg.readUByte();
12604
+ var general_constraint_indicator_flags_5 = eg.readUByte();
12605
+ var general_constraint_indicator_flags_6 = eg.readUByte();
12606
+ var general_level_idc = eg.readUByte();
12607
+ var sub_layer_profile_present_flags = [];
12608
+ var sub_layer_level_present_flags = [];
12609
+ for (var i = 0; i < max_sub_layers_minus1; i++) {
12610
+ sub_layer_profile_present_flags.push(eg.readBoolean());
12611
+ sub_layer_level_present_flags.push(eg.readBoolean());
12612
+ }
12613
+ if (max_sub_layers_minus1 > 0) {
12614
+ for (var _i = max_sub_layers_minus1; _i < 8; _i++) {
12615
+ eg.readBits(2);
12616
+ }
12617
+ }
12618
+ for (var _i2 = 0; _i2 < max_sub_layers_minus1; _i2++) {
12619
+ if (sub_layer_profile_present_flags[_i2]) {
12620
+ eg.readUByte(); // sub_layer_profile_space, sub_layer_tier_flag, sub_layer_profile_idc
12621
+ eg.readUByte();
12622
+ eg.readUByte();
12623
+ eg.readUByte();
12624
+ eg.readUByte(); // sub_layer_profile_compatibility_flag
12625
+ eg.readUByte();
12626
+ eg.readUByte();
12627
+ eg.readUByte();
12628
+ eg.readUByte();
12629
+ eg.readUByte();
12630
+ eg.readUByte();
12631
+ }
12632
+ if (sub_layer_level_present_flags[_i2]) {
12633
+ eg.readUByte();
12634
+ }
12635
+ }
12636
+ eg.readUEG(); // seq_parameter_set_id
12637
+ var chroma_format_idc = eg.readUEG();
12638
+ if (chroma_format_idc == 3) {
12639
+ eg.skipBits(1); //separate_colour_plane_flag
12640
+ }
12641
+ var pic_width_in_luma_samples = eg.readUEG();
12642
+ var pic_height_in_luma_samples = eg.readUEG();
12643
+ var conformance_window_flag = eg.readBoolean();
12644
+ var pic_left_offset = 0,
12645
+ pic_right_offset = 0,
12646
+ pic_top_offset = 0,
12647
+ pic_bottom_offset = 0;
12648
+ if (conformance_window_flag) {
12649
+ pic_left_offset += eg.readUEG();
12650
+ pic_right_offset += eg.readUEG();
12651
+ pic_top_offset += eg.readUEG();
12652
+ pic_bottom_offset += eg.readUEG();
12653
+ }
12654
+ var bit_depth_luma_minus8 = eg.readUEG();
12655
+ var bit_depth_chroma_minus8 = eg.readUEG();
12656
+ var log2_max_pic_order_cnt_lsb_minus4 = eg.readUEG();
12657
+ var sub_layer_ordering_info_present_flag = eg.readBoolean();
12658
+ for (var _i3 = sub_layer_ordering_info_present_flag ? 0 : max_sub_layers_minus1; _i3 <= max_sub_layers_minus1; _i3++) {
12659
+ eg.skipUEG(); // max_dec_pic_buffering_minus1[i]
12660
+ eg.skipUEG(); // max_num_reorder_pics[i]
12661
+ eg.skipUEG(); // max_latency_increase_plus1[i]
12662
+ }
12663
+ eg.skipUEG(); // log2_min_luma_coding_block_size_minus3
12664
+ eg.skipUEG(); // log2_diff_max_min_luma_coding_block_size
12665
+ eg.skipUEG(); // log2_min_transform_block_size_minus2
12666
+ eg.skipUEG(); // log2_diff_max_min_transform_block_size
12667
+ eg.skipUEG(); // max_transform_hierarchy_depth_inter
12668
+ eg.skipUEG(); // max_transform_hierarchy_depth_intra
12669
+ var scaling_list_enabled_flag = eg.readBoolean();
12670
+ if (scaling_list_enabled_flag) {
12671
+ var sps_scaling_list_data_present_flag = eg.readBoolean();
12672
+ if (sps_scaling_list_data_present_flag) {
12673
+ for (var sizeId = 0; sizeId < 4; sizeId++) {
12674
+ for (var matrixId = 0; matrixId < (sizeId === 3 ? 2 : 6); matrixId++) {
12675
+ var scaling_list_pred_mode_flag = eg.readBoolean();
12676
+ if (!scaling_list_pred_mode_flag) {
12677
+ eg.readUEG(); // scaling_list_pred_matrix_id_delta
12678
+ } else {
12679
+ var coefNum = Math.min(64, 1 << 4 + (sizeId << 1));
12680
+ if (sizeId > 1) {
12681
+ eg.readEG();
12682
+ }
12683
+ for (var _i4 = 0; _i4 < coefNum; _i4++) {
12684
+ eg.readEG();
12685
+ }
12221
12686
  }
12222
12687
  }
12223
12688
  }
12224
- // check if we can read unit type
12225
- if (i < len) {
12226
- unitType = array[i] & 0x1f;
12227
- // logger.log('find NALU @ offset:' + i + ',type:' + unitType);
12228
- lastUnitStart = i;
12229
- lastUnitType = unitType;
12230
- state = 0;
12231
- } else {
12232
- // not enough byte to read unit type. let's read it on next PES parsing
12233
- state = -1;
12234
- }
12235
- } else {
12236
- state = 0;
12237
12689
  }
12238
12690
  }
12239
- if (lastUnitStart >= 0 && state >= 0) {
12240
- var _unit = {
12241
- data: array.subarray(lastUnitStart, len),
12242
- type: lastUnitType,
12243
- state: state
12244
- };
12245
- units.push(_unit);
12246
- // logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
12247
- }
12248
- // no NALu found
12249
- if (units.length === 0) {
12250
- // append pes.data to previous NAL unit
12251
- var _lastUnit = this.getLastNalUnit(track.samples);
12252
- if (_lastUnit) {
12253
- _lastUnit.data = appendUint8Array(_lastUnit.data, array);
12691
+ eg.readBoolean(); // amp_enabled_flag
12692
+ eg.readBoolean(); // sample_adaptive_offset_enabled_flag
12693
+ var pcm_enabled_flag = eg.readBoolean();
12694
+ if (pcm_enabled_flag) {
12695
+ eg.readUByte();
12696
+ eg.skipUEG();
12697
+ eg.skipUEG();
12698
+ eg.readBoolean();
12699
+ }
12700
+ var num_short_term_ref_pic_sets = eg.readUEG();
12701
+ var num_delta_pocs = 0;
12702
+ for (var _i5 = 0; _i5 < num_short_term_ref_pic_sets; _i5++) {
12703
+ var inter_ref_pic_set_prediction_flag = false;
12704
+ if (_i5 !== 0) {
12705
+ inter_ref_pic_set_prediction_flag = eg.readBoolean();
12706
+ }
12707
+ if (inter_ref_pic_set_prediction_flag) {
12708
+ if (_i5 === num_short_term_ref_pic_sets) {
12709
+ eg.readUEG();
12710
+ }
12711
+ eg.readBoolean();
12712
+ eg.readUEG();
12713
+ var next_num_delta_pocs = 0;
12714
+ for (var j = 0; j <= num_delta_pocs; j++) {
12715
+ var used_by_curr_pic_flag = eg.readBoolean();
12716
+ var use_delta_flag = false;
12717
+ if (!used_by_curr_pic_flag) {
12718
+ use_delta_flag = eg.readBoolean();
12719
+ }
12720
+ if (used_by_curr_pic_flag || use_delta_flag) {
12721
+ next_num_delta_pocs++;
12722
+ }
12723
+ }
12724
+ num_delta_pocs = next_num_delta_pocs;
12725
+ } else {
12726
+ var num_negative_pics = eg.readUEG();
12727
+ var num_positive_pics = eg.readUEG();
12728
+ num_delta_pocs = num_negative_pics + num_positive_pics;
12729
+ for (var _j = 0; _j < num_negative_pics; _j++) {
12730
+ eg.readUEG();
12731
+ eg.readBoolean();
12732
+ }
12733
+ for (var _j2 = 0; _j2 < num_positive_pics; _j2++) {
12734
+ eg.readUEG();
12735
+ eg.readBoolean();
12736
+ }
12737
+ }
12738
+ }
12739
+ var long_term_ref_pics_present_flag = eg.readBoolean();
12740
+ if (long_term_ref_pics_present_flag) {
12741
+ var num_long_term_ref_pics_sps = eg.readUEG();
12742
+ for (var _i6 = 0; _i6 < num_long_term_ref_pics_sps; _i6++) {
12743
+ for (var _j3 = 0; _j3 < log2_max_pic_order_cnt_lsb_minus4 + 4; _j3++) {
12744
+ eg.readBits(1);
12745
+ }
12746
+ eg.readBits(1);
12747
+ }
12748
+ }
12749
+ var min_spatial_segmentation_idc = 0;
12750
+ var sar_width = 1,
12751
+ sar_height = 1;
12752
+ var fps_fixed = true,
12753
+ fps_den = 1,
12754
+ fps_num = 0;
12755
+ eg.readBoolean(); // sps_temporal_mvp_enabled_flag
12756
+ eg.readBoolean(); // strong_intra_smoothing_enabled_flag
12757
+ var default_display_window_flag = false;
12758
+ var vui_parameters_present_flag = eg.readBoolean();
12759
+ if (vui_parameters_present_flag) {
12760
+ var aspect_ratio_info_present_flag = eg.readBoolean();
12761
+ if (aspect_ratio_info_present_flag) {
12762
+ var aspect_ratio_idc = eg.readUByte();
12763
+ var sar_width_table = [1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2];
12764
+ var sar_height_table = [1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1];
12765
+ if (aspect_ratio_idc > 0 && aspect_ratio_idc < 16) {
12766
+ sar_width = sar_width_table[aspect_ratio_idc - 1];
12767
+ sar_height = sar_height_table[aspect_ratio_idc - 1];
12768
+ } else if (aspect_ratio_idc === 255) {
12769
+ sar_width = eg.readBits(16);
12770
+ sar_height = eg.readBits(16);
12771
+ }
12772
+ }
12773
+ var overscan_info_present_flag = eg.readBoolean();
12774
+ if (overscan_info_present_flag) {
12775
+ eg.readBoolean();
12776
+ }
12777
+ var video_signal_type_present_flag = eg.readBoolean();
12778
+ if (video_signal_type_present_flag) {
12779
+ eg.readBits(3);
12780
+ eg.readBoolean();
12781
+ var colour_description_present_flag = eg.readBoolean();
12782
+ if (colour_description_present_flag) {
12783
+ eg.readUByte();
12784
+ eg.readUByte();
12785
+ eg.readUByte();
12786
+ }
12787
+ }
12788
+ var chroma_loc_info_present_flag = eg.readBoolean();
12789
+ if (chroma_loc_info_present_flag) {
12790
+ eg.readUEG();
12791
+ eg.readUEG();
12792
+ }
12793
+ eg.readBoolean(); // neutral_chroma_indication_flag
12794
+ eg.readBoolean(); // field_seq_flag
12795
+ eg.readBoolean(); // frame_field_info_present_flag
12796
+ default_display_window_flag = eg.readBoolean();
12797
+ if (default_display_window_flag) {
12798
+ pic_left_offset += eg.readUEG();
12799
+ pic_right_offset += eg.readUEG();
12800
+ pic_top_offset += eg.readUEG();
12801
+ pic_bottom_offset += eg.readUEG();
12802
+ }
12803
+ var vui_timing_info_present_flag = eg.readBoolean();
12804
+ if (vui_timing_info_present_flag) {
12805
+ fps_den = eg.readBits(32);
12806
+ fps_num = eg.readBits(32);
12807
+ var vui_poc_proportional_to_timing_flag = eg.readBoolean();
12808
+ if (vui_poc_proportional_to_timing_flag) {
12809
+ eg.readUEG();
12810
+ }
12811
+ var vui_hrd_parameters_present_flag = eg.readBoolean();
12812
+ if (vui_hrd_parameters_present_flag) {
12813
+ //const commonInfPresentFlag = true;
12814
+ //if (commonInfPresentFlag) {
12815
+ var nal_hrd_parameters_present_flag = eg.readBoolean();
12816
+ var vcl_hrd_parameters_present_flag = eg.readBoolean();
12817
+ var sub_pic_hrd_params_present_flag = false;
12818
+ if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag) {
12819
+ sub_pic_hrd_params_present_flag = eg.readBoolean();
12820
+ if (sub_pic_hrd_params_present_flag) {
12821
+ eg.readUByte();
12822
+ eg.readBits(5);
12823
+ eg.readBoolean();
12824
+ eg.readBits(5);
12825
+ }
12826
+ eg.readBits(4); // bit_rate_scale
12827
+ eg.readBits(4); // cpb_size_scale
12828
+ if (sub_pic_hrd_params_present_flag) {
12829
+ eg.readBits(4);
12830
+ }
12831
+ eg.readBits(5);
12832
+ eg.readBits(5);
12833
+ eg.readBits(5);
12834
+ }
12835
+ //}
12836
+ for (var _i7 = 0; _i7 <= max_sub_layers_minus1; _i7++) {
12837
+ fps_fixed = eg.readBoolean(); // fixed_pic_rate_general_flag
12838
+ var fixed_pic_rate_within_cvs_flag = fps_fixed || eg.readBoolean();
12839
+ var low_delay_hrd_flag = false;
12840
+ if (fixed_pic_rate_within_cvs_flag) {
12841
+ eg.readEG();
12842
+ } else {
12843
+ low_delay_hrd_flag = eg.readBoolean();
12844
+ }
12845
+ var cpb_cnt = low_delay_hrd_flag ? 1 : eg.readUEG() + 1;
12846
+ if (nal_hrd_parameters_present_flag) {
12847
+ for (var _j4 = 0; _j4 < cpb_cnt; _j4++) {
12848
+ eg.readUEG();
12849
+ eg.readUEG();
12850
+ if (sub_pic_hrd_params_present_flag) {
12851
+ eg.readUEG();
12852
+ eg.readUEG();
12853
+ }
12854
+ eg.skipBits(1);
12855
+ }
12856
+ }
12857
+ if (vcl_hrd_parameters_present_flag) {
12858
+ for (var _j5 = 0; _j5 < cpb_cnt; _j5++) {
12859
+ eg.readUEG();
12860
+ eg.readUEG();
12861
+ if (sub_pic_hrd_params_present_flag) {
12862
+ eg.readUEG();
12863
+ eg.readUEG();
12864
+ }
12865
+ eg.skipBits(1);
12866
+ }
12867
+ }
12868
+ }
12869
+ }
12254
12870
  }
12871
+ var bitstream_restriction_flag = eg.readBoolean();
12872
+ if (bitstream_restriction_flag) {
12873
+ eg.readBoolean(); // tiles_fixed_structure_flag
12874
+ eg.readBoolean(); // motion_vectors_over_pic_boundaries_flag
12875
+ eg.readBoolean(); // restricted_ref_pic_lists_flag
12876
+ min_spatial_segmentation_idc = eg.readUEG();
12877
+ }
12878
+ }
12879
+ var width = pic_width_in_luma_samples,
12880
+ height = pic_height_in_luma_samples;
12881
+ if (conformance_window_flag || default_display_window_flag) {
12882
+ var chroma_scale_w = 1,
12883
+ chroma_scale_h = 1;
12884
+ if (chroma_format_idc === 1) {
12885
+ // YUV 420
12886
+ chroma_scale_w = chroma_scale_h = 2;
12887
+ } else if (chroma_format_idc == 2) {
12888
+ // YUV 422
12889
+ chroma_scale_w = 2;
12890
+ }
12891
+ width = pic_width_in_luma_samples - chroma_scale_w * pic_right_offset - chroma_scale_w * pic_left_offset;
12892
+ height = pic_height_in_luma_samples - chroma_scale_h * pic_bottom_offset - chroma_scale_h * pic_top_offset;
12893
+ }
12894
+ var profile_space_string = general_profile_space ? ['A', 'B', 'C'][general_profile_space] : '';
12895
+ var profile_compatibility_buf = general_profile_compatibility_flags_1 << 24 | general_profile_compatibility_flags_2 << 16 | general_profile_compatibility_flags_3 << 8 | general_profile_compatibility_flags_4;
12896
+ var profile_compatibility_rev = 0;
12897
+ for (var _i8 = 0; _i8 < 32; _i8++) {
12898
+ profile_compatibility_rev = (profile_compatibility_rev | (profile_compatibility_buf >> _i8 & 1) << 31 - _i8) >>> 0; // reverse bit position (and cast as UInt32)
12899
+ }
12900
+ var profile_compatibility_flags_string = profile_compatibility_rev.toString(16);
12901
+ if (general_profile_idc === 1 && profile_compatibility_flags_string === '2') {
12902
+ profile_compatibility_flags_string = '6';
12903
+ }
12904
+ var tier_flag_string = general_tier_flag ? 'H' : 'L';
12905
+ return {
12906
+ codecString: "hvc1." + profile_space_string + general_profile_idc + "." + profile_compatibility_flags_string + "." + tier_flag_string + general_level_idc + ".B0",
12907
+ params: {
12908
+ general_tier_flag: general_tier_flag,
12909
+ general_profile_idc: general_profile_idc,
12910
+ general_profile_space: general_profile_space,
12911
+ general_profile_compatibility_flags: [general_profile_compatibility_flags_1, general_profile_compatibility_flags_2, general_profile_compatibility_flags_3, general_profile_compatibility_flags_4],
12912
+ general_constraint_indicator_flags: [general_constraint_indicator_flags_1, general_constraint_indicator_flags_2, general_constraint_indicator_flags_3, general_constraint_indicator_flags_4, general_constraint_indicator_flags_5, general_constraint_indicator_flags_6],
12913
+ general_level_idc: general_level_idc,
12914
+ bit_depth: bit_depth_luma_minus8 + 8,
12915
+ bit_depth_luma_minus8: bit_depth_luma_minus8,
12916
+ bit_depth_chroma_minus8: bit_depth_chroma_minus8,
12917
+ min_spatial_segmentation_idc: min_spatial_segmentation_idc,
12918
+ chroma_format_idc: chroma_format_idc,
12919
+ frame_rate: {
12920
+ fixed: fps_fixed,
12921
+ fps: fps_num / fps_den
12922
+ }
12923
+ },
12924
+ width: width,
12925
+ height: height,
12926
+ pixelRatio: [sar_width, sar_height]
12927
+ };
12928
+ };
12929
+ _proto.readPPS = function readPPS(pps) {
12930
+ var eg = new ExpGolomb(this.ebsp2rbsp(pps));
12931
+ eg.readUByte();
12932
+ eg.readUByte();
12933
+ eg.skipUEG(); // pic_parameter_set_id
12934
+ eg.skipUEG(); // seq_parameter_set_id
12935
+ eg.skipBits(2); // dependent_slice_segments_enabled_flag, output_flag_present_flag
12936
+ eg.skipBits(3); // num_extra_slice_header_bits
12937
+ eg.skipBits(2); // sign_data_hiding_enabled_flag, cabac_init_present_flag
12938
+ eg.skipUEG();
12939
+ eg.skipUEG();
12940
+ eg.skipEG(); // init_qp_minus26
12941
+ eg.skipBits(2); // constrained_intra_pred_flag, transform_skip_enabled_flag
12942
+ var cu_qp_delta_enabled_flag = eg.readBoolean();
12943
+ if (cu_qp_delta_enabled_flag) {
12944
+ eg.skipUEG();
12945
+ }
12946
+ eg.skipEG(); // cb_qp_offset
12947
+ eg.skipEG(); // cr_qp_offset
12948
+ eg.skipBits(4); // pps_slice_chroma_qp_offsets_present_flag, weighted_pred_flag, weighted_bipred_flag, transquant_bypass_enabled_flag
12949
+ var tiles_enabled_flag = eg.readBoolean();
12950
+ var entropy_coding_sync_enabled_flag = eg.readBoolean();
12951
+ var parallelismType = 1; // slice-based parallel decoding
12952
+ if (entropy_coding_sync_enabled_flag && tiles_enabled_flag) {
12953
+ parallelismType = 0; // mixed-type parallel decoding
12954
+ } else if (entropy_coding_sync_enabled_flag) {
12955
+ parallelismType = 3; // wavefront-based parallel decoding
12956
+ } else if (tiles_enabled_flag) {
12957
+ parallelismType = 2; // tile-based parallel decoding
12255
12958
  }
12256
- track.naluState = state;
12257
- return units;
12959
+ return {
12960
+ parallelismType: parallelismType
12961
+ };
12258
12962
  };
12259
- return AvcVideoParser;
12963
+ _proto.matchSPS = function matchSPS(sps1, sps2) {
12964
+ // compare without headers and VPS related params
12965
+ return String.fromCharCode.apply(null, sps1).substr(3) === String.fromCharCode.apply(null, sps2).substr(3);
12966
+ };
12967
+ return HevcVideoParser;
12260
12968
  }(BaseVideoParser);
12261
12969
 
12262
12970
  /**
@@ -12274,7 +12982,7 @@
12274
12982
  }
12275
12983
  var _proto = SampleAesDecrypter.prototype;
12276
12984
  _proto.decryptBuffer = function decryptBuffer(encryptedData) {
12277
- return this.decrypter.decrypt(encryptedData, this.keyData.key.buffer, this.keyData.iv.buffer);
12985
+ return this.decrypter.decrypt(encryptedData, this.keyData.key.buffer, this.keyData.iv.buffer, DecrypterAesMode.cbc);
12278
12986
  }
12279
12987
 
12280
12988
  // AAC - encrypt all full 16 bytes blocks starting from offset 16
@@ -12393,7 +13101,7 @@
12393
13101
  this.observer = observer;
12394
13102
  this.config = config;
12395
13103
  this.typeSupported = typeSupported;
12396
- this.videoParser = new AvcVideoParser();
13104
+ this.videoParser = null;
12397
13105
  }
12398
13106
  TSDemuxer.probe = function probe(data) {
12399
13107
  var syncOffset = TSDemuxer.syncOffset(data);
@@ -12563,7 +13271,21 @@
12563
13271
  case videoPid:
12564
13272
  if (stt) {
12565
13273
  if (videoData && (pes = parsePES(videoData))) {
12566
- this.videoParser.parseAVCPES(videoTrack, textTrack, pes, false, this._duration);
13274
+ if (this.videoParser === null) {
13275
+ switch (videoTrack.segmentCodec) {
13276
+ case 'avc':
13277
+ this.videoParser = new AvcVideoParser();
13278
+ break;
13279
+ case 'hevc':
13280
+ {
13281
+ this.videoParser = new HevcVideoParser();
13282
+ }
13283
+ break;
13284
+ }
13285
+ }
13286
+ if (this.videoParser !== null) {
13287
+ this.videoParser.parsePES(videoTrack, textTrack, pes, false, this._duration);
13288
+ }
12567
13289
  }
12568
13290
  videoData = {
12569
13291
  data: [],
@@ -12726,8 +13448,22 @@
12726
13448
  // try to parse last PES packets
12727
13449
  var pes;
12728
13450
  if (videoData && (pes = parsePES(videoData))) {
12729
- this.videoParser.parseAVCPES(videoTrack, textTrack, pes, true, this._duration);
12730
- videoTrack.pesData = null;
13451
+ if (this.videoParser === null) {
13452
+ switch (videoTrack.segmentCodec) {
13453
+ case 'avc':
13454
+ this.videoParser = new AvcVideoParser();
13455
+ break;
13456
+ case 'hevc':
13457
+ {
13458
+ this.videoParser = new HevcVideoParser();
13459
+ }
13460
+ break;
13461
+ }
13462
+ }
13463
+ if (this.videoParser !== null) {
13464
+ this.videoParser.parsePES(videoTrack, textTrack, pes, true, this._duration);
13465
+ videoTrack.pesData = null;
13466
+ }
12731
13467
  } else {
12732
13468
  // either avcData null or PES truncated, keep it for next frag parsing
12733
13469
  videoTrack.pesData = videoData;
@@ -13059,7 +13795,14 @@
13059
13795
  logger.warn('Unsupported EC-3 in M2TS found');
13060
13796
  break;
13061
13797
  case 0x24:
13062
- logger.warn('Unsupported HEVC in M2TS found');
13798
+ // ITU-T Rec. H.265 and ISO/IEC 23008-2 (HEVC)
13799
+ {
13800
+ if (result.videoPid === -1) {
13801
+ result.videoPid = pid;
13802
+ result.segmentVideoCodec = 'hevc';
13803
+ logger.log('HEVC in M2TS found');
13804
+ }
13805
+ }
13063
13806
  break;
13064
13807
  }
13065
13808
  // move to the next table entry
@@ -13287,6 +14030,8 @@
13287
14030
  avc1: [],
13288
14031
  // codingname
13289
14032
  avcC: [],
14033
+ hvc1: [],
14034
+ hvcC: [],
13290
14035
  btrt: [],
13291
14036
  dinf: [],
13292
14037
  dref: [],
@@ -13714,8 +14459,10 @@
13714
14459
  return MP4.box(MP4.types.stsd, MP4.STSD, MP4.ac3(track));
13715
14460
  }
13716
14461
  return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track));
13717
- } else {
14462
+ } else if (track.segmentCodec === 'avc') {
13718
14463
  return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));
14464
+ } else {
14465
+ return MP4.box(MP4.types.stsd, MP4.STSD, MP4.hvc1(track));
13719
14466
  }
13720
14467
  };
13721
14468
  MP4.tkhd = function tkhd(track) {
@@ -13853,6 +14600,84 @@
13853
14600
  var result = appendUint8Array(MP4.FTYP, movie);
13854
14601
  return result;
13855
14602
  };
14603
+ MP4.hvc1 = function hvc1(track) {
14604
+ var ps = track.params;
14605
+ var units = [track.vps, track.sps, track.pps];
14606
+ var NALuLengthSize = 4;
14607
+ var config = new Uint8Array([0x01, ps.general_profile_space << 6 | (ps.general_tier_flag ? 32 : 0) | ps.general_profile_idc, ps.general_profile_compatibility_flags[0], ps.general_profile_compatibility_flags[1], ps.general_profile_compatibility_flags[2], ps.general_profile_compatibility_flags[3], ps.general_constraint_indicator_flags[0], ps.general_constraint_indicator_flags[1], ps.general_constraint_indicator_flags[2], ps.general_constraint_indicator_flags[3], ps.general_constraint_indicator_flags[4], ps.general_constraint_indicator_flags[5], ps.general_level_idc, 240 | ps.min_spatial_segmentation_idc >> 8, 255 & ps.min_spatial_segmentation_idc, 252 | ps.parallelismType, 252 | ps.chroma_format_idc, 248 | ps.bit_depth_luma_minus8, 248 | ps.bit_depth_chroma_minus8, 0x00, parseInt(ps.frame_rate.fps), NALuLengthSize - 1 | ps.temporal_id_nested << 2 | ps.num_temporal_layers << 3 | (ps.frame_rate.fixed ? 64 : 0), units.length]);
14608
+
14609
+ // compute hvcC size in bytes
14610
+ var length = config.length;
14611
+ for (var i = 0; i < units.length; i += 1) {
14612
+ length += 3;
14613
+ for (var j = 0; j < units[i].length; j += 1) {
14614
+ length += 2 + units[i][j].length;
14615
+ }
14616
+ }
14617
+ var hvcC = new Uint8Array(length);
14618
+ hvcC.set(config, 0);
14619
+ length = config.length;
14620
+ // append parameter set units: one vps, one or more sps and pps
14621
+ var iMax = units.length - 1;
14622
+ for (var _i = 0; _i < units.length; _i += 1) {
14623
+ hvcC.set(new Uint8Array([32 + _i | (_i === iMax ? 128 : 0), 0x00, units[_i].length]), length);
14624
+ length += 3;
14625
+ for (var _j = 0; _j < units[_i].length; _j += 1) {
14626
+ hvcC.set(new Uint8Array([units[_i][_j].length >> 8, units[_i][_j].length & 255]), length);
14627
+ length += 2;
14628
+ hvcC.set(units[_i][_j], length);
14629
+ length += units[_i][_j].length;
14630
+ }
14631
+ }
14632
+ var hvcc = MP4.box(MP4.types.hvcC, hvcC);
14633
+ var width = track.width;
14634
+ var height = track.height;
14635
+ var hSpacing = track.pixelRatio[0];
14636
+ var vSpacing = track.pixelRatio[1];
14637
+ return MP4.box(MP4.types.hvc1, new Uint8Array([0x00, 0x00, 0x00,
14638
+ // reserved
14639
+ 0x00, 0x00, 0x00,
14640
+ // reserved
14641
+ 0x00, 0x01,
14642
+ // data_reference_index
14643
+ 0x00, 0x00,
14644
+ // pre_defined
14645
+ 0x00, 0x00,
14646
+ // reserved
14647
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
14648
+ // pre_defined
14649
+ width >> 8 & 0xff, width & 0xff,
14650
+ // width
14651
+ height >> 8 & 0xff, height & 0xff,
14652
+ // height
14653
+ 0x00, 0x48, 0x00, 0x00,
14654
+ // horizresolution
14655
+ 0x00, 0x48, 0x00, 0x00,
14656
+ // vertresolution
14657
+ 0x00, 0x00, 0x00, 0x00,
14658
+ // reserved
14659
+ 0x00, 0x01,
14660
+ // frame_count
14661
+ 0x12, 0x64, 0x61, 0x69, 0x6c,
14662
+ // dailymotion/hls.js
14663
+ 0x79, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x68, 0x6c, 0x73, 0x2e, 0x6a, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
14664
+ // compressorname
14665
+ 0x00, 0x18,
14666
+ // depth = 24
14667
+ 0x11, 0x11]),
14668
+ // pre_defined = -1
14669
+ hvcc, MP4.box(MP4.types.btrt, new Uint8Array([0x00, 0x1c, 0x9c, 0x80,
14670
+ // bufferSizeDB
14671
+ 0x00, 0x2d, 0xc6, 0xc0,
14672
+ // maxBitrate
14673
+ 0x00, 0x2d, 0xc6, 0xc0])),
14674
+ // avgBitrate
14675
+ MP4.box(MP4.types.pasp, new Uint8Array([hSpacing >> 24,
14676
+ // hSpacing
14677
+ hSpacing >> 16 & 0xff, hSpacing >> 8 & 0xff, hSpacing & 0xff, vSpacing >> 24,
14678
+ // vSpacing
14679
+ vSpacing >> 16 & 0xff, vSpacing >> 8 & 0xff, vSpacing & 0xff])));
14680
+ };
13856
14681
  return MP4;
13857
14682
  }();
13858
14683
  MP4.types = void 0;
@@ -14254,9 +15079,9 @@
14254
15079
  var foundOverlap = delta < -1;
14255
15080
  if (foundHole || foundOverlap) {
14256
15081
  if (foundHole) {
14257
- logger.warn("AVC: " + toMsFromMpegTsClock(delta, true) + " ms (" + delta + "dts) hole between fragments detected at " + timeOffset.toFixed(3));
15082
+ logger.warn((track.segmentCodec || '').toUpperCase() + ": " + toMsFromMpegTsClock(delta, true) + " ms (" + delta + "dts) hole between fragments detected at " + timeOffset.toFixed(3));
14258
15083
  } else {
14259
- logger.warn("AVC: " + toMsFromMpegTsClock(-delta, true) + " ms (" + delta + "dts) overlapping between fragments detected at " + timeOffset.toFixed(3));
15084
+ logger.warn((track.segmentCodec || '').toUpperCase() + ": " + toMsFromMpegTsClock(-delta, true) + " ms (" + delta + "dts) overlapping between fragments detected at " + timeOffset.toFixed(3));
14260
15085
  }
14261
15086
  if (!foundOverlap || nextAvcDts >= inputSamples[0].pts || chromeVersion) {
14262
15087
  firstDTS = nextAvcDts;
@@ -14265,12 +15090,24 @@
14265
15090
  inputSamples[0].dts = firstDTS;
14266
15091
  inputSamples[0].pts = firstPTS;
14267
15092
  } else {
15093
+ var isPTSOrderRetained = true;
14268
15094
  for (var _i = 0; _i < inputSamples.length; _i++) {
14269
- if (inputSamples[_i].dts > firstPTS) {
15095
+ if (inputSamples[_i].dts > firstPTS && isPTSOrderRetained) {
14270
15096
  break;
14271
15097
  }
15098
+ var prevPTS = inputSamples[_i].pts;
14272
15099
  inputSamples[_i].dts -= delta;
14273
15100
  inputSamples[_i].pts -= delta;
15101
+
15102
+ // check to see if this sample's PTS order has changed
15103
+ // relative to the next one
15104
+ if (_i < inputSamples.length - 1) {
15105
+ var nextSamplePTS = inputSamples[_i + 1].pts;
15106
+ var currentSamplePTS = inputSamples[_i].pts;
15107
+ var currentOrder = nextSamplePTS <= currentSamplePTS;
15108
+ var prevOrder = nextSamplePTS <= prevPTS;
15109
+ isPTSOrderRetained = currentOrder == prevOrder;
15110
+ }
14274
15111
  }
14275
15112
  }
14276
15113
  logger.log("Video: Initial PTS/DTS adjusted: " + toMsFromMpegTsClock(firstPTS, true) + "/" + toMsFromMpegTsClock(firstDTS, true) + ", delta: " + toMsFromMpegTsClock(delta, true) + " ms");
@@ -14418,7 +15255,7 @@
14418
15255
  }
14419
15256
  }
14420
15257
  }
14421
- // next AVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)
15258
+ // next AVC/HEVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)
14422
15259
  mp4SampleDuration = stretchedLastFrame || !mp4SampleDuration ? averageSampleDuration : mp4SampleDuration;
14423
15260
  this.nextAvcDts = nextAvcDts = lastDTS + mp4SampleDuration;
14424
15261
  this.videoSampleDuration = mp4SampleDuration;
@@ -14553,7 +15390,7 @@
14553
15390
  logger.warn("[mp4-remuxer]: Injecting " + missing + " audio frame @ " + (nextPts / inputTimeScale).toFixed(3) + "s due to " + Math.round(1000 * delta / inputTimeScale) + " ms gap.");
14554
15391
  for (var j = 0; j < missing; j++) {
14555
15392
  var newStamp = Math.max(nextPts, 0);
14556
- var fillFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
15393
+ var fillFrame = AAC.getSilentFrame(track.parsedCodec || track.manifestCodec || track.codec, track.channelCount);
14557
15394
  if (!fillFrame) {
14558
15395
  logger.log('[mp4-remuxer]: Unable to get silent frame for given audio codec; duplicating last frame instead.');
14559
15396
  fillFrame = sample.unit.subarray();
@@ -14681,7 +15518,7 @@
14681
15518
  // samples count of this segment's duration
14682
15519
  var nbSamples = Math.ceil((endDTS - startDTS) / frameDuration);
14683
15520
  // silent frame
14684
- var silentFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
15521
+ var silentFrame = AAC.getSilentFrame(track.parsedCodec || track.manifestCodec || track.codec, track.channelCount);
14685
15522
  logger.warn('[mp4-remuxer]: remux empty Audio');
14686
15523
  // Can't remux if we can't generate a silent frame...
14687
15524
  if (!silentFrame) {
@@ -15071,13 +15908,15 @@
15071
15908
  duration = transmuxConfig.duration,
15072
15909
  initSegmentData = transmuxConfig.initSegmentData;
15073
15910
  var keyData = getEncryptionType(uintData, decryptdata);
15074
- if (keyData && keyData.method === 'AES-128') {
15911
+ if (keyData && isFullSegmentEncryption(keyData.method)) {
15075
15912
  var decrypter = this.getDecrypter();
15913
+ var aesMode = getAesModeFromFullSegmentMethod(keyData.method);
15914
+
15076
15915
  // Software decryption is synchronous; webCrypto is not
15077
15916
  if (decrypter.isSync()) {
15078
15917
  // Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
15079
15918
  // data is handled in the flush() call
15080
- var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer);
15919
+ var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer, aesMode);
15081
15920
  // For Low-Latency HLS Parts, decrypt in place, since part parsing is expected on push progress
15082
15921
  var loadingParts = chunkMeta.part > -1;
15083
15922
  if (loadingParts) {
@@ -15089,7 +15928,7 @@
15089
15928
  }
15090
15929
  uintData = new Uint8Array(decryptedData);
15091
15930
  } else {
15092
- this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer).then(function (decryptedData) {
15931
+ this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer, aesMode).then(function (decryptedData) {
15093
15932
  // Calling push here is important; if flush() is called while this is still resolving, this ensures that
15094
15933
  // the decrypted data has been transmuxed
15095
15934
  var result = _this.push(decryptedData, null, chunkMeta);
@@ -15710,7 +16549,7 @@
15710
16549
  observer.on(Events.ERROR, forwardMessage);
15711
16550
 
15712
16551
  // forward logger events to main thread
15713
- var forwardWorkerLogs = function forwardWorkerLogs() {
16552
+ var forwardWorkerLogs = function forwardWorkerLogs(logger) {
15714
16553
  var _loop = function _loop(logFn) {
15715
16554
  var func = function func(message) {
15716
16555
  forwardMessage('workerLog', {
@@ -15731,8 +16570,8 @@
15731
16570
  {
15732
16571
  var config = JSON.parse(data.config);
15733
16572
  self.transmuxer = new Transmuxer(observer, data.typeSupported, config, data.vendor, data.id);
15734
- enableLogs(config.debug, data.id);
15735
- forwardWorkerLogs();
16573
+ var logger = enableLogs(config.debug, data.id);
16574
+ forwardWorkerLogs(logger);
15736
16575
  forwardMessage('init', null);
15737
16576
  break;
15738
16577
  }
@@ -15906,16 +16745,7 @@
15906
16745
  this.observer = new EventEmitter();
15907
16746
  this.observer.on(Events.FRAG_DECRYPTED, forwardMessage);
15908
16747
  this.observer.on(Events.ERROR, forwardMessage);
15909
- var MediaSource = getMediaSource(config.preferManagedMediaSource) || {
15910
- isTypeSupported: function isTypeSupported() {
15911
- return false;
15912
- }
15913
- };
15914
- var m2tsTypeSupported = {
15915
- mpeg: MediaSource.isTypeSupported('audio/mpeg'),
15916
- mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
15917
- ac3: MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"')
15918
- };
16748
+ var m2tsTypeSupported = getM2TSSupportedAudioTypes(config.preferManagedMediaSource);
15919
16749
 
15920
16750
  // navigator.vendor is not always available in Web Worker
15921
16751
  // refer to https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/navigator
@@ -16199,7 +17029,7 @@
16199
17029
  _inheritsLoose(AudioStreamController, _BaseStreamController);
16200
17030
  function AudioStreamController(hls, fragmentTracker, keyLoader) {
16201
17031
  var _this;
16202
- _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[audio-stream-controller]', PlaylistLevelType.AUDIO) || this;
17032
+ _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'audio-stream-controller', PlaylistLevelType.AUDIO) || this;
16203
17033
  _this.videoBuffer = null;
16204
17034
  _this.videoTrackCC = -1;
16205
17035
  _this.waitingVideoCC = -1;
@@ -16211,27 +17041,24 @@
16211
17041
  _this.flushing = false;
16212
17042
  _this.bufferFlushed = false;
16213
17043
  _this.cachedTrackLoadedData = null;
16214
- _this._registerListeners();
17044
+ _this.registerListeners();
16215
17045
  return _this;
16216
17046
  }
16217
17047
  var _proto = AudioStreamController.prototype;
16218
17048
  _proto.onHandlerDestroying = function onHandlerDestroying() {
16219
- this._unregisterListeners();
17049
+ this.unregisterListeners();
16220
17050
  _BaseStreamController.prototype.onHandlerDestroying.call(this);
16221
17051
  this.mainDetails = null;
16222
17052
  this.bufferedTrack = null;
16223
17053
  this.switchingTrack = null;
16224
17054
  };
16225
- _proto._registerListeners = function _registerListeners() {
17055
+ _proto.registerListeners = function registerListeners() {
17056
+ _BaseStreamController.prototype.registerListeners.call(this);
16226
17057
  var hls = this.hls;
16227
- hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
16228
- hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
16229
- hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
16230
17058
  hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
16231
17059
  hls.on(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
16232
17060
  hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
16233
17061
  hls.on(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
16234
- hls.on(Events.ERROR, this.onError, this);
16235
17062
  hls.on(Events.BUFFER_RESET, this.onBufferReset, this);
16236
17063
  hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
16237
17064
  hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
@@ -16239,16 +17066,16 @@
16239
17066
  hls.on(Events.INIT_PTS_FOUND, this.onInitPtsFound, this);
16240
17067
  hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
16241
17068
  };
16242
- _proto._unregisterListeners = function _unregisterListeners() {
17069
+ _proto.unregisterListeners = function unregisterListeners() {
16243
17070
  var hls = this.hls;
16244
- hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
16245
- hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
16246
- hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
17071
+ if (!hls) {
17072
+ return;
17073
+ }
17074
+ _BaseStreamController.prototype.unregisterListeners.call(this);
16247
17075
  hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
16248
17076
  hls.off(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
16249
17077
  hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
16250
17078
  hls.off(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
16251
- hls.off(Events.ERROR, this.onError, this);
16252
17079
  hls.off(Events.BUFFER_RESET, this.onBufferReset, this);
16253
17080
  hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
16254
17081
  hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
@@ -16407,12 +17234,13 @@
16407
17234
  trackId = this.trackId;
16408
17235
  var config = hls.config;
16409
17236
 
16410
- // 1. if video not attached AND
17237
+ // 1. if buffering is suspended
17238
+ // 2. if video not attached AND
16411
17239
  // start fragment already requested OR start frag prefetch not enabled
16412
- // 2. if tracks or track not loaded and selected
17240
+ // 3. if tracks or track not loaded and selected
16413
17241
  // then exit loop
16414
17242
  // => if media not attached but start frag prefetch is enabled and start frag not requested yet, we will not exit loop
16415
- if (!media && (this.startFragRequested || !config.startFragPrefetch) || !(levels != null && levels[trackId])) {
17243
+ if (!this.buffering || !media && (this.startFragRequested || !config.startFragPrefetch) || !(levels != null && levels[trackId])) {
16416
17244
  return;
16417
17245
  }
16418
17246
  var levelInfo = levels[trackId];
@@ -16941,7 +17769,7 @@
16941
17769
  _inheritsLoose(AudioTrackController, _BasePlaylistControll);
16942
17770
  function AudioTrackController(hls) {
16943
17771
  var _this;
16944
- _this = _BasePlaylistControll.call(this, hls, '[audio-track-controller]') || this;
17772
+ _this = _BasePlaylistControll.call(this, hls, 'audio-track-controller') || this;
16945
17773
  _this.tracks = [];
16946
17774
  _this.groupIds = null;
16947
17775
  _this.tracksInGroup = [];
@@ -17270,26 +18098,23 @@
17270
18098
  _inheritsLoose(SubtitleStreamController, _BaseStreamController);
17271
18099
  function SubtitleStreamController(hls, fragmentTracker, keyLoader) {
17272
18100
  var _this;
17273
- _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[subtitle-stream-controller]', PlaylistLevelType.SUBTITLE) || this;
18101
+ _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'subtitle-stream-controller', PlaylistLevelType.SUBTITLE) || this;
17274
18102
  _this.currentTrackId = -1;
17275
18103
  _this.tracksBuffered = [];
17276
18104
  _this.mainDetails = null;
17277
- _this._registerListeners();
18105
+ _this.registerListeners();
17278
18106
  return _this;
17279
18107
  }
17280
18108
  var _proto = SubtitleStreamController.prototype;
17281
18109
  _proto.onHandlerDestroying = function onHandlerDestroying() {
17282
- this._unregisterListeners();
18110
+ this.unregisterListeners();
17283
18111
  _BaseStreamController.prototype.onHandlerDestroying.call(this);
17284
18112
  this.mainDetails = null;
17285
18113
  };
17286
- _proto._registerListeners = function _registerListeners() {
18114
+ _proto.registerListeners = function registerListeners() {
18115
+ _BaseStreamController.prototype.registerListeners.call(this);
17287
18116
  var hls = this.hls;
17288
- hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
17289
- hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
17290
- hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
17291
18117
  hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
17292
- hls.on(Events.ERROR, this.onError, this);
17293
18118
  hls.on(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);
17294
18119
  hls.on(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);
17295
18120
  hls.on(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);
@@ -17297,13 +18122,10 @@
17297
18122
  hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
17298
18123
  hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
17299
18124
  };
17300
- _proto._unregisterListeners = function _unregisterListeners() {
18125
+ _proto.unregisterListeners = function unregisterListeners() {
18126
+ _BaseStreamController.prototype.unregisterListeners.call(this);
17301
18127
  var hls = this.hls;
17302
- hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
17303
- hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
17304
- hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
17305
18128
  hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
17306
- hls.off(Events.ERROR, this.onError, this);
17307
18129
  hls.off(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);
17308
18130
  hls.off(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);
17309
18131
  hls.off(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);
@@ -17526,10 +18348,10 @@
17526
18348
  return;
17527
18349
  }
17528
18350
  // check to see if the payload needs to be decrypted
17529
- if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && decryptData.method === 'AES-128') {
18351
+ if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && isFullSegmentEncryption(decryptData.method)) {
17530
18352
  var startTime = performance.now();
17531
18353
  // decrypt the subtitles
17532
- this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).catch(function (err) {
18354
+ this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer, getAesModeFromFullSegmentMethod(decryptData.method)).catch(function (err) {
17533
18355
  hls.trigger(Events.ERROR, {
17534
18356
  type: ErrorTypes.MEDIA_ERROR,
17535
18357
  details: ErrorDetails.FRAG_DECRYPT_ERROR,
@@ -17661,7 +18483,7 @@
17661
18483
  _inheritsLoose(SubtitleTrackController, _BasePlaylistControll);
17662
18484
  function SubtitleTrackController(hls) {
17663
18485
  var _this;
17664
- _this = _BasePlaylistControll.call(this, hls, '[subtitle-track-controller]') || this;
18486
+ _this = _BasePlaylistControll.call(this, hls, 'subtitle-track-controller') || this;
17665
18487
  _this.media = null;
17666
18488
  _this.tracks = [];
17667
18489
  _this.groupIds = null;
@@ -17670,12 +18492,12 @@
17670
18492
  _this.currentTrack = null;
17671
18493
  _this.selectDefaultTrack = true;
17672
18494
  _this.queuedDefaultTrack = -1;
17673
- _this.asyncPollTrackChange = function () {
17674
- return _this.pollTrackChange(0);
17675
- };
17676
18495
  _this.useTextTrackPolling = false;
17677
18496
  _this.subtitlePollingInterval = -1;
17678
18497
  _this._subtitleDisplay = true;
18498
+ _this.asyncPollTrackChange = function () {
18499
+ return _this.pollTrackChange(0);
18500
+ };
17679
18501
  _this.onTextTracksChanged = function () {
17680
18502
  if (!_this.useTextTrackPolling) {
17681
18503
  self.clearInterval(_this.subtitlePollingInterval);
@@ -17711,6 +18533,7 @@
17711
18533
  this.tracks.length = 0;
17712
18534
  this.tracksInGroup.length = 0;
17713
18535
  this.currentTrack = null;
18536
+ // @ts-ignore
17714
18537
  this.onTextTracksChanged = this.asyncPollTrackChange = null;
17715
18538
  _BasePlaylistControll.prototype.destroy.call(this);
17716
18539
  };
@@ -18184,57 +19007,57 @@
18184
19007
  }();
18185
19008
 
18186
19009
  var VIDEO_CODEC_PROFILE_REPLACE = /(avc[1234]|hvc1|hev1|dvh[1e]|vp09|av01)(?:\.[^.,]+)+/;
18187
- var BufferController = /*#__PURE__*/function () {
19010
+ var BufferController = /*#__PURE__*/function (_Logger) {
19011
+ _inheritsLoose(BufferController, _Logger);
18188
19012
  function BufferController(hls) {
18189
- var _this = this;
19013
+ var _this;
19014
+ _this = _Logger.call(this, 'buffer-controller', hls.logger) || this;
18190
19015
  // The level details used to determine duration, target-duration and live
18191
- this.details = null;
19016
+ _this.details = null;
18192
19017
  // cache the self generated object url to detect hijack of video tag
18193
- this._objectUrl = null;
19018
+ _this._objectUrl = null;
18194
19019
  // A queue of buffer operations which require the SourceBuffer to not be updating upon execution
18195
- this.operationQueue = void 0;
19020
+ _this.operationQueue = void 0;
18196
19021
  // References to event listeners for each SourceBuffer, so that they can be referenced for event removal
18197
- this.listeners = void 0;
18198
- this.hls = void 0;
19022
+ _this.listeners = void 0;
19023
+ _this.hls = void 0;
18199
19024
  // The number of BUFFER_CODEC events received before any sourceBuffers are created
18200
- this.bufferCodecEventsExpected = 0;
19025
+ _this.bufferCodecEventsExpected = 0;
18201
19026
  // The total number of BUFFER_CODEC events received
18202
- this._bufferCodecEventsTotal = 0;
19027
+ _this._bufferCodecEventsTotal = 0;
18203
19028
  // A reference to the attached media element
18204
- this.media = null;
19029
+ _this.media = null;
18205
19030
  // A reference to the active media source
18206
- this.mediaSource = null;
19031
+ _this.mediaSource = null;
18207
19032
  // Last MP3 audio chunk appended
18208
- this.lastMpegAudioChunk = null;
18209
- this.appendSource = void 0;
19033
+ _this.lastMpegAudioChunk = null;
19034
+ _this.appendSource = void 0;
18210
19035
  // counters
18211
- this.appendErrors = {
19036
+ _this.appendErrors = {
18212
19037
  audio: 0,
18213
19038
  video: 0,
18214
19039
  audiovideo: 0
18215
19040
  };
18216
- this.tracks = {};
18217
- this.pendingTracks = {};
18218
- this.sourceBuffer = void 0;
18219
- this.log = void 0;
18220
- this.warn = void 0;
18221
- this.error = void 0;
18222
- this._onEndStreaming = function (event) {
19041
+ _this.tracks = {};
19042
+ _this.pendingTracks = {};
19043
+ _this.sourceBuffer = void 0;
19044
+ _this._onEndStreaming = function (event) {
18223
19045
  if (!_this.hls) {
18224
19046
  return;
18225
19047
  }
18226
19048
  _this.hls.pauseBuffering();
18227
19049
  };
18228
- this._onStartStreaming = function (event) {
19050
+ _this._onStartStreaming = function (event) {
18229
19051
  if (!_this.hls) {
18230
19052
  return;
18231
19053
  }
18232
19054
  _this.hls.resumeBuffering();
18233
19055
  };
18234
19056
  // Keep as arrow functions so that we can directly reference these functions directly as event listeners
18235
- this._onMediaSourceOpen = function () {
18236
- var media = _this.media,
18237
- mediaSource = _this.mediaSource;
19057
+ _this._onMediaSourceOpen = function () {
19058
+ var _assertThisInitialize = _assertThisInitialized(_this),
19059
+ media = _assertThisInitialize.media,
19060
+ mediaSource = _assertThisInitialize.mediaSource;
18238
19061
  _this.log('Media source opened');
18239
19062
  if (media) {
18240
19063
  media.removeEventListener('emptied', _this._onMediaEmptied);
@@ -18250,27 +19073,25 @@
18250
19073
  }
18251
19074
  _this.checkPendingTracks();
18252
19075
  };
18253
- this._onMediaSourceClose = function () {
19076
+ _this._onMediaSourceClose = function () {
18254
19077
  _this.log('Media source closed');
18255
19078
  };
18256
- this._onMediaSourceEnded = function () {
19079
+ _this._onMediaSourceEnded = function () {
18257
19080
  _this.log('Media source ended');
18258
19081
  };
18259
- this._onMediaEmptied = function () {
18260
- var mediaSrc = _this.mediaSrc,
18261
- _objectUrl = _this._objectUrl;
19082
+ _this._onMediaEmptied = function () {
19083
+ var _assertThisInitialize2 = _assertThisInitialized(_this),
19084
+ mediaSrc = _assertThisInitialize2.mediaSrc,
19085
+ _objectUrl = _assertThisInitialize2._objectUrl;
18262
19086
  if (mediaSrc !== _objectUrl) {
18263
- logger.error("Media element src was set while attaching MediaSource (" + _objectUrl + " > " + mediaSrc + ")");
19087
+ _this.error("Media element src was set while attaching MediaSource (" + _objectUrl + " > " + mediaSrc + ")");
18264
19088
  }
18265
19089
  };
18266
- this.hls = hls;
18267
- var logPrefix = '[buffer-controller]';
18268
- this.appendSource = hls.config.preferManagedMediaSource;
18269
- this.log = logger.log.bind(logger, logPrefix);
18270
- this.warn = logger.warn.bind(logger, logPrefix);
18271
- this.error = logger.error.bind(logger, logPrefix);
18272
- this._initSourceBuffer();
18273
- this.registerListeners();
19090
+ _this.hls = hls;
19091
+ _this.appendSource = hls.config.preferManagedMediaSource;
19092
+ _this._initSourceBuffer();
19093
+ _this.registerListeners();
19094
+ return _this;
18274
19095
  }
18275
19096
  var _proto = BufferController.prototype;
18276
19097
  _proto.hasSourceTypes = function hasSourceTypes() {
@@ -18282,6 +19103,12 @@
18282
19103
  this.lastMpegAudioChunk = null;
18283
19104
  // @ts-ignore
18284
19105
  this.hls = null;
19106
+ // @ts-ignore
19107
+ this._onMediaSourceOpen = this._onMediaSourceClose = null;
19108
+ // @ts-ignore
19109
+ this._onMediaSourceEnded = null;
19110
+ // @ts-ignore
19111
+ this._onStartStreaming = this._onEndStreaming = null;
18285
19112
  };
18286
19113
  _proto.registerListeners = function registerListeners() {
18287
19114
  var hls = this.hls;
@@ -18439,6 +19266,7 @@
18439
19266
  _this2.resetBuffer(type);
18440
19267
  });
18441
19268
  this._initSourceBuffer();
19269
+ this.hls.resumeBuffering();
18442
19270
  };
18443
19271
  _proto.resetBuffer = function resetBuffer(type) {
18444
19272
  var sb = this.sourceBuffer[type];
@@ -19142,7 +19970,7 @@
19142
19970
  }
19143
19971
  }]);
19144
19972
  return BufferController;
19145
- }();
19973
+ }(Logger);
19146
19974
  function removeSourceChildren(node) {
19147
19975
  var sourceChildren = node.querySelectorAll('source');
19148
19976
  [].slice.call(sourceChildren).forEach(function (source) {
@@ -21581,14 +22409,12 @@
21581
22409
  this.cea608Parser1 = this.cea608Parser2 = undefined;
21582
22410
  };
21583
22411
  _proto.initCea608Parsers = function initCea608Parsers() {
21584
- if (this.config.enableCEA708Captions && (!this.cea608Parser1 || !this.cea608Parser2)) {
21585
- var channel1 = new OutputFilter(this, 'textTrack1');
21586
- var channel2 = new OutputFilter(this, 'textTrack2');
21587
- var channel3 = new OutputFilter(this, 'textTrack3');
21588
- var channel4 = new OutputFilter(this, 'textTrack4');
21589
- this.cea608Parser1 = new Cea608Parser(1, channel1, channel2);
21590
- this.cea608Parser2 = new Cea608Parser(3, channel3, channel4);
21591
- }
22412
+ var channel1 = new OutputFilter(this, 'textTrack1');
22413
+ var channel2 = new OutputFilter(this, 'textTrack2');
22414
+ var channel3 = new OutputFilter(this, 'textTrack3');
22415
+ var channel4 = new OutputFilter(this, 'textTrack4');
22416
+ this.cea608Parser1 = new Cea608Parser(1, channel1, channel2);
22417
+ this.cea608Parser2 = new Cea608Parser(3, channel3, channel4);
21592
22418
  };
21593
22419
  _proto.addCues = function addCues(trackName, startTime, endTime, screen, cueRanges) {
21594
22420
  // skip cues which overlap more than 50% with previously parsed time ranges
@@ -21823,7 +22649,7 @@
21823
22649
  return t.label;
21824
22650
  });
21825
22651
  if (unusedTextTracks.length) {
21826
- logger.warn("Media element contains unused subtitle tracks: " + unusedTextTracks.join(', ') + ". Replace media element for each source to clear TextTracks and captions menu.");
22652
+ this.hls.logger.warn("Media element contains unused subtitle tracks: " + unusedTextTracks.join(', ') + ". Replace media element for each source to clear TextTracks and captions menu.");
21827
22653
  }
21828
22654
  }
21829
22655
  } else if (this.tracks.length) {
@@ -21869,23 +22695,20 @@
21869
22695
  return level == null ? void 0 : level.attrs['CLOSED-CAPTIONS'];
21870
22696
  };
21871
22697
  _proto.onFragLoading = function onFragLoading(event, data) {
21872
- this.initCea608Parsers();
21873
- var cea608Parser1 = this.cea608Parser1,
21874
- cea608Parser2 = this.cea608Parser2,
21875
- lastCc = this.lastCc,
21876
- lastSn = this.lastSn,
21877
- lastPartIndex = this.lastPartIndex;
21878
- if (!this.enabled || !cea608Parser1 || !cea608Parser2) {
21879
- return;
21880
- }
21881
22698
  // if this frag isn't contiguous, clear the parser so cues with bad start/end times aren't added to the textTrack
21882
- if (data.frag.type === PlaylistLevelType.MAIN) {
22699
+ if (this.enabled && data.frag.type === PlaylistLevelType.MAIN) {
21883
22700
  var _data$part$index, _data$part;
22701
+ var cea608Parser1 = this.cea608Parser1,
22702
+ cea608Parser2 = this.cea608Parser2,
22703
+ lastSn = this.lastSn;
22704
+ if (!cea608Parser1 || !cea608Parser2) {
22705
+ return;
22706
+ }
21884
22707
  var _data$frag = data.frag,
21885
22708
  cc = _data$frag.cc,
21886
22709
  sn = _data$frag.sn;
21887
- var partIndex = (_data$part$index = data == null ? void 0 : (_data$part = data.part) == null ? void 0 : _data$part.index) != null ? _data$part$index : -1;
21888
- if (!(sn === lastSn + 1 || sn === lastSn && partIndex === lastPartIndex + 1 || cc === lastCc)) {
22710
+ var partIndex = (_data$part$index = (_data$part = data.part) == null ? void 0 : _data$part.index) != null ? _data$part$index : -1;
22711
+ if (!(sn === lastSn + 1 || sn === lastSn && partIndex === this.lastPartIndex + 1 || cc === this.lastCc)) {
21889
22712
  cea608Parser1.reset();
21890
22713
  cea608Parser2.reset();
21891
22714
  }
@@ -21941,7 +22764,7 @@
21941
22764
  frag: frag
21942
22765
  });
21943
22766
  }, function (error) {
21944
- logger.log("Failed to parse IMSC1: " + error);
22767
+ hls.logger.log("Failed to parse IMSC1: " + error);
21945
22768
  hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {
21946
22769
  success: false,
21947
22770
  frag: frag,
@@ -21979,7 +22802,7 @@
21979
22802
  _this5._fallbackToIMSC1(frag, payload);
21980
22803
  }
21981
22804
  // Something went wrong while parsing. Trigger event with success false.
21982
- logger.log("Failed to parse VTT cue: " + error);
22805
+ hls.logger.log("Failed to parse VTT cue: " + error);
21983
22806
  if (missingInitPTS && maxAvCC > frag.cc) {
21984
22807
  return;
21985
22808
  }
@@ -22041,10 +22864,7 @@
22041
22864
  this.captionsTracks = {};
22042
22865
  };
22043
22866
  _proto.onFragParsingUserdata = function onFragParsingUserdata(event, data) {
22044
- this.initCea608Parsers();
22045
- var cea608Parser1 = this.cea608Parser1,
22046
- cea608Parser2 = this.cea608Parser2;
22047
- if (!this.enabled || !cea608Parser1 || !cea608Parser2) {
22867
+ if (!this.enabled || !this.config.enableCEA708Captions) {
22048
22868
  return;
22049
22869
  }
22050
22870
  var frag = data.frag,
@@ -22057,9 +22877,12 @@
22057
22877
  for (var i = 0; i < samples.length; i++) {
22058
22878
  var ccBytes = samples[i].bytes;
22059
22879
  if (ccBytes) {
22880
+ if (!this.cea608Parser1) {
22881
+ this.initCea608Parsers();
22882
+ }
22060
22883
  var ccdatas = this.extractCea608Data(ccBytes);
22061
- cea608Parser1.addData(samples[i].pts, ccdatas[0]);
22062
- cea608Parser2.addData(samples[i].pts, ccdatas[1]);
22884
+ this.cea608Parser1.addData(samples[i].pts, ccdatas[0]);
22885
+ this.cea608Parser2.addData(samples[i].pts, ccdatas[1]);
22063
22886
  }
22064
22887
  }
22065
22888
  };
@@ -22251,7 +23074,7 @@
22251
23074
  var hls = this.hls;
22252
23075
  var maxLevel = this.getMaxLevel(levels.length - 1);
22253
23076
  if (maxLevel !== this.autoLevelCapping) {
22254
- logger.log("Setting autoLevelCapping to " + maxLevel + ": " + levels[maxLevel].height + "p@" + levels[maxLevel].bitrate + " for media " + this.mediaWidth + "x" + this.mediaHeight);
23077
+ hls.logger.log("Setting autoLevelCapping to " + maxLevel + ": " + levels[maxLevel].height + "p@" + levels[maxLevel].bitrate + " for media " + this.mediaWidth + "x" + this.mediaHeight);
22255
23078
  }
22256
23079
  hls.autoLevelCapping = maxLevel;
22257
23080
  if (hls.autoLevelCapping > this.autoLevelCapping && this.streamController) {
@@ -22441,10 +23264,10 @@
22441
23264
  totalDroppedFrames: droppedFrames
22442
23265
  });
22443
23266
  if (droppedFPS > 0) {
22444
- // logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));
23267
+ // hls.logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));
22445
23268
  if (currentDropped > hls.config.fpsDroppedMonitoringThreshold * currentDecoded) {
22446
23269
  var currentLevel = hls.currentLevel;
22447
- logger.warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel);
23270
+ hls.logger.warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel);
22448
23271
  if (currentLevel > 0 && (hls.autoLevelCapping === -1 || hls.autoLevelCapping >= currentLevel)) {
22449
23272
  currentLevel = currentLevel - 1;
22450
23273
  hls.trigger(Events.FPS_DROP_LEVEL_CAPPING, {
@@ -22477,7 +23300,6 @@
22477
23300
  return FPSController;
22478
23301
  }();
22479
23302
 
22480
- var LOGGER_PREFIX = '[eme]';
22481
23303
  /**
22482
23304
  * Controller to deal with encrypted media extensions (EME)
22483
23305
  * @see https://developer.mozilla.org/en-US/docs/Web/API/Encrypted_Media_Extensions_API
@@ -22485,26 +23307,122 @@
22485
23307
  * @class
22486
23308
  * @constructor
22487
23309
  */
22488
- var EMEController = /*#__PURE__*/function () {
23310
+ var EMEController = /*#__PURE__*/function (_Logger) {
23311
+ _inheritsLoose(EMEController, _Logger);
22489
23312
  function EMEController(hls) {
22490
- this.hls = void 0;
22491
- this.config = void 0;
22492
- this.media = null;
22493
- this.keyFormatPromise = null;
22494
- this.keySystemAccessPromises = {};
22495
- this._requestLicenseFailureCount = 0;
22496
- this.mediaKeySessions = [];
22497
- this.keyIdToKeySessionPromise = {};
22498
- this.setMediaKeysQueue = EMEController.CDMCleanupPromise ? [EMEController.CDMCleanupPromise] : [];
22499
- this.onMediaEncrypted = this._onMediaEncrypted.bind(this);
22500
- this.onWaitingForKey = this._onWaitingForKey.bind(this);
22501
- this.debug = logger.debug.bind(logger, LOGGER_PREFIX);
22502
- this.log = logger.log.bind(logger, LOGGER_PREFIX);
22503
- this.warn = logger.warn.bind(logger, LOGGER_PREFIX);
22504
- this.error = logger.error.bind(logger, LOGGER_PREFIX);
22505
- this.hls = hls;
22506
- this.config = hls.config;
22507
- this.registerListeners();
23313
+ var _this;
23314
+ _this = _Logger.call(this, 'eme', hls.logger) || this;
23315
+ _this.hls = void 0;
23316
+ _this.config = void 0;
23317
+ _this.media = null;
23318
+ _this.keyFormatPromise = null;
23319
+ _this.keySystemAccessPromises = {};
23320
+ _this._requestLicenseFailureCount = 0;
23321
+ _this.mediaKeySessions = [];
23322
+ _this.keyIdToKeySessionPromise = {};
23323
+ _this.setMediaKeysQueue = EMEController.CDMCleanupPromise ? [EMEController.CDMCleanupPromise] : [];
23324
+ _this.onMediaEncrypted = function (event) {
23325
+ var initDataType = event.initDataType,
23326
+ initData = event.initData;
23327
+ _this.debug("\"" + event.type + "\" event: init data type: \"" + initDataType + "\"");
23328
+
23329
+ // Ignore event when initData is null
23330
+ if (initData === null) {
23331
+ return;
23332
+ }
23333
+ var keyId;
23334
+ var keySystemDomain;
23335
+ if (initDataType === 'sinf' && _this.config.drmSystems[KeySystems.FAIRPLAY]) {
23336
+ // Match sinf keyId to playlist skd://keyId=
23337
+ var json = bin2str(new Uint8Array(initData));
23338
+ try {
23339
+ var sinf = base64Decode(JSON.parse(json).sinf);
23340
+ var tenc = parseSinf(new Uint8Array(sinf));
23341
+ if (!tenc) {
23342
+ return;
23343
+ }
23344
+ keyId = tenc.subarray(8, 24);
23345
+ keySystemDomain = KeySystems.FAIRPLAY;
23346
+ } catch (error) {
23347
+ _this.warn('Failed to parse sinf "encrypted" event message initData');
23348
+ return;
23349
+ }
23350
+ } else {
23351
+ // Support clear-lead key-session creation (otherwise depend on playlist keys)
23352
+ var psshInfo = parsePssh(initData);
23353
+ if (psshInfo === null) {
23354
+ return;
23355
+ }
23356
+ if (psshInfo.version === 0 && psshInfo.systemId === KeySystemIds.WIDEVINE && psshInfo.data) {
23357
+ keyId = psshInfo.data.subarray(8, 24);
23358
+ }
23359
+ keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
23360
+ }
23361
+ if (!keySystemDomain || !keyId) {
23362
+ return;
23363
+ }
23364
+ var keyIdHex = Hex.hexDump(keyId);
23365
+ var _assertThisInitialize = _assertThisInitialized(_this),
23366
+ keyIdToKeySessionPromise = _assertThisInitialize.keyIdToKeySessionPromise,
23367
+ mediaKeySessions = _assertThisInitialize.mediaKeySessions;
23368
+ var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
23369
+ var _loop = function _loop() {
23370
+ // Match playlist key
23371
+ var keyContext = mediaKeySessions[i];
23372
+ var decryptdata = keyContext.decryptdata;
23373
+ if (decryptdata.pssh || !decryptdata.keyId) {
23374
+ return 0; // continue
23375
+ }
23376
+ var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
23377
+ if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
23378
+ keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
23379
+ delete keyIdToKeySessionPromise[oldKeyIdHex];
23380
+ decryptdata.pssh = new Uint8Array(initData);
23381
+ decryptdata.keyId = keyId;
23382
+ keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
23383
+ return _this.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
23384
+ });
23385
+ return 1; // break
23386
+ }
23387
+ },
23388
+ _ret;
23389
+ for (var i = 0; i < mediaKeySessions.length; i++) {
23390
+ _ret = _loop();
23391
+ if (_ret === 0) continue;
23392
+ if (_ret === 1) break;
23393
+ }
23394
+ if (!keySessionContextPromise) {
23395
+ // Clear-lead key (not encountered in playlist)
23396
+ keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = _this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref) {
23397
+ var _keySystemToKeySystem;
23398
+ var keySystem = _ref.keySystem,
23399
+ mediaKeys = _ref.mediaKeys;
23400
+ _this.throwIfDestroyed();
23401
+ var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
23402
+ decryptdata.pssh = new Uint8Array(initData);
23403
+ decryptdata.keyId = keyId;
23404
+ return _this.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
23405
+ _this.throwIfDestroyed();
23406
+ var keySessionContext = _this.createMediaKeySessionContext({
23407
+ decryptdata: decryptdata,
23408
+ keySystem: keySystem,
23409
+ mediaKeys: mediaKeys
23410
+ });
23411
+ return _this.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
23412
+ });
23413
+ });
23414
+ }
23415
+ keySessionContextPromise.catch(function (error) {
23416
+ return _this.handleError(error);
23417
+ });
23418
+ };
23419
+ _this.onWaitingForKey = function (event) {
23420
+ _this.log("\"" + event.type + "\" event");
23421
+ };
23422
+ _this.hls = hls;
23423
+ _this.config = hls.config;
23424
+ _this.registerListeners();
23425
+ return _this;
22508
23426
  }
22509
23427
  var _proto = EMEController.prototype;
22510
23428
  _proto.destroy = function destroy() {
@@ -22516,9 +23434,9 @@
22516
23434
  config.licenseXhrSetup = config.licenseResponseCallback = undefined;
22517
23435
  config.drmSystems = config.drmSystemOptions = {};
22518
23436
  // @ts-ignore
22519
- this.hls = this.onMediaEncrypted = this.onWaitingForKey = this.keyIdToKeySessionPromise = null;
23437
+ this.hls = this.config = this.keyIdToKeySessionPromise = null;
22520
23438
  // @ts-ignore
22521
- this.config = null;
23439
+ this.onMediaEncrypted = this.onWaitingForKey = null;
22522
23440
  };
22523
23441
  _proto.registerListeners = function registerListeners() {
22524
23442
  this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
@@ -22557,7 +23475,7 @@
22557
23475
  }
22558
23476
  };
22559
23477
  _proto.attemptKeySystemAccess = function attemptKeySystemAccess(keySystemsToAttempt) {
22560
- var _this = this;
23478
+ var _this2 = this;
22561
23479
  var levels = this.hls.levels;
22562
23480
  var uniqueCodec = function uniqueCodec(value, i, a) {
22563
23481
  return !!value && a.indexOf(value) === i;
@@ -22574,7 +23492,7 @@
22574
23492
  return new Promise(function (resolve, reject) {
22575
23493
  var attempt = function attempt(keySystems) {
22576
23494
  var keySystem = keySystems.shift();
22577
- _this.getMediaKeysPromise(keySystem, audioCodecs, videoCodecs).then(function (mediaKeys) {
23495
+ _this2.getMediaKeysPromise(keySystem, audioCodecs, videoCodecs).then(function (mediaKeys) {
22578
23496
  return resolve({
22579
23497
  keySystem: keySystem,
22580
23498
  mediaKeys: mediaKeys
@@ -22609,7 +23527,7 @@
22609
23527
  return requestMediaKeySystemAccessFunc(keySystem, supportedConfigurations);
22610
23528
  };
22611
23529
  _proto.getMediaKeysPromise = function getMediaKeysPromise(keySystem, audioCodecs, videoCodecs) {
22612
- var _this2 = this;
23530
+ var _this3 = this;
22613
23531
  // This can throw, but is caught in event handler callpath
22614
23532
  var mediaKeySystemConfigs = getSupportedMediaKeySystemConfigurations(keySystem, audioCodecs, videoCodecs, this.config.drmSystemOptions);
22615
23533
  var keySystemAccessPromises = this.keySystemAccessPromises[keySystem];
@@ -22621,23 +23539,23 @@
22621
23539
  keySystemAccess: keySystemAccess
22622
23540
  };
22623
23541
  keySystemAccess.catch(function (error) {
22624
- _this2.log("Failed to obtain access to key-system \"" + keySystem + "\": " + error);
23542
+ _this3.log("Failed to obtain access to key-system \"" + keySystem + "\": " + error);
22625
23543
  });
22626
23544
  return keySystemAccess.then(function (mediaKeySystemAccess) {
22627
- _this2.log("Access for key-system \"" + mediaKeySystemAccess.keySystem + "\" obtained");
22628
- var certificateRequest = _this2.fetchServerCertificate(keySystem);
22629
- _this2.log("Create media-keys for \"" + keySystem + "\"");
23545
+ _this3.log("Access for key-system \"" + mediaKeySystemAccess.keySystem + "\" obtained");
23546
+ var certificateRequest = _this3.fetchServerCertificate(keySystem);
23547
+ _this3.log("Create media-keys for \"" + keySystem + "\"");
22630
23548
  _keySystemAccessPromises.mediaKeys = mediaKeySystemAccess.createMediaKeys().then(function (mediaKeys) {
22631
- _this2.log("Media-keys created for \"" + keySystem + "\"");
23549
+ _this3.log("Media-keys created for \"" + keySystem + "\"");
22632
23550
  return certificateRequest.then(function (certificate) {
22633
23551
  if (certificate) {
22634
- return _this2.setMediaKeysServerCertificate(mediaKeys, keySystem, certificate);
23552
+ return _this3.setMediaKeysServerCertificate(mediaKeys, keySystem, certificate);
22635
23553
  }
22636
23554
  return mediaKeys;
22637
23555
  });
22638
23556
  });
22639
23557
  _keySystemAccessPromises.mediaKeys.catch(function (error) {
22640
- _this2.error("Failed to create media-keys for \"" + keySystem + "\"}: " + error);
23558
+ _this3.error("Failed to create media-keys for \"" + keySystem + "\"}: " + error);
22641
23559
  });
22642
23560
  return _keySystemAccessPromises.mediaKeys;
22643
23561
  });
@@ -22646,10 +23564,10 @@
22646
23564
  return keySystemAccessPromises.mediaKeys;
22647
23565
  });
22648
23566
  };
22649
- _proto.createMediaKeySessionContext = function createMediaKeySessionContext(_ref) {
22650
- var decryptdata = _ref.decryptdata,
22651
- keySystem = _ref.keySystem,
22652
- mediaKeys = _ref.mediaKeys;
23567
+ _proto.createMediaKeySessionContext = function createMediaKeySessionContext(_ref2) {
23568
+ var decryptdata = _ref2.decryptdata,
23569
+ keySystem = _ref2.keySystem,
23570
+ mediaKeys = _ref2.mediaKeys;
22653
23571
  this.log("Creating key-system session \"" + keySystem + "\" keyId: " + Hex.hexDump(decryptdata.keyId || []));
22654
23572
  var mediaKeysSession = mediaKeys.createSession();
22655
23573
  var mediaKeySessionContext = {
@@ -22698,14 +23616,14 @@
22698
23616
  return this.keyFormatPromise;
22699
23617
  };
22700
23618
  _proto.getKeyFormatPromise = function getKeyFormatPromise(keyFormats) {
22701
- var _this3 = this;
23619
+ var _this4 = this;
22702
23620
  return new Promise(function (resolve, reject) {
22703
- var keySystemsInConfig = getKeySystemsForConfig(_this3.config);
23621
+ var keySystemsInConfig = getKeySystemsForConfig(_this4.config);
22704
23622
  var keySystemsToAttempt = keyFormats.map(keySystemFormatToKeySystemDomain).filter(function (value) {
22705
23623
  return !!value && keySystemsInConfig.indexOf(value) !== -1;
22706
23624
  });
22707
- return _this3.getKeySystemSelectionPromise(keySystemsToAttempt).then(function (_ref2) {
22708
- var keySystem = _ref2.keySystem;
23625
+ return _this4.getKeySystemSelectionPromise(keySystemsToAttempt).then(function (_ref3) {
23626
+ var keySystem = _ref3.keySystem;
22709
23627
  var keySystemFormat = keySystemDomainToKeySystemFormat(keySystem);
22710
23628
  if (keySystemFormat) {
22711
23629
  resolve(keySystemFormat);
@@ -22716,31 +23634,31 @@
22716
23634
  });
22717
23635
  };
22718
23636
  _proto.loadKey = function loadKey(data) {
22719
- var _this4 = this;
23637
+ var _this5 = this;
22720
23638
  var decryptdata = data.keyInfo.decryptdata;
22721
23639
  var keyId = this.getKeyIdString(decryptdata);
22722
23640
  var keyDetails = "(keyId: " + keyId + " format: \"" + decryptdata.keyFormat + "\" method: " + decryptdata.method + " uri: " + decryptdata.uri + ")";
22723
23641
  this.log("Starting session for key " + keyDetails);
22724
23642
  var keySessionContextPromise = this.keyIdToKeySessionPromise[keyId];
22725
23643
  if (!keySessionContextPromise) {
22726
- keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (_ref3) {
22727
- var keySystem = _ref3.keySystem,
22728
- mediaKeys = _ref3.mediaKeys;
22729
- _this4.throwIfDestroyed();
22730
- _this4.log("Handle encrypted media sn: " + data.frag.sn + " " + data.frag.type + ": " + data.frag.level + " using key " + keyDetails);
22731
- return _this4.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
22732
- _this4.throwIfDestroyed();
22733
- var keySessionContext = _this4.createMediaKeySessionContext({
23644
+ keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (_ref4) {
23645
+ var keySystem = _ref4.keySystem,
23646
+ mediaKeys = _ref4.mediaKeys;
23647
+ _this5.throwIfDestroyed();
23648
+ _this5.log("Handle encrypted media sn: " + data.frag.sn + " " + data.frag.type + ": " + data.frag.level + " using key " + keyDetails);
23649
+ return _this5.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
23650
+ _this5.throwIfDestroyed();
23651
+ var keySessionContext = _this5.createMediaKeySessionContext({
22734
23652
  keySystem: keySystem,
22735
23653
  mediaKeys: mediaKeys,
22736
23654
  decryptdata: decryptdata
22737
23655
  });
22738
23656
  var scheme = 'cenc';
22739
- return _this4.generateRequestWithPreferredKeySession(keySessionContext, scheme, decryptdata.pssh, 'playlist-key');
23657
+ return _this5.generateRequestWithPreferredKeySession(keySessionContext, scheme, decryptdata.pssh, 'playlist-key');
22740
23658
  });
22741
23659
  });
22742
23660
  keySessionContextPromise.catch(function (error) {
22743
- return _this4.handleError(error);
23661
+ return _this5.handleError(error);
22744
23662
  });
22745
23663
  }
22746
23664
  return keySessionContextPromise;
@@ -22766,128 +23684,30 @@
22766
23684
  });
22767
23685
  }
22768
23686
  };
22769
- _proto.getKeySystemForKeyPromise = function getKeySystemForKeyPromise(decryptdata) {
22770
- var keyId = this.getKeyIdString(decryptdata);
22771
- var mediaKeySessionContext = this.keyIdToKeySessionPromise[keyId];
22772
- if (!mediaKeySessionContext) {
22773
- var keySystem = keySystemFormatToKeySystemDomain(decryptdata.keyFormat);
22774
- var keySystemsToAttempt = keySystem ? [keySystem] : getKeySystemsForConfig(this.config);
22775
- return this.attemptKeySystemAccess(keySystemsToAttempt);
22776
- }
22777
- return mediaKeySessionContext;
22778
- };
22779
- _proto.getKeySystemSelectionPromise = function getKeySystemSelectionPromise(keySystemsToAttempt) {
22780
- if (!keySystemsToAttempt.length) {
22781
- keySystemsToAttempt = getKeySystemsForConfig(this.config);
22782
- }
22783
- if (keySystemsToAttempt.length === 0) {
22784
- throw new EMEKeyError({
22785
- type: ErrorTypes.KEY_SYSTEM_ERROR,
22786
- details: ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE,
22787
- fatal: true
22788
- }, "Missing key-system license configuration options " + JSON.stringify({
22789
- drmSystems: this.config.drmSystems
22790
- }));
22791
- }
22792
- return this.attemptKeySystemAccess(keySystemsToAttempt);
22793
- };
22794
- _proto._onMediaEncrypted = function _onMediaEncrypted(event) {
22795
- var _this5 = this;
22796
- var initDataType = event.initDataType,
22797
- initData = event.initData;
22798
- this.debug("\"" + event.type + "\" event: init data type: \"" + initDataType + "\"");
22799
-
22800
- // Ignore event when initData is null
22801
- if (initData === null) {
22802
- return;
22803
- }
22804
- var keyId;
22805
- var keySystemDomain;
22806
- if (initDataType === 'sinf' && this.config.drmSystems[KeySystems.FAIRPLAY]) {
22807
- // Match sinf keyId to playlist skd://keyId=
22808
- var json = bin2str(new Uint8Array(initData));
22809
- try {
22810
- var sinf = base64Decode(JSON.parse(json).sinf);
22811
- var tenc = parseSinf(new Uint8Array(sinf));
22812
- if (!tenc) {
22813
- return;
22814
- }
22815
- keyId = tenc.subarray(8, 24);
22816
- keySystemDomain = KeySystems.FAIRPLAY;
22817
- } catch (error) {
22818
- this.warn('Failed to parse sinf "encrypted" event message initData');
22819
- return;
22820
- }
22821
- } else {
22822
- // Support clear-lead key-session creation (otherwise depend on playlist keys)
22823
- var psshInfo = parsePssh(initData);
22824
- if (psshInfo === null) {
22825
- return;
22826
- }
22827
- if (psshInfo.version === 0 && psshInfo.systemId === KeySystemIds.WIDEVINE && psshInfo.data) {
22828
- keyId = psshInfo.data.subarray(8, 24);
22829
- }
22830
- keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
22831
- }
22832
- if (!keySystemDomain || !keyId) {
22833
- return;
22834
- }
22835
- var keyIdHex = Hex.hexDump(keyId);
22836
- var keyIdToKeySessionPromise = this.keyIdToKeySessionPromise,
22837
- mediaKeySessions = this.mediaKeySessions;
22838
- var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
22839
- var _loop = function _loop() {
22840
- // Match playlist key
22841
- var keyContext = mediaKeySessions[i];
22842
- var decryptdata = keyContext.decryptdata;
22843
- if (decryptdata.pssh || !decryptdata.keyId) {
22844
- return 0; // continue
22845
- }
22846
- var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
22847
- if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
22848
- keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
22849
- delete keyIdToKeySessionPromise[oldKeyIdHex];
22850
- decryptdata.pssh = new Uint8Array(initData);
22851
- decryptdata.keyId = keyId;
22852
- keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
22853
- return _this5.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
22854
- });
22855
- return 1; // break
22856
- }
22857
- },
22858
- _ret;
22859
- for (var i = 0; i < mediaKeySessions.length; i++) {
22860
- _ret = _loop();
22861
- if (_ret === 0) continue;
22862
- if (_ret === 1) break;
22863
- }
22864
- if (!keySessionContextPromise) {
22865
- // Clear-lead key (not encountered in playlist)
22866
- keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref4) {
22867
- var _keySystemToKeySystem;
22868
- var keySystem = _ref4.keySystem,
22869
- mediaKeys = _ref4.mediaKeys;
22870
- _this5.throwIfDestroyed();
22871
- var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
22872
- decryptdata.pssh = new Uint8Array(initData);
22873
- decryptdata.keyId = keyId;
22874
- return _this5.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
22875
- _this5.throwIfDestroyed();
22876
- var keySessionContext = _this5.createMediaKeySessionContext({
22877
- decryptdata: decryptdata,
22878
- keySystem: keySystem,
22879
- mediaKeys: mediaKeys
22880
- });
22881
- return _this5.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
22882
- });
22883
- });
23687
+ _proto.getKeySystemForKeyPromise = function getKeySystemForKeyPromise(decryptdata) {
23688
+ var keyId = this.getKeyIdString(decryptdata);
23689
+ var mediaKeySessionContext = this.keyIdToKeySessionPromise[keyId];
23690
+ if (!mediaKeySessionContext) {
23691
+ var keySystem = keySystemFormatToKeySystemDomain(decryptdata.keyFormat);
23692
+ var keySystemsToAttempt = keySystem ? [keySystem] : getKeySystemsForConfig(this.config);
23693
+ return this.attemptKeySystemAccess(keySystemsToAttempt);
22884
23694
  }
22885
- keySessionContextPromise.catch(function (error) {
22886
- return _this5.handleError(error);
22887
- });
23695
+ return mediaKeySessionContext;
22888
23696
  };
22889
- _proto._onWaitingForKey = function _onWaitingForKey(event) {
22890
- this.log("\"" + event.type + "\" event");
23697
+ _proto.getKeySystemSelectionPromise = function getKeySystemSelectionPromise(keySystemsToAttempt) {
23698
+ if (!keySystemsToAttempt.length) {
23699
+ keySystemsToAttempt = getKeySystemsForConfig(this.config);
23700
+ }
23701
+ if (keySystemsToAttempt.length === 0) {
23702
+ throw new EMEKeyError({
23703
+ type: ErrorTypes.KEY_SYSTEM_ERROR,
23704
+ details: ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE,
23705
+ fatal: true
23706
+ }, "Missing key-system license configuration options " + JSON.stringify({
23707
+ drmSystems: this.config.drmSystems
23708
+ }));
23709
+ }
23710
+ return this.attemptKeySystemAccess(keySystemsToAttempt);
22891
23711
  };
22892
23712
  _proto.attemptSetMediaKeys = function attemptSetMediaKeys(keySystem, mediaKeys) {
22893
23713
  var _this6 = this;
@@ -23344,7 +24164,7 @@
23344
24164
  }
23345
24165
  };
23346
24166
  return EMEController;
23347
- }();
24167
+ }(Logger);
23348
24168
  EMEController.CDMCleanupPromise = void 0;
23349
24169
  var EMEKeyError = /*#__PURE__*/function (_Error) {
23350
24170
  _inheritsLoose(EMEKeyError, _Error);
@@ -23492,18 +24312,6 @@
23492
24312
  this.params = params;
23493
24313
  };
23494
24314
 
23495
- /**
23496
- * A class to represent structured field tokens when `Symbol` is not available.
23497
- *
23498
- * @group Structured Field
23499
- *
23500
- * @beta
23501
- */
23502
- var SfToken = function SfToken(description) {
23503
- this.description = void 0;
23504
- this.description = description;
23505
- };
23506
-
23507
24315
  var DICT = 'Dict';
23508
24316
 
23509
24317
  function format(value) {
@@ -23527,29 +24335,25 @@
23527
24335
  });
23528
24336
  }
23529
24337
 
23530
- var BARE_ITEM = 'Bare Item';
23531
-
23532
- var BOOLEAN = 'Boolean';
23533
-
23534
- var BYTES = 'Byte Sequence';
23535
-
23536
- var DECIMAL = 'Decimal';
23537
-
23538
- var INTEGER = 'Integer';
23539
-
23540
- function isInvalidInt(value) {
23541
- return value < -999999999999999 || 999999999999999 < value;
24338
+ function serializeError(src, type, cause) {
24339
+ return throwError('serialize', src, type, cause);
23542
24340
  }
23543
24341
 
23544
- var STRING_REGEX = /[\x00-\x1f\x7f]+/; // eslint-disable-line no-control-regex
23545
-
23546
- var TOKEN = 'Token';
24342
+ /**
24343
+ * A class to represent structured field tokens when `Symbol` is not available.
24344
+ *
24345
+ * @group Structured Field
24346
+ *
24347
+ * @beta
24348
+ */
24349
+ var SfToken = function SfToken(description) {
24350
+ this.description = void 0;
24351
+ this.description = description;
24352
+ };
23547
24353
 
23548
- var KEY = 'Key';
24354
+ var BARE_ITEM = 'Bare Item';
23549
24355
 
23550
- function serializeError(src, type, cause) {
23551
- return throwError('serialize', src, type, cause);
23552
- }
24356
+ var BOOLEAN = 'Boolean';
23553
24357
 
23554
24358
  // 4.1.9. Serializing a Boolean
23555
24359
  //
@@ -23588,6 +24392,8 @@
23588
24392
  return btoa(String.fromCharCode.apply(String, binary));
23589
24393
  }
23590
24394
 
24395
+ var BYTES = 'Byte Sequence';
24396
+
23591
24397
  // 4.1.8. Serializing a Byte Sequence
23592
24398
  //
23593
24399
  // Given a Byte Sequence as input_bytes, return an ASCII string suitable
@@ -23619,6 +24425,12 @@
23619
24425
  return ":" + base64encode(value) + ":";
23620
24426
  }
23621
24427
 
24428
+ var INTEGER = 'Integer';
24429
+
24430
+ function isInvalidInt(value) {
24431
+ return value < -999999999999999 || 999999999999999 < value;
24432
+ }
24433
+
23622
24434
  // 4.1.4. Serializing an Integer
23623
24435
  //
23624
24436
  // Given an Integer as input_integer, return an ASCII string suitable
@@ -23684,6 +24496,8 @@
23684
24496
  }
23685
24497
  }
23686
24498
 
24499
+ var DECIMAL = 'Decimal';
24500
+
23687
24501
  // 4.1.5. Serializing a Decimal
23688
24502
  //
23689
24503
  // Given a decimal number as input_decimal, return an ASCII string
@@ -23729,6 +24543,8 @@
23729
24543
 
23730
24544
  var STRING = 'String';
23731
24545
 
24546
+ var STRING_REGEX = /[\x00-\x1f\x7f]+/; // eslint-disable-line no-control-regex
24547
+
23732
24548
  // 4.1.6. Serializing a String
23733
24549
  //
23734
24550
  // Given a String as input_string, return an ASCII string suitable for
@@ -23764,6 +24580,8 @@
23764
24580
  return symbol.description || symbol.toString().slice(7, -1);
23765
24581
  }
23766
24582
 
24583
+ var TOKEN = 'Token';
24584
+
23767
24585
  function serializeToken(token) {
23768
24586
  var value = symbolToStr(token);
23769
24587
  if (/^([a-zA-Z*])([!#$%&'*+\-.^_`|~\w:/]*)$/.test(value) === false) {
@@ -23831,6 +24649,8 @@
23831
24649
  }
23832
24650
  }
23833
24651
 
24652
+ var KEY = 'Key';
24653
+
23834
24654
  // 4.1.1.3. Serializing a Key
23835
24655
  //
23836
24656
  // Given a key as input_key, return an ASCII string suitable for use in
@@ -24082,36 +24902,6 @@
24082
24902
  return toPath.join('/');
24083
24903
  }
24084
24904
 
24085
- /**
24086
- * Generate a random v4 UUID
24087
- *
24088
- * @returns A random v4 UUID
24089
- *
24090
- * @group Utils
24091
- *
24092
- * @beta
24093
- */
24094
- function uuid() {
24095
- try {
24096
- return crypto.randomUUID();
24097
- } catch (error) {
24098
- try {
24099
- var url = URL.createObjectURL(new Blob());
24100
- var _uuid = url.toString();
24101
- URL.revokeObjectURL(url);
24102
- return _uuid.slice(_uuid.lastIndexOf('/') + 1);
24103
- } catch (error) {
24104
- var dt = new Date().getTime();
24105
- var _uuid2 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
24106
- var r = (dt + Math.random() * 16) % 16 | 0;
24107
- dt = Math.floor(dt / 16);
24108
- return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
24109
- });
24110
- return _uuid2;
24111
- }
24112
- }
24113
- }
24114
-
24115
24905
  var toRounded = function toRounded(value) {
24116
24906
  return Math.round(value);
24117
24907
  };
@@ -24356,6 +25146,36 @@
24356
25146
  return "" + url + separator + query;
24357
25147
  }
24358
25148
 
25149
+ /**
25150
+ * Generate a random v4 UUID
25151
+ *
25152
+ * @returns A random v4 UUID
25153
+ *
25154
+ * @group Utils
25155
+ *
25156
+ * @beta
25157
+ */
25158
+ function uuid() {
25159
+ try {
25160
+ return crypto.randomUUID();
25161
+ } catch (error) {
25162
+ try {
25163
+ var url = URL.createObjectURL(new Blob());
25164
+ var _uuid = url.toString();
25165
+ URL.revokeObjectURL(url);
25166
+ return _uuid.slice(_uuid.lastIndexOf('/') + 1);
25167
+ } catch (error) {
25168
+ var dt = new Date().getTime();
25169
+ var _uuid2 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
25170
+ var r = (dt + Math.random() * 16) % 16 | 0;
25171
+ dt = Math.floor(dt / 16);
25172
+ return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
25173
+ });
25174
+ return _uuid2;
25175
+ }
25176
+ }
25177
+ }
25178
+
24359
25179
  /**
24360
25180
  * Controller to deal with Common Media Client Data (CMCD)
24361
25181
  * @see https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf
@@ -24420,6 +25240,12 @@
24420
25240
  data.tb = _this.getTopBandwidth(ot) / 1000;
24421
25241
  data.bl = _this.getBufferLength(ot);
24422
25242
  }
25243
+ var next = _this.getNextFrag(fragment);
25244
+ if (next) {
25245
+ if (next.url && next.url !== fragment.url) {
25246
+ data.nor = next.url;
25247
+ }
25248
+ }
24423
25249
  _this.apply(context, data);
24424
25250
  } catch (error) {
24425
25251
  logger.warn('Could not generate segment CMCD data.', error);
@@ -24514,7 +25340,7 @@
24514
25340
  data.su = this.buffering;
24515
25341
  }
24516
25342
 
24517
- // TODO: Implement rtp, nrr, nor, dl
25343
+ // TODO: Implement rtp, nrr, dl
24518
25344
 
24519
25345
  var includeKeys = this.includeKeys;
24520
25346
  if (includeKeys) {
@@ -24523,18 +25349,31 @@
24523
25349
  return acc;
24524
25350
  }, {});
24525
25351
  }
25352
+ var options = {
25353
+ baseUrl: context.url
25354
+ };
24526
25355
  if (this.useHeaders) {
24527
25356
  if (!context.headers) {
24528
25357
  context.headers = {};
24529
25358
  }
24530
- appendCmcdHeaders(context.headers, data);
25359
+ appendCmcdHeaders(context.headers, data, options);
24531
25360
  } else {
24532
- context.url = appendCmcdQuery(context.url, data);
25361
+ context.url = appendCmcdQuery(context.url, data, options);
24533
25362
  }
24534
25363
  };
25364
+ _proto.getNextFrag = function getNextFrag(fragment) {
25365
+ var _this$hls$levels$frag;
25366
+ var levelDetails = (_this$hls$levels$frag = this.hls.levels[fragment.level]) == null ? void 0 : _this$hls$levels$frag.details;
25367
+ if (levelDetails) {
25368
+ var index = fragment.sn - levelDetails.startSN;
25369
+ return levelDetails.fragments[index + 1];
25370
+ }
25371
+ return undefined;
25372
+ }
25373
+
24535
25374
  /**
24536
25375
  * The CMCD object type.
24537
- */
25376
+ */;
24538
25377
  _proto.getObjectType = function getObjectType(fragment) {
24539
25378
  var type = fragment.type;
24540
25379
  if (type === 'subtitle') {
@@ -24670,26 +25509,28 @@
24670
25509
  }();
24671
25510
 
24672
25511
  var PATHWAY_PENALTY_DURATION_MS = 300000;
24673
- var ContentSteeringController = /*#__PURE__*/function () {
25512
+ var ContentSteeringController = /*#__PURE__*/function (_Logger) {
25513
+ _inheritsLoose(ContentSteeringController, _Logger);
24674
25514
  function ContentSteeringController(hls) {
24675
- this.hls = void 0;
24676
- this.log = void 0;
24677
- this.loader = null;
24678
- this.uri = null;
24679
- this.pathwayId = '.';
24680
- this.pathwayPriority = null;
24681
- this.timeToLoad = 300;
24682
- this.reloadTimer = -1;
24683
- this.updated = 0;
24684
- this.started = false;
24685
- this.enabled = true;
24686
- this.levels = null;
24687
- this.audioTracks = null;
24688
- this.subtitleTracks = null;
24689
- this.penalizedPathways = {};
24690
- this.hls = hls;
24691
- this.log = logger.log.bind(logger, "[content-steering]:");
24692
- this.registerListeners();
25515
+ var _this;
25516
+ _this = _Logger.call(this, 'content-steering', hls.logger) || this;
25517
+ _this.hls = void 0;
25518
+ _this.loader = null;
25519
+ _this.uri = null;
25520
+ _this.pathwayId = '.';
25521
+ _this.pathwayPriority = null;
25522
+ _this.timeToLoad = 300;
25523
+ _this.reloadTimer = -1;
25524
+ _this.updated = 0;
25525
+ _this.started = false;
25526
+ _this.enabled = true;
25527
+ _this.levels = null;
25528
+ _this.audioTracks = null;
25529
+ _this.subtitleTracks = null;
25530
+ _this.penalizedPathways = {};
25531
+ _this.hls = hls;
25532
+ _this.registerListeners();
25533
+ return _this;
24693
25534
  }
24694
25535
  var _proto = ContentSteeringController.prototype;
24695
25536
  _proto.registerListeners = function registerListeners() {
@@ -24810,7 +25651,7 @@
24810
25651
  errorAction.resolved = this.pathwayId !== errorPathway;
24811
25652
  }
24812
25653
  if (!errorAction.resolved) {
24813
- logger.warn("Could not resolve " + data.details + " (\"" + data.error.message + "\") with content-steering for Pathway: " + errorPathway + " levels: " + (levels ? levels.length : levels) + " priorities: " + JSON.stringify(pathwayPriority) + " penalized: " + JSON.stringify(this.penalizedPathways));
25654
+ this.warn("Could not resolve " + data.details + " (\"" + data.error.message + "\") with content-steering for Pathway: " + errorPathway + " levels: " + (levels ? levels.length : levels) + " priorities: " + JSON.stringify(pathwayPriority) + " penalized: " + JSON.stringify(this.penalizedPathways));
24814
25655
  }
24815
25656
  }
24816
25657
  };
@@ -24890,7 +25731,7 @@
24890
25731
  return defaultPathway;
24891
25732
  };
24892
25733
  _proto.clonePathways = function clonePathways(pathwayClones) {
24893
- var _this = this;
25734
+ var _this2 = this;
24894
25735
  var levels = this.levels;
24895
25736
  if (!levels) {
24896
25737
  return;
@@ -24906,7 +25747,7 @@
24906
25747
  })) {
24907
25748
  return;
24908
25749
  }
24909
- var clonedVariants = _this.getLevelsForPathway(baseId).map(function (baseLevel) {
25750
+ var clonedVariants = _this2.getLevelsForPathway(baseId).map(function (baseLevel) {
24910
25751
  var attributes = new AttrList(baseLevel.attrs);
24911
25752
  attributes['PATHWAY-ID'] = cloneId;
24912
25753
  var clonedAudioGroupId = attributes.AUDIO && attributes.AUDIO + "_clone_" + cloneId;
@@ -24943,12 +25784,12 @@
24943
25784
  return clonedLevel;
24944
25785
  });
24945
25786
  levels.push.apply(levels, clonedVariants);
24946
- cloneRenditionGroups(_this.audioTracks, audioGroupCloneMap, uriReplacement, cloneId);
24947
- cloneRenditionGroups(_this.subtitleTracks, subtitleGroupCloneMap, uriReplacement, cloneId);
25787
+ cloneRenditionGroups(_this2.audioTracks, audioGroupCloneMap, uriReplacement, cloneId);
25788
+ cloneRenditionGroups(_this2.subtitleTracks, subtitleGroupCloneMap, uriReplacement, cloneId);
24948
25789
  });
24949
25790
  };
24950
25791
  _proto.loadSteeringManifest = function loadSteeringManifest(uri) {
24951
- var _this2 = this;
25792
+ var _this3 = this;
24952
25793
  var config = this.hls.config;
24953
25794
  var Loader = config.loader;
24954
25795
  if (this.loader) {
@@ -24983,87 +25824,87 @@
24983
25824
  };
24984
25825
  var callbacks = {
24985
25826
  onSuccess: function onSuccess(response, stats, context, networkDetails) {
24986
- _this2.log("Loaded steering manifest: \"" + url + "\"");
25827
+ _this3.log("Loaded steering manifest: \"" + url + "\"");
24987
25828
  var steeringData = response.data;
24988
- if (steeringData.VERSION !== 1) {
24989
- _this2.log("Steering VERSION " + steeringData.VERSION + " not supported!");
25829
+ if ((steeringData == null ? void 0 : steeringData.VERSION) !== 1) {
25830
+ _this3.log("Steering VERSION " + steeringData.VERSION + " not supported!");
24990
25831
  return;
24991
25832
  }
24992
- _this2.updated = performance.now();
24993
- _this2.timeToLoad = steeringData.TTL;
25833
+ _this3.updated = performance.now();
25834
+ _this3.timeToLoad = steeringData.TTL;
24994
25835
  var reloadUri = steeringData['RELOAD-URI'],
24995
25836
  pathwayClones = steeringData['PATHWAY-CLONES'],
24996
25837
  pathwayPriority = steeringData['PATHWAY-PRIORITY'];
24997
25838
  if (reloadUri) {
24998
25839
  try {
24999
- _this2.uri = new self.URL(reloadUri, url).href;
25840
+ _this3.uri = new self.URL(reloadUri, url).href;
25000
25841
  } catch (error) {
25001
- _this2.enabled = false;
25002
- _this2.log("Failed to parse Steering Manifest RELOAD-URI: " + reloadUri);
25842
+ _this3.enabled = false;
25843
+ _this3.log("Failed to parse Steering Manifest RELOAD-URI: " + reloadUri);
25003
25844
  return;
25004
25845
  }
25005
25846
  }
25006
- _this2.scheduleRefresh(_this2.uri || context.url);
25847
+ _this3.scheduleRefresh(_this3.uri || context.url);
25007
25848
  if (pathwayClones) {
25008
- _this2.clonePathways(pathwayClones);
25849
+ _this3.clonePathways(pathwayClones);
25009
25850
  }
25010
25851
  var loadedSteeringData = {
25011
25852
  steeringManifest: steeringData,
25012
25853
  url: url.toString()
25013
25854
  };
25014
- _this2.hls.trigger(Events.STEERING_MANIFEST_LOADED, loadedSteeringData);
25855
+ _this3.hls.trigger(Events.STEERING_MANIFEST_LOADED, loadedSteeringData);
25015
25856
  if (pathwayPriority) {
25016
- _this2.updatePathwayPriority(pathwayPriority);
25857
+ _this3.updatePathwayPriority(pathwayPriority);
25017
25858
  }
25018
25859
  },
25019
25860
  onError: function onError(error, context, networkDetails, stats) {
25020
- _this2.log("Error loading steering manifest: " + error.code + " " + error.text + " (" + context.url + ")");
25021
- _this2.stopLoad();
25861
+ _this3.log("Error loading steering manifest: " + error.code + " " + error.text + " (" + context.url + ")");
25862
+ _this3.stopLoad();
25022
25863
  if (error.code === 410) {
25023
- _this2.enabled = false;
25024
- _this2.log("Steering manifest " + context.url + " no longer available");
25864
+ _this3.enabled = false;
25865
+ _this3.log("Steering manifest " + context.url + " no longer available");
25025
25866
  return;
25026
25867
  }
25027
- var ttl = _this2.timeToLoad * 1000;
25868
+ var ttl = _this3.timeToLoad * 1000;
25028
25869
  if (error.code === 429) {
25029
- var loader = _this2.loader;
25870
+ var loader = _this3.loader;
25030
25871
  if (typeof (loader == null ? void 0 : loader.getResponseHeader) === 'function') {
25031
25872
  var retryAfter = loader.getResponseHeader('Retry-After');
25032
25873
  if (retryAfter) {
25033
25874
  ttl = parseFloat(retryAfter) * 1000;
25034
25875
  }
25035
25876
  }
25036
- _this2.log("Steering manifest " + context.url + " rate limited");
25877
+ _this3.log("Steering manifest " + context.url + " rate limited");
25037
25878
  return;
25038
25879
  }
25039
- _this2.scheduleRefresh(_this2.uri || context.url, ttl);
25880
+ _this3.scheduleRefresh(_this3.uri || context.url, ttl);
25040
25881
  },
25041
25882
  onTimeout: function onTimeout(stats, context, networkDetails) {
25042
- _this2.log("Timeout loading steering manifest (" + context.url + ")");
25043
- _this2.scheduleRefresh(_this2.uri || context.url);
25883
+ _this3.log("Timeout loading steering manifest (" + context.url + ")");
25884
+ _this3.scheduleRefresh(_this3.uri || context.url);
25044
25885
  }
25045
25886
  };
25046
25887
  this.log("Requesting steering manifest: " + url);
25047
25888
  this.loader.load(context, loaderConfig, callbacks);
25048
25889
  };
25049
25890
  _proto.scheduleRefresh = function scheduleRefresh(uri, ttlMs) {
25050
- var _this3 = this;
25891
+ var _this4 = this;
25051
25892
  if (ttlMs === void 0) {
25052
25893
  ttlMs = this.timeToLoad * 1000;
25053
25894
  }
25054
25895
  this.clearTimeout();
25055
25896
  this.reloadTimer = self.setTimeout(function () {
25056
- var _this3$hls;
25057
- var media = (_this3$hls = _this3.hls) == null ? void 0 : _this3$hls.media;
25897
+ var _this4$hls;
25898
+ var media = (_this4$hls = _this4.hls) == null ? void 0 : _this4$hls.media;
25058
25899
  if (media && !media.ended) {
25059
- _this3.loadSteeringManifest(uri);
25900
+ _this4.loadSteeringManifest(uri);
25060
25901
  return;
25061
25902
  }
25062
- _this3.scheduleRefresh(uri, _this3.timeToLoad * 1000);
25903
+ _this4.scheduleRefresh(uri, _this4.timeToLoad * 1000);
25063
25904
  }, ttlMs);
25064
25905
  };
25065
25906
  return ContentSteeringController;
25066
- }();
25907
+ }(Logger);
25067
25908
  function cloneRenditionGroups(tracks, groupCloneMap, uriReplacement, cloneId) {
25068
25909
  if (!tracks) {
25069
25910
  return;
@@ -25963,7 +26804,7 @@
25963
26804
  /**
25964
26805
  * @ignore
25965
26806
  */
25966
- function mergeConfig(defaultConfig, userConfig) {
26807
+ function mergeConfig(defaultConfig, userConfig, logger) {
25967
26808
  if ((userConfig.liveSyncDurationCount || userConfig.liveMaxLatencyDurationCount) && (userConfig.liveSyncDuration || userConfig.liveMaxLatencyDuration)) {
25968
26809
  throw new Error("Illegal hls.js config: don't mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration");
25969
26810
  }
@@ -26033,7 +26874,7 @@
26033
26874
  /**
26034
26875
  * @ignore
26035
26876
  */
26036
- function enableStreamingMode(config) {
26877
+ function enableStreamingMode(config, logger) {
26037
26878
  var currentLoader = config.loader;
26038
26879
  if (currentLoader !== FetchLoader && currentLoader !== XhrLoader) {
26039
26880
  // If a developer has configured their own loader, respect that choice
@@ -26050,12 +26891,11 @@
26050
26891
  }
26051
26892
  }
26052
26893
 
26053
- var chromeOrFirefox;
26054
26894
  var LevelController = /*#__PURE__*/function (_BasePlaylistControll) {
26055
26895
  _inheritsLoose(LevelController, _BasePlaylistControll);
26056
26896
  function LevelController(hls, contentSteeringController) {
26057
26897
  var _this;
26058
- _this = _BasePlaylistControll.call(this, hls, '[level-controller]') || this;
26898
+ _this = _BasePlaylistControll.call(this, hls, 'level-controller') || this;
26059
26899
  _this._levels = [];
26060
26900
  _this._firstLevel = -1;
26061
26901
  _this._maxAutoLevel = -1;
@@ -26124,21 +26964,13 @@
26124
26964
  var videoCodecFound = false;
26125
26965
  var audioCodecFound = false;
26126
26966
  data.levels.forEach(function (levelParsed) {
26127
- var _audioCodec, _videoCodec;
26967
+ var _videoCodec;
26128
26968
  var attributes = levelParsed.attrs;
26129
-
26130
- // erase audio codec info if browser does not support mp4a.40.34.
26131
- // demuxer will autodetect codec and fallback to mpeg/audio
26132
26969
  var audioCodec = levelParsed.audioCodec,
26133
26970
  videoCodec = levelParsed.videoCodec;
26134
- if (((_audioCodec = audioCodec) == null ? void 0 : _audioCodec.indexOf('mp4a.40.34')) !== -1) {
26135
- chromeOrFirefox || (chromeOrFirefox = /chrome|firefox/i.test(navigator.userAgent));
26136
- if (chromeOrFirefox) {
26137
- levelParsed.audioCodec = audioCodec = undefined;
26138
- }
26139
- }
26140
26971
  if (audioCodec) {
26141
- levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource);
26972
+ // Returns empty and set to undefined for 'mp4a.40.34' with fallback to 'audio/mpeg' SourceBuffer
26973
+ levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource) || undefined;
26142
26974
  }
26143
26975
  if (((_videoCodec = videoCodec) == null ? void 0 : _videoCodec.indexOf('avc1')) === 0) {
26144
26976
  videoCodec = levelParsed.videoCodec = convertAVC1ToAVCOTI(videoCodec);
@@ -26746,6 +27578,8 @@
26746
27578
  }
26747
27579
  return this.loadKeyEME(keyInfo, frag);
26748
27580
  case 'AES-128':
27581
+ case 'AES-256':
27582
+ case 'AES-256-CTR':
26749
27583
  return this.loadKeyHTTP(keyInfo, frag);
26750
27584
  default:
26751
27585
  return Promise.reject(this.createKeyLoadError(frag, ErrorDetails.KEY_LOAD_ERROR, new Error("Key supplied with unsupported METHOD: \"" + decryptdata.method + "\"")));
@@ -26885,21 +27719,26 @@
26885
27719
  var MAX_START_GAP_JUMP = 2.0;
26886
27720
  var SKIP_BUFFER_HOLE_STEP_SECONDS = 0.1;
26887
27721
  var SKIP_BUFFER_RANGE_START = 0.05;
26888
- var GapController = /*#__PURE__*/function () {
27722
+ var GapController = /*#__PURE__*/function (_Logger) {
27723
+ _inheritsLoose(GapController, _Logger);
26889
27724
  function GapController(config, media, fragmentTracker, hls) {
26890
- this.config = void 0;
26891
- this.media = null;
26892
- this.fragmentTracker = void 0;
26893
- this.hls = void 0;
26894
- this.nudgeRetry = 0;
26895
- this.stallReported = false;
26896
- this.stalled = null;
26897
- this.moved = false;
26898
- this.seeking = false;
26899
- this.config = config;
26900
- this.media = media;
26901
- this.fragmentTracker = fragmentTracker;
26902
- this.hls = hls;
27725
+ var _this;
27726
+ _this = _Logger.call(this, 'gap-controller', hls.logger) || this;
27727
+ _this.config = void 0;
27728
+ _this.media = null;
27729
+ _this.fragmentTracker = void 0;
27730
+ _this.hls = void 0;
27731
+ _this.nudgeRetry = 0;
27732
+ _this.stallReported = false;
27733
+ _this.stalled = null;
27734
+ _this.moved = false;
27735
+ _this.seeking = false;
27736
+ _this.ended = 0;
27737
+ _this.config = config;
27738
+ _this.media = media;
27739
+ _this.fragmentTracker = fragmentTracker;
27740
+ _this.hls = hls;
27741
+ return _this;
26903
27742
  }
26904
27743
  var _proto = GapController.prototype;
26905
27744
  _proto.destroy = function destroy() {
@@ -26914,7 +27753,7 @@
26914
27753
  *
26915
27754
  * @param lastCurrentTime - Previously read playhead position
26916
27755
  */;
26917
- _proto.poll = function poll(lastCurrentTime, activeFrag) {
27756
+ _proto.poll = function poll(lastCurrentTime, activeFrag, levelDetails, state) {
26918
27757
  var config = this.config,
26919
27758
  media = this.media,
26920
27759
  stalled = this.stalled;
@@ -26929,6 +27768,7 @@
26929
27768
 
26930
27769
  // The playhead is moving, no-op
26931
27770
  if (currentTime !== lastCurrentTime) {
27771
+ this.ended = 0;
26932
27772
  this.moved = true;
26933
27773
  if (!seeking) {
26934
27774
  this.nudgeRetry = 0;
@@ -26937,7 +27777,7 @@
26937
27777
  // The playhead is now moving, but was previously stalled
26938
27778
  if (this.stallReported) {
26939
27779
  var _stalledDuration = self.performance.now() - stalled;
26940
- logger.warn("playback not stuck anymore @" + currentTime + ", after " + Math.round(_stalledDuration) + "ms");
27780
+ this.warn("playback not stuck anymore @" + currentTime + ", after " + Math.round(_stalledDuration) + "ms");
26941
27781
  this.stallReported = false;
26942
27782
  }
26943
27783
  this.stalled = null;
@@ -26973,7 +27813,6 @@
26973
27813
  // Skip start gaps if we haven't played, but the last poll detected the start of a stall
26974
27814
  // The addition poll gives the browser a chance to jump the gap for us
26975
27815
  if (!this.moved && this.stalled !== null) {
26976
- var _level$details;
26977
27816
  // There is no playable buffer (seeked, waiting for buffer)
26978
27817
  var isBuffered = bufferInfo.len > 0;
26979
27818
  if (!isBuffered && !nextStart) {
@@ -26985,9 +27824,8 @@
26985
27824
  // When joining a live stream with audio tracks, account for live playlist window sliding by allowing
26986
27825
  // a larger jump over start gaps caused by the audio-stream-controller buffering a start fragment
26987
27826
  // that begins over 1 target duration after the video start position.
26988
- var level = this.hls.levels ? this.hls.levels[this.hls.currentLevel] : null;
26989
- var isLive = level == null ? void 0 : (_level$details = level.details) == null ? void 0 : _level$details.live;
26990
- var maxStartGapJump = isLive ? level.details.targetduration * 2 : MAX_START_GAP_JUMP;
27827
+ var isLive = !!(levelDetails != null && levelDetails.live);
27828
+ var maxStartGapJump = isLive ? levelDetails.targetduration * 2 : MAX_START_GAP_JUMP;
26991
27829
  var partialOrGap = this.fragmentTracker.getPartialFragment(currentTime);
26992
27830
  if (startJump > 0 && (startJump <= maxStartGapJump || partialOrGap)) {
26993
27831
  if (!media.paused) {
@@ -27005,6 +27843,17 @@
27005
27843
  }
27006
27844
  var stalledDuration = tnow - stalled;
27007
27845
  if (!seeking && stalledDuration >= STALL_MINIMUM_DURATION_MS) {
27846
+ // Dispatch MEDIA_ENDED when media.ended/ended event is not signalled at end of stream
27847
+ if (state === State.ENDED && !(levelDetails && levelDetails.live) && Math.abs(currentTime - ((levelDetails == null ? void 0 : levelDetails.edge) || 0)) < 1) {
27848
+ if (stalledDuration < 1000 || this.ended) {
27849
+ return;
27850
+ }
27851
+ this.ended = currentTime;
27852
+ this.hls.trigger(Events.MEDIA_ENDED, {
27853
+ stalled: true
27854
+ });
27855
+ return;
27856
+ }
27008
27857
  // Report stalling after trying to fix
27009
27858
  this._reportStall(bufferInfo);
27010
27859
  if (!this.media) {
@@ -27046,7 +27895,7 @@
27046
27895
  // needs to cross some sort of threshold covering all source-buffers content
27047
27896
  // to start playing properly.
27048
27897
  if ((bufferInfo.len > config.maxBufferHole || bufferInfo.nextStart && bufferInfo.nextStart - currentTime < config.maxBufferHole) && stalledDurationMs > config.highBufferWatchdogPeriod * 1000) {
27049
- logger.warn('Trying to nudge playhead over buffer-hole');
27898
+ this.warn('Trying to nudge playhead over buffer-hole');
27050
27899
  // Try to nudge currentTime over a buffer hole if we've been stalling for the configured amount of seconds
27051
27900
  // We only try to jump the hole if it's under the configured size
27052
27901
  // Reset stalled so to rearm watchdog timer
@@ -27068,7 +27917,7 @@
27068
27917
  // Report stalled error once
27069
27918
  this.stallReported = true;
27070
27919
  var error = new Error("Playback stalling at @" + media.currentTime + " due to low buffer (" + JSON.stringify(bufferInfo) + ")");
27071
- logger.warn(error.message);
27920
+ this.warn(error.message);
27072
27921
  hls.trigger(Events.ERROR, {
27073
27922
  type: ErrorTypes.MEDIA_ERROR,
27074
27923
  details: ErrorDetails.BUFFER_STALLED_ERROR,
@@ -27132,7 +27981,7 @@
27132
27981
  }
27133
27982
  }
27134
27983
  var targetTime = Math.max(startTime + SKIP_BUFFER_RANGE_START, currentTime + SKIP_BUFFER_HOLE_STEP_SECONDS);
27135
- logger.warn("skipping hole, adjusting currentTime from " + currentTime + " to " + targetTime);
27984
+ this.warn("skipping hole, adjusting currentTime from " + currentTime + " to " + targetTime);
27136
27985
  this.moved = true;
27137
27986
  this.stalled = null;
27138
27987
  media.currentTime = targetTime;
@@ -27171,7 +28020,7 @@
27171
28020
  var targetTime = currentTime + (nudgeRetry + 1) * config.nudgeOffset;
27172
28021
  // playback stalled in buffered area ... let's nudge currentTime to try to overcome this
27173
28022
  var error = new Error("Nudging 'currentTime' from " + currentTime + " to " + targetTime);
27174
- logger.warn(error.message);
28023
+ this.warn(error.message);
27175
28024
  media.currentTime = targetTime;
27176
28025
  hls.trigger(Events.ERROR, {
27177
28026
  type: ErrorTypes.MEDIA_ERROR,
@@ -27181,7 +28030,7 @@
27181
28030
  });
27182
28031
  } else {
27183
28032
  var _error = new Error("Playhead still not moving while enough data buffered @" + currentTime + " after " + config.nudgeMaxRetry + " nudges");
27184
- logger.error(_error.message);
28033
+ this.error(_error.message);
27185
28034
  hls.trigger(Events.ERROR, {
27186
28035
  type: ErrorTypes.MEDIA_ERROR,
27187
28036
  details: ErrorDetails.BUFFER_STALLED_ERROR,
@@ -27191,14 +28040,14 @@
27191
28040
  }
27192
28041
  };
27193
28042
  return GapController;
27194
- }();
28043
+ }(Logger);
27195
28044
 
27196
28045
  var TICK_INTERVAL = 100; // how often to tick in ms
27197
28046
  var StreamController = /*#__PURE__*/function (_BaseStreamController) {
27198
28047
  _inheritsLoose(StreamController, _BaseStreamController);
27199
28048
  function StreamController(hls, fragmentTracker, keyLoader) {
27200
28049
  var _this;
27201
- _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[stream-controller]', PlaylistLevelType.MAIN) || this;
28050
+ _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'stream-controller', PlaylistLevelType.MAIN) || this;
27202
28051
  _this.audioCodecSwap = false;
27203
28052
  _this.gapController = null;
27204
28053
  _this.level = -1;
@@ -27206,27 +28055,43 @@
27206
28055
  _this.altAudio = false;
27207
28056
  _this.audioOnly = false;
27208
28057
  _this.fragPlaying = null;
27209
- _this.onvplaying = null;
27210
- _this.onvseeked = null;
27211
28058
  _this.fragLastKbps = 0;
27212
28059
  _this.couldBacktrack = false;
27213
28060
  _this.backtrackFragment = null;
27214
28061
  _this.audioCodecSwitch = false;
27215
28062
  _this.videoBuffer = null;
27216
- _this._registerListeners();
28063
+ _this.onMediaPlaying = function () {
28064
+ // tick to speed up FRAG_CHANGED triggering
28065
+ _this.tick();
28066
+ };
28067
+ _this.onMediaSeeked = function () {
28068
+ var media = _this.media;
28069
+ var currentTime = media ? media.currentTime : null;
28070
+ if (isFiniteNumber(currentTime)) {
28071
+ _this.log("Media seeked to " + currentTime.toFixed(3));
28072
+ }
28073
+
28074
+ // If seeked was issued before buffer was appended do not tick immediately
28075
+ var bufferInfo = _this.getMainFwdBufferInfo();
28076
+ if (bufferInfo === null || bufferInfo.len === 0) {
28077
+ _this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
28078
+ return;
28079
+ }
28080
+
28081
+ // tick to speed up FRAG_CHANGED triggering
28082
+ _this.tick();
28083
+ };
28084
+ _this.registerListeners();
27217
28085
  return _this;
27218
28086
  }
27219
28087
  var _proto = StreamController.prototype;
27220
- _proto._registerListeners = function _registerListeners() {
28088
+ _proto.registerListeners = function registerListeners() {
28089
+ _BaseStreamController.prototype.registerListeners.call(this);
27221
28090
  var hls = this.hls;
27222
- hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
27223
- hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
27224
- hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
27225
28091
  hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);
27226
28092
  hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);
27227
28093
  hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
27228
28094
  hls.on(Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this);
27229
- hls.on(Events.ERROR, this.onError, this);
27230
28095
  hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
27231
28096
  hls.on(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
27232
28097
  hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
@@ -27234,15 +28099,12 @@
27234
28099
  hls.on(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);
27235
28100
  hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
27236
28101
  };
27237
- _proto._unregisterListeners = function _unregisterListeners() {
28102
+ _proto.unregisterListeners = function unregisterListeners() {
28103
+ _BaseStreamController.prototype.unregisterListeners.call(this);
27238
28104
  var hls = this.hls;
27239
- hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
27240
- hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
27241
- hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
27242
28105
  hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);
27243
28106
  hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
27244
28107
  hls.off(Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this);
27245
- hls.off(Events.ERROR, this.onError, this);
27246
28108
  hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
27247
28109
  hls.off(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
27248
28110
  hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
@@ -27251,7 +28113,9 @@
27251
28113
  hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);
27252
28114
  };
27253
28115
  _proto.onHandlerDestroying = function onHandlerDestroying() {
27254
- this._unregisterListeners();
28116
+ // @ts-ignore
28117
+ this.onMediaPlaying = this.onMediaSeeked = null;
28118
+ this.unregisterListeners();
27255
28119
  _BaseStreamController.prototype.onHandlerDestroying.call(this);
27256
28120
  };
27257
28121
  _proto.startLoad = function startLoad(startPosition) {
@@ -27361,7 +28225,7 @@
27361
28225
  if (this.altAudio && this.audioOnly) {
27362
28226
  return;
27363
28227
  }
27364
- if (!(levels != null && levels[level])) {
28228
+ if (!this.buffering || !(levels != null && levels[level])) {
27365
28229
  return;
27366
28230
  }
27367
28231
  var levelInfo = levels[level];
@@ -27567,18 +28431,15 @@
27567
28431
  _proto.onMediaAttached = function onMediaAttached(event, data) {
27568
28432
  _BaseStreamController.prototype.onMediaAttached.call(this, event, data);
27569
28433
  var media = data.media;
27570
- this.onvplaying = this.onMediaPlaying.bind(this);
27571
- this.onvseeked = this.onMediaSeeked.bind(this);
27572
- media.addEventListener('playing', this.onvplaying);
27573
- media.addEventListener('seeked', this.onvseeked);
28434
+ media.addEventListener('playing', this.onMediaPlaying);
28435
+ media.addEventListener('seeked', this.onMediaSeeked);
27574
28436
  this.gapController = new GapController(this.config, media, this.fragmentTracker, this.hls);
27575
28437
  };
27576
28438
  _proto.onMediaDetaching = function onMediaDetaching() {
27577
28439
  var media = this.media;
27578
- if (media && this.onvplaying && this.onvseeked) {
27579
- media.removeEventListener('playing', this.onvplaying);
27580
- media.removeEventListener('seeked', this.onvseeked);
27581
- this.onvplaying = this.onvseeked = null;
28440
+ if (media) {
28441
+ media.removeEventListener('playing', this.onMediaPlaying);
28442
+ media.removeEventListener('seeked', this.onMediaSeeked);
27582
28443
  this.videoBuffer = null;
27583
28444
  }
27584
28445
  this.fragPlaying = null;
@@ -27588,27 +28449,6 @@
27588
28449
  }
27589
28450
  _BaseStreamController.prototype.onMediaDetaching.call(this);
27590
28451
  };
27591
- _proto.onMediaPlaying = function onMediaPlaying() {
27592
- // tick to speed up FRAG_CHANGED triggering
27593
- this.tick();
27594
- };
27595
- _proto.onMediaSeeked = function onMediaSeeked() {
27596
- var media = this.media;
27597
- var currentTime = media ? media.currentTime : null;
27598
- if (isFiniteNumber(currentTime)) {
27599
- this.log("Media seeked to " + currentTime.toFixed(3));
27600
- }
27601
-
27602
- // If seeked was issued before buffer was appended do not tick immediately
27603
- var bufferInfo = this.getMainFwdBufferInfo();
27604
- if (bufferInfo === null || bufferInfo.len === 0) {
27605
- this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
27606
- return;
27607
- }
27608
-
27609
- // tick to speed up FRAG_CHANGED triggering
27610
- this.tick();
27611
- };
27612
28452
  _proto.onManifestLoading = function onManifestLoading() {
27613
28453
  // reset buffer on manifest loading
27614
28454
  this.log('Trigger BUFFER_RESET');
@@ -27889,8 +28729,10 @@
27889
28729
  }
27890
28730
  if (this.loadedmetadata || !BufferHelper.getBuffered(media).length) {
27891
28731
  // Resolve gaps using the main buffer, whose ranges are the intersections of the A/V sourcebuffers
27892
- var activeFrag = this.state !== State.IDLE ? this.fragCurrent : null;
27893
- gapController.poll(this.lastCurrentTime, activeFrag);
28732
+ var state = this.state;
28733
+ var activeFrag = state !== State.IDLE ? this.fragCurrent : null;
28734
+ var levelDetails = this.getLevelDetails();
28735
+ gapController.poll(this.lastCurrentTime, activeFrag, levelDetails, state);
27894
28736
  }
27895
28737
  this.lastCurrentTime = media.currentTime;
27896
28738
  };
@@ -28355,9 +29197,12 @@
28355
29197
  * The configuration object provided on player instantiation.
28356
29198
  */
28357
29199
  this.userConfig = void 0;
29200
+ /**
29201
+ * The logger functions used by this player instance, configured on player instantiation.
29202
+ */
29203
+ this.logger = void 0;
28358
29204
  this.coreComponents = void 0;
28359
29205
  this.networkControllers = void 0;
28360
- this.started = false;
28361
29206
  this._emitter = new EventEmitter();
28362
29207
  this._autoLevelCapping = -1;
28363
29208
  this._maxHdcpLevel = null;
@@ -28374,11 +29219,11 @@
28374
29219
  this._media = null;
28375
29220
  this.url = null;
28376
29221
  this.triggeringException = void 0;
28377
- enableLogs(userConfig.debug || false, 'Hls instance');
28378
- var config = this.config = mergeConfig(Hls.DefaultConfig, userConfig);
29222
+ var logger = this.logger = enableLogs(userConfig.debug || false, 'Hls instance');
29223
+ var config = this.config = mergeConfig(Hls.DefaultConfig, userConfig, logger);
28379
29224
  this.userConfig = userConfig;
28380
29225
  if (config.progressive) {
28381
- enableStreamingMode(config);
29226
+ enableStreamingMode(config, logger);
28382
29227
  }
28383
29228
 
28384
29229
  // core controllers and network loaders
@@ -28486,7 +29331,7 @@
28486
29331
  try {
28487
29332
  return this.emit(event, event, eventObject);
28488
29333
  } catch (error) {
28489
- logger.error('An internal error happened while handling event ' + event + '. Error message: "' + error.message + '". Here is a stacktrace:', error);
29334
+ this.logger.error('An internal error happened while handling event ' + event + '. Error message: "' + error.message + '". Here is a stacktrace:', error);
28490
29335
  // Prevent recursion in error event handlers that throw #5497
28491
29336
  if (!this.triggeringException) {
28492
29337
  this.triggeringException = true;
@@ -28512,7 +29357,7 @@
28512
29357
  * Dispose of the instance
28513
29358
  */;
28514
29359
  _proto.destroy = function destroy() {
28515
- logger.log('destroy');
29360
+ this.logger.log('destroy');
28516
29361
  this.trigger(Events.DESTROYING, undefined);
28517
29362
  this.detachMedia();
28518
29363
  this.removeAllListeners();
@@ -28537,7 +29382,7 @@
28537
29382
  * Attaches Hls.js to a media element
28538
29383
  */;
28539
29384
  _proto.attachMedia = function attachMedia(media) {
28540
- logger.log('attachMedia');
29385
+ this.logger.log('attachMedia');
28541
29386
  this._media = media;
28542
29387
  this.trigger(Events.MEDIA_ATTACHING, {
28543
29388
  media: media
@@ -28548,7 +29393,7 @@
28548
29393
  * Detach Hls.js from the media
28549
29394
  */;
28550
29395
  _proto.detachMedia = function detachMedia() {
28551
- logger.log('detachMedia');
29396
+ this.logger.log('detachMedia');
28552
29397
  this.trigger(Events.MEDIA_DETACHING, undefined);
28553
29398
  this._media = null;
28554
29399
  }
@@ -28565,7 +29410,7 @@
28565
29410
  });
28566
29411
  this._autoLevelCapping = -1;
28567
29412
  this._maxHdcpLevel = null;
28568
- logger.log("loadSource:" + loadingSource);
29413
+ this.logger.log("loadSource:" + loadingSource);
28569
29414
  if (media && loadedSource && (loadedSource !== loadingSource || this.bufferController.hasSourceTypes())) {
28570
29415
  this.detachMedia();
28571
29416
  this.attachMedia(media);
@@ -28587,8 +29432,7 @@
28587
29432
  if (startPosition === void 0) {
28588
29433
  startPosition = -1;
28589
29434
  }
28590
- logger.log("startLoad(" + startPosition + ")");
28591
- this.started = true;
29435
+ this.logger.log("startLoad(" + startPosition + ")");
28592
29436
  this.networkControllers.forEach(function (controller) {
28593
29437
  controller.startLoad(startPosition);
28594
29438
  });
@@ -28598,34 +29442,31 @@
28598
29442
  * Stop loading of any stream data.
28599
29443
  */;
28600
29444
  _proto.stopLoad = function stopLoad() {
28601
- logger.log('stopLoad');
28602
- this.started = false;
29445
+ this.logger.log('stopLoad');
28603
29446
  this.networkControllers.forEach(function (controller) {
28604
29447
  controller.stopLoad();
28605
29448
  });
28606
29449
  }
28607
29450
 
28608
29451
  /**
28609
- * Resumes stream controller segment loading if previously started.
29452
+ * Resumes stream controller segment loading after `pauseBuffering` has been called.
28610
29453
  */;
28611
29454
  _proto.resumeBuffering = function resumeBuffering() {
28612
- if (this.started) {
28613
- this.networkControllers.forEach(function (controller) {
28614
- if ('fragmentLoader' in controller) {
28615
- controller.startLoad(-1);
28616
- }
28617
- });
28618
- }
29455
+ this.networkControllers.forEach(function (controller) {
29456
+ if (controller.resumeBuffering) {
29457
+ controller.resumeBuffering();
29458
+ }
29459
+ });
28619
29460
  }
28620
29461
 
28621
29462
  /**
28622
- * Stops stream controller segment loading without changing 'started' state like stopLoad().
29463
+ * Prevents stream controller from loading new segments until `resumeBuffering` is called.
28623
29464
  * This allows for media buffering to be paused without interupting playlist loading.
28624
29465
  */;
28625
29466
  _proto.pauseBuffering = function pauseBuffering() {
28626
29467
  this.networkControllers.forEach(function (controller) {
28627
- if ('fragmentLoader' in controller) {
28628
- controller.stopLoad();
29468
+ if (controller.pauseBuffering) {
29469
+ controller.pauseBuffering();
28629
29470
  }
28630
29471
  });
28631
29472
  }
@@ -28634,7 +29475,7 @@
28634
29475
  * Swap through possible audio codecs in the stream (for example to switch from stereo to 5.1)
28635
29476
  */;
28636
29477
  _proto.swapAudioCodec = function swapAudioCodec() {
28637
- logger.log('swapAudioCodec');
29478
+ this.logger.log('swapAudioCodec');
28638
29479
  this.streamController.swapAudioCodec();
28639
29480
  }
28640
29481
 
@@ -28645,7 +29486,7 @@
28645
29486
  * Automatic recovery of media-errors by this process is configurable.
28646
29487
  */;
28647
29488
  _proto.recoverMediaError = function recoverMediaError() {
28648
- logger.log('recoverMediaError');
29489
+ this.logger.log('recoverMediaError');
28649
29490
  var media = this._media;
28650
29491
  this.detachMedia();
28651
29492
  if (media) {
@@ -28700,7 +29541,7 @@
28700
29541
  * Set quality level index immediately. This will flush the current buffer to replace the quality asap. That means playback will interrupt at least shortly to re-buffer and re-sync eventually. Set to -1 for automatic level selection.
28701
29542
  */,
28702
29543
  set: function set(newLevel) {
28703
- logger.log("set currentLevel:" + newLevel);
29544
+ this.logger.log("set currentLevel:" + newLevel);
28704
29545
  this.levelController.manualLevel = newLevel;
28705
29546
  this.streamController.immediateLevelSwitch();
28706
29547
  }
@@ -28721,7 +29562,7 @@
28721
29562
  * @param newLevel - Pass -1 for automatic level selection
28722
29563
  */,
28723
29564
  set: function set(newLevel) {
28724
- logger.log("set nextLevel:" + newLevel);
29565
+ this.logger.log("set nextLevel:" + newLevel);
28725
29566
  this.levelController.manualLevel = newLevel;
28726
29567
  this.streamController.nextLevelSwitch();
28727
29568
  }
@@ -28742,7 +29583,7 @@
28742
29583
  * @param newLevel - Pass -1 for automatic level selection
28743
29584
  */,
28744
29585
  set: function set(newLevel) {
28745
- logger.log("set loadLevel:" + newLevel);
29586
+ this.logger.log("set loadLevel:" + newLevel);
28746
29587
  this.levelController.manualLevel = newLevel;
28747
29588
  }
28748
29589
 
@@ -28777,7 +29618,7 @@
28777
29618
  * Sets "first-level", see getter.
28778
29619
  */,
28779
29620
  set: function set(newLevel) {
28780
- logger.log("set firstLevel:" + newLevel);
29621
+ this.logger.log("set firstLevel:" + newLevel);
28781
29622
  this.levelController.firstLevel = newLevel;
28782
29623
  }
28783
29624
 
@@ -28804,7 +29645,7 @@
28804
29645
  * (determined from download of first segment)
28805
29646
  */,
28806
29647
  set: function set(newLevel) {
28807
- logger.log("set startLevel:" + newLevel);
29648
+ this.logger.log("set startLevel:" + newLevel);
28808
29649
  // if not in automatic start level detection, ensure startLevel is greater than minAutoLevel
28809
29650
  if (newLevel !== -1) {
28810
29651
  newLevel = Math.max(newLevel, this.minAutoLevel);
@@ -28857,7 +29698,7 @@
28857
29698
  */
28858
29699
  function set(newLevel) {
28859
29700
  if (this._autoLevelCapping !== newLevel) {
28860
- logger.log("set autoLevelCapping:" + newLevel);
29701
+ this.logger.log("set autoLevelCapping:" + newLevel);
28861
29702
  this._autoLevelCapping = newLevel;
28862
29703
  this.levelController.checkMaxAutoUpdated();
28863
29704
  }
@@ -29182,7 +30023,7 @@
29182
30023
  * Get the video-dev/hls.js package version.
29183
30024
  */
29184
30025
  function get() {
29185
- return "1.5.4";
30026
+ return "1.5.5-0.canary.9978";
29186
30027
  }
29187
30028
  }, {
29188
30029
  key: "Events",