hls.js 1.5.6-0.canary.10011 → 1.5.6

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 (68) hide show
  1. package/README.md +0 -1
  2. package/dist/hls-demo.js +0 -10
  3. package/dist/hls-demo.js.map +1 -1
  4. package/dist/hls.js +1134 -2043
  5. package/dist/hls.js.d.ts +50 -65
  6. package/dist/hls.js.map +1 -1
  7. package/dist/hls.light.js +852 -1141
  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 +686 -974
  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 +847 -1741
  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 +21 -21
  20. package/src/config.ts +2 -3
  21. package/src/controller/abr-controller.ts +20 -21
  22. package/src/controller/audio-stream-controller.ts +16 -15
  23. package/src/controller/audio-track-controller.ts +1 -1
  24. package/src/controller/base-playlist-controller.ts +8 -20
  25. package/src/controller/base-stream-controller.ts +33 -149
  26. package/src/controller/buffer-controller.ts +11 -11
  27. package/src/controller/cap-level-controller.ts +2 -1
  28. package/src/controller/cmcd-controller.ts +6 -27
  29. package/src/controller/content-steering-controller.ts +6 -8
  30. package/src/controller/eme-controller.ts +22 -9
  31. package/src/controller/error-controller.ts +8 -6
  32. package/src/controller/fps-controller.ts +3 -2
  33. package/src/controller/gap-controller.ts +16 -43
  34. package/src/controller/latency-controller.ts +11 -9
  35. package/src/controller/level-controller.ts +18 -12
  36. package/src/controller/stream-controller.ts +32 -25
  37. package/src/controller/subtitle-stream-controller.ts +14 -13
  38. package/src/controller/subtitle-track-controller.ts +3 -5
  39. package/src/controller/timeline-controller.ts +30 -23
  40. package/src/crypt/aes-crypto.ts +2 -21
  41. package/src/crypt/decrypter.ts +18 -32
  42. package/src/crypt/fast-aes-key.ts +5 -24
  43. package/src/demux/audio/adts.ts +4 -9
  44. package/src/demux/sample-aes.ts +0 -2
  45. package/src/demux/transmuxer-interface.ts +12 -4
  46. package/src/demux/transmuxer-worker.ts +4 -4
  47. package/src/demux/transmuxer.ts +3 -16
  48. package/src/demux/tsdemuxer.ts +37 -71
  49. package/src/demux/video/avc-video-parser.ts +119 -208
  50. package/src/demux/video/base-video-parser.ts +2 -134
  51. package/src/demux/video/exp-golomb.ts +208 -0
  52. package/src/events.ts +0 -7
  53. package/src/hls.ts +34 -42
  54. package/src/loader/fragment-loader.ts +2 -9
  55. package/src/loader/key-loader.ts +0 -2
  56. package/src/loader/level-key.ts +9 -10
  57. package/src/loader/playlist-loader.ts +5 -4
  58. package/src/remux/mp4-generator.ts +1 -196
  59. package/src/remux/mp4-remuxer.ts +7 -23
  60. package/src/task-loop.ts +2 -5
  61. package/src/types/component-api.ts +0 -2
  62. package/src/types/demuxer.ts +0 -3
  63. package/src/types/events.ts +0 -4
  64. package/src/utils/codecs.ts +4 -33
  65. package/src/utils/logger.ts +24 -54
  66. package/src/crypt/decrypter-aes-mode.ts +0 -4
  67. package/src/demux/video/hevc-video-parser.ts +0 -746
  68. package/src/utils/encryption-methods-util.ts +0 -21
package/dist/hls.js CHANGED
@@ -5,21 +5,6 @@
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
- }
23
8
  function ownKeys(e, r) {
24
9
  var t = Object.keys(e);
25
10
  if (Object.getOwnPropertySymbols) {
@@ -118,6 +103,32 @@
118
103
  };
119
104
  return _setPrototypeOf(o, p);
120
105
  }
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
+ }
121
132
  function _isNativeFunction(fn) {
122
133
  try {
123
134
  return Function.toString.call(fn).indexOf("[native code]") !== -1;
@@ -383,7 +394,6 @@
383
394
  Events["MEDIA_ATTACHED"] = "hlsMediaAttached";
384
395
  Events["MEDIA_DETACHING"] = "hlsMediaDetaching";
385
396
  Events["MEDIA_DETACHED"] = "hlsMediaDetached";
386
- Events["MEDIA_ENDED"] = "hlsMediaEnded";
387
397
  Events["BUFFER_RESET"] = "hlsBufferReset";
388
398
  Events["BUFFER_CODECS"] = "hlsBufferCodecs";
389
399
  Events["BUFFER_CREATED"] = "hlsBufferCreated";
@@ -497,6 +507,61 @@
497
507
  return ErrorDetails;
498
508
  }({});
499
509
 
510
+ var noop = function noop() {};
511
+ var fakeLogger = {
512
+ trace: noop,
513
+ debug: noop,
514
+ log: noop,
515
+ warn: noop,
516
+ info: noop,
517
+ error: noop
518
+ };
519
+ var exportedLogger = fakeLogger;
520
+
521
+ // let lastCallTime;
522
+ // function formatMsgWithTimeInfo(type, msg) {
523
+ // const now = Date.now();
524
+ // const diff = lastCallTime ? '+' + (now - lastCallTime) : '0';
525
+ // lastCallTime = now;
526
+ // msg = (new Date(now)).toISOString() + ' | [' + type + '] > ' + msg + ' ( ' + diff + ' ms )';
527
+ // return msg;
528
+ // }
529
+
530
+ function consolePrintFn(type) {
531
+ var func = self.console[type];
532
+ if (func) {
533
+ return func.bind(self.console, "[" + type + "] >");
534
+ }
535
+ return noop;
536
+ }
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
+ });
544
+ }
545
+ function enableLogs(debugConfig, id) {
546
+ // check that console is available
547
+ if (typeof console === 'object' && debugConfig === true || typeof debugConfig === 'object') {
548
+ exportLoggerFunctions(debugConfig,
549
+ // Remove out from list here to hard-disable a log-level
550
+ // 'trace',
551
+ 'debug', 'log', 'info', 'warn', 'error');
552
+ // Some browsers don't allow to use bind on console object anyway
553
+ // fallback to default if needed
554
+ try {
555
+ exportedLogger.log("Debug logs enabled for \"" + id + "\" in hls.js version " + "1.5.6");
556
+ } catch (e) {
557
+ exportedLogger = fakeLogger;
558
+ }
559
+ } else {
560
+ exportedLogger = fakeLogger;
561
+ }
562
+ }
563
+ var logger = exportedLogger;
564
+
500
565
  var DECIMAL_RESOLUTION_REGEX = /^(\d+)x(\d+)$/;
501
566
  var ATTR_LIST_REGEX = /(.+?)=(".*?"|.*?)(?:,|$)/g;
502
567
 
@@ -585,77 +650,6 @@
585
650
  return AttrList;
586
651
  }();
587
652
 
588
- var Logger = function Logger(label, logger) {
589
- this.trace = void 0;
590
- this.debug = void 0;
591
- this.log = void 0;
592
- this.warn = void 0;
593
- this.info = void 0;
594
- this.error = void 0;
595
- var lb = "[" + label + "]:";
596
- this.trace = noop;
597
- this.debug = logger.debug.bind(null, lb);
598
- this.log = logger.log.bind(null, lb);
599
- this.warn = logger.warn.bind(null, lb);
600
- this.info = logger.info.bind(null, lb);
601
- this.error = logger.error.bind(null, lb);
602
- };
603
- var noop = function noop() {};
604
- var fakeLogger = {
605
- trace: noop,
606
- debug: noop,
607
- log: noop,
608
- warn: noop,
609
- info: noop,
610
- error: noop
611
- };
612
- function createLogger() {
613
- return _extends({}, fakeLogger);
614
- }
615
-
616
- // let lastCallTime;
617
- // function formatMsgWithTimeInfo(type, msg) {
618
- // const now = Date.now();
619
- // const diff = lastCallTime ? '+' + (now - lastCallTime) : '0';
620
- // lastCallTime = now;
621
- // msg = (new Date(now)).toISOString() + ' | [' + type + '] > ' + msg + ' ( ' + diff + ' ms )';
622
- // return msg;
623
- // }
624
-
625
- function consolePrintFn(type, id) {
626
- var func = self.console[type];
627
- return func ? func.bind(self.console, (id ? '[' + id + '] ' : '') + "[" + type + "] >") : noop;
628
- }
629
- function getLoggerFn(key, debugConfig, id) {
630
- return debugConfig[key] ? debugConfig[key].bind(debugConfig) : consolePrintFn(key, id);
631
- }
632
- var exportedLogger = createLogger();
633
- function enableLogs(debugConfig, context, id) {
634
- // check that console is available
635
- var newLogger = createLogger();
636
- if (typeof console === 'object' && debugConfig === true || typeof debugConfig === 'object') {
637
- var keys = [
638
- // Remove out from list here to hard-disable a log-level
639
- // 'trace',
640
- 'debug', 'log', 'info', 'warn', 'error'];
641
- keys.forEach(function (key) {
642
- newLogger[key] = getLoggerFn(key, debugConfig, id);
643
- });
644
- // Some browsers don't allow to use bind on console object anyway
645
- // fallback to default if needed
646
- try {
647
- newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.6-0.canary.10011");
648
- } catch (e) {
649
- /* log fn threw an exception. All logger methods are no-ops. */
650
- return createLogger();
651
- }
652
- }
653
- // global exported logger uses the log methods from last call to `enableLogs`
654
- _extends(exportedLogger, newLogger);
655
- return newLogger;
656
- }
657
- var logger = exportedLogger;
658
-
659
653
  // Avoid exporting const enum so that these values can be inlined
660
654
 
661
655
  function isDateRangeCueAttribute(attrName) {
@@ -1259,26 +1253,6 @@
1259
1253
  });
1260
1254
  }
1261
1255
 
1262
- var DecrypterAesMode = {
1263
- cbc: 0,
1264
- ctr: 1
1265
- };
1266
-
1267
- function isFullSegmentEncryption(method) {
1268
- return method === 'AES-128' || method === 'AES-256' || method === 'AES-256-CTR';
1269
- }
1270
- function getAesModeFromFullSegmentMethod(method) {
1271
- switch (method) {
1272
- case 'AES-128':
1273
- case 'AES-256':
1274
- return DecrypterAesMode.cbc;
1275
- case 'AES-256-CTR':
1276
- return DecrypterAesMode.ctr;
1277
- default:
1278
- throw new Error("invalid full segment method " + method);
1279
- }
1280
- }
1281
-
1282
1256
  /** returns `undefined` is `self` is missing, e.g. in node */
1283
1257
  var optionalSelf = typeof self !== 'undefined' ? self : undefined;
1284
1258
 
@@ -2951,13 +2925,13 @@
2951
2925
  this.keyFormatVersions = formatversions;
2952
2926
  this.iv = iv;
2953
2927
  this.encrypted = method ? method !== 'NONE' : false;
2954
- this.isCommonEncryption = this.encrypted && !isFullSegmentEncryption(method);
2928
+ this.isCommonEncryption = this.encrypted && method !== 'AES-128';
2955
2929
  }
2956
2930
  var _proto = LevelKey.prototype;
2957
2931
  _proto.isSupported = function isSupported() {
2958
2932
  // If it's Segment encryption or No encryption, just select that key system
2959
2933
  if (this.method) {
2960
- if (isFullSegmentEncryption(this.method) || this.method === 'NONE') {
2934
+ if (this.method === 'AES-128' || this.method === 'NONE') {
2961
2935
  return true;
2962
2936
  }
2963
2937
  if (this.keyFormat === 'identity') {
@@ -2979,13 +2953,14 @@
2979
2953
  if (!this.encrypted || !this.uri) {
2980
2954
  return null;
2981
2955
  }
2982
- if (isFullSegmentEncryption(this.method) && this.uri && !this.iv) {
2956
+ if (this.method === 'AES-128' && this.uri && !this.iv) {
2983
2957
  if (typeof sn !== 'number') {
2984
2958
  // We are fetching decryption data for a initialization segment
2985
- // If the segment was encrypted with AES-128/256
2959
+ // If the segment was encrypted with AES-128
2986
2960
  // It must have an IV defined. We cannot substitute the Segment Number in.
2987
- logger.warn("missing IV for initialization segment with method=\"" + this.method + "\" - compliance issue");
2988
-
2961
+ if (this.method === 'AES-128' && !this.iv) {
2962
+ logger.warn("missing IV for initialization segment with method=\"" + this.method + "\" - compliance issue");
2963
+ }
2989
2964
  // Explicitly set sn to resulting value from implicit conversions 'initSegment' values for IV generation.
2990
2965
  sn = 0;
2991
2966
  }
@@ -3279,28 +3254,23 @@
3279
3254
  if (CODEC_COMPATIBLE_NAMES[lowerCaseCodec]) {
3280
3255
  return CODEC_COMPATIBLE_NAMES[lowerCaseCodec];
3281
3256
  }
3257
+
3258
+ // Idealy fLaC and Opus would be first (spec-compliant) but
3259
+ // some browsers will report that fLaC is supported then fail.
3260
+ // see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
3282
3261
  var codecsToCheck = {
3283
- // Idealy fLaC and Opus would be first (spec-compliant) but
3284
- // some browsers will report that fLaC is supported then fail.
3285
- // see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
3286
3262
  flac: ['flac', 'fLaC', 'FLAC'],
3287
- opus: ['opus', 'Opus'],
3288
- // Replace audio codec info if browser does not support mp4a.40.34,
3289
- // and demuxer can fallback to 'audio/mpeg' or 'audio/mp4;codecs="mp3"'
3290
- 'mp4a.40.34': ['mp3']
3263
+ opus: ['opus', 'Opus']
3291
3264
  }[lowerCaseCodec];
3292
3265
  for (var i = 0; i < codecsToCheck.length; i++) {
3293
- var _getMediaSource;
3294
3266
  if (isCodecMediaSourceSupported(codecsToCheck[i], 'audio', preferManagedMediaSource)) {
3295
3267
  CODEC_COMPATIBLE_NAMES[lowerCaseCodec] = codecsToCheck[i];
3296
3268
  return codecsToCheck[i];
3297
- } else if (codecsToCheck[i] === 'mp3' && (_getMediaSource = getMediaSource(preferManagedMediaSource)) != null && _getMediaSource.isTypeSupported('audio/mpeg')) {
3298
- return '';
3299
3269
  }
3300
3270
  }
3301
3271
  return lowerCaseCodec;
3302
3272
  }
3303
- var AUDIO_CODEC_REGEXP = /flac|opus|mp4a\.40\.34/i;
3273
+ var AUDIO_CODEC_REGEXP = /flac|opus/i;
3304
3274
  function getCodecCompatibleName(codec, preferManagedMediaSource) {
3305
3275
  if (preferManagedMediaSource === void 0) {
3306
3276
  preferManagedMediaSource = true;
@@ -3328,18 +3298,6 @@
3328
3298
  }
3329
3299
  return codec;
3330
3300
  }
3331
- function getM2TSSupportedAudioTypes(preferManagedMediaSource) {
3332
- var MediaSource = getMediaSource(preferManagedMediaSource) || {
3333
- isTypeSupported: function isTypeSupported() {
3334
- return false;
3335
- }
3336
- };
3337
- return {
3338
- mpeg: MediaSource.isTypeSupported('audio/mpeg'),
3339
- mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
3340
- ac3: MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"')
3341
- };
3342
- }
3343
3301
 
3344
3302
  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;
3345
3303
  var MASTER_PLAYLIST_MEDIA_REGEX = /#EXT-X-MEDIA:(.*)/g;
@@ -4189,10 +4147,10 @@
4189
4147
  var loaderContext = loader.context;
4190
4148
  if (loaderContext && loaderContext.url === context.url && loaderContext.level === context.level) {
4191
4149
  // same URL can't overlap
4192
- this.hls.logger.trace('[playlist-loader]: playlist request ongoing');
4150
+ logger.trace('[playlist-loader]: playlist request ongoing');
4193
4151
  return;
4194
4152
  }
4195
- this.hls.logger.log("[playlist-loader]: aborting previous loader for type: " + context.type);
4153
+ logger.log("[playlist-loader]: aborting previous loader for type: " + context.type);
4196
4154
  loader.abort();
4197
4155
  }
4198
4156
 
@@ -4302,7 +4260,7 @@
4302
4260
  // alt audio rendition in which quality levels (main)
4303
4261
  // contains both audio+video. but with mixed audio track not signaled
4304
4262
  if (!embeddedAudioFound && levels[0].audioCodec && !levels[0].attrs.AUDIO) {
4305
- this.hls.logger.log('[playlist-loader]: audio codec signaled in quality level, but no embedded audio track signaled, create one');
4263
+ logger.log('[playlist-loader]: audio codec signaled in quality level, but no embedded audio track signaled, create one');
4306
4264
  audioTracks.unshift({
4307
4265
  type: 'main',
4308
4266
  name: 'main',
@@ -4402,7 +4360,7 @@
4402
4360
  message += " id: " + context.id + " group-id: \"" + context.groupId + "\"";
4403
4361
  }
4404
4362
  var error = new Error(message);
4405
- this.hls.logger.warn("[playlist-loader]: " + message);
4363
+ logger.warn("[playlist-loader]: " + message);
4406
4364
  var details = ErrorDetails.UNKNOWN;
4407
4365
  var fatal = false;
4408
4366
  var loader = this.getInternalLoader(context);
@@ -5003,43 +4961,8 @@
5003
4961
  this.currentTime = 0;
5004
4962
  this.stallCount = 0;
5005
4963
  this._latency = null;
5006
- this.onTimeupdate = function () {
5007
- var media = _this.media,
5008
- levelDetails = _this.levelDetails;
5009
- if (!media || !levelDetails) {
5010
- return;
5011
- }
5012
- _this.currentTime = media.currentTime;
5013
- var latency = _this.computeLatency();
5014
- if (latency === null) {
5015
- return;
5016
- }
5017
- _this._latency = latency;
5018
-
5019
- // Adapt playbackRate to meet target latency in low-latency mode
5020
- var _this$config = _this.config,
5021
- lowLatencyMode = _this$config.lowLatencyMode,
5022
- maxLiveSyncPlaybackRate = _this$config.maxLiveSyncPlaybackRate;
5023
- if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1 || !levelDetails.live) {
5024
- return;
5025
- }
5026
- var targetLatency = _this.targetLatency;
5027
- if (targetLatency === null) {
5028
- return;
5029
- }
5030
- var distanceFromTarget = latency - targetLatency;
5031
- // Only adjust playbackRate when within one target duration of targetLatency
5032
- // and more than one second from under-buffering.
5033
- // Playback further than one target duration from target can be considered DVR playback.
5034
- var liveMinLatencyDuration = Math.min(_this.maxLatency, targetLatency + levelDetails.targetduration);
5035
- var inLiveRange = distanceFromTarget < liveMinLatencyDuration;
5036
- if (inLiveRange && distanceFromTarget > 0.05 && _this.forwardBufferLength > 1) {
5037
- var max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));
5038
- var rate = Math.round(2 / (1 + Math.exp(-0.75 * distanceFromTarget - _this.edgeStalled)) * 20) / 20;
5039
- media.playbackRate = Math.min(max, Math.max(1, rate));
5040
- } else if (media.playbackRate !== 1 && media.playbackRate !== 0) {
5041
- media.playbackRate = 1;
5042
- }
4964
+ this.timeupdateHandler = function () {
4965
+ return _this.timeupdate();
5043
4966
  };
5044
4967
  this.hls = hls;
5045
4968
  this.config = hls.config;
@@ -5051,7 +4974,7 @@
5051
4974
  this.onMediaDetaching();
5052
4975
  this.levelDetails = null;
5053
4976
  // @ts-ignore
5054
- this.hls = null;
4977
+ this.hls = this.timeupdateHandler = null;
5055
4978
  };
5056
4979
  _proto.registerListeners = function registerListeners() {
5057
4980
  this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
@@ -5069,11 +4992,11 @@
5069
4992
  };
5070
4993
  _proto.onMediaAttached = function onMediaAttached(event, data) {
5071
4994
  this.media = data.media;
5072
- this.media.addEventListener('timeupdate', this.onTimeupdate);
4995
+ this.media.addEventListener('timeupdate', this.timeupdateHandler);
5073
4996
  };
5074
4997
  _proto.onMediaDetaching = function onMediaDetaching() {
5075
4998
  if (this.media) {
5076
- this.media.removeEventListener('timeupdate', this.onTimeupdate);
4999
+ this.media.removeEventListener('timeupdate', this.timeupdateHandler);
5077
5000
  this.media = null;
5078
5001
  }
5079
5002
  };
@@ -5086,10 +5009,10 @@
5086
5009
  var details = _ref.details;
5087
5010
  this.levelDetails = details;
5088
5011
  if (details.advanced) {
5089
- this.onTimeupdate();
5012
+ this.timeupdate();
5090
5013
  }
5091
5014
  if (!details.live && this.media) {
5092
- this.media.removeEventListener('timeupdate', this.onTimeupdate);
5015
+ this.media.removeEventListener('timeupdate', this.timeupdateHandler);
5093
5016
  }
5094
5017
  };
5095
5018
  _proto.onError = function onError(event, data) {
@@ -5099,7 +5022,45 @@
5099
5022
  }
5100
5023
  this.stallCount++;
5101
5024
  if ((_this$levelDetails = this.levelDetails) != null && _this$levelDetails.live) {
5102
- this.hls.logger.warn('[latency-controller]: Stall detected, adjusting target latency');
5025
+ logger.warn('[playback-rate-controller]: Stall detected, adjusting target latency');
5026
+ }
5027
+ };
5028
+ _proto.timeupdate = function timeupdate() {
5029
+ var media = this.media,
5030
+ levelDetails = this.levelDetails;
5031
+ if (!media || !levelDetails) {
5032
+ return;
5033
+ }
5034
+ this.currentTime = media.currentTime;
5035
+ var latency = this.computeLatency();
5036
+ if (latency === null) {
5037
+ return;
5038
+ }
5039
+ this._latency = latency;
5040
+
5041
+ // Adapt playbackRate to meet target latency in low-latency mode
5042
+ var _this$config = this.config,
5043
+ lowLatencyMode = _this$config.lowLatencyMode,
5044
+ maxLiveSyncPlaybackRate = _this$config.maxLiveSyncPlaybackRate;
5045
+ if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1 || !levelDetails.live) {
5046
+ return;
5047
+ }
5048
+ var targetLatency = this.targetLatency;
5049
+ if (targetLatency === null) {
5050
+ return;
5051
+ }
5052
+ var distanceFromTarget = latency - targetLatency;
5053
+ // Only adjust playbackRate when within one target duration of targetLatency
5054
+ // and more than one second from under-buffering.
5055
+ // Playback further than one target duration from target can be considered DVR playback.
5056
+ var liveMinLatencyDuration = Math.min(this.maxLatency, targetLatency + levelDetails.targetduration);
5057
+ var inLiveRange = distanceFromTarget < liveMinLatencyDuration;
5058
+ if (inLiveRange && distanceFromTarget > 0.05 && this.forwardBufferLength > 1) {
5059
+ var max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));
5060
+ var rate = Math.round(2 / (1 + Math.exp(-0.75 * distanceFromTarget - this.edgeStalled)) * 20) / 20;
5061
+ media.playbackRate = Math.min(max, Math.max(1, rate));
5062
+ } else if (media.playbackRate !== 1 && media.playbackRate !== 0) {
5063
+ media.playbackRate = 1;
5103
5064
  }
5104
5065
  };
5105
5066
  _proto.estimateLiveEdge = function estimateLiveEdge() {
@@ -6007,17 +5968,19 @@
6007
5968
  MoveAllAlternatesMatchingHDCP: 2,
6008
5969
  SwitchToSDR: 4
6009
5970
  }; // Reserved for future use
6010
- var ErrorController = /*#__PURE__*/function (_Logger) {
6011
- _inheritsLoose(ErrorController, _Logger);
5971
+ var ErrorController = /*#__PURE__*/function () {
6012
5972
  function ErrorController(hls) {
6013
- var _this;
6014
- _this = _Logger.call(this, 'error-controller', hls.logger) || this;
6015
- _this.hls = void 0;
6016
- _this.playlistError = 0;
6017
- _this.penalizedRenditions = {};
6018
- _this.hls = hls;
6019
- _this.registerListeners();
6020
- return _this;
5973
+ this.hls = void 0;
5974
+ this.playlistError = 0;
5975
+ this.penalizedRenditions = {};
5976
+ this.log = void 0;
5977
+ this.warn = void 0;
5978
+ this.error = void 0;
5979
+ this.hls = hls;
5980
+ this.log = logger.log.bind(logger, "[info]:");
5981
+ this.warn = logger.warn.bind(logger, "[warning]:");
5982
+ this.error = logger.error.bind(logger, "[error]:");
5983
+ this.registerListeners();
6021
5984
  }
6022
5985
  var _proto = ErrorController.prototype;
6023
5986
  _proto.registerListeners = function registerListeners() {
@@ -6373,19 +6336,19 @@
6373
6336
  }
6374
6337
  };
6375
6338
  return ErrorController;
6376
- }(Logger);
6339
+ }();
6377
6340
 
