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

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 +1930 -1095
  5. package/dist/hls.js.d.ts +63 -50
  6. package/dist/hls.js.map +1 -1
  7. package/dist/hls.light.js +1609 -778
  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 +1363 -542
  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 +1635 -815
  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 +63 -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.9977");
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;
12015
- }
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);
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;
12378
+ }
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
+ }
12118
12498
  }
12499
+ if (!VideoSample) {
12500
+ VideoSample = _this2.VideoSample = _this2.createVideoSample(true, pes.pts, pes.dts, '');
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,19 @@
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
+ this.videoParser = new HevcVideoParser();
13281
+ break;
13282
+ }
13283
+ }
13284
+ if (this.videoParser !== null) {
13285
+ this.videoParser.parsePES(videoTrack, textTrack, pes, false, this._duration);
13286
+ }
12567
13287
  }
12568
13288
  videoData = {
12569
13289
  data: [],
@@ -12726,8 +13446,20 @@
12726
13446
  // try to parse last PES packets
12727
13447
  var pes;
12728
13448
  if (videoData && (pes = parsePES(videoData))) {
12729
- this.videoParser.parseAVCPES(videoTrack, textTrack, pes, true, this._duration);
12730
- videoTrack.pesData = null;
13449
+ if (this.videoParser === null) {
13450
+ switch (videoTrack.segmentCodec) {
13451
+ case 'avc':
13452
+ this.videoParser = new AvcVideoParser();
13453
+ break;
13454
+ case 'hevc':
13455
+ this.videoParser = new HevcVideoParser();
13456
+ break;
13457
+ }
13458
+ }
13459
+ if (this.videoParser !== null) {
13460
+ this.videoParser.parsePES(videoTrack, textTrack, pes, true, this._duration);
13461
+ videoTrack.pesData = null;
13462
+ }
12731
13463
  } else {
12732
13464
  // either avcData null or PES truncated, keep it for next frag parsing
12733
13465
  videoTrack.pesData = videoData;
@@ -13059,7 +13791,12 @@
13059
13791
  logger.warn('Unsupported EC-3 in M2TS found');
13060
13792
  break;
13061
13793
  case 0x24:
13062
- logger.warn('Unsupported HEVC in M2TS found');
13794
+ // ITU-T Rec. H.265 and ISO/IEC 23008-2 (HEVC)
13795
+ if (result.videoPid === -1) {
13796
+ result.videoPid = pid;
13797
+ result.segmentVideoCodec = 'hevc';
13798
+ logger.log('HEVC in M2TS found');
13799
+ }
13063
13800
  break;
13064
13801
  }
13065
13802
  // move to the next table entry
@@ -13287,6 +14024,8 @@
13287
14024
  avc1: [],
13288
14025
  // codingname
13289
14026
  avcC: [],
14027
+ hvc1: [],
14028
+ hvcC: [],
13290
14029
  btrt: [],
13291
14030
  dinf: [],
13292
14031
  dref: [],
@@ -13714,8 +14453,10 @@
13714
14453
  return MP4.box(MP4.types.stsd, MP4.STSD, MP4.ac3(track));
13715
14454
  }
13716
14455
  return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track));
13717
- } else {
14456
+ } else if (track.segmentCodec === 'avc') {
13718
14457
  return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));
14458
+ } else {
14459
+ return MP4.box(MP4.types.stsd, MP4.STSD, MP4.hvc1(track));
13719
14460
  }
13720
14461
  };
13721
14462
  MP4.tkhd = function tkhd(track) {
@@ -13853,6 +14594,84 @@
13853
14594
  var result = appendUint8Array(MP4.FTYP, movie);
13854
14595
  return result;
13855
14596
  };
14597
+ MP4.hvc1 = function hvc1(track) {
14598
+ var ps = track.params;
14599
+ var units = [track.vps, track.sps, track.pps];
14600
+ var NALuLengthSize = 4;
14601
+ 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]);
14602
+
14603
+ // compute hvcC size in bytes
14604
+ var length = config.length;
14605
+ for (var i = 0; i < units.length; i += 1) {
14606
+ length += 3;
14607
+ for (var j = 0; j < units[i].length; j += 1) {
14608
+ length += 2 + units[i][j].length;
14609
+ }
14610
+ }
14611
+ var hvcC = new Uint8Array(length);
14612
+ hvcC.set(config, 0);
14613
+ length = config.length;
14614
+ // append parameter set units: one vps, one or more sps and pps
14615
+ var iMax = units.length - 1;
14616
+ for (var _i = 0; _i < units.length; _i += 1) {
14617
+ hvcC.set(new Uint8Array([32 + _i | (_i === iMax ? 128 : 0), 0x00, units[_i].length]), length);
14618
+ length += 3;
14619
+ for (var _j = 0; _j < units[_i].length; _j += 1) {
14620
+ hvcC.set(new Uint8Array([units[_i][_j].length >> 8, units[_i][_j].length & 255]), length);
14621
+ length += 2;
14622
+ hvcC.set(units[_i][_j], length);
14623
+ length += units[_i][_j].length;
14624
+ }
14625
+ }
14626
+ var hvcc = MP4.box(MP4.types.hvcC, hvcC);
14627
+ var width = track.width;
14628
+ var height = track.height;
14629
+ var hSpacing = track.pixelRatio[0];
14630
+ var vSpacing = track.pixelRatio[1];
14631
+ return MP4.box(MP4.types.hvc1, new Uint8Array([0x00, 0x00, 0x00,
14632
+ // reserved
14633
+ 0x00, 0x00, 0x00,
14634
+ // reserved
14635
+ 0x00, 0x01,
14636
+ // data_reference_index
14637
+ 0x00, 0x00,
14638
+ // pre_defined
14639
+ 0x00, 0x00,
14640
+ // reserved
14641
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
14642
+ // pre_defined
14643
+ width >> 8 & 0xff, width & 0xff,
14644
+ // width
14645
+ height >> 8 & 0xff, height & 0xff,
14646
+ // height
14647
+ 0x00, 0x48, 0x00, 0x00,
14648
+ // horizresolution
14649
+ 0x00, 0x48, 0x00, 0x00,
14650
+ // vertresolution
14651
+ 0x00, 0x00, 0x00, 0x00,
14652
+ // reserved
14653
+ 0x00, 0x01,
14654
+ // frame_count
14655
+ 0x12, 0x64, 0x61, 0x69, 0x6c,
14656
+ // dailymotion/hls.js
14657
+ 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,
14658
+ // compressorname
14659
+ 0x00, 0x18,
14660
+ // depth = 24
14661
+ 0x11, 0x11]),
14662
+ // pre_defined = -1
14663
+ hvcc, MP4.box(MP4.types.btrt, new Uint8Array([0x00, 0x1c, 0x9c, 0x80,
14664
+ // bufferSizeDB
14665
+ 0x00, 0x2d, 0xc6, 0xc0,
14666
+ // maxBitrate
14667
+ 0x00, 0x2d, 0xc6, 0xc0])),
14668
+ // avgBitrate
14669
+ MP4.box(MP4.types.pasp, new Uint8Array([hSpacing >> 24,
14670
+ // hSpacing
14671
+ hSpacing >> 16 & 0xff, hSpacing >> 8 & 0xff, hSpacing & 0xff, vSpacing >> 24,
14672
+ // vSpacing
14673
+ vSpacing >> 16 & 0xff, vSpacing >> 8 & 0xff, vSpacing & 0xff])));
14674
+ };
13856
14675
  return MP4;
13857
14676
  }();
13858
14677
  MP4.types = void 0;
@@ -14254,9 +15073,9 @@
14254
15073
  var foundOverlap = delta < -1;
14255
15074
  if (foundHole || foundOverlap) {
14256
15075
  if (foundHole) {
14257
- logger.warn("AVC: " + toMsFromMpegTsClock(delta, true) + " ms (" + delta + "dts) hole between fragments detected at " + timeOffset.toFixed(3));
15076
+ logger.warn((track.segmentCodec || '').toUpperCase() + ": " + toMsFromMpegTsClock(delta, true) + " ms (" + delta + "dts) hole between fragments detected at " + timeOffset.toFixed(3));
14258
15077
  } else {
14259
- logger.warn("AVC: " + toMsFromMpegTsClock(-delta, true) + " ms (" + delta + "dts) overlapping between fragments detected at " + timeOffset.toFixed(3));
15078
+ logger.warn((track.segmentCodec || '').toUpperCase() + ": " + toMsFromMpegTsClock(-delta, true) + " ms (" + delta + "dts) overlapping between fragments detected at " + timeOffset.toFixed(3));
14260
15079
  }
14261
15080
  if (!foundOverlap || nextAvcDts >= inputSamples[0].pts || chromeVersion) {
14262
15081
  firstDTS = nextAvcDts;
@@ -14265,12 +15084,24 @@
14265
15084
  inputSamples[0].dts = firstDTS;
14266
15085
  inputSamples[0].pts = firstPTS;
14267
15086
  } else {
15087
+ var isPTSOrderRetained = true;
14268
15088
  for (var _i = 0; _i < inputSamples.length; _i++) {
14269
- if (inputSamples[_i].dts > firstPTS) {
15089
+ if (inputSamples[_i].dts > firstPTS && isPTSOrderRetained) {
14270
15090
  break;
14271
15091
  }
15092
+ var prevPTS = inputSamples[_i].pts;
14272
15093
  inputSamples[_i].dts -= delta;
14273
15094
  inputSamples[_i].pts -= delta;
15095
+
15096
+ // check to see if this sample's PTS order has changed
15097
+ // relative to the next one
15098
+ if (_i < inputSamples.length - 1) {
15099
+ var nextSamplePTS = inputSamples[_i + 1].pts;
15100
+ var currentSamplePTS = inputSamples[_i].pts;
15101
+ var currentOrder = nextSamplePTS <= currentSamplePTS;
15102
+ var prevOrder = nextSamplePTS <= prevPTS;
15103
+ isPTSOrderRetained = currentOrder == prevOrder;
15104
+ }
14274
15105
  }
14275
15106
  }
14276
15107
  logger.log("Video: Initial PTS/DTS adjusted: " + toMsFromMpegTsClock(firstPTS, true) + "/" + toMsFromMpegTsClock(firstDTS, true) + ", delta: " + toMsFromMpegTsClock(delta, true) + " ms");
@@ -14418,7 +15249,7 @@
14418
15249
  }
14419
15250
  }
14420
15251
  }
14421
- // next AVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)
15252
+ // next AVC/HEVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)
14422
15253
  mp4SampleDuration = stretchedLastFrame || !mp4SampleDuration ? averageSampleDuration : mp4SampleDuration;
14423
15254
  this.nextAvcDts = nextAvcDts = lastDTS + mp4SampleDuration;
14424
15255
  this.videoSampleDuration = mp4SampleDuration;
@@ -14553,7 +15384,7 @@
14553
15384
  logger.warn("[mp4-remuxer]: Injecting " + missing + " audio frame @ " + (nextPts / inputTimeScale).toFixed(3) + "s due to " + Math.round(1000 * delta / inputTimeScale) + " ms gap.");
