hls.js 1.5.13-0.canary.10411 → 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 +2702 -4247
  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 +4504 -6059
  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 +136 -156
  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
@@ -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,136 +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
- endOfSegment: boolean,
90
- ): Array<{
91
- data: Uint8Array;
92
- type: number;
93
- state?: number;
94
- }> {
95
- const len = array.byteLength;
96
- let state = track.naluState || 0;
97
- const lastState = state;
98
- const units: VideoSampleUnit[] = [];
99
- let i = 0;
100
- let value: number;
101
- let overflow: number;
102
- let unitType: number;
103
- let lastUnitStart = -1;
104
- let lastUnitType: number = 0;
105
- // logger.log('PES:' + Hex.hexDump(array));
106
-
107
- if (state === -1) {
108
- // special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet
109
- lastUnitStart = 0;
110
- // NALu type is value read from offset 0
111
- lastUnitType = this.getNALuType(array, 0);
112
- state = 0;
113
- i = 1;
114
- }
115
-
116
- while (i < len) {
117
- value = array[i++];
118
- // optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case
119
- if (!state) {
120
- state = value ? 0 : 1;
121
- continue;
122
- }
123
- if (state === 1) {
124
- state = value ? 0 : 2;
125
- continue;
126
- }
127
- // here we have state either equal to 2 or 3
128
- if (!value) {
129
- state = 3;
130
- } else if (value === 1) {
131
- overflow = i - state - 1;
132
- if (lastUnitStart >= 0) {
133
- const unit: VideoSampleUnit = {
134
- data: array.subarray(lastUnitStart, overflow),
135
- type: lastUnitType,
136
- };
137
- // logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);
138
- units.push(unit);
139
- } else {
140
- // lastUnitStart is undefined => this is the first start code found in this PES packet
141
- // first check if start code delimiter is overlapping between 2 PES packets,
142
- // ie it started in last packet (lastState not zero)
143
- // and ended at the beginning of this PES packet (i <= 4 - lastState)
144
- const lastUnit = this.getLastNalUnit(track.samples);
145
- if (lastUnit) {
146
- if (lastState && i <= 4 - lastState) {
147
- // start delimiter overlapping between PES packets
148
- // strip start delimiter bytes from the end of last NAL unit
149
- // check if lastUnit had a state different from zero
150
- if (lastUnit.state) {
151
- // strip last bytes
152
- lastUnit.data = lastUnit.data.subarray(
153
- 0,
154
- lastUnit.data.byteLength - lastState,
155
- );
156
- }
157
- }
158
- // If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.
159
-
160
- if (overflow > 0) {
161
- // logger.log('first NALU found with overflow:' + overflow);
162
- lastUnit.data = appendUint8Array(
163
- lastUnit.data,
164
- array.subarray(0, overflow),
165
- );
166
- lastUnit.state = 0;
167
- }
168
- }
169
- }
170
- // check if we can read unit type
171
- if (i < len) {
172
- unitType = this.getNALuType(array, i);
173
- // logger.log('find NALU @ offset:' + i + ',type:' + unitType);
174
- lastUnitStart = i;
175
- lastUnitType = unitType;
176
- state = 0;
177
- } else {
178
- // not enough byte to read unit type. let's read it on next PES parsing
179
- state = -1;
180
- }
181
- } else {
182
- state = 0;
183
- }
184
- }
185
- if (lastUnitStart >= 0 && state >= 0) {
186
- const unit: VideoSampleUnit = {
187
- data: array.subarray(lastUnitStart, len),
188
- type: lastUnitType,
189
- state: state,
190
- };
191
- units.push(unit);
192
- // logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
193
- }
194
- // no NALu found
195
- if (units.length === 0) {
196
- // append pes.data to previous NAL unit
197
- const lastUnit = this.getLastNalUnit(track.samples);
198
- if (lastUnit) {
199
- lastUnit.data = appendUint8Array(lastUnit.data, array);
200
- }
201
- }
202
- track.naluState = state;
203
- return units;
204
- }
205
72
  }
206
73
 
207
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
@@ -1,9 +1,8 @@
1
- import type {
1
+ import {
2
2
  ManifestLoadedData,
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,
@@ -1,7 +1,7 @@
1
1
  import Hls from './hls';
2
2
  import { Events } from './events';
3
3
  import { ErrorTypes, ErrorDetails } from './errors';
4
- import type { Level } from './types/level';
4
+ import { Level } from './types/level';
5
5
  import AbrController from './controller/abr-controller';
6
6
  import AudioTrackController from './controller/audio-track-controller';
7
7
  import AudioStreamController from './controller/audio-stream-controller';