6378
- var BasePlaylistController = /*#__PURE__*/function (_Logger) {
6379
- _inheritsLoose(BasePlaylistController, _Logger);
6341
+ var BasePlaylistController = /*#__PURE__*/function () {
6380
6342
  function BasePlaylistController(hls, logPrefix) {
6381
- var _this;
6382
- _this = _Logger.call(this, logPrefix, hls.logger) || this;
6383
- _this.hls = void 0;
6384
- _this.timer = -1;
6385
- _this.requestScheduled = -1;
6386
- _this.canLoad = false;
6387
- _this.hls = hls;
6388
- return _this;
6343
+ this.hls = void 0;
6344
+ this.timer = -1;
6345
+ this.requestScheduled = -1;
6346
+ this.canLoad = false;
6347
+ this.log = void 0;
6348
+ this.warn = void 0;
6349
+ this.log = logger.log.bind(logger, logPrefix + ":");
6350
+ this.warn = logger.warn.bind(logger, logPrefix + ":");
6351
+ this.hls = hls;
6389
6352
  }
6390
6353
  var _proto = BasePlaylistController.prototype;
6391
6354
  _proto.destroy = function destroy() {
@@ -6418,7 +6381,7 @@
6418
6381
  try {
6419
6382
  uri = new self.URL(attr.URI, previous.url).href;
6420
6383
  } catch (error) {
6421
- this.warn("Could not construct new URL for Rendition Report: " + error);
6384
+ logger.warn("Could not construct new URL for Rendition Report: " + error);
6422
6385
  uri = attr.URI || '';
6423
6386
  }
6424
6387
  // Use exact match. Otherwise, the last partial match, if any, will be used
@@ -6457,7 +6420,7 @@
6457
6420
  return this.timer === -1 && this.requestScheduled === -1 && this.shouldLoadPlaylist(playlist);
6458
6421
  };
6459
6422
  _proto.playlistLoaded = function playlistLoaded(index, data, previousDetails) {
6460
- var _this2 = this;
6423
+ var _this = this;
6461
6424
  var details = data.details,
6462
6425
  stats = data.stats;
6463
6426
 
@@ -6504,12 +6467,7 @@
6504
6467
  var cdnAge = lastAdvanced + details.ageHeader;
6505
6468
  var currentGoal = Math.min(cdnAge - details.partTarget, details.targetduration * 1.5);
6506
6469
  if (currentGoal > 0) {
6507
- if (cdnAge > details.targetduration * 3) {
6508
- // Omit segment and part directives when the last response was more than 3 target durations ago,
6509
- this.log("Playlist last advanced " + lastAdvanced.toFixed(2) + "s ago. Omitting segment and part directives.");
6510
- msn = undefined;
6511
- part = undefined;
6512
- } else if (previousDetails != null && previousDetails.tuneInGoal && cdnAge - details.partTarget > previousDetails.tuneInGoal) {
6470
+ if (previousDetails && currentGoal > previousDetails.tuneInGoal) {
6513
6471
  // If we attempted to get the next or latest playlist update, but currentGoal increased,
6514
6472
  // then we either can't catchup, or the "age" header cannot be trusted.
6515
6473
  this.warn("CDN Tune-in goal increased from: " + previousDetails.tuneInGoal + " to: " + currentGoal + " with playlist age: " + details.age);
@@ -6567,7 +6525,7 @@
6567
6525
  // );
6568
6526
 
6569
6527
  this.timer = self.setTimeout(function () {
6570
- return _this2.loadPlaylist(deliveryDirectives);
6528
+ return _this.loadPlaylist(deliveryDirectives);
6571
6529
  }, estimatedTimeUntilUpdate);
6572
6530
  } else {
6573
6531
  this.clearTimer();
@@ -6583,7 +6541,7 @@
6583
6541
  return new HlsUrlParameters(msn, part, skip);
6584
6542
  };
6585
6543
  _proto.checkRetry = function checkRetry(errorEvent) {
6586
- var _this3 = this;
6544
+ var _this2 = this;
6587
6545
  var errorDetails = errorEvent.details;
6588
6546
  var isTimeout = isTimeoutError(errorEvent);
6589
6547
  var errorAction = errorEvent.errorAction;
@@ -6607,7 +6565,7 @@
6607
6565
  var delay = getRetryDelay(retryConfig, retryCount);
6608
6566
  // Schedule level/track reload
6609
6567
  this.timer = self.setTimeout(function () {
6610
- return _this3.loadPlaylist();
6568
+ return _this2.loadPlaylist();
6611
6569
  }, delay);
6612
6570
  this.warn("Retrying playlist loading " + (retryCount + 1) + "/" + retryConfig.maxNumRetry + " after \"" + errorDetails + "\" in " + delay + "ms");
6613
6571
  }
@@ -6618,7 +6576,7 @@
6618
6576
  return retry;
6619
6577
  };
6620
6578
  return BasePlaylistController;
6621
- }(Logger);
6579
+ }();
6622
6580
 
6623
6581
  /*
6624
6582
  * compute an Exponential Weighted moving average
@@ -7220,33 +7178,30 @@
7220
7178
  return -1;
7221
7179
  }
7222
7180
 
7223
- var AbrController = /*#__PURE__*/function (_Logger) {
7224
- _inheritsLoose(AbrController, _Logger);
7181
+ var AbrController = /*#__PURE__*/function () {
7225
7182
  function AbrController(_hls) {
7226
- var _this;
7227
- _this = _Logger.call(this, 'abr', _hls.logger) || this;
7228
- _this.hls = void 0;
7229
- _this.lastLevelLoadSec = 0;
7230
- _this.lastLoadedFragLevel = -1;
7231
- _this.firstSelection = -1;
7232
- _this._nextAutoLevel = -1;
7233
- _this.nextAutoLevelKey = '';
7234
- _this.audioTracksByGroup = null;
7235
- _this.codecTiers = null;
7236
- _this.timer = -1;
7237
- _this.fragCurrent = null;
7238
- _this.partCurrent = null;
7239
- _this.bitrateTestDelay = 0;
7240
- _this.bwEstimator = void 0;
7183
+ var _this = this;
7184
+ this.hls = void 0;
7185
+ this.lastLevelLoadSec = 0;
7186
+ this.lastLoadedFragLevel = -1;
7187
+ this.firstSelection = -1;
7188
+ this._nextAutoLevel = -1;
7189
+ this.nextAutoLevelKey = '';
7190
+ this.audioTracksByGroup = null;
7191
+ this.codecTiers = null;
7192
+ this.timer = -1;
7193
+ this.fragCurrent = null;
7194
+ this.partCurrent = null;
7195
+ this.bitrateTestDelay = 0;
7196
+ this.bwEstimator = void 0;
7241
7197
  /*
7242
7198
  This method monitors the download rate of the current fragment, and will downswitch if that fragment will not load
7243
7199
  quickly enough to prevent underbuffering
7244
7200
  */
7245
- _this._abandonRulesCheck = function () {
7246
- var _assertThisInitialize = _assertThisInitialized(_this),
7247
- frag = _assertThisInitialize.fragCurrent,
7248
- part = _assertThisInitialize.partCurrent,
7249
- hls = _assertThisInitialize.hls;
7201
+ this._abandonRulesCheck = function () {
7202
+ var frag = _this.fragCurrent,
7203
+ part = _this.partCurrent,
7204
+ hls = _this.hls;
7250
7205
  var autoLevelEnabled = hls.autoLevelEnabled,
7251
7206
  media = hls.media;
7252
7207
  if (!frag || !media) {
@@ -7335,22 +7290,21 @@
7335
7290
  _this.resetEstimator(nextLoadLevelBitrate);
7336
7291
  }
7337
7292
  _this.clearTimer();
7338
- _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");
7293
+ 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");
7339
7294
  hls.trigger(Events.FRAG_LOAD_EMERGENCY_ABORTED, {
7340
7295
  frag: frag,
7341
7296
  part: part,
7342
7297
  stats: stats
7343
7298
  });
7344
7299
  };
7345
- _this.hls = _hls;
7346
- _this.bwEstimator = _this.initEstimator();
7347
- _this.registerListeners();
7348
- return _this;
7300
+ this.hls = _hls;
7301
+ this.bwEstimator = this.initEstimator();
7302
+ this.registerListeners();
7349
7303
  }
7350
7304
  var _proto = AbrController.prototype;
7351
7305
  _proto.resetEstimator = function resetEstimator(abrEwmaDefaultEstimate) {
7352
7306
  if (abrEwmaDefaultEstimate) {
7353
- this.log("setting initial bwe to " + abrEwmaDefaultEstimate);
7307
+ logger.log("setting initial bwe to " + abrEwmaDefaultEstimate);
7354
7308
  this.hls.config.abrEwmaDefaultEstimate = abrEwmaDefaultEstimate;
7355
7309
  }
7356
7310
  this.firstSelection = -1;
@@ -7595,13 +7549,13 @@
7595
7549
  // cap maxLoadingDelay and ensure it is not bigger 'than bitrate test' frag duration
7596
7550
  var maxLoadingDelay = currentFragDuration ? Math.min(currentFragDuration, config.maxLoadingDelay) : config.maxLoadingDelay;
7597
7551
  maxStarvationDelay = maxLoadingDelay - bitrateTestDelay;
7598
- this.info("bitrate test took " + Math.round(1000 * bitrateTestDelay) + "ms, set first fragment max fetchDuration to " + Math.round(1000 * maxStarvationDelay) + " ms");
7552
+ logger.info("[abr] bitrate test took " + Math.round(1000 * bitrateTestDelay) + "ms, set first fragment max fetchDuration to " + Math.round(1000 * maxStarvationDelay) + " ms");
7599
7553
  // don't use conservative factor on bitrate test
7600
7554
  bwFactor = bwUpFactor = 1;
7601
7555
  }
7602
7556
  }
7603
7557
  var bestLevel = this.findBestLevel(avgbw, minAutoLevel, maxAutoLevel, bufferStarvationDelay, maxStarvationDelay, bwFactor, bwUpFactor);
7604
- this.info((bufferStarvationDelay ? 'rebuffering expected' : 'buffer is empty') + ", optimal quality level " + bestLevel);
7558
+ logger.info("[abr] " + (bufferStarvationDelay ? 'rebuffering expected' : 'buffer is empty') + ", optimal quality level " + bestLevel);
7605
7559
  if (bestLevel > -1) {
7606
7560
  return bestLevel;
7607
7561
  }
@@ -7669,7 +7623,7 @@
7669
7623
  currentVideoRange = preferHDR ? videoRanges[videoRanges.length - 1] : videoRanges[0];
7670
7624
  currentFrameRate = minFramerate;
7671
7625
  currentBw = Math.max(currentBw, minBitrate);
7672
- this.log("picked start tier " + JSON.stringify(startTier));
7626
+ logger.log("[abr] picked start tier " + JSON.stringify(startTier));
7673
7627
  } else {
7674
7628
  currentCodecSet = level == null ? void 0 : level.codecSet;
7675
7629
  currentVideoRange = level == null ? void 0 : level.videoRange;
@@ -7696,11 +7650,11 @@
7696
7650
  var levels = _this2.hls.levels;
7697
7651
  var index = levels.indexOf(levelInfo);
7698
7652
  if (decodingInfo.error) {
7699
- _this2.warn("MediaCapabilities decodingInfo error: \"" + decodingInfo.error + "\" for level " + index + " " + JSON.stringify(decodingInfo));
7653
+ logger.warn("[abr] MediaCapabilities decodingInfo error: \"" + decodingInfo.error + "\" for level " + index + " " + JSON.stringify(decodingInfo));
7700
7654
  } else if (!decodingInfo.supported) {
7701
- _this2.warn("Unsupported MediaCapabilities decodingInfo result for level " + index + " " + JSON.stringify(decodingInfo));
7655
+ logger.warn("[abr] Unsupported MediaCapabilities decodingInfo result for level " + index + " " + JSON.stringify(decodingInfo));
7702
7656
  if (index > -1 && levels.length > 1) {
7703
- _this2.log("Removing unsupported level " + index);
7657
+ logger.log("[abr] Removing unsupported level " + index);
7704
7658
  _this2.hls.removeLevel(index);
7705
7659
  }
7706
7660
  }
@@ -7747,9 +7701,9 @@
7747
7701
  var forcedAutoLevel = _this2.forcedAutoLevel;
7748
7702
  if (i !== loadLevel && (forcedAutoLevel === -1 || forcedAutoLevel !== loadLevel)) {
7749
7703
  if (levelsSkipped.length) {
7750
- _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);
7704
+ 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);
7751
7705
  }
7752
- _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);
7706
+ 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);
7753
7707
  }
7754
7708
  if (firstSelection) {
7755
7709
  _this2.firstSelection = i;
@@ -7783,7 +7737,7 @@
7783
7737
  }
7784
7738
  var firstLevel = this.hls.firstLevel;
7785
7739
  var clamped = Math.min(Math.max(firstLevel, minAutoLevel), maxAutoLevel);
7786
- this.warn("Could not find best starting auto level. Defaulting to first in playlist " + firstLevel + " clamped to " + clamped);
7740
+ logger.warn("[abr] Could not find best starting auto level. Defaulting to first in playlist " + firstLevel + " clamped to " + clamped);
7787
7741
  return clamped;
7788
7742
  }
7789
7743
  }, {
@@ -7836,7 +7790,7 @@
7836
7790
  }
7837
7791
  }]);
7838
7792
  return AbrController;
7839
- }(Logger);
7793
+ }();
7840
7794
 
7841
7795
  /**
7842
7796
  * @ignore
@@ -7867,17 +7821,13 @@
7867
7821
  * we are limiting the task execution per call stack to exactly one, but scheduling/post-poning further
7868
7822
  * task processing on the next main loop iteration (also known as "next tick" in the Node/JS runtime lingo).
7869
7823
  */
