hls.js 1.5.2-0.canary.9934 → 1.5.3

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 (60) hide show
  1. package/dist/hls-demo.js +0 -5
  2. package/dist/hls-demo.js.map +1 -1
  3. package/dist/hls.js +757 -883
  4. package/dist/hls.js.d.ts +47 -56
  5. package/dist/hls.js.map +1 -1
  6. package/dist/hls.light.js +477 -600
  7. package/dist/hls.light.js.map +1 -1
  8. package/dist/hls.light.min.js +1 -1
  9. package/dist/hls.light.min.js.map +1 -1
  10. package/dist/hls.light.mjs +335 -446
  11. package/dist/hls.light.mjs.map +1 -1
  12. package/dist/hls.min.js +1 -1
  13. package/dist/hls.min.js.map +1 -1
  14. package/dist/hls.mjs +572 -681
  15. package/dist/hls.mjs.map +1 -1
  16. package/dist/hls.worker.js +1 -1
  17. package/dist/hls.worker.js.map +1 -1
  18. package/package.json +11 -11
  19. package/src/config.ts +2 -3
  20. package/src/controller/abr-controller.ts +22 -22
  21. package/src/controller/audio-stream-controller.ts +14 -11
  22. package/src/controller/audio-track-controller.ts +1 -1
  23. package/src/controller/base-playlist-controller.ts +7 -7
  24. package/src/controller/base-stream-controller.ts +29 -47
  25. package/src/controller/buffer-controller.ts +11 -10
  26. package/src/controller/cap-level-controller.ts +2 -1
  27. package/src/controller/cmcd-controller.ts +3 -25
  28. package/src/controller/content-steering-controller.ts +6 -8
  29. package/src/controller/eme-controller.ts +22 -9
  30. package/src/controller/error-controller.ts +8 -6
  31. package/src/controller/fps-controller.ts +3 -2
  32. package/src/controller/gap-controller.ts +16 -43
  33. package/src/controller/latency-controller.ts +11 -9
  34. package/src/controller/level-controller.ts +17 -5
  35. package/src/controller/stream-controller.ts +31 -24
  36. package/src/controller/subtitle-stream-controller.ts +14 -13
  37. package/src/controller/subtitle-track-controller.ts +3 -5
  38. package/src/controller/timeline-controller.ts +30 -23
  39. package/src/crypt/aes-crypto.ts +2 -21
  40. package/src/crypt/decrypter.ts +18 -32
  41. package/src/crypt/fast-aes-key.ts +5 -24
  42. package/src/demux/audio/adts.ts +4 -9
  43. package/src/demux/sample-aes.ts +0 -2
  44. package/src/demux/transmuxer-interface.ts +12 -4
  45. package/src/demux/transmuxer-worker.ts +4 -4
  46. package/src/demux/transmuxer.ts +3 -16
  47. package/src/demux/tsdemuxer.ts +17 -12
  48. package/src/events.ts +0 -7
  49. package/src/hls.ts +20 -33
  50. package/src/loader/fragment-loader.ts +2 -9
  51. package/src/loader/key-loader.ts +0 -2
  52. package/src/loader/level-key.ts +9 -10
  53. package/src/remux/mp4-remuxer.ts +4 -20
  54. package/src/task-loop.ts +2 -5
  55. package/src/types/demuxer.ts +0 -1
  56. package/src/types/events.ts +0 -4
  57. package/src/utils/codecs.ts +4 -33
  58. package/src/utils/logger.ts +24 -53
  59. package/src/crypt/decrypter-aes-mode.ts +0 -4
  60. package/src/utils/encryption-methods-util.ts +0 -21
package/package.json CHANGED
@@ -67,10 +67,10 @@
67
67
  "@babel/plugin-proposal-object-rest-spread": "7.20.7",
68
68
  "@babel/plugin-proposal-optional-chaining": "7.21.0",
69
69
  "@babel/plugin-transform-object-assign": "7.23.3",
70
- "@babel/preset-env": "7.23.8",
70
+ "@babel/preset-env": "7.23.7",
71
71
  "@babel/preset-typescript": "7.23.3",
72
72
  "@babel/register": "7.23.7",
73
- "@microsoft/api-documenter": "7.23.19",
73
+ "@microsoft/api-documenter": "7.23.16",
74
74
  "@microsoft/api-extractor": "7.39.1",
75
75
  "@rollup/plugin-alias": "5.1.0",
76
76
  "@rollup/plugin-babel": "6.0.4",
@@ -78,19 +78,19 @@
78
78
  "@rollup/plugin-node-resolve": "15.2.3",
79
79
  "@rollup/plugin-replace": "5.0.5",