14554
15385
  for (var j = 0; j < missing; j++) {
14555
15386
  var newStamp = Math.max(nextPts, 0);
14556
- var fillFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
15387
+ var fillFrame = AAC.getSilentFrame(track.parsedCodec || track.manifestCodec || track.codec, track.channelCount);
14557
15388
  if (!fillFrame) {
14558
15389
  logger.log('[mp4-remuxer]: Unable to get silent frame for given audio codec; duplicating last frame instead.');
14559
15390
  fillFrame = sample.unit.subarray();
@@ -14681,7 +15512,7 @@
14681
15512
  // samples count of this segment's duration
14682
15513
  var nbSamples = Math.ceil((endDTS - startDTS) / frameDuration);
14683
15514
  // silent frame
14684
- var silentFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
15515
+ var silentFrame = AAC.getSilentFrame(track.parsedCodec || track.manifestCodec || track.codec, track.channelCount);
14685
15516
  logger.warn('[mp4-remuxer]: remux empty Audio');
14686
15517
  // Can't remux if we can't generate a silent frame...
14687
15518
  if (!silentFrame) {
@@ -15071,13 +15902,15 @@
15071
15902
  duration = transmuxConfig.duration,
15072
15903
  initSegmentData = transmuxConfig.initSegmentData;
15073
15904
  var keyData = getEncryptionType(uintData, decryptdata);
15074
- if (keyData && keyData.method === 'AES-128') {
15905
+ if (keyData && isFullSegmentEncryption(keyData.method)) {
15075
15906
  var decrypter = this.getDecrypter();
15907
+ var aesMode = getAesModeFromFullSegmentMethod(keyData.method);
15908
+
15076
15909
  // Software decryption is synchronous; webCrypto is not
15077
15910
  if (decrypter.isSync()) {
15078
15911
  // Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
15079
15912
  // data is handled in the flush() call
15080
- var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer);
15913
+ var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer, aesMode);
15081
15914
  // For Low-Latency HLS Parts, decrypt in place, since part parsing is expected on push progress
15082
15915
  var loadingParts = chunkMeta.part > -1;
15083
15916
  if (loadingParts) {
@@ -15089,7 +15922,7 @@
15089
15922
  }
15090
15923
  uintData = new Uint8Array(decryptedData);
15091
15924
  } else {
15092
- this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer).then(function (decryptedData) {
15925
+ this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer, aesMode).then(function (decryptedData) {
15093
15926
  // Calling push here is important; if flush() is called while this is still resolving, this ensures that
15094
15927
  // the decrypted data has been transmuxed
15095
15928
  var result = _this.push(decryptedData, null, chunkMeta);
@@ -15710,7 +16543,7 @@
15710
16543
  observer.on(Events.ERROR, forwardMessage);
15711
16544
 
15712
16545
  // forward logger events to main thread
15713
- var forwardWorkerLogs = function forwardWorkerLogs() {
16546
+ var forwardWorkerLogs = function forwardWorkerLogs(logger) {
15714
16547
  var _loop = function _loop(logFn) {
15715
16548
  var func = function func(message) {
15716
16549
  forwardMessage('workerLog', {
@@ -15731,8 +16564,8 @@
15731
16564
  {
15732
16565
  var config = JSON.parse(data.config);
15733
16566
  self.transmuxer = new Transmuxer(observer, data.typeSupported, config, data.vendor, data.id);
15734
- enableLogs(config.debug, data.id);
15735
- forwardWorkerLogs();
16567
+ var logger = enableLogs(config.debug, data.id);
16568
+ forwardWorkerLogs(logger);
15736
16569
  forwardMessage('init', null);
15737
16570
  break;
15738
16571
  }
@@ -15906,16 +16739,7 @@
15906
16739
  this.observer = new EventEmitter();
15907
16740
  this.observer.on(Events.FRAG_DECRYPTED, forwardMessage);
15908
16741
  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
- };
16742
+ var m2tsTypeSupported = getM2TSSupportedAudioTypes(config.preferManagedMediaSource);
15919
16743
 
15920
16744
  // navigator.vendor is not always available in Web Worker
15921
16745
  // refer to https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/navigator
@@ -16199,7 +17023,7 @@
16199
17023
  _inheritsLoose(AudioStreamController, _BaseStreamController);
16200
17024
  function AudioStreamController(hls, fragmentTracker, keyLoader) {
16201
17025
  var _this;
16202
- _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[audio-stream-controller]', PlaylistLevelType.AUDIO) || this;
17026
+ _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'audio-stream-controller', PlaylistLevelType.AUDIO) || this;
16203
17027
  _this.videoBuffer = null;
16204
17028
  _this.videoTrackCC = -1;
16205
17029
  _this.waitingVideoCC = -1;
@@ -16211,27 +17035,24 @@
16211
17035
  _this.flushing = false;
16212
17036
  _this.bufferFlushed = false;
16213
17037
  _this.cachedTrackLoadedData = null;
16214
- _this._registerListeners();
17038
+ _this.registerListeners();
16215
17039
  return _this;
16216
17040
  }
16217
17041
  var _proto = AudioStreamController.prototype;
16218
17042
  _proto.onHandlerDestroying = function onHandlerDestroying() {
16219
- this._unregisterListeners();
17043
+ this.unregisterListeners();
16220
17044
  _BaseStreamController.prototype.onHandlerDestroying.call(this);
16221
17045
  this.mainDetails = null;
16222
17046
  this.bufferedTrack = null;
16223
17047
  this.switchingTrack = null;
16224
17048
  };
16225
- _proto._registerListeners = function _registerListeners() {
17049
+ _proto.registerListeners = function registerListeners() {
17050
+ _BaseStreamController.prototype.registerListeners.call(this);
16226
17051
  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
17052
  hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
16231
17053
  hls.on(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
16232
17054
  hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
16233
17055
  hls.on(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
16234
- hls.on(Events.ERROR, this.onError, this);
16235
17056
  hls.on(Events.BUFFER_RESET, this.onBufferReset, this);
16236
17057
  hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
16237
17058
  hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
@@ -16239,16 +17060,16 @@
16239
17060
  hls.on(Events.INIT_PTS_FOUND, this.onInitPtsFound, this);
16240
17061
  hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
16241
17062
  };
16242
- _proto._unregisterListeners = function _unregisterListeners() {
17063
+ _proto.unregisterListeners = function unregisterListeners() {
16243
17064
  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);
17065
+ if (!hls) {
17066
+ return;
17067
+ }
17068
+ _BaseStreamController.prototype.unregisterListeners.call(this);
16247
17069
  hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
16248
17070
  hls.off(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
16249
17071
  hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
16250
17072
  hls.off(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
16251
- hls.off(Events.ERROR, this.onError, this);
16252
17073
  hls.off(Events.BUFFER_RESET, this.onBufferReset, this);
16253
17074
  hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
16254
17075
  hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
@@ -16407,12 +17228,13 @@
16407
17228
  trackId = this.trackId;
16408
17229
  var config = hls.config;
16409
17230
 
16410
- // 1. if video not attached AND
17231
+ // 1. if buffering is suspended
17232
+ // 2. if video not attached AND
16411
17233
  // start fragment already requested OR start frag prefetch not enabled
16412
- // 2. if tracks or track not loaded and selected
17234
+ // 3. if tracks or track not loaded and selected
16413
17235
  // then exit loop
16414
17236
  // => 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])) {
17237
+ if (!this.buffering || !media && (this.startFragRequested || !config.startFragPrefetch) || !(levels != null && levels[trackId])) {
16416
17238
  return;
16417
17239
  }
16418
17240
  var levelInfo = levels[trackId];
@@ -16941,7 +17763,7 @@
16941
17763
  _inheritsLoose(AudioTrackController, _BasePlaylistControll);
16942
17764
  function AudioTrackController(hls) {
16943
17765
  var _this;
16944
- _this = _BasePlaylistControll.call(this, hls, '[audio-track-controller]') || this;
17766
+ _this = _BasePlaylistControll.call(this, hls, 'audio-track-controller') || this;
16945
17767
  _this.tracks = [];
16946
17768
  _this.groupIds = null;
16947
17769
  _this.tracksInGroup = [];
@@ -17270,26 +18092,23 @@
17270
18092
  _inheritsLoose(SubtitleStreamController, _BaseStreamController);
17271
18093
  function SubtitleStreamController(hls, fragmentTracker, keyLoader) {
17272
18094
  var _this;
17273
- _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[subtitle-stream-controller]', PlaylistLevelType.SUBTITLE) || this;
18095
+ _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'subtitle-stream-controller', PlaylistLevelType.SUBTITLE) || this;
17274
18096
  _this.currentTrackId = -1;
17275
18097
  _this.tracksBuffered = [];
17276
18098
  _this.mainDetails = null;
17277
- _this._registerListeners();
18099
+ _this.registerListeners();
17278
18100
  return _this;
17279
18101
  }
17280
18102
  var _proto = SubtitleStreamController.prototype;
17281
18103
  _proto.onHandlerDestroying = function onHandlerDestroying() {
17282
- this._unregisterListeners();
18104
+ this.unregisterListeners();
17283
18105
  _BaseStreamController.prototype.onHandlerDestroying.call(this);
17284
18106
  this.mainDetails = null;
17285
18107
  };
17286
- _proto._registerListeners = function _registerListeners() {
18108
+ _proto.registerListeners = function registerListeners() {
18109
+ _BaseStreamController.prototype.registerListeners.call(this);
17287
18110
  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
18111
  hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
17292
- hls.on(Events.ERROR, this.onError, this);
17293
18112
  hls.on(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);
17294
18113
  hls.on(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);
17295
18114
  hls.on(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);
@@ -17297,13 +18116,10 @@
17297
18116
  hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
17298
18117
  hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
17299
18118
  };
17300
- _proto._unregisterListeners = function _unregisterListeners() {
18119
+ _proto.unregisterListeners = function unregisterListeners() {
18120
+ _BaseStreamController.prototype.unregisterListeners.call(this);
17301
18121
  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
18122
  hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
17306
- hls.off(Events.ERROR, this.onError, this);
17307
18123
  hls.off(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);
17308
18124
  hls.off(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);
17309
18125
  hls.off(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);
@@ -17526,10 +18342,10 @@
17526
18342
  return;
17527
18343
  }
17528
18344
  // 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') {
18345
+ if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && isFullSegmentEncryption(decryptData.method)) {
17530
18346
  var startTime = performance.now();
17531
18347
  // decrypt the subtitles
17532
- this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).catch(function (err) {
18348
+ this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer, getAesModeFromFullSegmentMethod(decryptData.method)).catch(function (err) {
17533
18349
  hls.trigger(Events.ERROR, {
17534
18350
  type: ErrorTypes.MEDIA_ERROR,
17535
18351
  details: ErrorDetails.FRAG_DECRYPT_ERROR,
@@ -17661,7 +18477,7 @@
17661
18477
  _inheritsLoose(SubtitleTrackController, _BasePlaylistControll);
17662
18478
  function SubtitleTrackController(hls) {
17663
18479
  var _this;
17664
- _this = _BasePlaylistControll.call(this, hls, '[subtitle-track-controller]') || this;
18480
+ _this = _BasePlaylistControll.call(this, hls, 'subtitle-track-controller') || this;
17665
18481
  _this.media = null;
17666
18482
  _this.tracks = [];
17667
18483
  _this.groupIds = null;
@@ -17670,12 +18486,12 @@
17670
18486
  _this.currentTrack = null;
17671
18487
  _this.selectDefaultTrack = true;
17672
18488
  _this.queuedDefaultTrack = -1;
17673
- _this.asyncPollTrackChange = function () {
17674
- return _this.pollTrackChange(0);
17675
- };
17676
18489
  _this.useTextTrackPolling = false;
17677
18490
  _this.subtitlePollingInterval = -1;
17678
18491
  _this._subtitleDisplay = true;
18492
+ _this.asyncPollTrackChange = function () {
18493
+ return _this.pollTrackChange(0);
18494
+ };
17679
18495
  _this.onTextTracksChanged = function () {
17680
18496
  if (!_this.useTextTrackPolling) {
17681
18497
  self.clearInterval(_this.subtitlePollingInterval);
@@ -17711,6 +18527,7 @@
17711
18527
  this.tracks.length = 0;
17712
18528
  this.tracksInGroup.length = 0;
17713
18529
  this.currentTrack = null;
18530
+ // @ts-ignore
17714
18531
  this.onTextTracksChanged = this.asyncPollTrackChange = null;
17715
18532
  _BasePlaylistControll.prototype.destroy.call(this);
17716
18533
  };
@@ -18184,57 +19001,57 @@
18184
19001
  }();
18185
19002
 
18186
19003
  var VIDEO_CODEC_PROFILE_REPLACE = /(avc[1234]|hvc1|hev1|dvh[1e]|vp09|av01)(?:\.[^.,]+)+/;
18187
- var BufferController = /*#__PURE__*/function () {
19004
+ var BufferController = /*#__PURE__*/function (_Logger) {
19005
+ _inheritsLoose(BufferController, _Logger);
18188
19006
  function BufferController(hls) {
18189
- var _this = this;
19007
+ var _this;
19008
+ _this = _Logger.call(this, 'buffer-controller', hls.logger) || this;
18190
19009
  // The level details used to determine duration, target-duration and live
18191
- this.details = null;
19010
+ _this.details = null;
18192
19011
  // cache the self generated object url to detect hijack of video tag
18193
- this._objectUrl = null;
19012
+ _this._objectUrl = null;
18194
19013
  // A queue of buffer operations which require the SourceBuffer to not be updating upon execution
18195
- this.operationQueue = void 0;
19014
+ _this.operationQueue = void 0;
18196
19015
  // 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;
19016
+ _this.listeners = void 0;
19017
+ _this.hls = void 0;
18199
19018
  // The number of BUFFER_CODEC events received before any sourceBuffers are created
18200
- this.bufferCodecEventsExpected = 0;
19019
+ _this.bufferCodecEventsExpected = 0;
18201
19020
  // The total number of BUFFER_CODEC events received
18202
- this._bufferCodecEventsTotal = 0;
19021
+ _this._bufferCodecEventsTotal = 0;
18203
19022
  // A reference to the attached media element
18204
- this.media = null;
19023
+ _this.media = null;
18205
19024
  // A reference to the active media source
18206
- this.mediaSource = null;
19025
+ _this.mediaSource = null;
18207
19026
  // Last MP3 audio chunk appended
18208
- this.lastMpegAudioChunk = null;
18209
- this.appendSource = void 0;
19027
+ _this.lastMpegAudioChunk = null;
19028
+ _this.appendSource = void 0;
18210
19029
  // counters
18211
- this.appendErrors = {
19030
+ _this.appendErrors = {
18212
19031
  audio: 0,
18213
19032
  video: 0,
18214
19033
  audiovideo: 0
18215
19034
  };
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) {
19035
+ _this.tracks = {};
19036
+ _this.pendingTracks = {};
19037
+ _this.sourceBuffer = void 0;
19038
+ _this._onEndStreaming = function (event) {
18223
19039
  if (!_this.hls) {
18224
19040
  return;
18225
19041
  }
18226
19042
  _this.hls.pauseBuffering();
18227
19043
  };
18228
- this._onStartStreaming = function (event) {
19044
+ _this._onStartStreaming = function (event) {
18229
19045
  if (!_this.hls) {
18230
19046
  return;
18231
19047
  }
18232
19048
  _this.hls.resumeBuffering();
18233
19049
  };
18234
19050
  // 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;
19051
+ _this._onMediaSourceOpen = function () {
19052
+ var _assertThisInitialize = _assertThisInitialized(_this),
19053
+ media = _assertThisInitialize.media,
19054
+ mediaSource = _assertThisInitialize.mediaSource;
18238
19055
  _this.log('Media source opened');
18239
19056
  if (media) {
18240
19057
  media.removeEventListener('emptied', _this._onMediaEmptied);
@@ -18250,27 +19067,25 @@
18250
19067
  }
18251
19068
  _this.checkPendingTracks();
18252
19069
  };
18253
- this._onMediaSourceClose = function () {
19070
+ _this._onMediaSourceClose = function () {
18254
19071
  _this.log('Media source closed');
18255
19072
  };
18256
- this._onMediaSourceEnded = function () {
19073
+ _this._onMediaSourceEnded = function () {
18257
19074
  _this.log('Media source ended');
18258
19075
  };
18259
- this._onMediaEmptied = function () {
18260
- var mediaSrc = _this.mediaSrc,
18261
- _objectUrl = _this._objectUrl;
19076
+ _this._onMediaEmptied = function () {
19077
+ var _assertThisInitialize2 = _assertThisInitialized(_this),
19078
+ mediaSrc = _assertThisInitialize2.mediaSrc,
19079
+ _objectUrl = _assertThisInitialize2._objectUrl;
18262
19080
  if (mediaSrc !== _objectUrl) {
18263
- logger.error("Media element src was set while attaching MediaSource (" + _objectUrl + " > " + mediaSrc + ")");
19081
+ _this.error("Media element src was set while attaching MediaSource (" + _objectUrl + " > " + mediaSrc + ")");
18264
19082
  }
18265
19083
  };
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();
19084
+ _this.hls = hls;
19085
+ _this.appendSource = hls.config.preferManagedMediaSource;
19086
+ _this._initSourceBuffer();
19087
+ _this.registerListeners();
19088
+ return _this;
18274
19089
  }
18275
19090
  var _proto = BufferController.prototype;
18276
19091
  _proto.hasSourceTypes = function hasSourceTypes() {
@@ -18282,6 +19097,12 @@
18282
19097
  this.lastMpegAudioChunk = null;
18283
19098
  // @ts-ignore
18284
19099
  this.hls = null;
19100
+ // @ts-ignore
19101
+ this._onMediaSourceOpen = this._onMediaSourceClose = null;
19102
+ // @ts-ignore
19103
+ this._onMediaSourceEnded = null;
19104
+ // @ts-ignore
19105
+ this._onStartStreaming = this._onEndStreaming = null;
18285
19106
  };
18286
19107
  _proto.registerListeners = function registerListeners() {
18287
19108
  var hls = this.hls;
@@ -18439,6 +19260,7 @@
18439
19260
  _this2.resetBuffer(type);
18440
19261
  });
18441
19262
  this._initSourceBuffer();
19263
+ this.hls.resumeBuffering();
18442
19264
  };
18443
19265
  _proto.resetBuffer = function resetBuffer(type) {
18444
19266
  var sb = this.sourceBuffer[type];
@@ -19142,7 +19964,7 @@
19142
19964
  }
19143
19965
  }]);
19144
19966
  return BufferController;
19145
- }();
19967
+ }(Logger);
19146
19968
  function removeSourceChildren(node) {
19147
19969
  var sourceChildren = node.querySelectorAll('source');
19148
19970
  [].slice.call(sourceChildren).forEach(function (source) {
@@ -21581,14 +22403,12 @@
21581
22403
  this.cea608Parser1 = this.cea608Parser2 = undefined;
21582
22404
  };
21583
22405
  _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
- }
22406
+ var channel1 = new OutputFilter(this, 'textTrack1');
22407
+ var channel2 = new OutputFilter(this, 'textTrack2');
22408
+ var channel3 = new OutputFilter(this, 'textTrack3');
22409
+ var channel4 = new OutputFilter(this, 'textTrack4');
22410
+ this.cea608Parser1 = new Cea608Parser(1, channel1, channel2);
22411
+ this.cea608Parser2 = new Cea608Parser(3, channel3, channel4);
21592
22412
  };
21593
22413
  _proto.addCues = function addCues(trackName, startTime, endTime, screen, cueRanges) {
21594
22414
  // skip cues which overlap more than 50% with previously parsed time ranges
@@ -21823,7 +22643,7 @@
21823
22643
  return t.label;
21824
22644
  });
21825
22645
  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.");
22646
+ 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
22647
  }
21828
22648
  }
21829
22649
  } else if (this.tracks.length) {
@@ -21869,23 +22689,20 @@
21869
22689
  return level == null ? void 0 : level.attrs['CLOSED-CAPTIONS'];
21870
22690
  };
21871
22691
  _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
22692
  // 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) {
22693
+ if (this.enabled && data.frag.type === PlaylistLevelType.MAIN) {
21883
22694
  var _data$part$index, _data$part;
22695
+ var cea608Parser1 = this.cea608Parser1,
22696
+ cea608Parser2 = this.cea608Parser2,
22697
+ lastSn = this.lastSn;
22698
+ if (!cea608Parser1 || !cea608Parser2) {
22699
+ return;
22700
+ }
21884
22701
  var _data$frag = data.frag,
21885
22702
  cc = _data$frag.cc,
21886
22703
  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)) {
22704
+ var partIndex = (_data$part$index = (_data$part = data.part) == null ? void 0 : _data$part.index) != null ? _data$part$index : -1;
22705
+ if (!(sn === lastSn + 1 || sn === lastSn && partIndex === this.lastPartIndex + 1 || cc === this.lastCc)) {
21889
22706
  cea608Parser1.reset();
21890
22707
  cea608Parser2.reset();
21891
22708
  }
@@ -21941,7 +22758,7 @@
21941
22758
  frag: frag
21942
22759
  });
21943
22760
  }, function (error) {
21944
- logger.log("Failed to parse IMSC1: " + error);
22761
+ hls.logger.log("Failed to parse IMSC1: " + error);
21945
22762
  hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {
21946
22763
  success: false,
21947
22764
  frag: frag,
@@ -21979,7 +22796,7 @@
21979
22796
  _this5._fallbackToIMSC1(frag, payload);
21980
22797
  }
21981
22798
  // Something went wrong while parsing. Trigger event with success false.
21982
- logger.log("Failed to parse VTT cue: " + error);
22799
+ hls.logger.log("Failed to parse VTT cue: " + error);
21983
22800
  if (missingInitPTS && maxAvCC > frag.cc) {
21984
22801
  return;
21985
22802
  }
@@ -22041,10 +22858,7 @@
22041
22858
  this.captionsTracks = {};
22042
22859
  };
22043
22860
  _proto.onFragParsingUserdata = function onFragParsingUserdata(event, data) {
22044
- this.initCea608Parsers();
22045
- var cea608Parser1 = this.cea608Parser1,
22046
- cea608Parser2 = this.cea608Parser2;
22047
- if (!this.enabled || !cea608Parser1 || !cea608Parser2) {
22861
+ if (!this.enabled || !this.config.enableCEA708Captions) {
22048
22862
  return;
22049
22863
  }
22050
22864
  var frag = data.frag,
@@ -22057,9 +22871,12 @@
22057
22871
  for (var i = 0; i < samples.length; i++) {
22058
22872
  var ccBytes = samples[i].bytes;
22059
22873
  if (ccBytes) {
22874
+ if (!this.cea608Parser1) {
22875
+ this.initCea608Parsers();
22876
+ }
22060
22877
  var ccdatas = this.extractCea608Data(ccBytes);
22061
- cea608Parser1.addData(samples[i].pts, ccdatas[0]);
22062
- cea608Parser2.addData(samples[i].pts, ccdatas[1]);
22878
+ this.cea608Parser1.addData(samples[i].pts, ccdatas[0]);
22879
+ this.cea608Parser2.addData(samples[i].pts, ccdatas[1]);
22063
22880
  }
22064
22881
  }
22065
22882
  };
@@ -22251,7 +23068,7 @@
22251
23068
  var hls = this.hls;
22252
23069
  var maxLevel = this.getMaxLevel(levels.length - 1);
22253
23070
  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);
23071
+ hls.logger.log("Setting autoLevelCapping to " + maxLevel + ": " + levels[maxLevel].height + "p@" + levels[maxLevel].bitrate + " for media " + this.mediaWidth + "x" + this.mediaHeight);
22255
23072
  }
22256
23073
  hls.autoLevelCapping = maxLevel;
22257
23074
  if (hls.autoLevelCapping > this.autoLevelCapping && this.streamController) {
@@ -22441,10 +23258,10 @@
22441
23258
  totalDroppedFrames: droppedFrames
22442
23259
  });
22443
23260
  if (droppedFPS > 0) {
22444
- // logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));
23261
+ // hls.logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));
22445
23262
  if (currentDropped > hls.config.fpsDroppedMonitoringThreshold * currentDecoded) {
22446
23263
  var currentLevel = hls.currentLevel;
22447
- logger.warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel);
23264
+ hls.logger.warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel);
22448
23265
  if (currentLevel > 0 && (hls.autoLevelCapping === -1 || hls.autoLevelCapping >= currentLevel)) {
22449
23266
  currentLevel = currentLevel - 1;
22450
23267
  hls.trigger(Events.FPS_DROP_LEVEL_CAPPING, {
@@ -22477,7 +23294,6 @@
22477
23294
  return FPSController;
22478
23295
  }();
22479
23296
 
22480
- var LOGGER_PREFIX = '[eme]';
22481
23297
  /**
22482
23298
  * Controller to deal with encrypted media extensions (EME)
22483
23299
  * @see https://developer.mozilla.org/en-US/docs/Web/API/Encrypted_Media_Extensions_API
@@ -22485,26 +23301,122 @@
22485
23301
  * @class
22486
23302
  * @constructor
22487
23303
  */
22488
- var EMEController = /*#__PURE__*/function () {
23304
+ var EMEController = /*#__PURE__*/function (_Logger) {
23305
+ _inheritsLoose(EMEController, _Logger);
22489
23306
  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();
23307
+ var _this;
23308
+ _this = _Logger.call(this, 'eme', hls.logger) || this;
23309
+ _this.hls = void 0;
23310
+ _this.config = void 0;
23311
+ _this.media = null;
23312
+ _this.keyFormatPromise = null;
23313
+ _this.keySystemAccessPromises = {};
23314
+ _this._requestLicenseFailureCount = 0;
23315
+ _this.mediaKeySessions = [];
23316
+ _this.keyIdToKeySessionPromise = {};
23317
+ _this.setMediaKeysQueue = EMEController.CDMCleanupPromise ? [EMEController.CDMCleanupPromise] : [];
23318
+ _this.onMediaEncrypted = function (event) {
23319
+ var initDataType = event.initDataType,
23320
+ initData = event.initData;
23321
+ _this.debug("\"" + event.type + "\" event: init data type: \"" + initDataType + "\"");
23322
+
23323
+ // Ignore event when initData is null
23324
+ if (initData === null) {
23325
+ return;
23326
+ }
23327
+ var keyId;
23328
+ var keySystemDomain;
23329
+ if (initDataType === 'sinf' && _this.config.drmSystems[KeySystems.FAIRPLAY]) {
23330
+ // Match sinf keyId to playlist skd://keyId=
23331
+ var json = bin2str(new Uint8Array(initData));
23332
+ try {
23333
+ var sinf = base64Decode(JSON.parse(json).sinf);
23334
+ var tenc = parseSinf(new Uint8Array(sinf));
23335
+ if (!tenc) {
23336
+ return;
23337
+ }
23338
+ keyId = tenc.subarray(8, 24);
23339
+ keySystemDomain = KeySystems.FAIRPLAY;
23340
+ } catch (error) {
23341
+ _this.warn('Failed to parse sinf "encrypted" event message initData');
23342
+ return;
23343
+ }
23344
+ } else {
23345
+ // Support clear-lead key-session creation (otherwise depend on playlist keys)
23346
+ var psshInfo = parsePssh(initData);
23347
+ if (psshInfo === null) {
23348
+ return;
23349
+ }
23350
+ if (psshInfo.version === 0 && psshInfo.systemId === KeySystemIds.WIDEVINE && psshInfo.data) {
23351
+ keyId = psshInfo.data.subarray(8, 24);
23352
+ }
23353
+ keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
23354
+ }
23355
+ if (!keySystemDomain || !keyId) {
23356
+ return;
23357
+ }
23358
+ var keyIdHex = Hex.hexDump(keyId);
23359
+ var _assertThisInitialize = _assertThisInitialized(_this),
23360
+ keyIdToKeySessionPromise = _assertThisInitialize.keyIdToKeySessionPromise,
23361
+ mediaKeySessions = _assertThisInitialize.mediaKeySessions;
23362
+ var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
23363
+ var _loop = function _loop() {
23364
+ // Match playlist key
23365
+ var keyContext = mediaKeySessions[i];
23366
+ var decryptdata = keyContext.decryptdata;
23367
+ if (decryptdata.pssh || !decryptdata.keyId) {
23368
+ return 0; // continue
23369
+ }
23370
+ var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
23371
+ if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
23372
+ keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
23373
+ delete keyIdToKeySessionPromise[oldKeyIdHex];
23374
+ decryptdata.pssh = new Uint8Array(initData);
23375
+ decryptdata.keyId = keyId;
23376
+ keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
23377
+ return _this.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
23378
+ });
23379
+ return 1; // break
23380
+ }
23381
+ },
23382
+ _ret;
23383
+ for (var i = 0; i < mediaKeySessions.length; i++) {
23384
+ _ret = _loop();
23385
+ if (_ret === 0) continue;
23386
+ if (_ret === 1) break;
23387
+ }
23388
+ if (!keySessionContextPromise) {
23389
+ // Clear-lead key (not encountered in playlist)
23390
+ keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = _this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref) {
23391
+ var _keySystemToKeySystem;
23392
+ var keySystem = _ref.keySystem,
23393
+ mediaKeys = _ref.mediaKeys;
23394
+ _this.throwIfDestroyed();
23395
+ var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
23396
+ decryptdata.pssh = new Uint8Array(initData);
23397
+ decryptdata.keyId = keyId;
23398
+ return _this.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
23399
+ _this.throwIfDestroyed();
23400
+ var keySessionContext = _this.createMediaKeySessionContext({
23401
+ decryptdata: decryptdata,
23402
+ keySystem: keySystem,
23403
+ mediaKeys: mediaKeys
23404
+ });
23405
+ return _this.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
23406
+ });
23407
+ });
23408
+ }
23409
+ keySessionContextPromise.catch(function (error) {
23410
+ return _this.handleError(error);
23411
+ });
23412
+ };
23413
+ _this.onWaitingForKey = function (event) {
23414
+ _this.log("\"" + event.type + "\" event");
23415
+ };
23416
+ _this.hls = hls;
23417
+ _this.config = hls.config;
23418
+ _this.registerListeners();
23419
+ return _this;
22508
23420
  }
22509
23421
  var _proto = EMEController.prototype;
22510
23422
  _proto.destroy = function destroy() {
@@ -22516,9 +23428,9 @@
22516
23428
  config.licenseXhrSetup = config.licenseResponseCallback = undefined;
22517
23429
  config.drmSystems = config.drmSystemOptions = {};
22518
23430
  // @ts-ignore
22519
- this.hls = this.onMediaEncrypted = this.onWaitingForKey = this.keyIdToKeySessionPromise = null;
23431
+ this.hls = this.config = this.keyIdToKeySessionPromise = null;
22520
23432
  // @ts-ignore
22521
- this.config = null;
23433
+ this.onMediaEncrypted = this.onWaitingForKey = null;
22522
23434
  };
22523
23435
  _proto.registerListeners = function registerListeners() {
22524
23436
  this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
@@ -22557,7 +23469,7 @@
22557
23469
  }
22558
23470
  };
22559
23471
  _proto.attemptKeySystemAccess = function attemptKeySystemAccess(keySystemsToAttempt) {
22560
- var _this = this;
23472
+ var _this2 = this;
22561
23473
  var levels = this.hls.levels;
22562
23474
  var uniqueCodec = function uniqueCodec(value, i, a) {
22563
23475
  return !!value && a.indexOf(value) === i;
@@ -22574,7 +23486,7 @@
22574
23486
  return new Promise(function (resolve, reject) {
22575
23487
  var attempt = function attempt(keySystems) {
22576
23488
  var keySystem = keySystems.shift();
22577
- _this.getMediaKeysPromise(keySystem, audioCodecs, videoCodecs).then(function (mediaKeys) {
23489
+ _this2.getMediaKeysPromise(keySystem, audioCodecs, videoCodecs).then(function (mediaKeys) {
22578
23490
  return resolve({
22579
23491
  keySystem: keySystem,
22580
23492
  mediaKeys: mediaKeys
@@ -22609,7 +23521,7 @@
22609
23521
  return requestMediaKeySystemAccessFunc(keySystem, supportedConfigurations);
22610
23522
  };
22611
23523
  _proto.getMediaKeysPromise = function getMediaKeysPromise(keySystem, audioCodecs, videoCodecs) {
22612
- var _this2 = this;
23524
+ var _this3 = this;
22613
23525
  // This can throw, but is caught in event handler callpath
22614
23526
  var mediaKeySystemConfigs = getSupportedMediaKeySystemConfigurations(keySystem, audioCodecs, videoCodecs, this.config.drmSystemOptions);
22615
23527
  var keySystemAccessPromises = this.keySystemAccessPromises[keySystem];
@@ -22621,23 +23533,23 @@
22621
23533
  keySystemAccess: keySystemAccess
22622
23534
  };
22623
23535
  keySystemAccess.catch(function (error) {
22624
- _this2.log("Failed to obtain access to key-system \"" + keySystem + "\": " + error);
23536
+ _this3.log("Failed to obtain access to key-system \"" + keySystem + "\": " + error);
22625
23537
  });
22626
23538
  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 + "\"");
23539
+ _this3.log("Access for key-system \"" + mediaKeySystemAccess.keySystem + "\" obtained");
23540
+ var certificateRequest = _this3.fetchServerCertificate(keySystem);
23541
+ _this3.log("Create media-keys for \"" + keySystem + "\"");
22630
23542
  _keySystemAccessPromises.mediaKeys = mediaKeySystemAccess.createMediaKeys().then(function (mediaKeys) {
22631
- _this2.log("Media-keys created for \"" + keySystem + "\"");
23543
+ _this3.log("Media-keys created for \"" + keySystem + "\"");
22632
23544
  return certificateRequest.then(function (certificate) {
22633
23545
  if (certificate) {
22634
- return _this2.setMediaKeysServerCertificate(mediaKeys, keySystem, certificate);
23546
+ return _this3.setMediaKeysServerCertificate(mediaKeys, keySystem, certificate);
22635
23547
  }
22636
23548
  return mediaKeys;
22637
23549
  });
22638
23550
  });
22639
23551
  _keySystemAccessPromises.mediaKeys.catch(function (error) {
22640
- _this2.error("Failed to create media-keys for \"" + keySystem + "\"}: " + error);
23552
+ _this3.error("Failed to create media-keys for \"" + keySystem + "\"}: " + error);
22641
23553
  });
22642
23554
  return _keySystemAccessPromises.mediaKeys;
22643
23555
  });
@@ -22646,10 +23558,10 @@
22646
23558
  return keySystemAccessPromises.mediaKeys;
22647
23559
  });
22648
23560
  };
22649
- _proto.createMediaKeySessionContext = function createMediaKeySessionContext(_ref) {
22650
- var decryptdata = _ref.decryptdata,
22651
- keySystem = _ref.keySystem,
22652
- mediaKeys = _ref.mediaKeys;
23561
+ _proto.createMediaKeySessionContext = function createMediaKeySessionContext(_ref2) {
23562
+ var decryptdata = _ref2.decryptdata,
23563
+ keySystem = _ref2.keySystem,
23564
+ mediaKeys = _ref2.mediaKeys;
22653
23565
  this.log("Creating key-system session \"" + keySystem + "\" keyId: " + Hex.hexDump(decryptdata.keyId || []));
22654
23566
  var mediaKeysSession = mediaKeys.createSession();
22655
23567
  var mediaKeySessionContext = {
@@ -22698,14 +23610,14 @@
22698
23610
  return this.keyFormatPromise;
22699
23611
  };
22700
23612
  _proto.getKeyFormatPromise = function getKeyFormatPromise(keyFormats) {
22701
- var _this3 = this;
23613
+ var _this4 = this;
22702
23614
  return new Promise(function (resolve, reject) {
22703
- var keySystemsInConfig = getKeySystemsForConfig(_this3.config);
23615
+ var keySystemsInConfig = getKeySystemsForConfig(_this4.config);
22704
23616
  var keySystemsToAttempt = keyFormats.map(keySystemFormatToKeySystemDomain).filter(function (value) {
22705
23617
  return !!value && keySystemsInConfig.indexOf(value) !== -1;
22706
23618
  });
22707
- return _this3.getKeySystemSelectionPromise(keySystemsToAttempt).then(function (_ref2) {
22708
- var keySystem = _ref2.keySystem;
23619
+ return _this4.getKeySystemSelectionPromise(keySystemsToAttempt).then(function (_ref3) {
23620
+ var keySystem = _ref3.keySystem;
22709
23621
  var keySystemFormat = keySystemDomainToKeySystemFormat(keySystem);
22710
23622
  if (keySystemFormat) {
22711
23623
  resolve(keySystemFormat);
@@ -22716,31 +23628,31 @@
22716
23628
  });
22717
23629
  };
22718
23630
  _proto.loadKey = function loadKey(data) {
22719
- var _this4 = this;
23631
+ var _this5 = this;
22720
23632
  var decryptdata = data.keyInfo.decryptdata;
22721
23633
  var keyId = this.getKeyIdString(decryptdata);
22722
23634
  var keyDetails = "(keyId: " + keyId + " format: \"" + decryptdata.keyFormat + "\" method: " + decryptdata.method + " uri: " + decryptdata.uri + ")";
22723
23635
  this.log("Starting session for key " + keyDetails);
22724
23636
  var keySessionContextPromise = this.keyIdToKeySessionPromise[keyId];
22725
23637
  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({
23638
+ keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (_ref4) {
23639
+ var keySystem = _ref4.keySystem,
23640
+ mediaKeys = _ref4.mediaKeys;
23641
+ _this5.throwIfDestroyed();
23642
+ _this5.log("Handle encrypted media sn: " + data.frag.sn + " " + data.frag.type + ": " + data.frag.level + " using key " + keyDetails);
23643
+ return _this5.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
23644
+ _this5.throwIfDestroyed();
23645
+ var keySessionContext = _this5.createMediaKeySessionContext({
22734
23646
  keySystem: keySystem,
22735
23647
  mediaKeys: mediaKeys,
22736
23648
  decryptdata: decryptdata
22737
23649
  });
22738
23650
  var scheme = 'cenc';
22739
- return _this4.generateRequestWithPreferredKeySession(keySessionContext, scheme, decryptdata.pssh, 'playlist-key');
23651
+ return _this5.generateRequestWithPreferredKeySession(keySessionContext, scheme, decryptdata.pssh, 'playlist-key');
22740
23652
  });
22741
23653
  });
22742
23654
  keySessionContextPromise.catch(function (error) {
22743
- return _this4.handleError(error);
23655
+ return _this5.handleError(error);
22744
23656
  });
22745
23657
  }
22746
23658
  return keySessionContextPromise;
@@ -22766,128 +23678,30 @@
22766
23678
  });
22767
23679
  }
22768
23680
  };
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
- });
23681
+ _proto.getKeySystemForKeyPromise = function getKeySystemForKeyPromise(decryptdata) {
23682
+ var keyId = this.getKeyIdString(decryptdata);
23683
+ var mediaKeySessionContext = this.keyIdToKeySessionPromise[keyId];
23684
+ if (!mediaKeySessionContext) {
23685
+ var keySystem = keySystemFormatToKeySystemDomain(decryptdata.keyFormat);
23686
+ var keySystemsToAttempt = keySystem ? [keySystem] : getKeySystemsForConfig(this.config);
23687
+ return this.attemptKeySystemAccess(keySystemsToAttempt);
22884
23688
  }
22885
- keySessionContextPromise.catch(function (error) {
22886
- return _this5.handleError(error);
22887
- });
23689
+ return mediaKeySessionContext;
22888
23690
  };
22889
- _proto._onWaitingForKey = function _onWaitingForKey(event) {
22890
- this.log("\"" + event.type + "\" event");
23691
+ _proto.getKeySystemSelectionPromise = function getKeySystemSelectionPromise(keySystemsToAttempt) {
23692
+ if (!keySystemsToAttempt.length) {
23693
+ keySystemsToAttempt = getKeySystemsForConfig(this.config);
23694
+ }
23695
+ if (keySystemsToAttempt.length === 0) {
23696
+ throw new EMEKeyError({
23697
+ type: ErrorTypes.KEY_SYSTEM_ERROR,
23698
+ details: ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE,
23699
+ fatal: true
23700
+ }, "Missing key-system license configuration options " + JSON.stringify({
23701
+ drmSystems: this.config.drmSystems
23702
+ }));
23703
+ }
23704
+ return this.attemptKeySystemAccess(keySystemsToAttempt);
22891
23705
  };
22892
23706
  _proto.attemptSetMediaKeys = function attemptSetMediaKeys(keySystem, mediaKeys) {
22893
23707
  var _this6 = this;
@@ -23344,7 +24158,7 @@
23344
24158
  }
23345
24159
  };
23346
24160
  return EMEController;
23347
- }();
24161
+ }(Logger);
23348
24162
  EMEController.CDMCleanupPromise = void 0;
23349
24163
  var EMEKeyError = /*#__PURE__*/function (_Error) {
23350
24164
  _inheritsLoose(EMEKeyError, _Error);
@@ -23492,18 +24306,6 @@
23492
24306
  this.params = params;
23493
24307
  };
23494
24308
 
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
24309
  var DICT = 'Dict';
23508
24310
 
23509
24311
  function format(value) {
@@ -23527,29 +24329,25 @@
23527
24329
  });
23528
24330
  }
23529
24331
 
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;
24332
+ function serializeError(src, type, cause) {
24333
+ return throwError('serialize', src, type, cause);
23542
24334
  }
23543
24335
 
23544
- var STRING_REGEX = /[\x00-\x1f\x7f]+/; // eslint-disable-line no-control-regex
23545
-
23546
- var TOKEN = 'Token';
24336
+ /**
24337
+ * A class to represent structured field tokens when `Symbol` is not available.
24338
+ *
24339
+ * @group Structured Field
24340
+ *
24341
+ * @beta
24342
+ */
24343
+ var SfToken = function SfToken(description) {
24344
+ this.description = void 0;
24345
+ this.description = description;
24346
+ };
23547
24347
 
23548
- var KEY = 'Key';
24348
+ var BARE_ITEM = 'Bare Item';
23549
24349
 
23550
- function serializeError(src, type, cause) {
23551
- return throwError('serialize', src, type, cause);
23552
- }
24350
+ var BOOLEAN = 'Boolean';
23553
24351
 
23554
24352
  // 4.1.9. Serializing a Boolean
23555
24353
  //
@@ -23588,6 +24386,8 @@
23588
24386
  return btoa(String.fromCharCode.apply(String, binary));
23589
24387
  }
23590
24388
 
24389
+ var BYTES = 'Byte Sequence';
24390
+
23591
24391
  // 4.1.8. Serializing a Byte Sequence
23592
24392
  //
23593
24393
  // Given a Byte Sequence as input_bytes, return an ASCII string suitable
@@ -23619,6 +24419,12 @@
23619
24419
  return ":" + base64encode(value) + ":";
23620
24420
  }
23621
24421
 
24422
+ var INTEGER = 'Integer';
24423
+
24424
+ function isInvalidInt(value) {
24425
+ return value < -999999999999999 || 999999999999999 < value;
24426
+ }
24427
+
23622
24428
  // 4.1.4. Serializing an Integer
23623
24429
  //
23624
24430
  // Given an Integer as input_integer, return an ASCII string suitable
@@ -23684,6 +24490,8 @@
23684
24490
  }
23685
24491
  }
23686
24492
 
24493
+ var DECIMAL = 'Decimal';
24494
+
23687
24495
  // 4.1.5. Serializing a Decimal
23688
24496
  //
23689
24497
  // Given a decimal number as input_decimal, return an ASCII string
@@ -23729,6 +24537,8 @@
23729
24537
 
23730
24538
  var STRING = 'String';
23731
24539
 
24540
+ var STRING_REGEX = /[\x00-\x1f\x7f]+/; // eslint-disable-line no-control-regex
24541
+
23732
24542
  // 4.1.6. Serializing a String
23733
24543
  //
23734
24544
  // Given a String as input_string, return an ASCII string suitable for
@@ -23764,6 +24574,8 @@
23764
24574
  return symbol.description || symbol.toString().slice(7, -1);
23765
24575
  }
23766
24576
 
24577
+ var TOKEN = 'Token';
24578
+
23767
24579
  function serializeToken(token) {
23768
24580
  var value = symbolToStr(token);
23769
24581
  if (/^([a-zA-Z*])([!#$%&'*+\-.^_`|~\w:/]*)$/.test(value) === false) {
@@ -23831,6 +24643,8 @@
23831
24643
  }
23832
24644
  }
23833
24645
 
24646
+ var KEY = 'Key';
24647
+
23834
24648
  // 4.1.1.3. Serializing a Key
23835
24649
  //
23836
24650
  // Given a key as input_key, return an ASCII string suitable for use in
@@ -24082,36 +24896,6 @@
24082
24896
  return toPath.join('/');
24083
24897
  }
24084
24898
 
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
24899
  var toRounded = function toRounded(value) {
24116
24900
  return Math.round(value);
24117
24901
  };
@@ -24356,6 +25140,36 @@
24356
25140
  return "" + url + separator + query;
24357
25141
  }
24358
25142
 
25143
+ /**
25144
+ * Generate a random v4 UUID
25145
+ *
25146
+ * @returns A random v4 UUID
25147
+ *
25148
+ * @group Utils
25149
+ *
25150
+ * @beta
25151
+ */
25152
+ function uuid() {
25153
+ try {
25154
+ return crypto.randomUUID();
25155
+ } catch (error) {
25156
+ try {
25157
+ var url = URL.createObjectURL(new Blob());
25158
+ var _uuid = url.toString();
25159
+ URL.revokeObjectURL(url);
25160
+ return _uuid.slice(_uuid.lastIndexOf('/') + 1);
25161
+ } catch (error) {
25162
+ var dt = new Date().getTime();
25163
+ var _uuid2 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
25164
+ var r = (dt + Math.random() * 16) % 16 | 0;
25165
+ dt = Math.floor(dt / 16);
25166
+ return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
25167
+ });
25168
+ return _uuid2;
25169
+ }
25170
+ }
25171
+ }
25172
+
24359
25173
  /**
24360
25174
  * Controller to deal with Common Media Client Data (CMCD)
24361
25175
  * @see https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf
@@ -24420,6 +25234,12 @@
24420
25234
  data.tb = _this.getTopBandwidth(ot) / 1000;
24421
25235
  data.bl = _this.getBufferLength(ot);
24422
25236
  }
25237
+ var next = _this.getNextFrag(fragment);
25238
+ if (next) {
25239
+ if (next.url && next.url !== fragment.url) {
25240
+ data.nor = next.url;
25241
+ }
25242
+ }
24423
25243
  _this.apply(context, data);
24424
25244
  } catch (error) {
24425
25245
  logger.warn('Could not generate segment CMCD data.', error);
@@ -24514,7 +25334,7 @@
24514
25334
  data.su = this.buffering;
24515
25335
  }
24516
25336
 
24517
- // TODO: Implement rtp, nrr, nor, dl
25337
+ // TODO: Implement rtp, nrr, dl
24518
25338
 
24519
25339
  var includeKeys = this.includeKeys;
24520
25340
  if (includeKeys) {
@@ -24523,18 +25343,31 @@
24523
25343
  return acc;
24524
25344
  }, {});
24525
25345
  }
25346
+ var options = {
25347
+ baseUrl: context.url
25348
+ };
24526
25349
  if (this.useHeaders) {
24527
25350
  if (!context.headers) {
24528
25351
  context.headers = {};
24529
25352
  }
24530
- appendCmcdHeaders(context.headers, data);
25353
+ appendCmcdHeaders(context.headers, data, options);
24531
25354
  } else {
24532
- context.url = appendCmcdQuery(context.url, data);
25355
+ context.url = appendCmcdQuery(context.url, data, options);
24533
25356
  }
24534
25357
  };
25358
+ _proto.getNextFrag = function getNextFrag(fragment) {
25359
+ var _this$hls$levels$frag;
25360
+ var levelDetails = (_this$hls$levels$frag = this.hls.levels[fragment.level]) == null ? void 0 : _this$hls$levels$frag.details;
25361
+ if (levelDetails) {
25362
+ var index = fragment.sn - levelDetails.startSN;
25363
+ return levelDetails.fragments[index + 1];
25364
+ }
25365
+ return undefined;
25366
+ }
25367
+
24535
25368
  /**
24536
25369
  * The CMCD object type.
24537
- */
25370
+ */;
24538
25371
  _proto.getObjectType = function getObjectType(fragment) {
24539
25372
  var type = fragment.type;
24540
25373
  if (type === 'subtitle') {
@@ -24670,26 +25503,28 @@
24670
25503
  }();
24671
25504
 
24672
25505
  var PATHWAY_PENALTY_DURATION_MS = 300000;
24673
- var ContentSteeringController = /*#__PURE__*/function () {
25506
+ var ContentSteeringController = /*#__PURE__*/function (_Logger) {
25507
+ _inheritsLoose(ContentSteeringController, _Logger);
24674
25508
  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();
25509
+ var _this;
25510
+ _this = _Logger.call(this, 'content-steering', hls.logger) || this;
25511
+ _this.hls = void 0;
25512
+ _this.loader = null;
25513
+ _this.uri = null;
25514
+ _this.pathwayId = '.';
25515
+ _this.pathwayPriority = null;
25516
+ _this.timeToLoad = 300;
25517
+ _this.reloadTimer = -1;
25518
+ _this.updated = 0;
25519
+ _this.started = false;
25520
+ _this.enabled = true;
25521
+ _this.levels = null;
25522
+ _this.audioTracks = null;
25523
+ _this.subtitleTracks = null;
25524
+ _this.penalizedPathways = {};
25525
+ _this.hls = hls;
25526
+ _this.registerListeners();
25527
+ return _this;
24693
25528
  }
24694
25529
  var _proto = ContentSteeringController.prototype;
24695
25530
  _proto.registerListeners = function registerListeners() {
@@ -24810,7 +25645,7 @@
24810
25645
  errorAction.resolved = this.pathwayId !== errorPathway;
24811
25646
  }
24812
25647
  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));
25648
+ 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
25649
  }
24815
25650
  }
