hls.js 1.5.13-0.canary.10410 → 1.5.13

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 (103) hide show
  1. package/README.md +3 -4
  2. package/dist/hls-demo.js +38 -41
  3. package/dist/hls-demo.js.map +1 -1
  4. package/dist/hls.js +2704 -4236
  5. package/dist/hls.js.d.ts +110 -179
  6. package/dist/hls.js.map +1 -1
  7. package/dist/hls.light.js +1994 -2914
  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 +3458 -4388
  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 +4506 -6048
  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 +38 -38
  20. package/src/config.ts +2 -5
  21. package/src/controller/abr-controller.ts +25 -39
  22. package/src/controller/audio-stream-controller.ts +137 -141
  23. package/src/controller/audio-track-controller.ts +1 -1
  24. package/src/controller/base-playlist-controller.ts +10 -27
  25. package/src/controller/base-stream-controller.ts +91 -235
  26. package/src/controller/buffer-controller.ts +97 -250
  27. package/src/controller/buffer-operation-queue.ts +19 -16
  28. package/src/controller/cap-level-controller.ts +2 -3
  29. package/src/controller/cmcd-controller.ts +14 -51
  30. package/src/controller/content-steering-controller.ts +15 -29
  31. package/src/controller/eme-controller.ts +23 -10
  32. package/src/controller/error-controller.ts +22 -28
  33. package/src/controller/fps-controller.ts +3 -8
  34. package/src/controller/fragment-finders.ts +16 -44
  35. package/src/controller/fragment-tracker.ts +25 -58
  36. package/src/controller/gap-controller.ts +16 -43
  37. package/src/controller/id3-track-controller.ts +35 -45
  38. package/src/controller/latency-controller.ts +13 -18
  39. package/src/controller/level-controller.ts +19 -37
  40. package/src/controller/stream-controller.ts +83 -100
  41. package/src/controller/subtitle-stream-controller.ts +47 -35
  42. package/src/controller/subtitle-track-controller.ts +3 -5
  43. package/src/controller/timeline-controller.ts +22 -20
  44. package/src/crypt/aes-crypto.ts +2 -21
  45. package/src/crypt/decrypter.ts +16 -32
  46. package/src/crypt/fast-aes-key.ts +5 -28
  47. package/src/demux/audio/aacdemuxer.ts +2 -2
  48. package/src/demux/audio/ac3-demuxer.ts +3 -4
  49. package/src/demux/audio/adts.ts +4 -9
  50. package/src/demux/audio/base-audio-demuxer.ts +14 -16
  51. package/src/demux/audio/mp3demuxer.ts +3 -4
  52. package/src/demux/audio/mpegaudio.ts +1 -1
  53. package/src/demux/id3.ts +411 -0
  54. package/src/demux/mp4demuxer.ts +7 -7
  55. package/src/demux/sample-aes.ts +0 -2
  56. package/src/demux/transmuxer-interface.ts +16 -8
  57. package/src/demux/transmuxer-worker.ts +4 -4
  58. package/src/demux/transmuxer.ts +3 -16
  59. package/src/demux/tsdemuxer.ts +38 -75
  60. package/src/demux/video/avc-video-parser.ts +121 -210
  61. package/src/demux/video/base-video-parser.ts +2 -135
  62. package/src/demux/video/exp-golomb.ts +208 -0
  63. package/src/events.ts +1 -8
  64. package/src/exports-named.ts +1 -1
  65. package/src/hls.ts +47 -84
  66. package/src/loader/date-range.ts +5 -71
  67. package/src/loader/fragment-loader.ts +21 -23
  68. package/src/loader/fragment.ts +4 -8
  69. package/src/loader/key-loader.ts +1 -3
  70. package/src/loader/level-details.ts +6 -6
  71. package/src/loader/level-key.ts +9 -10
  72. package/src/loader/m3u8-parser.ts +144 -138
  73. package/src/loader/playlist-loader.ts +7 -5
  74. package/src/remux/mp4-generator.ts +1 -196
  75. package/src/remux/mp4-remuxer.ts +62 -32
  76. package/src/remux/passthrough-remuxer.ts +1 -1
  77. package/src/task-loop.ts +2 -5
  78. package/src/types/component-api.ts +1 -3
  79. package/src/types/demuxer.ts +0 -3
  80. package/src/types/events.ts +6 -19
  81. package/src/types/fragment-tracker.ts +2 -2
  82. package/src/types/general.ts +6 -0
  83. package/src/types/media-playlist.ts +1 -9
  84. package/src/types/remuxer.ts +1 -1
  85. package/src/utils/attr-list.ts +9 -96
  86. package/src/utils/buffer-helper.ts +31 -12
  87. package/src/utils/cea-608-parser.ts +3 -1
  88. package/src/utils/codecs.ts +5 -34
  89. package/src/utils/fetch-loader.ts +1 -1
  90. package/src/utils/hdr.ts +7 -4
  91. package/src/utils/imsc1-ttml-parser.ts +1 -1
  92. package/src/utils/keysystem-util.ts +6 -1
  93. package/src/utils/level-helper.ts +44 -71
  94. package/src/utils/logger.ts +23 -58
  95. package/src/utils/mp4-tools.ts +3 -5
  96. package/src/utils/rendition-helper.ts +74 -100
  97. package/src/utils/variable-substitution.ts +19 -0
  98. package/src/utils/webvtt-parser.ts +12 -2
  99. package/src/crypt/decrypter-aes-mode.ts +0 -4
  100. package/src/demux/video/hevc-video-parser.ts +0 -749
  101. package/src/utils/encryption-methods-util.ts +0 -21
  102. package/src/utils/hash.ts +0 -10
  103. package/src/utils/utf8-utils.ts +0 -18