80
80
  "@rollup/plugin-terser": "0.4.4",
81
- "@rollup/plugin-typescript": "11.1.6",
82
- "@svta/common-media-library": "0.6.2",
81
+ "@rollup/plugin-typescript": "11.1.5",
82
+ "@svta/common-media-library": "0.6.1",
83
83
  "@types/chai": "4.3.11",
84
84
  "@types/chart.js": "2.9.41",
85
85
  "@types/mocha": "10.0.6",
86
86
  "@types/sinon-chai": "3.2.12",
87
- "@typescript-eslint/eslint-plugin": "6.19.1",
88
- "@typescript-eslint/parser": "6.19.1",
87
+ "@typescript-eslint/eslint-plugin": "6.17.0",
88
+ "@typescript-eslint/parser": "6.17.0",
89
89
  "babel-loader": "9.1.3",
90
90
  "babel-plugin-transform-remove-console": "6.9.4",
91
- "chai": "4.4.1",
91
+ "chai": "4.3.10",
92
92
  "chart.js": "2.9.4",
93
- "chromedriver": "120.0.2",
93
+ "chromedriver": "120.0.1",
94
94
  "doctoc": "2.2.1",
95
95
  "es-check": "7.1.1",
96
96
  "eslint": "8.56.0",
@@ -119,7 +119,7 @@
119
119
  "npm-run-all": "4.1.5",
120
120
  "prettier": "3.1.1",
121
121
  "promise-polyfill": "8.3.0",
122
- "rollup": "4.9.6",
122
+ "rollup": "4.9.4",
123
123
  "rollup-plugin-istanbul": "5.0.0",
124
124
  "sauce-connect-launcher": "1.3.2",
125
125
  "selenium-webdriver": "4.16.0",
@@ -128,7 +128,7 @@
128
128
  "sinon-chai": "3.7.0",
129
129
  "typescript": "5.3.3",
130
130
  "url-toolkit": "2.2.5",
131
- "wrangler": "3.24.0"
131
+ "wrangler": "3.22.4"
132
132
  },
133
- "version": "1.5.2-0.canary.9934"
133
+ "version": "1.5.3"
134
134
  }
package/src/config.ts CHANGED
@@ -17,10 +17,10 @@ import XhrLoader from './utils/xhr-loader';
17
17
  import FetchLoader, { fetchSupported } from './utils/fetch-loader';
18
18
  import Cues from './utils/cues';
19
19
  import { requestMediaKeySystemAccess } from './utils/mediakeys-helper';
20
+ import { ILogger, logger } from './utils/logger';
20
21
 
21
22
  import type Hls from './hls';
22
23
  import type { CuesInterface } from './utils/cues';
23
- import type { ILogger } from './utils/logger';
24
24
  import type { MediaKeyFunc, KeySystems } from './utils/mediakeys-helper';