24816
25651
  };
@@ -24890,7 +25725,7 @@
24890
25725
  return defaultPathway;
24891
25726
  };
24892
25727
  _proto.clonePathways = function clonePathways(pathwayClones) {
24893
- var _this = this;
25728
+ var _this2 = this;
24894
25729
  var levels = this.levels;
24895
25730
  if (!levels) {
24896
25731
  return;
@@ -24906,7 +25741,7 @@
24906
25741
  })) {
24907
25742
  return;
24908
25743
  }
24909
- var clonedVariants = _this.getLevelsForPathway(baseId).map(function (baseLevel) {
25744
+ var clonedVariants = _this2.getLevelsForPathway(baseId).map(function (baseLevel) {
24910
25745
  var attributes = new AttrList(baseLevel.attrs);
24911
25746
  attributes['PATHWAY-ID'] = cloneId;
24912
25747
  var clonedAudioGroupId = attributes.AUDIO && attributes.AUDIO + "_clone_" + cloneId;
@@ -24943,12 +25778,12 @@
24943
25778
  return clonedLevel;
24944
25779
  });
24945
25780
  levels.push.apply(levels, clonedVariants);
24946
- cloneRenditionGroups(_this.audioTracks, audioGroupCloneMap, uriReplacement, cloneId);
24947
- cloneRenditionGroups(_this.subtitleTracks, subtitleGroupCloneMap, uriReplacement, cloneId);
25781
+ cloneRenditionGroups(_this2.audioTracks, audioGroupCloneMap, uriReplacement, cloneId);
25782
+ cloneRenditionGroups(_this2.subtitleTracks, subtitleGroupCloneMap, uriReplacement, cloneId);
24948
25783
  });
