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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) 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 +1169 -2069
  5. package/dist/hls.js.d.ts +51 -65
  6. package/dist/hls.js.map +1 -1
  7. package/dist/hls.light.js +875 -1158
  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 +709 -993
  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 +869 -1756
  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 +40 -31
  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 +34 -27
  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/utils/mp4-tools.ts +6 -4
  67. package/src/crypt/decrypter-aes-mode.ts +0 -4
  68. package/src/demux/video/hevc-video-parser.ts +0 -746
  69. package/src/utils/encryption-methods-util.ts +0 -21
@@ -1,15 +1,12 @@
1
1
  import type { ParsedVideoSample } from '../tsdemuxer';
2
- import type {
2
+ import {
3
3
  DemuxedVideoTrack,
4
- DemuxedUserdataTrack,
5
4
  VideoSample,
6
5
  VideoSampleUnit,
7
6
  } from '../../types/demuxer';
8
- import type { PES } from '../tsdemuxer';
9
7
  import { logger } from '../../utils/logger';
10
- import { appendUint8Array } from '../../utils/mp4-tools';
11
8
 
12
- abstract class BaseVideoParser {
9
+ class BaseVideoParser {
13
10
  protected VideoSample: ParsedVideoSample | null = null;
14
11
 
15
12
  protected createVideoSample(
@@ -72,135 +69,6 @@ abstract class BaseVideoParser {
72
69
  );
73
70
  }
74
71
  }
75
-
76
- abstract parsePES(
77
- track: DemuxedVideoTrack,
78
- textTrack: DemuxedUserdataTrack,
79
- pes: PES,
80
- last: boolean,
81
- duration: number,
82
- );
83
-
84
- protected abstract getNALuType(data: Uint8Array, offset: number): number;
85
-
86
- protected parseNALu(
87
- track: DemuxedVideoTrack,
88
- array: Uint8Array,
89
- ): Array<{
90
- data: Uint8Array;
91
- type: number;
92
- state?: number;
93
- }> {
94
- const len = array.byteLength;
95
- let state = track.naluState || 0;
96
- const lastState = state;
97
- const units: VideoSampleUnit[] = [];
98
- let i = 0;
99
- let value: number;
100
- let overflow: number;
101
- let unitType: number;
102
- let lastUnitStart = -1;
103
- let lastUnitType: number = 0;
104
- // logger.log('PES:' + Hex.hexDump(array));
105
-
106
- if (state === -1) {
107
- // special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet
108
- lastUnitStart = 0;
109
- // NALu type is value read from offset 0
110
- lastUnitType = this.getNALuType(array, 0);
111
- state = 0;
112
- i = 1;
113
- }
114
-
115
- while (i < len) {
116
- value = array[i++];
117
- // optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case
118
- if (!state) {
119
- state = value ? 0 : 1;
120
- continue;
121
- }
122
- if (state === 1) {
123
- state = value ? 0 : 2;
124
- continue;
125
- }
126
- // here we have state either equal to 2 or 3
127
- if (!value) {
128
- state = 3;
129
- } else if (value === 1) {
130
- overflow = i - state - 1;
131
- if (lastUnitStart >= 0) {
132
- const unit: VideoSampleUnit = {
133
- data: array.subarray(lastUnitStart, overflow),
134
- type: lastUnitType,
135
- };
136
- // logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);
137
- units.push(unit);
138
- } else {
139
- // lastUnitStart is undefined => this is the first start code found in this PES packet
140
- // first check if start code delimiter is overlapping between 2 PES packets,
141
- // ie it started in last packet (lastState not zero)
142
- // and ended at the beginning of this PES packet (i <= 4 - lastState)
143
- const lastUnit = this.getLastNalUnit(track.samples);
144
- if (lastUnit) {
145
- if (lastState && i <= 4 - lastState) {
146
- // start delimiter overlapping between PES packets
147
- // strip start delimiter bytes from the end of last NAL unit
148
- // check if lastUnit had a state different from zero
149
- if (lastUnit.state) {
150
- // strip last bytes
151
- lastUnit.data = lastUnit.data.subarray(
152
- 0,
153
- lastUnit.data.byteLength - lastState,
154
- );
155
- }
156
- }
157
- // If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.
158
-
159
- if (overflow > 0) {
160
- // logger.log('first NALU found with overflow:' + overflow);
161
- lastUnit.data = appendUint8Array(
162
- lastUnit.data,
163
- array.subarray(0, overflow),
164
- );
165
- lastUnit.state = 0;
166
- }
167
- }
168
- }
169
- // check if we can read unit type
170
- if (i < len) {
171
- unitType = this.getNALuType(array, i);
172
- // logger.log('find NALU @ offset:' + i + ',type:' + unitType);
173
- lastUnitStart = i;
174
- lastUnitType = unitType;
175
- state = 0;
176
- } else {
177
- // not enough byte to read unit type. let's read it on next PES parsing
178
- state = -1;
179
- }
180
- } else {
181
- state = 0;
182
- }
183
- }
184
- if (lastUnitStart >= 0 && state >= 0) {
185
- const unit: VideoSampleUnit = {
186
- data: array.subarray(lastUnitStart, len),
187
- type: lastUnitType,
188
- state: state,
189
- };
190
- units.push(unit);
191
- // logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
192
- }
193
- // no NALu found
194
- if (units.length === 0) {
195
- // append pes.data to previous NAL unit
196
- const lastUnit = this.getLastNalUnit(track.samples);
197
- if (lastUnit) {
198
- lastUnit.data = appendUint8Array(lastUnit.data, array);
199
- }
200
- }
201
- track.naluState = state;
202
- return units;
203
- }
204
72
  }
205
73
 
206
74
  export default BaseVideoParser;
@@ -148,6 +148,214 @@ class ExpGolomb {
148
148
  readUInt(): number {
149
149
  return this.readBits(32);
150
150
  }
151
+
152
+ /**
153
+ * Advance the ExpGolomb decoder past a scaling list. The scaling
154
+ * list is optionally transmitted as part of a sequence parameter
155
+ * set and is not relevant to transmuxing.
156
+ * @param count the number of entries in this scaling list
157
+ * @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
158
+ */
159
+ skipScalingList(count: number): void {
160
+ let lastScale = 8;
161
+ let nextScale = 8;
162
+ let deltaScale;
163
+ for (let j = 0; j < count; j++) {
164
+ if (nextScale !== 0) {
165
+ deltaScale = this.readEG();
166
+ nextScale = (lastScale + deltaScale + 256) % 256;
167
+ }
168
+ lastScale = nextScale === 0 ? lastScale : nextScale;
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Read a sequence parameter set and return some interesting video
174
+ * properties. A sequence parameter set is the H264 metadata that
175
+ * describes the properties of upcoming video frames.
176
+ * @returns an object with configuration parsed from the
177
+ * sequence parameter set, including the dimensions of the
178
+ * associated video frames.
179
+ */
180
+ readSPS(): {
181
+ width: number;
182
+ height: number;
183
+ pixelRatio: [number, number];
184
+ } {
185
+ let frameCropLeftOffset = 0;
186
+ let frameCropRightOffset = 0;
187
+ let frameCropTopOffset = 0;
188
+ let frameCropBottomOffset = 0;
189
+ let numRefFramesInPicOrderCntCycle;
190
+ let scalingListCount;
191
+ let i;
192
+ const readUByte = this.readUByte.bind(this);
193
+ const readBits = this.readBits.bind(this);
194
+ const readUEG = this.readUEG.bind(this);
195
+ const readBoolean = this.readBoolean.bind(this);
196
+ const skipBits = this.skipBits.bind(this);
197
+ const skipEG = this.skipEG.bind(this);
198
+ const skipUEG = this.skipUEG.bind(this);
199
+ const skipScalingList = this.skipScalingList.bind(this);
200
+
201
+ readUByte();
202
+ const profileIdc = readUByte(); // profile_idc
203
+ readBits(5); // profileCompat constraint_set[0-4]_flag, u(5)
204
+ skipBits(3); // reserved_zero_3bits u(3),
205
+ readUByte(); // level_idc u(8)
206
+ skipUEG(); // seq_parameter_set_id
207
+ // some profiles have more optional data we don't need
208
+ if (
209
+ profileIdc === 100 ||
210
+ profileIdc === 110 ||
211
+ profileIdc === 122 ||
212
+ profileIdc === 244 ||
213
+ profileIdc === 44 ||
214
+ profileIdc === 83 ||
215
+ profileIdc === 86 ||
216
+ profileIdc === 118 ||
217
+ profileIdc === 128
218
+ ) {
219
+ const chromaFormatIdc = readUEG();
220
+ if (chromaFormatIdc === 3) {
221
+ skipBits(1);
222
+ } // separate_colour_plane_flag
223
+
224
+ skipUEG(); // bit_depth_luma_minus8
225
+ skipUEG(); // bit_depth_chroma_minus8
226
+ skipBits(1); // qpprime_y_zero_transform_bypass_flag
227
+ if (readBoolean()) {
228
+ // seq_scaling_matrix_present_flag
229
+ scalingListCount = chromaFormatIdc !== 3 ? 8 : 12;
230
+ for (i = 0; i < scalingListCount; i++) {
231
+ if (readBoolean()) {
232
+ // seq_scaling_list_present_flag[ i ]
233
+ if (i < 6) {
234
+ skipScalingList(16);
235
+ } else {
236
+ skipScalingList(64);
237
+ }
238
+ }
239
+ }
240
+ }
241
+ }
242
+ skipUEG(); // log2_max_frame_num_minus4
243
+ const picOrderCntType = readUEG();
244
+ if (picOrderCntType === 0) {
245
+ readUEG(); // log2_max_pic_order_cnt_lsb_minus4
246
+ } else if (picOrderCntType === 1) {
247
+ skipBits(1); // delta_pic_order_always_zero_flag
248
+ skipEG(); // offset_for_non_ref_pic
249
+ skipEG(); // offset_for_top_to_bottom_field
250
+ numRefFramesInPicOrderCntCycle = readUEG();
251
+ for (i = 0; i < numRefFramesInPicOrderCntCycle; i++) {
252
+ skipEG();
253
+ } // offset_for_ref_frame[ i ]
254
+ }
255
+ skipUEG(); // max_num_ref_frames
256
+ skipBits(1); // gaps_in_frame_num_value_allowed_flag
257
+ const picWidthInMbsMinus1 = readUEG();
258
+ const picHeightInMapUnitsMinus1 = readUEG();
259
+ const frameMbsOnlyFlag = readBits(1);
260
+ if (frameMbsOnlyFlag === 0) {
261
+ skipBits(1);
262
+ } // mb_adaptive_frame_field_flag
263
+
264
+ skipBits(1); // direct_8x8_inference_flag
265
+ if (readBoolean()) {
266
+ // frame_cropping_flag
267
+ frameCropLeftOffset = readUEG();
268
+ frameCropRightOffset = readUEG();
269
+ frameCropTopOffset = readUEG();
270
+ frameCropBottomOffset = readUEG();
271
+ }
272
+ let pixelRatio: [number, number] = [1, 1];
273
+ if (readBoolean()) {
274
+ // vui_parameters_present_flag
275
+ if (readBoolean()) {
276
+ // aspect_ratio_info_present_flag
277
+ const aspectRatioIdc = readUByte();
278
+ switch (aspectRatioIdc) {
279
+ case 1:
280
+ pixelRatio = [1, 1];
281
+ break;
282
+ case 2:
283
+ pixelRatio = [12, 11];
284
+ break;
285
+ case 3:
286
+ pixelRatio = [10, 11];
287
+ break;
288
+ case 4:
289
+ pixelRatio = [16, 11];
290
+ break;
291
+ case 5:
292
+ pixelRatio = [40, 33];
293
+ break;
294
+ case 6:
295
+ pixelRatio = [24, 11];
296
+ break;
297
+ case 7:
298
+ pixelRatio = [20, 11];
299
+ break;
300
+ case 8:
301
+ pixelRatio = [32, 11];
302
+ break;
303
+ case 9:
304
+ pixelRatio = [80, 33];
305
+ break;
306
+ case 10:
307
+ pixelRatio = [18, 11];
308
+ break;
309
+ case 11:
310
+ pixelRatio = [15, 11];
311
+ break;
312
+ case 12:
313
+ pixelRatio = [64, 33];
314
+ break;
315
+ case 13:
316
+ pixelRatio = [160, 99];
317
+ break;
318
+ case 14:
319
+ pixelRatio = [4, 3];
320
+ break;
321
+ case 15:
322
+ pixelRatio = [3, 2];
323
+ break;
324
+ case 16:
325
+ pixelRatio = [2, 1];
326
+ break;
327
+ case 255: {
328
+ pixelRatio = [
329
+ (readUByte() << 8) | readUByte(),
330
+ (readUByte() << 8) | readUByte(),
331
+ ];
332
+ break;
333
+ }
334
+ }
335
+ }
336
+ }
337
+ return {
338
+ width: Math.ceil(
339
+ (picWidthInMbsMinus1 + 1) * 16 -
340
+ frameCropLeftOffset * 2 -
341
+ frameCropRightOffset * 2,
342
+ ),
343
+ height:
344
+ (2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16 -
345
+ (frameMbsOnlyFlag ? 2 : 4) *
346
+ (frameCropTopOffset + frameCropBottomOffset),
347
+ pixelRatio: pixelRatio,
348
+ };
349
+ }
350
+
351
+ readSliceType() {
352
+ // skip NALu type
353
+ this.readUByte();
354
+ // discard first_mb_in_slice
355
+ this.readUEG();
356
+ // return slice_type
357
+ return this.readUEG();
358
+ }
151
359
  }
152
360
 
153
361
  export default ExpGolomb;
package/src/events.ts CHANGED
@@ -3,7 +3,6 @@ import {
3
3
  ManifestLoadingData,
4
4
  MediaAttachedData,
5
5
  MediaAttachingData,
6
- MediaEndedData,
7
6
  LevelLoadingData,
8
7
  LevelLoadedData,
9
8
  ManifestParsedData,
@@ -61,8 +60,6 @@ export enum Events {
61
60
  MEDIA_DETACHING = 'hlsMediaDetaching',
62
61
  // Fired when MediaSource has been detached from media element
63
62
  MEDIA_DETACHED = 'hlsMediaDetached',
64
- // Fired when HTMLMediaElement dispatches "ended" event, or stalls at end of VOD program
65
- MEDIA_ENDED = 'hlsMediaEnded',
66
63
  // Fired when the buffer is going to be reset
67
64
  BUFFER_RESET = 'hlsBufferReset',
68
65
  // Fired when we know about the codecs that we need buffers for to push into - data: {tracks : { container, codec, levelCodec, initSegment, metadata }}
@@ -187,10 +184,6 @@ export interface HlsListeners {
187
184
  ) => void;
188
185
  [Events.MEDIA_DETACHING]: (event: Events.MEDIA_DETACHING) => void;
189
186
  [Events.MEDIA_DETACHED]: (event: Events.MEDIA_DETACHED) => void;
190
- [Events.MEDIA_ENDED]: (
191
- event: Events.MEDIA_ENDED,
192
- data: MediaEndedData,
193
- ) => void;
194
187
  [Events.BUFFER_RESET]: (event: Events.BUFFER_RESET) => void;
195
188
  [Events.BUFFER_CODECS]: (
196
189
  event: Events.BUFFER_CODECS,
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;
@@ -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
@@ -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,7 +354,7 @@ 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();
@@ -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
  }
@@ -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 &&
@@ -439,7 +428,8 @@ export default class Hls implements HlsEventEmitter {
439
428
  * Defaults to -1 (None: starts from earliest point)
440
429
  */
441
430
  startLoad(startPosition: number = -1) {
442
- this.logger.log(`startLoad(${startPosition})`);
431
+ logger.log(`startLoad(${startPosition})`);
432
+ this.started = true;
443
433
  this.networkControllers.forEach((controller) => {
444
434
  controller.startLoad(startPosition);
445
435
  });
@@ -449,31 +439,34 @@ export default class Hls implements HlsEventEmitter {
449
439
  * Stop loading of any stream data.
450
440
  */
451
441
  stopLoad() {
452
- this.logger.log('stopLoad');
442
+ logger.log('stopLoad');
443
+ this.started = false;
453
444
  this.networkControllers.forEach((controller) => {
454
445
  controller.stopLoad();
455
446
  });
456
447
  }
457
448
 
458
449
  /**
459
- * Resumes stream controller segment loading after `pauseBuffering` has been called.
450
+ * Resumes stream controller segment loading if previously started.
460
451
  */
461
452
  resumeBuffering() {
462
- this.networkControllers.forEach((controller) => {
463
- if (controller.resumeBuffering) {
464
- controller.resumeBuffering();
465
- }
466
- });
453
+ if (this.started) {
454
+ this.networkControllers.forEach((controller) => {
455
+ if ('fragmentLoader' in controller) {
456
+ controller.startLoad(-1);
457
+ }
458
+ });
459
+ }
467
460
  }
468
461
 
469
462
  /**
470
- * Prevents stream controller from loading new segments until `resumeBuffering` is called.
463
+ * Stops stream controller segment loading without changing 'started' state like stopLoad().
471
464
  * This allows for media buffering to be paused without interupting playlist loading.
472
465
  */
473
466
  pauseBuffering() {
474
467
  this.networkControllers.forEach((controller) => {
475
- if (controller.pauseBuffering) {
476
- controller.pauseBuffering();
468
+ if ('fragmentLoader' in controller) {
469
+ controller.stopLoad();
477
470
  }
478
471
  });
479
472
  }
@@ -482,7 +475,7 @@ export default class Hls implements HlsEventEmitter {
482
475
  * Swap through possible audio codecs in the stream (for example to switch from stereo to 5.1)
483
476
  */
484
477
  swapAudioCodec() {
485
- this.logger.log('swapAudioCodec');
478
+ logger.log('swapAudioCodec');
486
479
  this.streamController.swapAudioCodec();
487
480
  }
488
481
 
@@ -493,7 +486,7 @@ export default class Hls implements HlsEventEmitter {
493
486
  * Automatic recovery of media-errors by this process is configurable.
494
487
  */
495
488
  recoverMediaError() {
496
- this.logger.log('recoverMediaError');
489
+ logger.log('recoverMediaError');
497
490
  const media = this._media;
498
491
  this.detachMedia();
499
492
  if (media) {
@@ -524,7 +517,7 @@ export default class Hls implements HlsEventEmitter {
524
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.
525
518
  */
526
519
  set currentLevel(newLevel: number) {
527
- this.logger.log(`set currentLevel:${newLevel}`);
520
+ logger.log(`set currentLevel:${newLevel}`);
528
521
  this.levelController.manualLevel = newLevel;
529
522
  this.streamController.immediateLevelSwitch();
530
523
  }
@@ -543,7 +536,7 @@ export default class Hls implements HlsEventEmitter {
543
536
  * @param newLevel - Pass -1 for automatic level selection
544
537
  */
545
538
  set nextLevel(newLevel: number) {
546
- this.logger.log(`set nextLevel:${newLevel}`);
539
+ logger.log(`set nextLevel:${newLevel}`);
547
540
  this.levelController.manualLevel = newLevel;
548
541
  this.streamController.nextLevelSwitch();
549
542
  }
@@ -562,7 +555,7 @@ export default class Hls implements HlsEventEmitter {
562
555
  * @param newLevel - Pass -1 for automatic level selection
563
556
  */
564
557
  set loadLevel(newLevel: number) {
565
- this.logger.log(`set loadLevel:${newLevel}`);
558
+ logger.log(`set loadLevel:${newLevel}`);
566
559
  this.levelController.manualLevel = newLevel;
567
560
  }
568
561
 
@@ -593,7 +586,7 @@ export default class Hls implements HlsEventEmitter {
593
586
  * Sets "first-level", see getter.
594
587
  */
595
588
  set firstLevel(newLevel: number) {
596
- this.logger.log(`set firstLevel:${newLevel}`);
589
+ logger.log(`set firstLevel:${newLevel}`);
597
590
  this.levelController.firstLevel = newLevel;
598
591
  }
599
592
 
@@ -618,7 +611,7 @@ export default class Hls implements HlsEventEmitter {
618
611
  * (determined from download of first segment)
619
612
  */
620
613
  set startLevel(newLevel: number) {
621
- this.logger.log(`set startLevel:${newLevel}`);
614
+ logger.log(`set startLevel:${newLevel}`);
622
615
  // if not in automatic start level detection, ensure startLevel is greater than minAutoLevel
623
616
  if (newLevel !== -1) {
624
617
  newLevel = Math.max(newLevel, this.minAutoLevel);
@@ -693,7 +686,7 @@ export default class Hls implements HlsEventEmitter {
693
686
  */
694
687
  set autoLevelCapping(newLevel: number) {
695
688
  if (this._autoLevelCapping !== newLevel) {
696
- this.logger.log(`set autoLevelCapping:${newLevel}`);
689
+ logger.log(`set autoLevelCapping:${newLevel}`);
697
690
  this._autoLevelCapping = newLevel;
698
691
  this.levelController.checkMaxAutoUpdated();
699
692
  }
@@ -1039,7 +1032,7 @@ export type {
1039
1032
  TSDemuxerConfig,
1040
1033
  } from './config';
1041
1034
  export type { MediaKeySessionContext } from './controller/eme-controller';
1042
- export type { ILogger, Logger } from './utils/logger';
1035
+ export type { ILogger } from './utils/logger';
1043
1036
  export type {
1044
1037
  PathwayClone,
1045
1038
  SteeringManifest,
@@ -1154,7 +1147,6 @@ export type {
1154
1147
  ManifestParsedData,
1155
1148
  MediaAttachedData,
1156
1149
  MediaAttachingData,
1157
- MediaEndedData,
1158
1150
  NonNativeTextTrack,
1159
1151
  NonNativeTextTracksData,
1160
1152
  SteeringManifestLoadedData,
@@ -336,11 +336,8 @@ function createLoaderContext(
336
336
  if (Number.isFinite(start) && Number.isFinite(end)) {
337
337
  let byteRangeStart = start;
338
338
  let byteRangeEnd = end;
339
- if (
340
- frag.sn === 'initSegment' &&
341
- isMethodFullSegmentAesCbc(frag.decryptdata?.method)
342
- ) {
343
- // 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,
344
341
  // has the unencrypted size specified in the range.
345
342
  // Ref: https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-6.3.6
346
343
  const fragmentLen = end - start;
@@ -375,10 +372,6 @@ function createGapLoadError(frag: Fragment, part?: Part): LoadError {
375
372
  return new LoadError(errorData);
376
373
  }
377
374
 
378
- function isMethodFullSegmentAesCbc(method) {
379
- return method === 'AES-128' || method === 'AES-256';
380
- }
381
-
382
375
  export class LoadError extends Error {
383
376
  public readonly data: FragLoadFailResult;
384
377
  constructor(data: FragLoadFailResult) {
@@ -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(