hls.js 1.5.5-0.canary.9995 → 1.5.5

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 +20 -20
  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.5");
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.5-0.canary.9995");
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
 
@@ -2949,13 +2923,13 @@
2949
2923
  this.keyFormatVersions = formatversions;
2950
2924
  this.iv = iv;
2951
2925
  this.encrypted = method ? method !== 'NONE' : false;
2952
- this.isCommonEncryption = this.encrypted && !isFullSegmentEncryption(method);
2926
+ this.isCommonEncryption = this.encrypted && method !== 'AES-128';
2953
2927
  }
2954
2928
  var _proto = LevelKey.prototype;
2955
2929
  _proto.isSupported = function isSupported() {
2956
2930
  // If it's Segment encryption or No encryption, just select that key system
2957
2931
  if (this.method) {
2958
- if (isFullSegmentEncryption(this.method) || this.method === 'NONE') {
2932
+ if (this.method === 'AES-128' || this.method === 'NONE') {
2959
2933
  return true;
2960
2934
  }
2961
2935
  if (this.keyFormat === 'identity') {
@@ -2977,13 +2951,14 @@
2977
2951
  if (!this.encrypted || !this.uri) {
2978
2952
  return null;
2979
2953
  }
2980
- if (isFullSegmentEncryption(this.method) && this.uri && !this.iv) {
2954
+ if (this.method === 'AES-128' && this.uri && !this.iv) {
2981
2955
  if (typeof sn !== 'number') {
2982
2956
  // We are fetching decryption data for a initialization segment
2983
- // If the segment was encrypted with AES-128/256
2957
+ // If the segment was encrypted with AES-128
2984
2958
  // It must have an IV defined. We cannot substitute the Segment Number in.
2985
- logger.warn("missing IV for initialization segment with method=\"" + this.method + "\" - compliance issue");
2986
-
2959
+ if (this.method === 'AES-128' && !this.iv) {
2960
+ logger.warn("missing IV for initialization segment with method=\"" + this.method + "\" - compliance issue");
2961
+ }
2987
2962
  // Explicitly set sn to resulting value from implicit conversions 'initSegment' values for IV generation.
2988
2963
  sn = 0;
2989
2964
  }
@@ -3277,28 +3252,23 @@
3277
3252
  if (CODEC_COMPATIBLE_NAMES[lowerCaseCodec]) {
3278
3253
  return CODEC_COMPATIBLE_NAMES[lowerCaseCodec];
3279
3254
  }
3255
+
3256
+ // Idealy fLaC and Opus would be first (spec-compliant) but
3257
+ // some browsers will report that fLaC is supported then fail.
3258
+ // see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
3280
3259
  var codecsToCheck = {
3281
- // Idealy fLaC and Opus would be first (spec-compliant) but
3282
- // some browsers will report that fLaC is supported then fail.
3283
- // see: https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
3284
3260
  flac: ['flac', 'fLaC', 'FLAC'],
3285
- opus: ['opus', 'Opus'],
3286
- // Replace audio codec info if browser does not support mp4a.40.34,
3287
- // and demuxer can fallback to 'audio/mpeg' or 'audio/mp4;codecs="mp3"'
3288
- 'mp4a.40.34': ['mp3']
3261
+ opus: ['opus', 'Opus']
3289
3262
  }[lowerCaseCodec];
3290
3263
  for (var i = 0; i < codecsToCheck.length; i++) {
3291
- var _getMediaSource;
3292
3264
  if (isCodecMediaSourceSupported(codecsToCheck[i], 'audio', preferManagedMediaSource)) {
3293
3265
  CODEC_COMPATIBLE_NAMES[lowerCaseCodec] = codecsToCheck[i];
3294
3266
  return codecsToCheck[i];
3295
- } else if (codecsToCheck[i] === 'mp3' && (_getMediaSource = getMediaSource(preferManagedMediaSource)) != null && _getMediaSource.isTypeSupported('audio/mpeg')) {
3296
- return '';
3297
3267
  }
3298
3268
  }
3299
3269
  return lowerCaseCodec;
3300
3270
  }
3301
- var AUDIO_CODEC_REGEXP = /flac|opus|mp4a\.40\.34/i;
3271
+ var AUDIO_CODEC_REGEXP = /flac|opus/i;
3302
3272
  function getCodecCompatibleName(codec, preferManagedMediaSource) {
3303
3273
  if (preferManagedMediaSource === void 0) {
3304
3274
  preferManagedMediaSource = true;
@@ -3326,18 +3296,6 @@
3326
3296
  }
3327
3297
  return codec;
3328
3298
  }
3329
- function getM2TSSupportedAudioTypes(preferManagedMediaSource) {
3330
- var MediaSource = getMediaSource(preferManagedMediaSource) || {
3331
- isTypeSupported: function isTypeSupported() {
3332
- return false;
3333
- }
3334
- };
3335
- return {
3336
- mpeg: MediaSource.isTypeSupported('audio/mpeg'),
3337
- mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
3338
- ac3: MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"')
3339
- };
3340
- }
3341
3299
 
3342
3300
  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;
3343
3301
  var MASTER_PLAYLIST_MEDIA_REGEX = /#EXT-X-MEDIA:(.*)/g;
@@ -4187,10 +4145,10 @@
4187
4145
  var loaderContext = loader.context;
4188
4146
  if (loaderContext && loaderContext.url === context.url && loaderContext.level === context.level) {
4189
4147
  // same URL can't overlap
4190
- this.hls.logger.trace('[playlist-loader]: playlist request ongoing');
4148
+ logger.trace('[playlist-loader]: playlist request ongoing');
4191
4149
  return;
4192
4150
  }
4193
- this.hls.logger.log("[playlist-loader]: aborting previous loader for type: " + context.type);
4151
+ logger.log("[playlist-loader]: aborting previous loader for type: " + context.type);
4194
4152
  loader.abort();
4195
4153
  }
4196
4154
 
@@ -4300,7 +4258,7 @@
4300
4258
  // alt audio rendition in which quality levels (main)
4301
4259
  // contains both audio+video. but with mixed audio track not signaled
4302
4260
  if (!embeddedAudioFound && levels[0].audioCodec && !levels[0].attrs.AUDIO) {
4303
- this.hls.logger.log('[playlist-loader]: audio codec signaled in quality level, but no embedded audio track signaled, create one');
4261
+ logger.log('[playlist-loader]: audio codec signaled in quality level, but no embedded audio track signaled, create one');
4304
4262
  audioTracks.unshift({
4305
4263
  type: 'main',
4306
4264
  name: 'main',
@@ -4400,7 +4358,7 @@
4400
4358
  message += " id: " + context.id + " group-id: \"" + context.groupId + "\"";
4401
4359
  }
4402
4360
  var error = new Error(message);
4403
- this.hls.logger.warn("[playlist-loader]: " + message);
4361
+ logger.warn("[playlist-loader]: " + message);
4404
4362
  var details = ErrorDetails.UNKNOWN;
4405
4363
  var fatal = false;
4406
4364
  var loader = this.getInternalLoader(context);
@@ -5001,43 +4959,8 @@
5001
4959
  this.currentTime = 0;
5002
4960
  this.stallCount = 0;
5003
4961
  this._latency = null;
5004
- this.onTimeupdate = function () {
5005
- var media = _this.media,
5006
- levelDetails = _this.levelDetails;
5007
- if (!media || !levelDetails) {
5008
- return;
5009
- }
5010
- _this.currentTime = media.currentTime;
5011
- var latency = _this.computeLatency();
5012
- if (latency === null) {
5013
- return;
5014
- }
5015
- _this._latency = latency;
5016
-
5017
- // Adapt playbackRate to meet target latency in low-latency mode
5018
- var _this$config = _this.config,
5019
- lowLatencyMode = _this$config.lowLatencyMode,
5020
- maxLiveSyncPlaybackRate = _this$config.maxLiveSyncPlaybackRate;
5021
- if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1 || !levelDetails.live) {
5022
- return;
5023
- }
5024
- var targetLatency = _this.targetLatency;
5025
- if (targetLatency === null) {
5026
- return;
5027
- }
5028
- var distanceFromTarget = latency - targetLatency;
5029
- // Only adjust playbackRate when within one target duration of targetLatency
5030
- // and more than one second from under-buffering.
5031
- // Playback further than one target duration from target can be considered DVR playback.
5032
- var liveMinLatencyDuration = Math.min(_this.maxLatency, targetLatency + levelDetails.targetduration);
5033
- var inLiveRange = distanceFromTarget < liveMinLatencyDuration;
5034
- if (inLiveRange && distanceFromTarget > 0.05 && _this.forwardBufferLength > 1) {
5035
- var max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));
5036
- var rate = Math.round(2 / (1 + Math.exp(-0.75 * distanceFromTarget - _this.edgeStalled)) * 20) / 20;
5037
- media.playbackRate = Math.min(max, Math.max(1, rate));
5038
- } else if (media.playbackRate !== 1 && media.playbackRate !== 0) {
5039
- media.playbackRate = 1;
5040
- }
4962
+ this.timeupdateHandler = function () {
4963
+ return _this.timeupdate();
5041
4964
  };
5042
4965
  this.hls = hls;
5043
4966
  this.config = hls.config;
@@ -5049,7 +4972,7 @@
5049
4972
  this.onMediaDetaching();
5050
4973
  this.levelDetails = null;
5051
4974
  // @ts-ignore
5052
- this.hls = null;
4975
+ this.hls = this.timeupdateHandler = null;
5053
4976
  };
5054
4977
  _proto.registerListeners = function registerListeners() {
5055
4978
  this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
@@ -5067,11 +4990,11 @@
5067
4990
  };
5068
4991
  _proto.onMediaAttached = function onMediaAttached(event, data) {
5069
4992
  this.media = data.media;
5070
- this.media.addEventListener('timeupdate', this.onTimeupdate);
4993
+ this.media.addEventListener('timeupdate', this.timeupdateHandler);
5071
4994
  };
5072
4995
  _proto.onMediaDetaching = function onMediaDetaching() {
5073
4996
  if (this.media) {
5074
- this.media.removeEventListener('timeupdate', this.onTimeupdate);
4997
+ this.media.removeEventListener('timeupdate', this.timeupdateHandler);
5075
4998
  this.media = null;
5076
4999
  }
5077
5000
  };
@@ -5084,10 +5007,10 @@
5084
5007
  var details = _ref.details;
5085
5008
  this.levelDetails = details;
5086
5009
  if (details.advanced) {
5087
- this.onTimeupdate();
5010
+ this.timeupdate();
5088
5011
  }
5089
5012
  if (!details.live && this.media) {
5090
- this.media.removeEventListener('timeupdate', this.onTimeupdate);
5013
+ this.media.removeEventListener('timeupdate', this.timeupdateHandler);
5091
5014
  }
5092
5015
  };
5093
5016
  _proto.onError = function onError(event, data) {
@@ -5097,7 +5020,45 @@
5097
5020
  }
5098
5021
  this.stallCount++;
5099
5022
  if ((_this$levelDetails = this.levelDetails) != null && _this$levelDetails.live) {
5100
- this.hls.logger.warn('[latency-controller]: Stall detected, adjusting target latency');
5023
+ logger.warn('[playback-rate-controller]: Stall detected, adjusting target latency');
5024
+ }
5025
+ };
5026
+ _proto.timeupdate = function timeupdate() {
5027
+ var media = this.media,
5028
+ levelDetails = this.levelDetails;
5029
+ if (!media || !levelDetails) {
5030
+ return;
5031
+ }
5032
+ this.currentTime = media.currentTime;
5033
+ var latency = this.computeLatency();
5034
+ if (latency === null) {
5035
+ return;
5036
+ }
5037
+ this._latency = latency;
5038
+
5039
+ // Adapt playbackRate to meet target latency in low-latency mode
5040
+ var _this$config = this.config,
5041
+ lowLatencyMode = _this$config.lowLatencyMode,
5042
+ maxLiveSyncPlaybackRate = _this$config.maxLiveSyncPlaybackRate;
5043
+ if (!lowLatencyMode || maxLiveSyncPlaybackRate === 1 || !levelDetails.live) {
5044
+ return;
5045
+ }
5046
+ var targetLatency = this.targetLatency;
5047
+ if (targetLatency === null) {
5048
+ return;
5049
+ }
5050
+ var distanceFromTarget = latency - targetLatency;
5051
+ // Only adjust playbackRate when within one target duration of targetLatency
5052
+ // and more than one second from under-buffering.
5053
+ // Playback further than one target duration from target can be considered DVR playback.
5054
+ var liveMinLatencyDuration = Math.min(this.maxLatency, targetLatency + levelDetails.targetduration);
5055
+ var inLiveRange = distanceFromTarget < liveMinLatencyDuration;
5056
+ if (inLiveRange && distanceFromTarget > 0.05 && this.forwardBufferLength > 1) {
5057
+ var max = Math.min(2, Math.max(1.0, maxLiveSyncPlaybackRate));
5058
+ var rate = Math.round(2 / (1 + Math.exp(-0.75 * distanceFromTarget - this.edgeStalled)) * 20) / 20;
5059
+ media.playbackRate = Math.min(max, Math.max(1, rate));
5060
+ } else if (media.playbackRate !== 1 && media.playbackRate !== 0) {
5061
+ media.playbackRate = 1;
5101
5062
  }
5102
5063
  };
5103
5064
  _proto.estimateLiveEdge = function estimateLiveEdge() {
@@ -6005,17 +5966,19 @@
6005
5966
  MoveAllAlternatesMatchingHDCP: 2,
6006
5967
  SwitchToSDR: 4
6007
5968
  }; // Reserved for future use
6008
- var ErrorController = /*#__PURE__*/function (_Logger) {
6009
- _inheritsLoose(ErrorController, _Logger);
5969
+ var ErrorController = /*#__PURE__*/function () {
6010
5970
  function ErrorController(hls) {
6011
- var _this;
6012
- _this = _Logger.call(this, 'error-controller', hls.logger) || this;
6013
- _this.hls = void 0;
6014
- _this.playlistError = 0;
6015
- _this.penalizedRenditions = {};
6016
- _this.hls = hls;
6017
- _this.registerListeners();
6018
- return _this;
5971
+ this.hls = void 0;
5972
+ this.playlistError = 0;
5973
+ this.penalizedRenditions = {};
5974
+ this.log = void 0;
5975
+ this.warn = void 0;
5976
+ this.error = void 0;
5977
+ this.hls = hls;
5978
+ this.log = logger.log.bind(logger, "[info]:");
5979
+ this.warn = logger.warn.bind(logger, "[warning]:");
5980
+ this.error = logger.error.bind(logger, "[error]:");
5981
+ this.registerListeners();
6019
5982
  }
6020
5983
  var _proto = ErrorController.prototype;
6021
5984
  _proto.registerListeners = function registerListeners() {
@@ -6371,19 +6334,19 @@
6371
6334
  }
6372
6335
  };
6373
6336
  return ErrorController;
6374
- }(Logger);
6337
+ }();
6375
6338
 
6376
- var BasePlaylistController = /*#__PURE__*/function (_Logger) {
6377
- _inheritsLoose(BasePlaylistController, _Logger);
6339
+ var BasePlaylistController = /*#__PURE__*/function () {
6378
6340
  function BasePlaylistController(hls, logPrefix) {
6379
- var _this;
6380
- _this = _Logger.call(this, logPrefix, hls.logger) || this;
6381
- _this.hls = void 0;
6382
- _this.timer = -1;
6383
- _this.requestScheduled = -1;
6384
- _this.canLoad = false;
6385
- _this.hls = hls;
6386
- return _this;
6341
+ this.hls = void 0;
6342
+ this.timer = -1;
6343
+ this.requestScheduled = -1;
6344
+ this.canLoad = false;
6345
+ this.log = void 0;
6346
+ this.warn = void 0;
6347
+ this.log = logger.log.bind(logger, logPrefix + ":");
6348
+ this.warn = logger.warn.bind(logger, logPrefix + ":");
6349
+ this.hls = hls;
6387
6350
  }
6388
6351
  var _proto = BasePlaylistController.prototype;
6389
6352
  _proto.destroy = function destroy() {
@@ -6416,7 +6379,7 @@
6416
6379
  try {
6417
6380
  uri = new self.URL(attr.URI, previous.url).href;
6418
6381
  } catch (error) {
6419
- this.warn("Could not construct new URL for Rendition Report: " + error);
6382
+ logger.warn("Could not construct new URL for Rendition Report: " + error);
6420
6383
  uri = attr.URI || '';
6421
6384
  }
6422
6385
  // Use exact match. Otherwise, the last partial match, if any, will be used
@@ -6455,7 +6418,7 @@
6455
6418
  return this.timer === -1 && this.requestScheduled === -1 && this.shouldLoadPlaylist(playlist);
6456
6419
  };
6457
6420
  _proto.playlistLoaded = function playlistLoaded(index, data, previousDetails) {
6458
- var _this2 = this;
6421
+ var _this = this;
6459
6422
  var details = data.details,
6460
6423
  stats = data.stats;
6461
6424
 
@@ -6502,12 +6465,7 @@
6502
6465
  var cdnAge = lastAdvanced + details.ageHeader;
6503
6466
  var currentGoal = Math.min(cdnAge - details.partTarget, details.targetduration * 1.5);
6504
6467
  if (currentGoal > 0) {
6505
- if (cdnAge > details.targetduration * 3) {
6506
- // Omit segment and part directives when the last response was more than 3 target durations ago,
6507
- this.log("Playlist last advanced " + lastAdvanced.toFixed(2) + "s ago. Omitting segment and part directives.");
6508
- msn = undefined;
6509
- part = undefined;
6510
- } else if (previousDetails != null && previousDetails.tuneInGoal && cdnAge - details.partTarget > previousDetails.tuneInGoal) {
6468
+ if (previousDetails && currentGoal > previousDetails.tuneInGoal) {
6511
6469
  // If we attempted to get the next or latest playlist update, but currentGoal increased,
6512
6470
  // then we either can't catchup, or the "age" header cannot be trusted.
6513
6471
  this.warn("CDN Tune-in goal increased from: " + previousDetails.tuneInGoal + " to: " + currentGoal + " with playlist age: " + details.age);
@@ -6565,7 +6523,7 @@
6565
6523
  // );
6566
6524
 
6567
6525
  this.timer = self.setTimeout(function () {
6568
- return _this2.loadPlaylist(deliveryDirectives);
6526
+ return _this.loadPlaylist(deliveryDirectives);
6569
6527
  }, estimatedTimeUntilUpdate);
6570
6528
  } else {
6571
6529
  this.clearTimer();
@@ -6581,7 +6539,7 @@
6581
6539
  return new HlsUrlParameters(msn, part, skip);
6582
6540
  };
6583
6541
  _proto.checkRetry = function checkRetry(errorEvent) {
6584
- var _this3 = this;
6542
+ var _this2 = this;
6585
6543
  var errorDetails = errorEvent.details;
6586
6544
  var isTimeout = isTimeoutError(errorEvent);
6587
6545
  var errorAction = errorEvent.errorAction;
@@ -6605,7 +6563,7 @@
6605
6563
  var delay = getRetryDelay(retryConfig, retryCount);
6606
6564
  // Schedule level/track reload
6607
6565
  this.timer = self.setTimeout(function () {
6608
- return _this3.loadPlaylist();
6566
+ return _this2.loadPlaylist();
6609
6567
  }, delay);
6610
6568
  this.warn("Retrying playlist loading " + (retryCount + 1) + "/" + retryConfig.maxNumRetry + " after \"" + errorDetails + "\" in " + delay + "ms");
6611
6569
  }
@@ -6616,7 +6574,7 @@
6616
6574
  return retry;
6617
6575
  };
6618
6576
  return BasePlaylistController;
6619
- }(Logger);
6577
+ }();
6620
6578
 
6621
6579
  /*
6622
6580
  * compute an Exponential Weighted moving average
@@ -7218,33 +7176,30 @@
7218
7176
  return -1;
7219
7177
  }
7220
7178
 
7221
- var AbrController = /*#__PURE__*/function (_Logger) {
7222
- _inheritsLoose(AbrController, _Logger);
7179
+ var AbrController = /*#__PURE__*/function () {
7223
7180
  function AbrController(_hls) {
7224
- var _this;
7225
- _this = _Logger.call(this, 'abr', _hls.logger) || this;
7226
- _this.hls = void 0;
7227
- _this.lastLevelLoadSec = 0;
7228
- _this.lastLoadedFragLevel = -1;
7229
- _this.firstSelection = -1;
7230
- _this._nextAutoLevel = -1;
7231
- _this.nextAutoLevelKey = '';
7232
- _this.audioTracksByGroup = null;
7233
- _this.codecTiers = null;
7234
- _this.timer = -1;
7235
- _this.fragCurrent = null;
7236
- _this.partCurrent = null;
7237
- _this.bitrateTestDelay = 0;
7238
- _this.bwEstimator = void 0;
7181
+ var _this = this;
7182
+ this.hls = void 0;
7183
+ this.lastLevelLoadSec = 0;
7184
+ this.lastLoadedFragLevel = -1;
7185
+ this.firstSelection = -1;
7186
+ this._nextAutoLevel = -1;
7187
+ this.nextAutoLevelKey = '';
7188
+ this.audioTracksByGroup = null;
7189
+ this.codecTiers = null;
7190
+ this.timer = -1;
7191
+ this.fragCurrent = null;
7192
+ this.partCurrent = null;
7193
+ this.bitrateTestDelay = 0;
7194
+ this.bwEstimator = void 0;
7239
7195
  /*
7240
7196
  This method monitors the download rate of the current fragment, and will downswitch if that fragment will not load
7241
7197
  quickly enough to prevent underbuffering
7242
7198
  */
7243
- _this._abandonRulesCheck = function () {
7244
- var _assertThisInitialize = _assertThisInitialized(_this),
7245
- frag = _assertThisInitialize.fragCurrent,
7246
- part = _assertThisInitialize.partCurrent,
7247
- hls = _assertThisInitialize.hls;
7199
+ this._abandonRulesCheck = function () {
7200
+ var frag = _this.fragCurrent,
7201
+ part = _this.partCurrent,
7202
+ hls = _this.hls;
7248
7203
  var autoLevelEnabled = hls.autoLevelEnabled,
7249
7204
  media = hls.media;
7250
7205
  if (!frag || !media) {
@@ -7333,22 +7288,21 @@
7333
7288
  _this.resetEstimator(nextLoadLevelBitrate);
7334
7289
  }
7335
7290
  _this.clearTimer();
7336
- _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");
7291
+ logger.warn("[abr] Fragment " + frag.sn + (part ? ' part ' + part.index : '') + " of level " + frag.level + " is loading too slowly;\n Time to underbuffer: " + bufferStarvationDelay.toFixed(3) + " s\n Estimated load time for current fragment: " + fragLoadedDelay.toFixed(3) + " s\n Estimated load time for down switch fragment: " + fragLevelNextLoadedDelay.toFixed(3) + " s\n TTFB estimate: " + (ttfb | 0) + " ms\n Current BW estimate: " + (isFiniteNumber(bwEstimate) ? bwEstimate | 0 : 'Unknown') + " bps\n New BW estimate: " + (_this.getBwEstimate() | 0) + " bps\n Switching to level " + nextLoadLevel + " @ " + (nextLoadLevelBitrate | 0) + " bps");
7337
7292
  hls.trigger(Events.FRAG_LOAD_EMERGENCY_ABORTED, {
7338
7293
  frag: frag,
7339
7294
  part: part,
7340
7295
  stats: stats
7341
7296
  });
7342
7297
  };
7343
- _this.hls = _hls;
7344
- _this.bwEstimator = _this.initEstimator();
7345
- _this.registerListeners();
7346
- return _this;
7298
+ this.hls = _hls;
7299
+ this.bwEstimator = this.initEstimator();
7300
+ this.registerListeners();
7347
7301
  }
7348
7302
  var _proto = AbrController.prototype;
7349
7303
  _proto.resetEstimator = function resetEstimator(abrEwmaDefaultEstimate) {
7350
7304
  if (abrEwmaDefaultEstimate) {
7351
- this.log("setting initial bwe to " + abrEwmaDefaultEstimate);
7305
+ logger.log("setting initial bwe to " + abrEwmaDefaultEstimate);
7352
7306
  this.hls.config.abrEwmaDefaultEstimate = abrEwmaDefaultEstimate;
7353
7307
  }
7354
7308
  this.firstSelection = -1;
@@ -7600,13 +7554,13 @@
7600
7554
  // cap maxLoadingDelay and ensure it is not bigger 'than bitrate test' frag duration
7601
7555
  var maxLoadingDelay = currentFragDuration ? Math.min(currentFragDuration, config.maxLoadingDelay) : config.maxLoadingDelay;
7602
7556
  maxStarvationDelay = maxLoadingDelay - bitrateTestDelay;
7603
- this.info("bitrate test took " + Math.round(1000 * bitrateTestDelay) + "ms, set first fragment max fetchDuration to " + Math.round(1000 * maxStarvationDelay) + " ms");
7557
+ logger.info("[abr] bitrate test took " + Math.round(1000 * bitrateTestDelay) + "ms, set first fragment max fetchDuration to " + Math.round(1000 * maxStarvationDelay) + " ms");
7604
7558
  // don't use conservative factor on bitrate test
7605
7559
  bwFactor = bwUpFactor = 1;
7606
7560
  }
7607
7561
  }
7608
7562
  var bestLevel = this.findBestLevel(avgbw, minAutoLevel, maxAutoLevel, bufferStarvationDelay, maxStarvationDelay, bwFactor, bwUpFactor);
7609
- this.info((bufferStarvationDelay ? 'rebuffering expected' : 'buffer is empty') + ", optimal quality level " + bestLevel);
7563
+ logger.info("[abr] " + (bufferStarvationDelay ? 'rebuffering expected' : 'buffer is empty') + ", optimal quality level " + bestLevel);
7610
7564
  if (bestLevel > -1) {
7611
7565
  return bestLevel;
7612
7566
  }
@@ -7662,7 +7616,7 @@
7662
7616
  currentVideoRange = preferHDR ? videoRanges[videoRanges.length - 1] : videoRanges[0];
7663
7617
  currentFrameRate = minFramerate;
7664
7618
  currentBw = Math.max(currentBw, minBitrate);
7665
- this.log("picked start tier " + JSON.stringify(startTier));
7619
+ logger.log("[abr] picked start tier " + JSON.stringify(startTier));
7666
7620
  } else {
7667
7621
  currentCodecSet = level == null ? void 0 : level.codecSet;
7668
7622
  currentVideoRange = level == null ? void 0 : level.videoRange;
@@ -7686,11 +7640,11 @@
7686
7640
  var levels = _this2.hls.levels;
7687
7641
  var index = levels.indexOf(levelInfo);
7688
7642
  if (decodingInfo.error) {
7689
- _this2.warn("MediaCapabilities decodingInfo error: \"" + decodingInfo.error + "\" for level " + index + " " + JSON.stringify(decodingInfo));
7643
+ logger.warn("[abr] MediaCapabilities decodingInfo error: \"" + decodingInfo.error + "\" for level " + index + " " + JSON.stringify(decodingInfo));
7690
7644
  } else if (!decodingInfo.supported) {
7691
- _this2.warn("Unsupported MediaCapabilities decodingInfo result for level " + index + " " + JSON.stringify(decodingInfo));
7645
+ logger.warn("[abr] Unsupported MediaCapabilities decodingInfo result for level " + index + " " + JSON.stringify(decodingInfo));
7692
7646
  if (index > -1 && levels.length > 1) {
7693
- _this2.log("Removing unsupported level " + index);
7647
+ logger.log("[abr] Removing unsupported level " + index);
7694
7648
  _this2.hls.removeLevel(index);
7695
7649
  }
7696
7650
  }
@@ -7737,9 +7691,9 @@
7737
7691
  var forcedAutoLevel = _this2.forcedAutoLevel;
7738
7692
  if (i !== loadLevel && (forcedAutoLevel === -1 || forcedAutoLevel !== loadLevel)) {
7739
7693
  if (levelsSkipped.length) {
7740
- _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);
7694
+ logger.trace("[abr] Skipped level(s) " + levelsSkipped.join(',') + " of " + maxAutoLevel + " max with CODECS and VIDEO-RANGE:\"" + levels[levelsSkipped[0]].codecs + "\" " + levels[levelsSkipped[0]].videoRange + "; not compatible with \"" + level.codecs + "\" " + currentVideoRange);
7741
7695
  }
7742
- _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);
7696
+ logger.info("[abr] switch candidate:" + selectionBaseLevel + "->" + i + " adjustedbw(" + Math.round(adjustedbw) + ")-bitrate=" + Math.round(adjustedbw - bitrate) + " ttfb:" + ttfbEstimateSec.toFixed(1) + " avgDuration:" + avgDuration.toFixed(1) + " maxFetchDuration:" + maxFetchDuration.toFixed(1) + " fetchDuration:" + fetchDuration.toFixed(1) + " firstSelection:" + firstSelection + " codecSet:" + currentCodecSet + " videoRange:" + currentVideoRange + " hls.loadLevel:" + loadLevel);
7743
7697
  }
7744
7698
  if (firstSelection) {
7745
7699
  _this2.firstSelection = i;
@@ -7773,7 +7727,7 @@
7773
7727
  }
7774
7728
  var firstLevel = this.hls.firstLevel;
7775
7729
  var clamped = Math.min(Math.max(firstLevel, minAutoLevel), maxAutoLevel);
7776
- this.warn("Could not find best starting auto level. Defaulting to first in playlist " + firstLevel + " clamped to " + clamped);
7730
+ logger.warn("[abr] Could not find best starting auto level. Defaulting to first in playlist " + firstLevel + " clamped to " + clamped);
7777
7731
  return clamped;
7778
7732
  }
7779
7733
  }, {
@@ -7826,7 +7780,7 @@
7826
7780
  }