package/src/hls.ts CHANGED
@@ -8,7 +8,7 @@ import KeyLoader from './loader/key-loader';
8
8
  import StreamController from './controller/stream-controller';
9
9
  import { isMSESupported, isSupported } from './is-supported';
10
10
  import { getMediaSource } from './utils/mediasource-helper';
11
- import { enableLogs, type ILogger } from './utils/logger';
11
+ import { logger, enableLogs } from './utils/logger';
12
12
  import { enableStreamingMode, hlsDefaultConfig, mergeConfig } from './config';
13
13
  import { EventEmitter } from 'eventemitter3';
14
14
  import { Events } from './events';
@@ -59,13 +59,9 @@ export default class Hls implements HlsEventEmitter {
59
59
  */
60
60
  public readonly userConfig: Partial<HlsConfig>;
61
61
 
62
- /**
63
- * The logger functions used by this player instance, configured on player instantiation.
64
- */
65
- public readonly logger: ILogger;
66
-
67
62
  private coreComponents: ComponentAPI[];
68
63
  private networkControllers: NetworkComponentAPI[];
64
+ private started: boolean = false;
69
65
  private _emitter: HlsEventEmitter = new EventEmitter();
70
66
  private _autoLevelCapping: number = -1;
71
67
  private _maxHdcpLevel: HdcpLevel = null;
@@ -80,7 +76,7 @@ export default class Hls implements HlsEventEmitter {
80
76
  private emeController: EMEController;
81
77
  private cmcdController: CMCDController;
82
78
  private _media: HTMLMediaElement | null = null;
83
- private _url: string | null = null;
79
+ private url: string | null = null;
84
80
  private triggeringException?: boolean;
85
81
 
86
82
  /**
@@ -146,19 +142,12 @@ export default class Hls implements HlsEventEmitter {
146
142
  * @param userConfig - Configuration options applied over `Hls.DefaultConfig`
147
143
  */
148
144
  constructor(userConfig: Partial<HlsConfig> = {}) {
149
- const logger = (this.logger = enableLogs(
150
- userConfig.debug || false,
151
- 'Hls instance',
152
- ));
153
- const config = (this.config = mergeConfig(
154
- Hls.DefaultConfig,
155
- userConfig,
156
- logger,
157
- ));
145
+ enableLogs(userConfig.debug || false, 'Hls instance');
146
+ const config = (this.config = mergeConfig(Hls.DefaultConfig, userConfig));
158
147
  this.userConfig = userConfig;
159
148
 
160
149
  if (config.progressive) {
161
- enableStreamingMode(config, logger);
150
+ enableStreamingMode(config);
162
151
  }
163
152
 
164
153
  // core controllers and network loaders
@@ -171,10 +160,8 @@ export default class Hls implements HlsEventEmitter {
171
160
  } = config;
172
161
  const errorController = new ConfigErrorController(this);
173
162
  const abrController = (this.abrController = new ConfigAbrController(this));
174
- // FragmentTracker must be defined before StreamController because the order of event handling is important
175
- const fragmentTracker = new FragmentTracker(this);
176
163
  const bufferController = (this.bufferController =
177
- new ConfigBufferController(this, fragmentTracker));
164
+ new ConfigBufferController(this));
178
165
  const capLevelController = (this.capLevelController =
179
166
  new ConfigCapLevelController(this));
180
167
 
@@ -183,7 +170,7 @@ export default class Hls implements HlsEventEmitter {
183
170
  const id3TrackController = new ID3TrackController(this);
184
171
 
185
172
  const ConfigContentSteeringController = config.contentSteeringController;
186
- // ContentSteeringController is defined before LevelController to receive Multivariant Playlist events first
173
+ // ConentSteeringController is defined before LevelController to receive Multivariant Playlist events first
187
174
  const contentSteering = ConfigContentSteeringController
188
175
  ? new ConfigContentSteeringController(this)
189
176
  : null;
@@ -191,6 +178,8 @@ export default class Hls implements HlsEventEmitter {
191
178
  this,
192
179
  contentSteering,
193
180
  ));
181
+ // FragmentTracker must be defined before StreamController because the order of event handling is important
182
+ const fragmentTracker = new FragmentTracker(this);
194
183
  const keyLoader = new KeyLoader(this.config);
195
184
  const streamController = (this.streamController = new StreamController(
196
185
  this,
@@ -232,7 +221,7 @@ export default class Hls implements HlsEventEmitter {
232
221
  new AudioStreamControllerClass(this, fragmentTracker, keyLoader),
233
222
  );
234
223
  }
235
- // Instantiate subtitleTrackController before SubtitleStreamController to receive level events first
224
+ // subtitleTrackController must be defined before subtitleStreamController because the order of event handling is important
236
225
  this.subtitleTrackController = this.createController(
237
226
  config.subtitleTrackController,
238
227
  networkControllers,
@@ -331,7 +320,7 @@ export default class Hls implements HlsEventEmitter {
331
320
  try {
332
321
  return this.emit(event, event, eventObject);
333
322
  } catch (error) {
334
- this.logger.error(
323
+ logger.error(
335
324
  'An internal error happened while handling event ' +
336
325
  event +
337
326
  '. Error message: "' +
@@ -365,12 +354,12 @@ export default class Hls implements HlsEventEmitter {
365
354
  * Dispose of the instance
366
355
  */
367
356
  destroy() {
368
- this.logger.log('destroy');
357
+ logger.log('destroy');
369
358
  this.trigger(Events.DESTROYING, undefined);
370
359
  this.detachMedia();
371
360
  this.removeAllListeners();
372
361
  this._autoLevelCapping = -1;
373
- this._url = null;
362
+ this.url = null;
374
363
 
375
364
  this.networkControllers.forEach((component) => component.destroy());
376
365
  this.networkControllers.length = 0;
@@ -388,7 +377,7 @@ export default class Hls implements HlsEventEmitter {
388
377
  * Attaches Hls.js to a media element
389
378
  */
390
379
  attachMedia(media: HTMLMediaElement) {
391
- this.logger.log('attachMedia');
380
+ logger.log('attachMedia');
392
381
  this._media = media;
393
382
  this.trigger(Events.MEDIA_ATTACHING, { media: media });
394
383
  }
@@ -397,7 +386,7 @@ export default class Hls implements HlsEventEmitter {
397
386
  * Detach Hls.js from the media
398
387
  */
399
388
  detachMedia() {
400
- this.logger.log('detachMedia');
389
+ logger.log('detachMedia');
401
390
  this.trigger(Events.MEDIA_DETACHING, undefined);
402
391
  this._media = null;
403
392
  }
@@ -408,8 +397,8 @@ export default class Hls implements HlsEventEmitter {
408
397
  loadSource(url: string) {
409
398
  this.stopLoad();
410
399
  const media = this.media;
411
- const loadedSource = this._url;
412
- const loadingSource = (this._url = buildAbsoluteURL(
400
+ const loadedSource = this.url;
401
+ const loadingSource = (this.url = buildAbsoluteURL(
413
402
  self.location.href,
414
403
  url,
415
404
  {
@@ -418,7 +407,7 @@ export default class Hls implements HlsEventEmitter {
418
407
  ));
419
408
  this._autoLevelCapping = -1;
420
409
  this._maxHdcpLevel = null;
421
- this.logger.log(`loadSource:${loadingSource}`);
410
+ logger.log(`loadSource:${loadingSource}`);
422
411
  if (
423
412
  media &&
424
413
  loadedSource &&
@@ -431,13 +420,6 @@ export default class Hls implements HlsEventEmitter {
431
420
  this.trigger(Events.MANIFEST_LOADING, { url: url });
432
421
  }
433
422
 
434
- /**
435
- * Gets the currently loaded URL
436
- */
437
- public get url(): string | null {
438
- return this._url;
439
- }
440
-
441
423
  /**
442
424
  * Start loading data from the stream source.
443
425
  * Depending on default config, client starts loading automatically when a source is set.
@@ -446,7 +428,8 @@ export default class Hls implements HlsEventEmitter {
446
428
  * Defaults to -1 (None: starts from earliest point)
447
429
  */
448
430
  startLoad(startPosition: number = -1) {
449
- this.logger.log(`startLoad(${startPosition})`);
431
+ logger.log(`startLoad(${startPosition})`);
432
+ this.started = true;
450
433
  this.networkControllers.forEach((controller) => {
451
434
  controller.startLoad(startPosition);
452
435
  });
@@ -456,31 +439,34 @@ export default class Hls implements HlsEventEmitter {
456
439
  * Stop loading of any stream data.
457
440
  */
458
441
  stopLoad() {
459
- this.logger.log('stopLoad');
442
+ logger.log('stopLoad');
443
+ this.started = false;
460
444
  this.networkControllers.forEach((controller) => {
461
445
  controller.stopLoad();
462
446
  });
463
447
  }
464
448
 
465
449
  /**
466
- * Resumes stream controller segment loading after `pauseBuffering` has been called.
450
+ * Resumes stream controller segment loading if previously started.
467
451
  */
468
452
  resumeBuffering() {
469
- this.networkControllers.forEach((controller) => {
470
- if (controller.resumeBuffering) {
471
- controller.resumeBuffering();
472
- }
473
- });
453
+ if (this.started) {
454
+ this.networkControllers.forEach((controller) => {
455
+ if ('fragmentLoader' in controller) {
456
+ controller.startLoad(-1);
457
+ }
458
+ });
459
+ }
474
460
  }
475
461
 
476
462
  /**
477
- * Prevents stream controller from loading new segments until `resumeBuffering` is called.
463
+ * Stops stream controller segment loading without changing 'started' state like stopLoad().
478
464
  * This allows for media buffering to be paused without interupting playlist loading.
479
465
  */
480
466
  pauseBuffering() {
481
467
  this.networkControllers.forEach((controller) => {
482
- if (controller.pauseBuffering) {
483
- controller.pauseBuffering();
468
+ if ('fragmentLoader' in controller) {
469
+ controller.stopLoad();
484
470
  }
485
471
  });
486
472
  }
@@ -489,7 +475,7 @@ export default class Hls implements HlsEventEmitter {
489
475
  * Swap through possible audio codecs in the stream (for example to switch from stereo to 5.1)
490
476
  */
491
477
  swapAudioCodec() {
492
- this.logger.log('swapAudioCodec');
478
+ logger.log('swapAudioCodec');
493
479
  this.streamController.swapAudioCodec();
494
480
  }
495
481
 
@@ -500,7 +486,7 @@ export default class Hls implements HlsEventEmitter {
500
486
  * Automatic recovery of media-errors by this process is configurable.
501
487
  */
502
488
  recoverMediaError() {
503
- this.logger.log('recoverMediaError');
489
+ logger.log('recoverMediaError');
504
490
  const media = this._media;
505
491
  this.detachMedia();
506
492
  if (media) {
@@ -531,7 +517,7 @@ export default class Hls implements HlsEventEmitter {
531
517
  * 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.
532
518
  */
533
519
  set currentLevel(newLevel: number) {
534
- this.logger.log(`set currentLevel:${newLevel}`);
520
+ logger.log(`set currentLevel:${newLevel}`);
535
521
  this.levelController.manualLevel = newLevel;
536
522
  this.streamController.immediateLevelSwitch();
537
523
  }
@@ -550,7 +536,7 @@ export default class Hls implements HlsEventEmitter {
550
536
  * @param newLevel - Pass -1 for automatic level selection
551
537
  */
552
538
  set nextLevel(newLevel: number) {
553
- this.logger.log(`set nextLevel:${newLevel}`);
539
+ logger.log(`set nextLevel:${newLevel}`);
554
540
  this.levelController.manualLevel = newLevel;
555
541
  this.streamController.nextLevelSwitch();
556
542
  }
@@ -569,7 +555,7 @@ export default class Hls implements HlsEventEmitter {
569
555
  * @param newLevel - Pass -1 for automatic level selection
570
556
  */
571
557
  set loadLevel(newLevel: number) {
572
- this.logger.log(`set loadLevel:${newLevel}`);
558
+ logger.log(`set loadLevel:${newLevel}`);
573
559
  this.levelController.manualLevel = newLevel;
574
560
  }
575
561
 
@@ -600,7 +586,7 @@ export default class Hls implements HlsEventEmitter {
600
586
  * Sets "first-level", see getter.
601
587
  */
602
588
  set firstLevel(newLevel: number) {
603
- this.logger.log(`set firstLevel:${newLevel}`);
589
+ logger.log(`set firstLevel:${newLevel}`);
604
590
  this.levelController.firstLevel = newLevel;
605
591
  }
606
592
 
@@ -625,7 +611,7 @@ export default class Hls implements HlsEventEmitter {
625
611
  * (determined from download of first segment)
626
612
  */
627
613
  set startLevel(newLevel: number) {
628
- this.logger.log(`set startLevel:${newLevel}`);
614
+ logger.log(`set startLevel:${newLevel}`);
629
615
  // if not in automatic start level detection, ensure startLevel is greater than minAutoLevel
630
616
  if (newLevel !== -1) {
631
617
  newLevel = Math.max(newLevel, this.minAutoLevel);
@@ -700,7 +686,7 @@ export default class Hls implements HlsEventEmitter {
700
686
  */
701
687
  set autoLevelCapping(newLevel: number) {
702
688
  if (this._autoLevelCapping !== newLevel) {
703
- this.logger.log(`set autoLevelCapping:${newLevel}`);
689
+ logger.log(`set autoLevelCapping:${newLevel}`);
704
690
  this._autoLevelCapping = newLevel;
705
691
  this.levelController.checkMaxAutoUpdated();
706
692
  }
@@ -809,10 +795,6 @@ export default class Hls implements HlsEventEmitter {
809
795
  return this.streamController.getMainFwdBufferInfo();
810
796
  }
811
797
 
812
- public get maxBufferLength(): number {
813
- return this.streamController.maxBufferLength;
814
- }
815
-
816
798
  /**
817
799
  * Find and select the best matching audio track, making a level switch when a Group change is necessary.
818
800
  * Updates `hls.config.audioPreference`. Returns the selected track, or null when no matching track is found.
@@ -820,7 +802,7 @@ export default class Hls implements HlsEventEmitter {
820
802
  public setAudioOption(
821
803
  audioOption: MediaPlaylist | AudioSelectionOption | undefined,
822
804
  ): MediaPlaylist | null {
823
- return this.audioTrackController?.setAudioOption(audioOption) || null;
805
+ return this.audioTrackController?.setAudioOption(audioOption);
824
806
  }
825
807
  /**
826
808
  * Find and select the best matching subtitle track, making a level switch when a Group change is necessary.
@@ -829,9 +811,8 @@ export default class Hls implements HlsEventEmitter {
829
811
  public setSubtitleOption(
830
812
  subtitleOption: MediaPlaylist | SubtitleSelectionOption | undefined,
831
813
  ): MediaPlaylist | null {
832
- return (
833
- this.subtitleTrackController?.setSubtitleOption(subtitleOption) || null
834
- );
814
+ this.subtitleTrackController?.setSubtitleOption(subtitleOption);
815
+ return null;
835
816
  }
836
817
 
837
818
  /**
@@ -976,10 +957,6 @@ export default class Hls implements HlsEventEmitter {
976
957
  return this.latencyController.targetLatency;
977
958
  }
978
959
 
979
- set targetLatency(latency: number) {
980
- this.latencyController.targetLatency = latency;
981
- }
982
-
983
960
  /**
984
961
  * the rate at which the edge of the current live playlist is advancing or 1 if there is none
985
962
  */
@@ -993,17 +970,6 @@ export default class Hls implements HlsEventEmitter {
993
970
  get forceStartLoad(): boolean {
994
971
  return this.streamController.forceStartLoad;
995
972
  }
996
-
997
- /**
998
- * ContentSteering pathwayPriority getter/setter
999
- */
1000
- get pathwayPriority(): string[] | null {
1001
- return this.levelController.pathwayPriority;
1002
- }
1003
-
1004
- set pathwayPriority(pathwayPriority: string[]) {
1005
- this.levelController.pathwayPriority = pathwayPriority;
1006
- }
1007
973
  }
1008
974
 
1009
975
  export type {
@@ -1066,7 +1032,7 @@ export type {
1066
1032
  TSDemuxerConfig,
1067
1033
  } from './config';
1068
1034
  export type { MediaKeySessionContext } from './controller/eme-controller';
1069
- export type { ILogger, Logger } from './utils/logger';
1035
+ export type { ILogger } from './utils/logger';
1070
1036
  export type {
1071
1037
  PathwayClone,
1072
1038
  SteeringManifest,
@@ -1080,7 +1046,7 @@ export type {
1080
1046
  KeySystems,
1081
1047
  KeySystemFormats,
1082
1048
  } from './utils/mediakeys-helper';
1083
- export type { DateRange, DateRangeCue } from './loader/date-range';
1049
+ export type { DateRange } from './loader/date-range';
1084
1050
  export type { LoadStats } from './loader/load-stats';
1085
1051
  export type { LevelKey } from './loader/level-key';
1086
1052
  export type { LevelDetails } from './loader/level-details';
@@ -1130,7 +1096,6 @@ export type { ChunkMetadata } from './types/transmuxer';
1130
1096
  export type {
1131
1097
  BaseSegment,
1132
1098
  Fragment,
1133
- MediaFragment,
1134
1099
  Part,
1135
1100
  ElementaryStreams,
1136
1101
  ElementaryStreamTypes,
@@ -1182,7 +1147,6 @@ export type {
1182
1147
  ManifestParsedData,
1183
1148
  MediaAttachedData,
1184
1149
  MediaAttachingData,
1185
- MediaEndedData,
1186
1150
  NonNativeTextTrack,
1187
1151
  NonNativeTextTracksData,
1188
1152
  SteeringManifestLoadedData,
@@ -1197,4 +1161,3 @@ export type {
1197
1161
  IErrorAction,
1198
1162
  } from './controller/error-controller';
1199
1163
  export type { AttrList } from './utils/attr-list';
1200
- export type { ParsedMultivariantPlaylist } from './loader/m3u8-parser';
@@ -1,12 +1,10 @@
1
1
  import { AttrList } from '../utils/attr-list';
2
2
  import { logger } from '../utils/logger';
3
- import type { Fragment } from './fragment';
4
3
 
5
4
  // Avoid exporting const enum so that these values can be inlined
6
5
  const enum DateRangeAttribute {
7
6
  ID = 'ID',
8
7
  CLASS = 'CLASS',
9
- CUE = 'CUE',
10
8
  START_DATE = 'START-DATE',
11
9
  DURATION = 'DURATION',
12
10
  END_DATE = 'END-DATE',
@@ -14,22 +12,12 @@ const enum DateRangeAttribute {
14
12
  PLANNED_DURATION = 'PLANNED-DURATION',
15
13
  SCTE35_OUT = 'SCTE35-OUT',
16
14
  SCTE35_IN = 'SCTE35-IN',
17
- SCTE35_CMD = 'SCTE35-CMD',
18
15
  }
19
16
 
20
- export type DateRangeCue = {
21
- pre: boolean;
22
- post: boolean;
23
- once: boolean;
24
- };
25
-
26
- const CLASS_INTERSTITIAL = 'com.apple.hls.interstitial';
27
-
28
17
  export function isDateRangeCueAttribute(attrName: string): boolean {
29
18
  return (
30
19
  attrName !== DateRangeAttribute.ID &&
31
20
  attrName !== DateRangeAttribute.CLASS &&
32
- attrName !== DateRangeAttribute.CUE &&
33
21
  attrName !== DateRangeAttribute.START_DATE &&
34
22
  attrName !== DateRangeAttribute.DURATION &&
35
23
  attrName !== DateRangeAttribute.END_DATE &&
@@ -40,27 +28,17 @@ export function isDateRangeCueAttribute(attrName: string): boolean {
40
28
  export function isSCTE35Attribute(attrName: string): boolean {
41
29
  return (
42
30
  attrName === DateRangeAttribute.SCTE35_OUT ||
43
- attrName === DateRangeAttribute.SCTE35_IN ||
44
- attrName === DateRangeAttribute.SCTE35_CMD
31
+ attrName === DateRangeAttribute.SCTE35_IN
45
32
  );
46
33
  }
47
34
 
48
35
  export class DateRange {
49
36
  public attr: AttrList;
50
- public tagAnchor: Fragment | null;
51
- public tagOrder: number;
52
37
  private _startDate: Date;
53
38
  private _endDate?: Date;
54
- private _cue?: DateRangeCue;
55
39
  private _badValueForSameId?: string;
56
40
 
57
- constructor(
58
- dateRangeAttr: AttrList,
59
- dateRangeWithSameId?: DateRange | undefined,
60
- tagCount: number = 0,
61
- ) {
62
- this.tagAnchor = dateRangeWithSameId?.tagAnchor || null;
63
- this.tagOrder = dateRangeWithSameId?.tagOrder ?? tagCount;
41
+ constructor(dateRangeAttr: AttrList, dateRangeWithSameId?: DateRange) {
64
42
  if (dateRangeWithSameId) {
65
43
  const previousAttr = dateRangeWithSameId.attr;
66
44
  for (const key in previousAttr) {
@@ -83,13 +61,9 @@ export class DateRange {
83
61
  );
84
62
  }
85
63
  this.attr = dateRangeAttr;
86
- this._startDate = dateRangeWithSameId
87
- ? dateRangeWithSameId.startDate
88
- : new Date(dateRangeAttr[DateRangeAttribute.START_DATE]);
64
+ this._startDate = new Date(dateRangeAttr[DateRangeAttribute.START_DATE]);
89
65
  if (DateRangeAttribute.END_DATE in this.attr) {
90
- const endDate =
91
- dateRangeWithSameId?.endDate ||
92
- new Date(this.attr[DateRangeAttribute.END_DATE]);
66
+ const endDate = new Date(this.attr[DateRangeAttribute.END_DATE]);
93
67
  if (Number.isFinite(endDate.getTime())) {
94
68
  this._endDate = endDate;
95
69
  }
@@ -104,36 +78,6 @@ export class DateRange {
104
78
  return this.attr.CLASS;
105
79
  }
106
80
 
107
- get cue(): DateRangeCue {
108
- const _cue = this._cue;
109
- if (_cue === undefined) {
110
- return (this._cue = this.attr.enumeratedStringList(
111
- this.attr.CUE ? 'CUE' : 'X-CUE',
112
- {
113
- pre: false,
114
- post: false,
115
- once: false,
116
- },
117
- ));
118
- }
119
- return _cue;
120
- }
121
-
122
- get startTime(): number {
123
- const { tagAnchor } = this;
124
- // eslint-disable-next-line @typescript-eslint/prefer-optional-chain
125
- if (tagAnchor === null || tagAnchor.programDateTime === null) {
126
- logger.warn(
127
- `Expected tagAnchor Fragment with PDT set for DateRange "${this.id}": ${tagAnchor}`,
128
- );
129
- return NaN;
130
- }
131
- return (
132
- tagAnchor.start +
133
- (this.startDate.getTime() - tagAnchor.programDateTime) / 1000
134
- );
135
- }
136
-
137
81
  get startDate(): Date {
138
82
  return this._startDate;
139
83
  }
@@ -176,23 +120,13 @@ export class DateRange {
176
120
  return this.attr.bool(DateRangeAttribute.END_ON_NEXT);
177
121
  }
178
122
 
179
- get isInterstitial(): boolean {
180
- return this.class === CLASS_INTERSTITIAL;
181
- }
182
-
183
123
  get isValid(): boolean {
184
124
  return (
185
125
  !!this.id &&
186
126
  !this._badValueForSameId &&
187
127
  Number.isFinite(this.startDate.getTime()) &&
188
128
  (this.duration === null || this.duration >= 0) &&
189
- (!this.endOnNext || !!this.class) &&
190
- (!this.attr.CUE ||
191
- (!this.cue.pre && !this.cue.post) ||
192
- this.cue.pre !== this.cue.post) &&
193
- (!this.isInterstitial ||
194
- 'X-ASSET-URI' in this.attr ||
195
- 'X-ASSET-LIST' in this.attr)
129
+ (!this.endOnNext || !!this.class)
196
130
  );
197
131
  }
198
132
  }
@@ -1,17 +1,18 @@
1
1
  import { ErrorTypes, ErrorDetails } from '../errors';
2
+ import { Fragment } from './fragment';
3
+ import {
4
+ Loader,
5
+ LoaderConfiguration,
6
+ FragmentLoaderContext,
7
+ } from '../types/loader';
2
8
  import { getLoaderConfigWithoutReties } from '../utils/error-helper';
3
9
  import type { HlsConfig } from '../config';
4
- import type { BaseSegment, Fragment, Part } from './fragment';
10
+ import type { BaseSegment, Part } from './fragment';
5
11
  import type {
6
12
  ErrorData,
7
13
  FragLoadedData,
8
14
  PartsLoadedData,
9
15
  } from '../types/events';
10
- import type {
11
- Loader,
12
- LoaderConfiguration,
13
- FragmentLoaderContext,
14
- } from '../types/loader';
15
16
 
16
17
  const MIN_CHUNK_SIZE = Math.pow(2, 17); // 128kb
17
18
 
@@ -76,11 +77,13 @@ export default class FragmentLoader {
76
77
  frag.gap = false;
77
78
  }
78
79
  }
79
- const loader = (this.loader = FragmentILoader
80
- ? new FragmentILoader(config)
81
- : (new DefaultILoader(config) as Loader<FragmentLoaderContext>));
80
+ const loader =
81
+ (this.loader =
82
+ frag.loader =
83
+ FragmentILoader
84
+ ? new FragmentILoader(config)
85
+ : (new DefaultILoader(config) as Loader<FragmentLoaderContext>));
82
86
  const loaderContext = createLoaderContext(frag);
83
- frag.loader = loader;
84
87
  const loadPolicy = getLoaderConfigWithoutReties(
85
88
  config.fragLoadPolicy.default,
86
89
  );
@@ -185,11 +188,13 @@ export default class FragmentLoader {
185
188
  reject(createGapLoadError(frag, part));
186
189
  return;
187
190
  }
188
- const loader = (this.loader = FragmentILoader
189
- ? new FragmentILoader(config)
190
- : (new DefaultILoader(config) as Loader<FragmentLoaderContext>));
191
+ const loader =
192
+ (this.loader =
193
+ frag.loader =
194
+ FragmentILoader
195
+ ? new FragmentILoader(config)
196
+ : (new DefaultILoader(config) as Loader<FragmentLoaderContext>));
191
197
  const loaderContext = createLoaderContext(frag, part);
192
- frag.loader = loader;
193
198
  // Should we define another load policy for parts?
194
199
  const loadPolicy = getLoaderConfigWithoutReties(
195
200
  config.fragLoadPolicy.default,
@@ -331,11 +336,8 @@ function createLoaderContext(
331
336
  if (Number.isFinite(start) && Number.isFinite(end)) {
332
337
  let byteRangeStart = start;
333
338
  let byteRangeEnd = end;
334
- if (
335
- frag.sn === 'initSegment' &&
336
- isMethodFullSegmentAesCbc(frag.decryptdata?.method)
337
- ) {
338
- // MAP segment encrypted with method 'AES-128' or 'AES-256' (cbc), when served with HTTP Range,
339
+ if (frag.sn === 'initSegment' && frag.decryptdata?.method === 'AES-128') {
340
+ // MAP segment encrypted with method 'AES-128', when served with HTTP Range,
339
341
  // has the unencrypted size specified in the range.
340
342
  // Ref: https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-6.3.6
341
343
  const fragmentLen = end - start;
@@ -370,10 +372,6 @@ function createGapLoadError(frag: Fragment, part?: Part): LoadError {
370
372
  return new LoadError(errorData);
371
373
  }
372
374
 
373
- function isMethodFullSegmentAesCbc(method) {
374
- return method === 'AES-128' || method === 'AES-256';
375
- }
376
-
377
375
  export class LoadError extends Error {
378
376
  public readonly data: FragLoadFailResult;
379
377
  constructor(data: FragLoadFailResult) {
@@ -90,10 +90,6 @@ export class BaseSegment {
90
90
  }
91
91
  }
92
92
 
93
- export interface MediaFragment extends Fragment {
94
- sn: number;
95
- }
96
-
97
93
  /**
98
94
  * Object representing parsed data from an HLS Segment. Found in {@link hls.js#LevelDetails.fragments}.
99
95
  */
@@ -127,9 +123,9 @@ export class Fragment extends BaseSegment {
127
123
  // The ending Presentation Time Stamp (PTS) of the fragment. Set after transmux complete.
128
124
  public endPTS?: number;
129
125
  // The starting Decode Time Stamp (DTS) of the fragment. Set after transmux complete.
130
- public startDTS?: number;
126
+ public startDTS!: number;
131
127
  // The ending Decode Time Stamp (DTS) of the fragment. Set after transmux complete.
132
- public endDTS?: number;
128
+ public endDTS!: number;
133
129
  // The start time of the fragment, as listed in the manifest. Updated after transmux complete.
134
130
  public start: number = 0;
135
131
  // Set by `updateFragPTSDTS` in level-helper
@@ -278,13 +274,13 @@ export class Part extends BaseSegment {
278
274
  public readonly gap: boolean = false;
279
275
  public readonly independent: boolean = false;
280
276
  public readonly relurl: string;
281
- public readonly fragment: MediaFragment;
277
+ public readonly fragment: Fragment;
282
278
  public readonly index: number;
283
279
  public stats: LoadStats = new LoadStats();
284
280
 
285
281
  constructor(
286
282
  partAttrs: AttrList,
287
- frag: MediaFragment,
283
+ frag: Fragment,
288
284
  baseurl: string,
289
285
  index: number,
290
286
  previous?: Part,
@@ -1,5 +1,5 @@
1
1
  import { ErrorTypes, ErrorDetails } from '../errors';
2
- import type {
2
+ import {
3
3
  LoaderStats,
4
4
  LoaderResponse,
5
5
  LoaderConfiguration,
@@ -194,8 +194,6 @@ export default class KeyLoader implements ComponentAPI {
194
194
  }
195
195
  return this.loadKeyEME(keyInfo, frag);
196
196
  case 'AES-128':
197
- case 'AES-256':
198
- case 'AES-256-CTR':
199
197
  return this.loadKeyHTTP(keyInfo, frag);
200
198
  default:
201
199
  return Promise.reject(