7870
- var TaskLoop = /*#__PURE__*/function (_Logger) {
7871
- _inheritsLoose(TaskLoop, _Logger);
7872
- function TaskLoop(label, logger) {
7873
- var _this;
7874
- _this = _Logger.call(this, label, logger) || this;
7875
- _this._boundTick = void 0;
7876
- _this._tickTimer = null;
7877
- _this._tickInterval = null;
7878
- _this._tickCallCount = 0;
7879
- _this._boundTick = _this.tick.bind(_assertThisInitialized(_this));
7880
- return _this;
7824
+ var TaskLoop = /*#__PURE__*/function () {
7825
+ function TaskLoop() {
7826
+ this._boundTick = void 0;
7827
+ this._tickTimer = null;
7828
+ this._tickInterval = null;
7829
+ this._tickCallCount = 0;
7830
+ this._boundTick = this.tick.bind(this);
7881
7831
  }
7882
7832
  var _proto = TaskLoop.prototype;
7883
7833
  _proto.destroy = function destroy() {
@@ -7963,7 +7913,7 @@
7963
7913
  */;
7964
7914
  _proto.doTick = function doTick() {};
7965
7915
  return TaskLoop;
7966
- }(Logger);
7916
+ }();
7967
7917
 
7968
7918
  var FragmentState = {
7969
7919
  NOT_LOADED: "NOT_LOADED",
@@ -8982,8 +8932,8 @@
8982
8932
  var _frag$decryptdata;
8983
8933
  var byteRangeStart = start;
8984
8934
  var byteRangeEnd = end;
8985
- if (frag.sn === 'initSegment' && isMethodFullSegmentAesCbc((_frag$decryptdata = frag.decryptdata) == null ? void 0 : _frag$decryptdata.method)) {
8986
- // MAP segment encrypted with method 'AES-128' or 'AES-256' (cbc), when served with HTTP Range,
8935
+ if (frag.sn === 'initSegment' && ((_frag$decryptdata = frag.decryptdata) == null ? void 0 : _frag$decryptdata.method) === 'AES-128') {
8936
+ // MAP segment encrypted with method 'AES-128', when served with HTTP Range,
8987
8937
  // has the unencrypted size specified in the range.
8988
8938
  // Ref: https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-6.3.6
8989
8939
  var fragmentLen = end - start;
@@ -9016,9 +8966,6 @@
9016
8966
  (part ? part : frag).stats.aborted = true;
9017
8967
  return new LoadError(errorData);
9018
8968
  }
9019
- function isMethodFullSegmentAesCbc(method) {
9020
- return method === 'AES-128' || method === 'AES-256';
9021
- }
9022
8969
  var LoadError = /*#__PURE__*/function (_Error) {
9023
8970
  _inheritsLoose(LoadError, _Error);
9024
8971
  function LoadError(data) {
@@ -9032,65 +8979,37 @@
9032
8979
  }( /*#__PURE__*/_wrapNativeSuper(Error));
9033
8980
 
9034
8981
  var AESCrypto = /*#__PURE__*/function () {
9035
- function AESCrypto(subtle, iv, aesMode) {
8982
+ function AESCrypto(subtle, iv) {
9036
8983
  this.subtle = void 0;
9037
8984
  this.aesIV = void 0;
9038
- this.aesMode = void 0;
9039
8985
  this.subtle = subtle;
9040
8986
  this.aesIV = iv;
9041
- this.aesMode = aesMode;
9042
8987
  }
9043
8988
  var _proto = AESCrypto.prototype;
9044
8989
  _proto.decrypt = function decrypt(data, key) {
9045
- switch (this.aesMode) {
9046
- case DecrypterAesMode.cbc:
9047
- return this.subtle.decrypt({
9048
- name: 'AES-CBC',
9049
- iv: this.aesIV
9050
- }, key, data);
9051
- case DecrypterAesMode.ctr:
9052
- return this.subtle.decrypt({
9053
- name: 'AES-CTR',
9054
- counter: this.aesIV,
9055
- length: 64
9056
- },
9057
- //64 : NIST SP800-38A standard suggests that the counter should occupy half of the counter block
9058
- key, data);
9059
- default:
9060
- throw new Error("[AESCrypto] invalid aes mode " + this.aesMode);
9061
- }
8990
+ return this.subtle.decrypt({
8991
+ name: 'AES-CBC',
8992
+ iv: this.aesIV
8993
+ }, key, data);
9062
8994
  };
9063
8995
  return AESCrypto;
9064
8996
  }();
9065
8997
 
9066
8998
  var FastAESKey = /*#__PURE__*/function () {
9067
- function FastAESKey(subtle, key, aesMode) {
8999
+ function FastAESKey(subtle, key) {
9068
9000
  this.subtle = void 0;
9069
9001
  this.key = void 0;
9070
- this.aesMode = void 0;
9071
9002
  this.subtle = subtle;
9072
9003
  this.key = key;
9073
- this.aesMode = aesMode;
9074
9004
  }
9075
9005
  var _proto = FastAESKey.prototype;
9076
9006
  _proto.expandKey = function expandKey() {
9077
- var subtleAlgoName = getSubtleAlgoName(this.aesMode);
9078
9007
  return this.subtle.importKey('raw', this.key, {
9079
- name: subtleAlgoName
9008
+ name: 'AES-CBC'
9080
9009
  }, false, ['encrypt', 'decrypt']);
9081
9010
  };
9082
9011
  return FastAESKey;
9083
9012
  }();
9084
- function getSubtleAlgoName(aesMode) {
9085
- switch (aesMode) {
9086
- case DecrypterAesMode.cbc:
9087
- return 'AES-CBC';
9088
- case DecrypterAesMode.ctr:
9089
- return 'AES-CTR';
9090
- default:
9091
- throw new Error("[FastAESKey] invalid aes mode " + aesMode);
9092
- }
9093
- }
9094
9013
 
9095
9014
  // PKCS7
9096
9015
  function removePadding(array) {
@@ -9343,8 +9262,7 @@
9343
9262
  this.currentIV = null;
9344
9263
  this.currentResult = null;
9345
9264
  this.useSoftware = void 0;
9346
- this.enableSoftwareAES = void 0;
9347
- this.enableSoftwareAES = config.enableSoftwareAES;
9265
+ this.useSoftware = config.enableSoftwareAES;
9348
9266
  this.removePKCS7Padding = removePKCS7Padding;
9349
9267
  // built in decryptor expects PKCS7 padding
9350
9268
  if (removePKCS7Padding) {
@@ -9357,7 +9275,9 @@
9357
9275
  /* no-op */
9358
9276
  }
9359
9277
  }
9360
- this.useSoftware = this.subtle === null;
9278
+ if (this.subtle === null) {
9279
+ this.useSoftware = true;
9280
+ }
9361
9281
  }
9362
9282
  var _proto = Decrypter.prototype;
9363
9283
  _proto.destroy = function destroy() {
@@ -9394,11 +9314,11 @@
9394
9314
  this.softwareDecrypter = null;
9395
9315
  }
9396
9316
  };
9397
- _proto.decrypt = function decrypt(data, key, iv, aesMode) {
9317
+ _proto.decrypt = function decrypt(data, key, iv) {
9398
9318
  var _this = this;
9399
9319
  if (this.useSoftware) {
9400
9320
  return new Promise(function (resolve, reject) {
9401
- _this.softwareDecrypt(new Uint8Array(data), key, iv, aesMode);
9321
+ _this.softwareDecrypt(new Uint8Array(data), key, iv);
9402
9322
  var decryptResult = _this.flush();
9403
9323
  if (decryptResult) {
9404
9324
  resolve(decryptResult.buffer);
@@ -9407,20 +9327,16 @@
9407
9327
  }
9408
9328
  });
9409
9329
  }
9410
- return this.webCryptoDecrypt(new Uint8Array(data), key, iv, aesMode);
9330
+ return this.webCryptoDecrypt(new Uint8Array(data), key, iv);
9411
9331
  }
9412
9332
 
9413
9333
  // Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
9414
9334
  // data is handled in the flush() call
9415
9335
  ;
9416
- _proto.softwareDecrypt = function softwareDecrypt(data, key, iv, aesMode) {
9336
+ _proto.softwareDecrypt = function softwareDecrypt(data, key, iv) {
9417
9337
  var currentIV = this.currentIV,
9418
9338
  currentResult = this.currentResult,
9419
9339
  remainderData = this.remainderData;
9420
- if (aesMode !== DecrypterAesMode.cbc || key.byteLength !== 16) {
9421
- logger.warn('SoftwareDecrypt: can only handle AES-128-CBC');
9422
- return null;
9423
- }
9424
9340
  this.logOnce('JS AES decrypt');
9425
9341
  // The output is staggered during progressive parsing - the current result is cached, and emitted on the next call
9426
9342
  // This is done in order to strip PKCS7 padding, which is found at the end of each segment. We only know we've reached
@@ -9453,12 +9369,12 @@
9453
9369
  }
9454
9370
  return result;
9455
9371
  };
9456
- _proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv, aesMode) {
9372
+ _proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv) {
9457
9373
  var _this2 = this;
9458
9374
  var subtle = this.subtle;
9459
9375
  if (this.key !== key || !this.fastAesKey) {
9460
9376
  this.key = key;
9461
- this.fastAesKey = new FastAESKey(subtle, key, aesMode);
9377
+ this.fastAesKey = new FastAESKey(subtle, key);
9462
9378
  }
9463
9379
  return this.fastAesKey.expandKey().then(function (aesKey) {
9464
9380
  // decrypt using web crypto
@@ -9466,25 +9382,22 @@
9466
9382
  return Promise.reject(new Error('web crypto not initialized'));
9467
9383
  }
9468
9384
  _this2.logOnce('WebCrypto AES decrypt');
9469
- var crypto = new AESCrypto(subtle, new Uint8Array(iv), aesMode);
9385
+ var crypto = new AESCrypto(subtle, new Uint8Array(iv));
9470
9386
  return crypto.decrypt(data.buffer, aesKey);
9471
9387
  }).catch(function (err) {
9472
9388
  logger.warn("[decrypter]: WebCrypto Error, disable WebCrypto API, " + err.name + ": " + err.message);
9473
- return _this2.onWebCryptoError(data, key, iv, aesMode);
9389
+ return _this2.onWebCryptoError(data, key, iv);
9474
9390
  });
9475
9391
  };
9476
- _proto.onWebCryptoError = function onWebCryptoError(data, key, iv, aesMode) {
9477
- var enableSoftwareAES = this.enableSoftwareAES;
9478
- if (enableSoftwareAES) {
9479
- this.useSoftware = true;
9480
- this.logEnabled = true;
9481
- this.softwareDecrypt(data, key, iv, aesMode);
9482
- var decryptResult = this.flush();
9483
- if (decryptResult) {
9484
- return decryptResult.buffer;
9485
- }
9392
+ _proto.onWebCryptoError = function onWebCryptoError(data, key, iv) {
9393
+ this.useSoftware = true;
9394
+ this.logEnabled = true;
9395
+ this.softwareDecrypt(data, key, iv);
9396
+ var decryptResult = this.flush();
9397
+ if (decryptResult) {
9398
+ return decryptResult.buffer;
9486
9399
  }
9487
- throw new Error('WebCrypto' + (enableSoftwareAES ? ' and softwareDecrypt' : '') + ': failed to decrypt data');
9400
+ throw new Error('WebCrypto and softwareDecrypt: failed to decrypt data');
9488
9401
  };
9489
9402
  _proto.getValidChunk = function getValidChunk(data) {
9490
9403
  var currentChunk = data;
@@ -9538,7 +9451,7 @@
9538
9451
  _inheritsLoose(BaseStreamController, _TaskLoop);
9539
9452
  function BaseStreamController(hls, fragmentTracker, keyLoader, logPrefix, playlistType) {
9540
9453
  var _this;
9541
- _this = _TaskLoop.call(this, logPrefix, hls.logger) || this;
9454
+ _this = _TaskLoop.call(this) || this;
9542
9455
  _this.hls = void 0;
9543
9456
  _this.fragPrevious = null;
9544
9457
  _this.fragCurrent = null;
@@ -9563,96 +9476,25 @@
9563
9476
  _this.startFragRequested = false;
9564
9477
  _this.decrypter = void 0;
9565
9478
  _this.initPTS = [];
9566
- _this.buffering = true;
9567
- _this.loadingParts = false;
9568
- _this.onMediaSeeking = function () {
9569
- var _assertThisInitialize = _assertThisInitialized(_this),
9570
- config = _assertThisInitialize.config,
9571
- fragCurrent = _assertThisInitialize.fragCurrent,
9572
- media = _assertThisInitialize.media,
9573
- mediaBuffer = _assertThisInitialize.mediaBuffer,
9574
- state = _assertThisInitialize.state;
9575
- var currentTime = media ? media.currentTime : 0;
9576
- var bufferInfo = BufferHelper.bufferInfo(mediaBuffer ? mediaBuffer : media, currentTime, config.maxBufferHole);
9577
- _this.log("media seeking to " + (isFiniteNumber(currentTime) ? currentTime.toFixed(3) : currentTime) + ", state: " + state);
9578
- if (_this.state === State.ENDED) {
9579
- _this.resetLoadingState();
9580
- } else if (fragCurrent) {
9581
- // Seeking while frag load is in progress
9582
- var tolerance = config.maxFragLookUpTolerance;
9583
- var fragStartOffset = fragCurrent.start - tolerance;
9584
- var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance;
9585
- // if seeking out of buffered range or into new one
9586
- if (!bufferInfo.len || fragEndOffset < bufferInfo.start || fragStartOffset > bufferInfo.end) {
9587
- var pastFragment = currentTime > fragEndOffset;
9588
- // if the seek position is outside the current fragment range
9589
- if (currentTime < fragStartOffset || pastFragment) {
9590
- if (pastFragment && fragCurrent.loader) {
9591
- _this.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
9592
- fragCurrent.abortRequests();
9593
- _this.resetLoadingState();
9594
- }
9595
- _this.fragPrevious = null;
9596
- }
9597
- }
9598
- }
9599
- if (media) {
9600
- // Remove gap fragments
9601
- _this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, _this.playlistType, true);
9602
- _this.lastCurrentTime = currentTime;
9603
- if (!_this.loadingParts) {
9604
- var bufferEnd = Math.max(bufferInfo.end, currentTime);
9605
- var shouldLoadParts = _this.shouldLoadParts(_this.getLevelDetails(), bufferEnd);
9606
- if (shouldLoadParts) {
9607
- _this.log("LL-Part loading ON after seeking to " + currentTime.toFixed(2) + " with buffer @" + bufferEnd.toFixed(2));
9608
- _this.loadingParts = shouldLoadParts;
9609
- }
9610
- }
9611
- }
9612
-
9613
- // in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
9614
- if (!_this.loadedmetadata && !bufferInfo.len) {
9615
- _this.nextLoadPosition = _this.startPosition = currentTime;
9616
- }
9617
-
9618
- // Async tick to speed up processing
9619
- _this.tickImmediate();
9620
- };
9621
- _this.onMediaEnded = function () {
9622
- // reset startPosition and lastCurrentTime to restart playback @ stream beginning
9623
- _this.startPosition = _this.lastCurrentTime = 0;
9624
- if (_this.playlistType === PlaylistLevelType.MAIN) {
9625
- _this.hls.trigger(Events.MEDIA_ENDED, {
9626
- stalled: false
9627
- });
9628
- }
9629
- };
9479
+ _this.onvseeking = null;
9480
+ _this.onvended = null;
9481
+ _this.logPrefix = '';
9482
+ _this.log = void 0;
9483
+ _this.warn = void 0;
9630
9484
  _this.playlistType = playlistType;
9485
+ _this.logPrefix = logPrefix;
9486
+ _this.log = logger.log.bind(logger, logPrefix + ":");
9487
+ _this.warn = logger.warn.bind(logger, logPrefix + ":");
9631
9488
  _this.hls = hls;
9632
9489
  _this.fragmentLoader = new FragmentLoader(hls.config);
9633
9490
  _this.keyLoader = keyLoader;
9634
9491
  _this.fragmentTracker = fragmentTracker;
9635
9492
  _this.config = hls.config;
9636
9493
  _this.decrypter = new Decrypter(hls.config);
9494
+ hls.on(Events.MANIFEST_LOADED, _this.onManifestLoaded, _assertThisInitialized(_this));
9637
9495
  return _this;
9638
9496
  }
9639
9497
  var _proto = BaseStreamController.prototype;
9640
- _proto.registerListeners = function registerListeners() {
9641
- var hls = this.hls;
9642
- hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
9643
- hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
9644
- hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
9645
- hls.on(Events.MANIFEST_LOADED, this.onManifestLoaded, this);
9646
- hls.on(Events.ERROR, this.onError, this);
9647
- };
9648
- _proto.unregisterListeners = function unregisterListeners() {
9649
- var hls = this.hls;
9650
- hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
9651
- hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
9652
- hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
9653
- hls.off(Events.MANIFEST_LOADED, this.onManifestLoaded, this);
9654
- hls.off(Events.ERROR, this.onError, this);
9655
- };
9656
9498
  _proto.doTick = function doTick() {
9657
9499
  this.onTickEnd();
9658
9500
  };
@@ -9676,12 +9518,6 @@
9676
9518
  this.clearNextTick();
9677
9519
  this.state = State.STOPPED;
9678
9520
  };
9679
- _proto.pauseBuffering = function pauseBuffering() {
9680
- this.buffering = false;
9681
- };
9682
- _proto.resumeBuffering = function resumeBuffering() {
9683
- this.buffering = true;
9684
- };
9685
9521
  _proto._streamEnded = function _streamEnded(bufferInfo, levelDetails) {
9686
9522
  // If playlist is live, there is another buffered range after the current range, nothing buffered, media is detached,
9687
9523
  // of nothing loading/loaded return false
@@ -9712,8 +9548,10 @@
9712
9548
  };
9713
9549
  _proto.onMediaAttached = function onMediaAttached(event, data) {
9714
9550
  var media = this.media = this.mediaBuffer = data.media;
9715
- media.addEventListener('seeking', this.onMediaSeeking);
9716
- media.addEventListener('ended', this.onMediaEnded);
9551
+ this.onvseeking = this.onMediaSeeking.bind(this);
9552
+ this.onvended = this.onMediaEnded.bind(this);
9553
+ media.addEventListener('seeking', this.onvseeking);
9554
+ media.addEventListener('ended', this.onvended);
9717
9555
  var config = this.config;
9718
9556
  if (this.levels && config.autoStartLoad && this.state === State.STOPPED) {
9719
9557
  this.startLoad(config.startPosition);
@@ -9727,9 +9565,10 @@
9727
9565
  }
9728
9566
 
9729
9567
  // remove video listeners
9730
- if (media) {
9731
- media.removeEventListener('seeking', this.onMediaSeeking);
9732
- media.removeEventListener('ended', this.onMediaEnded);
9568
+ if (media && this.onvseeking && this.onvended) {
9569
+ media.removeEventListener('seeking', this.onvseeking);
9570
+ media.removeEventListener('ended', this.onvended);
9571
+ this.onvseeking = this.onvended = null;
9733
9572
  }
9734
9573
  if (this.keyLoader) {
9735
9574
  this.keyLoader.detach();
@@ -9739,8 +9578,54 @@
9739
9578
  this.fragmentTracker.removeAllFragments();
9740
9579
  this.stopLoad();
9741
9580
  };
9742
- _proto.onManifestLoading = function onManifestLoading() {};
9743
- _proto.onError = function onError(event, data) {};
9581
+ _proto.onMediaSeeking = function onMediaSeeking() {
9582
+ var config = this.config,
9583
+ fragCurrent = this.fragCurrent,
9584
+ media = this.media,
9585
+ mediaBuffer = this.mediaBuffer,
9586
+ state = this.state;
9587
+ var currentTime = media ? media.currentTime : 0;
9588
+ var bufferInfo = BufferHelper.bufferInfo(mediaBuffer ? mediaBuffer : media, currentTime, config.maxBufferHole);
9589
+ this.log("media seeking to " + (isFiniteNumber(currentTime) ? currentTime.toFixed(3) : currentTime) + ", state: " + state);
9590
+ if (this.state === State.ENDED) {
9591
+ this.resetLoadingState();
9592
+ } else if (fragCurrent) {
9593
+ // Seeking while frag load is in progress
9594
+ var tolerance = config.maxFragLookUpTolerance;
9595
+ var fragStartOffset = fragCurrent.start - tolerance;
9596
+ var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance;
9597
+ // if seeking out of buffered range or into new one
9598
+ if (!bufferInfo.len || fragEndOffset < bufferInfo.start || fragStartOffset > bufferInfo.end) {
9599
+ var pastFragment = currentTime > fragEndOffset;
9600
+ // if the seek position is outside the current fragment range
9601
+ if (currentTime < fragStartOffset || pastFragment) {
9602
+ if (pastFragment && fragCurrent.loader) {
9603
+ this.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
9604
+ fragCurrent.abortRequests();
9605
+ this.resetLoadingState();
9606
+ }
9607
+ this.fragPrevious = null;
9608
+ }
9609
+ }
9610
+ }
9611
+ if (media) {
9612
+ // Remove gap fragments
9613
+ this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, this.playlistType, true);
9614
+ this.lastCurrentTime = currentTime;
9615
+ }
9616
+
9617
+ // in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
9618
+ if (!this.loadedmetadata && !bufferInfo.len) {
9619
+ this.nextLoadPosition = this.startPosition = currentTime;
9620
+ }
9621
+
9622
+ // Async tick to speed up processing
9623
+ this.tickImmediate();
9624
+ };
9625
+ _proto.onMediaEnded = function onMediaEnded() {
9626
+ // reset startPosition and lastCurrentTime to restart playback @ stream beginning
9627
+ this.startPosition = this.lastCurrentTime = 0;
9628
+ };
9744
9629
  _proto.onManifestLoaded = function onManifestLoaded(event, data) {
9745
9630
  this.startTimeOffset = data.startTimeOffset;
9746
9631
  this.initPTS = [];
@@ -9750,7 +9635,7 @@
9750
9635
  this.stopLoad();
9751
9636
  _TaskLoop.prototype.onHandlerDestroying.call(this);
9752
9637
  // @ts-ignore
9753
- this.hls = this.onMediaSeeking = this.onMediaEnded = null;
9638
+ this.hls = null;
9754
9639
  };
9755
9640
  _proto.onHandlerDestroyed = function onHandlerDestroyed() {
9756
9641
  this.state = State.STOPPED;
@@ -9880,10 +9765,10 @@
9880
9765
  var decryptData = frag.decryptdata;
9881
9766
 
9882
9767
  // check to see if the payload needs to be decrypted
9883
- if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && isFullSegmentEncryption(decryptData.method)) {
9768
+ if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && decryptData.method === 'AES-128') {
9884
9769
  var startTime = self.performance.now();
9885
9770
  // decrypt init segment data
9886
- return _this3.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer, getAesModeFromFullSegmentMethod(decryptData.method)).catch(function (err) {
9771
+ return _this3.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).catch(function (err) {
9887
9772
  hls.trigger(Events.ERROR, {
9888
9773
  type: ErrorTypes.MEDIA_ERROR,
9889
9774
  details: ErrorDetails.FRAG_DECRYPT_ERROR,
@@ -9996,7 +9881,7 @@
9996
9881
  }
9997
9882
  var keyLoadingPromise = null;
9998
9883
  if (frag.encrypted && !((_frag$decryptdata = frag.decryptdata) != null && _frag$decryptdata.key)) {
9999
- this.log("Loading key for " + frag.sn + " of [" + details.startSN + "-" + details.endSN + "], " + (this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track') + " " + frag.level);
9884
+ this.log("Loading key for " + frag.sn + " of [" + details.startSN + "-" + details.endSN + "], " + (this.logPrefix === '[stream-controller]' ? 'level' : 'track') + " " + frag.level);
10000
9885
  this.state = State.KEY_LOADING;
10001
9886
  this.fragCurrent = frag;
10002
9887
  keyLoadingPromise = this.keyLoader.load(frag).then(function (keyLoadedData) {
@@ -10017,16 +9902,8 @@
10017
9902
  } else if (!frag.encrypted && details.encryptedFragments.length) {
10018
9903
  this.keyLoader.loadClear(frag, details.encryptedFragments);
10019
9904
  }
10020
- var fragPrevious = this.fragPrevious;
10021
- if (frag.sn !== 'initSegment' && (!fragPrevious || frag.sn !== fragPrevious.sn)) {
10022
- var shouldLoadParts = this.shouldLoadParts(level.details, frag.end);
10023
- if (shouldLoadParts !== this.loadingParts) {
10024
- this.log("LL-Part loading " + (shouldLoadParts ? 'ON' : 'OFF') + " loading sn " + (fragPrevious == null ? void 0 : fragPrevious.sn) + "->" + frag.sn);
10025
- this.loadingParts = shouldLoadParts;
10026
- }
10027
- }
10028
9905
  targetBufferTime = Math.max(frag.start, targetBufferTime || 0);
10029
- if (this.loadingParts && frag.sn !== 'initSegment') {
9906
+ if (this.config.lowLatencyMode && frag.sn !== 'initSegment') {
10030
9907
  var partList = details.partList;
10031
9908
  if (partList && progressCallback) {
10032
9909
  if (targetBufferTime > frag.end && details.fragmentHint) {
@@ -10035,7 +9912,7 @@
10035
9912
  var partIndex = this.getNextPart(partList, frag, targetBufferTime);
10036
9913
  if (partIndex > -1) {
10037
9914
  var part = partList[partIndex];
10038
- 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)));
9915
+ 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)));
10039
9916
  this.nextLoadPosition = part.start + part.duration;
10040
9917
  this.state = State.FRAG_LOADING;
10041
9918
  var _result;
@@ -10068,14 +9945,7 @@
10068
9945
  }
10069
9946
  }
10070
9947
  }
10071
- if (frag.sn !== 'initSegment' && this.loadingParts) {
10072
- this.log("LL-Part loading OFF after next part miss @" + targetBufferTime.toFixed(2));
10073
- this.loadingParts = false;
10074
- } else if (!frag.url) {
10075
- // Selected fragment hint for part but not loading parts
10076
- return Promise.resolve(null);
10077
- }
10078
- 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)));
9948
+ 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)));
10079
9949
  // Don't update nextLoadPosition for fragments which are not buffered
10080
9950
  if (isFiniteNumber(frag.sn) && !this.bitrateTest) {
10081
9951
  this.nextLoadPosition = frag.start + frag.duration;
@@ -10177,36 +10047,8 @@
10177
10047
  if (part) {
10178
10048
  part.stats.parsing.end = now;
10179
10049
  }
10180
- // See if part loading should be disabled/enabled based on buffer and playback position.
10181
- if (frag.sn !== 'initSegment') {
10182
- var levelDetails = this.getLevelDetails();
10183
- var loadingPartsAtEdge = levelDetails && frag.sn > levelDetails.endSN;
10184
- var shouldLoadParts = loadingPartsAtEdge || this.shouldLoadParts(levelDetails, frag.end);
10185
- if (shouldLoadParts !== this.loadingParts) {
10186
- this.log("LL-Part loading " + (shouldLoadParts ? 'ON' : 'OFF') + " after parsing segment ending @" + frag.end.toFixed(2));
10187
- this.loadingParts = shouldLoadParts;
10188
- }
10189
- }
10190
10050
  this.updateLevelTiming(frag, part, level, chunkMeta.partial);
10191
10051
  };
10192
- _proto.shouldLoadParts = function shouldLoadParts(details, bufferEnd) {
10193
- if (this.config.lowLatencyMode) {
10194
- if (!details) {
10195
- return this.loadingParts;
10196
- }
10197
- if (details != null && details.partList) {
10198
- var _details$fragmentHint;
10199
- // Buffer must be ahead of first part + duration of parts after last segment
10200
- // and playback must be at or past segment adjacent to part list
10201
- var firstPart = details.partList[0];
10202
- var safePartStart = firstPart.end + (((_details$fragmentHint = details.fragmentHint) == null ? void 0 : _details$fragmentHint.duration) || 0);
10203
- if (bufferEnd >= safePartStart && this.lastCurrentTime > firstPart.start - firstPart.fragment.duration) {
10204
- return true;
10205
- }
10206
- }
10207
- }
10208
- return false;
10209
- };
10210
10052
  _proto.getCurrentContext = function getCurrentContext(chunkMeta) {
10211
10053
  var levels = this.levels,
10212
10054
  fragCurrent = this.fragCurrent;
@@ -10341,8 +10183,7 @@
10341
10183
  // find fragment index, contiguous with end of buffer position
10342
10184
  var config = this.config;
10343
10185
  var start = fragments[0].start;
10344
- var canLoadParts = config.lowLatencyMode && !!levelDetails.partList;
10345
- var frag = null;
10186
+ var frag;
10346
10187
  if (levelDetails.live) {
10347
10188
  var initialLiveManifestSize = config.initialLiveManifestSize;
10348
10189
  if (fragLen < initialLiveManifestSize) {
@@ -10354,10 +10195,6 @@
10354
10195
  // Do not load using live logic if the starting frag is requested - we want to use getFragmentAtPosition() so that
10355
10196
  // we get the fragment matching that start time
10356
10197
  if (!levelDetails.PTSKnown && !this.startFragRequested && this.startPosition === -1 || pos < start) {
10357
- if (canLoadParts && !this.loadingParts) {
10358
- this.log("LL-Part loading ON for initial live fragment");
10359
- this.loadingParts = true;
10360
- }
10361
10198
  frag = this.getInitialLiveFragment(levelDetails, fragments);
10362
10199
  this.startPosition = this.nextLoadPosition = frag ? this.hls.liveSyncPosition || frag.start : pos;
10363
10200
  }
@@ -10368,7 +10205,7 @@
10368
10205
 
10369
10206
  // If we haven't run into any special cases already, just load the fragment most closely matching the requested position
10370
10207
  if (!frag) {
10371
- var end = this.loadingParts ? levelDetails.partEnd : levelDetails.fragmentEnd;
10208
+ var end = config.lowLatencyMode ? levelDetails.partEnd : levelDetails.fragmentEnd;
10372
10209
  frag = this.getFragmentAtPosition(pos, end, levelDetails);
10373
10210
  }
10374
10211
  return this.mapToInitFragWhenRequired(frag);
@@ -10482,7 +10319,7 @@
10482
10319
  var fragmentHint = levelDetails.fragmentHint;
10483
10320
  var tolerance = config.maxFragLookUpTolerance;
10484
10321
  var partList = levelDetails.partList;
10485
- var loadingParts = !!(this.loadingParts && partList != null && partList.length && fragmentHint);
10322
+ var loadingParts = !!(config.lowLatencyMode && partList != null && partList.length && fragmentHint);
10486
10323
  if (loadingParts && fragmentHint && !this.bitrateTest) {
10487
10324
  // Include incomplete fragment with parts at end
10488
10325
  fragments = fragments.concat(fragmentHint);
@@ -10669,7 +10506,7 @@
10669
10506
  errorAction.resolved = true;
10670
10507
  }
10671
10508
  } else {
10672
- this.warn(data.details + " reached or exceeded max retry (" + retryCount + ")");
10509
+ logger.warn(data.details + " reached or exceeded max retry (" + retryCount + ")");
10673
10510
  return;
10674
10511
  }
10675
10512
  } else if ((errorAction == null ? void 0 : errorAction.action) === NetworkErrorAction.SendAlternateToPenaltyBox) {
@@ -11069,7 +10906,6 @@
11069
10906
  */
11070
10907
  function getAudioConfig(observer, data, offset, audioCodec) {
11071
10908
  var adtsObjectType;
11072
- var originalAdtsObjectType;
11073
10909
  var adtsExtensionSamplingIndex;
11074
10910
  var adtsChannelConfig;
11075
10911
  var config;
@@ -11077,7 +10913,7 @@
11077
10913
  var manifestCodec = audioCodec;
11078
10914
  var adtsSamplingRates = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];
11079
10915
  // byte 2
11080
- adtsObjectType = originalAdtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1;
10916
+ adtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1;
11081
10917
  var adtsSamplingIndex = (data[offset + 2] & 0x3c) >>> 2;
11082
10918
  if (adtsSamplingIndex > adtsSamplingRates.length - 1) {
11083
10919
  var error = new Error("invalid ADTS sampling index:" + adtsSamplingIndex);
@@ -11094,8 +10930,8 @@
11094
10930
  // byte 3
11095
10931
  adtsChannelConfig |= (data[offset + 3] & 0xc0) >>> 6;
11096
10932
  logger.log("manifest codec:" + audioCodec + ", ADTS type:" + adtsObjectType + ", samplingIndex:" + adtsSamplingIndex);
11097
- // Firefox and Pale Moon: freq less than 24kHz = AAC SBR (HE-AAC)
11098
- if (/firefox|palemoon/i.test(userAgent)) {
10933
+ // firefox: freq less than 24kHz = AAC SBR (HE-AAC)
10934
+ if (/firefox/i.test(userAgent)) {
11099
10935
  if (adtsSamplingIndex >= 6) {
11100
10936
  adtsObjectType = 5;
11101
10937
  config = new Array(4);
@@ -11189,7 +11025,6 @@
11189
11025
  samplerate: adtsSamplingRates[adtsSamplingIndex],
11190
11026
  channelCount: adtsChannelConfig,
11191
11027
  codec: 'mp4a.40.' + adtsObjectType,
11192
- parsedCodec: 'mp4a.40.' + originalAdtsObjectType,
11193
11028
  manifestCodec: manifestCodec
11194
11029
  };
11195
11030
  }
@@ -11244,8 +11079,7 @@
11244
11079
  track.channelCount = config.channelCount;
11245
11080
  track.codec = config.codec;
11246
11081
  track.manifestCodec = config.manifestCodec;
11247
- track.parsedCodec = config.parsedCodec;
11248
- logger.log("parsed codec:" + track.parsedCodec + ", codec:" + track.codec + ", rate:" + config.samplerate + ", channels:" + config.channelCount);
11082
+ logger.log("parsed codec:" + track.codec + ", rate:" + config.samplerate + ", channels:" + config.channelCount);
11249
11083
  }
11250
11084
  }
11251
11085
  function getFrameDuration(samplerate) {
@@ -11843,110 +11677,6 @@
11843
11677
  logger.log(VideoSample.pts + '/' + VideoSample.dts + ':' + VideoSample.debug);
11844
11678
  }
11845
11679
  };
11846
- _proto.parseNALu = function parseNALu(track, array) {
11847
- var len = array.byteLength;
11848
- var state = track.naluState || 0;
11849
- var lastState = state;
11850
- var units = [];
11851
- var i = 0;
11852
- var value;
11853
- var overflow;
11854
- var unitType;
11855
- var lastUnitStart = -1;
11856
- var lastUnitType = 0;
11857
- // logger.log('PES:' + Hex.hexDump(array));
11858
-
11859
- if (state === -1) {
11860
- // special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet
11861
- lastUnitStart = 0;
11862
- // NALu type is value read from offset 0
11863
- lastUnitType = this.getNALuType(array, 0);
11864
- state = 0;
11865
- i = 1;
11866
- }
11867
- while (i < len) {
11868
- value = array[i++];
11869
- // optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case
11870
- if (!state) {
11871
- state = value ? 0 : 1;
11872
- continue;
11873
- }
11874
- if (state === 1) {
11875
- state = value ? 0 : 2;
11876
- continue;
11877
- }
11878
- // here we have state either equal to 2 or 3
11879
- if (!value) {
11880
- state = 3;
11881
- } else if (value === 1) {
11882
- overflow = i - state - 1;
11883
- if (lastUnitStart >= 0) {
11884
- var unit = {
11885
- data: array.subarray(lastUnitStart, overflow),
11886
- type: lastUnitType
11887
- };
11888
- // logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);
11889
- units.push(unit);
11890
- } else {
11891
- // lastUnitStart is undefined => this is the first start code found in this PES packet
11892
- // first check if start code delimiter is overlapping between 2 PES packets,
11893
- // ie it started in last packet (lastState not zero)
11894
- // and ended at the beginning of this PES packet (i <= 4 - lastState)
11895
- var lastUnit = this.getLastNalUnit(track.samples);
11896
- if (lastUnit) {
11897
- if (lastState && i <= 4 - lastState) {
11898
- // start delimiter overlapping between PES packets
11899
- // strip start delimiter bytes from the end of last NAL unit
11900
- // check if lastUnit had a state different from zero
11901
- if (lastUnit.state) {
11902
- // strip last bytes
11903
- lastUnit.data = lastUnit.data.subarray(0, lastUnit.data.byteLength - lastState);
11904
- }
11905
- }
11906
- // If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.
11907
-
11908
- if (overflow > 0) {
11909
- // logger.log('first NALU found with overflow:' + overflow);
11910
- lastUnit.data = appendUint8Array(lastUnit.data, array.subarray(0, overflow));
11911
- lastUnit.state = 0;
11912
- }
11913
- }
11914
- }
11915
- // check if we can read unit type
11916
- if (i < len) {
11917
- unitType = this.getNALuType(array, i);
11918
- // logger.log('find NALU @ offset:' + i + ',type:' + unitType);
11919
- lastUnitStart = i;
11920
- lastUnitType = unitType;
11921
- state = 0;
11922
- } else {
11923
- // not enough byte to read unit type. let's read it on next PES parsing
11924
- state = -1;
11925
- }
11926
- } else {
11927
- state = 0;
11928
- }
11929
- }
11930
- if (lastUnitStart >= 0 && state >= 0) {
11931
- var _unit = {
11932
- data: array.subarray(lastUnitStart, len),
11933
- type: lastUnitType,
11934
- state: state
11935
- };
11936
- units.push(_unit);
11937
- // logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
11938
- }
11939
- // no NALu found
11940
- if (units.length === 0) {
11941
- // append pes.data to previous NAL unit
11942
- var _lastUnit = this.getLastNalUnit(track.samples);
11943
- if (_lastUnit) {
11944
- _lastUnit.data = appendUint8Array(_lastUnit.data, array);
11945
- }
11946
- }
11947
- track.naluState = state;
11948
- return units;
11949
- };
11950
11680
  return BaseVideoParser;
11951
11681
  }();
11952
11682
 
@@ -12101,236 +11831,78 @@
12101
11831
  ;
12102
11832
  _proto.readUInt = function readUInt() {
12103
11833
  return this.readBits(32);
12104
- };
12105
- return ExpGolomb;
12106
- }();
12107
-
12108
- var AvcVideoParser = /*#__PURE__*/function (_BaseVideoParser) {
12109
- _inheritsLoose(AvcVideoParser, _BaseVideoParser);
12110
- function AvcVideoParser() {
12111
- return _BaseVideoParser.apply(this, arguments) || this;
12112
11834
  }
12113
- var _proto = AvcVideoParser.prototype;
12114
- _proto.parsePES = function parsePES(track, textTrack, pes, last, duration) {
12115
- var _this = this;
12116
- var units = this.parseNALu(track, pes.data);
12117
- var VideoSample = this.VideoSample;
12118
- var push;
12119
- var spsfound = false;
12120
- // free pes.data to save up some memory
12121
- pes.data = null;
12122
11835
 
12123
- // if new NAL units found and last sample still there, let's push ...
12124
- // this helps parsing streams with missing AUD (only do this if AUD never found)
12125
- if (VideoSample && units.length && !track.audFound) {
12126
- this.pushAccessUnit(VideoSample, track);
12127
- VideoSample = this.VideoSample = this.createVideoSample(false, pes.pts, pes.dts, '');
11836
+ /**
11837
+ * Advance the ExpGolomb decoder past a scaling list. The scaling
11838
+ * list is optionally transmitted as part of a sequence parameter
11839
+ * set and is not relevant to transmuxing.
11840
+ * @param count the number of entries in this scaling list
11841
+ * @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
11842
+ */;
11843
+ _proto.skipScalingList = function skipScalingList(count) {
11844
+ var lastScale = 8;
11845
+ var nextScale = 8;
11846
+ var deltaScale;
11847
+ for (var j = 0; j < count; j++) {
11848
+ if (nextScale !== 0) {
11849
+ deltaScale = this.readEG();
11850
+ nextScale = (lastScale + deltaScale + 256) % 256;
11851
+ }
11852
+ lastScale = nextScale === 0 ? lastScale : nextScale;
12128
11853
  }
12129
- units.forEach(function (unit) {
12130
- var _VideoSample2;
12131
- switch (unit.type) {
12132
- // NDR
12133
- case 1:
12134
- {
12135
- var iskey = false;
12136
- push = true;
12137
- var data = unit.data;
12138
- // only check slice type to detect KF in case SPS found in same packet (any keyframe is preceded by SPS ...)
12139
- if (spsfound && data.length > 4) {
12140
- // retrieve slice type by parsing beginning of NAL unit (follow H264 spec, slice_header definition) to detect keyframe embedded in NDR
12141
- var sliceType = _this.readSliceType(data);
12142
- // 2 : I slice, 4 : SI slice, 7 : I slice, 9: SI slice
12143
- // SI slice : A slice that is coded using intra prediction only and using quantisation of the prediction samples.
12144
- // An SI slice can be coded such that its decoded samples can be constructed identically to an SP slice.
12145
- // I slice: A slice that is not an SI slice that is decoded using intra prediction only.
12146
- // if (sliceType === 2 || sliceType === 7) {
12147
- if (sliceType === 2 || sliceType === 4 || sliceType === 7 || sliceType === 9) {
12148
- iskey = true;
12149
- }
12150
- }
12151
- if (iskey) {
12152
- var _VideoSample;
12153
- // if we have non-keyframe data already, that cannot belong to the same frame as a keyframe, so force a push
12154
- if ((_VideoSample = VideoSample) != null && _VideoSample.frame && !VideoSample.key) {
12155
- _this.pushAccessUnit(VideoSample, track);
12156
- VideoSample = _this.VideoSample = null;
12157
- }
12158
- }
12159
- if (!VideoSample) {
12160
- VideoSample = _this.VideoSample = _this.createVideoSample(true, pes.pts, pes.dts, '');
12161
- }
12162
- VideoSample.frame = true;
12163
- VideoSample.key = iskey;
12164
- break;
12165
- // IDR
12166
- }
12167
- case 5:
12168
- push = true;
12169
- // handle PES not starting with AUD
12170
- // if we have frame data already, that cannot belong to the same frame, so force a push
12171
- if ((_VideoSample2 = VideoSample) != null && _VideoSample2.frame && !VideoSample.key) {
12172
- _this.pushAccessUnit(VideoSample, track);
12173
- VideoSample = _this.VideoSample = null;
12174
- }
12175
- if (!VideoSample) {
12176
- VideoSample = _this.VideoSample = _this.createVideoSample(true, pes.pts, pes.dts, '');
12177
- }
12178
- VideoSample.key = true;
12179
- VideoSample.frame = true;
12180
- break;
12181
- // SEI
12182
- case 6:
12183
- {
12184
- push = true;
12185
- parseSEIMessageFromNALu(unit.data, 1, pes.pts, textTrack.samples);
12186
- break;
12187
- // SPS
12188
- }
12189
- case 7:
12190
- {
12191
- var _track$pixelRatio, _track$pixelRatio2;
12192
- push = true;
12193
- spsfound = true;
12194
- var sps = unit.data;
12195
- var config = _this.readSPS(sps);
12196
- 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]) {
12197
- track.width = config.width;
12198
- track.height = config.height;
12199
- track.pixelRatio = config.pixelRatio;
12200
- track.sps = [sps];
12201
- track.duration = duration;
12202
- var codecarray = sps.subarray(1, 4);
12203
- var codecstring = 'avc1.';
12204
- for (var i = 0; i < 3; i++) {
12205
- var h = codecarray[i].toString(16);
12206
- if (h.length < 2) {
12207
- h = '0' + h;
12208
- }
12209
- codecstring += h;
12210
- }
12211
- track.codec = codecstring;
12212
- }
12213
- break;
12214
- }
12215
- // PPS
12216
- case 8:
12217
- push = true;
12218
- track.pps = [unit.data];
12219
- break;
12220
- // AUD
12221
- case 9:
12222
- push = true;
12223
- track.audFound = true;
12224
- if (VideoSample) {
12225
- _this.pushAccessUnit(VideoSample, track);
12226
- }
12227
- VideoSample = _this.VideoSample = _this.createVideoSample(false, pes.pts, pes.dts, '');
12228
- break;
12229
- // Filler Data
12230
- case 12:
12231
- push = true;
12232
- break;
12233
- default:
12234
- push = false;
12235
- if (VideoSample) {
12236
- VideoSample.debug += 'unknown NAL ' + unit.type + ' ';
12237
- }
12238
- break;
12239
- }
12240
- if (VideoSample && push) {
12241
- var _units = VideoSample.units;
12242
- _units.push(unit);
12243
- }
12244
- });
12245
- // if last PES packet, push samples
12246
- if (last && VideoSample) {
12247
- this.pushAccessUnit(VideoSample, track);
12248
- this.VideoSample = null;
12249
- }
12250
- };
12251
- _proto.getNALuType = function getNALuType(data, offset) {
12252
- return data[offset] & 0x1f;
12253
- };
12254
- _proto.readSliceType = function readSliceType(data) {
12255
- var eg = new ExpGolomb(data);
12256
- // skip NALu type
12257
- eg.readUByte();
12258
- // discard first_mb_in_slice
12259
- eg.readUEG();
12260
- // return slice_type
12261
- return eg.readUEG();
12262
- }
12263
-
12264
- /**
12265
- * The scaling list is optionally transmitted as part of a sequence parameter
12266
- * set and is not relevant to transmuxing.
12267
- * @param count the number of entries in this scaling list
12268
- * @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
12269
- */;
12270
- _proto.skipScalingList = function skipScalingList(count, reader) {
12271
- var lastScale = 8;
12272
- var nextScale = 8;
12273
- var deltaScale;
12274
- for (var j = 0; j < count; j++) {
12275
- if (nextScale !== 0) {
12276
- deltaScale = reader.readEG();
12277
- nextScale = (lastScale + deltaScale + 256) % 256;
12278
- }
12279
- lastScale = nextScale === 0 ? lastScale : nextScale;
12280
- }
12281
- }
12282
-
12283
- /**
12284
- * Read a sequence parameter set and return some interesting video
12285
- * properties. A sequence parameter set is the H264 metadata that
12286
- * describes the properties of upcoming video frames.
12287
- * @returns an object with configuration parsed from the
12288
- * sequence parameter set, including the dimensions of the
12289
- * associated video frames.
12290
- */;
12291
- _proto.readSPS = function readSPS(sps) {
12292
- var eg = new ExpGolomb(sps);
12293
- var frameCropLeftOffset = 0;
12294
- var frameCropRightOffset = 0;
12295
- var frameCropTopOffset = 0;
12296
- var frameCropBottomOffset = 0;
12297
- var numRefFramesInPicOrderCntCycle;
12298
- var scalingListCount;
12299
- var i;
12300
- var readUByte = eg.readUByte.bind(eg);
12301
- var readBits = eg.readBits.bind(eg);
12302
- var readUEG = eg.readUEG.bind(eg);
12303
- var readBoolean = eg.readBoolean.bind(eg);
12304
- var skipBits = eg.skipBits.bind(eg);
12305
- var skipEG = eg.skipEG.bind(eg);
12306
- var skipUEG = eg.skipUEG.bind(eg);
12307
- var skipScalingList = this.skipScalingList.bind(this);
12308
- readUByte();
12309
- var profileIdc = readUByte(); // profile_idc
12310
- readBits(5); // profileCompat constraint_set[0-4]_flag, u(5)
12311
- skipBits(3); // reserved_zero_3bits u(3),
12312
- readUByte(); // level_idc u(8)
12313
- skipUEG(); // seq_parameter_set_id
12314
- // some profiles have more optional data we don't need
12315
- if (profileIdc === 100 || profileIdc === 110 || profileIdc === 122 || profileIdc === 244 || profileIdc === 44 || profileIdc === 83 || profileIdc === 86 || profileIdc === 118 || profileIdc === 128) {
12316
- var chromaFormatIdc = readUEG();
12317
- if (chromaFormatIdc === 3) {
12318
- skipBits(1);
12319
- } // separate_colour_plane_flag
12320
-
12321
- skipUEG(); // bit_depth_luma_minus8
12322
- skipUEG(); // bit_depth_chroma_minus8
12323
- skipBits(1); // qpprime_y_zero_transform_bypass_flag
12324
- if (readBoolean()) {
12325
- // seq_scaling_matrix_present_flag
12326
- scalingListCount = chromaFormatIdc !== 3 ? 8 : 12;
12327
- for (i = 0; i < scalingListCount; i++) {
12328
- if (readBoolean()) {
12329
- // seq_scaling_list_present_flag[ i ]
12330
- if (i < 6) {
12331
- skipScalingList(16, eg);
12332
- } else {
12333
- skipScalingList(64, eg);
11854
+ }
11855
+
11856
+ /**
11857
+ * Read a sequence parameter set and return some interesting video
11858
+ * properties. A sequence parameter set is the H264 metadata that
11859
+ * describes the properties of upcoming video frames.
11860
+ * @returns an object with configuration parsed from the
11861
+ * sequence parameter set, including the dimensions of the
11862
+ * associated video frames.
11863
+ */;
11864
+ _proto.readSPS = function readSPS() {
11865
+ var frameCropLeftOffset = 0;
11866
+ var frameCropRightOffset = 0;
11867
+ var frameCropTopOffset = 0;
11868
+ var frameCropBottomOffset = 0;
11869
+ var numRefFramesInPicOrderCntCycle;
11870
+ var scalingListCount;
11871
+ var i;
11872
+ var readUByte = this.readUByte.bind(this);
11873
+ var readBits = this.readBits.bind(this);
11874
+ var readUEG = this.readUEG.bind(this);
11875
+ var readBoolean = this.readBoolean.bind(this);
11876
+ var skipBits = this.skipBits.bind(this);
11877
+ var skipEG = this.skipEG.bind(this);
11878
+ var skipUEG = this.skipUEG.bind(this);
11879
+ var skipScalingList = this.skipScalingList.bind(this);
11880
+ readUByte();
11881
+ var profileIdc = readUByte(); // profile_idc
11882
+ readBits(5); // profileCompat constraint_set[0-4]_flag, u(5)
11883
+ skipBits(3); // reserved_zero_3bits u(3),
11884
+ readUByte(); // level_idc u(8)
11885
+ skipUEG(); // seq_parameter_set_id
11886
+ // some profiles have more optional data we don't need
11887
+ if (profileIdc === 100 || profileIdc === 110 || profileIdc === 122 || profileIdc === 244 || profileIdc === 44 || profileIdc === 83 || profileIdc === 86 || profileIdc === 118 || profileIdc === 128) {
11888
+ var chromaFormatIdc = readUEG();
11889
+ if (chromaFormatIdc === 3) {
11890
+ skipBits(1);
11891
+ } // separate_colour_plane_flag
11892
+
11893
+ skipUEG(); // bit_depth_luma_minus8
11894
+ skipUEG(); // bit_depth_chroma_minus8
11895
+ skipBits(1); // qpprime_y_zero_transform_bypass_flag
11896
+ if (readBoolean()) {
11897
+ // seq_scaling_matrix_present_flag
11898
+ scalingListCount = chromaFormatIdc !== 3 ? 8 : 12;
11899
+ for (i = 0; i < scalingListCount; i++) {
11900
+ if (readBoolean()) {
11901
+ // seq_scaling_list_present_flag[ i ]
11902
+ if (i < 6) {
11903
+ skipScalingList(16);
11904
+ } else {
11905
+ skipScalingList(64);
12334
11906
  }
12335
11907
  }
12336
11908
  }
@@ -12435,24 +12007,26 @@
12435
12007
  pixelRatio: pixelRatio
12436
12008
  };
12437
12009
  };
12438
- return AvcVideoParser;
12439
- }(BaseVideoParser);
12010
+ _proto.readSliceType = function readSliceType() {
12011
+ // skip NALu type
12012
+ this.readUByte();
12013
+ // discard first_mb_in_slice
12014
+ this.readUEG();
12015
+ // return slice_type
12016
+ return this.readUEG();
12017
+ };
12018
+ return ExpGolomb;
12019
+ }();
12440
12020
 
12441
- var HevcVideoParser = /*#__PURE__*/function (_BaseVideoParser) {
12442
- _inheritsLoose(HevcVideoParser, _BaseVideoParser);
12443
- function HevcVideoParser() {
12444
- var _this;
12445
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
12446
- args[_key] = arguments[_key];
12447
- }
12448
- _this = _BaseVideoParser.call.apply(_BaseVideoParser, [this].concat(args)) || this;
12449
- _this.initVPS = null;
12450
- return _this;
12021
+ var AvcVideoParser = /*#__PURE__*/function (_BaseVideoParser) {
12022
+ _inheritsLoose(AvcVideoParser, _BaseVideoParser);
12023
+ function AvcVideoParser() {
12024
+ return _BaseVideoParser.apply(this, arguments) || this;
12451
12025
  }
12452
- var _proto = HevcVideoParser.prototype;
12453
- _proto.parsePES = function parsePES(track, textTrack, pes, last, duration) {
12454
- var _this2 = this;
12455
- var units = this.parseNALu(track, pes.data);
12026
+ var _proto = AvcVideoParser.prototype;
12027
+ _proto.parseAVCPES = function parseAVCPES(track, textTrack, pes, last, duration) {
12028
+ var _this = this;
12029
+ var units = this.parseAVCNALu(track, pes.data);
12456
12030
  var VideoSample = this.VideoSample;
12457
12031
  var push;
12458
12032
  var spsfound = false;
@@ -12468,143 +12042,112 @@
12468
12042
  units.forEach(function (unit) {
12469
12043
  var _VideoSample2;
12470
12044
  switch (unit.type) {
12471
- // NON-IDR, NON RANDOM ACCESS SLICE
12472
- case 0:
12045
+ // NDR
12473
12046
  case 1:
12474
- case 2:
12475
- case 3:
12476
- case 4:
12477
- case 5:
12478
- case 6:
12479
- case 7:
12480
- case 8:
12481
- case 9:
12482
- if (!VideoSample) {
12483
- VideoSample = _this2.VideoSample = _this2.createVideoSample(false, pes.pts, pes.dts, '');
12484
- }
12485
- VideoSample.frame = true;
12486
- push = true;
12487
- break;
12488
-
12489
- // CRA, BLA (random access picture)
12490
- case 16:
12491
- case 17:
12492
- case 18:
12493
- case 21:
12494
- push = true;
12495
- if (spsfound) {
12496
- var _VideoSample;
12497
- // handle PES not starting with AUD
12498
- // if we have frame data already, that cannot belong to the same frame, so force a push
12499
- if ((_VideoSample = VideoSample) != null && _VideoSample.frame && !VideoSample.key) {
12500
- _this2.pushAccessUnit(VideoSample, track);
12501
- VideoSample = _this2.VideoSample = null;
12047
+ {
12048
+ var iskey = false;
12049
+ push = true;
12050
+ var data = unit.data;
12051
+ // only check slice type to detect KF in case SPS found in same packet (any keyframe is preceded by SPS ...)
12052
+ if (spsfound && data.length > 4) {
12053
+ // retrieve slice type by parsing beginning of NAL unit (follow H264 spec, slice_header definition) to detect keyframe embedded in NDR
12054
+ var sliceType = new ExpGolomb(data).readSliceType();
12055
+ // 2 : I slice, 4 : SI slice, 7 : I slice, 9: SI slice
12056
+ // SI slice : A slice that is coded using intra prediction only and using quantisation of the prediction samples.
12057
+ // An SI slice can be coded such that its decoded samples can be constructed identically to an SP slice.
12058
+ // I slice: A slice that is not an SI slice that is decoded using intra prediction only.
12059
+ // if (sliceType === 2 || sliceType === 7) {
12060
+ if (sliceType === 2 || sliceType === 4 || sliceType === 7 || sliceType === 9) {
12061
+ iskey = true;
12062
+ }
12502
12063
  }
12064
+ if (iskey) {
12065
+ var _VideoSample;
12066
+ // if we have non-keyframe data already, that cannot belong to the same frame as a keyframe, so force a push
12067
+ if ((_VideoSample = VideoSample) != null && _VideoSample.frame && !VideoSample.key) {
12068
+ _this.pushAccessUnit(VideoSample, track);
12069
+ VideoSample = _this.VideoSample = null;
12070
+ }
12071
+ }
12072
+ if (!VideoSample) {
12073
+ VideoSample = _this.VideoSample = _this.createVideoSample(true, pes.pts, pes.dts, '');
12074
+ }
12075
+ VideoSample.frame = true;
12076
+ VideoSample.key = iskey;
12077
+ break;
12078
+ // IDR
12503
12079
  }
12504
- if (!VideoSample) {
12505
- VideoSample = _this2.VideoSample = _this2.createVideoSample(true, pes.pts, pes.dts, '');
12506
- }
12507
- VideoSample.key = true;
12508
- VideoSample.frame = true;
12509
- break;
12510
-
12511
- // IDR
12512
- case 19:
12513
- case 20:
12080
+ case 5:
12514
12081
  push = true;
12515
12082
  // handle PES not starting with AUD
12516
12083
  // if we have frame data already, that cannot belong to the same frame, so force a push
12517
12084
  if ((_VideoSample2 = VideoSample) != null && _VideoSample2.frame && !VideoSample.key) {
12518
- _this2.pushAccessUnit(VideoSample, track);
12519
- VideoSample = _this2.VideoSample = null;
12085
+ _this.pushAccessUnit(VideoSample, track);
12086
+ VideoSample = _this.VideoSample = null;
12520
12087
  }
12521
12088
  if (!VideoSample) {
12522
- VideoSample = _this2.VideoSample = _this2.createVideoSample(true, pes.pts, pes.dts, '');
12089
+ VideoSample = _this.VideoSample = _this.createVideoSample(true, pes.pts, pes.dts, '');
12523
12090
  }
12524
12091
  VideoSample.key = true;
12525
12092
  VideoSample.frame = true;
12526
12093
  break;
12527
-
12528
12094
  // SEI
12529
- case 39:
12530
- push = true;
12531
- parseSEIMessageFromNALu(unit.data, 2,
12532
- // NALu header size
12533
- pes.pts, textTrack.samples);
12534
- break;
12535
-
12536
- // VPS
12537
- case 32:
12538
- push = true;
12539
- if (!track.vps) {
12540
- var config = _this2.readVPS(unit.data);
12541
- track.params = _objectSpread2({}, config);
12542
- _this2.initVPS = unit.data;
12095
+ case 6:
12096
+ {
12097
+ push = true;
12098
+ parseSEIMessageFromNALu(unit.data, 1, pes.pts, textTrack.samples);
12099
+ break;
12100
+ // SPS
12543
12101
  }
12544
- track.vps = [unit.data];
12545
- break;
12546
-
12547
- // SPS
12548
- case 33:
12549
- push = true;
12550
- spsfound = true;
12551
- if (typeof track.params === 'object') {
12552
- if (track.vps !== undefined && track.vps[0] !== _this2.initVPS && track.sps !== undefined && !_this2.matchSPS(track.sps[0], unit.data)) {
12553
- _this2.initVPS = track.vps[0];
12554
- track.sps = track.pps = undefined;
12555
- }
12556
- if (!track.sps) {
12557
- var _config = _this2.readSPS(unit.data);
12558
- track.width = _config.width;
12559
- track.height = _config.height;
12560
- track.pixelRatio = _config.pixelRatio;
12102
+ case 7:
12103
+ {
12104
+ var _track$pixelRatio, _track$pixelRatio2;
12105
+ push = true;
12106
+ spsfound = true;
12107
+ var sps = unit.data;
12108
+ var expGolombDecoder = new ExpGolomb(sps);
12109
+ var config = expGolombDecoder.readSPS();
12110
+ 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]) {
12111
+ track.width = config.width;
12112
+ track.height = config.height;
12113
+ track.pixelRatio = config.pixelRatio;
12114
+ track.sps = [sps];
12561
12115
  track.duration = duration;
12562
- track.codec = _config.codecString;
12563
- track.sps = [];
12564
- for (var prop in _config.params) {
12565
- track.params[prop] = _config.params[prop];
12116
+ var codecarray = sps.subarray(1, 4);
12117
+ var codecstring = 'avc1.';
12118
+ for (var i = 0; i < 3; i++) {
12119
+ var h = codecarray[i].toString(16);
12120
+ if (h.length < 2) {
12121
+ h = '0' + h;
12122
+ }
12123
+ codecstring += h;
12566
12124
  }
12125
+ track.codec = codecstring;
12567
12126
  }
12568
- if (track.vps !== undefined && track.vps[0] === _this2.initVPS) {
12569
- track.sps.push(unit.data);
12570
- }
12571
- }
12572
- if (!VideoSample) {
12573
- VideoSample = _this2.VideoSample = _this2.createVideoSample(true, pes.pts, pes.dts, '');
12127
+ break;
12574
12128
  }
12575
- VideoSample.key = true;
12576
- break;
12577
-
12578
12129
  // PPS
12579
- case 34:
12130
+ case 8:
12580
12131
  push = true;
12581
- if (typeof track.params === 'object') {
12582
- if (!track.pps) {
12583
- track.pps = [];
12584
- var _config2 = _this2.readPPS(unit.data);
12585
- for (var _prop in _config2) {
12586
- track.params[_prop] = _config2[_prop];
12587
- }
12588
- }
12589
- if (_this2.initVPS !== null || track.pps.length === 0) {
12590
- track.pps.push(unit.data);
12591
- }
12592
- }
12132
+ track.pps = [unit.data];
12593
12133
  break;
12594
-
12595
- // ACCESS UNIT DELIMITER
12596
- case 35:
12134
+ // AUD
12135
+ case 9:
12597
12136
  push = true;
12598
12137
  track.audFound = true;
12599
12138
  if (VideoSample) {
12600
- _this2.pushAccessUnit(VideoSample, track);
12139
+ _this.pushAccessUnit(VideoSample, track);
12601
12140
  }
12602
- VideoSample = _this2.VideoSample = _this2.createVideoSample(false, pes.pts, pes.dts, '');
12141
+ VideoSample = _this.VideoSample = _this.createVideoSample(false, pes.pts, pes.dts, '');
12142
+ break;
12143
+ // Filler Data
12144
+ case 12:
12145
+ push = true;
12603
12146
  break;
12604
12147
  default:
12605
12148
  push = false;
12606
12149
  if (VideoSample) {
12607
- VideoSample.debug += 'unknown or irrelevant NAL ' + unit.type + ' ';
12150
+ VideoSample.debug += 'unknown NAL ' + unit.type + ' ';
12608
12151
  }
12609
12152
  break;
12610
12153
  }
@@ -12619,425 +12162,111 @@
12619
12162
  this.VideoSample = null;
12620
12163
  }
12621
12164
  };
12622
- _proto.getNALuType = function getNALuType(data, offset) {
12623
- return (data[offset] & 0x7e) >>> 1;
12624
- };
12625
- _proto.ebsp2rbsp = function ebsp2rbsp(arr) {
12626
- var dst = new Uint8Array(arr.byteLength);
12627
- var dstIdx = 0;
12628
- for (var i = 0; i < arr.byteLength; i++) {
12629
- if (i >= 2) {
12630
- // Unescape: Skip 0x03 after 00 00
12631
- if (arr[i] === 0x03 && arr[i - 1] === 0x00 && arr[i - 2] === 0x00) {
12632
- continue;
12633
- }
12634
- }
12635
- dst[dstIdx] = arr[i];
12636
- dstIdx++;
12637
- }
12638
- return new Uint8Array(dst.buffer, 0, dstIdx);
12639
- };
12640
- _proto.readVPS = function readVPS(vps) {
12641
- var eg = new ExpGolomb(vps);
12642
- // remove header
12643
- eg.readUByte();
12644
- eg.readUByte();
12645
- eg.readBits(4); // video_parameter_set_id
12646
- eg.skipBits(2);
12647
- eg.readBits(6); // max_layers_minus1
12648
- var max_sub_layers_minus1 = eg.readBits(3);
12649
- var temporal_id_nesting_flag = eg.readBoolean();
12650
- // ...vui fps can be here, but empty fps value is not critical for metadata
12165
+ _proto.parseAVCNALu = function parseAVCNALu(track, array) {
12166
+ var len = array.byteLength;
12167
+ var state = track.naluState || 0;
12168
+ var lastState = state;
12169
+ var units = [];
12170
+ var i = 0;
12171
+ var value;
12172
+ var overflow;
12173
+ var unitType;
12174
+ var lastUnitStart = -1;
12175
+ var lastUnitType = 0;
12176
+ // logger.log('PES:' + Hex.hexDump(array));
12651
12177
 
12652
- return {
12653
- numTemporalLayers: max_sub_layers_minus1 + 1,
12654
- temporalIdNested: temporal_id_nesting_flag
12655
- };
12656
- };
12657
- _proto.readSPS = function readSPS(sps) {
12658
- var eg = new ExpGolomb(this.ebsp2rbsp(sps));
12659
- eg.readUByte();
12660
- eg.readUByte();
12661
- eg.readBits(4); //video_parameter_set_id
12662
- var max_sub_layers_minus1 = eg.readBits(3);
12663
- eg.readBoolean(); // temporal_id_nesting_flag
12664
-
12665
- // profile_tier_level
12666
- var general_profile_space = eg.readBits(2);
12667
- var general_tier_flag = eg.readBoolean();
12668
- var general_profile_idc = eg.readBits(5);
12669
- var general_profile_compatibility_flags_1 = eg.readUByte();
12670
- var general_profile_compatibility_flags_2 = eg.readUByte();
12671
- var general_profile_compatibility_flags_3 = eg.readUByte();
12672
- var general_profile_compatibility_flags_4 = eg.readUByte();
12673
- var general_constraint_indicator_flags_1 = eg.readUByte();
12674
- var general_constraint_indicator_flags_2 = eg.readUByte();
12675
- var general_constraint_indicator_flags_3 = eg.readUByte();
12676
- var general_constraint_indicator_flags_4 = eg.readUByte();
12677
- var general_constraint_indicator_flags_5 = eg.readUByte();
12678
- var general_constraint_indicator_flags_6 = eg.readUByte();
12679
- var general_level_idc = eg.readUByte();
12680
- var sub_layer_profile_present_flags = [];
12681
- var sub_layer_level_present_flags = [];
12682
- for (var i = 0; i < max_sub_layers_minus1; i++) {
12683
- sub_layer_profile_present_flags.push(eg.readBoolean());
12684
- sub_layer_level_present_flags.push(eg.readBoolean());
12685
- }
12686
- if (max_sub_layers_minus1 > 0) {
12687
- for (var _i = max_sub_layers_minus1; _i < 8; _i++) {
12688
- eg.readBits(2);
12689
- }
12690
- }
12691
- for (var _i2 = 0; _i2 < max_sub_layers_minus1; _i2++) {
12692
- if (sub_layer_profile_present_flags[_i2]) {
12693
- eg.readUByte(); // sub_layer_profile_space, sub_layer_tier_flag, sub_layer_profile_idc
12694
- eg.readUByte();
12695
- eg.readUByte();
12696
- eg.readUByte();
12697
- eg.readUByte(); // sub_layer_profile_compatibility_flag
12698
- eg.readUByte();
12699
- eg.readUByte();
12700
- eg.readUByte();
12701
- eg.readUByte();
12702
- eg.readUByte();
12703
- eg.readUByte();
12704
- }
12705
- if (sub_layer_level_present_flags[_i2]) {
12706
- eg.readUByte();
12707
- }
12708
- }
12709
- eg.readUEG(); // seq_parameter_set_id
12710
- var chroma_format_idc = eg.readUEG();
12711
- if (chroma_format_idc == 3) {
12712
- eg.skipBits(1); //separate_colour_plane_flag
12713
- }
12714
- var pic_width_in_luma_samples = eg.readUEG();
12715
- var pic_height_in_luma_samples = eg.readUEG();
12716
- var conformance_window_flag = eg.readBoolean();
12717
- var pic_left_offset = 0,
12718
- pic_right_offset = 0,
12719
- pic_top_offset = 0,
12720
- pic_bottom_offset = 0;
12721
- if (conformance_window_flag) {
12722
- pic_left_offset += eg.readUEG();
12723
- pic_right_offset += eg.readUEG();
12724
- pic_top_offset += eg.readUEG();
12725
- pic_bottom_offset += eg.readUEG();
12726
- }
12727
- var bit_depth_luma_minus8 = eg.readUEG();
12728
- var bit_depth_chroma_minus8 = eg.readUEG();
12729
- var log2_max_pic_order_cnt_lsb_minus4 = eg.readUEG();
12730
- var sub_layer_ordering_info_present_flag = eg.readBoolean();
12731
- for (var _i3 = sub_layer_ordering_info_present_flag ? 0 : max_sub_layers_minus1; _i3 <= max_sub_layers_minus1; _i3++) {
12732
- eg.skipUEG(); // max_dec_pic_buffering_minus1[i]
12733
- eg.skipUEG(); // max_num_reorder_pics[i]
12734
- eg.skipUEG(); // max_latency_increase_plus1[i]
12735
- }
12736
- eg.skipUEG(); // log2_min_luma_coding_block_size_minus3
12737
- eg.skipUEG(); // log2_diff_max_min_luma_coding_block_size
12738
- eg.skipUEG(); // log2_min_transform_block_size_minus2
12739
- eg.skipUEG(); // log2_diff_max_min_transform_block_size
12740
- eg.skipUEG(); // max_transform_hierarchy_depth_inter
12741
- eg.skipUEG(); // max_transform_hierarchy_depth_intra
12742
- var scaling_list_enabled_flag = eg.readBoolean();
12743
- if (scaling_list_enabled_flag) {
12744
- var sps_scaling_list_data_present_flag = eg.readBoolean();
12745
- if (sps_scaling_list_data_present_flag) {
12746
- for (var sizeId = 0; sizeId < 4; sizeId++) {
12747
- for (var matrixId = 0; matrixId < (sizeId === 3 ? 2 : 6); matrixId++) {
12748
- var scaling_list_pred_mode_flag = eg.readBoolean();
12749
- if (!scaling_list_pred_mode_flag) {
12750
- eg.readUEG(); // scaling_list_pred_matrix_id_delta
12751
- } else {
12752
- var coefNum = Math.min(64, 1 << 4 + (sizeId << 1));
12753
- if (sizeId > 1) {
12754
- eg.readEG();
12755
- }
12756
- for (var _i4 = 0; _i4 < coefNum; _i4++) {
12757
- eg.readEG();
12758
- }
12759
- }
12760
- }
12761
- }
12762
- }
12178
+ if (state === -1) {
12179
+ // special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet
12180
+ lastUnitStart = 0;
12181
+ // NALu type is value read from offset 0
12182
+ lastUnitType = array[0] & 0x1f;
12183
+ state = 0;
12184
+ i = 1;
12763
12185
  }
12764
- eg.readBoolean(); // amp_enabled_flag
12765
- eg.readBoolean(); // sample_adaptive_offset_enabled_flag
12766
- var pcm_enabled_flag = eg.readBoolean();
12767
- if (pcm_enabled_flag) {
12768
- eg.readUByte();
12769
- eg.skipUEG();
12770
- eg.skipUEG();
12771
- eg.readBoolean();
12772
- }
12773
- var num_short_term_ref_pic_sets = eg.readUEG();
12774
- var num_delta_pocs = 0;
12775
- for (var _i5 = 0; _i5 < num_short_term_ref_pic_sets; _i5++) {
12776
- var inter_ref_pic_set_prediction_flag = false;
12777
- if (_i5 !== 0) {
12778
- inter_ref_pic_set_prediction_flag = eg.readBoolean();
12779
- }
12780
- if (inter_ref_pic_set_prediction_flag) {
12781
- if (_i5 === num_short_term_ref_pic_sets) {
12782
- eg.readUEG();
12783
- }
12784
- eg.readBoolean();
12785
- eg.readUEG();
12786
- var next_num_delta_pocs = 0;
12787
- for (var j = 0; j <= num_delta_pocs; j++) {
12788
- var used_by_curr_pic_flag = eg.readBoolean();
12789
- var use_delta_flag = false;
12790
- if (!used_by_curr_pic_flag) {
12791
- use_delta_flag = eg.readBoolean();
12792
- }
12793
- if (used_by_curr_pic_flag || use_delta_flag) {
12794
- next_num_delta_pocs++;
12795
- }
12796
- }
12797
- num_delta_pocs = next_num_delta_pocs;
12798
- } else {
12799
- var num_negative_pics = eg.readUEG();
12800
- var num_positive_pics = eg.readUEG();
12801
- num_delta_pocs = num_negative_pics + num_positive_pics;
12802
- for (var _j = 0; _j < num_negative_pics; _j++) {
12803
- eg.readUEG();
12804
- eg.readBoolean();
12805
- }
12806
- for (var _j2 = 0; _j2 < num_positive_pics; _j2++) {
12807
- eg.readUEG();
12808
- eg.readBoolean();
12809
- }
12810
- }
12811
- }
12812
- var long_term_ref_pics_present_flag = eg.readBoolean();
12813
- if (long_term_ref_pics_present_flag) {
12814
- var num_long_term_ref_pics_sps = eg.readUEG();
12815
- for (var _i6 = 0; _i6 < num_long_term_ref_pics_sps; _i6++) {
12816
- for (var _j3 = 0; _j3 < log2_max_pic_order_cnt_lsb_minus4 + 4; _j3++) {
12817
- eg.readBits(1);
12818
- }
12819
- eg.readBits(1);
12820
- }
12821
- }
12822
- var min_spatial_segmentation_idc = 0;
12823
- var sar_width = 1,
12824
- sar_height = 1;
12825
- var fps_fixed = true,
12826
- fps_den = 1,
12827
- fps_num = 0;
12828
- eg.readBoolean(); // sps_temporal_mvp_enabled_flag
12829
- eg.readBoolean(); // strong_intra_smoothing_enabled_flag
12830
- var default_display_window_flag = false;
12831
- var vui_parameters_present_flag = eg.readBoolean();
12832
- if (vui_parameters_present_flag) {
12833
- var aspect_ratio_info_present_flag = eg.readBoolean();
12834
- if (aspect_ratio_info_present_flag) {
12835
- var aspect_ratio_idc = eg.readUByte();
12836
- var sar_width_table = [1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2];
12837
- var sar_height_table = [1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1];
12838
- if (aspect_ratio_idc > 0 && aspect_ratio_idc < 16) {
12839
- sar_width = sar_width_table[aspect_ratio_idc - 1];
12840
- sar_height = sar_height_table[aspect_ratio_idc - 1];
12841
- } else if (aspect_ratio_idc === 255) {
12842
- sar_width = eg.readBits(16);
12843
- sar_height = eg.readBits(16);
12844
- }
12845
- }
12846
- var overscan_info_present_flag = eg.readBoolean();
12847
- if (overscan_info_present_flag) {
12848
- eg.readBoolean();
12849
- }
12850
- var video_signal_type_present_flag = eg.readBoolean();
12851
- if (video_signal_type_present_flag) {
12852
- eg.readBits(3);
12853
- eg.readBoolean();
12854
- var colour_description_present_flag = eg.readBoolean();
12855
- if (colour_description_present_flag) {
12856
- eg.readUByte();
12857
- eg.readUByte();
12858
- eg.readUByte();
12859
- }
12860
- }
12861
- var chroma_loc_info_present_flag = eg.readBoolean();
12862
- if (chroma_loc_info_present_flag) {
12863
- eg.readUEG();
12864
- eg.readUEG();
12865
- }
12866
- eg.readBoolean(); // neutral_chroma_indication_flag
12867
- eg.readBoolean(); // field_seq_flag
12868
- eg.readBoolean(); // frame_field_info_present_flag
12869
- default_display_window_flag = eg.readBoolean();
12870
- if (default_display_window_flag) {
12871
- pic_left_offset += eg.readUEG();
12872
- pic_right_offset += eg.readUEG();
12873
- pic_top_offset += eg.readUEG();
12874
- pic_bottom_offset += eg.readUEG();
12875
- }
12876
- var vui_timing_info_present_flag = eg.readBoolean();
12877
- if (vui_timing_info_present_flag) {
12878
- fps_den = eg.readBits(32);
12879
- fps_num = eg.readBits(32);
12880
- var vui_poc_proportional_to_timing_flag = eg.readBoolean();
12881
- if (vui_poc_proportional_to_timing_flag) {
12882
- eg.readUEG();
12883
- }
12884
- var vui_hrd_parameters_present_flag = eg.readBoolean();
12885
- if (vui_hrd_parameters_present_flag) {
12886
- //const commonInfPresentFlag = true;
12887
- //if (commonInfPresentFlag) {
12888
- var nal_hrd_parameters_present_flag = eg.readBoolean();
12889
- var vcl_hrd_parameters_present_flag = eg.readBoolean();
12890
- var sub_pic_hrd_params_present_flag = false;
12891
- if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag) {
12892
- sub_pic_hrd_params_present_flag = eg.readBoolean();
12893
- if (sub_pic_hrd_params_present_flag) {
12894
- eg.readUByte();
12895
- eg.readBits(5);
12896
- eg.readBoolean();
12897
- eg.readBits(5);
12898
- }
12899
- eg.readBits(4); // bit_rate_scale
12900
- eg.readBits(4); // cpb_size_scale
12901
- if (sub_pic_hrd_params_present_flag) {
12902
- eg.readBits(4);
12903
- }
12904
- eg.readBits(5);
12905
- eg.readBits(5);
12906
- eg.readBits(5);
12907
- }
12908
- //}
12909
- for (var _i7 = 0; _i7 <= max_sub_layers_minus1; _i7++) {
12910
- fps_fixed = eg.readBoolean(); // fixed_pic_rate_general_flag
12911
- var fixed_pic_rate_within_cvs_flag = fps_fixed || eg.readBoolean();
12912
- var low_delay_hrd_flag = false;
12913
- if (fixed_pic_rate_within_cvs_flag) {
12914
- eg.readEG();
12915
- } else {
12916
- low_delay_hrd_flag = eg.readBoolean();
12917
- }
12918
- var cpb_cnt = low_delay_hrd_flag ? 1 : eg.readUEG() + 1;
12919
- if (nal_hrd_parameters_present_flag) {
12920
- for (var _j4 = 0; _j4 < cpb_cnt; _j4++) {
12921
- eg.readUEG();
12922
- eg.readUEG();
12923
- if (sub_pic_hrd_params_present_flag) {
12924
- eg.readUEG();
12925
- eg.readUEG();
12926
- }
12927
- eg.skipBits(1);
12186
+ while (i < len) {
12187
+ value = array[i++];
12188
+ // optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case
12189
+ if (!state) {
12190
+ state = value ? 0 : 1;
12191
+ continue;
12192
+ }
12193
+ if (state === 1) {
12194
+ state = value ? 0 : 2;
12195
+ continue;
12196
+ }
12197
+ // here we have state either equal to 2 or 3
12198
+ if (!value) {
12199
+ state = 3;
12200
+ } else if (value === 1) {
12201
+ overflow = i - state - 1;
12202
+ if (lastUnitStart >= 0) {
12203
+ var unit = {
12204
+ data: array.subarray(lastUnitStart, overflow),
12205
+ type: lastUnitType
12206
+ };
12207
+ // logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);
12208
+ units.push(unit);
12209
+ } else {
12210
+ // lastUnitStart is undefined => this is the first start code found in this PES packet
12211
+ // first check if start code delimiter is overlapping between 2 PES packets,
12212
+ // ie it started in last packet (lastState not zero)
12213
+ // and ended at the beginning of this PES packet (i <= 4 - lastState)
12214
+ var lastUnit = this.getLastNalUnit(track.samples);
12215
+ if (lastUnit) {
12216
+ if (lastState && i <= 4 - lastState) {
12217
+ // start delimiter overlapping between PES packets
12218
+ // strip start delimiter bytes from the end of last NAL unit
12219
+ // check if lastUnit had a state different from zero
12220
+ if (lastUnit.state) {
12221
+ // strip last bytes
12222
+ lastUnit.data = lastUnit.data.subarray(0, lastUnit.data.byteLength - lastState);
12928
12223
  }
12929
12224
  }
12930
- if (vcl_hrd_parameters_present_flag) {
12931
- for (var _j5 = 0; _j5 < cpb_cnt; _j5++) {
12932
- eg.readUEG();
12933
- eg.readUEG();
12934
- if (sub_pic_hrd_params_present_flag) {
12935
- eg.readUEG();
12936
- eg.readUEG();
12937
- }
12938
- eg.skipBits(1);
12939
- }
12225
+ // If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.
12226
+
12227
+ if (overflow > 0) {
12228
+ // logger.log('first NALU found with overflow:' + overflow);
12229
+ lastUnit.data = appendUint8Array(lastUnit.data, array.subarray(0, overflow));
12230
+ lastUnit.state = 0;
12940
12231
  }
12941
12232
  }
12942
12233
  }
12943
- }
12944
- var bitstream_restriction_flag = eg.readBoolean();
12945
- if (bitstream_restriction_flag) {
12946
- eg.readBoolean(); // tiles_fixed_structure_flag
12947
- eg.readBoolean(); // motion_vectors_over_pic_boundaries_flag
12948
- eg.readBoolean(); // restricted_ref_pic_lists_flag
12949
- min_spatial_segmentation_idc = eg.readUEG();
12950
- }
12951
- }
12952
- var width = pic_width_in_luma_samples,
12953
- height = pic_height_in_luma_samples;
12954
- if (conformance_window_flag || default_display_window_flag) {
12955
- var chroma_scale_w = 1,
12956
- chroma_scale_h = 1;
12957
- if (chroma_format_idc === 1) {
12958
- // YUV 420
12959
- chroma_scale_w = chroma_scale_h = 2;
12960
- } else if (chroma_format_idc == 2) {
12961
- // YUV 422
12962
- chroma_scale_w = 2;
12963
- }
12964
- width = pic_width_in_luma_samples - chroma_scale_w * pic_right_offset - chroma_scale_w * pic_left_offset;
12965
- height = pic_height_in_luma_samples - chroma_scale_h * pic_bottom_offset - chroma_scale_h * pic_top_offset;
12966
- }
12967
- var profile_space_string = general_profile_space ? ['A', 'B', 'C'][general_profile_space] : '';
12968
- 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;
12969
- var profile_compatibility_rev = 0;
12970
- for (var _i8 = 0; _i8 < 32; _i8++) {
12971
- profile_compatibility_rev = (profile_compatibility_rev | (profile_compatibility_buf >> _i8 & 1) << 31 - _i8) >>> 0; // reverse bit position (and cast as UInt32)
12972
- }
12973
- var profile_compatibility_flags_string = profile_compatibility_rev.toString(16);
12974
- if (general_profile_idc === 1 && profile_compatibility_flags_string === '2') {
12975
- profile_compatibility_flags_string = '6';
12976
- }
12977
- var tier_flag_string = general_tier_flag ? 'H' : 'L';
12978
- return {
12979
- codecString: "hvc1." + profile_space_string + general_profile_idc + "." + profile_compatibility_flags_string + "." + tier_flag_string + general_level_idc + ".B0",
12980
- params: {
12981
- general_tier_flag: general_tier_flag,
12982
- general_profile_idc: general_profile_idc,
12983
- general_profile_space: general_profile_space,
12984
- general_profile_compatibility_flags: [general_profile_compatibility_flags_1, general_profile_compatibility_flags_2, general_profile_compatibility_flags_3, general_profile_compatibility_flags_4],
12985
- 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],
12986
- general_level_idc: general_level_idc,
12987
- bit_depth: bit_depth_luma_minus8 + 8,
12988
- bit_depth_luma_minus8: bit_depth_luma_minus8,
12989
- bit_depth_chroma_minus8: bit_depth_chroma_minus8,
12990
- min_spatial_segmentation_idc: min_spatial_segmentation_idc,
12991
- chroma_format_idc: chroma_format_idc,
12992
- frame_rate: {
12993
- fixed: fps_fixed,
12994
- fps: fps_num / fps_den
12234
+ // check if we can read unit type
12235
+ if (i < len) {
12236
+ unitType = array[i] & 0x1f;
12237
+ // logger.log('find NALU @ offset:' + i + ',type:' + unitType);
12238
+ lastUnitStart = i;
12239
+ lastUnitType = unitType;
12240
+ state = 0;
12241
+ } else {
12242
+ // not enough byte to read unit type. let's read it on next PES parsing
12243
+ state = -1;
12995
12244
  }
12996
- },
12997
- width: width,
12998
- height: height,
12999
- pixelRatio: [sar_width, sar_height]
13000
- };
13001
- };
13002
- _proto.readPPS = function readPPS(pps) {
13003
- var eg = new ExpGolomb(this.ebsp2rbsp(pps));
13004
- eg.readUByte();
13005
- eg.readUByte();
13006
- eg.skipUEG(); // pic_parameter_set_id
13007
- eg.skipUEG(); // seq_parameter_set_id
13008
- eg.skipBits(2); // dependent_slice_segments_enabled_flag, output_flag_present_flag
13009
- eg.skipBits(3); // num_extra_slice_header_bits
13010
- eg.skipBits(2); // sign_data_hiding_enabled_flag, cabac_init_present_flag
13011
- eg.skipUEG();
13012
- eg.skipUEG();
13013
- eg.skipEG(); // init_qp_minus26
13014
- eg.skipBits(2); // constrained_intra_pred_flag, transform_skip_enabled_flag
13015
- var cu_qp_delta_enabled_flag = eg.readBoolean();
13016
- if (cu_qp_delta_enabled_flag) {
13017
- eg.skipUEG();
13018
- }
13019
- eg.skipEG(); // cb_qp_offset
13020
- eg.skipEG(); // cr_qp_offset
13021
- eg.skipBits(4); // pps_slice_chroma_qp_offsets_present_flag, weighted_pred_flag, weighted_bipred_flag, transquant_bypass_enabled_flag
13022
- var tiles_enabled_flag = eg.readBoolean();
13023
- var entropy_coding_sync_enabled_flag = eg.readBoolean();
13024
- var parallelismType = 1; // slice-based parallel decoding
13025
- if (entropy_coding_sync_enabled_flag && tiles_enabled_flag) {
13026
- parallelismType = 0; // mixed-type parallel decoding
13027
- } else if (entropy_coding_sync_enabled_flag) {
13028
- parallelismType = 3; // wavefront-based parallel decoding
13029
- } else if (tiles_enabled_flag) {
13030
- parallelismType = 2; // tile-based parallel decoding
12245
+ } else {
12246
+ state = 0;
12247
+ }
13031
12248
  }
13032
- return {
13033
- parallelismType: parallelismType
13034
- };
13035
- };
13036
- _proto.matchSPS = function matchSPS(sps1, sps2) {
13037
- // compare without headers and VPS related params
13038
- return String.fromCharCode.apply(null, sps1).substr(3) === String.fromCharCode.apply(null, sps2).substr(3);
12249
+ if (lastUnitStart >= 0 && state >= 0) {
12250
+ var _unit = {
12251
+ data: array.subarray(lastUnitStart, len),
12252
+ type: lastUnitType,
12253
+ state: state
12254
+ };
12255
+ units.push(_unit);
12256
+ // logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
12257
+ }
12258
+ // no NALu found
12259
+ if (units.length === 0) {
12260
+ // append pes.data to previous NAL unit
12261
+ var _lastUnit = this.getLastNalUnit(track.samples);
12262
+ if (_lastUnit) {
12263
+ _lastUnit.data = appendUint8Array(_lastUnit.data, array);
12264
+ }
12265
+ }
12266
+ track.naluState = state;
12267
+ return units;
13039
12268
  };
13040
- return HevcVideoParser;
12269
+ return AvcVideoParser;
13041
12270
  }(BaseVideoParser);
13042
12271
 
13043
12272
  /**
@@ -13055,7 +12284,7 @@
13055
12284
  }
13056
12285
  var _proto = SampleAesDecrypter.prototype;
13057
12286
  _proto.decryptBuffer = function decryptBuffer(encryptedData) {
13058
- return this.decrypter.decrypt(encryptedData, this.keyData.key.buffer, this.keyData.iv.buffer, DecrypterAesMode.cbc);
12287
+ return this.decrypter.decrypt(encryptedData, this.keyData.key.buffer, this.keyData.iv.buffer);
13059
12288
  }
13060
12289
 
13061
12290
  // AAC - encrypt all full 16 bytes blocks starting from offset 16
@@ -13174,7 +12403,7 @@
13174
12403
  this.observer = observer;
13175
12404
  this.config = config;
13176
12405
  this.typeSupported = typeSupported;
13177
- this.videoParser = null;
12406
+ this.videoParser = new AvcVideoParser();
13178
12407
  }
13179
12408
  TSDemuxer.probe = function probe(data) {
13180
12409
  var syncOffset = TSDemuxer.syncOffset(data);
@@ -13344,21 +12573,7 @@
13344
12573
  case videoPid:
13345
12574
  if (stt) {
13346
12575
  if (videoData && (pes = parsePES(videoData))) {
13347
- if (this.videoParser === null) {
13348
- switch (videoTrack.segmentCodec) {
13349
- case 'avc':
13350
- this.videoParser = new AvcVideoParser();
13351
- break;
13352
- case 'hevc':
13353
- {
13354
- this.videoParser = new HevcVideoParser();
13355
- }
13356
- break;
13357
- }
13358
- }
13359
- if (this.videoParser !== null) {
13360
- this.videoParser.parsePES(videoTrack, textTrack, pes, false, this._duration);
13361
- }
12576
+ this.videoParser.parseAVCPES(videoTrack, textTrack, pes, false, this._duration);
13362
12577
  }
13363
12578
  videoData = {
13364
12579
  data: [],
@@ -13515,28 +12730,14 @@
13515
12730
  videoTrack = demuxResult.videoTrack,
13516
12731
  id3Track = demuxResult.id3Track,
13517
12732
  textTrack = demuxResult.textTrack;
13518
- var videoData = videoTrack.pesData;
13519
- var audioData = audioTrack.pesData;
13520
- var id3Data = id3Track.pesData;
13521
- // try to parse last PES packets
13522
- var pes;
13523
- if (videoData && (pes = parsePES(videoData))) {
13524
- if (this.videoParser === null) {
13525
- switch (videoTrack.segmentCodec) {
13526
- case 'avc':
13527
- this.videoParser = new AvcVideoParser();
13528
- break;
13529
- case 'hevc':
13530
- {
13531
- this.videoParser = new HevcVideoParser();
13532
- }
13533
- break;
13534
- }
13535
- }
13536
- if (this.videoParser !== null) {
13537
- this.videoParser.parsePES(videoTrack, textTrack, pes, true, this._duration);
13538
- videoTrack.pesData = null;
13539
- }
12733
+ var videoData = videoTrack.pesData;
12734
+ var audioData = audioTrack.pesData;
12735
+ var id3Data = id3Track.pesData;
12736
+ // try to parse last PES packets
12737
+ var pes;
12738
+ if (videoData && (pes = parsePES(videoData))) {
12739
+ this.videoParser.parseAVCPES(videoTrack, textTrack, pes, true, this._duration);
12740
+ videoTrack.pesData = null;
13540
12741
  } else {
13541
12742
  // either avcData null or PES truncated, keep it for next frag parsing
13542
12743
  videoTrack.pesData = videoData;
@@ -13868,14 +13069,7 @@
13868
13069
  logger.warn('Unsupported EC-3 in M2TS found');
13869
13070
  break;
13870
13071
  case 0x24:
13871
- // ITU-T Rec. H.265 and ISO/IEC 23008-2 (HEVC)
13872
- {
13873
- if (result.videoPid === -1) {
13874
- result.videoPid = pid;
13875
- result.segmentVideoCodec = 'hevc';
13876
- logger.log('HEVC in M2TS found');
13877
- }
13878
- }
13072
+ logger.warn('Unsupported HEVC in M2TS found');
13879
13073
  break;
13880
13074
  }
13881
13075
  // move to the next table entry
@@ -14103,8 +13297,6 @@
14103
13297
  avc1: [],
14104
13298
  // codingname
14105
13299
  avcC: [],
14106
- hvc1: [],
14107
- hvcC: [],
14108
13300
  btrt: [],
14109
13301
  dinf: [],
14110
13302
  dref: [],
@@ -14532,10 +13724,8 @@
14532
13724
  return MP4.box(MP4.types.stsd, MP4.STSD, MP4.ac3(track));
14533
13725
  }
14534
13726
  return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track));
14535
- } else if (track.segmentCodec === 'avc') {
14536
- return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));
14537
13727
  } else {
14538
- return MP4.box(MP4.types.stsd, MP4.STSD, MP4.hvc1(track));
13728
+ return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));
14539
13729
  }
14540
13730
  };
14541
13731
  MP4.tkhd = function tkhd(track) {
@@ -14673,84 +13863,6 @@
14673
13863
  var result = appendUint8Array(MP4.FTYP, movie);
14674
13864
  return result;
14675
13865
  };
14676
- MP4.hvc1 = function hvc1(track) {
14677
- var ps = track.params;
14678
- var units = [track.vps, track.sps, track.pps];
14679
- var NALuLengthSize = 4;
14680
- 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]);
14681
-
14682
- // compute hvcC size in bytes
14683
- var length = config.length;
14684
- for (var i = 0; i < units.length; i += 1) {
14685
- length += 3;
14686
- for (var j = 0; j < units[i].length; j += 1) {
14687
- length += 2 + units[i][j].length;
14688
- }
14689
- }
14690
- var hvcC = new Uint8Array(length);
14691
- hvcC.set(config, 0);
14692
- length = config.length;
14693
- // append parameter set units: one vps, one or more sps and pps
14694
- var iMax = units.length - 1;
14695
- for (var _i = 0; _i < units.length; _i += 1) {
14696
- hvcC.set(new Uint8Array([32 + _i | (_i === iMax ? 128 : 0), 0x00, units[_i].length]), length);
14697
- length += 3;
14698
- for (var _j = 0; _j < units[_i].length; _j += 1) {
14699
- hvcC.set(new Uint8Array([units[_i][_j].length >> 8, units[_i][_j].length & 255]), length);
14700
- length += 2;
14701
- hvcC.set(units[_i][_j], length);
14702
- length += units[_i][_j].length;
14703
- }
14704
- }
14705
- var hvcc = MP4.box(MP4.types.hvcC, hvcC);
14706
- var width = track.width;
14707
- var height = track.height;
14708
- var hSpacing = track.pixelRatio[0];
14709
- var vSpacing = track.pixelRatio[1];
14710
- return MP4.box(MP4.types.hvc1, new Uint8Array([0x00, 0x00, 0x00,
14711
- // reserved
14712
- 0x00, 0x00, 0x00,
14713
- // reserved
14714
- 0x00, 0x01,
14715
- // data_reference_index
14716
- 0x00, 0x00,
14717
- // pre_defined
14718
- 0x00, 0x00,
14719
- // reserved
14720
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
14721
- // pre_defined
14722
- width >> 8 & 0xff, width & 0xff,
14723
- // width
14724
- height >> 8 & 0xff, height & 0xff,
14725
- // height
14726
- 0x00, 0x48, 0x00, 0x00,
14727
- // horizresolution
14728
- 0x00, 0x48, 0x00, 0x00,
14729
- // vertresolution
14730
- 0x00, 0x00, 0x00, 0x00,
14731
- // reserved
14732
- 0x00, 0x01,
14733
- // frame_count
14734
- 0x12, 0x64, 0x61, 0x69, 0x6c,
14735
- // dailymotion/hls.js
14736
- 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,
14737
- // compressorname
14738
- 0x00, 0x18,
14739
- // depth = 24
14740
- 0x11, 0x11]),
14741
- // pre_defined = -1
14742
- hvcc, MP4.box(MP4.types.btrt, new Uint8Array([0x00, 0x1c, 0x9c, 0x80,
14743
- // bufferSizeDB
14744
- 0x00, 0x2d, 0xc6, 0xc0,
14745
- // maxBitrate
14746
- 0x00, 0x2d, 0xc6, 0xc0])),
14747
- // avgBitrate
14748
- MP4.box(MP4.types.pasp, new Uint8Array([hSpacing >> 24,
14749
- // hSpacing
14750
- hSpacing >> 16 & 0xff, hSpacing >> 8 & 0xff, hSpacing & 0xff, vSpacing >> 24,
14751
- // vSpacing
14752
- vSpacing >> 16 & 0xff, vSpacing >> 8 & 0xff, vSpacing & 0xff])));
14753
- };
14754
13866
  return MP4;
14755
13867
  }();
14756
13868
  MP4.types = void 0;
@@ -15152,9 +14264,9 @@
15152
14264
  var foundOverlap = delta < -1;
15153
14265
  if (foundHole || foundOverlap) {
15154
14266
  if (foundHole) {
15155
- logger.warn((track.segmentCodec || '').toUpperCase() + ": " + toMsFromMpegTsClock(delta, true) + " ms (" + delta + "dts) hole between fragments detected at " + timeOffset.toFixed(3));
14267
+ logger.warn("AVC: " + toMsFromMpegTsClock(delta, true) + " ms (" + delta + "dts) hole between fragments detected at " + timeOffset.toFixed(3));
15156
14268
  } else {
15157
- logger.warn((track.segmentCodec || '').toUpperCase() + ": " + toMsFromMpegTsClock(-delta, true) + " ms (" + delta + "dts) overlapping between fragments detected at " + timeOffset.toFixed(3));
14269
+ logger.warn("AVC: " + toMsFromMpegTsClock(-delta, true) + " ms (" + delta + "dts) overlapping between fragments detected at " + timeOffset.toFixed(3));
15158
14270
  }
15159
14271
  if (!foundOverlap || nextAvcDts >= inputSamples[0].pts || chromeVersion) {
15160
14272
  firstDTS = nextAvcDts;
@@ -15163,24 +14275,12 @@
15163
14275
  inputSamples[0].dts = firstDTS;
15164
14276
  inputSamples[0].pts = firstPTS;
15165
14277
  } else {
15166
- var isPTSOrderRetained = true;
15167
14278
  for (var _i = 0; _i < inputSamples.length; _i++) {
15168
- if (inputSamples[_i].dts > firstPTS && isPTSOrderRetained) {
14279
+ if (inputSamples[_i].dts > firstPTS) {
15169
14280
  break;
15170
14281
  }
15171
- var prevPTS = inputSamples[_i].pts;
15172
14282
  inputSamples[_i].dts -= delta;
15173
14283
  inputSamples[_i].pts -= delta;
15174
-
15175
- // check to see if this sample's PTS order has changed
15176
- // relative to the next one
15177
- if (_i < inputSamples.length - 1) {
15178
- var nextSamplePTS = inputSamples[_i + 1].pts;
15179
- var currentSamplePTS = inputSamples[_i].pts;
15180
- var currentOrder = nextSamplePTS <= currentSamplePTS;
15181
- var prevOrder = nextSamplePTS <= prevPTS;
15182
- isPTSOrderRetained = currentOrder == prevOrder;
15183
- }
15184
14284
  }
15185
14285
  }
15186
14286
  logger.log("Video: Initial PTS/DTS adjusted: " + toMsFromMpegTsClock(firstPTS, true) + "/" + toMsFromMpegTsClock(firstDTS, true) + ", delta: " + toMsFromMpegTsClock(delta, true) + " ms");
@@ -15328,7 +14428,7 @@
15328
14428
  }
15329
14429
  }
15330
14430
  }
15331
- // next AVC/HEVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)
14431
+ // next AVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)
15332
14432
  mp4SampleDuration = stretchedLastFrame || !mp4SampleDuration ? averageSampleDuration : mp4SampleDuration;
15333
14433
  this.nextAvcDts = nextAvcDts = lastDTS + mp4SampleDuration;
15334
14434
  this.videoSampleDuration = mp4SampleDuration;
@@ -15463,7 +14563,7 @@
15463
14563
  logger.warn("[mp4-remuxer]: Injecting " + missing + " audio frame @ " + (nextPts / inputTimeScale).toFixed(3) + "s due to " + Math.round(1000 * delta / inputTimeScale) + " ms gap.");
15464
14564
  for (var j = 0; j < missing; j++) {
15465
14565
  var newStamp = Math.max(nextPts, 0);
15466
- var fillFrame = AAC.getSilentFrame(track.parsedCodec || track.manifestCodec || track.codec, track.channelCount);
14566
+ var fillFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
15467
14567
  if (!fillFrame) {
15468
14568
  logger.log('[mp4-remuxer]: Unable to get silent frame for given audio codec; duplicating last frame instead.');
15469
14569
  fillFrame = sample.unit.subarray();
@@ -15591,7 +14691,7 @@
15591
14691
  // samples count of this segment's duration
15592
14692
  var nbSamples = Math.ceil((endDTS - startDTS) / frameDuration);
15593
14693
  // silent frame
15594
- var silentFrame = AAC.getSilentFrame(track.parsedCodec || track.manifestCodec || track.codec, track.channelCount);
14694
+ var silentFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
15595
14695
  logger.warn('[mp4-remuxer]: remux empty Audio');
15596
14696
  // Can't remux if we can't generate a silent frame...
15597
14697
  if (!silentFrame) {
@@ -15981,15 +15081,13 @@
15981
15081
  duration = transmuxConfig.duration,
15982
15082
  initSegmentData = transmuxConfig.initSegmentData;
15983
15083
  var keyData = getEncryptionType(uintData, decryptdata);
15984
- if (keyData && isFullSegmentEncryption(keyData.method)) {
15084
+ if (keyData && keyData.method === 'AES-128') {
15985
15085
  var decrypter = this.getDecrypter();
15986
- var aesMode = getAesModeFromFullSegmentMethod(keyData.method);
15987
-
15988
15086
  // Software decryption is synchronous; webCrypto is not
15989
15087
  if (decrypter.isSync()) {
15990
15088
  // Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
15991
15089
  // data is handled in the flush() call
15992
- var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer, aesMode);
15090
+ var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer);
15993
15091
  // For Low-Latency HLS Parts, decrypt in place, since part parsing is expected on push progress
15994
15092
  var loadingParts = chunkMeta.part > -1;
15995
15093
  if (loadingParts) {
@@ -16001,7 +15099,7 @@
16001
15099
  }
16002
15100
  uintData = new Uint8Array(decryptedData);
16003
15101
  } else {
16004
- this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer, aesMode).then(function (decryptedData) {
15102
+ this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer).then(function (decryptedData) {
16005
15103
  // Calling push here is important; if flush() is called while this is still resolving, this ensures that
16006
15104
  // the decrypted data has been transmuxed
16007
15105
  var result = _this.push(decryptedData, null, chunkMeta);
@@ -16622,7 +15720,7 @@
16622
15720
  observer.on(Events.ERROR, forwardMessage);
16623
15721
 
16624
15722
  // forward logger events to main thread
16625
- var forwardWorkerLogs = function forwardWorkerLogs(logger) {
15723
+ var forwardWorkerLogs = function forwardWorkerLogs() {
16626
15724
  var _loop = function _loop(logFn) {
16627
15725
  var func = function func(message) {
16628
15726
  forwardMessage('workerLog', {
@@ -16643,8 +15741,8 @@
16643
15741
  {
16644
15742
  var config = JSON.parse(data.config);
16645
15743
  self.transmuxer = new Transmuxer(observer, data.typeSupported, config, data.vendor, data.id);
16646
- var logger = enableLogs(config.debug, data.id);
16647
- forwardWorkerLogs(logger);
15744
+ enableLogs(config.debug, data.id);
15745
+ forwardWorkerLogs();
16648
15746
  forwardMessage('init', null);
16649
15747
  break;
16650
15748
  }
@@ -16818,7 +15916,16 @@
16818
15916
  this.observer = new EventEmitter();
16819
15917
  this.observer.on(Events.FRAG_DECRYPTED, forwardMessage);
16820
15918
  this.observer.on(Events.ERROR, forwardMessage);
16821
- var m2tsTypeSupported = getM2TSSupportedAudioTypes(config.preferManagedMediaSource);
15919
+ var MediaSource = getMediaSource(config.preferManagedMediaSource) || {
15920
+ isTypeSupported: function isTypeSupported() {
15921
+ return false;
15922
+ }
15923
+ };
15924
+ var m2tsTypeSupported = {
15925
+ mpeg: MediaSource.isTypeSupported('audio/mpeg'),
15926
+ mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
15927
+ ac3: MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"')
15928
+ };
16822
15929
 
16823
15930
  // navigator.vendor is not always available in Web Worker
16824
15931
  // refer to https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/navigator
@@ -17102,7 +16209,7 @@
17102
16209
  _inheritsLoose(AudioStreamController, _BaseStreamController);
17103
16210
  function AudioStreamController(hls, fragmentTracker, keyLoader) {
17104
16211
  var _this;
17105
- _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'audio-stream-controller', PlaylistLevelType.AUDIO) || this;
16212
+ _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[audio-stream-controller]', PlaylistLevelType.AUDIO) || this;
17106
16213
  _this.videoBuffer = null;
17107
16214
  _this.videoTrackCC = -1;
17108
16215
  _this.waitingVideoCC = -1;
@@ -17114,24 +16221,27 @@
17114
16221
  _this.flushing = false;
17115
16222
  _this.bufferFlushed = false;
17116
16223
  _this.cachedTrackLoadedData = null;
17117
- _this.registerListeners();
16224
+ _this._registerListeners();
17118
16225
  return _this;
17119
16226
  }
17120
16227
  var _proto = AudioStreamController.prototype;
17121
16228
  _proto.onHandlerDestroying = function onHandlerDestroying() {
17122
- this.unregisterListeners();
16229
+ this._unregisterListeners();
17123
16230
  _BaseStreamController.prototype.onHandlerDestroying.call(this);
17124
16231
  this.mainDetails = null;
17125
16232
  this.bufferedTrack = null;
17126
16233
  this.switchingTrack = null;
17127
16234
  };
17128
- _proto.registerListeners = function registerListeners() {
17129
- _BaseStreamController.prototype.registerListeners.call(this);
16235
+ _proto._registerListeners = function _registerListeners() {
17130
16236
  var hls = this.hls;
16237
+ hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
16238
+ hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
16239
+ hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
17131
16240
  hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
17132
16241
  hls.on(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
17133
16242
  hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
17134
16243
  hls.on(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
16244
+ hls.on(Events.ERROR, this.onError, this);
17135
16245
  hls.on(Events.BUFFER_RESET, this.onBufferReset, this);
17136
16246
  hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
17137
16247
  hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
@@ -17139,16 +16249,16 @@
17139
16249
  hls.on(Events.INIT_PTS_FOUND, this.onInitPtsFound, this);
17140
16250
  hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
17141
16251
  };
17142
- _proto.unregisterListeners = function unregisterListeners() {
16252
+ _proto._unregisterListeners = function _unregisterListeners() {
17143
16253
  var hls = this.hls;
17144
- if (!hls) {
17145
- return;
17146
- }
17147
- _BaseStreamController.prototype.unregisterListeners.call(this);
16254
+ hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
16255
+ hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
16256
+ hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
17148
16257
  hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
17149
16258
  hls.off(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
17150
16259
  hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
17151
16260
  hls.off(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
16261
+ hls.off(Events.ERROR, this.onError, this);
17152
16262
  hls.off(Events.BUFFER_RESET, this.onBufferReset, this);
17153
16263
  hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
17154
16264
  hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
@@ -17307,13 +16417,12 @@
17307
16417
  trackId = this.trackId;
17308
16418
  var config = hls.config;
17309
16419
 
17310
- // 1. if buffering is suspended
17311
- // 2. if video not attached AND
16420
+ // 1. if video not attached AND
17312
16421
  // start fragment already requested OR start frag prefetch not enabled
17313
- // 3. if tracks or track not loaded and selected
16422
+ // 2. if tracks or track not loaded and selected
17314
16423
  // then exit loop
17315
16424
  // => if media not attached but start frag prefetch is enabled and start frag not requested yet, we will not exit loop
17316
- if (!this.buffering || !media && (this.startFragRequested || !config.startFragPrefetch) || !(levels != null && levels[trackId])) {
16425
+ if (!media && (this.startFragRequested || !config.startFragPrefetch) || !(levels != null && levels[trackId])) {
17317
16426
  return;
17318
16427
  }
17319
16428
  var levelInfo = levels[trackId];
@@ -17842,7 +16951,7 @@
17842
16951
  _inheritsLoose(AudioTrackController, _BasePlaylistControll);
17843
16952
  function AudioTrackController(hls) {
17844
16953
  var _this;
17845
- _this = _BasePlaylistControll.call(this, hls, 'audio-track-controller') || this;
16954
+ _this = _BasePlaylistControll.call(this, hls, '[audio-track-controller]') || this;
17846
16955
  _this.tracks = [];
17847
16956
  _this.groupIds = null;
17848
16957
  _this.tracksInGroup = [];
@@ -18171,23 +17280,26 @@
18171
17280
  _inheritsLoose(SubtitleStreamController, _BaseStreamController);
18172
17281
  function SubtitleStreamController(hls, fragmentTracker, keyLoader) {
18173
17282
  var _this;
18174
- _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'subtitle-stream-controller', PlaylistLevelType.SUBTITLE) || this;
17283
+ _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[subtitle-stream-controller]', PlaylistLevelType.SUBTITLE) || this;
18175
17284
  _this.currentTrackId = -1;
18176
17285
  _this.tracksBuffered = [];
18177
17286
  _this.mainDetails = null;
18178
- _this.registerListeners();
17287
+ _this._registerListeners();
18179
17288
  return _this;
18180
17289
  }
18181
17290
  var _proto = SubtitleStreamController.prototype;
18182
17291
  _proto.onHandlerDestroying = function onHandlerDestroying() {
18183
- this.unregisterListeners();
17292
+ this._unregisterListeners();
18184
17293
  _BaseStreamController.prototype.onHandlerDestroying.call(this);
18185
17294
  this.mainDetails = null;
18186
17295
  };
18187
- _proto.registerListeners = function registerListeners() {
18188
- _BaseStreamController.prototype.registerListeners.call(this);
17296
+ _proto._registerListeners = function _registerListeners() {
18189
17297
  var hls = this.hls;
17298
+ hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
17299
+ hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
17300
+ hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
18190
17301
  hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
17302
+ hls.on(Events.ERROR, this.onError, this);
18191
17303
  hls.on(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);
18192
17304
  hls.on(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);
18193
17305
  hls.on(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);
@@ -18195,10 +17307,13 @@
18195
17307
  hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
18196
17308
  hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
18197
17309
  };
18198
- _proto.unregisterListeners = function unregisterListeners() {
18199
- _BaseStreamController.prototype.unregisterListeners.call(this);
17310
+ _proto._unregisterListeners = function _unregisterListeners() {
18200
17311
  var hls = this.hls;
17312
+ hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
17313
+ hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
17314
+ hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
18201
17315
  hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
17316
+ hls.off(Events.ERROR, this.onError, this);
18202
17317
  hls.off(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);
18203
17318
  hls.off(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);
18204
17319
  hls.off(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);
@@ -18421,10 +17536,10 @@
18421
17536
  return;
18422
17537
  }
18423
17538
  // check to see if the payload needs to be decrypted
18424
- if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && isFullSegmentEncryption(decryptData.method)) {
17539
+ if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && decryptData.method === 'AES-128') {
18425
17540
  var startTime = performance.now();
18426
17541
  // decrypt the subtitles
18427
- this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer, getAesModeFromFullSegmentMethod(decryptData.method)).catch(function (err) {
17542
+ this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).catch(function (err) {
18428
17543
  hls.trigger(Events.ERROR, {
18429
17544
  type: ErrorTypes.MEDIA_ERROR,
18430
17545
  details: ErrorDetails.FRAG_DECRYPT_ERROR,
@@ -18556,7 +17671,7 @@
18556
17671
  _inheritsLoose(SubtitleTrackController, _BasePlaylistControll);
18557
17672
  function SubtitleTrackController(hls) {
18558
17673
  var _this;
18559
- _this = _BasePlaylistControll.call(this, hls, 'subtitle-track-controller') || this;
17674
+ _this = _BasePlaylistControll.call(this, hls, '[subtitle-track-controller]') || this;
18560
17675
  _this.media = null;
18561
17676
  _this.tracks = [];
18562
17677
  _this.groupIds = null;
@@ -18565,12 +17680,12 @@
18565
17680
  _this.currentTrack = null;
18566
17681
  _this.selectDefaultTrack = true;
18567
17682
  _this.queuedDefaultTrack = -1;
18568
- _this.useTextTrackPolling = false;
18569
- _this.subtitlePollingInterval = -1;
18570
- _this._subtitleDisplay = true;
18571
17683
  _this.asyncPollTrackChange = function () {
18572
17684
  return _this.pollTrackChange(0);
18573
17685
  };
17686
+ _this.useTextTrackPolling = false;
17687
+ _this.subtitlePollingInterval = -1;
17688
+ _this._subtitleDisplay = true;
18574
17689
  _this.onTextTracksChanged = function () {
18575
17690
  if (!_this.useTextTrackPolling) {
18576
17691
  self.clearInterval(_this.subtitlePollingInterval);
@@ -18606,7 +17721,6 @@
18606
17721
  this.tracks.length = 0;
18607
17722
  this.tracksInGroup.length = 0;
18608
17723
  this.currentTrack = null;
18609
- // @ts-ignore
18610
17724
  this.onTextTracksChanged = this.asyncPollTrackChange = null;
18611
17725
  _BasePlaylistControll.prototype.destroy.call(this);
18612
17726
  };
@@ -19080,57 +18194,57 @@
19080
18194
  }();
19081
18195
 
19082
18196
  var VIDEO_CODEC_PROFILE_REPLACE = /(avc[1234]|hvc1|hev1|dvh[1e]|vp09|av01)(?:\.[^.,]+)+/;
19083
- var BufferController = /*#__PURE__*/function (_Logger) {
19084
- _inheritsLoose(BufferController, _Logger);
18197
+ var BufferController = /*#__PURE__*/function () {
19085
18198
  function BufferController(hls) {
19086
- var _this;
19087
- _this = _Logger.call(this, 'buffer-controller', hls.logger) || this;
18199
+ var _this = this;
19088
18200
  // The level details used to determine duration, target-duration and live
19089
- _this.details = null;
18201
+ this.details = null;
19090
18202
  // cache the self generated object url to detect hijack of video tag
19091
- _this._objectUrl = null;
18203
+ this._objectUrl = null;
19092
18204
  // A queue of buffer operations which require the SourceBuffer to not be updating upon execution
19093
- _this.operationQueue = void 0;
18205
+ this.operationQueue = void 0;
19094
18206
  // References to event listeners for each SourceBuffer, so that they can be referenced for event removal
19095
- _this.listeners = void 0;
19096
- _this.hls = void 0;
18207
+ this.listeners = void 0;
18208
+ this.hls = void 0;
19097
18209
  // The number of BUFFER_CODEC events received before any sourceBuffers are created
19098
- _this.bufferCodecEventsExpected = 0;
18210
+ this.bufferCodecEventsExpected = 0;
19099
18211
  // The total number of BUFFER_CODEC events received
19100
- _this._bufferCodecEventsTotal = 0;
18212
+ this._bufferCodecEventsTotal = 0;
19101
18213
  // A reference to the attached media element
19102
- _this.media = null;
18214
+ this.media = null;
19103
18215
  // A reference to the active media source
19104
- _this.mediaSource = null;
18216
+ this.mediaSource = null;
19105
18217
  // Last MP3 audio chunk appended
19106
- _this.lastMpegAudioChunk = null;
19107
- _this.appendSource = void 0;
18218
+ this.lastMpegAudioChunk = null;
18219
+ this.appendSource = void 0;
19108
18220
  // counters
19109
- _this.appendErrors = {
18221
+ this.appendErrors = {
19110
18222
  audio: 0,
19111
18223
  video: 0,
19112
18224
  audiovideo: 0
19113
18225
  };
19114
- _this.tracks = {};
19115
- _this.pendingTracks = {};
19116
- _this.sourceBuffer = void 0;
19117
- _this._onEndStreaming = function (event) {
18226
+ this.tracks = {};
18227
+ this.pendingTracks = {};
18228
+ this.sourceBuffer = void 0;
18229
+ this.log = void 0;
18230
+ this.warn = void 0;
18231
+ this.error = void 0;
18232
+ this._onEndStreaming = function (event) {
19118
18233
  if (!_this.hls) {
19119
18234
  return;
19120
18235
  }
19121
18236
  _this.hls.pauseBuffering();
19122
18237
  };
19123
- _this._onStartStreaming = function (event) {
18238
+ this._onStartStreaming = function (event) {
19124
18239
  if (!_this.hls) {
19125
18240
  return;
19126
18241
  }
19127
18242
  _this.hls.resumeBuffering();
19128
18243
  };
19129
18244
  // Keep as arrow functions so that we can directly reference these functions directly as event listeners
19130
- _this._onMediaSourceOpen = function () {
19131
- var _assertThisInitialize = _assertThisInitialized(_this),
19132
- media = _assertThisInitialize.media,
19133
- mediaSource = _assertThisInitialize.mediaSource;
18245
+ this._onMediaSourceOpen = function () {
18246
+ var media = _this.media,
18247
+ mediaSource = _this.mediaSource;
19134
18248
  _this.log('Media source opened');
19135
18249
  if (media) {
19136
18250
  media.removeEventListener('emptied', _this._onMediaEmptied);
@@ -19146,25 +18260,27 @@
19146
18260
  }
19147
18261
  _this.checkPendingTracks();
19148
18262
  };
19149
- _this._onMediaSourceClose = function () {
18263
+ this._onMediaSourceClose = function () {
19150
18264
  _this.log('Media source closed');
19151
18265
  };
19152
- _this._onMediaSourceEnded = function () {
18266
+ this._onMediaSourceEnded = function () {
19153
18267
  _this.log('Media source ended');
19154
18268
  };
19155
- _this._onMediaEmptied = function () {
19156
- var _assertThisInitialize2 = _assertThisInitialized(_this),
19157
- mediaSrc = _assertThisInitialize2.mediaSrc,
19158
- _objectUrl = _assertThisInitialize2._objectUrl;
18269
+ this._onMediaEmptied = function () {
18270
+ var mediaSrc = _this.mediaSrc,
18271
+ _objectUrl = _this._objectUrl;
19159
18272
  if (mediaSrc !== _objectUrl) {
19160
- _this.error("Media element src was set while attaching MediaSource (" + _objectUrl + " > " + mediaSrc + ")");
18273
+ logger.error("Media element src was set while attaching MediaSource (" + _objectUrl + " > " + mediaSrc + ")");
19161
18274
  }
19162
18275
  };
19163
- _this.hls = hls;
19164
- _this.appendSource = hls.config.preferManagedMediaSource;
19165
- _this._initSourceBuffer();
19166
- _this.registerListeners();
19167
- return _this;
18276
+ this.hls = hls;
18277
+ var logPrefix = '[buffer-controller]';
18278
+ this.appendSource = hls.config.preferManagedMediaSource;
18279
+ this.log = logger.log.bind(logger, logPrefix);
18280
+ this.warn = logger.warn.bind(logger, logPrefix);
18281
+ this.error = logger.error.bind(logger, logPrefix);
18282
+ this._initSourceBuffer();
18283
+ this.registerListeners();
19168
18284
  }
19169
18285
  var _proto = BufferController.prototype;
19170
18286
  _proto.hasSourceTypes = function hasSourceTypes() {
@@ -19176,12 +18292,6 @@
19176
18292
  this.lastMpegAudioChunk = null;
19177
18293
  // @ts-ignore
19178
18294
  this.hls = null;
19179
- // @ts-ignore
19180
- this._onMediaSourceOpen = this._onMediaSourceClose = null;
19181
- // @ts-ignore
19182
- this._onMediaSourceEnded = null;
19183
- // @ts-ignore
19184
- this._onStartStreaming = this._onEndStreaming = null;
19185
18295
  };
19186
18296
  _proto.registerListeners = function registerListeners() {
19187
18297
  var hls = this.hls;
@@ -19339,7 +18449,6 @@
19339
18449
  _this2.resetBuffer(type);
19340
18450
  });
19341
18451
  this._initSourceBuffer();
19342
- this.hls.resumeBuffering();
19343
18452
  };
19344
18453
  _proto.resetBuffer = function resetBuffer(type) {
19345
18454
  var sb = this.sourceBuffer[type];
@@ -20043,7 +19152,7 @@
20043
19152
  }
20044
19153
  }]);
20045
19154
  return BufferController;
20046
- }(Logger);
19155
+ }();
20047
19156
  function removeSourceChildren(node) {
20048
19157
  var sourceChildren = node.querySelectorAll('source');
20049
19158
  [].slice.call(sourceChildren).forEach(function (source) {
@@ -22482,12 +21591,14 @@
22482
21591
  this.cea608Parser1 = this.cea608Parser2 = undefined;
22483
21592
  };
22484
21593
  _proto.initCea608Parsers = function initCea608Parsers() {
22485
- var channel1 = new OutputFilter(this, 'textTrack1');
22486
- var channel2 = new OutputFilter(this, 'textTrack2');
22487
- var channel3 = new OutputFilter(this, 'textTrack3');
22488
- var channel4 = new OutputFilter(this, 'textTrack4');
22489
- this.cea608Parser1 = new Cea608Parser(1, channel1, channel2);
22490
- this.cea608Parser2 = new Cea608Parser(3, channel3, channel4);
21594
+ if (this.config.enableCEA708Captions && (!this.cea608Parser1 || !this.cea608Parser2)) {
21595
+ var channel1 = new OutputFilter(this, 'textTrack1');
21596
+ var channel2 = new OutputFilter(this, 'textTrack2');
21597
+ var channel3 = new OutputFilter(this, 'textTrack3');
21598
+ var channel4 = new OutputFilter(this, 'textTrack4');
21599
+ this.cea608Parser1 = new Cea608Parser(1, channel1, channel2);
21600
+ this.cea608Parser2 = new Cea608Parser(3, channel3, channel4);
21601
+ }
22491
21602
  };
22492
21603
  _proto.addCues = function addCues(trackName, startTime, endTime, screen, cueRanges) {
22493
21604
  // skip cues which overlap more than 50% with previously parsed time ranges
@@ -22722,7 +21833,7 @@
22722
21833
  return t.label;
22723
21834
  });
22724
21835
  if (unusedTextTracks.length) {
22725
- this.hls.logger.warn("Media element contains unused subtitle tracks: " + unusedTextTracks.join(', ') + ". Replace media element for each source to clear TextTracks and captions menu.");
21836
+ logger.warn("Media element contains unused subtitle tracks: " + unusedTextTracks.join(', ') + ". Replace media element for each source to clear TextTracks and captions menu.");
22726
21837
  }
22727
21838
  }
22728
21839
  } else if (this.tracks.length) {
@@ -22768,20 +21879,23 @@
22768
21879
  return level == null ? void 0 : level.attrs['CLOSED-CAPTIONS'];
22769
21880
  };
22770
21881
  _proto.onFragLoading = function onFragLoading(event, data) {
21882
+ this.initCea608Parsers();
21883
+ var cea608Parser1 = this.cea608Parser1,
21884
+ cea608Parser2 = this.cea608Parser2,
21885
+ lastCc = this.lastCc,
21886
+ lastSn = this.lastSn,
21887
+ lastPartIndex = this.lastPartIndex;
21888
+ if (!this.enabled || !cea608Parser1 || !cea608Parser2) {
21889
+ return;
21890
+ }
22771
21891
  // if this frag isn't contiguous, clear the parser so cues with bad start/end times aren't added to the textTrack
22772
- if (this.enabled && data.frag.type === PlaylistLevelType.MAIN) {
21892
+ if (data.frag.type === PlaylistLevelType.MAIN) {
22773
21893
  var _data$part$index, _data$part;
22774
- var cea608Parser1 = this.cea608Parser1,
22775
- cea608Parser2 = this.cea608Parser2,
22776
- lastSn = this.lastSn;
22777
- if (!cea608Parser1 || !cea608Parser2) {
22778
- return;
22779
- }
22780
21894
  var _data$frag = data.frag,
22781
21895
  cc = _data$frag.cc,
22782
21896
  sn = _data$frag.sn;
22783
- var partIndex = (_data$part$index = (_data$part = data.part) == null ? void 0 : _data$part.index) != null ? _data$part$index : -1;
22784
- if (!(sn === lastSn + 1 || sn === lastSn && partIndex === this.lastPartIndex + 1 || cc === this.lastCc)) {
21897
+ var partIndex = (_data$part$index = data == null ? void 0 : (_data$part = data.part) == null ? void 0 : _data$part.index) != null ? _data$part$index : -1;
21898
+ if (!(sn === lastSn + 1 || sn === lastSn && partIndex === lastPartIndex + 1 || cc === lastCc)) {
22785
21899
  cea608Parser1.reset();
22786
21900
  cea608Parser2.reset();
22787
21901
  }
@@ -22837,7 +21951,7 @@
22837
21951
  frag: frag
22838
21952
  });
22839
21953
  }, function (error) {
22840
- hls.logger.log("Failed to parse IMSC1: " + error);
21954
+ logger.log("Failed to parse IMSC1: " + error);
22841
21955
  hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {
22842
21956
  success: false,
22843
21957
  frag: frag,
@@ -22875,7 +21989,7 @@
22875
21989
  _this5._fallbackToIMSC1(frag, payload);
22876
21990
  }
22877
21991
  // Something went wrong while parsing. Trigger event with success false.
22878
- hls.logger.log("Failed to parse VTT cue: " + error);
21992
+ logger.log("Failed to parse VTT cue: " + error);
22879
21993
  if (missingInitPTS && maxAvCC > frag.cc) {
22880
21994
  return;
22881
21995
  }
@@ -22937,7 +22051,10 @@
22937
22051
  this.captionsTracks = {};
22938
22052
  };
22939
22053
  _proto.onFragParsingUserdata = function onFragParsingUserdata(event, data) {
22940
- if (!this.enabled || !this.config.enableCEA708Captions) {
22054
+ this.initCea608Parsers();
22055
+ var cea608Parser1 = this.cea608Parser1,
22056
+ cea608Parser2 = this.cea608Parser2;
22057
+ if (!this.enabled || !cea608Parser1 || !cea608Parser2) {
22941
22058
  return;
22942
22059
  }
22943
22060
  var frag = data.frag,
@@ -22950,12 +22067,9 @@
22950
22067
  for (var i = 0; i < samples.length; i++) {
22951
22068
  var ccBytes = samples[i].bytes;
22952
22069
  if (ccBytes) {
22953
- if (!this.cea608Parser1) {
22954
- this.initCea608Parsers();
22955
- }
22956
22070
  var ccdatas = this.extractCea608Data(ccBytes);
22957
- this.cea608Parser1.addData(samples[i].pts, ccdatas[0]);
22958
- this.cea608Parser2.addData(samples[i].pts, ccdatas[1]);
22071
+ cea608Parser1.addData(samples[i].pts, ccdatas[0]);
22072
+ cea608Parser2.addData(samples[i].pts, ccdatas[1]);
22959
22073
  }
22960
22074
  }
22961
22075
  };
@@ -23147,7 +22261,7 @@
23147
22261
  var hls = this.hls;
23148
22262
  var maxLevel = this.getMaxLevel(levels.length - 1);
23149
22263
  if (maxLevel !== this.autoLevelCapping) {
23150
- hls.logger.log("Setting autoLevelCapping to " + maxLevel + ": " + levels[maxLevel].height + "p@" + levels[maxLevel].bitrate + " for media " + this.mediaWidth + "x" + this.mediaHeight);
22264
+ logger.log("Setting autoLevelCapping to " + maxLevel + ": " + levels[maxLevel].height + "p@" + levels[maxLevel].bitrate + " for media " + this.mediaWidth + "x" + this.mediaHeight);
23151
22265
  }
23152
22266
  hls.autoLevelCapping = maxLevel;
23153
22267
  if (hls.autoLevelCapping > this.autoLevelCapping && this.streamController) {
@@ -23337,10 +22451,10 @@
23337
22451
  totalDroppedFrames: droppedFrames
23338
22452
  });
23339
22453
  if (droppedFPS > 0) {
23340
- // hls.logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));
22454
+ // logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));
23341
22455
  if (currentDropped > hls.config.fpsDroppedMonitoringThreshold * currentDecoded) {
23342
22456
  var currentLevel = hls.currentLevel;
23343
- hls.logger.warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel);
22457
+ logger.warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel);
23344
22458
  if (currentLevel > 0 && (hls.autoLevelCapping === -1 || hls.autoLevelCapping >= currentLevel)) {
23345
22459
  currentLevel = currentLevel - 1;
23346
22460
  hls.trigger(Events.FPS_DROP_LEVEL_CAPPING, {
@@ -23373,6 +22487,7 @@
23373
22487
  return FPSController;
23374
22488
  }();
23375
22489
 
22490
+ var LOGGER_PREFIX = '[eme]';
23376
22491
  /**
23377
22492
  * Controller to deal with encrypted media extensions (EME)
23378
22493
  * @see https://developer.mozilla.org/en-US/docs/Web/API/Encrypted_Media_Extensions_API
@@ -23380,122 +22495,26 @@
23380
22495
  * @class
23381
22496
  * @constructor
23382
22497
  */
23383
- var EMEController = /*#__PURE__*/function (_Logger) {
23384
- _inheritsLoose(EMEController, _Logger);
22498
+ var EMEController = /*#__PURE__*/function () {
23385
22499
  function EMEController(hls) {
23386
- var _this;
23387
- _this = _Logger.call(this, 'eme', hls.logger) || this;
23388
- _this.hls = void 0;
23389
- _this.config = void 0;
23390
- _this.media = null;
23391
- _this.keyFormatPromise = null;
23392
- _this.keySystemAccessPromises = {};
23393
- _this._requestLicenseFailureCount = 0;
23394
- _this.mediaKeySessions = [];
23395
- _this.keyIdToKeySessionPromise = {};
23396
- _this.setMediaKeysQueue = EMEController.CDMCleanupPromise ? [EMEController.CDMCleanupPromise] : [];
23397
- _this.onMediaEncrypted = function (event) {
23398
- var initDataType = event.initDataType,
23399
- initData = event.initData;
23400
- _this.debug("\"" + event.type + "\" event: init data type: \"" + initDataType + "\"");
23401
-
23402
- // Ignore event when initData is null
23403
- if (initData === null) {
23404
- return;
23405
- }
23406
- var keyId;
23407
- var keySystemDomain;
23408
- if (initDataType === 'sinf' && _this.config.drmSystems[KeySystems.FAIRPLAY]) {
23409
- // Match sinf keyId to playlist skd://keyId=
23410
- var json = bin2str(new Uint8Array(initData));
23411
- try {
23412
- var sinf = base64Decode(JSON.parse(json).sinf);
23413
- var tenc = parseSinf(new Uint8Array(sinf));
23414
- if (!tenc) {
23415
- return;
23416
- }
23417
- keyId = tenc.subarray(8, 24);
23418
- keySystemDomain = KeySystems.FAIRPLAY;
23419
- } catch (error) {
23420
- _this.warn('Failed to parse sinf "encrypted" event message initData');
23421
- return;
23422
- }
23423
- } else {
23424
- // Support clear-lead key-session creation (otherwise depend on playlist keys)
23425
- var psshInfo = parsePssh(initData);
23426
- if (psshInfo === null) {
23427
- return;
23428
- }
23429
- if (psshInfo.version === 0 && psshInfo.systemId === KeySystemIds.WIDEVINE && psshInfo.data) {
23430
- keyId = psshInfo.data.subarray(8, 24);
23431
- }
23432
- keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
23433
- }
23434
- if (!keySystemDomain || !keyId) {
23435
- return;
23436
- }
23437
- var keyIdHex = Hex.hexDump(keyId);
23438
- var _assertThisInitialize = _assertThisInitialized(_this),
23439
- keyIdToKeySessionPromise = _assertThisInitialize.keyIdToKeySessionPromise,
23440
- mediaKeySessions = _assertThisInitialize.mediaKeySessions;
23441
- var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
23442
- var _loop = function _loop() {
23443
- // Match playlist key
23444
- var keyContext = mediaKeySessions[i];
23445
- var decryptdata = keyContext.decryptdata;
23446
- if (decryptdata.pssh || !decryptdata.keyId) {
23447
- return 0; // continue
23448
- }
23449
- var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
23450
- if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
23451
- keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
23452
- delete keyIdToKeySessionPromise[oldKeyIdHex];
23453
- decryptdata.pssh = new Uint8Array(initData);
23454
- decryptdata.keyId = keyId;
23455
- keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
23456
- return _this.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
23457
- });
23458
- return 1; // break
23459
- }
23460
- },
23461
- _ret;
23462
- for (var i = 0; i < mediaKeySessions.length; i++) {
23463
- _ret = _loop();
23464
- if (_ret === 0) continue;
23465
- if (_ret === 1) break;
23466
- }
23467
- if (!keySessionContextPromise) {
23468
- // Clear-lead key (not encountered in playlist)
23469
- keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = _this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref) {
23470
- var _keySystemToKeySystem;
23471
- var keySystem = _ref.keySystem,
23472
- mediaKeys = _ref.mediaKeys;
23473
- _this.throwIfDestroyed();
23474
- var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
23475
- decryptdata.pssh = new Uint8Array(initData);
23476
- decryptdata.keyId = keyId;
23477
- return _this.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
23478
- _this.throwIfDestroyed();
23479
- var keySessionContext = _this.createMediaKeySessionContext({
23480
- decryptdata: decryptdata,
23481
- keySystem: keySystem,
23482
- mediaKeys: mediaKeys
23483
- });
23484
- return _this.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
23485
- });
23486
- });
23487
- }
23488
- keySessionContextPromise.catch(function (error) {
23489
- return _this.handleError(error);
23490
- });
23491
- };
23492
- _this.onWaitingForKey = function (event) {
23493
- _this.log("\"" + event.type + "\" event");
23494
- };
23495
- _this.hls = hls;
23496
- _this.config = hls.config;
23497
- _this.registerListeners();
23498
- return _this;
22500
+ this.hls = void 0;
22501
+ this.config = void 0;
22502
+ this.media = null;
22503
+ this.keyFormatPromise = null;
22504
+ this.keySystemAccessPromises = {};
22505
+ this._requestLicenseFailureCount = 0;
22506
+ this.mediaKeySessions = [];
22507
+ this.keyIdToKeySessionPromise = {};
22508
+ this.setMediaKeysQueue = EMEController.CDMCleanupPromise ? [EMEController.CDMCleanupPromise] : [];
22509
+ this.onMediaEncrypted = this._onMediaEncrypted.bind(this);
22510
+ this.onWaitingForKey = this._onWaitingForKey.bind(this);
22511
+ this.debug = logger.debug.bind(logger, LOGGER_PREFIX);
22512
+ this.log = logger.log.bind(logger, LOGGER_PREFIX);
22513
+ this.warn = logger.warn.bind(logger, LOGGER_PREFIX);
22514
+ this.error = logger.error.bind(logger, LOGGER_PREFIX);
22515
+ this.hls = hls;
22516
+ this.config = hls.config;
22517
+ this.registerListeners();
23499
22518
  }
23500
22519
  var _proto = EMEController.prototype;
23501
22520
  _proto.destroy = function destroy() {
@@ -23507,9 +22526,9 @@
23507
22526
  config.licenseXhrSetup = config.licenseResponseCallback = undefined;
23508
22527
  config.drmSystems = config.drmSystemOptions = {};
23509
22528
  // @ts-ignore
23510
- this.hls = this.config = this.keyIdToKeySessionPromise = null;
22529
+ this.hls = this.onMediaEncrypted = this.onWaitingForKey = this.keyIdToKeySessionPromise = null;
23511
22530
  // @ts-ignore
23512
- this.onMediaEncrypted = this.onWaitingForKey = null;
22531
+ this.config = null;
23513
22532
  };
23514
22533
  _proto.registerListeners = function registerListeners() {
23515
22534
  this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
@@ -23548,7 +22567,7 @@
23548
22567
  }
23549
22568
  };
23550
22569
  _proto.attemptKeySystemAccess = function attemptKeySystemAccess(keySystemsToAttempt) {
23551
- var _this2 = this;
22570
+ var _this = this;
23552
22571
  var levels = this.hls.levels;
23553
22572
  var uniqueCodec = function uniqueCodec(value, i, a) {
23554
22573
  return !!value && a.indexOf(value) === i;
@@ -23565,7 +22584,7 @@
23565
22584
  return new Promise(function (resolve, reject) {
23566
22585
  var attempt = function attempt(keySystems) {
23567
22586
  var keySystem = keySystems.shift();
23568
- _this2.getMediaKeysPromise(keySystem, audioCodecs, videoCodecs).then(function (mediaKeys) {
22587
+ _this.getMediaKeysPromise(keySystem, audioCodecs, videoCodecs).then(function (mediaKeys) {
23569
22588
  return resolve({
23570
22589
  keySystem: keySystem,
23571
22590
  mediaKeys: mediaKeys
@@ -23600,7 +22619,7 @@
23600
22619
  return requestMediaKeySystemAccessFunc(keySystem, supportedConfigurations);
23601
22620
  };
23602
22621
  _proto.getMediaKeysPromise = function getMediaKeysPromise(keySystem, audioCodecs, videoCodecs) {
23603
- var _this3 = this;
22622
+ var _this2 = this;
23604
22623
  // This can throw, but is caught in event handler callpath
23605
22624
  var mediaKeySystemConfigs = getSupportedMediaKeySystemConfigurations(keySystem, audioCodecs, videoCodecs, this.config.drmSystemOptions);
23606
22625
  var keySystemAccessPromises = this.keySystemAccessPromises[keySystem];
@@ -23612,23 +22631,23 @@
23612
22631
  keySystemAccess: keySystemAccess
23613
22632
  };
23614
22633
  keySystemAccess.catch(function (error) {
23615
- _this3.log("Failed to obtain access to key-system \"" + keySystem + "\": " + error);
22634
+ _this2.log("Failed to obtain access to key-system \"" + keySystem + "\": " + error);
23616
22635
  });
23617
22636
  return keySystemAccess.then(function (mediaKeySystemAccess) {
23618
- _this3.log("Access for key-system \"" + mediaKeySystemAccess.keySystem + "\" obtained");
23619
- var certificateRequest = _this3.fetchServerCertificate(keySystem);
23620
- _this3.log("Create media-keys for \"" + keySystem + "\"");
22637
+ _this2.log("Access for key-system \"" + mediaKeySystemAccess.keySystem + "\" obtained");
22638
+ var certificateRequest = _this2.fetchServerCertificate(keySystem);
22639
+ _this2.log("Create media-keys for \"" + keySystem + "\"");
23621
22640
  _keySystemAccessPromises.mediaKeys = mediaKeySystemAccess.createMediaKeys().then(function (mediaKeys) {
23622
- _this3.log("Media-keys created for \"" + keySystem + "\"");
22641
+ _this2.log("Media-keys created for \"" + keySystem + "\"");
23623
22642
  return certificateRequest.then(function (certificate) {
23624
22643
  if (certificate) {
23625
- return _this3.setMediaKeysServerCertificate(mediaKeys, keySystem, certificate);
22644
+ return _this2.setMediaKeysServerCertificate(mediaKeys, keySystem, certificate);
23626
22645
  }
23627
22646
  return mediaKeys;
23628
22647
  });
23629
22648
  });
23630
22649
  _keySystemAccessPromises.mediaKeys.catch(function (error) {
23631
- _this3.error("Failed to create media-keys for \"" + keySystem + "\"}: " + error);
22650
+ _this2.error("Failed to create media-keys for \"" + keySystem + "\"}: " + error);
23632
22651
  });
23633
22652
  return _keySystemAccessPromises.mediaKeys;
23634
22653
  });
@@ -23637,10 +22656,10 @@
23637
22656
  return keySystemAccessPromises.mediaKeys;
23638
22657
  });
23639
22658
  };
23640
- _proto.createMediaKeySessionContext = function createMediaKeySessionContext(_ref2) {
23641
- var decryptdata = _ref2.decryptdata,
23642
- keySystem = _ref2.keySystem,
23643
- mediaKeys = _ref2.mediaKeys;
22659
+ _proto.createMediaKeySessionContext = function createMediaKeySessionContext(_ref) {
22660
+ var decryptdata = _ref.decryptdata,
22661
+ keySystem = _ref.keySystem,
22662
+ mediaKeys = _ref.mediaKeys;
23644
22663
  this.log("Creating key-system session \"" + keySystem + "\" keyId: " + Hex.hexDump(decryptdata.keyId || []));
23645
22664
  var mediaKeysSession = mediaKeys.createSession();
23646
22665
  var mediaKeySessionContext = {
@@ -23689,14 +22708,14 @@
23689
22708
  return this.keyFormatPromise;
23690
22709
  };
23691
22710
  _proto.getKeyFormatPromise = function getKeyFormatPromise(keyFormats) {
23692
- var _this4 = this;
22711
+ var _this3 = this;
23693
22712
  return new Promise(function (resolve, reject) {
23694
- var keySystemsInConfig = getKeySystemsForConfig(_this4.config);
22713
+ var keySystemsInConfig = getKeySystemsForConfig(_this3.config);
23695
22714
  var keySystemsToAttempt = keyFormats.map(keySystemFormatToKeySystemDomain).filter(function (value) {
23696
22715
  return !!value && keySystemsInConfig.indexOf(value) !== -1;
23697
22716
  });
23698
- return _this4.getKeySystemSelectionPromise(keySystemsToAttempt).then(function (_ref3) {
23699
- var keySystem = _ref3.keySystem;
22717
+ return _this3.getKeySystemSelectionPromise(keySystemsToAttempt).then(function (_ref2) {
22718
+ var keySystem = _ref2.keySystem;
23700
22719
  var keySystemFormat = keySystemDomainToKeySystemFormat(keySystem);
23701
22720
  if (keySystemFormat) {
23702
22721
  resolve(keySystemFormat);
@@ -23707,31 +22726,31 @@
23707
22726
  });
23708
22727
  };
23709
22728
  _proto.loadKey = function loadKey(data) {
23710
- var _this5 = this;
22729
+ var _this4 = this;
23711
22730
  var decryptdata = data.keyInfo.decryptdata;
23712
22731
  var keyId = this.getKeyIdString(decryptdata);
23713
22732
  var keyDetails = "(keyId: " + keyId + " format: \"" + decryptdata.keyFormat + "\" method: " + decryptdata.method + " uri: " + decryptdata.uri + ")";
23714
22733
  this.log("Starting session for key " + keyDetails);
23715
22734
  var keySessionContextPromise = this.keyIdToKeySessionPromise[keyId];
23716
22735
  if (!keySessionContextPromise) {
23717
- keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (_ref4) {
23718
- var keySystem = _ref4.keySystem,
23719
- mediaKeys = _ref4.mediaKeys;
23720
- _this5.throwIfDestroyed();
23721
- _this5.log("Handle encrypted media sn: " + data.frag.sn + " " + data.frag.type + ": " + data.frag.level + " using key " + keyDetails);
23722
- return _this5.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
23723
- _this5.throwIfDestroyed();
23724
- var keySessionContext = _this5.createMediaKeySessionContext({
22736
+ keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (_ref3) {
22737
+ var keySystem = _ref3.keySystem,
22738
+ mediaKeys = _ref3.mediaKeys;
22739
+ _this4.throwIfDestroyed();
22740
+ _this4.log("Handle encrypted media sn: " + data.frag.sn + " " + data.frag.type + ": " + data.frag.level + " using key " + keyDetails);
22741
+ return _this4.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
22742
+ _this4.throwIfDestroyed();
22743
+ var keySessionContext = _this4.createMediaKeySessionContext({
23725
22744
  keySystem: keySystem,
23726
22745
  mediaKeys: mediaKeys,
23727
22746
  decryptdata: decryptdata
23728
22747
  });
23729
22748
  var scheme = 'cenc';
23730
- return _this5.generateRequestWithPreferredKeySession(keySessionContext, scheme, decryptdata.pssh, 'playlist-key');
22749
+ return _this4.generateRequestWithPreferredKeySession(keySessionContext, scheme, decryptdata.pssh, 'playlist-key');
23731
22750
  });
23732
22751
  });
23733
22752
  keySessionContextPromise.catch(function (error) {
23734
- return _this5.handleError(error);
22753
+ return _this4.handleError(error);
23735
22754
  });
23736
22755
  }
23737
22756
  return keySessionContextPromise;
@@ -23765,22 +22784,120 @@
23765
22784
  var keySystemsToAttempt = keySystem ? [keySystem] : getKeySystemsForConfig(this.config);
23766
22785
  return this.attemptKeySystemAccess(keySystemsToAttempt);
23767
22786
  }
23768
- return mediaKeySessionContext;
22787
+ return mediaKeySessionContext;
22788
+ };
22789
+ _proto.getKeySystemSelectionPromise = function getKeySystemSelectionPromise(keySystemsToAttempt) {
22790
+ if (!keySystemsToAttempt.length) {
22791
+ keySystemsToAttempt = getKeySystemsForConfig(this.config);
22792
+ }
22793
+ if (keySystemsToAttempt.length === 0) {
22794
+ throw new EMEKeyError({
22795
+ type: ErrorTypes.KEY_SYSTEM_ERROR,
22796
+ details: ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE,
22797
+ fatal: true
22798
+ }, "Missing key-system license configuration options " + JSON.stringify({
22799
+ drmSystems: this.config.drmSystems
22800
+ }));
22801
+ }
22802
+ return this.attemptKeySystemAccess(keySystemsToAttempt);
22803
+ };
22804
+ _proto._onMediaEncrypted = function _onMediaEncrypted(event) {
22805
+ var _this5 = this;
22806
+ var initDataType = event.initDataType,
22807
+ initData = event.initData;
22808
+ this.debug("\"" + event.type + "\" event: init data type: \"" + initDataType + "\"");
22809
+
22810
+ // Ignore event when initData is null
22811
+ if (initData === null) {
22812
+ return;
22813
+ }
22814
+ var keyId;
22815
+ var keySystemDomain;
22816
+ if (initDataType === 'sinf' && this.config.drmSystems[KeySystems.FAIRPLAY]) {
22817
+ // Match sinf keyId to playlist skd://keyId=
22818
+ var json = bin2str(new Uint8Array(initData));
22819
+ try {
22820
+ var sinf = base64Decode(JSON.parse(json).sinf);
22821
+ var tenc = parseSinf(new Uint8Array(sinf));
22822
+ if (!tenc) {
22823
+ return;
22824
+ }
22825
+ keyId = tenc.subarray(8, 24);
22826
+ keySystemDomain = KeySystems.FAIRPLAY;
22827
+ } catch (error) {
22828
+ this.warn('Failed to parse sinf "encrypted" event message initData');
22829
+ return;
22830
+ }
22831
+ } else {
22832
+ // Support clear-lead key-session creation (otherwise depend on playlist keys)
22833
+ var psshInfo = parsePssh(initData);
22834
+ if (psshInfo === null) {
22835
+ return;
22836
+ }
22837
+ if (psshInfo.version === 0 && psshInfo.systemId === KeySystemIds.WIDEVINE && psshInfo.data) {
22838
+ keyId = psshInfo.data.subarray(8, 24);
22839
+ }
22840
+ keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
22841
+ }
22842
+ if (!keySystemDomain || !keyId) {
22843
+ return;
22844
+ }
22845
+ var keyIdHex = Hex.hexDump(keyId);
22846
+ var keyIdToKeySessionPromise = this.keyIdToKeySessionPromise,
22847
+ mediaKeySessions = this.mediaKeySessions;
22848
+ var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
22849
+ var _loop = function _loop() {
22850
+ // Match playlist key
22851
+ var keyContext = mediaKeySessions[i];
22852
+ var decryptdata = keyContext.decryptdata;
22853
+ if (decryptdata.pssh || !decryptdata.keyId) {
22854
+ return 0; // continue
22855
+ }
22856
+ var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
22857
+ if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
22858
+ keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
22859
+ delete keyIdToKeySessionPromise[oldKeyIdHex];
22860
+ decryptdata.pssh = new Uint8Array(initData);
22861
+ decryptdata.keyId = keyId;
22862
+ keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
22863
+ return _this5.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
22864
+ });
22865
+ return 1; // break
22866
+ }
22867
+ },
22868
+ _ret;
22869
+ for (var i = 0; i < mediaKeySessions.length; i++) {
22870
+ _ret = _loop();
22871
+ if (_ret === 0) continue;
22872
+ if (_ret === 1) break;
22873
+ }
22874
+ if (!keySessionContextPromise) {
22875
+ // Clear-lead key (not encountered in playlist)
22876
+ keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref4) {
22877
+ var _keySystemToKeySystem;
22878
+ var keySystem = _ref4.keySystem,
22879
+ mediaKeys = _ref4.mediaKeys;
22880
+ _this5.throwIfDestroyed();
22881
+ var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
22882
+ decryptdata.pssh = new Uint8Array(initData);
22883
+ decryptdata.keyId = keyId;
22884
+ return _this5.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
22885
+ _this5.throwIfDestroyed();
22886
+ var keySessionContext = _this5.createMediaKeySessionContext({
22887
+ decryptdata: decryptdata,
22888
+ keySystem: keySystem,
22889
+ mediaKeys: mediaKeys
22890
+ });
22891
+ return _this5.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
22892
+ });
22893
+ });
22894
+ }
22895
+ keySessionContextPromise.catch(function (error) {
22896
+ return _this5.handleError(error);
22897
+ });
23769
22898
  };
23770
- _proto.getKeySystemSelectionPromise = function getKeySystemSelectionPromise(keySystemsToAttempt) {
23771
- if (!keySystemsToAttempt.length) {
23772
- keySystemsToAttempt = getKeySystemsForConfig(this.config);
23773
- }
23774
- if (keySystemsToAttempt.length === 0) {
23775
- throw new EMEKeyError({
23776
- type: ErrorTypes.KEY_SYSTEM_ERROR,
23777
- details: ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE,
23778
- fatal: true
23779
- }, "Missing key-system license configuration options " + JSON.stringify({
23780
- drmSystems: this.config.drmSystems
23781
- }));
23782
- }
23783
- return this.attemptKeySystemAccess(keySystemsToAttempt);
22899
+ _proto._onWaitingForKey = function _onWaitingForKey(event) {
22900
+ this.log("\"" + event.type + "\" event");
23784
22901
  };
23785
22902
  _proto.attemptSetMediaKeys = function attemptSetMediaKeys(keySystem, mediaKeys) {
23786
22903
  var _this6 = this;
@@ -24237,7 +23354,7 @@
24237
23354
  }
24238
23355
  };
24239
23356
  return EMEController;
24240
- }(Logger);
23357
+ }();
24241
23358
  EMEController.CDMCleanupPromise = void 0;
24242
23359
  var EMEKeyError = /*#__PURE__*/function (_Error) {
24243
23360
  _inheritsLoose(EMEKeyError, _Error);
@@ -24385,6 +23502,18 @@
24385
23502
  this.params = params;
24386
23503
  };
24387
23504
 
23505
+ /**
23506
+ * A class to represent structured field tokens when `Symbol` is not available.
23507
+ *
23508
+ * @group Structured Field
23509
+ *
23510
+ * @beta
23511
+ */
23512
+ var SfToken = function SfToken(description) {
23513
+ this.description = void 0;
23514
+ this.description = description;
23515
+ };
23516
+
24388
23517
  var DICT = 'Dict';
24389
23518
 
24390
23519
  function format(value) {
@@ -24408,25 +23537,29 @@
24408
23537
  });
24409
23538
  }
24410
23539
 
24411
- function serializeError(src, type, cause) {
24412
- return throwError('serialize', src, type, cause);
23540
+ var BARE_ITEM = 'Bare Item';
23541
+
23542
+ var BOOLEAN = 'Boolean';
23543
+
23544
+ var BYTES = 'Byte Sequence';
23545
+
23546
+ var DECIMAL = 'Decimal';
23547
+
23548
+ var INTEGER = 'Integer';
23549
+
23550
+ function isInvalidInt(value) {
23551
+ return value < -999999999999999 || 999999999999999 < value;
24413
23552
  }
24414
23553
 
24415
- /**
24416
- * A class to represent structured field tokens when `Symbol` is not available.
24417
- *
24418
- * @group Structured Field
24419
- *
24420
- * @beta
24421
- */
24422
- var SfToken = function SfToken(description) {
24423
- this.description = void 0;
24424
- this.description = description;
24425
- };
23554
+ var STRING_REGEX = /[\x00-\x1f\x7f]+/; // eslint-disable-line no-control-regex
24426
23555
 
24427
- var BARE_ITEM = 'Bare Item';
23556
+ var TOKEN = 'Token';
24428
23557
 
24429
- var BOOLEAN = 'Boolean';
23558
+ var KEY = 'Key';
23559
+
23560
+ function serializeError(src, type, cause) {
23561
+ return throwError('serialize', src, type, cause);
23562
+ }
24430
23563
 
24431
23564
  // 4.1.9. Serializing a Boolean
24432
23565
  //
@@ -24465,8 +23598,6 @@
24465
23598
  return btoa(String.fromCharCode.apply(String, binary));
24466
23599
  }
24467
23600
 
24468
- var BYTES = 'Byte Sequence';
24469
-
24470
23601
  // 4.1.8. Serializing a Byte Sequence
24471
23602
  //
24472
23603
  // Given a Byte Sequence as input_bytes, return an ASCII string suitable
@@ -24498,12 +23629,6 @@
24498
23629
  return ":" + base64encode(value) + ":";
24499
23630
  }
24500
23631
 
24501
- var INTEGER = 'Integer';
24502
-
24503
- function isInvalidInt(value) {
24504
- return value < -999999999999999 || 999999999999999 < value;
24505
- }
24506
-
24507
23632
  // 4.1.4. Serializing an Integer
24508
23633
  //
24509
23634
  // Given an Integer as input_integer, return an ASCII string suitable
@@ -24569,8 +23694,6 @@
24569
23694
  }
24570
23695
  }
24571
23696
 
24572
- var DECIMAL = 'Decimal';
24573
-
24574
23697
  // 4.1.5. Serializing a Decimal
24575
23698
  //
24576
23699
  // Given a decimal number as input_decimal, return an ASCII string
@@ -24616,8 +23739,6 @@
24616
23739
 
24617
23740
  var STRING = 'String';
24618
23741
 
24619
- var STRING_REGEX = /[\x00-\x1f\x7f]+/; // eslint-disable-line no-control-regex
24620
-
24621
23742
  // 4.1.6. Serializing a String
24622
23743
  //
24623
23744
  // Given a String as input_string, return an ASCII string suitable for
@@ -24653,8 +23774,6 @@
24653
23774
  return symbol.description || symbol.toString().slice(7, -1);
24654
23775
  }
24655
23776
 
24656
- var TOKEN = 'Token';
24657
-
24658
23777
  function serializeToken(token) {
24659
23778
  var value = symbolToStr(token);
24660
23779
  if (/^([a-zA-Z*])([!#$%&'*+\-.^_`|~\w:/]*)$/.test(value) === false) {
@@ -24722,8 +23841,6 @@
24722
23841
  }
24723
23842
  }
24724
23843
 
24725
- var KEY = 'Key';
24726
-
24727
23844
  // 4.1.1.3. Serializing a Key
24728
23845
  //
24729
23846
  // Given a key as input_key, return an ASCII string suitable for use in
@@ -24975,6 +24092,36 @@
24975
24092
  return toPath.join('/');
24976
24093
  }
24977
24094
 
24095
+ /**
24096
+ * Generate a random v4 UUID
24097
+ *
24098
+ * @returns A random v4 UUID
24099
+ *
24100
+ * @group Utils
24101
+ *
24102
+ * @beta
24103
+ */
24104
+ function uuid() {
24105
+ try {
24106
+ return crypto.randomUUID();
24107
+ } catch (error) {
24108
+ try {
24109
+ var url = URL.createObjectURL(new Blob());
24110
+ var _uuid = url.toString();
24111
+ URL.revokeObjectURL(url);
24112
+ return _uuid.slice(_uuid.lastIndexOf('/') + 1);
24113
+ } catch (error) {
24114
+ var dt = new Date().getTime();
24115
+ var _uuid2 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
24116
+ var r = (dt + Math.random() * 16) % 16 | 0;
24117
+ dt = Math.floor(dt / 16);
24118
+ return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
24119
+ });
24120
+ return _uuid2;
24121
+ }
24122
+ }
24123
+ }
24124
+
24978
24125
  var toRounded = function toRounded(value) {
24979
24126
  return Math.round(value);
24980
24127
  };
@@ -25219,36 +24366,6 @@
25219
24366
  return "" + url + separator + query;
25220
24367
  }
25221
24368
 
25222
- /**
25223
- * Generate a random v4 UUID
25224
- *
25225
- * @returns A random v4 UUID
25226
- *
25227
- * @group Utils
25228
- *
25229
- * @beta
25230
- */
25231
- function uuid() {
25232
- try {
25233
- return crypto.randomUUID();
25234
- } catch (error) {
25235
- try {
25236
- var url = URL.createObjectURL(new Blob());
25237
- var _uuid = url.toString();
25238
- URL.revokeObjectURL(url);
25239
- return _uuid.slice(_uuid.lastIndexOf('/') + 1);
25240
- } catch (error) {
25241
- var dt = new Date().getTime();
25242
- var _uuid2 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
25243
- var r = (dt + Math.random() * 16) % 16 | 0;
25244
- dt = Math.floor(dt / 16);
25245
- return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
25246
- });
25247
- return _uuid2;
25248
- }
25249
- }
25250
- }
25251
-
25252
24369
  /**
25253
24370
  * Controller to deal with Common Media Client Data (CMCD)
25254
24371
  * @see https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf
@@ -25293,7 +24410,7 @@
25293
24410
  su: !_this.initialized
25294
24411
  });
25295
24412
  } catch (error) {
25296
- _this.hls.logger.warn('Could not generate manifest CMCD data.', error);
24413
+ logger.warn('Could not generate manifest CMCD data.', error);
25297
24414
  }
25298
24415
  };
25299
24416
  /**
@@ -25313,15 +24430,9 @@
25313
24430
  data.tb = _this.getTopBandwidth(ot) / 1000;
25314
24431
  data.bl = _this.getBufferLength(ot);
25315
24432
  }
25316
- var next = _this.getNextFrag(fragment);
25317
- if (next) {
25318
- if (next.url && next.url !== fragment.url) {
25319
- data.nor = next.url;
25320
- }
25321
- }
25322
24433
  _this.apply(context, data);
25323
24434
  } catch (error) {
25324
- _this.hls.logger.warn('Could not generate segment CMCD data.', error);
24435
+ logger.warn('Could not generate segment CMCD data.', error);
25325
24436
  }
25326
24437
  };
25327
24438
  this.hls = hls;
@@ -25413,7 +24524,7 @@
25413
24524
  data.su = this.buffering;
25414
24525
  }
25415
24526
 
25416
- // TODO: Implement rtp, nrr, dl
24527
+ // TODO: Implement rtp, nrr, nor, dl
25417
24528
 
25418
24529
  var includeKeys = this.includeKeys;
25419
24530
  if (includeKeys) {
@@ -25422,31 +24533,18 @@
25422
24533
  return acc;
25423
24534
  }, {});
25424
24535
  }
25425
- var options = {
25426
- baseUrl: context.url
25427
- };
25428
24536
  if (this.useHeaders) {
25429
24537
  if (!context.headers) {
25430
24538
  context.headers = {};
25431
24539
  }
25432
- appendCmcdHeaders(context.headers, data, options);
24540
+ appendCmcdHeaders(context.headers, data);
25433
24541
  } else {
25434
- context.url = appendCmcdQuery(context.url, data, options);
24542
+ context.url = appendCmcdQuery(context.url, data);
25435
24543
  }
25436
24544
  };
25437
- _proto.getNextFrag = function getNextFrag(fragment) {
25438
- var _this$hls$levels$frag;
25439
- var levelDetails = (_this$hls$levels$frag = this.hls.levels[fragment.level]) == null ? void 0 : _this$hls$levels$frag.details;
25440
- if (levelDetails) {
25441
- var index = fragment.sn - levelDetails.startSN;
25442
- return levelDetails.fragments[index + 1];
25443
- }
25444
- return undefined;
25445
- }
25446
-
25447
24545
  /**
25448
24546
  * The CMCD object type.
25449
- */;
24547
+ */
25450
24548
  _proto.getObjectType = function getObjectType(fragment) {
25451
24549
  var type = fragment.type;
25452
24550
  if (type === 'subtitle') {
@@ -25582,28 +24680,26 @@
25582
24680
  }();
25583
24681
 
25584
24682
  var PATHWAY_PENALTY_DURATION_MS = 300000;
25585
- var ContentSteeringController = /*#__PURE__*/function (_Logger) {
25586
- _inheritsLoose(ContentSteeringController, _Logger);
24683
+ var ContentSteeringController = /*#__PURE__*/function () {
25587
24684
  function ContentSteeringController(hls) {
25588
- var _this;
25589
- _this = _Logger.call(this, 'content-steering', hls.logger) || this;
25590
- _this.hls = void 0;
25591
- _this.loader = null;
25592
- _this.uri = null;
25593
- _this.pathwayId = '.';
25594
- _this.pathwayPriority = null;
25595
- _this.timeToLoad = 300;
25596
- _this.reloadTimer = -1;
25597
- _this.updated = 0;
25598
- _this.started = false;
25599
- _this.enabled = true;
25600
- _this.levels = null;
25601
- _this.audioTracks = null;
25602
- _this.subtitleTracks = null;
25603
- _this.penalizedPathways = {};
25604
- _this.hls = hls;
25605
- _this.registerListeners();
25606
- return _this;
24685
+ this.hls = void 0;
24686
+ this.log = void 0;
24687
+ this.loader = null;
24688
+ this.uri = null;
24689
+ this.pathwayId = '.';
24690
+ this.pathwayPriority = null;
24691
+ this.timeToLoad = 300;
24692
+ this.reloadTimer = -1;
24693
+ this.updated = 0;
24694
+ this.started = false;
24695
+ this.enabled = true;
24696
+ this.levels = null;
24697
+ this.audioTracks = null;
24698
+ this.subtitleTracks = null;
24699
+ this.penalizedPathways = {};
24700
+ this.hls = hls;
24701
+ this.log = logger.log.bind(logger, "[content-steering]:");
24702
+ this.registerListeners();
25607
24703
  }
25608
24704
  var _proto = ContentSteeringController.prototype;
25609
24705
  _proto.registerListeners = function registerListeners() {
@@ -25724,7 +24820,7 @@
25724
24820
  errorAction.resolved = this.pathwayId !== errorPathway;
25725
24821
  }
25726
24822
  if (!errorAction.resolved) {
25727
- 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));
24823
+ 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));
25728
24824
  }
25729
24825
  }
25730
24826
  };
@@ -25804,7 +24900,7 @@
25804
24900
  return defaultPathway;
25805
24901
  };
25806
24902
  _proto.clonePathways = function clonePathways(pathwayClones) {
25807
- var _this2 = this;
24903
+ var _this = this;
25808
24904
  var levels = this.levels;
25809
24905
  if (!levels) {
25810
24906
  return;
@@ -25820,7 +24916,7 @@
25820
24916
  })) {
25821
24917
  return;
25822
24918
  }
25823
- var clonedVariants = _this2.getLevelsForPathway(baseId).map(function (baseLevel) {
24919
+ var clonedVariants = _this.getLevelsForPathway(baseId).map(function (baseLevel) {
25824
24920
  var attributes = new AttrList(baseLevel.attrs);
25825
24921
  attributes['PATHWAY-ID'] = cloneId;
25826
24922
  var clonedAudioGroupId = attributes.AUDIO && attributes.AUDIO + "_clone_" + cloneId;
@@ -25857,12 +24953,12 @@
25857
24953
  return clonedLevel;
25858
24954
  });
25859
24955
  levels.push.apply(levels, clonedVariants);
25860
- cloneRenditionGroups(_this2.audioTracks, audioGroupCloneMap, uriReplacement, cloneId);
25861
- cloneRenditionGroups(_this2.subtitleTracks, subtitleGroupCloneMap, uriReplacement, cloneId);
24956
+ cloneRenditionGroups(_this.audioTracks, audioGroupCloneMap, uriReplacement, cloneId);
24957
+ cloneRenditionGroups(_this.subtitleTracks, subtitleGroupCloneMap, uriReplacement, cloneId);
25862
24958
  });
25863
24959
  };
25864
24960
  _proto.loadSteeringManifest = function loadSteeringManifest(uri) {
25865
- var _this3 = this;
24961
+ var _this2 = this;
25866
24962
  var config = this.hls.config;
25867
24963
  var Loader = config.loader;
25868
24964
  if (this.loader) {
@@ -25897,87 +24993,87 @@
25897
24993
  };
25898
24994
  var callbacks = {
25899
24995
  onSuccess: function onSuccess(response, stats, context, networkDetails) {
25900
- _this3.log("Loaded steering manifest: \"" + url + "\"");
24996
+ _this2.log("Loaded steering manifest: \"" + url + "\"");
25901
24997
  var steeringData = response.data;
25902
- if ((steeringData == null ? void 0 : steeringData.VERSION) !== 1) {
25903
- _this3.log("Steering VERSION " + steeringData.VERSION + " not supported!");
24998
+ if (steeringData.VERSION !== 1) {
24999
+ _this2.log("Steering VERSION " + steeringData.VERSION + " not supported!");
25904
25000
  return;
25905
25001
  }
25906
- _this3.updated = performance.now();
25907
- _this3.timeToLoad = steeringData.TTL;
25002
+ _this2.updated = performance.now();
25003
+ _this2.timeToLoad = steeringData.TTL;
25908
25004
  var reloadUri = steeringData['RELOAD-URI'],
25909
25005
  pathwayClones = steeringData['PATHWAY-CLONES'],
25910
25006
  pathwayPriority = steeringData['PATHWAY-PRIORITY'];
25911
25007
  if (reloadUri) {
25912
25008
  try {
25913
- _this3.uri = new self.URL(reloadUri, url).href;
25009
+ _this2.uri = new self.URL(reloadUri, url).href;
25914
25010
  } catch (error) {
25915
- _this3.enabled = false;
25916
- _this3.log("Failed to parse Steering Manifest RELOAD-URI: " + reloadUri);
25011
+ _this2.enabled = false;
25012
+ _this2.log("Failed to parse Steering Manifest RELOAD-URI: " + reloadUri);
25917
25013
  return;
25918
25014
  }
25919
25015
  }
25920
- _this3.scheduleRefresh(_this3.uri || context.url);
25016
+ _this2.scheduleRefresh(_this2.uri || context.url);
25921
25017
  if (pathwayClones) {
25922
- _this3.clonePathways(pathwayClones);
25018
+ _this2.clonePathways(pathwayClones);
25923
25019
  }
25924
25020
  var loadedSteeringData = {
25925
25021
  steeringManifest: steeringData,
25926
25022
  url: url.toString()
25927
25023
  };
25928
- _this3.hls.trigger(Events.STEERING_MANIFEST_LOADED, loadedSteeringData);
25024
+ _this2.hls.trigger(Events.STEERING_MANIFEST_LOADED, loadedSteeringData);
25929
25025
  if (pathwayPriority) {
25930
- _this3.updatePathwayPriority(pathwayPriority);
25026
+ _this2.updatePathwayPriority(pathwayPriority);
25931
25027
  }
25932
25028
  },
25933
25029
  onError: function onError(error, context, networkDetails, stats) {
25934
- _this3.log("Error loading steering manifest: " + error.code + " " + error.text + " (" + context.url + ")");
25935
- _this3.stopLoad();
25030
+ _this2.log("Error loading steering manifest: " + error.code + " " + error.text + " (" + context.url + ")");
25031
+ _this2.stopLoad();
25936
25032
  if (error.code === 410) {
25937
- _this3.enabled = false;
25938
- _this3.log("Steering manifest " + context.url + " no longer available");
25033
+ _this2.enabled = false;
25034
+ _this2.log("Steering manifest " + context.url + " no longer available");
25939
25035
  return;
25940
25036
  }
25941
- var ttl = _this3.timeToLoad * 1000;
25037
+ var ttl = _this2.timeToLoad * 1000;
25942
25038
  if (error.code === 429) {
25943
- var loader = _this3.loader;
25039
+ var loader = _this2.loader;
25944
25040
  if (typeof (loader == null ? void 0 : loader.getResponseHeader) === 'function') {
25945
25041
  var retryAfter = loader.getResponseHeader('Retry-After');
25946
25042
  if (retryAfter) {
25947
25043
  ttl = parseFloat(retryAfter) * 1000;
25948
25044
  }
25949
25045
  }
25950
- _this3.log("Steering manifest " + context.url + " rate limited");
25046
+ _this2.log("Steering manifest " + context.url + " rate limited");
25951
25047
  return;
25952
25048
  }
25953
- _this3.scheduleRefresh(_this3.uri || context.url, ttl);
25049
+ _this2.scheduleRefresh(_this2.uri || context.url, ttl);
25954
25050
  },
25955
25051
  onTimeout: function onTimeout(stats, context, networkDetails) {
25956
- _this3.log("Timeout loading steering manifest (" + context.url + ")");
25957
- _this3.scheduleRefresh(_this3.uri || context.url);
25052
+ _this2.log("Timeout loading steering manifest (" + context.url + ")");
25053
+ _this2.scheduleRefresh(_this2.uri || context.url);
25958
25054
  }
25959
25055
  };
25960
25056
  this.log("Requesting steering manifest: " + url);
25961
25057
  this.loader.load(context, loaderConfig, callbacks);
25962
25058
  };
25963
25059
  _proto.scheduleRefresh = function scheduleRefresh(uri, ttlMs) {
25964
- var _this4 = this;
25060
+ var _this3 = this;
25965
25061
  if (ttlMs === void 0) {
25966
25062
  ttlMs = this.timeToLoad * 1000;
25967
25063
  }
25968
25064
  this.clearTimeout();
25969
25065
  this.reloadTimer = self.setTimeout(function () {
25970
- var _this4$hls;
25971
- var media = (_this4$hls = _this4.hls) == null ? void 0 : _this4$hls.media;
25066
+ var _this3$hls;
25067
+ var media = (_this3$hls = _this3.hls) == null ? void 0 : _this3$hls.media;
25972
25068
  if (media && !media.ended) {
25973
- _this4.loadSteeringManifest(uri);
25069
+ _this3.loadSteeringManifest(uri);
25974
25070
  return;
25975
25071
  }
25976
- _this4.scheduleRefresh(uri, _this4.timeToLoad * 1000);
25072
+ _this3.scheduleRefresh(uri, _this3.timeToLoad * 1000);
25977
25073
  }, ttlMs);
25978
25074
  };
25979
25075
  return ContentSteeringController;
25980
- }(Logger);
25076
+ }();
25981
25077
  function cloneRenditionGroups(tracks, groupCloneMap, uriReplacement, cloneId) {
25982
25078
  if (!tracks) {
25983
25079
  return;
@@ -26877,7 +25973,7 @@
26877
25973
  /**
26878
25974
  * @ignore
26879
25975
  */
26880
- function mergeConfig(defaultConfig, userConfig, logger) {
25976
+ function mergeConfig(defaultConfig, userConfig) {
26881
25977
  if ((userConfig.liveSyncDurationCount || userConfig.liveMaxLatencyDurationCount) && (userConfig.liveSyncDuration || userConfig.liveMaxLatencyDuration)) {
26882
25978
  throw new Error("Illegal hls.js config: don't mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration");
26883
25979
  }
@@ -26947,7 +26043,7 @@
26947
26043
  /**
26948
26044
  * @ignore
26949
26045
  */
26950
- function enableStreamingMode(config, logger) {
26046
+ function enableStreamingMode(config) {
26951
26047
  var currentLoader = config.loader;
26952
26048
  if (currentLoader !== FetchLoader && currentLoader !== XhrLoader) {
26953
26049
  // If a developer has configured their own loader, respect that choice
@@ -26964,11 +26060,12 @@
26964
26060
  }
26965
26061
  }
26966
26062
 
26063
+ var chromeOrFirefox;
26967
26064
  var LevelController = /*#__PURE__*/function (_BasePlaylistControll) {
26968
26065
  _inheritsLoose(LevelController, _BasePlaylistControll);
26969
26066
  function LevelController(hls, contentSteeringController) {
26970
26067
  var _this;
26971
- _this = _BasePlaylistControll.call(this, hls, 'level-controller') || this;
26068
+ _this = _BasePlaylistControll.call(this, hls, '[level-controller]') || this;
26972
26069
  _this._levels = [];
26973
26070
  _this._firstLevel = -1;
26974
26071
  _this._maxAutoLevel = -1;
@@ -27037,13 +26134,21 @@
27037
26134
  var videoCodecFound = false;
27038
26135
  var audioCodecFound = false;
27039
26136
  data.levels.forEach(function (levelParsed) {
27040
- var _videoCodec;
26137
+ var _audioCodec, _videoCodec;
27041
26138
  var attributes = levelParsed.attrs;
26139
+
26140
+ // erase audio codec info if browser does not support mp4a.40.34.
26141
+ // demuxer will autodetect codec and fallback to mpeg/audio
27042
26142
  var audioCodec = levelParsed.audioCodec,
27043
26143
  videoCodec = levelParsed.videoCodec;
26144
+ if (((_audioCodec = audioCodec) == null ? void 0 : _audioCodec.indexOf('mp4a.40.34')) !== -1) {
26145
+ chromeOrFirefox || (chromeOrFirefox = /chrome|firefox/i.test(navigator.userAgent));
26146
+ if (chromeOrFirefox) {
26147
+ levelParsed.audioCodec = audioCodec = undefined;
26148
+ }
26149
+ }
27044
26150
  if (audioCodec) {
27045
- // Returns empty and set to undefined for 'mp4a.40.34' with fallback to 'audio/mpeg' SourceBuffer
27046
- levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource) || undefined;
26151
+ levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource);
27047
26152
  }
27048
26153
  if (((_videoCodec = videoCodec) == null ? void 0 : _videoCodec.indexOf('avc1')) === 0) {
27049
26154
  videoCodec = levelParsed.videoCodec = convertAVC1ToAVCOTI(videoCodec);
@@ -27275,12 +26380,7 @@
27275
26380
  if (curLevel.fragmentError === 0) {
27276
26381
  curLevel.loadError = 0;
27277
26382
  }
27278
- // Ignore matching details populated by loading a Media Playlist directly
27279
- var previousDetails = curLevel.details;
27280
- if (previousDetails === data.details && previousDetails.advanced) {
27281
- previousDetails = undefined;
27282
- }
27283
- this.playlistLoaded(level, data, previousDetails);
26383
+ this.playlistLoaded(level, data, curLevel.details);
27284
26384
  } else if ((_data$deliveryDirecti2 = data.deliveryDirectives) != null && _data$deliveryDirecti2.skip) {
27285
26385
  // received a delta playlist update that cannot be merged
27286
26386
  details.deltaUpdateFailed = true;
@@ -27656,8 +26756,6 @@
27656
26756
  }
27657
26757
  return this.loadKeyEME(keyInfo, frag);
27658
26758
  case 'AES-128':
27659
- case 'AES-256':
27660
- case 'AES-256-CTR':
27661
26759
  return this.loadKeyHTTP(keyInfo, frag);
27662
26760
  default:
27663
26761
  return Promise.reject(this.createKeyLoadError(frag, ErrorDetails.KEY_LOAD_ERROR, new Error("Key supplied with unsupported METHOD: \"" + decryptdata.method + "\"")));
@@ -27797,26 +26895,21 @@
27797
26895
  var MAX_START_GAP_JUMP = 2.0;
27798
26896
  var SKIP_BUFFER_HOLE_STEP_SECONDS = 0.1;
27799
26897
  var SKIP_BUFFER_RANGE_START = 0.05;
27800
- var GapController = /*#__PURE__*/function (_Logger) {
27801
- _inheritsLoose(GapController, _Logger);
26898
+ var GapController = /*#__PURE__*/function () {
27802
26899
  function GapController(config, media, fragmentTracker, hls) {
27803
- var _this;
27804
- _this = _Logger.call(this, 'gap-controller', hls.logger) || this;
27805
- _this.config = void 0;
27806
- _this.media = null;
27807
- _this.fragmentTracker = void 0;
27808
- _this.hls = void 0;
27809
- _this.nudgeRetry = 0;
27810
- _this.stallReported = false;
27811
- _this.stalled = null;
27812
- _this.moved = false;
27813
- _this.seeking = false;
27814
- _this.ended = 0;
27815
- _this.config = config;
27816
- _this.media = media;
27817
- _this.fragmentTracker = fragmentTracker;
27818
- _this.hls = hls;
27819
- return _this;
26900
+ this.config = void 0;
26901
+ this.media = null;
26902
+ this.fragmentTracker = void 0;
26903
+ this.hls = void 0;
26904
+ this.nudgeRetry = 0;
26905
+ this.stallReported = false;
26906
+ this.stalled = null;
26907
+ this.moved = false;
26908
+ this.seeking = false;
26909
+ this.config = config;
26910
+ this.media = media;
26911
+ this.fragmentTracker = fragmentTracker;
26912
+ this.hls = hls;
27820
26913
  }
27821
26914
  var _proto = GapController.prototype;
27822
26915
  _proto.destroy = function destroy() {
@@ -27831,7 +26924,7 @@
27831
26924
  *
27832
26925
  * @param lastCurrentTime - Previously read playhead position
27833
26926
  */;
27834
- _proto.poll = function poll(lastCurrentTime, activeFrag, levelDetails, state) {
26927
+ _proto.poll = function poll(lastCurrentTime, activeFrag) {
27835
26928
  var config = this.config,
27836
26929
  media = this.media,
27837
26930
  stalled = this.stalled;
@@ -27846,7 +26939,6 @@
27846
26939
 
27847
26940
  // The playhead is moving, no-op
27848
26941
  if (currentTime !== lastCurrentTime) {
27849
- this.ended = 0;
27850
26942
  this.moved = true;
27851
26943
  if (!seeking) {
27852
26944
  this.nudgeRetry = 0;
@@ -27855,7 +26947,7 @@
27855
26947
  // The playhead is now moving, but was previously stalled
27856
26948
  if (this.stallReported) {
27857
26949
  var _stalledDuration = self.performance.now() - stalled;
27858
- this.warn("playback not stuck anymore @" + currentTime + ", after " + Math.round(_stalledDuration) + "ms");
26950
+ logger.warn("playback not stuck anymore @" + currentTime + ", after " + Math.round(_stalledDuration) + "ms");
27859
26951
  this.stallReported = false;
27860
26952
  }
27861
26953
  this.stalled = null;
@@ -27891,6 +26983,7 @@
27891
26983
  // Skip start gaps if we haven't played, but the last poll detected the start of a stall
27892
26984
  // The addition poll gives the browser a chance to jump the gap for us
27893
26985
  if (!this.moved && this.stalled !== null) {
26986
+ var _level$details;
27894
26987
  // There is no playable buffer (seeked, waiting for buffer)
27895
26988
  var isBuffered = bufferInfo.len > 0;
27896
26989
  if (!isBuffered && !nextStart) {
@@ -27902,8 +26995,9 @@
27902
26995
  // When joining a live stream with audio tracks, account for live playlist window sliding by allowing
27903
26996
  // a larger jump over start gaps caused by the audio-stream-controller buffering a start fragment
27904
26997
  // that begins over 1 target duration after the video start position.
27905
- var isLive = !!(levelDetails != null && levelDetails.live);
27906
- var maxStartGapJump = isLive ? levelDetails.targetduration * 2 : MAX_START_GAP_JUMP;
26998
+ var level = this.hls.levels ? this.hls.levels[this.hls.currentLevel] : null;
26999
+ var isLive = level == null ? void 0 : (_level$details = level.details) == null ? void 0 : _level$details.live;
27000
+ var maxStartGapJump = isLive ? level.details.targetduration * 2 : MAX_START_GAP_JUMP;
27907
27001
  var partialOrGap = this.fragmentTracker.getPartialFragment(currentTime);
27908
27002
  if (startJump > 0 && (startJump <= maxStartGapJump || partialOrGap)) {
27909
27003
  if (!media.paused) {
@@ -27921,17 +27015,6 @@
27921
27015
  }
27922
27016
  var stalledDuration = tnow - stalled;
27923
27017
  if (!seeking && stalledDuration >= STALL_MINIMUM_DURATION_MS) {
27924
- // Dispatch MEDIA_ENDED when media.ended/ended event is not signalled at end of stream
27925
- if (state === State.ENDED && !(levelDetails && levelDetails.live) && Math.abs(currentTime - ((levelDetails == null ? void 0 : levelDetails.edge) || 0)) < 1) {
27926
- if (stalledDuration < 1000 || this.ended) {
27927
- return;
27928
- }
27929
- this.ended = currentTime;
27930
- this.hls.trigger(Events.MEDIA_ENDED, {
27931
- stalled: true
27932
- });
27933
- return;
27934
- }
27935
27018
  // Report stalling after trying to fix
27936
27019
  this._reportStall(bufferInfo);
27937
27020
  if (!this.media) {
@@ -27973,7 +27056,7 @@
27973
27056
  // needs to cross some sort of threshold covering all source-buffers content
27974
27057
  // to start playing properly.
27975
27058
  if ((bufferInfo.len > config.maxBufferHole || bufferInfo.nextStart && bufferInfo.nextStart - currentTime < config.maxBufferHole) && stalledDurationMs > config.highBufferWatchdogPeriod * 1000) {
27976
- this.warn('Trying to nudge playhead over buffer-hole');
27059
+ logger.warn('Trying to nudge playhead over buffer-hole');
27977
27060
  // Try to nudge currentTime over a buffer hole if we've been stalling for the configured amount of seconds
27978
27061
  // We only try to jump the hole if it's under the configured size
27979
27062
  // Reset stalled so to rearm watchdog timer
@@ -27995,7 +27078,7 @@
27995
27078
  // Report stalled error once
27996
27079
  this.stallReported = true;
27997
27080
  var error = new Error("Playback stalling at @" + media.currentTime + " due to low buffer (" + JSON.stringify(bufferInfo) + ")");
27998
- this.warn(error.message);
27081
+ logger.warn(error.message);
27999
27082
  hls.trigger(Events.ERROR, {
28000
27083
  type: ErrorTypes.MEDIA_ERROR,
28001
27084
  details: ErrorDetails.BUFFER_STALLED_ERROR,
@@ -28059,7 +27142,7 @@
28059
27142
  }
28060
27143
  }
28061
27144
  var targetTime = Math.max(startTime + SKIP_BUFFER_RANGE_START, currentTime + SKIP_BUFFER_HOLE_STEP_SECONDS);
28062
- this.warn("skipping hole, adjusting currentTime from " + currentTime + " to " + targetTime);
27145
+ logger.warn("skipping hole, adjusting currentTime from " + currentTime + " to " + targetTime);
28063
27146
  this.moved = true;
28064
27147
  this.stalled = null;
28065
27148
  media.currentTime = targetTime;
@@ -28098,7 +27181,7 @@
28098
27181
  var targetTime = currentTime + (nudgeRetry + 1) * config.nudgeOffset;
28099
27182
  // playback stalled in buffered area ... let's nudge currentTime to try to overcome this
28100
27183
  var error = new Error("Nudging 'currentTime' from " + currentTime + " to " + targetTime);
28101
- this.warn(error.message);
27184
+ logger.warn(error.message);
28102
27185
  media.currentTime = targetTime;
28103
27186
  hls.trigger(Events.ERROR, {
28104
27187
  type: ErrorTypes.MEDIA_ERROR,
@@ -28108,7 +27191,7 @@
28108
27191
  });
28109
27192
  } else {
28110
27193
  var _error = new Error("Playhead still not moving while enough data buffered @" + currentTime + " after " + config.nudgeMaxRetry + " nudges");
28111
- this.error(_error.message);
27194
+ logger.error(_error.message);
28112
27195
  hls.trigger(Events.ERROR, {
28113
27196
  type: ErrorTypes.MEDIA_ERROR,
28114
27197
  details: ErrorDetails.BUFFER_STALLED_ERROR,
@@ -28118,14 +27201,14 @@
28118
27201
  }
28119
27202
  };
28120
27203
  return GapController;
28121
- }(Logger);
27204
+ }();
28122
27205
 
28123
27206
  var TICK_INTERVAL = 100; // how often to tick in ms
28124
27207
  var StreamController = /*#__PURE__*/function (_BaseStreamController) {
28125
27208
  _inheritsLoose(StreamController, _BaseStreamController);
28126
27209
  function StreamController(hls, fragmentTracker, keyLoader) {
28127
27210
  var _this;
28128
- _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'stream-controller', PlaylistLevelType.MAIN) || this;
27211
+ _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[stream-controller]', PlaylistLevelType.MAIN) || this;
28129
27212
  _this.audioCodecSwap = false;
28130
27213
  _this.gapController = null;
28131
27214
  _this.level = -1;
@@ -28133,43 +27216,27 @@
28133
27216
  _this.altAudio = false;
28134
27217
  _this.audioOnly = false;
28135
27218
  _this.fragPlaying = null;
27219
+ _this.onvplaying = null;
27220
+ _this.onvseeked = null;
28136
27221
  _this.fragLastKbps = 0;
28137
27222
  _this.couldBacktrack = false;
28138
27223
  _this.backtrackFragment = null;
28139
27224
  _this.audioCodecSwitch = false;
28140
27225
  _this.videoBuffer = null;
28141
- _this.onMediaPlaying = function () {
28142
- // tick to speed up FRAG_CHANGED triggering
28143
- _this.tick();
28144
- };
28145
- _this.onMediaSeeked = function () {
28146
- var media = _this.media;
28147
- var currentTime = media ? media.currentTime : null;
28148
- if (isFiniteNumber(currentTime)) {
28149
- _this.log("Media seeked to " + currentTime.toFixed(3));
28150
- }
28151
-
28152
- // If seeked was issued before buffer was appended do not tick immediately
28153
- var bufferInfo = _this.getMainFwdBufferInfo();
28154
- if (bufferInfo === null || bufferInfo.len === 0) {
28155
- _this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
28156
- return;
28157
- }
28158
-
28159
- // tick to speed up FRAG_CHANGED triggering
28160
- _this.tick();
28161
- };
28162
- _this.registerListeners();
27226
+ _this._registerListeners();
28163
27227
  return _this;
28164
27228
  }
28165
27229
  var _proto = StreamController.prototype;
28166
- _proto.registerListeners = function registerListeners() {
28167
- _BaseStreamController.prototype.registerListeners.call(this);
27230
+ _proto._registerListeners = function _registerListeners() {
28168
27231
  var hls = this.hls;
27232
+ hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
27233
+ hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
27234
+ hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
28169
27235
  hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);
28170
27236
  hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);
28171
27237
  hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
28172
27238
  hls.on(Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this);
27239
+ hls.on(Events.ERROR, this.onError, this);
28173
27240
  hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
28174
27241
  hls.on(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
28175
27242
  hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
@@ -28177,12 +27244,15 @@
28177
27244
  hls.on(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);
28178
27245
  hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
28179
27246
  };
28180
- _proto.unregisterListeners = function unregisterListeners() {
28181
- _BaseStreamController.prototype.unregisterListeners.call(this);
27247
+ _proto._unregisterListeners = function _unregisterListeners() {
28182
27248
  var hls = this.hls;
27249
+ hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
27250
+ hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
27251
+ hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
28183
27252
  hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);
28184
27253
  hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
28185
27254
  hls.off(Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this);
27255
+ hls.off(Events.ERROR, this.onError, this);
28186
27256
  hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
28187
27257
  hls.off(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
28188
27258
  hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
@@ -28191,9 +27261,7 @@
28191
27261
  hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);
28192
27262
  };
28193
27263
  _proto.onHandlerDestroying = function onHandlerDestroying() {
28194
- // @ts-ignore
28195
- this.onMediaPlaying = this.onMediaSeeked = null;
28196
- this.unregisterListeners();
27264
+ this._unregisterListeners();
28197
27265
  _BaseStreamController.prototype.onHandlerDestroying.call(this);
28198
27266
  };
28199
27267
  _proto.startLoad = function startLoad(startPosition) {
@@ -28302,7 +27370,7 @@
28302
27370
  return;
28303
27371
  }
28304
27372
  var level = hls.nextLoadLevel;
28305
- if (!this.buffering || !(levels != null && levels[level])) {
27373
+ if (!(levels != null && levels[level])) {
28306
27374
  return;
28307
27375
  }
28308
27376
  var levelInfo = levels[level];
@@ -28508,15 +27576,18 @@
28508
27576
  _proto.onMediaAttached = function onMediaAttached(event, data) {
28509
27577
  _BaseStreamController.prototype.onMediaAttached.call(this, event, data);
28510
27578
  var media = data.media;
28511
- media.addEventListener('playing', this.onMediaPlaying);
28512
- media.addEventListener('seeked', this.onMediaSeeked);
27579
+ this.onvplaying = this.onMediaPlaying.bind(this);
27580
+ this.onvseeked = this.onMediaSeeked.bind(this);
27581
+ media.addEventListener('playing', this.onvplaying);
27582
+ media.addEventListener('seeked', this.onvseeked);
28513
27583
  this.gapController = new GapController(this.config, media, this.fragmentTracker, this.hls);
28514
27584
  };
28515
27585
  _proto.onMediaDetaching = function onMediaDetaching() {
28516
27586
  var media = this.media;
28517
- if (media) {
28518
- media.removeEventListener('playing', this.onMediaPlaying);
28519
- media.removeEventListener('seeked', this.onMediaSeeked);
27587
+ if (media && this.onvplaying && this.onvseeked) {
27588
+ media.removeEventListener('playing', this.onvplaying);
27589
+ media.removeEventListener('seeked', this.onvseeked);
27590
+ this.onvplaying = this.onvseeked = null;
28520
27591
  this.videoBuffer = null;
28521
27592
  }
28522
27593
  this.fragPlaying = null;
@@ -28526,6 +27597,27 @@
28526
27597
  }
28527
27598
  _BaseStreamController.prototype.onMediaDetaching.call(this);
28528
27599
  };
27600
+ _proto.onMediaPlaying = function onMediaPlaying() {
27601
+ // tick to speed up FRAG_CHANGED triggering
27602
+ this.tick();
27603
+ };
27604
+ _proto.onMediaSeeked = function onMediaSeeked() {
27605
+ var media = this.media;
27606
+ var currentTime = media ? media.currentTime : null;
27607
+ if (isFiniteNumber(currentTime)) {
27608
+ this.log("Media seeked to " + currentTime.toFixed(3));
27609
+ }
27610
+
27611
+ // If seeked was issued before buffer was appended do not tick immediately
27612
+ var bufferInfo = this.getMainFwdBufferInfo();
27613
+ if (bufferInfo === null || bufferInfo.len === 0) {
27614
+ this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
27615
+ return;
27616
+ }
27617
+
27618
+ // tick to speed up FRAG_CHANGED triggering
27619
+ this.tick();
27620
+ };
28529
27621
  _proto.onManifestLoading = function onManifestLoading() {
28530
27622
  // reset buffer on manifest loading
28531
27623
  this.log('Trigger BUFFER_RESET');
@@ -28806,10 +27898,8 @@
28806
27898
  }
28807
27899
  if (this.loadedmetadata || !BufferHelper.getBuffered(media).length) {
28808
27900
  // Resolve gaps using the main buffer, whose ranges are the intersections of the A/V sourcebuffers
28809
- var state = this.state;
28810
- var activeFrag = state !== State.IDLE ? this.fragCurrent : null;
28811
- var levelDetails = this.getLevelDetails();
28812
- gapController.poll(this.lastCurrentTime, activeFrag, levelDetails, state);
27901
+ var activeFrag = this.state !== State.IDLE ? this.fragCurrent : null;
27902
+ gapController.poll(this.lastCurrentTime, activeFrag);
28813
27903
  }
28814
27904
  this.lastCurrentTime = media.currentTime;
28815
27905
  };
@@ -29274,12 +28364,9 @@
29274
28364
  * The configuration object provided on player instantiation.
29275
28365
  */
29276
28366
  this.userConfig = void 0;
29277
- /**
29278
- * The logger functions used by this player instance, configured on player instantiation.
29279
- */
29280
- this.logger = void 0;
29281
28367
  this.coreComponents = void 0;
29282
28368
  this.networkControllers = void 0;
28369
+ this.started = false;
29283
28370
  this._emitter = new EventEmitter();
29284
28371
  this._autoLevelCapping = -1;
29285
28372
  this._maxHdcpLevel = null;
@@ -29296,11 +28383,11 @@
29296
28383
  this._media = null;
29297
28384
  this.url = null;
29298
28385
  this.triggeringException = void 0;
29299
- var logger = this.logger = enableLogs(userConfig.debug || false, 'Hls instance');
29300
- var config = this.config = mergeConfig(Hls.DefaultConfig, userConfig, logger);
28386
+ enableLogs(userConfig.debug || false, 'Hls instance');
28387
+ var config = this.config = mergeConfig(Hls.DefaultConfig, userConfig);
29301
28388
  this.userConfig = userConfig;
29302
28389
  if (config.progressive) {
29303
- enableStreamingMode(config, logger);
28390
+ enableStreamingMode(config);
29304
28391
  }
29305
28392
 
29306
28393
  // core controllers and network loaders
@@ -29408,7 +28495,7 @@
29408
28495
  try {
29409
28496
  return this.emit(event, event, eventObject);
29410
28497
  } catch (error) {
29411
- this.logger.error('An internal error happened while handling event ' + event + '. Error message: "' + error.message + '". Here is a stacktrace:', error);
28498
+ logger.error('An internal error happened while handling event ' + event + '. Error message: "' + error.message + '". Here is a stacktrace:', error);
29412
28499
  // Prevent recursion in error event handlers that throw #5497
29413
28500
  if (!this.triggeringException) {
29414
28501
  this.triggeringException = true;
@@ -29434,7 +28521,7 @@
29434
28521
  * Dispose of the instance
29435
28522
  */;
29436
28523
  _proto.destroy = function destroy() {
29437
- this.logger.log('destroy');
28524
+ logger.log('destroy');
29438
28525
  this.trigger(Events.DESTROYING, undefined);
29439
28526
  this.detachMedia();
29440
28527
  this.removeAllListeners();
@@ -29459,7 +28546,7 @@
29459
28546
  * Attaches Hls.js to a media element
29460
28547
  */;
29461
28548
  _proto.attachMedia = function attachMedia(media) {
29462
- this.logger.log('attachMedia');
28549
+ logger.log('attachMedia');
29463
28550
  this._media = media;
29464
28551
  this.trigger(Events.MEDIA_ATTACHING, {
29465
28552
  media: media
@@ -29470,7 +28557,7 @@
29470
28557
  * Detach Hls.js from the media
29471
28558
  */;
29472
28559
  _proto.detachMedia = function detachMedia() {
29473
- this.logger.log('detachMedia');
28560
+ logger.log('detachMedia');
29474
28561
  this.trigger(Events.MEDIA_DETACHING, undefined);
29475
28562
  this._media = null;
29476
28563
  }
@@ -29487,7 +28574,7 @@
29487
28574
  });
29488
28575
  this._autoLevelCapping = -1;
29489
28576
  this._maxHdcpLevel = null;
29490
- this.logger.log("loadSource:" + loadingSource);
28577
+ logger.log("loadSource:" + loadingSource);
29491
28578
  if (media && loadedSource && (loadedSource !== loadingSource || this.bufferController.hasSourceTypes())) {
29492
28579
  this.detachMedia();
29493
28580
  this.attachMedia(media);
@@ -29509,7 +28596,8 @@
29509
28596
  if (startPosition === void 0) {
29510
28597
  startPosition = -1;
29511
28598
  }
29512
- this.logger.log("startLoad(" + startPosition + ")");
28599
+ logger.log("startLoad(" + startPosition + ")");
28600
+ this.started = true;
29513
28601
  this.networkControllers.forEach(function (controller) {
29514
28602
  controller.startLoad(startPosition);
29515
28603
  });
@@ -29519,31 +28607,34 @@
29519
28607
  * Stop loading of any stream data.
29520
28608
  */;
29521
28609
  _proto.stopLoad = function stopLoad() {
29522
- this.logger.log('stopLoad');
28610
+ logger.log('stopLoad');
28611
+ this.started = false;
29523
28612
  this.networkControllers.forEach(function (controller) {
29524
28613
  controller.stopLoad();
29525
28614
  });
29526
28615
  }
29527
28616
 
29528
28617
  /**
29529
- * Resumes stream controller segment loading after `pauseBuffering` has been called.
28618
+ * Resumes stream controller segment loading if previously started.
29530
28619
  */;
29531
28620
  _proto.resumeBuffering = function resumeBuffering() {
29532
- this.networkControllers.forEach(function (controller) {
29533
- if (controller.resumeBuffering) {
29534
- controller.resumeBuffering();
29535
- }
29536
- });
28621
+ if (this.started) {
28622
+ this.networkControllers.forEach(function (controller) {
28623
+ if ('fragmentLoader' in controller) {
28624
+ controller.startLoad(-1);
28625
+ }
28626
+ });
28627
+ }
29537
28628
  }
29538
28629
 
29539
28630
  /**
29540
- * Prevents stream controller from loading new segments until `resumeBuffering` is called.
28631
+ * Stops stream controller segment loading without changing 'started' state like stopLoad().
29541
28632
  * This allows for media buffering to be paused without interupting playlist loading.
29542
28633
  */;
29543
28634
  _proto.pauseBuffering = function pauseBuffering() {
29544
28635
  this.networkControllers.forEach(function (controller) {
29545
- if (controller.pauseBuffering) {
29546
- controller.pauseBuffering();
28636
+ if ('fragmentLoader' in controller) {
28637
+ controller.stopLoad();
29547
28638
  }
29548
28639
  });
29549
28640
  }
@@ -29552,7 +28643,7 @@
29552
28643
  * Swap through possible audio codecs in the stream (for example to switch from stereo to 5.1)
29553
28644
  */;
29554
28645
  _proto.swapAudioCodec = function swapAudioCodec() {
29555
- this.logger.log('swapAudioCodec');
28646
+ logger.log('swapAudioCodec');
29556
28647
  this.streamController.swapAudioCodec();
29557
28648
  }
29558
28649
 
@@ -29563,7 +28654,7 @@
29563
28654
  * Automatic recovery of media-errors by this process is configurable.
29564
28655
  */;
29565
28656
  _proto.recoverMediaError = function recoverMediaError() {
29566
- this.logger.log('recoverMediaError');
28657
+ logger.log('recoverMediaError');
29567
28658
  var media = this._media;
29568
28659
  this.detachMedia();
29569
28660
  if (media) {
@@ -29618,7 +28709,7 @@
29618
28709
  * 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.
29619
28710
  */,
29620
28711
  set: function set(newLevel) {
29621
- this.logger.log("set currentLevel:" + newLevel);
28712
+ logger.log("set currentLevel:" + newLevel);
29622
28713
  this.levelController.manualLevel = newLevel;
29623
28714
  this.streamController.immediateLevelSwitch();
29624
28715
  }
@@ -29639,7 +28730,7 @@
29639
28730
  * @param newLevel - Pass -1 for automatic level selection
29640
28731
  */,
29641
28732
  set: function set(newLevel) {
29642
- this.logger.log("set nextLevel:" + newLevel);
28733
+ logger.log("set nextLevel:" + newLevel);
29643
28734
  this.levelController.manualLevel = newLevel;
29644
28735
  this.streamController.nextLevelSwitch();
29645
28736
  }
@@ -29660,7 +28751,7 @@
29660
28751
  * @param newLevel - Pass -1 for automatic level selection
29661
28752
  */,
29662
28753
  set: function set(newLevel) {
29663
- this.logger.log("set loadLevel:" + newLevel);
28754
+ logger.log("set loadLevel:" + newLevel);
29664
28755
  this.levelController.manualLevel = newLevel;
29665
28756
  }
29666
28757
 
@@ -29695,7 +28786,7 @@
29695
28786
  * Sets "first-level", see getter.
29696
28787
  */,
29697
28788
  set: function set(newLevel) {
29698
- this.logger.log("set firstLevel:" + newLevel);
28789
+ logger.log("set firstLevel:" + newLevel);
29699
28790
  this.levelController.firstLevel = newLevel;
29700
28791
  }
29701
28792
 
@@ -29722,7 +28813,7 @@
29722
28813
  * (determined from download of first segment)
29723
28814
  */,
29724
28815
  set: function set(newLevel) {
29725
- this.logger.log("set startLevel:" + newLevel);
28816
+ logger.log("set startLevel:" + newLevel);
29726
28817
  // if not in automatic start level detection, ensure startLevel is greater than minAutoLevel
29727
28818
  if (newLevel !== -1) {
29728
28819
  newLevel = Math.max(newLevel, this.minAutoLevel);
@@ -29775,7 +28866,7 @@
29775
28866
  */
29776
28867
  function set(newLevel) {
29777
28868
  if (this._autoLevelCapping !== newLevel) {
29778
- this.logger.log("set autoLevelCapping:" + newLevel);
28869
+ logger.log("set autoLevelCapping:" + newLevel);
29779
28870
  this._autoLevelCapping = newLevel;
29780
28871
  this.levelController.checkMaxAutoUpdated();
29781
28872
  }
@@ -30100,7 +29191,7 @@
30100
29191
  * Get the video-dev/hls.js package version.
30101
29192
  */
30102
29193
  function get() {
30103
- return "1.5.6-0.canary.10011";
29194
+ return "1.5.6";
30104
29195
  }
30105
29196
  }, {
30106
29197
  key: "Events",