24949
25784
  };
24950
25785
  _proto.loadSteeringManifest = function loadSteeringManifest(uri) {
24951
- var _this2 = this;
25786
+ var _this3 = this;
24952
25787
  var config = this.hls.config;
24953
25788
  var Loader = config.loader;
24954
25789
  if (this.loader) {
@@ -24983,87 +25818,87 @@
24983
25818
  };
24984
25819
  var callbacks = {
24985
25820
  onSuccess: function onSuccess(response, stats, context, networkDetails) {
24986
- _this2.log("Loaded steering manifest: \"" + url + "\"");
25821
+ _this3.log("Loaded steering manifest: \"" + url + "\"");
24987
25822
  var steeringData = response.data;
24988
- if (steeringData.VERSION !== 1) {
24989
- _this2.log("Steering VERSION " + steeringData.VERSION + " not supported!");
25823
+ if ((steeringData == null ? void 0 : steeringData.VERSION) !== 1) {
25824
+ _this3.log("Steering VERSION " + steeringData.VERSION + " not supported!");
24990
25825
  return;
24991
25826
  }
24992
- _this2.updated = performance.now();
24993
- _this2.timeToLoad = steeringData.TTL;
25827
+ _this3.updated = performance.now();
25828
+ _this3.timeToLoad = steeringData.TTL;
24994
25829
  var reloadUri = steeringData['RELOAD-URI'],
24995
25830
  pathwayClones = steeringData['PATHWAY-CLONES'],
24996
25831
  pathwayPriority = steeringData['PATHWAY-PRIORITY'];
24997
25832
  if (reloadUri) {
24998
25833
  try {
24999
- _this2.uri = new self.URL(reloadUri, url).href;
25834
+ _this3.uri = new self.URL(reloadUri, url).href;
25000
25835
  } catch (error) {
25001
- _this2.enabled = false;
25002
- _this2.log("Failed to parse Steering Manifest RELOAD-URI: " + reloadUri);
25836
+ _this3.enabled = false;
25837
+ _this3.log("Failed to parse Steering Manifest RELOAD-URI: " + reloadUri);
25003
25838
  return;
25004
25839
  }
25005
25840
  }
25006
- _this2.scheduleRefresh(_this2.uri || context.url);
25841
+ _this3.scheduleRefresh(_this3.uri || context.url);
25007
25842
  if (pathwayClones) {
25008
- _this2.clonePathways(pathwayClones);
25843
+ _this3.clonePathways(pathwayClones);
25009
25844
  }
25010
25845
  var loadedSteeringData = {
25011
25846
  steeringManifest: steeringData,
25012
25847
  url: url.toString()
25013
25848
  };
25014
- _this2.hls.trigger(Events.STEERING_MANIFEST_LOADED, loadedSteeringData);
25849
+ _this3.hls.trigger(Events.STEERING_MANIFEST_LOADED, loadedSteeringData);
25015
25850
  if (pathwayPriority) {
25016
- _this2.updatePathwayPriority(pathwayPriority);
25851
+ _this3.updatePathwayPriority(pathwayPriority);
25017
25852
  }
25018
25853
  },
25019
25854
  onError: function onError(error, context, networkDetails, stats) {
25020
- _this2.log("Error loading steering manifest: " + error.code + " " + error.text + " (" + context.url + ")");
25021
- _this2.stopLoad();
25855
+ _this3.log("Error loading steering manifest: " + error.code + " " + error.text + " (" + context.url + ")");
25856
+ _this3.stopLoad();
25022
25857
  if (error.code === 410) {
25023
- _this2.enabled = false;
25024
- _this2.log("Steering manifest " + context.url + " no longer available");
25858
+ _this3.enabled = false;
25859
+ _this3.log("Steering manifest " + context.url + " no longer available");
25025
25860
  return;
25026
25861
  }
25027
- var ttl = _this2.timeToLoad * 1000;
25862
+ var ttl = _this3.timeToLoad * 1000;
25028
25863
  if (error.code === 429) {
25029
- var loader = _this2.loader;
25864
+ var loader = _this3.loader;
25030
25865
  if (typeof (loader == null ? void 0 : loader.getResponseHeader) === 'function') {
25031
25866
  var retryAfter = loader.getResponseHeader('Retry-After');
25032
25867
  if (retryAfter) {
25033
25868
  ttl = parseFloat(retryAfter) * 1000;
25034
25869
  }
25035
25870
  }
25036
- _this2.log("Steering manifest " + context.url + " rate limited");
25871
+ _this3.log("Steering manifest " + context.url + " rate limited");
25037
25872
  return;
25038
25873
  }
25039
- _this2.scheduleRefresh(_this2.uri || context.url, ttl);
25874
+ _this3.scheduleRefresh(_this3.uri || context.url, ttl);
25040
25875
  },
25041
25876
  onTimeout: function onTimeout(stats, context, networkDetails) {
25042
- _this2.log("Timeout loading steering manifest (" + context.url + ")");
25043
- _this2.scheduleRefresh(_this2.uri || context.url);
25877
+ _this3.log("Timeout loading steering manifest (" + context.url + ")");
25878
+ _this3.scheduleRefresh(_this3.uri || context.url);
25044
25879
  }
25045
25880
  };
25046
25881
  this.log("Requesting steering manifest: " + url);
25047
25882
  this.loader.load(context, loaderConfig, callbacks);
25048
25883
  };
25049
25884
  _proto.scheduleRefresh = function scheduleRefresh(uri, ttlMs) {
25050
- var _this3 = this;
25885
+ var _this4 = this;
25051
25886
  if (ttlMs === void 0) {
25052
25887
  ttlMs = this.timeToLoad * 1000;
25053
25888
  }
25054
25889
  this.clearTimeout();
25055
25890
  this.reloadTimer = self.setTimeout(function () {
25056
- var _this3$hls;
25057
- var media = (_this3$hls = _this3.hls) == null ? void 0 : _this3$hls.media;
25891
+ var _this4$hls;
25892
+ var media = (_this4$hls = _this4.hls) == null ? void 0 : _this4$hls.media;
25058
25893
  if (media && !media.ended) {
25059
- _this3.loadSteeringManifest(uri);
25894
+ _this4.loadSteeringManifest(uri);
25060
25895
  return;
25061
25896
  }
25062
- _this3.scheduleRefresh(uri, _this3.timeToLoad * 1000);
25897
+ _this4.scheduleRefresh(uri, _this4.timeToLoad * 1000);
25063
25898
  }, ttlMs);
25064
25899
  };
25065
25900
  return ContentSteeringController;
25066
- }();
25901
+ }(Logger);
25067
25902
  function cloneRenditionGroups(tracks, groupCloneMap, uriReplacement, cloneId) {
25068
25903
  if (!tracks) {
25069
25904
  return;
@@ -25963,7 +26798,7 @@
25963
26798
  /**
25964
26799
  * @ignore
25965
26800
  */
25966
- function mergeConfig(defaultConfig, userConfig) {
26801
+ function mergeConfig(defaultConfig, userConfig, logger) {
25967
26802
  if ((userConfig.liveSyncDurationCount || userConfig.liveMaxLatencyDurationCount) && (userConfig.liveSyncDuration || userConfig.liveMaxLatencyDuration)) {
25968
26803
  throw new Error("Illegal hls.js config: don't mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration");
25969
26804
  }
@@ -26033,7 +26868,7 @@
26033
26868
  /**
26034
26869
  * @ignore
26035
26870
  */
26036
- function enableStreamingMode(config) {
26871
+ function enableStreamingMode(config, logger) {
26037
26872
  var currentLoader = config.loader;
26038
26873
  if (currentLoader !== FetchLoader && currentLoader !== XhrLoader) {
26039
26874
  // If a developer has configured their own loader, respect that choice
@@ -26050,12 +26885,11 @@
26050
26885
  }
26051
26886
  }
26052
26887
 
26053
- var chromeOrFirefox;
26054
26888
  var LevelController = /*#__PURE__*/function (_BasePlaylistControll) {
26055
26889
  _inheritsLoose(LevelController, _BasePlaylistControll);
26056
26890
  function LevelController(hls, contentSteeringController) {
26057
26891
  var _this;
26058
- _this = _BasePlaylistControll.call(this, hls, '[level-controller]') || this;
26892
+ _this = _BasePlaylistControll.call(this, hls, 'level-controller') || this;
26059
26893
  _this._levels = [];
26060
26894
  _this._firstLevel = -1;
26061
26895
  _this._maxAutoLevel = -1;
@@ -26124,21 +26958,13 @@
26124
26958
  var videoCodecFound = false;
26125
26959
  var audioCodecFound = false;
26126
26960
  data.levels.forEach(function (levelParsed) {
26127
- var _audioCodec, _videoCodec;
26961
+ var _videoCodec;
26128
26962
  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
26963
  var audioCodec = levelParsed.audioCodec,
26133
26964
  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
26965
  if (audioCodec) {
26141
- levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource);
26966
+ // Returns empty and set to undefined for 'mp4a.40.34' with fallback to 'audio/mpeg' SourceBuffer
26967
+ levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource) || undefined;
26142
26968
  }
26143
26969
  if (((_videoCodec = videoCodec) == null ? void 0 : _videoCodec.indexOf('avc1')) === 0) {
26144
26970
  videoCodec = levelParsed.videoCodec = convertAVC1ToAVCOTI(videoCodec);
@@ -26746,6 +27572,8 @@
26746
27572
  }
26747
27573
  return this.loadKeyEME(keyInfo, frag);
26748
27574
  case 'AES-128':
27575
+ case 'AES-256':
27576
+ case 'AES-256-CTR':
26749
27577
  return this.loadKeyHTTP(keyInfo, frag);
26750
27578
  default:
26751
27579
  return Promise.reject(this.createKeyLoadError(frag, ErrorDetails.KEY_LOAD_ERROR, new Error("Key supplied with unsupported METHOD: \"" + decryptdata.method + "\"")));
@@ -26885,21 +27713,26 @@
26885
27713
  var MAX_START_GAP_JUMP = 2.0;
26886
27714
  var SKIP_BUFFER_HOLE_STEP_SECONDS = 0.1;
26887
27715
  var SKIP_BUFFER_RANGE_START = 0.05;
26888
- var GapController = /*#__PURE__*/function () {
27716
+ var GapController = /*#__PURE__*/function (_Logger) {
27717
+ _inheritsLoose(GapController, _Logger);
26889
27718
  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;
27719
+ var _this;
27720
+ _this = _Logger.call(this, 'gap-controller', hls.logger) || this;
27721
+ _this.config = void 0;
27722
+ _this.media = null;
27723
+ _this.fragmentTracker = void 0;
27724
+ _this.hls = void 0;
27725
+ _this.nudgeRetry = 0;
27726
+ _this.stallReported = false;
27727
+ _this.stalled = null;
27728
+ _this.moved = false;
27729
+ _this.seeking = false;
27730
+ _this.ended = 0;
27731
+ _this.config = config;
27732
+ _this.media = media;
27733
+ _this.fragmentTracker = fragmentTracker;
27734
+ _this.hls = hls;
27735
+ return _this;
26903
27736
  }
26904
27737
  var _proto = GapController.prototype;
26905
27738
  _proto.destroy = function destroy() {
@@ -26914,7 +27747,7 @@
26914
27747
  *
26915
27748
  * @param lastCurrentTime - Previously read playhead position
26916
27749
  */;
26917
- _proto.poll = function poll(lastCurrentTime, activeFrag) {
27750
+ _proto.poll = function poll(lastCurrentTime, activeFrag, levelDetails, state) {
26918
27751
  var config = this.config,
26919
27752
  media = this.media,
26920
27753
  stalled = this.stalled;
@@ -26929,6 +27762,7 @@
26929
27762
 
26930
27763
  // The playhead is moving, no-op
26931
27764
  if (currentTime !== lastCurrentTime) {
27765
+ this.ended = 0;
26932
27766
  this.moved = true;
26933
27767
  if (!seeking) {
26934
27768
  this.nudgeRetry = 0;
@@ -26937,7 +27771,7 @@
26937
27771
  // The playhead is now moving, but was previously stalled
26938
27772
  if (this.stallReported) {
26939
27773
  var _stalledDuration = self.performance.now() - stalled;
26940
- logger.warn("playback not stuck anymore @" + currentTime + ", after " + Math.round(_stalledDuration) + "ms");
27774
+ this.warn("playback not stuck anymore @" + currentTime + ", after " + Math.round(_stalledDuration) + "ms");
26941
27775
  this.stallReported = false;
26942
27776
  }
26943
27777
  this.stalled = null;
@@ -26973,7 +27807,6 @@
26973
27807
  // Skip start gaps if we haven't played, but the last poll detected the start of a stall
26974
27808
  // The addition poll gives the browser a chance to jump the gap for us
26975
27809
  if (!this.moved && this.stalled !== null) {
26976
- var _level$details;
26977
27810
  // There is no playable buffer (seeked, waiting for buffer)
26978
27811
  var isBuffered = bufferInfo.len > 0;
26979
27812
  if (!isBuffered && !nextStart) {
@@ -26985,9 +27818,8 @@
26985
27818
  // When joining a live stream with audio tracks, account for live playlist window sliding by allowing
26986
27819
  // a larger jump over start gaps caused by the audio-stream-controller buffering a start fragment
26987
27820
  // 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;
27821
+ var isLive = !!(levelDetails != null && levelDetails.live);
27822
+ var maxStartGapJump = isLive ? levelDetails.targetduration * 2 : MAX_START_GAP_JUMP;
26991
27823
  var partialOrGap = this.fragmentTracker.getPartialFragment(currentTime);
26992
27824
  if (startJump > 0 && (startJump <= maxStartGapJump || partialOrGap)) {
26993
27825
  if (!media.paused) {
@@ -27005,6 +27837,17 @@
27005
27837
  }
27006
27838
  var stalledDuration = tnow - stalled;
27007
27839
  if (!seeking && stalledDuration >= STALL_MINIMUM_DURATION_MS) {
27840
+ // Dispatch MEDIA_ENDED when media.ended/ended event is not signalled at end of stream
27841
+ if (state === State.ENDED && !(levelDetails && levelDetails.live) && Math.abs(currentTime - ((levelDetails == null ? void 0 : levelDetails.edge) || 0)) < 1) {
27842
+ if (stalledDuration < 1000 || this.ended) {
27843
+ return;
27844
+ }
27845
+ this.ended = currentTime;
27846
+ this.hls.trigger(Events.MEDIA_ENDED, {
27847
+ stalled: true
27848
+ });
27849
+ return;
27850
+ }
27008
27851
  // Report stalling after trying to fix
27009
27852
  this._reportStall(bufferInfo);
27010
27853
  if (!this.media) {
@@ -27046,7 +27889,7 @@
27046
27889
  // needs to cross some sort of threshold covering all source-buffers content
27047
27890
  // to start playing properly.
27048
27891
  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');
27892
+ this.warn('Trying to nudge playhead over buffer-hole');
27050
27893
  // Try to nudge currentTime over a buffer hole if we've been stalling for the configured amount of seconds
27051
27894
  // We only try to jump the hole if it's under the configured size
27052
27895
  // Reset stalled so to rearm watchdog timer
@@ -27068,7 +27911,7 @@
27068
27911
  // Report stalled error once
27069
27912
  this.stallReported = true;
27070
27913
  var error = new Error("Playback stalling at @" + media.currentTime + " due to low buffer (" + JSON.stringify(bufferInfo) + ")");
27071
- logger.warn(error.message);
27914
+ this.warn(error.message);
27072
27915
  hls.trigger(Events.ERROR, {
27073
27916
  type: ErrorTypes.MEDIA_ERROR,
27074
27917
  details: ErrorDetails.BUFFER_STALLED_ERROR,
@@ -27132,7 +27975,7 @@
27132
27975
  }
27133
27976
  }
27134
27977
  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);
27978
+ this.warn("skipping hole, adjusting currentTime from " + currentTime + " to " + targetTime);
27136
27979
  this.moved = true;
27137
27980
  this.stalled = null;
27138
27981
  media.currentTime = targetTime;
@@ -27171,7 +28014,7 @@
27171
28014
  var targetTime = currentTime + (nudgeRetry + 1) * config.nudgeOffset;
27172
28015
  // playback stalled in buffered area ... let's nudge currentTime to try to overcome this
27173
28016
  var error = new Error("Nudging 'currentTime' from " + currentTime + " to " + targetTime);
27174
- logger.warn(error.message);
28017
+ this.warn(error.message);
27175
28018
  media.currentTime = targetTime;
27176
28019
  hls.trigger(Events.ERROR, {
27177
28020
  type: ErrorTypes.MEDIA_ERROR,
@@ -27181,7 +28024,7 @@
27181
28024
  });
27182
28025
  } else {
27183
28026
  var _error = new Error("Playhead still not moving while enough data buffered @" + currentTime + " after " + config.nudgeMaxRetry + " nudges");
27184
- logger.error(_error.message);
28027
+ this.error(_error.message);
27185
28028
  hls.trigger(Events.ERROR, {
27186
28029
  type: ErrorTypes.MEDIA_ERROR,
27187
28030
  details: ErrorDetails.BUFFER_STALLED_ERROR,
@@ -27191,14 +28034,14 @@
27191
28034
  }
27192
28035
  };
27193
28036
  return GapController;
27194
- }();
28037
+ }(Logger);
27195
28038
 
27196
28039
  var TICK_INTERVAL = 100; // how often to tick in ms
27197
28040
  var StreamController = /*#__PURE__*/function (_BaseStreamController) {
27198
28041
  _inheritsLoose(StreamController, _BaseStreamController);
27199
28042
  function StreamController(hls, fragmentTracker, keyLoader) {
27200
28043
  var _this;
27201
- _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[stream-controller]', PlaylistLevelType.MAIN) || this;
28044
+ _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'stream-controller', PlaylistLevelType.MAIN) || this;
27202
28045
  _this.audioCodecSwap = false;
27203
28046
  _this.gapController = null;
27204
28047
  _this.level = -1;
@@ -27206,27 +28049,43 @@
27206
28049
  _this.altAudio = false;
27207
28050
  _this.audioOnly = false;
27208
28051
  _this.fragPlaying = null;
27209
- _this.onvplaying = null;
27210
- _this.onvseeked = null;
27211
28052
  _this.fragLastKbps = 0;
27212
28053
  _this.couldBacktrack = false;
27213
28054
  _this.backtrackFragment = null;
27214
28055
  _this.audioCodecSwitch = false;
27215
28056
  _this.videoBuffer = null;
27216
- _this._registerListeners();
28057
+ _this.onMediaPlaying = function () {
28058
+ // tick to speed up FRAG_CHANGED triggering
28059
+ _this.tick();
28060
+ };
28061
+ _this.onMediaSeeked = function () {
28062
+ var media = _this.media;
28063
+ var currentTime = media ? media.currentTime : null;
28064
+ if (isFiniteNumber(currentTime)) {
28065
+ _this.log("Media seeked to " + currentTime.toFixed(3));
28066
+ }
28067
+
28068
+ // If seeked was issued before buffer was appended do not tick immediately
28069
+ var bufferInfo = _this.getMainFwdBufferInfo();
28070
+ if (bufferInfo === null || bufferInfo.len === 0) {
28071
+ _this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
28072
+ return;
28073
+ }
28074
+
28075
+ // tick to speed up FRAG_CHANGED triggering
28076
+ _this.tick();
28077
+ };
28078
+ _this.registerListeners();
27217
28079
  return _this;
27218
28080
  }
27219
28081
  var _proto = StreamController.prototype;
27220
- _proto._registerListeners = function _registerListeners() {
28082
+ _proto.registerListeners = function registerListeners() {
28083
+ _BaseStreamController.prototype.registerListeners.call(this);
27221
28084
  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
28085
  hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);
27226
28086
  hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);
27227
28087
  hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
27228
28088
  hls.on(Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this);
27229
- hls.on(Events.ERROR, this.onError, this);
27230
28089
  hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
27231
28090
  hls.on(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
27232
28091
  hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
@@ -27234,15 +28093,12 @@
27234
28093
  hls.on(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);
27235
28094
  hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
27236
28095
  };
27237
- _proto._unregisterListeners = function _unregisterListeners() {
28096
+ _proto.unregisterListeners = function unregisterListeners() {
28097
+ _BaseStreamController.prototype.unregisterListeners.call(this);
27238
28098
  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
28099
  hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);
27243
28100
  hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
27244
28101
  hls.off(Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this);
27245
- hls.off(Events.ERROR, this.onError, this);
27246
28102
  hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
27247
28103
  hls.off(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
27248
28104
  hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
@@ -27251,7 +28107,9 @@
27251
28107
  hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);
27252
28108
  };
27253
28109
  _proto.onHandlerDestroying = function onHandlerDestroying() {
27254
- this._unregisterListeners();
28110
+ // @ts-ignore
28111
+ this.onMediaPlaying = this.onMediaSeeked = null;
28112
+ this.unregisterListeners();
27255
28113
  _BaseStreamController.prototype.onHandlerDestroying.call(this);
27256
28114
  };
27257
28115
  _proto.startLoad = function startLoad(startPosition) {
@@ -27361,7 +28219,7 @@
27361
28219
  if (this.altAudio && this.audioOnly) {
27362
28220
  return;
27363
28221
  }
27364
- if (!(levels != null && levels[level])) {
28222
+ if (!this.buffering || !(levels != null && levels[level])) {
27365
28223
  return;
27366
28224
  }
27367
28225
  var levelInfo = levels[level];
@@ -27567,18 +28425,15 @@
27567
28425
  _proto.onMediaAttached = function onMediaAttached(event, data) {
27568
28426
  _BaseStreamController.prototype.onMediaAttached.call(this, event, data);
27569
28427
  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);
28428
+ media.addEventListener('playing', this.onMediaPlaying);
28429
+ media.addEventListener('seeked', this.onMediaSeeked);
27574
28430
  this.gapController = new GapController(this.config, media, this.fragmentTracker, this.hls);
27575
28431
  };
27576
28432
  _proto.onMediaDetaching = function onMediaDetaching() {
27577
28433
  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;
28434
+ if (media) {
28435
+ media.removeEventListener('playing', this.onMediaPlaying);
28436
+ media.removeEventListener('seeked', this.onMediaSeeked);
27582
28437
  this.videoBuffer = null;
27583
28438
  }
27584
28439
  this.fragPlaying = null;
@@ -27588,27 +28443,6 @@
27588
28443
  }
27589
28444
  _BaseStreamController.prototype.onMediaDetaching.call(this);
27590
28445
  };
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
28446
  _proto.onManifestLoading = function onManifestLoading() {
27613
28447
  // reset buffer on manifest loading
27614
28448
  this.log('Trigger BUFFER_RESET');
@@ -27889,8 +28723,10 @@
27889
28723
  }
27890
28724
  if (this.loadedmetadata || !BufferHelper.getBuffered(media).length) {
27891
28725
  // 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);
28726
+ var state = this.state;
28727
+ var activeFrag = state !== State.IDLE ? this.fragCurrent : null;
28728
+ var levelDetails = this.getLevelDetails();
28729
+ gapController.poll(this.lastCurrentTime, activeFrag, levelDetails, state);
27894
28730
  }
27895
28731
  this.lastCurrentTime = media.currentTime;
27896
28732
  };
@@ -28355,9 +29191,12 @@
28355
29191
  * The configuration object provided on player instantiation.
28356
29192
  */
28357
29193
  this.userConfig = void 0;
29194
+ /**
29195
+ * The logger functions used by this player instance, configured on player instantiation.
29196
+ */
29197
+ this.logger = void 0;
28358
29198
  this.coreComponents = void 0;
28359
29199
  this.networkControllers = void 0;
28360
- this.started = false;
28361
29200
  this._emitter = new EventEmitter();
28362
29201
  this._autoLevelCapping = -1;
28363
29202
  this._maxHdcpLevel = null;
@@ -28374,11 +29213,11 @@
28374
29213
  this._media = null;
28375
29214
  this.url = null;
28376
29215
  this.triggeringException = void 0;
28377
- enableLogs(userConfig.debug || false, 'Hls instance');
28378
- var config = this.config = mergeConfig(Hls.DefaultConfig, userConfig);
29216
+ var logger = this.logger = enableLogs(userConfig.debug || false, 'Hls instance');
29217
+ var config = this.config = mergeConfig(Hls.DefaultConfig, userConfig, logger);
28379
29218
  this.userConfig = userConfig;
28380
29219
  if (config.progressive) {
28381
- enableStreamingMode(config);
29220
+ enableStreamingMode(config, logger);
28382
29221
  }
28383
29222
 
28384
29223
  // core controllers and network loaders
@@ -28486,7 +29325,7 @@
28486
29325
  try {
28487
29326
  return this.emit(event, event, eventObject);
28488
29327
  } catch (error) {
28489
- logger.error('An internal error happened while handling event ' + event + '. Error message: "' + error.message + '". Here is a stacktrace:', error);
29328
+ this.logger.error('An internal error happened while handling event ' + event + '. Error message: "' + error.message + '". Here is a stacktrace:', error);
28490
29329
  // Prevent recursion in error event handlers that throw #5497
28491
29330
  if (!this.triggeringException) {
28492
29331
  this.triggeringException = true;
@@ -28512,7 +29351,7 @@
28512
29351
  * Dispose of the instance
28513
29352
  */;
28514
29353
  _proto.destroy = function destroy() {
28515
- logger.log('destroy');
29354
+ this.logger.log('destroy');
28516
29355
  this.trigger(Events.DESTROYING, undefined);
28517
29356
  this.detachMedia();
28518
29357
  this.removeAllListeners();
@@ -28537,7 +29376,7 @@
28537
29376
  * Attaches Hls.js to a media element
28538
29377
  */;
28539
29378
  _proto.attachMedia = function attachMedia(media) {
28540
- logger.log('attachMedia');
29379
+ this.logger.log('attachMedia');
28541
29380
  this._media = media;
28542
29381
  this.trigger(Events.MEDIA_ATTACHING, {
28543
29382
  media: media
@@ -28548,7 +29387,7 @@
28548
29387
  * Detach Hls.js from the media
28549
29388
  */;
28550
29389
  _proto.detachMedia = function detachMedia() {
28551
- logger.log('detachMedia');
29390
+ this.logger.log('detachMedia');
28552
29391
  this.trigger(Events.MEDIA_DETACHING, undefined);
28553
29392
  this._media = null;
28554
29393
  }
@@ -28565,7 +29404,7 @@
28565
29404
  });
28566
29405
  this._autoLevelCapping = -1;
28567
29406
  this._maxHdcpLevel = null;
28568
- logger.log("loadSource:" + loadingSource);
29407
+ this.logger.log("loadSource:" + loadingSource);
28569
29408
  if (media && loadedSource && (loadedSource !== loadingSource || this.bufferController.hasSourceTypes())) {
28570
29409
  this.detachMedia();
28571
29410
  this.attachMedia(media);
@@ -28587,8 +29426,7 @@
28587
29426
  if (startPosition === void 0) {
28588
29427
  startPosition = -1;
28589
29428
  }
28590
- logger.log("startLoad(" + startPosition + ")");
28591
- this.started = true;
29429
+ this.logger.log("startLoad(" + startPosition + ")");
28592
29430
  this.networkControllers.forEach(function (controller) {
28593
29431
  controller.startLoad(startPosition);
28594
29432
  });
@@ -28598,34 +29436,31 @@
28598
29436
  * Stop loading of any stream data.
28599
29437
  */;
28600
29438
  _proto.stopLoad = function stopLoad() {
28601
- logger.log('stopLoad');
28602
- this.started = false;
29439
+ this.logger.log('stopLoad');
28603
29440
  this.networkControllers.forEach(function (controller) {
28604
29441
  controller.stopLoad();
28605
29442
  });
28606
29443
  }
28607
29444
 
28608
29445
  /**
28609
- * Resumes stream controller segment loading if previously started.
29446
+ * Resumes stream controller segment loading after `pauseBuffering` has been called.
28610
29447
  */;
28611
29448
  _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
- }
29449
+ this.networkControllers.forEach(function (controller) {
29450
+ if (controller.resumeBuffering) {
29451
+ controller.resumeBuffering();
29452
+ }
29453
+ });
28619
29454
  }
28620
29455
 
28621
29456
  /**
28622
- * Stops stream controller segment loading without changing 'started' state like stopLoad().
29457
+ * Prevents stream controller from loading new segments until `resumeBuffering` is called.
28623
29458
  * This allows for media buffering to be paused without interupting playlist loading.
28624
29459
  */;
28625
29460
  _proto.pauseBuffering = function pauseBuffering() {
28626
29461
  this.networkControllers.forEach(function (controller) {
28627
- if ('fragmentLoader' in controller) {
28628
- controller.stopLoad();
29462
+ if (controller.pauseBuffering) {
29463
+ controller.pauseBuffering();
28629
29464
  }
28630
29465
  });
28631
29466
  }
@@ -28634,7 +29469,7 @@
28634
29469
  * Swap through possible audio codecs in the stream (for example to switch from stereo to 5.1)
28635
29470
  */;
28636
29471
  _proto.swapAudioCodec = function swapAudioCodec() {
28637
- logger.log('swapAudioCodec');
29472
+ this.logger.log('swapAudioCodec');
28638
29473
  this.streamController.swapAudioCodec();
28639
29474
  }
28640
29475
 
@@ -28645,7 +29480,7 @@
28645
29480
  * Automatic recovery of media-errors by this process is configurable.
28646
29481
  */;
28647
29482
  _proto.recoverMediaError = function recoverMediaError() {
28648
- logger.log('recoverMediaError');
29483
+ this.logger.log('recoverMediaError');
28649
29484
  var media = this._media;
28650
29485
  this.detachMedia();
28651
29486
  if (media) {
@@ -28700,7 +29535,7 @@
28700
29535
  * 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
29536
  */,
28702
29537
  set: function set(newLevel) {
28703
- logger.log("set currentLevel:" + newLevel);
29538
+ this.logger.log("set currentLevel:" + newLevel);
28704
29539
  this.levelController.manualLevel = newLevel;
28705
29540
  this.streamController.immediateLevelSwitch();
28706
29541
  }
@@ -28721,7 +29556,7 @@
28721
29556
  * @param newLevel - Pass -1 for automatic level selection
28722
29557
  */,
28723
29558
  set: function set(newLevel) {
28724
- logger.log("set nextLevel:" + newLevel);
29559
+ this.logger.log("set nextLevel:" + newLevel);
28725
29560
  this.levelController.manualLevel = newLevel;
28726
29561
  this.streamController.nextLevelSwitch();
28727
29562
  }
@@ -28742,7 +29577,7 @@
28742
29577
  * @param newLevel - Pass -1 for automatic level selection
28743
29578
  */,
28744
29579
  set: function set(newLevel) {
28745
- logger.log("set loadLevel:" + newLevel);
29580
+ this.logger.log("set loadLevel:" + newLevel);
28746
29581
  this.levelController.manualLevel = newLevel;
28747
29582
  }
28748
29583
 
@@ -28777,7 +29612,7 @@
28777
29612
  * Sets "first-level", see getter.
28778
29613
  */,
28779
29614
  set: function set(newLevel) {
28780
- logger.log("set firstLevel:" + newLevel);
29615
+ this.logger.log("set firstLevel:" + newLevel);
28781
29616
  this.levelController.firstLevel = newLevel;
28782
29617
  }
28783
29618
 
@@ -28804,7 +29639,7 @@
28804
29639
  * (determined from download of first segment)
28805
29640
  */,
28806
29641
  set: function set(newLevel) {
28807
- logger.log("set startLevel:" + newLevel);
29642
+ this.logger.log("set startLevel:" + newLevel);
28808
29643
  // if not in automatic start level detection, ensure startLevel is greater than minAutoLevel
28809
29644
  if (newLevel !== -1) {
28810
29645
  newLevel = Math.max(newLevel, this.minAutoLevel);
@@ -28857,7 +29692,7 @@
28857
29692
  */
28858
29693
  function set(newLevel) {
28859
29694
  if (this._autoLevelCapping !== newLevel) {
28860
- logger.log("set autoLevelCapping:" + newLevel);
29695
+ this.logger.log("set autoLevelCapping:" + newLevel);
28861
29696
  this._autoLevelCapping = newLevel;
28862
29697
  this.levelController.checkMaxAutoUpdated();
28863
29698
  }
@@ -29182,7 +30017,7 @@
29182
30017
  * Get the video-dev/hls.js package version.
29183
30018
  */
29184
30019
  function get() {
29185
- return "1.5.4";
30020
+ return "1.5.5-0.canary.9977";
29186
30021
  }
29187
30022
  }, {
29188
30023
  key: "Events",