7827
7781
  }]);
7828
7782
  return AbrController;
7829
- }(Logger);
7783
+ }();
7830
7784
 
7831
7785
  /**
7832
7786
  * @ignore
@@ -7857,17 +7811,13 @@
7857
7811
  * we are limiting the task execution per call stack to exactly one, but scheduling/post-poning further
7858
7812
  * task processing on the next main loop iteration (also known as "next tick" in the Node/JS runtime lingo).
7859
7813
  */
7860
- var TaskLoop = /*#__PURE__*/function (_Logger) {
7861
- _inheritsLoose(TaskLoop, _Logger);
7862
- function TaskLoop(label, logger) {
7863
- var _this;
7864
- _this = _Logger.call(this, label, logger) || this;
7865
- _this._boundTick = void 0;
7866
- _this._tickTimer = null;
7867
- _this._tickInterval = null;
7868
- _this._tickCallCount = 0;
7869
- _this._boundTick = _this.tick.bind(_assertThisInitialized(_this));
7870
- return _this;
7814
+ var TaskLoop = /*#__PURE__*/function () {
7815
+ function TaskLoop() {
7816
+ this._boundTick = void 0;
7817
+ this._tickTimer = null;
7818
+ this._tickInterval = null;
7819
+ this._tickCallCount = 0;
7820
+ this._boundTick = this.tick.bind(this);
7871
7821
  }
7872
7822
  var _proto = TaskLoop.prototype;
7873
7823
  _proto.destroy = function destroy() {
@@ -7953,7 +7903,7 @@
7953
7903
  */;
7954
7904
  _proto.doTick = function doTick() {};
7955
7905
  return TaskLoop;
7956
- }(Logger);
7906
+ }();
7957
7907
 
7958
7908
  var FragmentState = {
7959
7909
  NOT_LOADED: "NOT_LOADED",
@@ -8972,8 +8922,8 @@
8972
8922
  var _frag$decryptdata;
8973
8923
  var byteRangeStart = start;
8974
8924
  var byteRangeEnd = end;
8975
- if (frag.sn === 'initSegment' && isMethodFullSegmentAesCbc((_frag$decryptdata = frag.decryptdata) == null ? void 0 : _frag$decryptdata.method)) {
8976
- // MAP segment encrypted with method 'AES-128' or 'AES-256' (cbc), when served with HTTP Range,
8925
+ if (frag.sn === 'initSegment' && ((_frag$decryptdata = frag.decryptdata) == null ? void 0 : _frag$decryptdata.method) === 'AES-128') {
8926
+ // MAP segment encrypted with method 'AES-128', when served with HTTP Range,
8977
8927
  // has the unencrypted size specified in the range.
8978
8928
  // Ref: https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-6.3.6
8979
8929
  var fragmentLen = end - start;
@@ -9006,9 +8956,6 @@
9006
8956
  (part ? part : frag).stats.aborted = true;
9007
8957
  return new LoadError(errorData);
9008
8958
  }
9009
- function isMethodFullSegmentAesCbc(method) {
9010
- return method === 'AES-128' || method === 'AES-256';
9011
- }
9012
8959
  var LoadError = /*#__PURE__*/function (_Error) {
9013
8960
  _inheritsLoose(LoadError, _Error);
9014
8961
  function LoadError(data) {
@@ -9022,65 +8969,37 @@
9022
8969
  }( /*#__PURE__*/_wrapNativeSuper(Error));
9023
8970
 
9024
8971
  var AESCrypto = /*#__PURE__*/function () {
9025
- function AESCrypto(subtle, iv, aesMode) {
8972
+ function AESCrypto(subtle, iv) {
9026
8973
  this.subtle = void 0;
9027
8974
  this.aesIV = void 0;
9028
- this.aesMode = void 0;
9029
8975
  this.subtle = subtle;
9030
8976
  this.aesIV = iv;
9031
- this.aesMode = aesMode;
9032
8977
  }
9033
8978
  var _proto = AESCrypto.prototype;
9034
8979
  _proto.decrypt = function decrypt(data, key) {
9035
- switch (this.aesMode) {
9036
- case DecrypterAesMode.cbc:
9037
- return this.subtle.decrypt({
9038
- name: 'AES-CBC',
9039
- iv: this.aesIV
9040
- }, key, data);
9041
- case DecrypterAesMode.ctr:
9042
- return this.subtle.decrypt({
9043
- name: 'AES-CTR',
9044
- counter: this.aesIV,
9045
- length: 64
9046
- },
9047
- //64 : NIST SP800-38A standard suggests that the counter should occupy half of the counter block
9048
- key, data);
9049
- default:
9050
- throw new Error("[AESCrypto] invalid aes mode " + this.aesMode);
9051
- }
8980
+ return this.subtle.decrypt({
8981
+ name: 'AES-CBC',
8982
+ iv: this.aesIV
8983
+ }, key, data);
9052
8984
  };
9053
8985
  return AESCrypto;
9054
8986
  }();
9055
8987
 
9056
8988
  var FastAESKey = /*#__PURE__*/function () {
9057
- function FastAESKey(subtle, key, aesMode) {
8989
+ function FastAESKey(subtle, key) {
9058
8990
  this.subtle = void 0;
9059
8991
  this.key = void 0;
9060
- this.aesMode = void 0;
9061
8992
  this.subtle = subtle;
9062
8993
  this.key = key;
9063
- this.aesMode = aesMode;
9064
8994
  }
9065
8995
  var _proto = FastAESKey.prototype;
9066
8996
  _proto.expandKey = function expandKey() {
9067
- var subtleAlgoName = getSubtleAlgoName(this.aesMode);
9068
8997
  return this.subtle.importKey('raw', this.key, {
9069
- name: subtleAlgoName
8998
+ name: 'AES-CBC'
9070
8999
  }, false, ['encrypt', 'decrypt']);
9071
9000
  };
9072
9001
  return FastAESKey;
9073
9002
  }();
9074
- function getSubtleAlgoName(aesMode) {
9075
- switch (aesMode) {
9076
- case DecrypterAesMode.cbc:
9077
- return 'AES-CBC';
9078
- case DecrypterAesMode.ctr:
9079
- return 'AES-CTR';
9080
- default:
9081
- throw new Error("[FastAESKey] invalid aes mode " + aesMode);
9082
- }
9083
- }
9084
9003
 
9085
9004
  // PKCS7
9086
9005
  function removePadding(array) {
@@ -9333,8 +9252,7 @@
9333
9252
  this.currentIV = null;
9334
9253
  this.currentResult = null;
9335
9254
  this.useSoftware = void 0;
9336
- this.enableSoftwareAES = void 0;
9337
- this.enableSoftwareAES = config.enableSoftwareAES;
9255
+ this.useSoftware = config.enableSoftwareAES;
9338
9256
  this.removePKCS7Padding = removePKCS7Padding;
9339
9257
  // built in decryptor expects PKCS7 padding
9340
9258
  if (removePKCS7Padding) {
@@ -9347,7 +9265,9 @@
9347
9265
  /* no-op */
9348
9266
  }
9349
9267
  }
9350
- this.useSoftware = this.subtle === null;
9268
+ if (this.subtle === null) {
9269
+ this.useSoftware = true;
9270
+ }
9351
9271
  }
9352
9272
  var _proto = Decrypter.prototype;
9353
9273
  _proto.destroy = function destroy() {
@@ -9384,11 +9304,11 @@
9384
9304
  this.softwareDecrypter = null;
9385
9305
  }
9386
9306
  };
9387
- _proto.decrypt = function decrypt(data, key, iv, aesMode) {
9307
+ _proto.decrypt = function decrypt(data, key, iv) {
9388
9308
  var _this = this;
9389
9309
  if (this.useSoftware) {
9390
9310
  return new Promise(function (resolve, reject) {
9391
- _this.softwareDecrypt(new Uint8Array(data), key, iv, aesMode);
9311
+ _this.softwareDecrypt(new Uint8Array(data), key, iv);
9392
9312
  var decryptResult = _this.flush();
9393
9313
  if (decryptResult) {
9394
9314
  resolve(decryptResult.buffer);
@@ -9397,20 +9317,16 @@
9397
9317
  }
9398
9318
  });
9399
9319
  }
9400
- return this.webCryptoDecrypt(new Uint8Array(data), key, iv, aesMode);
9320
+ return this.webCryptoDecrypt(new Uint8Array(data), key, iv);
9401
9321
  }
9402
9322
 
9403
9323
  // Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
9404
9324
  // data is handled in the flush() call
9405
9325
  ;
9406
- _proto.softwareDecrypt = function softwareDecrypt(data, key, iv, aesMode) {
9326
+ _proto.softwareDecrypt = function softwareDecrypt(data, key, iv) {
9407
9327
  var currentIV = this.currentIV,
9408
9328
  currentResult = this.currentResult,
9409
9329
  remainderData = this.remainderData;
9410
- if (aesMode !== DecrypterAesMode.cbc || key.byteLength !== 16) {
9411
- logger.warn('SoftwareDecrypt: can only handle AES-128-CBC');
9412
- return null;
9413
- }
9414
9330
  this.logOnce('JS AES decrypt');
9415
9331
  // The output is staggered during progressive parsing - the current result is cached, and emitted on the next call
9416
9332
  // This is done in order to strip PKCS7 padding, which is found at the end of each segment. We only know we've reached
@@ -9443,12 +9359,12 @@
9443
9359
  }
9444
9360
  return result;
9445
9361
  };
9446
- _proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv, aesMode) {
9362
+ _proto.webCryptoDecrypt = function webCryptoDecrypt(data, key, iv) {
9447
9363
  var _this2 = this;
9448
9364
  var subtle = this.subtle;
9449
9365
  if (this.key !== key || !this.fastAesKey) {
9450
9366
  this.key = key;
9451
- this.fastAesKey = new FastAESKey(subtle, key, aesMode);
9367
+ this.fastAesKey = new FastAESKey(subtle, key);
9452
9368
  }
9453
9369
  return this.fastAesKey.expandKey().then(function (aesKey) {
9454
9370
  // decrypt using web crypto
@@ -9456,25 +9372,22 @@
9456
9372
  return Promise.reject(new Error('web crypto not initialized'));
9457
9373
  }
9458
9374
  _this2.logOnce('WebCrypto AES decrypt');
9459
- var crypto = new AESCrypto(subtle, new Uint8Array(iv), aesMode);
9375
+ var crypto = new AESCrypto(subtle, new Uint8Array(iv));
9460
9376
  return crypto.decrypt(data.buffer, aesKey);
9461
9377
  }).catch(function (err) {
9462
9378
  logger.warn("[decrypter]: WebCrypto Error, disable WebCrypto API, " + err.name + ": " + err.message);
9463
- return _this2.onWebCryptoError(data, key, iv, aesMode);
9379
+ return _this2.onWebCryptoError(data, key, iv);
9464
9380
  });
9465
9381
  };
9466
- _proto.onWebCryptoError = function onWebCryptoError(data, key, iv, aesMode) {
9467
- var enableSoftwareAES = this.enableSoftwareAES;
9468
- if (enableSoftwareAES) {
9469
- this.useSoftware = true;
9470
- this.logEnabled = true;
9471
- this.softwareDecrypt(data, key, iv, aesMode);
9472
- var decryptResult = this.flush();
9473
- if (decryptResult) {
9474
- return decryptResult.buffer;
9475
- }
9382
+ _proto.onWebCryptoError = function onWebCryptoError(data, key, iv) {
9383
+ this.useSoftware = true;
9384
+ this.logEnabled = true;
9385
+ this.softwareDecrypt(data, key, iv);
9386
+ var decryptResult = this.flush();
9387
+ if (decryptResult) {
9388
+ return decryptResult.buffer;
9476
9389
  }
9477
- throw new Error('WebCrypto' + (enableSoftwareAES ? ' and softwareDecrypt' : '') + ': failed to decrypt data');
9390
+ throw new Error('WebCrypto and softwareDecrypt: failed to decrypt data');
9478
9391
  };
9479
9392
  _proto.getValidChunk = function getValidChunk(data) {
9480
9393
  var currentChunk = data;
@@ -9528,7 +9441,7 @@
9528
9441
  _inheritsLoose(BaseStreamController, _TaskLoop);
9529
9442
  function BaseStreamController(hls, fragmentTracker, keyLoader, logPrefix, playlistType) {
9530
9443
  var _this;
9531
- _this = _TaskLoop.call(this, logPrefix, hls.logger) || this;
9444
+ _this = _TaskLoop.call(this) || this;
9532
9445
  _this.hls = void 0;
9533
9446
  _this.fragPrevious = null;
9534
9447
  _this.fragCurrent = null;
@@ -9553,96 +9466,25 @@
9553
9466
  _this.startFragRequested = false;
9554
9467
  _this.decrypter = void 0;
9555
9468
  _this.initPTS = [];
9556
- _this.buffering = true;
9557
- _this.loadingParts = false;
9558
- _this.onMediaSeeking = function () {
9559
- var _assertThisInitialize = _assertThisInitialized(_this),
9560
- config = _assertThisInitialize.config,
9561
- fragCurrent = _assertThisInitialize.fragCurrent,
9562
- media = _assertThisInitialize.media,
9563
- mediaBuffer = _assertThisInitialize.mediaBuffer,
9564
- state = _assertThisInitialize.state;
9565
- var currentTime = media ? media.currentTime : 0;
9566
- var bufferInfo = BufferHelper.bufferInfo(mediaBuffer ? mediaBuffer : media, currentTime, config.maxBufferHole);
9567
- _this.log("media seeking to " + (isFiniteNumber(currentTime) ? currentTime.toFixed(3) : currentTime) + ", state: " + state);
9568
- if (_this.state === State.ENDED) {
9569
- _this.resetLoadingState();
9570
- } else if (fragCurrent) {
9571
- // Seeking while frag load is in progress
9572
- var tolerance = config.maxFragLookUpTolerance;
9573
- var fragStartOffset = fragCurrent.start - tolerance;
9574
- var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance;
9575
- // if seeking out of buffered range or into new one
9576
- if (!bufferInfo.len || fragEndOffset < bufferInfo.start || fragStartOffset > bufferInfo.end) {
9577
- var pastFragment = currentTime > fragEndOffset;
9578
- // if the seek position is outside the current fragment range
9579
- if (currentTime < fragStartOffset || pastFragment) {
9580
- if (pastFragment && fragCurrent.loader) {
9581
- _this.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
9582
- fragCurrent.abortRequests();
9583
- _this.resetLoadingState();
9584
- }
9585
- _this.fragPrevious = null;
9586
- }
9587
- }
9588
- }
9589
- if (media) {
9590
- // Remove gap fragments
9591
- _this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, _this.playlistType, true);
9592
- _this.lastCurrentTime = currentTime;
9593
- if (!_this.loadingParts) {
9594
- var bufferEnd = Math.max(bufferInfo.end, currentTime);
9595
- var shouldLoadParts = _this.shouldLoadParts(_this.getLevelDetails(), bufferEnd);
9596
- if (shouldLoadParts) {
9597
- _this.log("LL-Part loading ON after seeking to " + currentTime.toFixed(2) + " with buffer @" + bufferEnd.toFixed(2));
9598
- _this.loadingParts = shouldLoadParts;
9599
- }
9600
- }
9601
- }
9602
-
9603
- // in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
9604
- if (!_this.loadedmetadata && !bufferInfo.len) {
9605
- _this.nextLoadPosition = _this.startPosition = currentTime;
9606
- }
9607
-
9608
- // Async tick to speed up processing
9609
- _this.tickImmediate();
9610
- };
9611
- _this.onMediaEnded = function () {
9612
- // reset startPosition and lastCurrentTime to restart playback @ stream beginning
9613
- _this.startPosition = _this.lastCurrentTime = 0;
9614
- if (_this.playlistType === PlaylistLevelType.MAIN) {
9615
- _this.hls.trigger(Events.MEDIA_ENDED, {
9616
- stalled: false
9617
- });
9618
- }
9619
- };
9469
+ _this.onvseeking = null;
9470
+ _this.onvended = null;
9471
+ _this.logPrefix = '';
9472
+ _this.log = void 0;
9473
+ _this.warn = void 0;
9620
9474
  _this.playlistType = playlistType;
9475
+ _this.logPrefix = logPrefix;
9476
+ _this.log = logger.log.bind(logger, logPrefix + ":");
9477
+ _this.warn = logger.warn.bind(logger, logPrefix + ":");
9621
9478
  _this.hls = hls;
9622
9479
  _this.fragmentLoader = new FragmentLoader(hls.config);
9623
9480
  _this.keyLoader = keyLoader;
9624
9481
  _this.fragmentTracker = fragmentTracker;
9625
9482
  _this.config = hls.config;
9626
9483
  _this.decrypter = new Decrypter(hls.config);
9484
+ hls.on(Events.MANIFEST_LOADED, _this.onManifestLoaded, _assertThisInitialized(_this));
9627
9485
  return _this;
9628
9486
  }
9629
9487
  var _proto = BaseStreamController.prototype;
9630
- _proto.registerListeners = function registerListeners() {
9631
- var hls = this.hls;
9632
- hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
9633
- hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
9634
- hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
9635
- hls.on(Events.MANIFEST_LOADED, this.onManifestLoaded, this);
9636
- hls.on(Events.ERROR, this.onError, this);
9637
- };
9638
- _proto.unregisterListeners = function unregisterListeners() {
9639
- var hls = this.hls;
9640
- hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
9641
- hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
9642
- hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
9643
- hls.off(Events.MANIFEST_LOADED, this.onManifestLoaded, this);
9644
- hls.off(Events.ERROR, this.onError, this);
9645
- };
9646
9488
  _proto.doTick = function doTick() {
9647
9489
  this.onTickEnd();
9648
9490
  };
@@ -9666,12 +9508,6 @@
9666
9508
  this.clearNextTick();
9667
9509
  this.state = State.STOPPED;
9668
9510
  };
9669
- _proto.pauseBuffering = function pauseBuffering() {
9670
- this.buffering = false;
9671
- };
9672
- _proto.resumeBuffering = function resumeBuffering() {
9673
- this.buffering = true;
9674
- };
9675
9511
  _proto._streamEnded = function _streamEnded(bufferInfo, levelDetails) {
9676
9512
  // If playlist is live, there is another buffered range after the current range, nothing buffered, media is detached,
9677
9513
  // of nothing loading/loaded return false
@@ -9702,8 +9538,10 @@
9702
9538
  };
9703
9539
  _proto.onMediaAttached = function onMediaAttached(event, data) {
9704
9540
  var media = this.media = this.mediaBuffer = data.media;
9705
- media.addEventListener('seeking', this.onMediaSeeking);
9706
- media.addEventListener('ended', this.onMediaEnded);
9541
+ this.onvseeking = this.onMediaSeeking.bind(this);
9542
+ this.onvended = this.onMediaEnded.bind(this);
9543
+ media.addEventListener('seeking', this.onvseeking);
9544
+ media.addEventListener('ended', this.onvended);
9707
9545
  var config = this.config;
9708
9546
  if (this.levels && config.autoStartLoad && this.state === State.STOPPED) {
9709
9547
  this.startLoad(config.startPosition);
@@ -9717,9 +9555,10 @@
9717
9555
  }
9718
9556
 
9719
9557
  // remove video listeners
9720
- if (media) {
9721
- media.removeEventListener('seeking', this.onMediaSeeking);
9722
- media.removeEventListener('ended', this.onMediaEnded);
9558
+ if (media && this.onvseeking && this.onvended) {
9559
+ media.removeEventListener('seeking', this.onvseeking);
9560
+ media.removeEventListener('ended', this.onvended);
9561
+ this.onvseeking = this.onvended = null;
9723
9562
  }
9724
9563
  if (this.keyLoader) {
9725
9564
  this.keyLoader.detach();
@@ -9729,8 +9568,54 @@
9729
9568
  this.fragmentTracker.removeAllFragments();
9730
9569
  this.stopLoad();
9731
9570
  };
9732
- _proto.onManifestLoading = function onManifestLoading() {};
9733
- _proto.onError = function onError(event, data) {};
9571
+ _proto.onMediaSeeking = function onMediaSeeking() {
9572
+ var config = this.config,
9573
+ fragCurrent = this.fragCurrent,
9574
+ media = this.media,
9575
+ mediaBuffer = this.mediaBuffer,
9576
+ state = this.state;
9577
+ var currentTime = media ? media.currentTime : 0;
9578
+ var bufferInfo = BufferHelper.bufferInfo(mediaBuffer ? mediaBuffer : media, currentTime, config.maxBufferHole);
9579
+ this.log("media seeking to " + (isFiniteNumber(currentTime) ? currentTime.toFixed(3) : currentTime) + ", state: " + state);
9580
+ if (this.state === State.ENDED) {
9581
+ this.resetLoadingState();
9582
+ } else if (fragCurrent) {
9583
+ // Seeking while frag load is in progress
9584
+ var tolerance = config.maxFragLookUpTolerance;
9585
+ var fragStartOffset = fragCurrent.start - tolerance;
9586
+ var fragEndOffset = fragCurrent.start + fragCurrent.duration + tolerance;
9587
+ // if seeking out of buffered range or into new one
9588
+ if (!bufferInfo.len || fragEndOffset < bufferInfo.start || fragStartOffset > bufferInfo.end) {
9589
+ var pastFragment = currentTime > fragEndOffset;
9590
+ // if the seek position is outside the current fragment range
9591
+ if (currentTime < fragStartOffset || pastFragment) {
9592
+ if (pastFragment && fragCurrent.loader) {
9593
+ this.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
9594
+ fragCurrent.abortRequests();
9595
+ this.resetLoadingState();
9596
+ }
9597
+ this.fragPrevious = null;
9598
+ }
9599
+ }
9600
+ }
9601
+ if (media) {
9602
+ // Remove gap fragments
9603
+ this.fragmentTracker.removeFragmentsInRange(currentTime, Infinity, this.playlistType, true);
9604
+ this.lastCurrentTime = currentTime;
9605
+ }
9606
+
9607
+ // in case seeking occurs although no media buffered, adjust startPosition and nextLoadPosition to seek target
9608
+ if (!this.loadedmetadata && !bufferInfo.len) {
9609
+ this.nextLoadPosition = this.startPosition = currentTime;
9610
+ }
9611
+
9612
+ // Async tick to speed up processing
9613
+ this.tickImmediate();
9614
+ };
9615
+ _proto.onMediaEnded = function onMediaEnded() {
9616
+ // reset startPosition and lastCurrentTime to restart playback @ stream beginning
9617
+ this.startPosition = this.lastCurrentTime = 0;
9618
+ };
9734
9619
  _proto.onManifestLoaded = function onManifestLoaded(event, data) {
9735
9620
  this.startTimeOffset = data.startTimeOffset;
9736
9621
  this.initPTS = [];
@@ -9740,7 +9625,7 @@
9740
9625
  this.stopLoad();
9741
9626
  _TaskLoop.prototype.onHandlerDestroying.call(this);
9742
9627
  // @ts-ignore
9743
- this.hls = this.onMediaSeeking = this.onMediaEnded = null;
9628
+ this.hls = null;
9744
9629
  };
9745
9630
  _proto.onHandlerDestroyed = function onHandlerDestroyed() {
9746
9631
  this.state = State.STOPPED;
@@ -9870,10 +9755,10 @@
9870
9755
  var decryptData = frag.decryptdata;
9871
9756
 
9872
9757
  // check to see if the payload needs to be decrypted
9873
- if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && isFullSegmentEncryption(decryptData.method)) {
9758
+ if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && decryptData.method === 'AES-128') {
9874
9759
  var startTime = self.performance.now();
9875
9760
  // decrypt init segment data
9876
- return _this3.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer, getAesModeFromFullSegmentMethod(decryptData.method)).catch(function (err) {
9761
+ return _this3.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).catch(function (err) {
9877
9762
  hls.trigger(Events.ERROR, {
9878
9763
  type: ErrorTypes.MEDIA_ERROR,
9879
9764
  details: ErrorDetails.FRAG_DECRYPT_ERROR,
@@ -9986,7 +9871,7 @@
9986
9871
  }
9987
9872
  var keyLoadingPromise = null;
9988
9873
  if (frag.encrypted && !((_frag$decryptdata = frag.decryptdata) != null && _frag$decryptdata.key)) {
9989
- this.log("Loading key for " + frag.sn + " of [" + details.startSN + "-" + details.endSN + "], " + (this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track') + " " + frag.level);
9874
+ this.log("Loading key for " + frag.sn + " of [" + details.startSN + "-" + details.endSN + "], " + (this.logPrefix === '[stream-controller]' ? 'level' : 'track') + " " + frag.level);
9990
9875
  this.state = State.KEY_LOADING;
9991
9876
  this.fragCurrent = frag;
9992
9877
  keyLoadingPromise = this.keyLoader.load(frag).then(function (keyLoadedData) {
@@ -10007,16 +9892,8 @@
10007
9892
  } else if (!frag.encrypted && details.encryptedFragments.length) {
10008
9893
  this.keyLoader.loadClear(frag, details.encryptedFragments);
10009
9894
  }
10010
- var fragPrevious = this.fragPrevious;
10011
- if (frag.sn !== 'initSegment' && (!fragPrevious || frag.sn !== fragPrevious.sn)) {
10012
- var shouldLoadParts = this.shouldLoadParts(level.details, frag.end);
10013
- if (shouldLoadParts !== this.loadingParts) {
10014
- this.log("LL-Part loading " + (shouldLoadParts ? 'ON' : 'OFF') + " loading sn " + (fragPrevious == null ? void 0 : fragPrevious.sn) + "->" + frag.sn);
10015
- this.loadingParts = shouldLoadParts;
10016
- }
10017
- }
10018
9895
  targetBufferTime = Math.max(frag.start, targetBufferTime || 0);
10019
- if (this.loadingParts && frag.sn !== 'initSegment') {
9896
+ if (this.config.lowLatencyMode && frag.sn !== 'initSegment') {
10020
9897
  var partList = details.partList;
10021
9898
  if (partList && progressCallback) {
10022
9899
  if (targetBufferTime > frag.end && details.fragmentHint) {
@@ -10025,7 +9902,7 @@
10025
9902
  var partIndex = this.getNextPart(partList, frag, targetBufferTime);
10026
9903
  if (partIndex > -1) {
10027
9904
  var part = partList[partIndex];
10028
- 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)));
9905
+ this.log("Loading part sn: " + frag.sn + " p: " + part.index + " cc: " + frag.cc + " of playlist [" + details.startSN + "-" + details.endSN + "] parts [0-" + partIndex + "-" + (partList.length - 1) + "] " + (this.logPrefix === '[stream-controller]' ? 'level' : 'track') + ": " + frag.level + ", target: " + parseFloat(targetBufferTime.toFixed(3)));
10029
9906
  this.nextLoadPosition = part.start + part.duration;
10030
9907
  this.state = State.FRAG_LOADING;
10031
9908
  var _result;
@@ -10058,14 +9935,7 @@
10058
9935
  }
10059
9936
  }
10060
9937
  }
10061
- if (frag.sn !== 'initSegment' && this.loadingParts) {
10062
- this.log("LL-Part loading OFF after next part miss @" + targetBufferTime.toFixed(2));
10063
- this.loadingParts = false;
10064
- } else if (!frag.url) {
10065
- // Selected fragment hint for part but not loading parts
10066
- return Promise.resolve(null);
10067
- }
10068
- 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)));
9938
+ this.log("Loading fragment " + frag.sn + " cc: " + frag.cc + " " + (details ? 'of [' + details.startSN + '-' + details.endSN + '] ' : '') + (this.logPrefix === '[stream-controller]' ? 'level' : 'track') + ": " + frag.level + ", target: " + parseFloat(targetBufferTime.toFixed(3)));
10069
9939
  // Don't update nextLoadPosition for fragments which are not buffered
10070
9940
  if (isFiniteNumber(frag.sn) && !this.bitrateTest) {
10071
9941
  this.nextLoadPosition = frag.start + frag.duration;
@@ -10167,36 +10037,8 @@
10167
10037
  if (part) {
10168
10038
  part.stats.parsing.end = now;
10169
10039
  }
10170
- // See if part loading should be disabled/enabled based on buffer and playback position.
10171
- if (frag.sn !== 'initSegment') {
10172
- var levelDetails = this.getLevelDetails();
10173
- var loadingPartsAtEdge = levelDetails && frag.sn > levelDetails.endSN;
10174
- var shouldLoadParts = loadingPartsAtEdge || this.shouldLoadParts(levelDetails, frag.end);
10175
- if (shouldLoadParts !== this.loadingParts) {
10176
- this.log("LL-Part loading " + (shouldLoadParts ? 'ON' : 'OFF') + " after parsing segment ending @" + frag.end.toFixed(2));
10177
- this.loadingParts = shouldLoadParts;
10178
- }
10179
- }
10180
10040
  this.updateLevelTiming(frag, part, level, chunkMeta.partial);
10181
10041
  };
10182
- _proto.shouldLoadParts = function shouldLoadParts(details, bufferEnd) {
10183
- if (this.config.lowLatencyMode) {
10184
- if (!details) {
10185
- return this.loadingParts;
10186
- }
10187
- if (details != null && details.partList) {
10188
- var _details$fragmentHint;
10189
- // Buffer must be ahead of first part + duration of parts after last segment
10190
- // and playback must be at or past segment adjacent to part list
10191
- var firstPart = details.partList[0];
10192
- var safePartStart = firstPart.end + (((_details$fragmentHint = details.fragmentHint) == null ? void 0 : _details$fragmentHint.duration) || 0);
10193
- if (bufferEnd >= safePartStart && this.lastCurrentTime > firstPart.start - firstPart.fragment.duration) {
10194
- return true;
10195
- }
10196
- }
10197
- }
10198
- return false;
10199
- };
10200
10042
  _proto.getCurrentContext = function getCurrentContext(chunkMeta) {
10201
10043
  var levels = this.levels,
10202
10044
  fragCurrent = this.fragCurrent;
@@ -10331,8 +10173,7 @@
10331
10173
  // find fragment index, contiguous with end of buffer position
10332
10174
  var config = this.config;
10333
10175
  var start = fragments[0].start;
10334
- var canLoadParts = config.lowLatencyMode && !!levelDetails.partList;
10335
- var frag = null;
10176
+ var frag;
10336
10177
  if (levelDetails.live) {
10337
10178
  var initialLiveManifestSize = config.initialLiveManifestSize;
10338
10179
  if (fragLen < initialLiveManifestSize) {
@@ -10344,10 +10185,6 @@
10344
10185
  // Do not load using live logic if the starting frag is requested - we want to use getFragmentAtPosition() so that
10345
10186
  // we get the fragment matching that start time
10346
10187
  if (!levelDetails.PTSKnown && !this.startFragRequested && this.startPosition === -1 || pos < start) {
10347
- if (canLoadParts && !this.loadingParts) {
10348
- this.log("LL-Part loading ON for initial live fragment");
10349
- this.loadingParts = true;
10350
- }
10351
10188
  frag = this.getInitialLiveFragment(levelDetails, fragments);
10352
10189
  this.startPosition = this.nextLoadPosition = frag ? this.hls.liveSyncPosition || frag.start : pos;
10353
10190
  }
@@ -10358,7 +10195,7 @@
10358
10195
 
10359
10196
  // If we haven't run into any special cases already, just load the fragment most closely matching the requested position
10360
10197
  if (!frag) {
10361
- var end = this.loadingParts ? levelDetails.partEnd : levelDetails.fragmentEnd;
10198
+ var end = config.lowLatencyMode ? levelDetails.partEnd : levelDetails.fragmentEnd;
10362
10199
  frag = this.getFragmentAtPosition(pos, end, levelDetails);
10363
10200
  }
10364
10201
  return this.mapToInitFragWhenRequired(frag);
@@ -10472,7 +10309,7 @@
10472
10309
  var fragmentHint = levelDetails.fragmentHint;
10473
10310
  var tolerance = config.maxFragLookUpTolerance;
10474
10311
  var partList = levelDetails.partList;
10475
- var loadingParts = !!(this.loadingParts && partList != null && partList.length && fragmentHint);
10312
+ var loadingParts = !!(config.lowLatencyMode && partList != null && partList.length && fragmentHint);
10476
10313
  if (loadingParts && fragmentHint && !this.bitrateTest) {
10477
10314
  // Include incomplete fragment with parts at end
10478
10315
  fragments = fragments.concat(fragmentHint);
@@ -10659,7 +10496,7 @@
10659
10496
  errorAction.resolved = true;
10660
10497
  }
10661
10498
  } else {
10662
- this.warn(data.details + " reached or exceeded max retry (" + retryCount + ")");
10499
+ logger.warn(data.details + " reached or exceeded max retry (" + retryCount + ")");
10663
10500
  return;
10664
10501
  }
10665
10502
  } else if ((errorAction == null ? void 0 : errorAction.action) === NetworkErrorAction.SendAlternateToPenaltyBox) {
@@ -11059,7 +10896,6 @@
11059
10896
  */
11060
10897
  function getAudioConfig(observer, data, offset, audioCodec) {
11061
10898
  var adtsObjectType;
11062
- var originalAdtsObjectType;
11063
10899
  var adtsExtensionSamplingIndex;
11064
10900
  var adtsChannelConfig;
11065
10901
  var config;
@@ -11067,7 +10903,7 @@
11067
10903
  var manifestCodec = audioCodec;
11068
10904
  var adtsSamplingRates = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];
11069
10905
  // byte 2
11070
- adtsObjectType = originalAdtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1;
10906
+ adtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1;
11071
10907
  var adtsSamplingIndex = (data[offset + 2] & 0x3c) >>> 2;
11072
10908
  if (adtsSamplingIndex > adtsSamplingRates.length - 1) {
11073
10909
  var error = new Error("invalid ADTS sampling index:" + adtsSamplingIndex);
@@ -11084,8 +10920,8 @@
11084
10920
  // byte 3
11085
10921
  adtsChannelConfig |= (data[offset + 3] & 0xc0) >>> 6;
11086
10922
  logger.log("manifest codec:" + audioCodec + ", ADTS type:" + adtsObjectType + ", samplingIndex:" + adtsSamplingIndex);
11087
- // Firefox and Pale Moon: freq less than 24kHz = AAC SBR (HE-AAC)
11088
- if (/firefox|palemoon/i.test(userAgent)) {
10923
+ // firefox: freq less than 24kHz = AAC SBR (HE-AAC)
10924
+ if (/firefox/i.test(userAgent)) {
11089
10925
  if (adtsSamplingIndex >= 6) {
11090
10926
  adtsObjectType = 5;
11091
10927
  config = new Array(4);
@@ -11179,7 +11015,6 @@
11179
11015
  samplerate: adtsSamplingRates[adtsSamplingIndex],
11180
11016
  channelCount: adtsChannelConfig,
11181
11017
  codec: 'mp4a.40.' + adtsObjectType,
11182
- parsedCodec: 'mp4a.40.' + originalAdtsObjectType,
11183
11018
  manifestCodec: manifestCodec
11184
11019
  };
11185
11020
  }
@@ -11234,8 +11069,7 @@
11234
11069
  track.channelCount = config.channelCount;
11235
11070
  track.codec = config.codec;
11236
11071
  track.manifestCodec = config.manifestCodec;
11237
- track.parsedCodec = config.parsedCodec;
11238
- logger.log("parsed codec:" + track.parsedCodec + ", codec:" + track.codec + ", rate:" + config.samplerate + ", channels:" + config.channelCount);
11072
+ logger.log("parsed codec:" + track.codec + ", rate:" + config.samplerate + ", channels:" + config.channelCount);
11239
11073
  }
11240
11074
  }
11241
11075
  function getFrameDuration(samplerate) {
@@ -11833,110 +11667,6 @@
11833
11667
  logger.log(VideoSample.pts + '/' + VideoSample.dts + ':' + VideoSample.debug);
11834
11668
  }
11835
11669
  };
11836
- _proto.parseNALu = function parseNALu(track, array) {
11837
- var len = array.byteLength;
11838
- var state = track.naluState || 0;
11839
- var lastState = state;
11840
- var units = [];
11841
- var i = 0;
11842
- var value;
11843
- var overflow;
11844
- var unitType;
11845
- var lastUnitStart = -1;
11846
- var lastUnitType = 0;
11847
- // logger.log('PES:' + Hex.hexDump(array));
11848
-
11849
- if (state === -1) {
11850
- // special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet
11851
- lastUnitStart = 0;
11852
- // NALu type is value read from offset 0
11853
- lastUnitType = this.getNALuType(array, 0);
11854
- state = 0;
11855
- i = 1;
11856
- }
11857
- while (i < len) {
11858
- value = array[i++];
11859
- // optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case
11860
- if (!state) {
11861
- state = value ? 0 : 1;
11862
- continue;
11863
- }
11864
- if (state === 1) {
11865
- state = value ? 0 : 2;
11866
- continue;
11867
- }
11868
- // here we have state either equal to 2 or 3
11869
- if (!value) {
11870
- state = 3;
11871
- } else if (value === 1) {
11872
- overflow = i - state - 1;
11873
- if (lastUnitStart >= 0) {
11874
- var unit = {
11875
- data: array.subarray(lastUnitStart, overflow),
11876
- type: lastUnitType
11877
- };
11878
- // logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);
11879
- units.push(unit);
11880
- } else {
11881
- // lastUnitStart is undefined => this is the first start code found in this PES packet
11882
- // first check if start code delimiter is overlapping between 2 PES packets,
11883
- // ie it started in last packet (lastState not zero)
11884
- // and ended at the beginning of this PES packet (i <= 4 - lastState)
11885
- var lastUnit = this.getLastNalUnit(track.samples);
11886
- if (lastUnit) {
11887
- if (lastState && i <= 4 - lastState) {
11888
- // start delimiter overlapping between PES packets
11889
- // strip start delimiter bytes from the end of last NAL unit
11890
- // check if lastUnit had a state different from zero
11891
- if (lastUnit.state) {
11892
- // strip last bytes
11893
- lastUnit.data = lastUnit.data.subarray(0, lastUnit.data.byteLength - lastState);
11894
- }
11895
- }
11896
- // If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.
11897
-
11898
- if (overflow > 0) {
11899
- // logger.log('first NALU found with overflow:' + overflow);
11900
- lastUnit.data = appendUint8Array(lastUnit.data, array.subarray(0, overflow));
11901
- lastUnit.state = 0;
11902
- }
11903
- }
11904
- }
11905
- // check if we can read unit type
11906
- if (i < len) {
11907
- unitType = this.getNALuType(array, i);
11908
- // logger.log('find NALU @ offset:' + i + ',type:' + unitType);
11909
- lastUnitStart = i;
11910
- lastUnitType = unitType;
11911
- state = 0;
11912
- } else {
11913
- // not enough byte to read unit type. let's read it on next PES parsing
11914
- state = -1;
11915
- }
11916
- } else {
11917
- state = 0;
11918
- }
11919
- }
11920
- if (lastUnitStart >= 0 && state >= 0) {
11921
- var _unit = {
11922
- data: array.subarray(lastUnitStart, len),
11923
- type: lastUnitType,
11924
- state: state
11925
- };
11926
- units.push(_unit);
11927
- // logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
11928
- }
11929
- // no NALu found
11930
- if (units.length === 0) {
11931
- // append pes.data to previous NAL unit
11932
- var _lastUnit = this.getLastNalUnit(track.samples);
11933
- if (_lastUnit) {
11934
- _lastUnit.data = appendUint8Array(_lastUnit.data, array);
11935
- }
11936
- }
11937
- track.naluState = state;
11938
- return units;
11939
- };
11940
11670
  return BaseVideoParser;
11941
11671
  }();
11942
11672
 
@@ -12091,236 +11821,78 @@
12091
11821
  ;
12092
11822
  _proto.readUInt = function readUInt() {
12093
11823
  return this.readBits(32);
12094
- };
12095
- return ExpGolomb;
12096
- }();
12097
-
12098
- var AvcVideoParser = /*#__PURE__*/function (_BaseVideoParser) {
12099
- _inheritsLoose(AvcVideoParser, _BaseVideoParser);
12100
- function AvcVideoParser() {
12101
- return _BaseVideoParser.apply(this, arguments) || this;
12102
11824
  }
12103
- var _proto = AvcVideoParser.prototype;
12104
- _proto.parsePES = function parsePES(track, textTrack, pes, last, duration) {
12105
- var _this = this;
12106
- var units = this.parseNALu(track, pes.data);
12107
- var VideoSample = this.VideoSample;
12108
- var push;
12109
- var spsfound = false;
12110
- // free pes.data to save up some memory
12111
- pes.data = null;
12112
11825
 
12113
- // if new NAL units found and last sample still there, let's push ...
12114
- // this helps parsing streams with missing AUD (only do this if AUD never found)
12115
- if (VideoSample && units.length && !track.audFound) {
12116
- this.pushAccessUnit(VideoSample, track);
12117
- VideoSample = this.VideoSample = this.createVideoSample(false, pes.pts, pes.dts, '');
11826
+ /**
11827
+ * Advance the ExpGolomb decoder past a scaling list. The scaling
11828
+ * list is optionally transmitted as part of a sequence parameter
11829
+ * set and is not relevant to transmuxing.
11830
+ * @param count the number of entries in this scaling list
11831
+ * @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
11832
+ */;
11833
+ _proto.skipScalingList = function skipScalingList(count) {
11834
+ var lastScale = 8;
11835
+ var nextScale = 8;
11836
+ var deltaScale;
11837
+ for (var j = 0; j < count; j++) {
11838
+ if (nextScale !== 0) {
11839
+ deltaScale = this.readEG();
11840
+ nextScale = (lastScale + deltaScale + 256) % 256;
11841
+ }
11842
+ lastScale = nextScale === 0 ? lastScale : nextScale;
12118
11843
  }
12119
- units.forEach(function (unit) {
12120
- var _VideoSample2;
12121
- switch (unit.type) {
12122
- // NDR
12123
- case 1:
12124
- {
12125
- var iskey = false;
12126
- push = true;
12127
- var data = unit.data;
12128
- // only check slice type to detect KF in case SPS found in same packet (any keyframe is preceded by SPS ...)
12129
- if (spsfound && data.length > 4) {
12130
- // retrieve slice type by parsing beginning of NAL unit (follow H264 spec, slice_header definition) to detect keyframe embedded in NDR
12131
- var sliceType = _this.readSliceType(data);
12132
- // 2 : I slice, 4 : SI slice, 7 : I slice, 9: SI slice
12133
- // SI slice : A slice that is coded using intra prediction only and using quantisation of the prediction samples.
12134
- // An SI slice can be coded such that its decoded samples can be constructed identically to an SP slice.
12135
- // I slice: A slice that is not an SI slice that is decoded using intra prediction only.
12136
- // if (sliceType === 2 || sliceType === 7) {
12137
- if (sliceType === 2 || sliceType === 4 || sliceType === 7 || sliceType === 9) {
12138
- iskey = true;
12139
- }
12140
- }
12141
- if (iskey) {
12142
- var _VideoSample;
12143
- // if we have non-keyframe data already, that cannot belong to the same frame as a keyframe, so force a push
12144
- if ((_VideoSample = VideoSample) != null && _VideoSample.frame && !VideoSample.key) {
12145
- _this.pushAccessUnit(VideoSample, track);
12146
- VideoSample = _this.VideoSample = null;
12147
- }
12148
- }
12149
- if (!VideoSample) {
12150
- VideoSample = _this.VideoSample = _this.createVideoSample(true, pes.pts, pes.dts, '');
12151
- }
12152
- VideoSample.frame = true;
12153
- VideoSample.key = iskey;
12154
- break;
12155
- // IDR
12156
- }
12157
- case 5:
12158
- push = true;
12159
- // handle PES not starting with AUD
12160
- // if we have frame data already, that cannot belong to the same frame, so force a push
12161
- if ((_VideoSample2 = VideoSample) != null && _VideoSample2.frame && !VideoSample.key) {
12162
- _this.pushAccessUnit(VideoSample, track);
12163
- VideoSample = _this.VideoSample = null;
12164
- }
12165
- if (!VideoSample) {
12166
- VideoSample = _this.VideoSample = _this.createVideoSample(true, pes.pts, pes.dts, '');
12167
- }
12168
- VideoSample.key = true;
12169
- VideoSample.frame = true;
12170
- break;
12171
- // SEI
12172
- case 6:
12173
- {
12174
- push = true;
12175
- parseSEIMessageFromNALu(unit.data, 1, pes.pts, textTrack.samples);
12176
- break;
12177
- // SPS
12178
- }
12179
- case 7:
12180
- {
12181
- var _track$pixelRatio, _track$pixelRatio2;
12182
- push = true;
12183
- spsfound = true;
12184
- var sps = unit.data;
12185
- var config = _this.readSPS(sps);
12186
- 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]) {
12187
- track.width = config.width;
12188
- track.height = config.height;
12189
- track.pixelRatio = config.pixelRatio;
12190
- track.sps = [sps];
12191
- track.duration = duration;
12192
- var codecarray = sps.subarray(1, 4);
12193
- var codecstring = 'avc1.';
12194
- for (var i = 0; i < 3; i++) {
12195
- var h = codecarray[i].toString(16);
12196
- if (h.length < 2) {
12197
- h = '0' + h;
12198
- }
12199
- codecstring += h;
12200
- }
12201
- track.codec = codecstring;
12202
- }
12203
- break;
12204
- }
12205
- // PPS
12206
- case 8:
12207
- push = true;
12208
- track.pps = [unit.data];
12209
- break;
12210
- // AUD
12211
- case 9:
12212
- push = true;
12213
- track.audFound = true;
12214
- if (VideoSample) {
12215
- _this.pushAccessUnit(VideoSample, track);
12216
- }
12217
- VideoSample = _this.VideoSample = _this.createVideoSample(false, pes.pts, pes.dts, '');
12218
- break;
12219
- // Filler Data
12220
- case 12:
12221
- push = true;
12222
- break;
12223
- default:
12224
- push = false;
12225
- if (VideoSample) {
12226
- VideoSample.debug += 'unknown NAL ' + unit.type + ' ';
12227
- }
12228
- break;
12229
- }
12230
- if (VideoSample && push) {
12231
- var _units = VideoSample.units;
12232
- _units.push(unit);
12233
- }
12234
- });
12235
- // if last PES packet, push samples
12236
- if (last && VideoSample) {
12237
- this.pushAccessUnit(VideoSample, track);
12238
- this.VideoSample = null;
12239
- }
12240
- };
12241
- _proto.getNALuType = function getNALuType(data, offset) {
12242
- return data[offset] & 0x1f;
12243
- };
12244
- _proto.readSliceType = function readSliceType(data) {
12245
- var eg = new ExpGolomb(data);
12246
- // skip NALu type
12247
- eg.readUByte();
12248
- // discard first_mb_in_slice
12249
- eg.readUEG();
12250
- // return slice_type
12251
- return eg.readUEG();
12252
- }
12253
-
12254
- /**
12255
- * The scaling list is optionally transmitted as part of a sequence parameter
12256
- * set and is not relevant to transmuxing.
12257
- * @param count the number of entries in this scaling list
12258
- * @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
12259
- */;
12260
- _proto.skipScalingList = function skipScalingList(count, reader) {
12261
- var lastScale = 8;
12262
- var nextScale = 8;
12263
- var deltaScale;
12264
- for (var j = 0; j < count; j++) {
12265
- if (nextScale !== 0) {
12266
- deltaScale = reader.readEG();
12267
- nextScale = (lastScale + deltaScale + 256) % 256;
12268
- }
12269
- lastScale = nextScale === 0 ? lastScale : nextScale;
12270
- }
12271
- }
12272
-
12273
- /**
12274
- * Read a sequence parameter set and return some interesting video
12275
- * properties. A sequence parameter set is the H264 metadata that
12276
- * describes the properties of upcoming video frames.
12277
- * @returns an object with configuration parsed from the
12278
- * sequence parameter set, including the dimensions of the
12279
- * associated video frames.
12280
- */;
12281
- _proto.readSPS = function readSPS(sps) {
12282
- var eg = new ExpGolomb(sps);
12283
- var frameCropLeftOffset = 0;
12284
- var frameCropRightOffset = 0;
12285
- var frameCropTopOffset = 0;
12286
- var frameCropBottomOffset = 0;
12287
- var numRefFramesInPicOrderCntCycle;
12288
- var scalingListCount;
12289
- var i;
12290
- var readUByte = eg.readUByte.bind(eg);
12291
- var readBits = eg.readBits.bind(eg);
12292
- var readUEG = eg.readUEG.bind(eg);
12293
- var readBoolean = eg.readBoolean.bind(eg);
12294
- var skipBits = eg.skipBits.bind(eg);
12295
- var skipEG = eg.skipEG.bind(eg);
12296
- var skipUEG = eg.skipUEG.bind(eg);
12297
- var skipScalingList = this.skipScalingList.bind(this);
12298
- readUByte();
12299
- var profileIdc = readUByte(); // profile_idc
12300
- readBits(5); // profileCompat constraint_set[0-4]_flag, u(5)
12301
- skipBits(3); // reserved_zero_3bits u(3),
12302
- readUByte(); // level_idc u(8)
12303
- skipUEG(); // seq_parameter_set_id
12304
- // some profiles have more optional data we don't need
12305
- if (profileIdc === 100 || profileIdc === 110 || profileIdc === 122 || profileIdc === 244 || profileIdc === 44 || profileIdc === 83 || profileIdc === 86 || profileIdc === 118 || profileIdc === 128) {
12306
- var chromaFormatIdc = readUEG();
12307
- if (chromaFormatIdc === 3) {
12308
- skipBits(1);
12309
- } // separate_colour_plane_flag
12310
-
12311
- skipUEG(); // bit_depth_luma_minus8
12312
- skipUEG(); // bit_depth_chroma_minus8
12313
- skipBits(1); // qpprime_y_zero_transform_bypass_flag
12314
- if (readBoolean()) {
12315
- // seq_scaling_matrix_present_flag
12316
- scalingListCount = chromaFormatIdc !== 3 ? 8 : 12;
12317
- for (i = 0; i < scalingListCount; i++) {
12318
- if (readBoolean()) {
12319
- // seq_scaling_list_present_flag[ i ]
12320
- if (i < 6) {
12321
- skipScalingList(16, eg);
12322
- } else {
12323
- skipScalingList(64, eg);
11844
+ }
11845
+
11846
+ /**
11847
+ * Read a sequence parameter set and return some interesting video
11848
+ * properties. A sequence parameter set is the H264 metadata that
11849
+ * describes the properties of upcoming video frames.
11850
+ * @returns an object with configuration parsed from the
11851
+ * sequence parameter set, including the dimensions of the
11852
+ * associated video frames.
11853
+ */;
11854
+ _proto.readSPS = function readSPS() {
11855
+ var frameCropLeftOffset = 0;
11856
+ var frameCropRightOffset = 0;
11857
+ var frameCropTopOffset = 0;
11858
+ var frameCropBottomOffset = 0;
11859
+ var numRefFramesInPicOrderCntCycle;
11860
+ var scalingListCount;
11861
+ var i;
11862
+ var readUByte = this.readUByte.bind(this);
11863
+ var readBits = this.readBits.bind(this);
11864
+ var readUEG = this.readUEG.bind(this);
11865
+ var readBoolean = this.readBoolean.bind(this);
11866
+ var skipBits = this.skipBits.bind(this);
11867
+ var skipEG = this.skipEG.bind(this);
11868
+ var skipUEG = this.skipUEG.bind(this);
11869
+ var skipScalingList = this.skipScalingList.bind(this);
11870
+ readUByte();
11871
+ var profileIdc = readUByte(); // profile_idc
11872
+ readBits(5); // profileCompat constraint_set[0-4]_flag, u(5)
11873
+ skipBits(3); // reserved_zero_3bits u(3),
11874
+ readUByte(); // level_idc u(8)
11875
+ skipUEG(); // seq_parameter_set_id
11876
+ // some profiles have more optional data we don't need
11877
+ if (profileIdc === 100 || profileIdc === 110 || profileIdc === 122 || profileIdc === 244 || profileIdc === 44 || profileIdc === 83 || profileIdc === 86 || profileIdc === 118 || profileIdc === 128) {
11878
+ var chromaFormatIdc = readUEG();
11879
+ if (chromaFormatIdc === 3) {
11880
+ skipBits(1);
11881
+ } // separate_colour_plane_flag
11882
+
11883
+ skipUEG(); // bit_depth_luma_minus8
11884
+ skipUEG(); // bit_depth_chroma_minus8
11885
+ skipBits(1); // qpprime_y_zero_transform_bypass_flag
11886
+ if (readBoolean()) {
11887
+ // seq_scaling_matrix_present_flag
11888
+ scalingListCount = chromaFormatIdc !== 3 ? 8 : 12;
11889
+ for (i = 0; i < scalingListCount; i++) {
11890
+ if (readBoolean()) {
11891
+ // seq_scaling_list_present_flag[ i ]
11892
+ if (i < 6) {
11893
+ skipScalingList(16);
11894
+ } else {
11895
+ skipScalingList(64);
12324
11896
  }
12325
11897
  }
12326
11898
  }
@@ -12425,24 +11997,26 @@
12425
11997
  pixelRatio: pixelRatio
12426
11998
  };
12427
11999
  };
12428
- return AvcVideoParser;
12429
- }(BaseVideoParser);
12000
+ _proto.readSliceType = function readSliceType() {
12001
+ // skip NALu type
12002
+ this.readUByte();
12003
+ // discard first_mb_in_slice
12004
+ this.readUEG();
12005
+ // return slice_type
12006
+ return this.readUEG();
12007
+ };
12008
+ return ExpGolomb;
12009
+ }();
12430
12010
 
12431
- var HevcVideoParser = /*#__PURE__*/function (_BaseVideoParser) {
12432
- _inheritsLoose(HevcVideoParser, _BaseVideoParser);
12433
- function HevcVideoParser() {
12434
- var _this;
12435
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
12436
- args[_key] = arguments[_key];
12437
- }
12438
- _this = _BaseVideoParser.call.apply(_BaseVideoParser, [this].concat(args)) || this;
12439
- _this.initVPS = null;
12440
- return _this;
12011
+ var AvcVideoParser = /*#__PURE__*/function (_BaseVideoParser) {
12012
+ _inheritsLoose(AvcVideoParser, _BaseVideoParser);
12013
+ function AvcVideoParser() {
12014
+ return _BaseVideoParser.apply(this, arguments) || this;
12441
12015
  }
12442
- var _proto = HevcVideoParser.prototype;
12443
- _proto.parsePES = function parsePES(track, textTrack, pes, last, duration) {
12444
- var _this2 = this;
12445
- var units = this.parseNALu(track, pes.data);
12016
+ var _proto = AvcVideoParser.prototype;
12017
+ _proto.parseAVCPES = function parseAVCPES(track, textTrack, pes, last, duration) {
12018
+ var _this = this;
12019
+ var units = this.parseAVCNALu(track, pes.data);
12446
12020
  var VideoSample = this.VideoSample;
12447
12021
  var push;
12448
12022
  var spsfound = false;
@@ -12458,143 +12032,112 @@
12458
12032
  units.forEach(function (unit) {
12459
12033
  var _VideoSample2;
12460
12034
  switch (unit.type) {
12461
- // NON-IDR, NON RANDOM ACCESS SLICE
12462
- case 0:
12035
+ // NDR
12463
12036
  case 1:
12464
- case 2:
12465
- case 3:
12466
- case 4:
12467
- case 5:
12468
- case 6:
12469
- case 7:
12470
- case 8:
12471
- case 9:
12472
- if (!VideoSample) {
12473
- VideoSample = _this2.VideoSample = _this2.createVideoSample(false, pes.pts, pes.dts, '');
12474
- }
12475
- VideoSample.frame = true;
12476
- push = true;
12477
- break;
12478
-
12479
- // CRA, BLA (random access picture)
12480
- case 16:
12481
- case 17:
12482
- case 18:
12483
- case 21:
12484
- push = true;
12485
- if (spsfound) {
12486
- var _VideoSample;
12487
- // handle PES not starting with AUD
12488
- // if we have frame data already, that cannot belong to the same frame, so force a push
12489
- if ((_VideoSample = VideoSample) != null && _VideoSample.frame && !VideoSample.key) {
12490
- _this2.pushAccessUnit(VideoSample, track);
12491
- VideoSample = _this2.VideoSample = null;
12037
+ {
12038
+ var iskey = false;
12039
+ push = true;
12040
+ var data = unit.data;
12041
+ // only check slice type to detect KF in case SPS found in same packet (any keyframe is preceded by SPS ...)
12042
+ if (spsfound && data.length > 4) {
12043
+ // retrieve slice type by parsing beginning of NAL unit (follow H264 spec, slice_header definition) to detect keyframe embedded in NDR
12044
+ var sliceType = new ExpGolomb(data).readSliceType();
12045
+ // 2 : I slice, 4 : SI slice, 7 : I slice, 9: SI slice
12046
+ // SI slice : A slice that is coded using intra prediction only and using quantisation of the prediction samples.
12047
+ // An SI slice can be coded such that its decoded samples can be constructed identically to an SP slice.
12048
+ // I slice: A slice that is not an SI slice that is decoded using intra prediction only.
12049
+ // if (sliceType === 2 || sliceType === 7) {
12050
+ if (sliceType === 2 || sliceType === 4 || sliceType === 7 || sliceType === 9) {
12051
+ iskey = true;
12052
+ }
12492
12053
  }
12054
+ if (iskey) {
12055
+ var _VideoSample;
12056
+ // if we have non-keyframe data already, that cannot belong to the same frame as a keyframe, so force a push
12057
+ if ((_VideoSample = VideoSample) != null && _VideoSample.frame && !VideoSample.key) {
12058
+ _this.pushAccessUnit(VideoSample, track);
12059
+ VideoSample = _this.VideoSample = null;
12060
+ }
12061
+ }
12062
+ if (!VideoSample) {
12063
+ VideoSample = _this.VideoSample = _this.createVideoSample(true, pes.pts, pes.dts, '');
12064
+ }
12065
+ VideoSample.frame = true;
12066
+ VideoSample.key = iskey;
12067
+ break;
12068
+ // IDR
12493
12069
  }
12494
- if (!VideoSample) {
12495
- VideoSample = _this2.VideoSample = _this2.createVideoSample(true, pes.pts, pes.dts, '');
12496
- }
12497
- VideoSample.key = true;
12498
- VideoSample.frame = true;
12499
- break;
12500
-
12501
- // IDR
12502
- case 19:
12503
- case 20:
12070
+ case 5:
12504
12071
  push = true;
12505
12072
  // handle PES not starting with AUD
12506
12073
  // if we have frame data already, that cannot belong to the same frame, so force a push
12507
12074
  if ((_VideoSample2 = VideoSample) != null && _VideoSample2.frame && !VideoSample.key) {
12508
- _this2.pushAccessUnit(VideoSample, track);
12509
- VideoSample = _this2.VideoSample = null;
12075
+ _this.pushAccessUnit(VideoSample, track);
12076
+ VideoSample = _this.VideoSample = null;
12510
12077
  }
12511
12078
  if (!VideoSample) {
12512
- VideoSample = _this2.VideoSample = _this2.createVideoSample(true, pes.pts, pes.dts, '');
12079
+ VideoSample = _this.VideoSample = _this.createVideoSample(true, pes.pts, pes.dts, '');
12513
12080
  }
12514
12081
  VideoSample.key = true;
12515
12082
  VideoSample.frame = true;
12516
12083
  break;
12517
-
12518
12084
  // SEI
12519
- case 39:
12520
- push = true;
12521
- parseSEIMessageFromNALu(unit.data, 2,
12522
- // NALu header size
12523
- pes.pts, textTrack.samples);
12524
- break;
12525
-
12526
- // VPS
12527
- case 32:
12528
- push = true;
12529
- if (!track.vps) {
12530
- var config = _this2.readVPS(unit.data);
12531
- track.params = _objectSpread2({}, config);
12532
- _this2.initVPS = unit.data;
12085
+ case 6:
12086
+ {
12087
+ push = true;
12088
+ parseSEIMessageFromNALu(unit.data, 1, pes.pts, textTrack.samples);
12089
+ break;
12090
+ // SPS
12533
12091
  }
12534
- track.vps = [unit.data];
12535
- break;
12536
-
12537
- // SPS
12538
- case 33:
12539
- push = true;
12540
- spsfound = true;
12541
- if (typeof track.params === 'object') {
12542
- if (track.vps !== undefined && track.vps[0] !== _this2.initVPS && track.sps !== undefined && !_this2.matchSPS(track.sps[0], unit.data)) {
12543
- _this2.initVPS = track.vps[0];
12544
- track.sps = track.pps = undefined;
12545
- }
12546
- if (!track.sps) {
12547
- var _config = _this2.readSPS(unit.data);
12548
- track.width = _config.width;
12549
- track.height = _config.height;
12550
- track.pixelRatio = _config.pixelRatio;
12092
+ case 7:
12093
+ {
12094
+ var _track$pixelRatio, _track$pixelRatio2;
12095
+ push = true;
12096
+ spsfound = true;
12097
+ var sps = unit.data;
12098
+ var expGolombDecoder = new ExpGolomb(sps);
12099
+ var config = expGolombDecoder.readSPS();
12100
+ if (!track.sps || track.width !== config.width || track.height !== config.height || ((_track$pixelRatio = track.pixelRatio) == null ? void 0 : _track$pixelRatio[0]) !== config.pixelRatio[0] || ((_track$pixelRatio2 = track.pixelRatio) == null ? void 0 : _track$pixelRatio2[1]) !== config.pixelRatio[1]) {
12101
+ track.width = config.width;
12102
+ track.height = config.height;
12103
+ track.pixelRatio = config.pixelRatio;
12104
+ track.sps = [sps];
12551
12105
  track.duration = duration;
12552
- track.codec = _config.codecString;
12553
- track.sps = [];
12554
- for (var prop in _config.params) {
12555
- track.params[prop] = _config.params[prop];
12106
+ var codecarray = sps.subarray(1, 4);
12107
+ var codecstring = 'avc1.';
12108
+ for (var i = 0; i < 3; i++) {
12109
+ var h = codecarray[i].toString(16);
12110
+ if (h.length < 2) {
12111
+ h = '0' + h;
12112
+ }
12113
+ codecstring += h;
12556
12114
  }
12115
+ track.codec = codecstring;
12557
12116
  }
12558
- if (track.vps !== undefined && track.vps[0] === _this2.initVPS) {
12559
- track.sps.push(unit.data);
12560
- }
12561
- }
12562
- if (!VideoSample) {
12563
- VideoSample = _this2.VideoSample = _this2.createVideoSample(true, pes.pts, pes.dts, '');
12117
+ break;
12564
12118
  }
12565
- VideoSample.key = true;
12566
- break;
12567
-
12568
12119
  // PPS
12569
- case 34:
12120
+ case 8:
12570
12121
  push = true;
12571
- if (typeof track.params === 'object') {
12572
- if (!track.pps) {
12573
- track.pps = [];
12574
- var _config2 = _this2.readPPS(unit.data);
12575
- for (var _prop in _config2) {
12576
- track.params[_prop] = _config2[_prop];
12577
- }
12578
- }
12579
- if (_this2.initVPS !== null || track.pps.length === 0) {
12580
- track.pps.push(unit.data);
12581
- }
12582
- }
12122
+ track.pps = [unit.data];
12583
12123
  break;
12584
-
12585
- // ACCESS UNIT DELIMITER
12586
- case 35:
12124
+ // AUD
12125
+ case 9:
12587
12126
  push = true;
12588
12127
  track.audFound = true;
12589
12128
  if (VideoSample) {
12590
- _this2.pushAccessUnit(VideoSample, track);
12129
+ _this.pushAccessUnit(VideoSample, track);
12591
12130
  }
12592
- VideoSample = _this2.VideoSample = _this2.createVideoSample(false, pes.pts, pes.dts, '');
12131
+ VideoSample = _this.VideoSample = _this.createVideoSample(false, pes.pts, pes.dts, '');
12132
+ break;
12133
+ // Filler Data
12134
+ case 12:
12135
+ push = true;
12593
12136
  break;
12594
12137
  default:
12595
12138
  push = false;
12596
12139
  if (VideoSample) {
12597
- VideoSample.debug += 'unknown or irrelevant NAL ' + unit.type + ' ';
12140
+ VideoSample.debug += 'unknown NAL ' + unit.type + ' ';
12598
12141
  }
12599
12142
  break;
12600
12143
  }
@@ -12609,425 +12152,111 @@
12609
12152
  this.VideoSample = null;
12610
12153
  }
12611
12154
  };
12612
- _proto.getNALuType = function getNALuType(data, offset) {
12613
- return (data[offset] & 0x7e) >>> 1;
12614
- };
12615
- _proto.ebsp2rbsp = function ebsp2rbsp(arr) {
12616
- var dst = new Uint8Array(arr.byteLength);
12617
- var dstIdx = 0;
12618
- for (var i = 0; i < arr.byteLength; i++) {
12619
- if (i >= 2) {
12620
- // Unescape: Skip 0x03 after 00 00
12621
- if (arr[i] === 0x03 && arr[i - 1] === 0x00 && arr[i - 2] === 0x00) {
12622
- continue;
12623
- }
12624
- }
12625
- dst[dstIdx] = arr[i];
12626
- dstIdx++;
12627
- }
12628
- return new Uint8Array(dst.buffer, 0, dstIdx);
12629
- };
12630
- _proto.readVPS = function readVPS(vps) {
12631
- var eg = new ExpGolomb(vps);
12632
- // remove header
12633
- eg.readUByte();
12634
- eg.readUByte();
12635
- eg.readBits(4); // video_parameter_set_id
12636
- eg.skipBits(2);
12637
- eg.readBits(6); // max_layers_minus1
12638
- var max_sub_layers_minus1 = eg.readBits(3);
12639
- var temporal_id_nesting_flag = eg.readBoolean();
12640
- // ...vui fps can be here, but empty fps value is not critical for metadata
12155
+ _proto.parseAVCNALu = function parseAVCNALu(track, array) {
12156
+ var len = array.byteLength;
12157
+ var state = track.naluState || 0;
12158
+ var lastState = state;
12159
+ var units = [];
12160
+ var i = 0;
12161
+ var value;
12162
+ var overflow;
12163
+ var unitType;
12164
+ var lastUnitStart = -1;
12165
+ var lastUnitType = 0;
12166
+ // logger.log('PES:' + Hex.hexDump(array));
12641
12167
 
12642
- return {
12643
- numTemporalLayers: max_sub_layers_minus1 + 1,
12644
- temporalIdNested: temporal_id_nesting_flag
12645
- };
12646
- };
12647
- _proto.readSPS = function readSPS(sps) {
12648
- var eg = new ExpGolomb(this.ebsp2rbsp(sps));
12649
- eg.readUByte();
12650
- eg.readUByte();
12651
- eg.readBits(4); //video_parameter_set_id
12652
- var max_sub_layers_minus1 = eg.readBits(3);
12653
- eg.readBoolean(); // temporal_id_nesting_flag
12654
-
12655
- // profile_tier_level
12656
- var general_profile_space = eg.readBits(2);
12657
- var general_tier_flag = eg.readBoolean();
12658
- var general_profile_idc = eg.readBits(5);
12659
- var general_profile_compatibility_flags_1 = eg.readUByte();
12660
- var general_profile_compatibility_flags_2 = eg.readUByte();
12661
- var general_profile_compatibility_flags_3 = eg.readUByte();
12662
- var general_profile_compatibility_flags_4 = eg.readUByte();
12663
- var general_constraint_indicator_flags_1 = eg.readUByte();
12664
- var general_constraint_indicator_flags_2 = eg.readUByte();
12665
- var general_constraint_indicator_flags_3 = eg.readUByte();
12666
- var general_constraint_indicator_flags_4 = eg.readUByte();
12667
- var general_constraint_indicator_flags_5 = eg.readUByte();
12668
- var general_constraint_indicator_flags_6 = eg.readUByte();
12669
- var general_level_idc = eg.readUByte();
12670
- var sub_layer_profile_present_flags = [];
12671
- var sub_layer_level_present_flags = [];
12672
- for (var i = 0; i < max_sub_layers_minus1; i++) {
12673
- sub_layer_profile_present_flags.push(eg.readBoolean());
12674
- sub_layer_level_present_flags.push(eg.readBoolean());
12675
- }
12676
- if (max_sub_layers_minus1 > 0) {
12677
- for (var _i = max_sub_layers_minus1; _i < 8; _i++) {
12678
- eg.readBits(2);
12679
- }
12680
- }
12681
- for (var _i2 = 0; _i2 < max_sub_layers_minus1; _i2++) {
12682
- if (sub_layer_profile_present_flags[_i2]) {
12683
- eg.readUByte(); // sub_layer_profile_space, sub_layer_tier_flag, sub_layer_profile_idc
12684
- eg.readUByte();
12685
- eg.readUByte();
12686
- eg.readUByte();
12687
- eg.readUByte(); // sub_layer_profile_compatibility_flag
12688
- eg.readUByte();
12689
- eg.readUByte();
12690
- eg.readUByte();
12691
- eg.readUByte();
12692
- eg.readUByte();
12693
- eg.readUByte();
12694
- }
12695
- if (sub_layer_level_present_flags[_i2]) {
12696
- eg.readUByte();
12697
- }
12698
- }
12699
- eg.readUEG(); // seq_parameter_set_id
12700
- var chroma_format_idc = eg.readUEG();
12701
- if (chroma_format_idc == 3) {
12702
- eg.skipBits(1); //separate_colour_plane_flag
12703
- }
12704
- var pic_width_in_luma_samples = eg.readUEG();
12705
- var pic_height_in_luma_samples = eg.readUEG();
12706
- var conformance_window_flag = eg.readBoolean();
12707
- var pic_left_offset = 0,
12708
- pic_right_offset = 0,
12709
- pic_top_offset = 0,
12710
- pic_bottom_offset = 0;
12711
- if (conformance_window_flag) {
12712
- pic_left_offset += eg.readUEG();
12713
- pic_right_offset += eg.readUEG();
12714
- pic_top_offset += eg.readUEG();
12715
- pic_bottom_offset += eg.readUEG();
12716
- }
12717
- var bit_depth_luma_minus8 = eg.readUEG();
12718
- var bit_depth_chroma_minus8 = eg.readUEG();
12719
- var log2_max_pic_order_cnt_lsb_minus4 = eg.readUEG();
12720
- var sub_layer_ordering_info_present_flag = eg.readBoolean();
12721
- for (var _i3 = sub_layer_ordering_info_present_flag ? 0 : max_sub_layers_minus1; _i3 <= max_sub_layers_minus1; _i3++) {
12722
- eg.skipUEG(); // max_dec_pic_buffering_minus1[i]
12723
- eg.skipUEG(); // max_num_reorder_pics[i]
12724
- eg.skipUEG(); // max_latency_increase_plus1[i]
12725
- }
12726
- eg.skipUEG(); // log2_min_luma_coding_block_size_minus3
12727
- eg.skipUEG(); // log2_diff_max_min_luma_coding_block_size
12728
- eg.skipUEG(); // log2_min_transform_block_size_minus2
12729
- eg.skipUEG(); // log2_diff_max_min_transform_block_size
12730
- eg.skipUEG(); // max_transform_hierarchy_depth_inter
12731
- eg.skipUEG(); // max_transform_hierarchy_depth_intra
12732
- var scaling_list_enabled_flag = eg.readBoolean();
12733
- if (scaling_list_enabled_flag) {
12734
- var sps_scaling_list_data_present_flag = eg.readBoolean();
12735
- if (sps_scaling_list_data_present_flag) {
12736
- for (var sizeId = 0; sizeId < 4; sizeId++) {
12737
- for (var matrixId = 0; matrixId < (sizeId === 3 ? 2 : 6); matrixId++) {
12738
- var scaling_list_pred_mode_flag = eg.readBoolean();
12739
- if (!scaling_list_pred_mode_flag) {
12740
- eg.readUEG(); // scaling_list_pred_matrix_id_delta
12741
- } else {
12742
- var coefNum = Math.min(64, 1 << 4 + (sizeId << 1));
12743
- if (sizeId > 1) {
12744
- eg.readEG();
12745
- }
12746
- for (var _i4 = 0; _i4 < coefNum; _i4++) {
12747
- eg.readEG();
12748
- }
12749
- }
12750
- }
12751
- }
12752
- }
12168
+ if (state === -1) {
12169
+ // special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet
12170
+ lastUnitStart = 0;
12171
+ // NALu type is value read from offset 0
12172
+ lastUnitType = array[0] & 0x1f;
12173
+ state = 0;
12174
+ i = 1;
12753
12175
  }
12754
- eg.readBoolean(); // amp_enabled_flag
12755
- eg.readBoolean(); // sample_adaptive_offset_enabled_flag
12756
- var pcm_enabled_flag = eg.readBoolean();
12757
- if (pcm_enabled_flag) {
12758
- eg.readUByte();
12759
- eg.skipUEG();
12760
- eg.skipUEG();
12761
- eg.readBoolean();
12762
- }
12763
- var num_short_term_ref_pic_sets = eg.readUEG();
12764
- var num_delta_pocs = 0;
12765
- for (var _i5 = 0; _i5 < num_short_term_ref_pic_sets; _i5++) {
12766
- var inter_ref_pic_set_prediction_flag = false;
12767
- if (_i5 !== 0) {
12768
- inter_ref_pic_set_prediction_flag = eg.readBoolean();
12769
- }
12770
- if (inter_ref_pic_set_prediction_flag) {
12771
- if (_i5 === num_short_term_ref_pic_sets) {
12772
- eg.readUEG();
12773
- }
12774
- eg.readBoolean();
12775
- eg.readUEG();
12776
- var next_num_delta_pocs = 0;
12777
- for (var j = 0; j <= num_delta_pocs; j++) {
12778
- var used_by_curr_pic_flag = eg.readBoolean();
12779
- var use_delta_flag = false;
12780
- if (!used_by_curr_pic_flag) {
12781
- use_delta_flag = eg.readBoolean();
12782
- }
12783
- if (used_by_curr_pic_flag || use_delta_flag) {
12784
- next_num_delta_pocs++;
12785
- }
12786
- }
12787
- num_delta_pocs = next_num_delta_pocs;
12788
- } else {
12789
- var num_negative_pics = eg.readUEG();
12790
- var num_positive_pics = eg.readUEG();
12791
- num_delta_pocs = num_negative_pics + num_positive_pics;
12792
- for (var _j = 0; _j < num_negative_pics; _j++) {
12793
- eg.readUEG();
12794
- eg.readBoolean();
12795
- }
12796
- for (var _j2 = 0; _j2 < num_positive_pics; _j2++) {
12797
- eg.readUEG();
12798
- eg.readBoolean();
12799
- }
12800
- }
12801
- }
12802
- var long_term_ref_pics_present_flag = eg.readBoolean();
12803
- if (long_term_ref_pics_present_flag) {
12804
- var num_long_term_ref_pics_sps = eg.readUEG();
12805
- for (var _i6 = 0; _i6 < num_long_term_ref_pics_sps; _i6++) {
12806
- for (var _j3 = 0; _j3 < log2_max_pic_order_cnt_lsb_minus4 + 4; _j3++) {
12807
- eg.readBits(1);
12808
- }
12809
- eg.readBits(1);
12810
- }
12811
- }
12812
- var min_spatial_segmentation_idc = 0;
12813
- var sar_width = 1,
12814
- sar_height = 1;
12815
- var fps_fixed = true,
12816
- fps_den = 1,
12817
- fps_num = 0;
12818
- eg.readBoolean(); // sps_temporal_mvp_enabled_flag
12819
- eg.readBoolean(); // strong_intra_smoothing_enabled_flag
12820
- var default_display_window_flag = false;
12821
- var vui_parameters_present_flag = eg.readBoolean();
12822
- if (vui_parameters_present_flag) {
12823
- var aspect_ratio_info_present_flag = eg.readBoolean();
12824
- if (aspect_ratio_info_present_flag) {
12825
- var aspect_ratio_idc = eg.readUByte();
12826
- var sar_width_table = [1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2];
12827
- var sar_height_table = [1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1];
12828
- if (aspect_ratio_idc > 0 && aspect_ratio_idc < 16) {
12829
- sar_width = sar_width_table[aspect_ratio_idc - 1];
12830
- sar_height = sar_height_table[aspect_ratio_idc - 1];
12831
- } else if (aspect_ratio_idc === 255) {
12832
- sar_width = eg.readBits(16);
12833
- sar_height = eg.readBits(16);
12834
- }
12835
- }
12836
- var overscan_info_present_flag = eg.readBoolean();
12837
- if (overscan_info_present_flag) {
12838
- eg.readBoolean();
12839
- }
12840
- var video_signal_type_present_flag = eg.readBoolean();
12841
- if (video_signal_type_present_flag) {
12842
- eg.readBits(3);
12843
- eg.readBoolean();
12844
- var colour_description_present_flag = eg.readBoolean();
12845
- if (colour_description_present_flag) {
12846
- eg.readUByte();
12847
- eg.readUByte();
12848
- eg.readUByte();
12849
- }
12850
- }
12851
- var chroma_loc_info_present_flag = eg.readBoolean();
12852
- if (chroma_loc_info_present_flag) {
12853
- eg.readUEG();
12854
- eg.readUEG();
12855
- }
12856
- eg.readBoolean(); // neutral_chroma_indication_flag
12857
- eg.readBoolean(); // field_seq_flag
12858
- eg.readBoolean(); // frame_field_info_present_flag
12859
- default_display_window_flag = eg.readBoolean();
12860
- if (default_display_window_flag) {
12861
- pic_left_offset += eg.readUEG();
12862
- pic_right_offset += eg.readUEG();
12863
- pic_top_offset += eg.readUEG();
12864
- pic_bottom_offset += eg.readUEG();
12865
- }
12866
- var vui_timing_info_present_flag = eg.readBoolean();
12867
- if (vui_timing_info_present_flag) {
12868
- fps_den = eg.readBits(32);
12869
- fps_num = eg.readBits(32);
12870
- var vui_poc_proportional_to_timing_flag = eg.readBoolean();
12871
- if (vui_poc_proportional_to_timing_flag) {
12872
- eg.readUEG();
12873
- }
12874
- var vui_hrd_parameters_present_flag = eg.readBoolean();
12875
- if (vui_hrd_parameters_present_flag) {
12876
- //const commonInfPresentFlag = true;
12877
- //if (commonInfPresentFlag) {
12878
- var nal_hrd_parameters_present_flag = eg.readBoolean();
12879
- var vcl_hrd_parameters_present_flag = eg.readBoolean();
12880
- var sub_pic_hrd_params_present_flag = false;
12881
- if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag) {
12882
- sub_pic_hrd_params_present_flag = eg.readBoolean();
12883
- if (sub_pic_hrd_params_present_flag) {
12884
- eg.readUByte();
12885
- eg.readBits(5);
12886
- eg.readBoolean();
12887
- eg.readBits(5);
12888
- }
12889
- eg.readBits(4); // bit_rate_scale
12890
- eg.readBits(4); // cpb_size_scale
12891
- if (sub_pic_hrd_params_present_flag) {
12892
- eg.readBits(4);
12893
- }
12894
- eg.readBits(5);
12895
- eg.readBits(5);
12896
- eg.readBits(5);
12897
- }
12898
- //}
12899
- for (var _i7 = 0; _i7 <= max_sub_layers_minus1; _i7++) {
12900
- fps_fixed = eg.readBoolean(); // fixed_pic_rate_general_flag
12901
- var fixed_pic_rate_within_cvs_flag = fps_fixed || eg.readBoolean();
12902
- var low_delay_hrd_flag = false;
12903
- if (fixed_pic_rate_within_cvs_flag) {
12904
- eg.readEG();
12905
- } else {
12906
- low_delay_hrd_flag = eg.readBoolean();
12907
- }
12908
- var cpb_cnt = low_delay_hrd_flag ? 1 : eg.readUEG() + 1;
12909
- if (nal_hrd_parameters_present_flag) {
12910
- for (var _j4 = 0; _j4 < cpb_cnt; _j4++) {
12911
- eg.readUEG();
12912
- eg.readUEG();
12913
- if (sub_pic_hrd_params_present_flag) {
12914
- eg.readUEG();
12915
- eg.readUEG();
12916
- }
12917
- eg.skipBits(1);
12176
+ while (i < len) {
12177
+ value = array[i++];
12178
+ // optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case
12179
+ if (!state) {
12180
+ state = value ? 0 : 1;
12181
+ continue;
12182
+ }
12183
+ if (state === 1) {
12184
+ state = value ? 0 : 2;
12185
+ continue;
12186
+ }
12187
+ // here we have state either equal to 2 or 3
12188
+ if (!value) {
12189
+ state = 3;
12190
+ } else if (value === 1) {
12191
+ overflow = i - state - 1;
12192
+ if (lastUnitStart >= 0) {
12193
+ var unit = {
12194
+ data: array.subarray(lastUnitStart, overflow),
12195
+ type: lastUnitType
12196
+ };
12197
+ // logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);
12198
+ units.push(unit);
12199
+ } else {
12200
+ // lastUnitStart is undefined => this is the first start code found in this PES packet
12201
+ // first check if start code delimiter is overlapping between 2 PES packets,
12202
+ // ie it started in last packet (lastState not zero)
12203
+ // and ended at the beginning of this PES packet (i <= 4 - lastState)
12204
+ var lastUnit = this.getLastNalUnit(track.samples);
12205
+ if (lastUnit) {
12206
+ if (lastState && i <= 4 - lastState) {
12207
+ // start delimiter overlapping between PES packets
12208
+ // strip start delimiter bytes from the end of last NAL unit
12209
+ // check if lastUnit had a state different from zero
12210
+ if (lastUnit.state) {
12211
+ // strip last bytes
12212
+ lastUnit.data = lastUnit.data.subarray(0, lastUnit.data.byteLength - lastState);
12918
12213
  }
12919
12214
  }
12920
- if (vcl_hrd_parameters_present_flag) {
12921
- for (var _j5 = 0; _j5 < cpb_cnt; _j5++) {
12922
- eg.readUEG();
12923
- eg.readUEG();
12924
- if (sub_pic_hrd_params_present_flag) {
12925
- eg.readUEG();
12926
- eg.readUEG();
12927
- }
12928
- eg.skipBits(1);
12929
- }
12215
+ // If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.
12216
+
12217
+ if (overflow > 0) {
12218
+ // logger.log('first NALU found with overflow:' + overflow);
12219
+ lastUnit.data = appendUint8Array(lastUnit.data, array.subarray(0, overflow));
12220
+ lastUnit.state = 0;
12930
12221
  }
12931
12222
  }
12932
12223
  }
12933
- }
12934
- var bitstream_restriction_flag = eg.readBoolean();
12935
- if (bitstream_restriction_flag) {
12936
- eg.readBoolean(); // tiles_fixed_structure_flag
12937
- eg.readBoolean(); // motion_vectors_over_pic_boundaries_flag
12938
- eg.readBoolean(); // restricted_ref_pic_lists_flag
12939
- min_spatial_segmentation_idc = eg.readUEG();
12940
- }
12941
- }
12942
- var width = pic_width_in_luma_samples,
12943
- height = pic_height_in_luma_samples;
12944
- if (conformance_window_flag || default_display_window_flag) {
12945
- var chroma_scale_w = 1,
12946
- chroma_scale_h = 1;
12947
- if (chroma_format_idc === 1) {
12948
- // YUV 420
12949
- chroma_scale_w = chroma_scale_h = 2;
12950
- } else if (chroma_format_idc == 2) {
12951
- // YUV 422
12952
- chroma_scale_w = 2;
12953
- }
12954
- width = pic_width_in_luma_samples - chroma_scale_w * pic_right_offset - chroma_scale_w * pic_left_offset;
12955
- height = pic_height_in_luma_samples - chroma_scale_h * pic_bottom_offset - chroma_scale_h * pic_top_offset;
12956
- }
12957
- var profile_space_string = general_profile_space ? ['A', 'B', 'C'][general_profile_space] : '';
12958
- 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;
12959
- var profile_compatibility_rev = 0;
12960
- for (var _i8 = 0; _i8 < 32; _i8++) {
12961
- profile_compatibility_rev = (profile_compatibility_rev | (profile_compatibility_buf >> _i8 & 1) << 31 - _i8) >>> 0; // reverse bit position (and cast as UInt32)
12962
- }
12963
- var profile_compatibility_flags_string = profile_compatibility_rev.toString(16);
12964
- if (general_profile_idc === 1 && profile_compatibility_flags_string === '2') {
12965
- profile_compatibility_flags_string = '6';
12966
- }
12967
- var tier_flag_string = general_tier_flag ? 'H' : 'L';
12968
- return {
12969
- codecString: "hvc1." + profile_space_string + general_profile_idc + "." + profile_compatibility_flags_string + "." + tier_flag_string + general_level_idc + ".B0",
12970
- params: {
12971
- general_tier_flag: general_tier_flag,
12972
- general_profile_idc: general_profile_idc,
12973
- general_profile_space: general_profile_space,
12974
- general_profile_compatibility_flags: [general_profile_compatibility_flags_1, general_profile_compatibility_flags_2, general_profile_compatibility_flags_3, general_profile_compatibility_flags_4],
12975
- 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],
12976
- general_level_idc: general_level_idc,
12977
- bit_depth: bit_depth_luma_minus8 + 8,
12978
- bit_depth_luma_minus8: bit_depth_luma_minus8,
12979
- bit_depth_chroma_minus8: bit_depth_chroma_minus8,
12980
- min_spatial_segmentation_idc: min_spatial_segmentation_idc,
12981
- chroma_format_idc: chroma_format_idc,
12982
- frame_rate: {
12983
- fixed: fps_fixed,
12984
- fps: fps_num / fps_den
12224
+ // check if we can read unit type
12225
+ if (i < len) {
12226
+ unitType = array[i] & 0x1f;
12227
+ // logger.log('find NALU @ offset:' + i + ',type:' + unitType);
12228
+ lastUnitStart = i;
12229
+ lastUnitType = unitType;
12230
+ state = 0;
12231
+ } else {
12232
+ // not enough byte to read unit type. let's read it on next PES parsing
12233
+ state = -1;
12985
12234
  }
12986
- },
12987
- width: width,
12988
- height: height,
12989
- pixelRatio: [sar_width, sar_height]
12990
- };
12991
- };
12992
- _proto.readPPS = function readPPS(pps) {
12993
- var eg = new ExpGolomb(this.ebsp2rbsp(pps));
12994
- eg.readUByte();
12995
- eg.readUByte();
12996
- eg.skipUEG(); // pic_parameter_set_id
12997
- eg.skipUEG(); // seq_parameter_set_id
12998
- eg.skipBits(2); // dependent_slice_segments_enabled_flag, output_flag_present_flag
12999
- eg.skipBits(3); // num_extra_slice_header_bits
13000
- eg.skipBits(2); // sign_data_hiding_enabled_flag, cabac_init_present_flag
13001
- eg.skipUEG();
13002
- eg.skipUEG();
13003
- eg.skipEG(); // init_qp_minus26
13004
- eg.skipBits(2); // constrained_intra_pred_flag, transform_skip_enabled_flag
13005
- var cu_qp_delta_enabled_flag = eg.readBoolean();
13006
- if (cu_qp_delta_enabled_flag) {
13007
- eg.skipUEG();
13008
- }
13009
- eg.skipEG(); // cb_qp_offset
13010
- eg.skipEG(); // cr_qp_offset
13011
- eg.skipBits(4); // pps_slice_chroma_qp_offsets_present_flag, weighted_pred_flag, weighted_bipred_flag, transquant_bypass_enabled_flag
13012
- var tiles_enabled_flag = eg.readBoolean();
13013
- var entropy_coding_sync_enabled_flag = eg.readBoolean();
13014
- var parallelismType = 1; // slice-based parallel decoding
13015
- if (entropy_coding_sync_enabled_flag && tiles_enabled_flag) {
13016
- parallelismType = 0; // mixed-type parallel decoding
13017
- } else if (entropy_coding_sync_enabled_flag) {
13018
- parallelismType = 3; // wavefront-based parallel decoding
13019
- } else if (tiles_enabled_flag) {
13020
- parallelismType = 2; // tile-based parallel decoding
12235
+ } else {
12236
+ state = 0;
12237
+ }
13021
12238
  }
13022
- return {
13023
- parallelismType: parallelismType
13024
- };
13025
- };
13026
- _proto.matchSPS = function matchSPS(sps1, sps2) {
13027
- // compare without headers and VPS related params
13028
- return String.fromCharCode.apply(null, sps1).substr(3) === String.fromCharCode.apply(null, sps2).substr(3);
12239
+ if (lastUnitStart >= 0 && state >= 0) {
12240
+ var _unit = {
12241
+ data: array.subarray(lastUnitStart, len),
12242
+ type: lastUnitType,
12243
+ state: state
12244
+ };
12245
+ units.push(_unit);
12246
+ // logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
12247
+ }
12248
+ // no NALu found
12249
+ if (units.length === 0) {
12250
+ // append pes.data to previous NAL unit
12251
+ var _lastUnit = this.getLastNalUnit(track.samples);
12252
+ if (_lastUnit) {
12253
+ _lastUnit.data = appendUint8Array(_lastUnit.data, array);
12254
+ }
12255
+ }
12256
+ track.naluState = state;
12257
+ return units;
13029
12258
  };
13030
- return HevcVideoParser;
12259
+ return AvcVideoParser;
13031
12260
  }(BaseVideoParser);
13032
12261
 
13033
12262
  /**
@@ -13045,7 +12274,7 @@
13045
12274
  }
13046
12275
  var _proto = SampleAesDecrypter.prototype;
13047
12276
  _proto.decryptBuffer = function decryptBuffer(encryptedData) {
13048
- return this.decrypter.decrypt(encryptedData, this.keyData.key.buffer, this.keyData.iv.buffer, DecrypterAesMode.cbc);
12277
+ return this.decrypter.decrypt(encryptedData, this.keyData.key.buffer, this.keyData.iv.buffer);
13049
12278
  }
13050
12279
 
13051
12280
  // AAC - encrypt all full 16 bytes blocks starting from offset 16
@@ -13164,7 +12393,7 @@
13164
12393
  this.observer = observer;
13165
12394
  this.config = config;
13166
12395
  this.typeSupported = typeSupported;
13167
- this.videoParser = null;
12396
+ this.videoParser = new AvcVideoParser();
13168
12397
  }
13169
12398
  TSDemuxer.probe = function probe(data) {
13170
12399
  var syncOffset = TSDemuxer.syncOffset(data);
@@ -13334,21 +12563,7 @@
13334
12563
  case videoPid:
13335
12564
  if (stt) {
13336
12565
  if (videoData && (pes = parsePES(videoData))) {
13337
- if (this.videoParser === null) {
13338
- switch (videoTrack.segmentCodec) {
13339
- case 'avc':
13340
- this.videoParser = new AvcVideoParser();
13341
- break;
13342
- case 'hevc':
13343
- {
13344
- this.videoParser = new HevcVideoParser();
13345
- }
13346
- break;
13347
- }
13348
- }
13349
- if (this.videoParser !== null) {
13350
- this.videoParser.parsePES(videoTrack, textTrack, pes, false, this._duration);
13351
- }
12566
+ this.videoParser.parseAVCPES(videoTrack, textTrack, pes, false, this._duration);
13352
12567
  }
13353
12568
  videoData = {
13354
12569
  data: [],
@@ -13505,28 +12720,14 @@
13505
12720
  videoTrack = demuxResult.videoTrack,
13506
12721
  id3Track = demuxResult.id3Track,
13507
12722
  textTrack = demuxResult.textTrack;
13508
- var videoData = videoTrack.pesData;
13509
- var audioData = audioTrack.pesData;
13510
- var id3Data = id3Track.pesData;
13511
- // try to parse last PES packets
13512
- var pes;
13513
- if (videoData && (pes = parsePES(videoData))) {
13514
- if (this.videoParser === null) {
13515
- switch (videoTrack.segmentCodec) {
13516
- case 'avc':
13517
- this.videoParser = new AvcVideoParser();
13518
- break;
13519
- case 'hevc':
13520
- {
13521
- this.videoParser = new HevcVideoParser();
13522
- }
13523
- break;
13524
- }
13525
- }
13526
- if (this.videoParser !== null) {
13527
- this.videoParser.parsePES(videoTrack, textTrack, pes, true, this._duration);
13528
- videoTrack.pesData = null;
13529
- }
12723
+ var videoData = videoTrack.pesData;
12724
+ var audioData = audioTrack.pesData;
12725
+ var id3Data = id3Track.pesData;
12726
+ // try to parse last PES packets
12727
+ var pes;
12728
+ if (videoData && (pes = parsePES(videoData))) {
12729
+ this.videoParser.parseAVCPES(videoTrack, textTrack, pes, true, this._duration);
12730
+ videoTrack.pesData = null;
13530
12731
  } else {
13531
12732
  // either avcData null or PES truncated, keep it for next frag parsing
13532
12733
  videoTrack.pesData = videoData;
@@ -13858,14 +13059,7 @@
13858
13059
  logger.warn('Unsupported EC-3 in M2TS found');
13859
13060
  break;
13860
13061
  case 0x24:
13861
- // ITU-T Rec. H.265 and ISO/IEC 23008-2 (HEVC)
13862
- {
13863
- if (result.videoPid === -1) {
13864
- result.videoPid = pid;
13865
- result.segmentVideoCodec = 'hevc';
13866
- logger.log('HEVC in M2TS found');
13867
- }
13868
- }
13062
+ logger.warn('Unsupported HEVC in M2TS found');
13869
13063
  break;
13870
13064
  }
13871
13065
  // move to the next table entry
@@ -14093,8 +13287,6 @@
14093
13287
  avc1: [],
14094
13288
  // codingname
14095
13289
  avcC: [],
14096
- hvc1: [],
14097
- hvcC: [],
14098
13290
  btrt: [],
14099
13291
  dinf: [],
14100
13292
  dref: [],
@@ -14522,10 +13714,8 @@
14522
13714
  return MP4.box(MP4.types.stsd, MP4.STSD, MP4.ac3(track));
14523
13715
  }
14524
13716
  return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track));
14525
- } else if (track.segmentCodec === 'avc') {
14526
- return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));
14527
13717
  } else {
14528
- return MP4.box(MP4.types.stsd, MP4.STSD, MP4.hvc1(track));
13718
+ return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));
14529
13719
  }
14530
13720
  };
14531
13721
  MP4.tkhd = function tkhd(track) {
@@ -14663,84 +13853,6 @@
14663
13853
  var result = appendUint8Array(MP4.FTYP, movie);
14664
13854
  return result;
14665
13855
  };
14666
- MP4.hvc1 = function hvc1(track) {
14667
- var ps = track.params;
14668
- var units = [track.vps, track.sps, track.pps];
14669
- var NALuLengthSize = 4;
14670
- 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]);
14671
-
14672
- // compute hvcC size in bytes
14673
- var length = config.length;
14674
- for (var i = 0; i < units.length; i += 1) {
14675
- length += 3;
14676
- for (var j = 0; j < units[i].length; j += 1) {
14677
- length += 2 + units[i][j].length;
14678
- }
14679
- }
14680
- var hvcC = new Uint8Array(length);
14681
- hvcC.set(config, 0);
14682
- length = config.length;
14683
- // append parameter set units: one vps, one or more sps and pps
14684
- var iMax = units.length - 1;
14685
- for (var _i = 0; _i < units.length; _i += 1) {
14686
- hvcC.set(new Uint8Array([32 + _i | (_i === iMax ? 128 : 0), 0x00, units[_i].length]), length);
14687
- length += 3;
14688
- for (var _j = 0; _j < units[_i].length; _j += 1) {
14689
- hvcC.set(new Uint8Array([units[_i][_j].length >> 8, units[_i][_j].length & 255]), length);
14690
- length += 2;
14691
- hvcC.set(units[_i][_j], length);
14692
- length += units[_i][_j].length;
14693
- }
14694
- }
14695
- var hvcc = MP4.box(MP4.types.hvcC, hvcC);
14696
- var width = track.width;
14697
- var height = track.height;
14698
- var hSpacing = track.pixelRatio[0];
14699
- var vSpacing = track.pixelRatio[1];
14700
- return MP4.box(MP4.types.hvc1, new Uint8Array([0x00, 0x00, 0x00,
14701
- // reserved
14702
- 0x00, 0x00, 0x00,
14703
- // reserved
14704
- 0x00, 0x01,
14705
- // data_reference_index
14706
- 0x00, 0x00,
14707
- // pre_defined
14708
- 0x00, 0x00,
14709
- // reserved
14710
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
14711
- // pre_defined
14712
- width >> 8 & 0xff, width & 0xff,
14713
- // width
14714
- height >> 8 & 0xff, height & 0xff,
14715
- // height
14716
- 0x00, 0x48, 0x00, 0x00,
14717
- // horizresolution
14718
- 0x00, 0x48, 0x00, 0x00,
14719
- // vertresolution
14720
- 0x00, 0x00, 0x00, 0x00,
14721
- // reserved
14722
- 0x00, 0x01,
14723
- // frame_count
14724
- 0x12, 0x64, 0x61, 0x69, 0x6c,
14725
- // dailymotion/hls.js
14726
- 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,
14727
- // compressorname
14728
- 0x00, 0x18,
14729
- // depth = 24
14730
- 0x11, 0x11]),
14731
- // pre_defined = -1
14732
- hvcc, MP4.box(MP4.types.btrt, new Uint8Array([0x00, 0x1c, 0x9c, 0x80,
14733
- // bufferSizeDB
14734
- 0x00, 0x2d, 0xc6, 0xc0,
14735
- // maxBitrate
14736
- 0x00, 0x2d, 0xc6, 0xc0])),
14737
- // avgBitrate
14738
- MP4.box(MP4.types.pasp, new Uint8Array([hSpacing >> 24,
14739
- // hSpacing
14740
- hSpacing >> 16 & 0xff, hSpacing >> 8 & 0xff, hSpacing & 0xff, vSpacing >> 24,
14741
- // vSpacing
14742
- vSpacing >> 16 & 0xff, vSpacing >> 8 & 0xff, vSpacing & 0xff])));
14743
- };
14744
13856
  return MP4;
14745
13857
  }();
14746
13858
  MP4.types = void 0;
@@ -15142,9 +14254,9 @@
15142
14254
  var foundOverlap = delta < -1;
15143
14255
  if (foundHole || foundOverlap) {
15144
14256
  if (foundHole) {
15145
- logger.warn((track.segmentCodec || '').toUpperCase() + ": " + toMsFromMpegTsClock(delta, true) + " ms (" + delta + "dts) hole between fragments detected at " + timeOffset.toFixed(3));
14257
+ logger.warn("AVC: " + toMsFromMpegTsClock(delta, true) + " ms (" + delta + "dts) hole between fragments detected at " + timeOffset.toFixed(3));
15146
14258
  } else {
15147
- logger.warn((track.segmentCodec || '').toUpperCase() + ": " + toMsFromMpegTsClock(-delta, true) + " ms (" + delta + "dts) overlapping between fragments detected at " + timeOffset.toFixed(3));
14259
+ logger.warn("AVC: " + toMsFromMpegTsClock(-delta, true) + " ms (" + delta + "dts) overlapping between fragments detected at " + timeOffset.toFixed(3));
15148
14260
  }
15149
14261
  if (!foundOverlap || nextAvcDts >= inputSamples[0].pts || chromeVersion) {
15150
14262
  firstDTS = nextAvcDts;
@@ -15153,24 +14265,12 @@
15153
14265
  inputSamples[0].dts = firstDTS;
15154
14266
  inputSamples[0].pts = firstPTS;
15155
14267
  } else {
15156
- var isPTSOrderRetained = true;
15157
14268
  for (var _i = 0; _i < inputSamples.length; _i++) {
15158
- if (inputSamples[_i].dts > firstPTS && isPTSOrderRetained) {
14269
+ if (inputSamples[_i].dts > firstPTS) {
15159
14270
  break;
15160
14271
  }
15161
- var prevPTS = inputSamples[_i].pts;
15162
14272
  inputSamples[_i].dts -= delta;
15163
14273
  inputSamples[_i].pts -= delta;
15164
-
15165
- // check to see if this sample's PTS order has changed
15166
- // relative to the next one
15167
- if (_i < inputSamples.length - 1) {
15168
- var nextSamplePTS = inputSamples[_i + 1].pts;
15169
- var currentSamplePTS = inputSamples[_i].pts;
15170
- var currentOrder = nextSamplePTS <= currentSamplePTS;
15171
- var prevOrder = nextSamplePTS <= prevPTS;
15172
- isPTSOrderRetained = currentOrder == prevOrder;
15173
- }
15174
14274
  }
15175
14275
  }
15176
14276
  logger.log("Video: Initial PTS/DTS adjusted: " + toMsFromMpegTsClock(firstPTS, true) + "/" + toMsFromMpegTsClock(firstDTS, true) + ", delta: " + toMsFromMpegTsClock(delta, true) + " ms");
@@ -15318,7 +14418,7 @@
15318
14418
  }
15319
14419
  }
15320
14420
  }
15321
- // next AVC/HEVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)
14421
+ // next AVC sample DTS should be equal to last sample DTS + last sample duration (in PES timescale)
15322
14422
  mp4SampleDuration = stretchedLastFrame || !mp4SampleDuration ? averageSampleDuration : mp4SampleDuration;
15323
14423
  this.nextAvcDts = nextAvcDts = lastDTS + mp4SampleDuration;
15324
14424
  this.videoSampleDuration = mp4SampleDuration;
@@ -15453,7 +14553,7 @@
15453
14553
  logger.warn("[mp4-remuxer]: Injecting " + missing + " audio frame @ " + (nextPts / inputTimeScale).toFixed(3) + "s due to " + Math.round(1000 * delta / inputTimeScale) + " ms gap.");
15454
14554
  for (var j = 0; j < missing; j++) {
15455
14555
  var newStamp = Math.max(nextPts, 0);
15456
- var fillFrame = AAC.getSilentFrame(track.parsedCodec || track.manifestCodec || track.codec, track.channelCount);
14556
+ var fillFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
15457
14557
  if (!fillFrame) {
15458
14558
  logger.log('[mp4-remuxer]: Unable to get silent frame for given audio codec; duplicating last frame instead.');
15459
14559
  fillFrame = sample.unit.subarray();
@@ -15581,7 +14681,7 @@
15581
14681
  // samples count of this segment's duration
15582
14682
  var nbSamples = Math.ceil((endDTS - startDTS) / frameDuration);
15583
14683
  // silent frame
15584
- var silentFrame = AAC.getSilentFrame(track.parsedCodec || track.manifestCodec || track.codec, track.channelCount);
14684
+ var silentFrame = AAC.getSilentFrame(track.manifestCodec || track.codec, track.channelCount);
15585
14685
  logger.warn('[mp4-remuxer]: remux empty Audio');
15586
14686
  // Can't remux if we can't generate a silent frame...
15587
14687
  if (!silentFrame) {
@@ -15971,15 +15071,13 @@
15971
15071
  duration = transmuxConfig.duration,
15972
15072
  initSegmentData = transmuxConfig.initSegmentData;
15973
15073
  var keyData = getEncryptionType(uintData, decryptdata);
15974
- if (keyData && isFullSegmentEncryption(keyData.method)) {
15074
+ if (keyData && keyData.method === 'AES-128') {
15975
15075
  var decrypter = this.getDecrypter();
15976
- var aesMode = getAesModeFromFullSegmentMethod(keyData.method);
15977
-
15978
15076
  // Software decryption is synchronous; webCrypto is not
15979
15077
  if (decrypter.isSync()) {
15980
15078
  // Software decryption is progressive. Progressive decryption may not return a result on each call. Any cached
15981
15079
  // data is handled in the flush() call
15982
- var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer, aesMode);
15080
+ var decryptedData = decrypter.softwareDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer);
15983
15081
  // For Low-Latency HLS Parts, decrypt in place, since part parsing is expected on push progress
15984
15082
  var loadingParts = chunkMeta.part > -1;
15985
15083
  if (loadingParts) {
@@ -15991,7 +15089,7 @@
15991
15089
  }
15992
15090
  uintData = new Uint8Array(decryptedData);
15993
15091
  } else {
15994
- this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer, aesMode).then(function (decryptedData) {
15092
+ this.decryptionPromise = decrypter.webCryptoDecrypt(uintData, keyData.key.buffer, keyData.iv.buffer).then(function (decryptedData) {
15995
15093
  // Calling push here is important; if flush() is called while this is still resolving, this ensures that
15996
15094
  // the decrypted data has been transmuxed
15997
15095
  var result = _this.push(decryptedData, null, chunkMeta);
@@ -16612,7 +15710,7 @@
16612
15710
  observer.on(Events.ERROR, forwardMessage);
16613
15711
 
16614
15712
  // forward logger events to main thread
16615
- var forwardWorkerLogs = function forwardWorkerLogs(logger) {
15713
+ var forwardWorkerLogs = function forwardWorkerLogs() {
16616
15714
  var _loop = function _loop(logFn) {
16617
15715
  var func = function func(message) {
16618
15716
  forwardMessage('workerLog', {
@@ -16633,8 +15731,8 @@
16633
15731
  {
16634
15732
  var config = JSON.parse(data.config);
16635
15733
  self.transmuxer = new Transmuxer(observer, data.typeSupported, config, data.vendor, data.id);
16636
- var logger = enableLogs(config.debug, data.id);
16637
- forwardWorkerLogs(logger);
15734
+ enableLogs(config.debug, data.id);
15735
+ forwardWorkerLogs();
16638
15736
  forwardMessage('init', null);
16639
15737
  break;
16640
15738
  }
@@ -16808,7 +15906,16 @@
16808
15906
  this.observer = new EventEmitter();
16809
15907
  this.observer.on(Events.FRAG_DECRYPTED, forwardMessage);
16810
15908
  this.observer.on(Events.ERROR, forwardMessage);
16811
- var m2tsTypeSupported = getM2TSSupportedAudioTypes(config.preferManagedMediaSource);
15909
+ var MediaSource = getMediaSource(config.preferManagedMediaSource) || {
15910
+ isTypeSupported: function isTypeSupported() {
15911
+ return false;
15912
+ }
15913
+ };
15914
+ var m2tsTypeSupported = {
15915
+ mpeg: MediaSource.isTypeSupported('audio/mpeg'),
15916
+ mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'),
15917
+ ac3: MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"')
15918
+ };
16812
15919
 
16813
15920
  // navigator.vendor is not always available in Web Worker
16814
15921
  // refer to https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/navigator
@@ -17092,7 +16199,7 @@
17092
16199
  _inheritsLoose(AudioStreamController, _BaseStreamController);
17093
16200
  function AudioStreamController(hls, fragmentTracker, keyLoader) {
17094
16201
  var _this;
17095
- _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'audio-stream-controller', PlaylistLevelType.AUDIO) || this;
16202
+ _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[audio-stream-controller]', PlaylistLevelType.AUDIO) || this;
17096
16203
  _this.videoBuffer = null;
17097
16204
  _this.videoTrackCC = -1;
17098
16205
  _this.waitingVideoCC = -1;
@@ -17104,24 +16211,27 @@
17104
16211
  _this.flushing = false;
17105
16212
  _this.bufferFlushed = false;
17106
16213
  _this.cachedTrackLoadedData = null;
17107
- _this.registerListeners();
16214
+ _this._registerListeners();
17108
16215
  return _this;
17109
16216
  }
17110
16217
  var _proto = AudioStreamController.prototype;
17111
16218
  _proto.onHandlerDestroying = function onHandlerDestroying() {
17112
- this.unregisterListeners();
16219
+ this._unregisterListeners();
17113
16220
  _BaseStreamController.prototype.onHandlerDestroying.call(this);
17114
16221
  this.mainDetails = null;
17115
16222
  this.bufferedTrack = null;
17116
16223
  this.switchingTrack = null;
17117
16224
  };
17118
- _proto.registerListeners = function registerListeners() {
17119
- _BaseStreamController.prototype.registerListeners.call(this);
16225
+ _proto._registerListeners = function _registerListeners() {
17120
16226
  var hls = this.hls;
16227
+ hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
16228
+ hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
16229
+ hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
17121
16230
  hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
17122
16231
  hls.on(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
17123
16232
  hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
17124
16233
  hls.on(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
16234
+ hls.on(Events.ERROR, this.onError, this);
17125
16235
  hls.on(Events.BUFFER_RESET, this.onBufferReset, this);
17126
16236
  hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
17127
16237
  hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
@@ -17129,16 +16239,16 @@
17129
16239
  hls.on(Events.INIT_PTS_FOUND, this.onInitPtsFound, this);
17130
16240
  hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
17131
16241
  };
17132
- _proto.unregisterListeners = function unregisterListeners() {
16242
+ _proto._unregisterListeners = function _unregisterListeners() {
17133
16243
  var hls = this.hls;
17134
- if (!hls) {
17135
- return;
17136
- }
17137
- _BaseStreamController.prototype.unregisterListeners.call(this);
16244
+ hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
16245
+ hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
16246
+ hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
17138
16247
  hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
17139
16248
  hls.off(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
17140
16249
  hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
17141
16250
  hls.off(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
16251
+ hls.off(Events.ERROR, this.onError, this);
17142
16252
  hls.off(Events.BUFFER_RESET, this.onBufferReset, this);
17143
16253
  hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
17144
16254
  hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
@@ -17297,13 +16407,12 @@
17297
16407
  trackId = this.trackId;
17298
16408
  var config = hls.config;
17299
16409
 
17300
- // 1. if buffering is suspended
17301
- // 2. if video not attached AND
16410
+ // 1. if video not attached AND
17302
16411
  // start fragment already requested OR start frag prefetch not enabled
17303
- // 3. if tracks or track not loaded and selected
16412
+ // 2. if tracks or track not loaded and selected
17304
16413
  // then exit loop
17305
16414
  // => if media not attached but start frag prefetch is enabled and start frag not requested yet, we will not exit loop
17306
- if (!this.buffering || !media && (this.startFragRequested || !config.startFragPrefetch) || !(levels != null && levels[trackId])) {
16415
+ if (!media && (this.startFragRequested || !config.startFragPrefetch) || !(levels != null && levels[trackId])) {
17307
16416
  return;
17308
16417
  }
17309
16418
  var levelInfo = levels[trackId];
@@ -17832,7 +16941,7 @@
17832
16941
  _inheritsLoose(AudioTrackController, _BasePlaylistControll);
17833
16942
  function AudioTrackController(hls) {
17834
16943
  var _this;
17835
- _this = _BasePlaylistControll.call(this, hls, 'audio-track-controller') || this;
16944
+ _this = _BasePlaylistControll.call(this, hls, '[audio-track-controller]') || this;
17836
16945
  _this.tracks = [];
17837
16946
  _this.groupIds = null;
17838
16947
  _this.tracksInGroup = [];
@@ -18161,23 +17270,26 @@
18161
17270
  _inheritsLoose(SubtitleStreamController, _BaseStreamController);
18162
17271
  function SubtitleStreamController(hls, fragmentTracker, keyLoader) {
18163
17272
  var _this;
18164
- _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'subtitle-stream-controller', PlaylistLevelType.SUBTITLE) || this;
17273
+ _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[subtitle-stream-controller]', PlaylistLevelType.SUBTITLE) || this;
18165
17274
  _this.currentTrackId = -1;
18166
17275
  _this.tracksBuffered = [];
18167
17276
  _this.mainDetails = null;
18168
- _this.registerListeners();
17277
+ _this._registerListeners();
18169
17278
  return _this;
18170
17279
  }
18171
17280
  var _proto = SubtitleStreamController.prototype;
18172
17281
  _proto.onHandlerDestroying = function onHandlerDestroying() {
18173
- this.unregisterListeners();
17282
+ this._unregisterListeners();
18174
17283
  _BaseStreamController.prototype.onHandlerDestroying.call(this);
18175
17284
  this.mainDetails = null;
18176
17285
  };
18177
- _proto.registerListeners = function registerListeners() {
18178
- _BaseStreamController.prototype.registerListeners.call(this);
17286
+ _proto._registerListeners = function _registerListeners() {
18179
17287
  var hls = this.hls;
17288
+ hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
17289
+ hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
17290
+ hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
18180
17291
  hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
17292
+ hls.on(Events.ERROR, this.onError, this);
18181
17293
  hls.on(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);
18182
17294
  hls.on(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);
18183
17295
  hls.on(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);
@@ -18185,10 +17297,13 @@
18185
17297
  hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
18186
17298
  hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
18187
17299
  };
18188
- _proto.unregisterListeners = function unregisterListeners() {
18189
- _BaseStreamController.prototype.unregisterListeners.call(this);
17300
+ _proto._unregisterListeners = function _unregisterListeners() {
18190
17301
  var hls = this.hls;
17302
+ hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
17303
+ hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
17304
+ hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
18191
17305
  hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
17306
+ hls.off(Events.ERROR, this.onError, this);
18192
17307
  hls.off(Events.SUBTITLE_TRACKS_UPDATED, this.onSubtitleTracksUpdated, this);
18193
17308
  hls.off(Events.SUBTITLE_TRACK_SWITCH, this.onSubtitleTrackSwitch, this);
18194
17309
  hls.off(Events.SUBTITLE_TRACK_LOADED, this.onSubtitleTrackLoaded, this);
@@ -18411,10 +17526,10 @@
18411
17526
  return;
18412
17527
  }
18413
17528
  // check to see if the payload needs to be decrypted
18414
- if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && isFullSegmentEncryption(decryptData.method)) {
17529
+ if (payload && payload.byteLength > 0 && decryptData != null && decryptData.key && decryptData.iv && decryptData.method === 'AES-128') {
18415
17530
  var startTime = performance.now();
18416
17531
  // decrypt the subtitles
18417
- this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer, getAesModeFromFullSegmentMethod(decryptData.method)).catch(function (err) {
17532
+ this.decrypter.decrypt(new Uint8Array(payload), decryptData.key.buffer, decryptData.iv.buffer).catch(function (err) {
18418
17533
  hls.trigger(Events.ERROR, {
18419
17534
  type: ErrorTypes.MEDIA_ERROR,
18420
17535
  details: ErrorDetails.FRAG_DECRYPT_ERROR,
@@ -18546,7 +17661,7 @@
18546
17661
  _inheritsLoose(SubtitleTrackController, _BasePlaylistControll);
18547
17662
  function SubtitleTrackController(hls) {
18548
17663
  var _this;
18549
- _this = _BasePlaylistControll.call(this, hls, 'subtitle-track-controller') || this;
17664
+ _this = _BasePlaylistControll.call(this, hls, '[subtitle-track-controller]') || this;
18550
17665
  _this.media = null;
18551
17666
  _this.tracks = [];
18552
17667
  _this.groupIds = null;
@@ -18555,12 +17670,12 @@
18555
17670
  _this.currentTrack = null;
18556
17671
  _this.selectDefaultTrack = true;
18557
17672
  _this.queuedDefaultTrack = -1;
18558
- _this.useTextTrackPolling = false;
18559
- _this.subtitlePollingInterval = -1;
18560
- _this._subtitleDisplay = true;
18561
17673
  _this.asyncPollTrackChange = function () {
18562
17674
  return _this.pollTrackChange(0);
18563
17675
  };
17676
+ _this.useTextTrackPolling = false;
17677
+ _this.subtitlePollingInterval = -1;
17678
+ _this._subtitleDisplay = true;
18564
17679
  _this.onTextTracksChanged = function () {
18565
17680
  if (!_this.useTextTrackPolling) {
18566
17681
  self.clearInterval(_this.subtitlePollingInterval);
@@ -18596,7 +17711,6 @@
18596
17711
  this.tracks.length = 0;
18597
17712
  this.tracksInGroup.length = 0;
18598
17713
  this.currentTrack = null;
18599
- // @ts-ignore
18600
17714
  this.onTextTracksChanged = this.asyncPollTrackChange = null;
18601
17715
  _BasePlaylistControll.prototype.destroy.call(this);
18602
17716
  };
@@ -19070,57 +18184,57 @@
19070
18184
  }();
19071
18185
 
19072
18186
  var VIDEO_CODEC_PROFILE_REPLACE = /(avc[1234]|hvc1|hev1|dvh[1e]|vp09|av01)(?:\.[^.,]+)+/;
19073
- var BufferController = /*#__PURE__*/function (_Logger) {
19074
- _inheritsLoose(BufferController, _Logger);
18187
+ var BufferController = /*#__PURE__*/function () {
19075
18188
  function BufferController(hls) {
19076
- var _this;
19077
- _this = _Logger.call(this, 'buffer-controller', hls.logger) || this;
18189
+ var _this = this;
19078
18190
  // The level details used to determine duration, target-duration and live
19079
- _this.details = null;
18191
+ this.details = null;
19080
18192
  // cache the self generated object url to detect hijack of video tag
19081
- _this._objectUrl = null;
18193
+ this._objectUrl = null;
19082
18194
  // A queue of buffer operations which require the SourceBuffer to not be updating upon execution
19083
- _this.operationQueue = void 0;
18195
+ this.operationQueue = void 0;
19084
18196
  // References to event listeners for each SourceBuffer, so that they can be referenced for event removal
19085
- _this.listeners = void 0;
19086
- _this.hls = void 0;
18197
+ this.listeners = void 0;
18198
+ this.hls = void 0;
19087
18199
  // The number of BUFFER_CODEC events received before any sourceBuffers are created
19088
- _this.bufferCodecEventsExpected = 0;
18200
+ this.bufferCodecEventsExpected = 0;
19089
18201
  // The total number of BUFFER_CODEC events received
19090
- _this._bufferCodecEventsTotal = 0;
18202
+ this._bufferCodecEventsTotal = 0;
19091
18203
  // A reference to the attached media element
19092
- _this.media = null;
18204
+ this.media = null;
19093
18205
  // A reference to the active media source
19094
- _this.mediaSource = null;
18206
+ this.mediaSource = null;
19095
18207
  // Last MP3 audio chunk appended
19096
- _this.lastMpegAudioChunk = null;
19097
- _this.appendSource = void 0;
18208
+ this.lastMpegAudioChunk = null;
18209
+ this.appendSource = void 0;
19098
18210
  // counters
19099
- _this.appendErrors = {
18211
+ this.appendErrors = {
19100
18212
  audio: 0,
19101
18213
  video: 0,
19102
18214
  audiovideo: 0
19103
18215
  };
19104
- _this.tracks = {};
19105
- _this.pendingTracks = {};
19106
- _this.sourceBuffer = void 0;
19107
- _this._onEndStreaming = function (event) {
18216
+ this.tracks = {};
18217
+ this.pendingTracks = {};
18218
+ this.sourceBuffer = void 0;
18219
+ this.log = void 0;
18220
+ this.warn = void 0;
18221
+ this.error = void 0;
18222
+ this._onEndStreaming = function (event) {
19108
18223
  if (!_this.hls) {
19109
18224
  return;
19110
18225
  }
19111
18226
  _this.hls.pauseBuffering();
19112
18227
  };
19113
- _this._onStartStreaming = function (event) {
18228
+ this._onStartStreaming = function (event) {
19114
18229
  if (!_this.hls) {
19115
18230
  return;
19116
18231
  }
19117
18232
  _this.hls.resumeBuffering();
19118
18233
  };
19119
18234
  // Keep as arrow functions so that we can directly reference these functions directly as event listeners
19120
- _this._onMediaSourceOpen = function () {
19121
- var _assertThisInitialize = _assertThisInitialized(_this),
19122
- media = _assertThisInitialize.media,
19123
- mediaSource = _assertThisInitialize.mediaSource;
18235
+ this._onMediaSourceOpen = function () {
18236
+ var media = _this.media,
18237
+ mediaSource = _this.mediaSource;
19124
18238
  _this.log('Media source opened');
19125
18239
  if (media) {
19126
18240
  media.removeEventListener('emptied', _this._onMediaEmptied);
@@ -19136,25 +18250,27 @@
19136
18250
  }
19137
18251
  _this.checkPendingTracks();
19138
18252
  };
19139
- _this._onMediaSourceClose = function () {
18253
+ this._onMediaSourceClose = function () {
19140
18254
  _this.log('Media source closed');
19141
18255
  };
19142
- _this._onMediaSourceEnded = function () {
18256
+ this._onMediaSourceEnded = function () {
19143
18257
  _this.log('Media source ended');
19144
18258
  };
19145
- _this._onMediaEmptied = function () {
19146
- var _assertThisInitialize2 = _assertThisInitialized(_this),
19147
- mediaSrc = _assertThisInitialize2.mediaSrc,
19148
- _objectUrl = _assertThisInitialize2._objectUrl;
18259
+ this._onMediaEmptied = function () {
18260
+ var mediaSrc = _this.mediaSrc,
18261
+ _objectUrl = _this._objectUrl;
19149
18262
  if (mediaSrc !== _objectUrl) {
19150
- _this.error("Media element src was set while attaching MediaSource (" + _objectUrl + " > " + mediaSrc + ")");
18263
+ logger.error("Media element src was set while attaching MediaSource (" + _objectUrl + " > " + mediaSrc + ")");
19151
18264
  }
19152
18265
  };
19153
- _this.hls = hls;
19154
- _this.appendSource = hls.config.preferManagedMediaSource;
19155
- _this._initSourceBuffer();
19156
- _this.registerListeners();
19157
- return _this;
18266
+ this.hls = hls;
18267
+ var logPrefix = '[buffer-controller]';
18268
+ this.appendSource = hls.config.preferManagedMediaSource;
18269
+ this.log = logger.log.bind(logger, logPrefix);
18270
+ this.warn = logger.warn.bind(logger, logPrefix);
18271
+ this.error = logger.error.bind(logger, logPrefix);
18272
+ this._initSourceBuffer();
18273
+ this.registerListeners();
19158
18274
  }
19159
18275
  var _proto = BufferController.prototype;
19160
18276
  _proto.hasSourceTypes = function hasSourceTypes() {
@@ -19166,12 +18282,6 @@
19166
18282
  this.lastMpegAudioChunk = null;
19167
18283
  // @ts-ignore
19168
18284
  this.hls = null;
19169
- // @ts-ignore
19170
- this._onMediaSourceOpen = this._onMediaSourceClose = null;
19171
- // @ts-ignore
19172
- this._onMediaSourceEnded = null;
19173
- // @ts-ignore
19174
- this._onStartStreaming = this._onEndStreaming = null;
19175
18285
  };
19176
18286
  _proto.registerListeners = function registerListeners() {
19177
18287
  var hls = this.hls;
@@ -19329,7 +18439,6 @@
19329
18439
  _this2.resetBuffer(type);
19330
18440
  });
19331
18441
  this._initSourceBuffer();
19332
- this.hls.resumeBuffering();
19333
18442
  };
19334
18443
  _proto.resetBuffer = function resetBuffer(type) {
19335
18444
  var sb = this.sourceBuffer[type];
@@ -20033,7 +19142,7 @@
20033
19142
  }
20034
19143
  }]);
20035
19144
  return BufferController;
20036
- }(Logger);
19145
+ }();
20037
19146
  function removeSourceChildren(node) {
20038
19147
  var sourceChildren = node.querySelectorAll('source');
20039
19148
  [].slice.call(sourceChildren).forEach(function (source) {
@@ -22472,12 +21581,14 @@
22472
21581
  this.cea608Parser1 = this.cea608Parser2 = undefined;
22473
21582
  };
22474
21583
  _proto.initCea608Parsers = function initCea608Parsers() {
22475
- var channel1 = new OutputFilter(this, 'textTrack1');
22476
- var channel2 = new OutputFilter(this, 'textTrack2');
22477
- var channel3 = new OutputFilter(this, 'textTrack3');
22478
- var channel4 = new OutputFilter(this, 'textTrack4');
22479
- this.cea608Parser1 = new Cea608Parser(1, channel1, channel2);
22480
- this.cea608Parser2 = new Cea608Parser(3, channel3, channel4);
21584
+ if (this.config.enableCEA708Captions && (!this.cea608Parser1 || !this.cea608Parser2)) {
21585
+ var channel1 = new OutputFilter(this, 'textTrack1');
21586
+ var channel2 = new OutputFilter(this, 'textTrack2');
21587
+ var channel3 = new OutputFilter(this, 'textTrack3');
21588
+ var channel4 = new OutputFilter(this, 'textTrack4');
21589
+ this.cea608Parser1 = new Cea608Parser(1, channel1, channel2);
21590
+ this.cea608Parser2 = new Cea608Parser(3, channel3, channel4);
21591
+ }
22481
21592
  };
22482
21593
  _proto.addCues = function addCues(trackName, startTime, endTime, screen, cueRanges) {
22483
21594
  // skip cues which overlap more than 50% with previously parsed time ranges
@@ -22712,7 +21823,7 @@
22712
21823
  return t.label;
22713
21824
  });
22714
21825
  if (unusedTextTracks.length) {
22715
- this.hls.logger.warn("Media element contains unused subtitle tracks: " + unusedTextTracks.join(', ') + ". Replace media element for each source to clear TextTracks and captions menu.");
21826
+ logger.warn("Media element contains unused subtitle tracks: " + unusedTextTracks.join(', ') + ". Replace media element for each source to clear TextTracks and captions menu.");
22716
21827
  }
22717
21828
  }
22718
21829
  } else if (this.tracks.length) {
@@ -22758,20 +21869,23 @@
22758
21869
  return level == null ? void 0 : level.attrs['CLOSED-CAPTIONS'];
22759
21870
  };
22760
21871
  _proto.onFragLoading = function onFragLoading(event, data) {
21872
+ this.initCea608Parsers();
21873
+ var cea608Parser1 = this.cea608Parser1,
21874
+ cea608Parser2 = this.cea608Parser2,
21875
+ lastCc = this.lastCc,
21876
+ lastSn = this.lastSn,
21877
+ lastPartIndex = this.lastPartIndex;
21878
+ if (!this.enabled || !cea608Parser1 || !cea608Parser2) {
21879
+ return;
21880
+ }
22761
21881
  // if this frag isn't contiguous, clear the parser so cues with bad start/end times aren't added to the textTrack
22762
- if (this.enabled && data.frag.type === PlaylistLevelType.MAIN) {
21882
+ if (data.frag.type === PlaylistLevelType.MAIN) {
22763
21883
  var _data$part$index, _data$part;
22764
- var cea608Parser1 = this.cea608Parser1,
22765
- cea608Parser2 = this.cea608Parser2,
22766
- lastSn = this.lastSn;
22767
- if (!cea608Parser1 || !cea608Parser2) {
22768
- return;
22769
- }
22770
21884
  var _data$frag = data.frag,
22771
21885
  cc = _data$frag.cc,
22772
21886
  sn = _data$frag.sn;
22773
- var partIndex = (_data$part$index = (_data$part = data.part) == null ? void 0 : _data$part.index) != null ? _data$part$index : -1;
22774
- if (!(sn === lastSn + 1 || sn === lastSn && partIndex === this.lastPartIndex + 1 || cc === this.lastCc)) {
21887
+ var partIndex = (_data$part$index = data == null ? void 0 : (_data$part = data.part) == null ? void 0 : _data$part.index) != null ? _data$part$index : -1;
21888
+ if (!(sn === lastSn + 1 || sn === lastSn && partIndex === lastPartIndex + 1 || cc === lastCc)) {
22775
21889
  cea608Parser1.reset();
22776
21890
  cea608Parser2.reset();
22777
21891
  }
@@ -22827,7 +21941,7 @@
22827
21941
  frag: frag
22828
21942
  });
22829
21943
  }, function (error) {
22830
- hls.logger.log("Failed to parse IMSC1: " + error);
21944
+ logger.log("Failed to parse IMSC1: " + error);
22831
21945
  hls.trigger(Events.SUBTITLE_FRAG_PROCESSED, {
22832
21946
  success: false,
22833
21947
  frag: frag,
@@ -22865,7 +21979,7 @@
22865
21979
  _this5._fallbackToIMSC1(frag, payload);
22866
21980
  }
22867
21981
  // Something went wrong while parsing. Trigger event with success false.
22868
- hls.logger.log("Failed to parse VTT cue: " + error);
21982
+ logger.log("Failed to parse VTT cue: " + error);
22869
21983
  if (missingInitPTS && maxAvCC > frag.cc) {
22870
21984
  return;
22871
21985
  }
@@ -22927,7 +22041,10 @@
22927
22041
  this.captionsTracks = {};
22928
22042
  };
22929
22043
  _proto.onFragParsingUserdata = function onFragParsingUserdata(event, data) {
22930
- if (!this.enabled || !this.config.enableCEA708Captions) {
22044
+ this.initCea608Parsers();
22045
+ var cea608Parser1 = this.cea608Parser1,
22046
+ cea608Parser2 = this.cea608Parser2;
22047
+ if (!this.enabled || !cea608Parser1 || !cea608Parser2) {
22931
22048
  return;
22932
22049
  }
22933
22050
  var frag = data.frag,
@@ -22940,12 +22057,9 @@
22940
22057
  for (var i = 0; i < samples.length; i++) {
22941
22058
  var ccBytes = samples[i].bytes;
22942
22059
  if (ccBytes) {
22943
- if (!this.cea608Parser1) {
22944
- this.initCea608Parsers();
22945
- }
22946
22060
  var ccdatas = this.extractCea608Data(ccBytes);
22947
- this.cea608Parser1.addData(samples[i].pts, ccdatas[0]);
22948
- this.cea608Parser2.addData(samples[i].pts, ccdatas[1]);
22061
+ cea608Parser1.addData(samples[i].pts, ccdatas[0]);
22062
+ cea608Parser2.addData(samples[i].pts, ccdatas[1]);
22949
22063
  }
22950
22064
  }
22951
22065
  };
@@ -23137,7 +22251,7 @@
23137
22251
  var hls = this.hls;
23138
22252
  var maxLevel = this.getMaxLevel(levels.length - 1);
23139
22253
  if (maxLevel !== this.autoLevelCapping) {
23140
- hls.logger.log("Setting autoLevelCapping to " + maxLevel + ": " + levels[maxLevel].height + "p@" + levels[maxLevel].bitrate + " for media " + this.mediaWidth + "x" + this.mediaHeight);
22254
+ logger.log("Setting autoLevelCapping to " + maxLevel + ": " + levels[maxLevel].height + "p@" + levels[maxLevel].bitrate + " for media " + this.mediaWidth + "x" + this.mediaHeight);
23141
22255
  }
23142
22256
  hls.autoLevelCapping = maxLevel;
23143
22257
  if (hls.autoLevelCapping > this.autoLevelCapping && this.streamController) {
@@ -23327,10 +22441,10 @@
23327
22441
  totalDroppedFrames: droppedFrames
23328
22442
  });
23329
22443
  if (droppedFPS > 0) {
23330
- // hls.logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));
22444
+ // logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));
23331
22445
  if (currentDropped > hls.config.fpsDroppedMonitoringThreshold * currentDecoded) {
23332
22446
  var currentLevel = hls.currentLevel;
23333
- hls.logger.warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel);
22447
+ logger.warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel);
23334
22448
  if (currentLevel > 0 && (hls.autoLevelCapping === -1 || hls.autoLevelCapping >= currentLevel)) {
23335
22449
  currentLevel = currentLevel - 1;
23336
22450
  hls.trigger(Events.FPS_DROP_LEVEL_CAPPING, {
@@ -23363,6 +22477,7 @@
23363
22477
  return FPSController;
23364
22478
  }();
23365
22479
 
22480
+ var LOGGER_PREFIX = '[eme]';
23366
22481
  /**
23367
22482
  * Controller to deal with encrypted media extensions (EME)
23368
22483
  * @see https://developer.mozilla.org/en-US/docs/Web/API/Encrypted_Media_Extensions_API
@@ -23370,122 +22485,26 @@
23370
22485
  * @class
23371
22486
  * @constructor
23372
22487
  */
23373
- var EMEController = /*#__PURE__*/function (_Logger) {
23374
- _inheritsLoose(EMEController, _Logger);
22488
+ var EMEController = /*#__PURE__*/function () {
23375
22489
  function EMEController(hls) {
23376
- var _this;
23377
- _this = _Logger.call(this, 'eme', hls.logger) || this;
23378
- _this.hls = void 0;
23379
- _this.config = void 0;
23380
- _this.media = null;
23381
- _this.keyFormatPromise = null;
23382
- _this.keySystemAccessPromises = {};
23383
- _this._requestLicenseFailureCount = 0;
23384
- _this.mediaKeySessions = [];
23385
- _this.keyIdToKeySessionPromise = {};
23386
- _this.setMediaKeysQueue = EMEController.CDMCleanupPromise ? [EMEController.CDMCleanupPromise] : [];
23387
- _this.onMediaEncrypted = function (event) {
23388
- var initDataType = event.initDataType,
23389
- initData = event.initData;
23390
- _this.debug("\"" + event.type + "\" event: init data type: \"" + initDataType + "\"");
23391
-
23392
- // Ignore event when initData is null
23393
- if (initData === null) {
23394
- return;
23395
- }
23396
- var keyId;
23397
- var keySystemDomain;
23398
- if (initDataType === 'sinf' && _this.config.drmSystems[KeySystems.FAIRPLAY]) {
23399
- // Match sinf keyId to playlist skd://keyId=
23400
- var json = bin2str(new Uint8Array(initData));
23401
- try {
23402
- var sinf = base64Decode(JSON.parse(json).sinf);
23403
- var tenc = parseSinf(new Uint8Array(sinf));
23404
- if (!tenc) {
23405
- return;
23406
- }
23407
- keyId = tenc.subarray(8, 24);
23408
- keySystemDomain = KeySystems.FAIRPLAY;
23409
- } catch (error) {
23410
- _this.warn('Failed to parse sinf "encrypted" event message initData');
23411
- return;
23412
- }
23413
- } else {
23414
- // Support clear-lead key-session creation (otherwise depend on playlist keys)
23415
- var psshInfo = parsePssh(initData);
23416
- if (psshInfo === null) {
23417
- return;
23418
- }
23419
- if (psshInfo.version === 0 && psshInfo.systemId === KeySystemIds.WIDEVINE && psshInfo.data) {
23420
- keyId = psshInfo.data.subarray(8, 24);
23421
- }
23422
- keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
23423
- }
23424
- if (!keySystemDomain || !keyId) {
23425
- return;
23426
- }
23427
- var keyIdHex = Hex.hexDump(keyId);
23428
- var _assertThisInitialize = _assertThisInitialized(_this),
23429
- keyIdToKeySessionPromise = _assertThisInitialize.keyIdToKeySessionPromise,
23430
- mediaKeySessions = _assertThisInitialize.mediaKeySessions;
23431
- var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
23432
- var _loop = function _loop() {
23433
- // Match playlist key
23434
- var keyContext = mediaKeySessions[i];
23435
- var decryptdata = keyContext.decryptdata;
23436
- if (decryptdata.pssh || !decryptdata.keyId) {
23437
- return 0; // continue
23438
- }
23439
- var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
23440
- if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
23441
- keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
23442
- delete keyIdToKeySessionPromise[oldKeyIdHex];
23443
- decryptdata.pssh = new Uint8Array(initData);
23444
- decryptdata.keyId = keyId;
23445
- keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
23446
- return _this.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
23447
- });
23448
- return 1; // break
23449
- }
23450
- },
23451
- _ret;
23452
- for (var i = 0; i < mediaKeySessions.length; i++) {
23453
- _ret = _loop();
23454
- if (_ret === 0) continue;
23455
- if (_ret === 1) break;
23456
- }
23457
- if (!keySessionContextPromise) {
23458
- // Clear-lead key (not encountered in playlist)
23459
- keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = _this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref) {
23460
- var _keySystemToKeySystem;
23461
- var keySystem = _ref.keySystem,
23462
- mediaKeys = _ref.mediaKeys;
23463
- _this.throwIfDestroyed();
23464
- var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
23465
- decryptdata.pssh = new Uint8Array(initData);
23466
- decryptdata.keyId = keyId;
23467
- return _this.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
23468
- _this.throwIfDestroyed();
23469
- var keySessionContext = _this.createMediaKeySessionContext({
23470
- decryptdata: decryptdata,
23471
- keySystem: keySystem,
23472
- mediaKeys: mediaKeys
23473
- });
23474
- return _this.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
23475
- });
23476
- });
23477
- }
23478
- keySessionContextPromise.catch(function (error) {
23479
- return _this.handleError(error);
23480
- });
23481
- };
23482
- _this.onWaitingForKey = function (event) {
23483
- _this.log("\"" + event.type + "\" event");
23484
- };
23485
- _this.hls = hls;
23486
- _this.config = hls.config;
23487
- _this.registerListeners();
23488
- return _this;
22490
+ this.hls = void 0;
22491
+ this.config = void 0;
22492
+ this.media = null;
22493
+ this.keyFormatPromise = null;
22494
+ this.keySystemAccessPromises = {};
22495
+ this._requestLicenseFailureCount = 0;
22496
+ this.mediaKeySessions = [];
22497
+ this.keyIdToKeySessionPromise = {};
22498
+ this.setMediaKeysQueue = EMEController.CDMCleanupPromise ? [EMEController.CDMCleanupPromise] : [];
22499
+ this.onMediaEncrypted = this._onMediaEncrypted.bind(this);
22500
+ this.onWaitingForKey = this._onWaitingForKey.bind(this);
22501
+ this.debug = logger.debug.bind(logger, LOGGER_PREFIX);
22502
+ this.log = logger.log.bind(logger, LOGGER_PREFIX);
22503
+ this.warn = logger.warn.bind(logger, LOGGER_PREFIX);
22504
+ this.error = logger.error.bind(logger, LOGGER_PREFIX);
22505
+ this.hls = hls;
22506
+ this.config = hls.config;
22507
+ this.registerListeners();
23489
22508
  }
23490
22509
  var _proto = EMEController.prototype;
23491
22510
  _proto.destroy = function destroy() {
@@ -23497,9 +22516,9 @@
23497
22516
  config.licenseXhrSetup = config.licenseResponseCallback = undefined;
23498
22517
  config.drmSystems = config.drmSystemOptions = {};
23499
22518
  // @ts-ignore
23500
- this.hls = this.config = this.keyIdToKeySessionPromise = null;
22519
+ this.hls = this.onMediaEncrypted = this.onWaitingForKey = this.keyIdToKeySessionPromise = null;
23501
22520
  // @ts-ignore
23502
- this.onMediaEncrypted = this.onWaitingForKey = null;
22521
+ this.config = null;
23503
22522
  };
23504
22523
  _proto.registerListeners = function registerListeners() {
23505
22524
  this.hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
@@ -23538,7 +22557,7 @@
23538
22557
  }
23539
22558
  };
23540
22559
  _proto.attemptKeySystemAccess = function attemptKeySystemAccess(keySystemsToAttempt) {
23541
- var _this2 = this;
22560
+ var _this = this;
23542
22561
  var levels = this.hls.levels;
23543
22562
  var uniqueCodec = function uniqueCodec(value, i, a) {
23544
22563
  return !!value && a.indexOf(value) === i;
@@ -23555,7 +22574,7 @@
23555
22574
  return new Promise(function (resolve, reject) {
23556
22575
  var attempt = function attempt(keySystems) {
23557
22576
  var keySystem = keySystems.shift();
23558
- _this2.getMediaKeysPromise(keySystem, audioCodecs, videoCodecs).then(function (mediaKeys) {
22577
+ _this.getMediaKeysPromise(keySystem, audioCodecs, videoCodecs).then(function (mediaKeys) {
23559
22578
  return resolve({
23560
22579
  keySystem: keySystem,
23561
22580
  mediaKeys: mediaKeys
@@ -23590,7 +22609,7 @@
23590
22609
  return requestMediaKeySystemAccessFunc(keySystem, supportedConfigurations);
23591
22610
  };
23592
22611
  _proto.getMediaKeysPromise = function getMediaKeysPromise(keySystem, audioCodecs, videoCodecs) {
23593
- var _this3 = this;
22612
+ var _this2 = this;
23594
22613
  // This can throw, but is caught in event handler callpath
23595
22614
  var mediaKeySystemConfigs = getSupportedMediaKeySystemConfigurations(keySystem, audioCodecs, videoCodecs, this.config.drmSystemOptions);
23596
22615
  var keySystemAccessPromises = this.keySystemAccessPromises[keySystem];
@@ -23602,23 +22621,23 @@
23602
22621
  keySystemAccess: keySystemAccess
23603
22622
  };
23604
22623
  keySystemAccess.catch(function (error) {
23605
- _this3.log("Failed to obtain access to key-system \"" + keySystem + "\": " + error);
22624
+ _this2.log("Failed to obtain access to key-system \"" + keySystem + "\": " + error);
23606
22625
  });
23607
22626
  return keySystemAccess.then(function (mediaKeySystemAccess) {
23608
- _this3.log("Access for key-system \"" + mediaKeySystemAccess.keySystem + "\" obtained");
23609
- var certificateRequest = _this3.fetchServerCertificate(keySystem);
23610
- _this3.log("Create media-keys for \"" + keySystem + "\"");
22627
+ _this2.log("Access for key-system \"" + mediaKeySystemAccess.keySystem + "\" obtained");
22628
+ var certificateRequest = _this2.fetchServerCertificate(keySystem);
22629
+ _this2.log("Create media-keys for \"" + keySystem + "\"");
23611
22630
  _keySystemAccessPromises.mediaKeys = mediaKeySystemAccess.createMediaKeys().then(function (mediaKeys) {
23612
- _this3.log("Media-keys created for \"" + keySystem + "\"");
22631
+ _this2.log("Media-keys created for \"" + keySystem + "\"");
23613
22632
  return certificateRequest.then(function (certificate) {
23614
22633
  if (certificate) {
23615
- return _this3.setMediaKeysServerCertificate(mediaKeys, keySystem, certificate);
22634
+ return _this2.setMediaKeysServerCertificate(mediaKeys, keySystem, certificate);
23616
22635
  }
23617
22636
  return mediaKeys;
23618
22637
  });
23619
22638
  });
23620
22639
  _keySystemAccessPromises.mediaKeys.catch(function (error) {
23621
- _this3.error("Failed to create media-keys for \"" + keySystem + "\"}: " + error);
22640
+ _this2.error("Failed to create media-keys for \"" + keySystem + "\"}: " + error);
23622
22641
  });
23623
22642
  return _keySystemAccessPromises.mediaKeys;
23624
22643
  });
@@ -23627,10 +22646,10 @@
23627
22646
  return keySystemAccessPromises.mediaKeys;
23628
22647
  });
23629
22648
  };
23630
- _proto.createMediaKeySessionContext = function createMediaKeySessionContext(_ref2) {
23631
- var decryptdata = _ref2.decryptdata,
23632
- keySystem = _ref2.keySystem,
23633
- mediaKeys = _ref2.mediaKeys;
22649
+ _proto.createMediaKeySessionContext = function createMediaKeySessionContext(_ref) {
22650
+ var decryptdata = _ref.decryptdata,
22651
+ keySystem = _ref.keySystem,
22652
+ mediaKeys = _ref.mediaKeys;
23634
22653
  this.log("Creating key-system session \"" + keySystem + "\" keyId: " + Hex.hexDump(decryptdata.keyId || []));
23635
22654
  var mediaKeysSession = mediaKeys.createSession();
23636
22655
  var mediaKeySessionContext = {
@@ -23679,14 +22698,14 @@
23679
22698
  return this.keyFormatPromise;
23680
22699
  };
23681
22700
  _proto.getKeyFormatPromise = function getKeyFormatPromise(keyFormats) {
23682
- var _this4 = this;
22701
+ var _this3 = this;
23683
22702
  return new Promise(function (resolve, reject) {
23684
- var keySystemsInConfig = getKeySystemsForConfig(_this4.config);
22703
+ var keySystemsInConfig = getKeySystemsForConfig(_this3.config);
23685
22704
  var keySystemsToAttempt = keyFormats.map(keySystemFormatToKeySystemDomain).filter(function (value) {
23686
22705
  return !!value && keySystemsInConfig.indexOf(value) !== -1;
23687
22706
  });
23688
- return _this4.getKeySystemSelectionPromise(keySystemsToAttempt).then(function (_ref3) {
23689
- var keySystem = _ref3.keySystem;
22707
+ return _this3.getKeySystemSelectionPromise(keySystemsToAttempt).then(function (_ref2) {
22708
+ var keySystem = _ref2.keySystem;
23690
22709
  var keySystemFormat = keySystemDomainToKeySystemFormat(keySystem);
23691
22710
  if (keySystemFormat) {
23692
22711
  resolve(keySystemFormat);
@@ -23697,31 +22716,31 @@
23697
22716
  });
23698
22717
  };
23699
22718
  _proto.loadKey = function loadKey(data) {
23700
- var _this5 = this;
22719
+ var _this4 = this;
23701
22720
  var decryptdata = data.keyInfo.decryptdata;
23702
22721
  var keyId = this.getKeyIdString(decryptdata);
23703
22722
  var keyDetails = "(keyId: " + keyId + " format: \"" + decryptdata.keyFormat + "\" method: " + decryptdata.method + " uri: " + decryptdata.uri + ")";
23704
22723
  this.log("Starting session for key " + keyDetails);
23705
22724
  var keySessionContextPromise = this.keyIdToKeySessionPromise[keyId];
23706
22725
  if (!keySessionContextPromise) {
23707
- keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (_ref4) {
23708
- var keySystem = _ref4.keySystem,
23709
- mediaKeys = _ref4.mediaKeys;
23710
- _this5.throwIfDestroyed();
23711
- _this5.log("Handle encrypted media sn: " + data.frag.sn + " " + data.frag.type + ": " + data.frag.level + " using key " + keyDetails);
23712
- return _this5.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
23713
- _this5.throwIfDestroyed();
23714
- var keySessionContext = _this5.createMediaKeySessionContext({
22726
+ keySessionContextPromise = this.keyIdToKeySessionPromise[keyId] = this.getKeySystemForKeyPromise(decryptdata).then(function (_ref3) {
22727
+ var keySystem = _ref3.keySystem,
22728
+ mediaKeys = _ref3.mediaKeys;
22729
+ _this4.throwIfDestroyed();
22730
+ _this4.log("Handle encrypted media sn: " + data.frag.sn + " " + data.frag.type + ": " + data.frag.level + " using key " + keyDetails);
22731
+ return _this4.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
22732
+ _this4.throwIfDestroyed();
22733
+ var keySessionContext = _this4.createMediaKeySessionContext({
23715
22734
  keySystem: keySystem,
23716
22735
  mediaKeys: mediaKeys,
23717
22736
  decryptdata: decryptdata
23718
22737
  });
23719
22738
  var scheme = 'cenc';
23720
- return _this5.generateRequestWithPreferredKeySession(keySessionContext, scheme, decryptdata.pssh, 'playlist-key');
22739
+ return _this4.generateRequestWithPreferredKeySession(keySessionContext, scheme, decryptdata.pssh, 'playlist-key');
23721
22740
  });
23722
22741
  });
23723
22742
  keySessionContextPromise.catch(function (error) {
23724
- return _this5.handleError(error);
22743
+ return _this4.handleError(error);
23725
22744
  });
23726
22745
  }
23727
22746
  return keySessionContextPromise;
@@ -23755,22 +22774,120 @@
23755
22774
  var keySystemsToAttempt = keySystem ? [keySystem] : getKeySystemsForConfig(this.config);
23756
22775
  return this.attemptKeySystemAccess(keySystemsToAttempt);
23757
22776
  }
23758
- return mediaKeySessionContext;
22777
+ return mediaKeySessionContext;
22778
+ };
22779
+ _proto.getKeySystemSelectionPromise = function getKeySystemSelectionPromise(keySystemsToAttempt) {
22780
+ if (!keySystemsToAttempt.length) {
22781
+ keySystemsToAttempt = getKeySystemsForConfig(this.config);
22782
+ }
22783
+ if (keySystemsToAttempt.length === 0) {
22784
+ throw new EMEKeyError({
22785
+ type: ErrorTypes.KEY_SYSTEM_ERROR,
22786
+ details: ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE,
22787
+ fatal: true
22788
+ }, "Missing key-system license configuration options " + JSON.stringify({
22789
+ drmSystems: this.config.drmSystems
22790
+ }));
22791
+ }
22792
+ return this.attemptKeySystemAccess(keySystemsToAttempt);
22793
+ };
22794
+ _proto._onMediaEncrypted = function _onMediaEncrypted(event) {
22795
+ var _this5 = this;
22796
+ var initDataType = event.initDataType,
22797
+ initData = event.initData;
22798
+ this.debug("\"" + event.type + "\" event: init data type: \"" + initDataType + "\"");
22799
+
22800
+ // Ignore event when initData is null
22801
+ if (initData === null) {
22802
+ return;
22803
+ }
22804
+ var keyId;
22805
+ var keySystemDomain;
22806
+ if (initDataType === 'sinf' && this.config.drmSystems[KeySystems.FAIRPLAY]) {
22807
+ // Match sinf keyId to playlist skd://keyId=
22808
+ var json = bin2str(new Uint8Array(initData));
22809
+ try {
22810
+ var sinf = base64Decode(JSON.parse(json).sinf);
22811
+ var tenc = parseSinf(new Uint8Array(sinf));
22812
+ if (!tenc) {
22813
+ return;
22814
+ }
22815
+ keyId = tenc.subarray(8, 24);
22816
+ keySystemDomain = KeySystems.FAIRPLAY;
22817
+ } catch (error) {
22818
+ this.warn('Failed to parse sinf "encrypted" event message initData');
22819
+ return;
22820
+ }
22821
+ } else {
22822
+ // Support clear-lead key-session creation (otherwise depend on playlist keys)
22823
+ var psshInfo = parsePssh(initData);
22824
+ if (psshInfo === null) {
22825
+ return;
22826
+ }
22827
+ if (psshInfo.version === 0 && psshInfo.systemId === KeySystemIds.WIDEVINE && psshInfo.data) {
22828
+ keyId = psshInfo.data.subarray(8, 24);
22829
+ }
22830
+ keySystemDomain = keySystemIdToKeySystemDomain(psshInfo.systemId);
22831
+ }
22832
+ if (!keySystemDomain || !keyId) {
22833
+ return;
22834
+ }
22835
+ var keyIdHex = Hex.hexDump(keyId);
22836
+ var keyIdToKeySessionPromise = this.keyIdToKeySessionPromise,
22837
+ mediaKeySessions = this.mediaKeySessions;
22838
+ var keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex];
22839
+ var _loop = function _loop() {
22840
+ // Match playlist key
22841
+ var keyContext = mediaKeySessions[i];
22842
+ var decryptdata = keyContext.decryptdata;
22843
+ if (decryptdata.pssh || !decryptdata.keyId) {
22844
+ return 0; // continue
22845
+ }
22846
+ var oldKeyIdHex = Hex.hexDump(decryptdata.keyId);
22847
+ if (keyIdHex === oldKeyIdHex || decryptdata.uri.replace(/-/g, '').indexOf(keyIdHex) !== -1) {
22848
+ keySessionContextPromise = keyIdToKeySessionPromise[oldKeyIdHex];
22849
+ delete keyIdToKeySessionPromise[oldKeyIdHex];
22850
+ decryptdata.pssh = new Uint8Array(initData);
22851
+ decryptdata.keyId = keyId;
22852
+ keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = keySessionContextPromise.then(function () {
22853
+ return _this5.generateRequestWithPreferredKeySession(keyContext, initDataType, initData, 'encrypted-event-key-match');
22854
+ });
22855
+ return 1; // break
22856
+ }
22857
+ },
22858
+ _ret;
22859
+ for (var i = 0; i < mediaKeySessions.length; i++) {
22860
+ _ret = _loop();
22861
+ if (_ret === 0) continue;
22862
+ if (_ret === 1) break;
22863
+ }
22864
+ if (!keySessionContextPromise) {
22865
+ // Clear-lead key (not encountered in playlist)
22866
+ keySessionContextPromise = keyIdToKeySessionPromise[keyIdHex] = this.getKeySystemSelectionPromise([keySystemDomain]).then(function (_ref4) {
22867
+ var _keySystemToKeySystem;
22868
+ var keySystem = _ref4.keySystem,
22869
+ mediaKeys = _ref4.mediaKeys;
22870
+ _this5.throwIfDestroyed();
22871
+ var decryptdata = new LevelKey('ISO-23001-7', keyIdHex, (_keySystemToKeySystem = keySystemDomainToKeySystemFormat(keySystem)) != null ? _keySystemToKeySystem : '');
22872
+ decryptdata.pssh = new Uint8Array(initData);
22873
+ decryptdata.keyId = keyId;
22874
+ return _this5.attemptSetMediaKeys(keySystem, mediaKeys).then(function () {
22875
+ _this5.throwIfDestroyed();
22876
+ var keySessionContext = _this5.createMediaKeySessionContext({
22877
+ decryptdata: decryptdata,
22878
+ keySystem: keySystem,
22879
+ mediaKeys: mediaKeys
22880
+ });
22881
+ return _this5.generateRequestWithPreferredKeySession(keySessionContext, initDataType, initData, 'encrypted-event-no-match');
22882
+ });
22883
+ });
22884
+ }
22885
+ keySessionContextPromise.catch(function (error) {
22886
+ return _this5.handleError(error);
22887
+ });
23759
22888
  };
23760
- _proto.getKeySystemSelectionPromise = function getKeySystemSelectionPromise(keySystemsToAttempt) {
23761
- if (!keySystemsToAttempt.length) {
23762
- keySystemsToAttempt = getKeySystemsForConfig(this.config);
23763
- }
23764
- if (keySystemsToAttempt.length === 0) {
23765
- throw new EMEKeyError({
23766
- type: ErrorTypes.KEY_SYSTEM_ERROR,
23767
- details: ErrorDetails.KEY_SYSTEM_NO_CONFIGURED_LICENSE,
23768
- fatal: true
23769
- }, "Missing key-system license configuration options " + JSON.stringify({
23770
- drmSystems: this.config.drmSystems
23771
- }));
23772
- }
23773
- return this.attemptKeySystemAccess(keySystemsToAttempt);
22889
+ _proto._onWaitingForKey = function _onWaitingForKey(event) {
22890
+ this.log("\"" + event.type + "\" event");
23774
22891
  };
23775
22892
  _proto.attemptSetMediaKeys = function attemptSetMediaKeys(keySystem, mediaKeys) {
23776
22893
  var _this6 = this;
@@ -24227,7 +23344,7 @@
24227
23344
  }
24228
23345
  };
24229
23346
  return EMEController;
24230
- }(Logger);
23347
+ }();
24231
23348
  EMEController.CDMCleanupPromise = void 0;
24232
23349
  var EMEKeyError = /*#__PURE__*/function (_Error) {
24233
23350
  _inheritsLoose(EMEKeyError, _Error);
@@ -24375,6 +23492,18 @@
24375
23492
  this.params = params;
24376
23493
  };
24377
23494
 
23495
+ /**
23496
+ * A class to represent structured field tokens when `Symbol` is not available.
23497
+ *
23498
+ * @group Structured Field
23499
+ *
23500
+ * @beta
23501
+ */
23502
+ var SfToken = function SfToken(description) {
23503
+ this.description = void 0;
23504
+ this.description = description;
23505
+ };
23506
+
24378
23507
  var DICT = 'Dict';
24379
23508
 
24380
23509
  function format(value) {
@@ -24398,25 +23527,29 @@
24398
23527
  });
24399
23528
  }
24400
23529
 
24401
- function serializeError(src, type, cause) {
24402
- return throwError('serialize', src, type, cause);
23530
+ var BARE_ITEM = 'Bare Item';
23531
+
23532
+ var BOOLEAN = 'Boolean';
23533
+
23534
+ var BYTES = 'Byte Sequence';
23535
+
23536
+ var DECIMAL = 'Decimal';
23537
+
23538
+ var INTEGER = 'Integer';
23539
+
23540
+ function isInvalidInt(value) {
23541
+ return value < -999999999999999 || 999999999999999 < value;
24403
23542
  }
24404
23543
 
24405
- /**
24406
- * A class to represent structured field tokens when `Symbol` is not available.
24407
- *
24408
- * @group Structured Field
24409
- *
24410
- * @beta
24411
- */
24412
- var SfToken = function SfToken(description) {
24413
- this.description = void 0;
24414
- this.description = description;
24415
- };
23544
+ var STRING_REGEX = /[\x00-\x1f\x7f]+/; // eslint-disable-line no-control-regex
24416
23545
 
24417
- var BARE_ITEM = 'Bare Item';
23546
+ var TOKEN = 'Token';
24418
23547
 
24419
- var BOOLEAN = 'Boolean';
23548
+ var KEY = 'Key';
23549
+
23550
+ function serializeError(src, type, cause) {
23551
+ return throwError('serialize', src, type, cause);
23552
+ }
24420
23553
 
24421
23554
  // 4.1.9. Serializing a Boolean
24422
23555
  //
@@ -24455,8 +23588,6 @@
24455
23588
  return btoa(String.fromCharCode.apply(String, binary));
24456
23589
  }
24457
23590
 
24458
- var BYTES = 'Byte Sequence';
24459
-
24460
23591
  // 4.1.8. Serializing a Byte Sequence
24461
23592
  //
24462
23593
  // Given a Byte Sequence as input_bytes, return an ASCII string suitable
@@ -24488,12 +23619,6 @@
24488
23619
  return ":" + base64encode(value) + ":";
24489
23620
  }
24490
23621
 
24491
- var INTEGER = 'Integer';
24492
-
24493
- function isInvalidInt(value) {
24494
- return value < -999999999999999 || 999999999999999 < value;
24495
- }
24496
-
24497
23622
  // 4.1.4. Serializing an Integer
24498
23623
  //
24499
23624
  // Given an Integer as input_integer, return an ASCII string suitable
@@ -24559,8 +23684,6 @@
24559
23684
  }
24560
23685
  }
24561
23686
 
24562
- var DECIMAL = 'Decimal';
24563
-
24564
23687
  // 4.1.5. Serializing a Decimal
24565
23688
  //
24566
23689
  // Given a decimal number as input_decimal, return an ASCII string
@@ -24606,8 +23729,6 @@
24606
23729
 
24607
23730
  var STRING = 'String';
24608
23731
 
24609
- var STRING_REGEX = /[\x00-\x1f\x7f]+/; // eslint-disable-line no-control-regex
24610
-
24611
23732
  // 4.1.6. Serializing a String
24612
23733
  //
24613
23734
  // Given a String as input_string, return an ASCII string suitable for
@@ -24643,8 +23764,6 @@
24643
23764
  return symbol.description || symbol.toString().slice(7, -1);
24644
23765
  }
24645
23766
 
24646
- var TOKEN = 'Token';
24647
-
24648
23767
  function serializeToken(token) {
24649
23768
  var value = symbolToStr(token);
24650
23769
  if (/^([a-zA-Z*])([!#$%&'*+\-.^_`|~\w:/]*)$/.test(value) === false) {
@@ -24712,8 +23831,6 @@
24712
23831
  }
24713
23832
  }
24714
23833
 
24715
- var KEY = 'Key';
24716
-
24717
23834
  // 4.1.1.3. Serializing a Key
24718
23835
  //
24719
23836
  // Given a key as input_key, return an ASCII string suitable for use in
@@ -24965,6 +24082,36 @@
24965
24082
  return toPath.join('/');
24966
24083
  }
24967
24084
 
24085
+ /**
24086
+ * Generate a random v4 UUID
24087
+ *
24088
+ * @returns A random v4 UUID
24089
+ *
24090
+ * @group Utils
24091
+ *
24092
+ * @beta
24093
+ */
24094
+ function uuid() {
24095
+ try {
24096
+ return crypto.randomUUID();
24097
+ } catch (error) {
24098
+ try {
24099
+ var url = URL.createObjectURL(new Blob());
24100
+ var _uuid = url.toString();
24101
+ URL.revokeObjectURL(url);
24102
+ return _uuid.slice(_uuid.lastIndexOf('/') + 1);
24103
+ } catch (error) {
24104
+ var dt = new Date().getTime();
24105
+ var _uuid2 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
24106
+ var r = (dt + Math.random() * 16) % 16 | 0;
24107
+ dt = Math.floor(dt / 16);
24108
+ return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
24109
+ });
24110
+ return _uuid2;
24111
+ }
24112
+ }
24113
+ }
24114
+
24968
24115
  var toRounded = function toRounded(value) {
24969
24116
  return Math.round(value);
24970
24117
  };
@@ -25209,36 +24356,6 @@
25209
24356
  return "" + url + separator + query;
25210
24357
  }
25211
24358
 
25212
- /**
25213
- * Generate a random v4 UUID
25214
- *
25215
- * @returns A random v4 UUID
25216
- *
25217
- * @group Utils
25218
- *
25219
- * @beta
25220
- */
25221
- function uuid() {
25222
- try {
25223
- return crypto.randomUUID();
25224
- } catch (error) {
25225
- try {
25226
- var url = URL.createObjectURL(new Blob());
25227
- var _uuid = url.toString();
25228
- URL.revokeObjectURL(url);
25229
- return _uuid.slice(_uuid.lastIndexOf('/') + 1);
25230
- } catch (error) {
25231
- var dt = new Date().getTime();
25232
- var _uuid2 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
25233
- var r = (dt + Math.random() * 16) % 16 | 0;
25234
- dt = Math.floor(dt / 16);
25235
- return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
25236
- });
25237
- return _uuid2;
25238
- }
25239
- }
25240
- }
25241
-
25242
24359
  /**
25243
24360
  * Controller to deal with Common Media Client Data (CMCD)
25244
24361
  * @see https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf
@@ -25283,7 +24400,7 @@
25283
24400
  su: !_this.initialized
25284
24401
  });
25285
24402
  } catch (error) {
25286
- _this.hls.logger.warn('Could not generate manifest CMCD data.', error);
24403
+ logger.warn('Could not generate manifest CMCD data.', error);
25287
24404
  }
25288
24405
  };
25289
24406
  /**
@@ -25303,15 +24420,9 @@
25303
24420
  data.tb = _this.getTopBandwidth(ot) / 1000;
25304
24421
  data.bl = _this.getBufferLength(ot);
25305
24422
  }
25306
- var next = _this.getNextFrag(fragment);
25307
- if (next) {
25308
- if (next.url && next.url !== fragment.url) {
25309
- data.nor = next.url;
25310
- }
25311
- }
25312
24423
  _this.apply(context, data);
25313
24424
  } catch (error) {
25314
- _this.hls.logger.warn('Could not generate segment CMCD data.', error);
24425
+ logger.warn('Could not generate segment CMCD data.', error);
25315
24426
  }
25316
24427
  };
25317
24428
  this.hls = hls;
@@ -25403,7 +24514,7 @@
25403
24514
  data.su = this.buffering;
25404
24515
  }
25405
24516
 
25406
- // TODO: Implement rtp, nrr, dl
24517
+ // TODO: Implement rtp, nrr, nor, dl
25407
24518
 
25408
24519
  var includeKeys = this.includeKeys;
25409
24520
  if (includeKeys) {
@@ -25412,31 +24523,18 @@
25412
24523
  return acc;
25413
24524
  }, {});
25414
24525
  }
25415
- var options = {
25416
- baseUrl: context.url
25417
- };
25418
24526
  if (this.useHeaders) {
25419
24527
  if (!context.headers) {
25420
24528
  context.headers = {};
25421
24529
  }
25422
- appendCmcdHeaders(context.headers, data, options);
24530
+ appendCmcdHeaders(context.headers, data);
25423
24531
  } else {
25424
- context.url = appendCmcdQuery(context.url, data, options);
24532
+ context.url = appendCmcdQuery(context.url, data);
25425
24533
  }
25426
24534
  };
25427
- _proto.getNextFrag = function getNextFrag(fragment) {
25428
- var _this$hls$levels$frag;
25429
- var levelDetails = (_this$hls$levels$frag = this.hls.levels[fragment.level]) == null ? void 0 : _this$hls$levels$frag.details;
25430
- if (levelDetails) {
25431
- var index = fragment.sn - levelDetails.startSN;
25432
- return levelDetails.fragments[index + 1];
25433
- }
25434
- return undefined;
25435
- }
25436
-
25437
24535
  /**
25438
24536
  * The CMCD object type.
25439
- */;
24537
+ */
25440
24538
  _proto.getObjectType = function getObjectType(fragment) {
25441
24539
  var type = fragment.type;
25442
24540
  if (type === 'subtitle') {
@@ -25572,28 +24670,26 @@
25572
24670
  }();
25573
24671
 
25574
24672
  var PATHWAY_PENALTY_DURATION_MS = 300000;
25575
- var ContentSteeringController = /*#__PURE__*/function (_Logger) {
25576
- _inheritsLoose(ContentSteeringController, _Logger);
24673
+ var ContentSteeringController = /*#__PURE__*/function () {
25577
24674
  function ContentSteeringController(hls) {
25578
- var _this;
25579
- _this = _Logger.call(this, 'content-steering', hls.logger) || this;
25580
- _this.hls = void 0;
25581
- _this.loader = null;
25582
- _this.uri = null;
25583
- _this.pathwayId = '.';
25584
- _this.pathwayPriority = null;
25585
- _this.timeToLoad = 300;
25586
- _this.reloadTimer = -1;
25587
- _this.updated = 0;
25588
- _this.started = false;
25589
- _this.enabled = true;
25590
- _this.levels = null;
25591
- _this.audioTracks = null;
25592
- _this.subtitleTracks = null;
25593
- _this.penalizedPathways = {};
25594
- _this.hls = hls;
25595
- _this.registerListeners();
25596
- return _this;
24675
+ this.hls = void 0;
24676
+ this.log = void 0;
24677
+ this.loader = null;
24678
+ this.uri = null;
24679
+ this.pathwayId = '.';
24680
+ this.pathwayPriority = null;
24681
+ this.timeToLoad = 300;
24682
+ this.reloadTimer = -1;
24683
+ this.updated = 0;
24684
+ this.started = false;
24685
+ this.enabled = true;
24686
+ this.levels = null;
24687
+ this.audioTracks = null;
24688
+ this.subtitleTracks = null;
24689
+ this.penalizedPathways = {};
24690
+ this.hls = hls;
24691
+ this.log = logger.log.bind(logger, "[content-steering]:");
24692
+ this.registerListeners();
25597
24693
  }
25598
24694
  var _proto = ContentSteeringController.prototype;
25599
24695
  _proto.registerListeners = function registerListeners() {
@@ -25714,7 +24810,7 @@
25714
24810
  errorAction.resolved = this.pathwayId !== errorPathway;
25715
24811
  }
25716
24812
  if (!errorAction.resolved) {
25717
- 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));
24813
+ logger.warn("Could not resolve " + data.details + " (\"" + data.error.message + "\") with content-steering for Pathway: " + errorPathway + " levels: " + (levels ? levels.length : levels) + " priorities: " + JSON.stringify(pathwayPriority) + " penalized: " + JSON.stringify(this.penalizedPathways));
25718
24814
  }
25719
24815
  }
25720
24816
  };
@@ -25794,7 +24890,7 @@
25794
24890
  return defaultPathway;
25795
24891
  };
25796
24892
  _proto.clonePathways = function clonePathways(pathwayClones) {
25797
- var _this2 = this;
24893
+ var _this = this;
25798
24894
  var levels = this.levels;
25799
24895
  if (!levels) {
25800
24896
  return;
@@ -25810,7 +24906,7 @@
25810
24906
  })) {
25811
24907
  return;
25812
24908
  }
25813
- var clonedVariants = _this2.getLevelsForPathway(baseId).map(function (baseLevel) {
24909
+ var clonedVariants = _this.getLevelsForPathway(baseId).map(function (baseLevel) {
25814
24910
  var attributes = new AttrList(baseLevel.attrs);
25815
24911
  attributes['PATHWAY-ID'] = cloneId;
25816
24912
  var clonedAudioGroupId = attributes.AUDIO && attributes.AUDIO + "_clone_" + cloneId;
@@ -25847,12 +24943,12 @@
25847
24943
  return clonedLevel;
25848
24944
  });
25849
24945
  levels.push.apply(levels, clonedVariants);
25850
- cloneRenditionGroups(_this2.audioTracks, audioGroupCloneMap, uriReplacement, cloneId);
25851
- cloneRenditionGroups(_this2.subtitleTracks, subtitleGroupCloneMap, uriReplacement, cloneId);
24946
+ cloneRenditionGroups(_this.audioTracks, audioGroupCloneMap, uriReplacement, cloneId);
24947
+ cloneRenditionGroups(_this.subtitleTracks, subtitleGroupCloneMap, uriReplacement, cloneId);
25852
24948
  });
25853
24949
  };
25854
24950
  _proto.loadSteeringManifest = function loadSteeringManifest(uri) {
25855
- var _this3 = this;
24951
+ var _this2 = this;
25856
24952
  var config = this.hls.config;
25857
24953
  var Loader = config.loader;
25858
24954
  if (this.loader) {
@@ -25887,87 +24983,87 @@
25887
24983
  };
25888
24984
  var callbacks = {
25889
24985
  onSuccess: function onSuccess(response, stats, context, networkDetails) {
25890
- _this3.log("Loaded steering manifest: \"" + url + "\"");
24986
+ _this2.log("Loaded steering manifest: \"" + url + "\"");
25891
24987
  var steeringData = response.data;
25892
- if ((steeringData == null ? void 0 : steeringData.VERSION) !== 1) {
25893
- _this3.log("Steering VERSION " + steeringData.VERSION + " not supported!");
24988
+ if (steeringData.VERSION !== 1) {
24989
+ _this2.log("Steering VERSION " + steeringData.VERSION + " not supported!");
25894
24990
  return;
25895
24991
  }
25896
- _this3.updated = performance.now();
25897
- _this3.timeToLoad = steeringData.TTL;
24992
+ _this2.updated = performance.now();
24993
+ _this2.timeToLoad = steeringData.TTL;
25898
24994
  var reloadUri = steeringData['RELOAD-URI'],
25899
24995
  pathwayClones = steeringData['PATHWAY-CLONES'],
25900
24996
  pathwayPriority = steeringData['PATHWAY-PRIORITY'];
25901
24997
  if (reloadUri) {
25902
24998
  try {
25903
- _this3.uri = new self.URL(reloadUri, url).href;
24999
+ _this2.uri = new self.URL(reloadUri, url).href;
25904
25000
  } catch (error) {
25905
- _this3.enabled = false;
25906
- _this3.log("Failed to parse Steering Manifest RELOAD-URI: " + reloadUri);
25001
+ _this2.enabled = false;
25002
+ _this2.log("Failed to parse Steering Manifest RELOAD-URI: " + reloadUri);
25907
25003
  return;
25908
25004
  }
25909
25005
  }
25910
- _this3.scheduleRefresh(_this3.uri || context.url);
25006
+ _this2.scheduleRefresh(_this2.uri || context.url);
25911
25007
  if (pathwayClones) {
25912
- _this3.clonePathways(pathwayClones);
25008
+ _this2.clonePathways(pathwayClones);
25913
25009
  }
25914
25010
  var loadedSteeringData = {
25915
25011
  steeringManifest: steeringData,
25916
25012
  url: url.toString()
25917
25013
  };
25918
- _this3.hls.trigger(Events.STEERING_MANIFEST_LOADED, loadedSteeringData);
25014
+ _this2.hls.trigger(Events.STEERING_MANIFEST_LOADED, loadedSteeringData);
25919
25015
  if (pathwayPriority) {
25920
- _this3.updatePathwayPriority(pathwayPriority);
25016
+ _this2.updatePathwayPriority(pathwayPriority);
25921
25017
  }
25922
25018
  },
25923
25019
  onError: function onError(error, context, networkDetails, stats) {
25924
- _this3.log("Error loading steering manifest: " + error.code + " " + error.text + " (" + context.url + ")");
25925
- _this3.stopLoad();
25020
+ _this2.log("Error loading steering manifest: " + error.code + " " + error.text + " (" + context.url + ")");
25021
+ _this2.stopLoad();
25926
25022
  if (error.code === 410) {
25927
- _this3.enabled = false;
25928
- _this3.log("Steering manifest " + context.url + " no longer available");
25023
+ _this2.enabled = false;
25024
+ _this2.log("Steering manifest " + context.url + " no longer available");
25929
25025
  return;
25930
25026
  }
25931
- var ttl = _this3.timeToLoad * 1000;
25027
+ var ttl = _this2.timeToLoad * 1000;
25932
25028
  if (error.code === 429) {
25933
- var loader = _this3.loader;
25029
+ var loader = _this2.loader;
25934
25030
  if (typeof (loader == null ? void 0 : loader.getResponseHeader) === 'function') {
25935
25031
  var retryAfter = loader.getResponseHeader('Retry-After');
25936
25032
  if (retryAfter) {
25937
25033
  ttl = parseFloat(retryAfter) * 1000;
25938
25034
  }
25939
25035
  }
25940
- _this3.log("Steering manifest " + context.url + " rate limited");
25036
+ _this2.log("Steering manifest " + context.url + " rate limited");
25941
25037
  return;
25942
25038
  }
25943
- _this3.scheduleRefresh(_this3.uri || context.url, ttl);
25039
+ _this2.scheduleRefresh(_this2.uri || context.url, ttl);
25944
25040
  },
25945
25041
  onTimeout: function onTimeout(stats, context, networkDetails) {
25946
- _this3.log("Timeout loading steering manifest (" + context.url + ")");
25947
- _this3.scheduleRefresh(_this3.uri || context.url);
25042
+ _this2.log("Timeout loading steering manifest (" + context.url + ")");
25043
+ _this2.scheduleRefresh(_this2.uri || context.url);
25948
25044
  }
25949
25045
  };
25950
25046
  this.log("Requesting steering manifest: " + url);
25951
25047
  this.loader.load(context, loaderConfig, callbacks);
25952
25048
  };
25953
25049
  _proto.scheduleRefresh = function scheduleRefresh(uri, ttlMs) {
25954
- var _this4 = this;
25050
+ var _this3 = this;
25955
25051
  if (ttlMs === void 0) {
25956
25052
  ttlMs = this.timeToLoad * 1000;
25957
25053
  }
25958
25054
  this.clearTimeout();
25959
25055
  this.reloadTimer = self.setTimeout(function () {
25960
- var _this4$hls;
25961
- var media = (_this4$hls = _this4.hls) == null ? void 0 : _this4$hls.media;
25056
+ var _this3$hls;
25057
+ var media = (_this3$hls = _this3.hls) == null ? void 0 : _this3$hls.media;
25962
25058
  if (media && !media.ended) {
25963
- _this4.loadSteeringManifest(uri);
25059
+ _this3.loadSteeringManifest(uri);
25964
25060
  return;
25965
25061
  }
25966
- _this4.scheduleRefresh(uri, _this4.timeToLoad * 1000);
25062
+ _this3.scheduleRefresh(uri, _this3.timeToLoad * 1000);
25967
25063
  }, ttlMs);
25968
25064
  };
25969
25065
  return ContentSteeringController;
25970
- }(Logger);
25066
+ }();
25971
25067
  function cloneRenditionGroups(tracks, groupCloneMap, uriReplacement, cloneId) {
25972
25068
  if (!tracks) {
25973
25069
  return;
@@ -26867,7 +25963,7 @@
26867
25963
  /**
26868
25964
  * @ignore
26869
25965
  */
26870
- function mergeConfig(defaultConfig, userConfig, logger) {
25966
+ function mergeConfig(defaultConfig, userConfig) {
26871
25967
  if ((userConfig.liveSyncDurationCount || userConfig.liveMaxLatencyDurationCount) && (userConfig.liveSyncDuration || userConfig.liveMaxLatencyDuration)) {
26872
25968
  throw new Error("Illegal hls.js config: don't mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration");
26873
25969
  }
@@ -26937,7 +26033,7 @@
26937
26033
  /**
26938
26034
  * @ignore
26939
26035
  */
26940
- function enableStreamingMode(config, logger) {
26036
+ function enableStreamingMode(config) {
26941
26037
  var currentLoader = config.loader;
26942
26038
  if (currentLoader !== FetchLoader && currentLoader !== XhrLoader) {
26943
26039
  // If a developer has configured their own loader, respect that choice
@@ -26954,11 +26050,12 @@
26954
26050
  }
26955
26051
  }
26956
26052
 
26053
+ var chromeOrFirefox;
26957
26054
  var LevelController = /*#__PURE__*/function (_BasePlaylistControll) {
26958
26055
  _inheritsLoose(LevelController, _BasePlaylistControll);
26959
26056
  function LevelController(hls, contentSteeringController) {
26960
26057
  var _this;
26961
- _this = _BasePlaylistControll.call(this, hls, 'level-controller') || this;
26058
+ _this = _BasePlaylistControll.call(this, hls, '[level-controller]') || this;
26962
26059
  _this._levels = [];
26963
26060
  _this._firstLevel = -1;
26964
26061
  _this._maxAutoLevel = -1;
@@ -27027,13 +26124,21 @@
27027
26124
  var videoCodecFound = false;
27028
26125
  var audioCodecFound = false;
27029
26126
  data.levels.forEach(function (levelParsed) {
27030
- var _videoCodec;
26127
+ var _audioCodec, _videoCodec;
27031
26128
  var attributes = levelParsed.attrs;
26129
+
26130
+ // erase audio codec info if browser does not support mp4a.40.34.
26131
+ // demuxer will autodetect codec and fallback to mpeg/audio
27032
26132
  var audioCodec = levelParsed.audioCodec,
27033
26133
  videoCodec = levelParsed.videoCodec;
26134
+ if (((_audioCodec = audioCodec) == null ? void 0 : _audioCodec.indexOf('mp4a.40.34')) !== -1) {
26135
+ chromeOrFirefox || (chromeOrFirefox = /chrome|firefox/i.test(navigator.userAgent));
26136
+ if (chromeOrFirefox) {
26137
+ levelParsed.audioCodec = audioCodec = undefined;
26138
+ }
26139
+ }
27034
26140
  if (audioCodec) {
27035
- // Returns empty and set to undefined for 'mp4a.40.34' with fallback to 'audio/mpeg' SourceBuffer
27036
- levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource) || undefined;
26141
+ levelParsed.audioCodec = audioCodec = getCodecCompatibleName(audioCodec, preferManagedMediaSource);
27037
26142
  }
27038
26143
  if (((_videoCodec = videoCodec) == null ? void 0 : _videoCodec.indexOf('avc1')) === 0) {
27039
26144
  videoCodec = levelParsed.videoCodec = convertAVC1ToAVCOTI(videoCodec);
@@ -27265,12 +26370,7 @@
27265
26370
  if (curLevel.fragmentError === 0) {
27266
26371
  curLevel.loadError = 0;
27267
26372
  }
27268
- // Ignore matching details populated by loading a Media Playlist directly
27269
- var previousDetails = curLevel.details;
27270
- if (previousDetails === data.details && previousDetails.advanced) {
27271
- previousDetails = undefined;
27272
- }
27273
- this.playlistLoaded(level, data, previousDetails);
26373
+ this.playlistLoaded(level, data, curLevel.details);
27274
26374
  } else if ((_data$deliveryDirecti2 = data.deliveryDirectives) != null && _data$deliveryDirecti2.skip) {
27275
26375
  // received a delta playlist update that cannot be merged
27276
26376
  details.deltaUpdateFailed = true;
@@ -27646,8 +26746,6 @@
27646
26746
  }
27647
26747
  return this.loadKeyEME(keyInfo, frag);
27648
26748
  case 'AES-128':
27649
- case 'AES-256':
27650
- case 'AES-256-CTR':
27651
26749
  return this.loadKeyHTTP(keyInfo, frag);
27652
26750
  default:
27653
26751
  return Promise.reject(this.createKeyLoadError(frag, ErrorDetails.KEY_LOAD_ERROR, new Error("Key supplied with unsupported METHOD: \"" + decryptdata.method + "\"")));
@@ -27787,26 +26885,21 @@
27787
26885
  var MAX_START_GAP_JUMP = 2.0;
27788
26886
  var SKIP_BUFFER_HOLE_STEP_SECONDS = 0.1;
27789
26887
  var SKIP_BUFFER_RANGE_START = 0.05;
27790
- var GapController = /*#__PURE__*/function (_Logger) {
27791
- _inheritsLoose(GapController, _Logger);
26888
+ var GapController = /*#__PURE__*/function () {
27792
26889
  function GapController(config, media, fragmentTracker, hls) {
27793
- var _this;
27794
- _this = _Logger.call(this, 'gap-controller', hls.logger) || this;
27795
- _this.config = void 0;
27796
- _this.media = null;
27797
- _this.fragmentTracker = void 0;
27798
- _this.hls = void 0;
27799
- _this.nudgeRetry = 0;
27800
- _this.stallReported = false;
27801
- _this.stalled = null;
27802
- _this.moved = false;
27803
- _this.seeking = false;
27804
- _this.ended = 0;
27805
- _this.config = config;
27806
- _this.media = media;
27807
- _this.fragmentTracker = fragmentTracker;
27808
- _this.hls = hls;
27809
- return _this;
26890
+ this.config = void 0;
26891
+ this.media = null;
26892
+ this.fragmentTracker = void 0;
26893
+ this.hls = void 0;
26894
+ this.nudgeRetry = 0;
26895
+ this.stallReported = false;
26896
+ this.stalled = null;
26897
+ this.moved = false;
26898
+ this.seeking = false;
26899
+ this.config = config;
26900
+ this.media = media;
26901
+ this.fragmentTracker = fragmentTracker;
26902
+ this.hls = hls;
27810
26903
  }
27811
26904
  var _proto = GapController.prototype;
27812
26905
  _proto.destroy = function destroy() {
@@ -27821,7 +26914,7 @@
27821
26914
  *
27822
26915
  * @param lastCurrentTime - Previously read playhead position
27823
26916
  */;
27824
- _proto.poll = function poll(lastCurrentTime, activeFrag, levelDetails, state) {
26917
+ _proto.poll = function poll(lastCurrentTime, activeFrag) {
27825
26918
  var config = this.config,
27826
26919
  media = this.media,
27827
26920
  stalled = this.stalled;
@@ -27836,7 +26929,6 @@
27836
26929
 
27837
26930
  // The playhead is moving, no-op
27838
26931
  if (currentTime !== lastCurrentTime) {
27839
- this.ended = 0;
27840
26932
  this.moved = true;
27841
26933
  if (!seeking) {
27842
26934
  this.nudgeRetry = 0;
@@ -27845,7 +26937,7 @@
27845
26937
  // The playhead is now moving, but was previously stalled
27846
26938
  if (this.stallReported) {
27847
26939
  var _stalledDuration = self.performance.now() - stalled;
27848
- this.warn("playback not stuck anymore @" + currentTime + ", after " + Math.round(_stalledDuration) + "ms");
26940
+ logger.warn("playback not stuck anymore @" + currentTime + ", after " + Math.round(_stalledDuration) + "ms");
27849
26941
  this.stallReported = false;
27850
26942
  }
27851
26943
  this.stalled = null;
@@ -27881,6 +26973,7 @@
27881
26973
  // Skip start gaps if we haven't played, but the last poll detected the start of a stall
27882
26974
  // The addition poll gives the browser a chance to jump the gap for us
27883
26975
  if (!this.moved && this.stalled !== null) {
26976
+ var _level$details;
27884
26977
  // There is no playable buffer (seeked, waiting for buffer)
27885
26978
  var isBuffered = bufferInfo.len > 0;
27886
26979
  if (!isBuffered && !nextStart) {
@@ -27892,8 +26985,9 @@
27892
26985
  // When joining a live stream with audio tracks, account for live playlist window sliding by allowing
27893
26986
  // a larger jump over start gaps caused by the audio-stream-controller buffering a start fragment
27894
26987
  // that begins over 1 target duration after the video start position.
27895
- var isLive = !!(levelDetails != null && levelDetails.live);
27896
- var maxStartGapJump = isLive ? levelDetails.targetduration * 2 : MAX_START_GAP_JUMP;
26988
+ var level = this.hls.levels ? this.hls.levels[this.hls.currentLevel] : null;
26989
+ var isLive = level == null ? void 0 : (_level$details = level.details) == null ? void 0 : _level$details.live;
26990
+ var maxStartGapJump = isLive ? level.details.targetduration * 2 : MAX_START_GAP_JUMP;
27897
26991
  var partialOrGap = this.fragmentTracker.getPartialFragment(currentTime);
27898
26992
  if (startJump > 0 && (startJump <= maxStartGapJump || partialOrGap)) {
27899
26993
  if (!media.paused) {
@@ -27911,17 +27005,6 @@
27911
27005
  }
27912
27006
  var stalledDuration = tnow - stalled;
27913
27007
  if (!seeking && stalledDuration >= STALL_MINIMUM_DURATION_MS) {
27914
- // Dispatch MEDIA_ENDED when media.ended/ended event is not signalled at end of stream
27915
- if (state === State.ENDED && !(levelDetails && levelDetails.live) && Math.abs(currentTime - ((levelDetails == null ? void 0 : levelDetails.edge) || 0)) < 1) {
27916
- if (stalledDuration < 1000 || this.ended) {
27917
- return;
27918
- }
27919
- this.ended = currentTime;
27920
- this.hls.trigger(Events.MEDIA_ENDED, {
27921
- stalled: true
27922
- });
27923
- return;
27924
- }
27925
27008
  // Report stalling after trying to fix
27926
27009
  this._reportStall(bufferInfo);
27927
27010
  if (!this.media) {
@@ -27963,7 +27046,7 @@
27963
27046
  // needs to cross some sort of threshold covering all source-buffers content
27964
27047
  // to start playing properly.
27965
27048
  if ((bufferInfo.len > config.maxBufferHole || bufferInfo.nextStart && bufferInfo.nextStart - currentTime < config.maxBufferHole) && stalledDurationMs > config.highBufferWatchdogPeriod * 1000) {
27966
- this.warn('Trying to nudge playhead over buffer-hole');
27049
+ logger.warn('Trying to nudge playhead over buffer-hole');
27967
27050
  // Try to nudge currentTime over a buffer hole if we've been stalling for the configured amount of seconds
27968
27051
  // We only try to jump the hole if it's under the configured size
27969
27052
  // Reset stalled so to rearm watchdog timer
@@ -27985,7 +27068,7 @@
27985
27068
  // Report stalled error once
27986
27069
  this.stallReported = true;
27987
27070
  var error = new Error("Playback stalling at @" + media.currentTime + " due to low buffer (" + JSON.stringify(bufferInfo) + ")");
27988
- this.warn(error.message);
27071
+ logger.warn(error.message);
27989
27072
  hls.trigger(Events.ERROR, {
27990
27073
  type: ErrorTypes.MEDIA_ERROR,
27991
27074
  details: ErrorDetails.BUFFER_STALLED_ERROR,
@@ -28049,7 +27132,7 @@
28049
27132
  }
28050
27133
  }
28051
27134
  var targetTime = Math.max(startTime + SKIP_BUFFER_RANGE_START, currentTime + SKIP_BUFFER_HOLE_STEP_SECONDS);
28052
- this.warn("skipping hole, adjusting currentTime from " + currentTime + " to " + targetTime);
27135
+ logger.warn("skipping hole, adjusting currentTime from " + currentTime + " to " + targetTime);
28053
27136
  this.moved = true;
28054
27137
  this.stalled = null;
28055
27138
  media.currentTime = targetTime;
@@ -28088,7 +27171,7 @@
28088
27171
  var targetTime = currentTime + (nudgeRetry + 1) * config.nudgeOffset;
28089
27172
  // playback stalled in buffered area ... let's nudge currentTime to try to overcome this
28090
27173
  var error = new Error("Nudging 'currentTime' from " + currentTime + " to " + targetTime);
28091
- this.warn(error.message);
27174
+ logger.warn(error.message);
28092
27175
  media.currentTime = targetTime;
28093
27176
  hls.trigger(Events.ERROR, {
28094
27177
  type: ErrorTypes.MEDIA_ERROR,
@@ -28098,7 +27181,7 @@
28098
27181
  });
28099
27182
  } else {
28100
27183
  var _error = new Error("Playhead still not moving while enough data buffered @" + currentTime + " after " + config.nudgeMaxRetry + " nudges");
28101
- this.error(_error.message);
27184
+ logger.error(_error.message);
28102
27185
  hls.trigger(Events.ERROR, {
28103
27186
  type: ErrorTypes.MEDIA_ERROR,
28104
27187
  details: ErrorDetails.BUFFER_STALLED_ERROR,
@@ -28108,14 +27191,14 @@
28108
27191
  }
28109
27192
  };
28110
27193
  return GapController;
28111
- }(Logger);
27194
+ }();
28112
27195
 
28113
27196
  var TICK_INTERVAL = 100; // how often to tick in ms
28114
27197
  var StreamController = /*#__PURE__*/function (_BaseStreamController) {
28115
27198
  _inheritsLoose(StreamController, _BaseStreamController);
28116
27199
  function StreamController(hls, fragmentTracker, keyLoader) {
28117
27200
  var _this;
28118
- _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, 'stream-controller', PlaylistLevelType.MAIN) || this;
27201
+ _this = _BaseStreamController.call(this, hls, fragmentTracker, keyLoader, '[stream-controller]', PlaylistLevelType.MAIN) || this;
28119
27202
  _this.audioCodecSwap = false;
28120
27203
  _this.gapController = null;
28121
27204
  _this.level = -1;
@@ -28123,43 +27206,27 @@
28123
27206
  _this.altAudio = false;
28124
27207
  _this.audioOnly = false;
28125
27208
  _this.fragPlaying = null;
27209
+ _this.onvplaying = null;
27210
+ _this.onvseeked = null;
28126
27211
  _this.fragLastKbps = 0;
28127
27212
  _this.couldBacktrack = false;
28128
27213
  _this.backtrackFragment = null;
28129
27214
  _this.audioCodecSwitch = false;
28130
27215
  _this.videoBuffer = null;
28131
- _this.onMediaPlaying = function () {
28132
- // tick to speed up FRAG_CHANGED triggering
28133
- _this.tick();
28134
- };
28135
- _this.onMediaSeeked = function () {
28136
- var media = _this.media;
28137
- var currentTime = media ? media.currentTime : null;
28138
- if (isFiniteNumber(currentTime)) {
28139
- _this.log("Media seeked to " + currentTime.toFixed(3));
28140
- }
28141
-
28142
- // If seeked was issued before buffer was appended do not tick immediately
28143
- var bufferInfo = _this.getMainFwdBufferInfo();
28144
- if (bufferInfo === null || bufferInfo.len === 0) {
28145
- _this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
28146
- return;
28147
- }
28148
-
28149
- // tick to speed up FRAG_CHANGED triggering
28150
- _this.tick();
28151
- };
28152
- _this.registerListeners();
27216
+ _this._registerListeners();
28153
27217
  return _this;
28154
27218
  }
28155
27219
  var _proto = StreamController.prototype;
28156
- _proto.registerListeners = function registerListeners() {
28157
- _BaseStreamController.prototype.registerListeners.call(this);
27220
+ _proto._registerListeners = function _registerListeners() {
28158
27221
  var hls = this.hls;
27222
+ hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
27223
+ hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
27224
+ hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
28159
27225
  hls.on(Events.MANIFEST_PARSED, this.onManifestParsed, this);
28160
27226
  hls.on(Events.LEVEL_LOADING, this.onLevelLoading, this);
28161
27227
  hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
28162
27228
  hls.on(Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this);
27229
+ hls.on(Events.ERROR, this.onError, this);
28163
27230
  hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
28164
27231
  hls.on(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
28165
27232
  hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
@@ -28167,12 +27234,15 @@
28167
27234
  hls.on(Events.LEVELS_UPDATED, this.onLevelsUpdated, this);
28168
27235
  hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
28169
27236
  };
28170
- _proto.unregisterListeners = function unregisterListeners() {
28171
- _BaseStreamController.prototype.unregisterListeners.call(this);
27237
+ _proto._unregisterListeners = function _unregisterListeners() {
28172
27238
  var hls = this.hls;
27239
+ hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
27240
+ hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
27241
+ hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
28173
27242
  hls.off(Events.MANIFEST_PARSED, this.onManifestParsed, this);
28174
27243
  hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
28175
27244
  hls.off(Events.FRAG_LOAD_EMERGENCY_ABORTED, this.onFragLoadEmergencyAborted, this);
27245
+ hls.off(Events.ERROR, this.onError, this);
28176
27246
  hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
28177
27247
  hls.off(Events.AUDIO_TRACK_SWITCHED, this.onAudioTrackSwitched, this);
28178
27248
  hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
@@ -28181,9 +27251,7 @@
28181
27251
  hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);
28182
27252
  };
28183
27253
  _proto.onHandlerDestroying = function onHandlerDestroying() {
28184
- // @ts-ignore
28185
- this.onMediaPlaying = this.onMediaSeeked = null;
28186
- this.unregisterListeners();
27254
+ this._unregisterListeners();
28187
27255
  _BaseStreamController.prototype.onHandlerDestroying.call(this);
28188
27256
  };
28189
27257
  _proto.startLoad = function startLoad(startPosition) {
@@ -28293,7 +27361,7 @@
28293
27361
  if (this.altAudio && this.audioOnly) {
28294
27362
  return;
28295
27363
  }
28296
- if (!this.buffering || !(levels != null && levels[level])) {
27364
+ if (!(levels != null && levels[level])) {
28297
27365
  return;
28298
27366
  }
28299
27367
  var levelInfo = levels[level];
@@ -28499,15 +27567,18 @@
28499
27567
  _proto.onMediaAttached = function onMediaAttached(event, data) {
28500
27568
  _BaseStreamController.prototype.onMediaAttached.call(this, event, data);
28501
27569
  var media = data.media;
28502
- media.addEventListener('playing', this.onMediaPlaying);
28503
- media.addEventListener('seeked', this.onMediaSeeked);
27570
+ this.onvplaying = this.onMediaPlaying.bind(this);
27571
+ this.onvseeked = this.onMediaSeeked.bind(this);
27572
+ media.addEventListener('playing', this.onvplaying);
27573
+ media.addEventListener('seeked', this.onvseeked);
28504
27574
  this.gapController = new GapController(this.config, media, this.fragmentTracker, this.hls);
28505
27575
  };
28506
27576
  _proto.onMediaDetaching = function onMediaDetaching() {
28507
27577
  var media = this.media;
28508
- if (media) {
28509
- media.removeEventListener('playing', this.onMediaPlaying);
28510
- media.removeEventListener('seeked', this.onMediaSeeked);
27578
+ if (media && this.onvplaying && this.onvseeked) {
27579
+ media.removeEventListener('playing', this.onvplaying);
27580
+ media.removeEventListener('seeked', this.onvseeked);
27581
+ this.onvplaying = this.onvseeked = null;
28511
27582
  this.videoBuffer = null;
28512
27583
  }
28513
27584
  this.fragPlaying = null;
@@ -28517,6 +27588,27 @@
28517
27588
  }
28518
27589
  _BaseStreamController.prototype.onMediaDetaching.call(this);
28519
27590
  };
27591
+ _proto.onMediaPlaying = function onMediaPlaying() {
27592
+ // tick to speed up FRAG_CHANGED triggering
27593
+ this.tick();
27594
+ };
27595
+ _proto.onMediaSeeked = function onMediaSeeked() {
27596
+ var media = this.media;
27597
+ var currentTime = media ? media.currentTime : null;
27598
+ if (isFiniteNumber(currentTime)) {
27599
+ this.log("Media seeked to " + currentTime.toFixed(3));
27600
+ }
27601
+
27602
+ // If seeked was issued before buffer was appended do not tick immediately
27603
+ var bufferInfo = this.getMainFwdBufferInfo();
27604
+ if (bufferInfo === null || bufferInfo.len === 0) {
27605
+ this.warn("Main forward buffer length on \"seeked\" event " + (bufferInfo ? bufferInfo.len : 'empty') + ")");
27606
+ return;
27607
+ }
27608
+
27609
+ // tick to speed up FRAG_CHANGED triggering
27610
+ this.tick();
27611
+ };
28520
27612
  _proto.onManifestLoading = function onManifestLoading() {
28521
27613
  // reset buffer on manifest loading
28522
27614
  this.log('Trigger BUFFER_RESET');
@@ -28797,10 +27889,8 @@
28797
27889
  }
28798
27890
  if (this.loadedmetadata || !BufferHelper.getBuffered(media).length) {
28799
27891
  // Resolve gaps using the main buffer, whose ranges are the intersections of the A/V sourcebuffers
28800
- var state = this.state;
28801
- var activeFrag = state !== State.IDLE ? this.fragCurrent : null;
28802
- var levelDetails = this.getLevelDetails();
28803
- gapController.poll(this.lastCurrentTime, activeFrag, levelDetails, state);
27892
+ var activeFrag = this.state !== State.IDLE ? this.fragCurrent : null;
27893
+ gapController.poll(this.lastCurrentTime, activeFrag);
28804
27894
  }
28805
27895
  this.lastCurrentTime = media.currentTime;
28806
27896
  };
@@ -29265,12 +28355,9 @@
29265
28355
  * The configuration object provided on player instantiation.
29266
28356
  */
29267
28357
  this.userConfig = void 0;
29268
- /**
29269
- * The logger functions used by this player instance, configured on player instantiation.
29270
- */
29271
- this.logger = void 0;
29272
28358
  this.coreComponents = void 0;
29273
28359
  this.networkControllers = void 0;
28360
+ this.started = false;
29274
28361
  this._emitter = new EventEmitter();
29275
28362
  this._autoLevelCapping = -1;
29276
28363
  this._maxHdcpLevel = null;
@@ -29287,11 +28374,11 @@
29287
28374
  this._media = null;
29288
28375
  this.url = null;
29289
28376
  this.triggeringException = void 0;
29290
- var logger = this.logger = enableLogs(userConfig.debug || false, 'Hls instance');
29291
- var config = this.config = mergeConfig(Hls.DefaultConfig, userConfig, logger);
28377
+ enableLogs(userConfig.debug || false, 'Hls instance');
28378
+ var config = this.config = mergeConfig(Hls.DefaultConfig, userConfig);
29292
28379
  this.userConfig = userConfig;
29293
28380
  if (config.progressive) {
29294
- enableStreamingMode(config, logger);
28381
+ enableStreamingMode(config);
29295
28382
  }
29296
28383
 
29297
28384
  // core controllers and network loaders
@@ -29399,7 +28486,7 @@
29399
28486
  try {
29400
28487
  return this.emit(event, event, eventObject);
29401
28488
  } catch (error) {
29402
- this.logger.error('An internal error happened while handling event ' + event + '. Error message: "' + error.message + '". Here is a stacktrace:', error);
28489
+ logger.error('An internal error happened while handling event ' + event + '. Error message: "' + error.message + '". Here is a stacktrace:', error);
29403
28490
  // Prevent recursion in error event handlers that throw #5497
29404
28491
  if (!this.triggeringException) {
29405
28492
  this.triggeringException = true;
@@ -29425,7 +28512,7 @@
29425
28512
  * Dispose of the instance
29426
28513
  */;
29427
28514
  _proto.destroy = function destroy() {
29428
- this.logger.log('destroy');
28515
+ logger.log('destroy');
29429
28516
  this.trigger(Events.DESTROYING, undefined);
29430
28517
  this.detachMedia();
29431
28518
  this.removeAllListeners();
@@ -29450,7 +28537,7 @@
29450
28537
  * Attaches Hls.js to a media element
29451
28538
  */;
29452
28539
  _proto.attachMedia = function attachMedia(media) {
29453
- this.logger.log('attachMedia');
28540
+ logger.log('attachMedia');
29454
28541
  this._media = media;
29455
28542
  this.trigger(Events.MEDIA_ATTACHING, {
29456
28543
  media: media
@@ -29461,7 +28548,7 @@
29461
28548
  * Detach Hls.js from the media
29462
28549
  */;
29463
28550
  _proto.detachMedia = function detachMedia() {
29464
- this.logger.log('detachMedia');
28551
+ logger.log('detachMedia');
29465
28552
  this.trigger(Events.MEDIA_DETACHING, undefined);
29466
28553
  this._media = null;
29467
28554
  }
@@ -29478,7 +28565,7 @@
29478
28565
  });
29479
28566
  this._autoLevelCapping = -1;
29480
28567
  this._maxHdcpLevel = null;
29481
- this.logger.log("loadSource:" + loadingSource);
28568
+ logger.log("loadSource:" + loadingSource);
29482
28569
  if (media && loadedSource && (loadedSource !== loadingSource || this.bufferController.hasSourceTypes())) {
29483
28570
  this.detachMedia();
29484
28571
  this.attachMedia(media);
@@ -29500,7 +28587,8 @@
29500
28587
  if (startPosition === void 0) {
29501
28588
  startPosition = -1;
29502
28589
  }
29503
- this.logger.log("startLoad(" + startPosition + ")");
28590
+ logger.log("startLoad(" + startPosition + ")");
28591
+ this.started = true;
29504
28592
  this.networkControllers.forEach(function (controller) {
29505
28593
  controller.startLoad(startPosition);
29506
28594
  });
@@ -29510,31 +28598,34 @@
29510
28598
  * Stop loading of any stream data.
29511
28599
  */;
29512
28600
  _proto.stopLoad = function stopLoad() {
29513
- this.logger.log('stopLoad');
28601
+ logger.log('stopLoad');
28602
+ this.started = false;
29514
28603
  this.networkControllers.forEach(function (controller) {
29515
28604
  controller.stopLoad();
29516
28605
  });
29517
28606
  }
29518
28607
 
29519
28608
  /**
29520
- * Resumes stream controller segment loading after `pauseBuffering` has been called.
28609
+ * Resumes stream controller segment loading if previously started.
29521
28610
  */;
29522
28611
  _proto.resumeBuffering = function resumeBuffering() {
29523
- this.networkControllers.forEach(function (controller) {
29524
- if (controller.resumeBuffering) {
29525
- controller.resumeBuffering();
29526
- }
29527
- });
28612
+ if (this.started) {
28613
+ this.networkControllers.forEach(function (controller) {
28614
+ if ('fragmentLoader' in controller) {
28615
+ controller.startLoad(-1);
28616
+ }
28617
+ });
28618
+ }
29528
28619
  }
29529
28620
 
29530
28621
  /**
29531
- * Prevents stream controller from loading new segments until `resumeBuffering` is called.
28622
+ * Stops stream controller segment loading without changing 'started' state like stopLoad().
29532
28623
  * This allows for media buffering to be paused without interupting playlist loading.
29533
28624
  */;
29534
28625
  _proto.pauseBuffering = function pauseBuffering() {
29535
28626
  this.networkControllers.forEach(function (controller) {
29536
- if (controller.pauseBuffering) {
29537
- controller.pauseBuffering();
28627
+ if ('fragmentLoader' in controller) {
28628
+ controller.stopLoad();
29538
28629
  }
29539
28630
  });
29540
28631
  }
@@ -29543,7 +28634,7 @@
29543
28634
  * Swap through possible audio codecs in the stream (for example to switch from stereo to 5.1)
29544
28635
  */;
29545
28636
  _proto.swapAudioCodec = function swapAudioCodec() {
29546
- this.logger.log('swapAudioCodec');
28637
+ logger.log('swapAudioCodec');
29547
28638
  this.streamController.swapAudioCodec();
29548
28639
  }
29549
28640
 
@@ -29554,7 +28645,7 @@
29554
28645
  * Automatic recovery of media-errors by this process is configurable.
29555
28646
  */;
29556
28647
  _proto.recoverMediaError = function recoverMediaError() {
29557
- this.logger.log('recoverMediaError');
28648
+ logger.log('recoverMediaError');
29558
28649
  var media = this._media;
29559
28650
  this.detachMedia();
29560
28651
  if (media) {
@@ -29609,7 +28700,7 @@
29609
28700
  * 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.
29610
28701
  */,
29611
28702
  set: function set(newLevel) {
29612
- this.logger.log("set currentLevel:" + newLevel);
28703
+ logger.log("set currentLevel:" + newLevel);
29613
28704
  this.levelController.manualLevel = newLevel;
29614
28705
  this.streamController.immediateLevelSwitch();
29615
28706
  }
@@ -29630,7 +28721,7 @@
29630
28721
  * @param newLevel - Pass -1 for automatic level selection
29631
28722
  */,
29632
28723
  set: function set(newLevel) {
29633
- this.logger.log("set nextLevel:" + newLevel);
28724
+ logger.log("set nextLevel:" + newLevel);
29634
28725
  this.levelController.manualLevel = newLevel;
29635
28726
  this.streamController.nextLevelSwitch();
29636
28727
  }
@@ -29651,7 +28742,7 @@
29651
28742
  * @param newLevel - Pass -1 for automatic level selection
29652
28743
  */,
29653
28744
  set: function set(newLevel) {
29654
- this.logger.log("set loadLevel:" + newLevel);
28745
+ logger.log("set loadLevel:" + newLevel);
29655
28746
  this.levelController.manualLevel = newLevel;
29656
28747
  }
29657
28748
 
@@ -29686,7 +28777,7 @@
29686
28777
  * Sets "first-level", see getter.
29687
28778
  */,
29688
28779
  set: function set(newLevel) {
29689
- this.logger.log("set firstLevel:" + newLevel);
28780
+ logger.log("set firstLevel:" + newLevel);
29690
28781
  this.levelController.firstLevel = newLevel;
29691
28782
  }
29692
28783
 
@@ -29713,7 +28804,7 @@
29713
28804
  * (determined from download of first segment)
29714
28805
  */,
29715
28806
  set: function set(newLevel) {
29716
- this.logger.log("set startLevel:" + newLevel);
28807
+ logger.log("set startLevel:" + newLevel);
29717
28808
  // if not in automatic start level detection, ensure startLevel is greater than minAutoLevel
29718
28809
  if (newLevel !== -1) {
29719
28810
  newLevel = Math.max(newLevel, this.minAutoLevel);
@@ -29766,7 +28857,7 @@
29766
28857
  */
29767
28858
  function set(newLevel) {
29768
28859
  if (this._autoLevelCapping !== newLevel) {
29769
- this.logger.log("set autoLevelCapping:" + newLevel);
28860
+ logger.log("set autoLevelCapping:" + newLevel);
29770
28861
  this._autoLevelCapping = newLevel;
29771
28862
  this.levelController.checkMaxAutoUpdated();
29772
28863
  }
@@ -30091,7 +29182,7 @@
30091
29182
  * Get the video-dev/hls.js package version.
30092
29183
  */
30093
29184
  function get() {
30094
- return "1.5.5-0.canary.9995";
29185
+ return "1.5.5";
30095
29186
  }
30096
29187
  }, {
30097
29188
  key: "Events",