25
25
  import type {
26
26
  FragmentLoaderContext,
@@ -558,7 +558,6 @@ function timelineConfig(): TimelineControllerConfig {
558
558
  export function mergeConfig(
559
559
  defaultConfig: HlsConfig,
560
560
  userConfig: Partial<HlsConfig>,
561
- logger: ILogger,
562
561
  ): HlsConfig {
563
562
  if (
564
563
  (userConfig.liveSyncDurationCount ||
@@ -665,7 +664,7 @@ function deepCpy(obj: any): any {
665
664
  /**
666
665
  * @ignore
667
666
  */
668
- export function enableStreamingMode(config: HlsConfig, logger: ILogger) {
667
+ export function enableStreamingMode(config) {
669
668
  const currentLoader = config.loader;
670
669
  if (currentLoader !== FetchLoader && currentLoader !== XhrLoader) {
671
670
  // If a developer has configured their own loader, respect that choice
@@ -2,7 +2,7 @@ import EwmaBandWidthEstimator from '../utils/ewma-bandwidth-estimator';
2
2
  import { Events } from '../events';
3
3
  import { ErrorDetails } from '../errors';
4
4
  import { PlaylistLevelType } from '../types/loader';
5
- import { Logger } from '../utils/logger';
5
+ import { logger } from '../utils/logger';
6
6
  import {
7
7
  SUPPORTED_INFO_DEFAULT,
8
8
  getMediaDecodingInfoPromise,
@@ -31,7 +31,7 @@ import type {
31
31
  } from '../types/events';
32
32
  import type { AbrComponentAPI } from '../types/component-api';
33
33
 
34
- class AbrController extends Logger implements AbrComponentAPI {
34
+ class AbrController implements AbrComponentAPI {
35
35
  protected hls: Hls;
36
36
  private lastLevelLoadSec: number = 0;
37
37
  private lastLoadedFragLevel: number = -1;
@@ -48,7 +48,6 @@ class AbrController extends Logger implements AbrComponentAPI {
48
48
  public bwEstimator: EwmaBandWidthEstimator;
49
49
 
50
50
  constructor(hls: Hls) {
51
- super('abr', hls.logger);
52
51
  this.hls = hls;
53
52
  this.bwEstimator = this.initEstimator();
54
53
  this.registerListeners();
@@ -56,7 +55,7 @@ class AbrController extends Logger implements AbrComponentAPI {
56
55
 
57
56
  public resetEstimator(abrEwmaDefaultEstimate?: number) {
58
57
  if (abrEwmaDefaultEstimate) {
59
- this.log(`setting initial bwe to ${abrEwmaDefaultEstimate}`);
58
+ logger.log(`setting initial bwe to ${abrEwmaDefaultEstimate}`);
60
59
  this.hls.config.abrEwmaDefaultEstimate = abrEwmaDefaultEstimate;
61
60
  }
62
61
  this.firstSelection = -1;
@@ -356,7 +355,7 @@ class AbrController extends Logger implements AbrComponentAPI {
356
355
  }
357
356
 
358
357
  this.clearTimer();
359
- this.warn(`Fragment ${frag.sn}${
358
+ logger.warn(`[abr] Fragment ${frag.sn}${
360
359
  part ? ' part ' + part.index : ''
361
360
  } of level ${frag.level} is loading too slowly;
362
361
  Time to underbuffer: ${bufferStarvationDelay.toFixed(3)} s
@@ -480,8 +479,8 @@ class AbrController extends Logger implements AbrComponentAPI {
480
479
  }
481
480
  const firstLevel = this.hls.firstLevel;
482
481
  const clamped = Math.min(Math.max(firstLevel, minAutoLevel), maxAutoLevel);
483
- this.warn(
484
- `Could not find best starting auto level. Defaulting to first in playlist ${firstLevel} clamped to ${clamped}`,
482
+ logger.warn(
483
+ `[abr] Could not find best starting auto level. Defaulting to first in playlist ${firstLevel} clamped to ${clamped}`,
485
484
  );
486
485
  return clamped;
487
486
  }
@@ -592,8 +591,8 @@ class AbrController extends Logger implements AbrComponentAPI {
592
591
  ? Math.min(currentFragDuration, config.maxLoadingDelay)
593
592
  : config.maxLoadingDelay;
594
593
  maxStarvationDelay = maxLoadingDelay - bitrateTestDelay;
595
- this.info(
596
- `bitrate test took ${Math.round(
594
+ logger.info(
595
+ `[abr] bitrate test took ${Math.round(
597
596
  1000 * bitrateTestDelay,
598
597
  )}ms, set first fragment max fetchDuration to ${Math.round(
599
598
  1000 * maxStarvationDelay,
@@ -612,8 +611,8 @@ class AbrController extends Logger implements AbrComponentAPI {
612
611
  bwFactor,
613
612
  bwUpFactor,
614
613
  );
615
- this.info(
616
- `${
614
+ logger.info(
615
+ `[abr] ${
617
616
  bufferStarvationDelay ? 'rebuffering expected' : 'buffer is empty'
618
617
  }, optimal quality level ${bestLevel}`,
619
618
  );
@@ -692,7 +691,7 @@ class AbrController extends Logger implements AbrComponentAPI {
692
691
  : videoRanges[0];
693
692
  currentFrameRate = minFramerate;
694
693
  currentBw = Math.max(currentBw, minBitrate);
695
- this.log(`picked start tier ${JSON.stringify(startTier)}`);
694
+ logger.log(`[abr] picked start tier ${JSON.stringify(startTier)}`);
696
695
  } else {
697
696
  currentCodecSet = level?.codecSet;
698
697
  currentVideoRange = level?.videoRange;
@@ -742,19 +741,19 @@ class AbrController extends Logger implements AbrComponentAPI {
742
741
  const levels = this.hls.levels;
743
742
  const index = levels.indexOf(levelInfo);
744
743
  if (decodingInfo.error) {
745
- this.warn(
746
- `MediaCapabilities decodingInfo error: "${
744
+ logger.warn(
745
+ `[abr] MediaCapabilities decodingInfo error: "${
747
746
  decodingInfo.error
748
747
  }" for level ${index} ${JSON.stringify(decodingInfo)}`,
749
748
  );
750
749
  } else if (!decodingInfo.supported) {
751
- this.warn(
752
- `Unsupported MediaCapabilities decodingInfo result for level ${index} ${JSON.stringify(
750
+ logger.warn(
751
+ `[abr] Unsupported MediaCapabilities decodingInfo result for level ${index} ${JSON.stringify(
753
752
  decodingInfo,
754
753
  )}`,
755
754
  );
756
755
  if (index > -1 && levels.length > 1) {
757
- this.log(`Removing unsupported level ${index}`);
756
+ logger.log(`[abr] Removing unsupported level ${index}`);
758
757
  this.hls.removeLevel(index);
759
758
  }
760
759
  }
@@ -773,7 +772,8 @@ class AbrController extends Logger implements AbrComponentAPI {
773
772
  (!upSwitch &&
774
773
  currentFrameRate > 0 &&
775
774
  currentFrameRate < levelInfo.frameRate) ||
776
- !levelInfo.supportedResult?.decodingInfoResults?.[0].smooth
775
+ (levelInfo.supportedResult &&
776
+ !levelInfo.supportedResult.decodingInfoResults?.[0].smooth)
777
777
  ) {
778
778
  levelsSkipped.push(i);
779
779
  continue;
@@ -832,8 +832,8 @@ class AbrController extends Logger implements AbrComponentAPI {
832
832
  (forcedAutoLevel === -1 || forcedAutoLevel !== loadLevel)
833
833
  ) {
834
834
  if (levelsSkipped.length) {
835
- this.trace(
836
- `Skipped level(s) ${levelsSkipped.join(
835
+ logger.trace(
836
+ `[abr] Skipped level(s) ${levelsSkipped.join(
837
837
  ',',
838
838
  )} of ${maxAutoLevel} max with CODECS and VIDEO-RANGE:"${
839
839
  levels[levelsSkipped[0]].codecs
@@ -842,8 +842,8 @@ class AbrController extends Logger implements AbrComponentAPI {
842
842
  }" ${currentVideoRange}`,
843
843
  );
844
844
  }
845
- this.info(
846
- `switch candidate:${selectionBaseLevel}->${i} adjustedbw(${Math.round(
845
+ logger.info(
846
+ `[abr] switch candidate:${selectionBaseLevel}->${i} adjustedbw(${Math.round(
847
847
  adjustedbw,
848
848
  )})-bitrate=${Math.round(
849
849
  adjustedbw - bitrate,
@@ -71,27 +71,30 @@ class AudioStreamController
71
71
  hls,
72
72
  fragmentTracker,
73
73
  keyLoader,
74
- 'audio-stream-controller',
74
+ '[audio-stream-controller]',
75
75
  PlaylistLevelType.AUDIO,
76
76
  );
77
- this.registerListeners();
77
+ this._registerListeners();
78
78
  }
79
79
 
80
80
  protected onHandlerDestroying() {
81
- this.unregisterListeners();
81
+ this._unregisterListeners();
82
82
  super.onHandlerDestroying();
83
83
  this.mainDetails = null;
84
84
  this.bufferedTrack = null;
85
85
  this.switchingTrack = null;
86
86
  }
87
87
 
88
- protected registerListeners() {
89
- super.registerListeners();
88
+ private _registerListeners() {
90
89
  const { hls } = this;
90
+ hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
91
+ hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
92
+ hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
91
93
  hls.on(Events.LEVEL_LOADED, this.onLevelLoaded, this);
92
94
  hls.on(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
93
95
  hls.on(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
94
96
  hls.on(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
97
+ hls.on(Events.ERROR, this.onError, this);
95
98
  hls.on(Events.BUFFER_RESET, this.onBufferReset, this);
96
99
  hls.on(Events.BUFFER_CREATED, this.onBufferCreated, this);
97
100
  hls.on(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
@@ -100,16 +103,16 @@ class AudioStreamController
100
103
  hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
101
104
  }
102
105
 
103
- protected unregisterListeners() {
106
+ private _unregisterListeners() {
104
107
  const { hls } = this;
105
- if (!hls) {
106
- return;
107
- }
108
- super.unregisterListeners();
108
+ hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
109
+ hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
110
+ hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
109
111
  hls.off(Events.LEVEL_LOADED, this.onLevelLoaded, this);
110
112
  hls.off(Events.AUDIO_TRACKS_UPDATED, this.onAudioTracksUpdated, this);
111
113
  hls.off(Events.AUDIO_TRACK_SWITCHING, this.onAudioTrackSwitching, this);
112
114
  hls.off(Events.AUDIO_TRACK_LOADED, this.onAudioTrackLoaded, this);
115
+ hls.off(Events.ERROR, this.onError, this);
113
116
  hls.off(Events.BUFFER_RESET, this.onBufferReset, this);
114
117
  hls.off(Events.BUFFER_CREATED, this.onBufferCreated, this);
115
118
  hls.off(Events.BUFFER_FLUSHING, this.onBufferFlushing, this);
@@ -710,7 +713,7 @@ class AudioStreamController
710
713
  this.fragBufferedComplete(frag, part);
711
714
  }
712
715
 
713
- protected onError(event: Events.ERROR, data: ErrorData) {
716
+ private onError(event: Events.ERROR, data: ErrorData) {
714
717
  if (data.fatal) {
715
718
  this.state = State.ERROR;
716
719
  return;
@@ -33,7 +33,7 @@ class AudioTrackController extends BasePlaylistController {
33
33
  private selectDefaultTrack: boolean = true;
34
34
 
35
35
  constructor(hls: Hls) {
36
- super(hls, 'audio-track-controller');
36
+ super(hls, '[audio-track-controller]');
37
37
  this.registerListeners();
38
38
  }
39
39
 
@@ -5,7 +5,7 @@ import { computeReloadInterval, mergeDetails } from '../utils/level-helper';
5
5
  import { ErrorData } from '../types/events';
6
6
  import { getRetryDelay, isTimeoutError } from '../utils/error-helper';
7
7
  import { NetworkErrorAction } from './error-controller';
8
- import { Logger } from '../utils/logger';
8
+ import { logger } from '../utils/logger';
9
9
  import type { LevelDetails } from '../loader/level-details';
10
10
  import type { MediaPlaylist } from '../types/media-playlist';
11
11
  import type {
@@ -14,17 +14,17 @@ import type {
14
14
  TrackLoadedData,
15
15
  } from '../types/events';
16
16
 
17
- export default class BasePlaylistController
18
- extends Logger
19
- implements NetworkComponentAPI
20
- {
17
+ export default class BasePlaylistController implements NetworkComponentAPI {
21
18
  protected hls: Hls;
22
19
  protected timer: number = -1;
23
20
  protected requestScheduled: number = -1;
24
21
  protected canLoad: boolean = false;
22
+ protected log: (msg: any) => void;
23
+ protected warn: (msg: any) => void;
25
24
 
26
25
  constructor(hls: Hls, logPrefix: string) {
27
- super(logPrefix, hls.logger);
26
+ this.log = logger.log.bind(logger, `${logPrefix}:`);
27
+ this.warn = logger.warn.bind(logger, `${logPrefix}:`);
28
28
  this.hls = hls;
29
29
  }
30
30
 
@@ -65,7 +65,7 @@ export default class BasePlaylistController
65
65
  try {
66
66
  uri = new self.URL(attr.URI, previous.url).href;
67
67
  } catch (error) {
68
- this.warn(
68
+ logger.warn(
69
69
  `Could not construct new URL for Rendition Report: ${error}`,
70
70
  );
71
71
  uri = attr.URI || '';
@@ -1,15 +1,12 @@
1
1
  import TaskLoop from '../task-loop';
2
2
  import { FragmentState } from './fragment-tracker';
3
3
  import { Bufferable, BufferHelper, BufferInfo } from '../utils/buffer-helper';
4
+ import { logger } from '../utils/logger';
4
5
  import { Events } from '../events';
5
6
  import { ErrorDetails, ErrorTypes } from '../errors';
6
7
  import { ChunkMetadata } from '../types/transmuxer';
7
8
  import { appendUint8Array } from '../utils/mp4-tools';
8
9
  import { alignStream } from '../utils/discontinuities';
9
- import {
10
- isFullSegmentEncryption,
11
- getAesModeFromFullSegmentMethod,
12
- } from '../utils/encryption-methods-util';
13
10
  import {
14
11
  findFragmentByPDT,
15
12
  findFragmentByPTS,
@@ -100,6 +97,12 @@ export default class BaseStreamController
100
97
  protected startFragRequested: boolean = false;
101
98
  protected decrypter: Decrypter;
102
99
  protected initPTS: RationalTimestamp[] = [];
100
+ protected onvseeking: EventListener | null = null;
101
+ protected onvended: EventListener | null = null;
102
+
103
+ private readonly logPrefix: string = '';
104
+ protected log: (msg: any) => void;
105
+ protected warn: (msg: any) => void;
103
106
 
104
107
  constructor(
105
108
  hls: Hls,
@@ -108,32 +111,18 @@ export default class BaseStreamController
108
111
  logPrefix: string,
109
112
  playlistType: PlaylistLevelType,
110
113
  ) {
111
- super(logPrefix, hls.logger);
114
+ super();
112
115
  this.playlistType = playlistType;
116
+ this.logPrefix = logPrefix;
117
+ this.log = logger.log.bind(logger, `${logPrefix}:`);
118
+ this.warn = logger.warn.bind(logger, `${logPrefix}:`);
113
119
  this.hls = hls;
114
120
  this.fragmentLoader = new FragmentLoader(hls.config);
115
121
  this.keyLoader = keyLoader;
116
122
  this.fragmentTracker = fragmentTracker;
117
123
  this.config = hls.config;
118
124
  this.decrypter = new Decrypter(hls.config);
119
- }
120
-
121
- protected registerListeners() {
122
- const { hls } = this;
123
- hls.on(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
124
- hls.on(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
125
- hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
126
125
  hls.on(Events.MANIFEST_LOADED, this.onManifestLoaded, this);
127
- hls.on(Events.ERROR, this.onError, this);
128
- }
129
-
130
- protected unregisterListeners() {
131
- const { hls } = this;
132
- hls.off(Events.MEDIA_ATTACHED, this.onMediaAttached, this);
133
- hls.off(Events.MEDIA_DETACHING, this.onMediaDetaching, this);
134
- hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
135
- hls.off(Events.MANIFEST_LOADED, this.onManifestLoaded, this);
136
- hls.off(Events.ERROR, this.onError, this);
137
126
  }
138
127
 
139
128
  protected doTick() {
@@ -208,8 +197,10 @@ export default class BaseStreamController
208
197
  data: MediaAttachedData,
209
198
  ) {
210
199
  const media = (this.media = this.mediaBuffer = data.media);
211
- media.addEventListener('seeking', this.onMediaSeeking);
212
- media.addEventListener('ended', this.onMediaEnded);
200
+ this.onvseeking = this.onMediaSeeking.bind(this) as EventListener;
201
+ this.onvended = this.onMediaEnded.bind(this) as EventListener;
202
+ media.addEventListener('seeking', this.onvseeking);
203
+ media.addEventListener('ended', this.onvended);
213
204
  const config = this.config;
214
205
  if (this.levels && config.autoStartLoad && this.state === State.STOPPED) {
215
206
  this.startLoad(config.startPosition);
@@ -224,9 +215,10 @@ export default class BaseStreamController
224
215
  }
225
216
 
226
217
  // remove video listeners
227
- if (media) {
228
- media.removeEventListener('seeking', this.onMediaSeeking);
229
- media.removeEventListener('ended', this.onMediaEnded);
218
+ if (media && this.onvseeking && this.onvended) {
219
+ media.removeEventListener('seeking', this.onvseeking);
220
+ media.removeEventListener('ended', this.onvended);
221
+ this.onvseeking = this.onvended = null;
230
222
  }
231
223
  if (this.keyLoader) {
232
224
  this.keyLoader.detach();
@@ -237,11 +229,7 @@ export default class BaseStreamController
237
229
  this.stopLoad();
238
230
  }
239
231
 
240
- protected onManifestLoading() {}
241
-
242
- protected onError(event: Events.ERROR, data: ErrorData) {}
243
-
244
- protected onMediaSeeking = () => {
232
+ protected onMediaSeeking() {
245
233
  const { config, fragCurrent, media, mediaBuffer, state } = this;
246
234
  const currentTime: number = media ? media.currentTime : 0;
247
235
  const bufferInfo = BufferHelper.bufferInfo(
@@ -304,17 +292,12 @@ export default class BaseStreamController
304
292
 
305
293
  // Async tick to speed up processing
306
294
  this.tickImmediate();
307
- };
295
+ }
308
296
 
309
- protected onMediaEnded = () => {
297
+ protected onMediaEnded() {
310
298
  // reset startPosition and lastCurrentTime to restart playback @ stream beginning
311
299
  this.startPosition = this.lastCurrentTime = 0;
312
- if (this.playlistType === PlaylistLevelType.MAIN) {
313
- this.hls.trigger(Events.MEDIA_ENDED, {
314
- stalled: false,
315
- });
316
- }
317
- };
300
+ }
318
301
 
319
302
  protected onManifestLoaded(
320
303
  event: Events.MANIFEST_LOADED,
@@ -329,7 +312,7 @@ export default class BaseStreamController
329
312
  this.stopLoad();
330
313
  super.onHandlerDestroying();
331
314
  // @ts-ignore
332
- this.hls = this.onMediaSeeking = this.onMediaEnded = null;
315
+ this.hls = null;
333
316
  }
334
317
 
335
318
  protected onHandlerDestroyed() {
@@ -503,7 +486,7 @@ export default class BaseStreamController
503
486
  payload.byteLength > 0 &&
504
487
  decryptData?.key &&
505
488
  decryptData.iv &&
506
- isFullSegmentEncryption(decryptData.method)
489
+ decryptData.method === 'AES-128'
507
490
  ) {
508
491
  const startTime = self.performance.now();
509
492
  // decrypt init segment data
@@ -512,7 +495,6 @@ export default class BaseStreamController
512
495
  new Uint8Array(payload),
513
496
  decryptData.key.buffer,
514
497
  decryptData.iv.buffer,
515
- getAesModeFromFullSegmentMethod(decryptData.method),
516
498
  )
517
499
  .catch((err) => {
518
500
  hls.trigger(Events.ERROR, {
@@ -667,7 +649,7 @@ export default class BaseStreamController
667
649
  if (frag.encrypted && !frag.decryptdata?.key) {
668
650
  this.log(
669
651
  `Loading key for ${frag.sn} of [${details.startSN}-${details.endSN}], ${
670
- this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track'
652
+ this.logPrefix === '[stream-controller]' ? 'level' : 'track'
671
653
  } ${frag.level}`,
672
654
  );
673
655
  this.state = State.KEY_LOADING;
@@ -707,7 +689,7 @@ export default class BaseStreamController
707
689
  } of playlist [${details.startSN}-${
708
690
  details.endSN
709
691
  }] parts [0-${partIndex}-${partList.length - 1}] ${
710
- this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track'
692
+ this.logPrefix === '[stream-controller]' ? 'level' : 'track'
711
693
  }: ${frag.level}, target: ${parseFloat(
712
694
  targetBufferTime.toFixed(3),
713
695
  )}`,
@@ -766,7 +748,7 @@ export default class BaseStreamController
766
748
  this.log(
767
749
  `Loading fragment ${frag.sn} cc: ${frag.cc} ${
768
750
  details ? 'of [' + details.startSN + '-' + details.endSN + '] ' : ''
769
- }${this.playlistType === PlaylistLevelType.MAIN ? 'level' : 'track'}: ${
751
+ }${this.logPrefix === '[stream-controller]' ? 'level' : 'track'}: ${
770
752
  frag.level
771
753
  }, target: ${parseFloat(targetBufferTime.toFixed(3))}`,
772
754
  );
@@ -1568,7 +1550,7 @@ export default class BaseStreamController
1568
1550
  errorAction.resolved = true;
1569
1551
  }
1570
1552
  } else {
1571
- this.warn(
1553
+ logger.warn(
1572
1554
  `${data.details} reached or exceeded max retry (${retryCount})`,
1573
1555
  );
1574
1556
  return;
@@ -1,5 +1,5 @@
1
1
  import { Events } from '../events';
2
- import { Logger } from '../utils/logger';
2
+ import { logger } from '../utils/logger';
3
3
  import { ErrorDetails, ErrorTypes } from '../errors';
4
4
  import { BufferHelper } from '../utils/buffer-helper';
5
5
  import {
@@ -42,7 +42,7 @@ interface BufferedChangeEvent extends Event {
42
42
  readonly removedRanges?: TimeRanges;
43
43
  }
44
44
 
45
- export default class BufferController extends Logger implements ComponentAPI {
45
+ export default class BufferController implements ComponentAPI {
46
46
  // The level details used to determine duration, target-duration and live
47
47
  private details: LevelDetails | null = null;
48
48
  // cache the self generated object url to detect hijack of video tag
@@ -82,10 +82,17 @@ export default class BufferController extends Logger implements ComponentAPI {
82
82
  public pendingTracks: TrackSet = {};
83
83
  public sourceBuffer!: SourceBuffers;
84
84
 
85
+ protected log: (msg: any) => void;
86
+ protected warn: (msg: any, obj?: any) => void;
87
+ protected error: (msg: any, obj?: any) => void;
88
+
85
89
  constructor(hls: Hls) {
86
- super('buffer-controller', hls.logger);
87
90
  this.hls = hls;
91
+ const logPrefix = '[buffer-controller]';
88
92
  this.appendSource = hls.config.preferManagedMediaSource;
93
+ this.log = logger.log.bind(logger, logPrefix);
94
+ this.warn = logger.warn.bind(logger, logPrefix);
95
+ this.error = logger.error.bind(logger, logPrefix);
89
96
  this._initSourceBuffer();
90
97
  this.registerListeners();
91
98
  }
@@ -103,12 +110,6 @@ export default class BufferController extends Logger implements ComponentAPI {
103
110
  this.lastMpegAudioChunk = null;
104
111
  // @ts-ignore
105
112
  this.hls = null;
106
- // @ts-ignore
107
- this._onMediaSourceOpen = this._onMediaSourceClose = null;
108
- // @ts-ignore
109
- this._onMediaSourceEnded = null;
110
- // @ts-ignore
111
- this._onStartStreaming = this._onEndStreaming = null;
112
113
  }
113
114
 
114
115
  protected registerListeners() {
@@ -1003,7 +1004,7 @@ export default class BufferController extends Logger implements ComponentAPI {
1003
1004
  private _onMediaEmptied = () => {
1004
1005
  const { mediaSrc, _objectUrl } = this;
1005
1006
  if (mediaSrc !== _objectUrl) {
1006
- this.error(
1007
+ logger.error(
1007
1008
  `Media element src was set while attaching MediaSource (${_objectUrl} > ${mediaSrc})`,
1008
1009
  );
1009
1010
  }
@@ -12,6 +12,7 @@ import type {
12
12
  LevelsUpdatedData,
13
13
  } from '../types/events';
14
14
  import StreamController from './stream-controller';
15
+ import { logger } from '../utils/logger';
15
16
  import type { ComponentAPI } from '../types/component-api';
16
17
  import type Hls from '../hls';
17
18
 
@@ -151,7 +152,7 @@ class CapLevelController implements ComponentAPI {
151
152
  const hls = this.hls;
152
153
  const maxLevel = this.getMaxLevel(levels.length - 1);
153
154
  if (maxLevel !== this.autoLevelCapping) {
154
- hls.logger.log(
155
+ logger.log(
155
156
  `Setting autoLevelCapping to ${maxLevel}: ${levels[maxLevel].height}p@${levels[maxLevel].bitrate} for media ${this.mediaWidth}x${this.mediaHeight}`,
156
157
  );
157
158
  }
@@ -5,7 +5,6 @@ import { CmcdObjectType } from '@svta/common-media-library/cmcd/CmcdObjectType';
5
5
  import { CmcdStreamingFormat } from '@svta/common-media-library/cmcd/CmcdStreamingFormat';
6
6
  import { appendCmcdHeaders } from '@svta/common-media-library/cmcd/appendCmcdHeaders';
7
7
  import { appendCmcdQuery } from '@svta/common-media-library/cmcd/appendCmcdQuery';
8
- import type { CmcdEncodeOptions } from '@svta/common-media-library/cmcd/CmcdEncodeOptions';
9
8
  import { uuid } from '@svta/common-media-library/utils/uuid';
10
9
  import { BufferHelper } from '../utils/buffer-helper';
11
10
  import { logger } from '../utils/logger';
@@ -166,7 +165,7 @@ export default class CMCDController implements ComponentAPI {
166
165
  data.su = this.buffering;
167
166
  }
168
167
 
169
- // TODO: Implement rtp, nrr, dl
168
+ // TODO: Implement rtp, nrr, nor, dl
170
169
 
171
170
  const { includeKeys } = this;
172
171
  if (includeKeys) {
@@ -176,18 +175,14 @@ export default class CMCDController implements ComponentAPI {
176
175
  }, {});
177
176
  }
178
177
 
179
- const options: CmcdEncodeOptions = {
180
- baseUrl: context.url,
181
- };
182
-
183
178
  if (this.useHeaders) {
184
179
  if (!context.headers) {
185
180
  context.headers = {};
186
181
  }
187
182
 
188
- appendCmcdHeaders(context.headers, data, options);
183
+ appendCmcdHeaders(context.headers, data);
189
184
  } else {
190
- context.url = appendCmcdQuery(context.url, data, options);
185
+ context.url = appendCmcdQuery(context.url, data);
191
186
  }
192
187
  }
193
188
 
@@ -228,29 +223,12 @@ export default class CMCDController implements ComponentAPI {
228
223
  data.bl = this.getBufferLength(ot);
229
224
  }
230
225
 
231
- const next = this.getNextFrag(fragment);
232
- if (next) {
233
- if (next.url && next.url !== fragment.url) {
234
- data.nor = next.url;
235
- }
236
- }
237
-
238
226
  this.apply(context, data);
239
227
  } catch (error) {
240
228
  logger.warn('Could not generate segment CMCD data.', error);
241
229
  }
242
230
  };
243
231
 
244
- private getNextFrag(fragment: Fragment): Fragment | undefined {
245
- const levelDetails = this.hls.levels[fragment.level]?.details;
246
- if (levelDetails) {
247
- const index = (fragment.sn as number) - levelDetails.startSN;
248
- return levelDetails.fragments[index + 1];
249
- }
250
-
251
- return undefined;
252
- }
253
-
254
232
  /**
255
233
  * The CMCD object type.
256
234
  */