hls.js 1.5.14-0.canary.10517 → 1.5.14

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 (107) 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 +2903 -4542
  5. package/dist/hls.js.d.ts +112 -186
  6. package/dist/hls.js.map +1 -1
  7. package/dist/hls.light.js +2284 -3295
  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 +1804 -2817
  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 +4652 -6293
  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 +107 -263
  26. package/src/controller/buffer-controller.ts +98 -252
  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 +5 -5
  48. package/src/demux/audio/ac3-demuxer.ts +4 -5
  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/inject-worker.ts +4 -38
  55. package/src/demux/mp4demuxer.ts +7 -7
  56. package/src/demux/sample-aes.ts +0 -2
  57. package/src/demux/transmuxer-interface.ts +83 -106
  58. package/src/demux/transmuxer-worker.ts +77 -111
  59. package/src/demux/transmuxer.ts +22 -46
  60. package/src/demux/tsdemuxer.ts +62 -122
  61. package/src/demux/video/avc-video-parser.ts +121 -210
  62. package/src/demux/video/base-video-parser.ts +2 -135
  63. package/src/demux/video/exp-golomb.ts +208 -0
  64. package/src/errors.ts +0 -2
  65. package/src/events.ts +1 -8
  66. package/src/exports-named.ts +1 -1
  67. package/src/hls.ts +48 -97
  68. package/src/loader/date-range.ts +5 -71
  69. package/src/loader/fragment-loader.ts +21 -23
  70. package/src/loader/fragment.ts +4 -8
  71. package/src/loader/key-loader.ts +1 -3
  72. package/src/loader/level-details.ts +6 -6
  73. package/src/loader/level-key.ts +9 -10
  74. package/src/loader/m3u8-parser.ts +144 -138
  75. package/src/loader/playlist-loader.ts +7 -5
  76. package/src/remux/mp4-generator.ts +1 -196
  77. package/src/remux/mp4-remuxer.ts +84 -55
  78. package/src/remux/passthrough-remuxer.ts +8 -23
  79. package/src/task-loop.ts +2 -5
  80. package/src/types/component-api.ts +1 -3
  81. package/src/types/demuxer.ts +0 -3
  82. package/src/types/events.ts +6 -19
  83. package/src/types/fragment-tracker.ts +2 -2
  84. package/src/types/general.ts +6 -0
  85. package/src/types/media-playlist.ts +1 -9
  86. package/src/types/remuxer.ts +1 -1
  87. package/src/utils/attr-list.ts +9 -96
  88. package/src/utils/buffer-helper.ts +31 -12
  89. package/src/utils/cea-608-parser.ts +3 -1
  90. package/src/utils/codecs.ts +5 -34
  91. package/src/utils/discontinuities.ts +47 -21
  92. package/src/utils/fetch-loader.ts +1 -1
  93. package/src/utils/hdr.ts +7 -4
  94. package/src/utils/imsc1-ttml-parser.ts +1 -1
  95. package/src/utils/keysystem-util.ts +6 -1
  96. package/src/utils/level-helper.ts +44 -71
  97. package/src/utils/logger.ts +23 -58
  98. package/src/utils/mp4-tools.ts +3 -5
  99. package/src/utils/rendition-helper.ts +74 -100
  100. package/src/utils/variable-substitution.ts +19 -0
  101. package/src/utils/webvtt-parser.ts +12 -2
  102. package/src/crypt/decrypter-aes-mode.ts +0 -4
  103. package/src/demux/video/hevc-video-parser.ts +0 -749
  104. package/src/utils/encryption-methods-util.ts +0 -21
  105. package/src/utils/hash.ts +0 -10
  106. package/src/utils/utf8-utils.ts +0 -18
  107. package/src/version.ts +0 -1
@@ -1,23 +1,25 @@
1
1
  import BaseVideoParser from './base-video-parser';
2
- import type {
2
+ import {
3
3
  DemuxedVideoTrack,
4
4
  DemuxedUserdataTrack,
5
+ VideoSampleUnit,
5
6
  } from '../../types/demuxer';
6
- import { parseSEIMessageFromNALu } from '../../utils/mp4-tools';
7
-
8
- import type { PES } from '../tsdemuxer';
9
-
7
+ import {
8
+ appendUint8Array,
9
+ parseSEIMessageFromNALu,
10
+ } from '../../utils/mp4-tools';
10
11
  import ExpGolomb from './exp-golomb';
12
+ import type { PES } from '../tsdemuxer';
11
13
 
12
14
  class AvcVideoParser extends BaseVideoParser {
13
- public parsePES(
15
+ public parseAVCPES(
14
16
  track: DemuxedVideoTrack,
15
17
  textTrack: DemuxedUserdataTrack,
16
18
  pes: PES,
17
- endOfSegment: boolean,
19
+ last: boolean,
18
20
  duration: number,
19
21
  ) {
20
- const units = this.parseNALu(track, pes.data, endOfSegment);
22
+ const units = this.parseAVCNALu(track, pes.data);
21
23
  const debug = false;
22
24
  let VideoSample = this.VideoSample;
23
25
  let push: boolean;
@@ -47,7 +49,7 @@ class AvcVideoParser extends BaseVideoParser {
47
49
  // only check slice type to detect KF in case SPS found in same packet (any keyframe is preceded by SPS ...)
48
50
  if (spsfound && data.length > 4) {
49
51
  // retrieve slice type by parsing beginning of NAL unit (follow H264 spec, slice_header definition) to detect keyframe embedded in NDR
50
- const sliceType = this.readSliceType(data);
52
+ const sliceType = new ExpGolomb(data).readSliceType();
51
53
  // 2 : I slice, 4 : SI slice, 7 : I slice, 9: SI slice
52
54
  // SI slice : A slice that is coded using intra prediction only and using quantisation of the prediction samples.
53
55
  // An SI slice can be coded such that its decoded samples can be constructed identically to an SP slice.
@@ -136,7 +138,9 @@ class AvcVideoParser extends BaseVideoParser {
136
138
  VideoSample.debug += 'SPS ';
137
139
  }
138
140
  const sps = unit.data;
139
- const config = this.readSPS(sps);
141
+ const expGolombDecoder = new ExpGolomb(sps);
142
+ const config = expGolombDecoder.readSPS();
143
+
140
144
  if (
141
145
  !track.sps ||
142
146
  track.width !== config.width ||
@@ -161,6 +165,7 @@ class AvcVideoParser extends BaseVideoParser {
161
165
  }
162
166
  track.codec = codecstring;
163
167
  }
168
+
164
169
  break;
165
170
  }
166
171
  // PPS
@@ -206,223 +211,129 @@ class AvcVideoParser extends BaseVideoParser {
206
211
  }
207
212
  });
208
213
  // if last PES packet, push samples
209
- if (endOfSegment && VideoSample) {
214
+ if (last && VideoSample) {
210
215
  this.pushAccessUnit(VideoSample, track);
211
216
  this.VideoSample = null;
212
217
  }
213
218
  }
214
219
 
215
- protected getNALuType(data: Uint8Array, offset: number): number {
216
- return data[offset] & 0x1f;
217
- }
218
-
219
- readSliceType(data: Uint8Array) {
220
- const eg = new ExpGolomb(data);
221
- // skip NALu type
222
- eg.readUByte();
223
- // discard first_mb_in_slice
224
- eg.readUEG();
225
- // return slice_type
226
- return eg.readUEG();
227
- }
220
+ private parseAVCNALu(
221
+ track: DemuxedVideoTrack,
222
+ array: Uint8Array,
223
+ ): Array<{
224
+ data: Uint8Array;
225
+ type: number;
226
+ state?: number;
227
+ }> {
228
+ const len = array.byteLength;
229
+ let state = track.naluState || 0;
230
+ const lastState = state;
231
+ const units: VideoSampleUnit[] = [];
232
+ let i = 0;
233
+ let value: number;
234
+ let overflow: number;
235
+ let unitType: number;
236
+ let lastUnitStart = -1;
237
+ let lastUnitType: number = 0;
238
+ // logger.log('PES:' + Hex.hexDump(array));
228
239
 
229
- /**
230
- * The scaling list is optionally transmitted as part of a sequence parameter
231
- * set and is not relevant to transmuxing.
232
- * @param count the number of entries in this scaling list
233
- * @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
234
- */
235
- skipScalingList(count: number, reader: ExpGolomb): void {
236
- let lastScale = 8;
237
- let nextScale = 8;
238
- let deltaScale;
239
- for (let j = 0; j < count; j++) {
240
- if (nextScale !== 0) {
241
- deltaScale = reader.readEG();
242
- nextScale = (lastScale + deltaScale + 256) % 256;
243
- }
244
- lastScale = nextScale === 0 ? lastScale : nextScale;
240
+ if (state === -1) {
241
+ // special use case where we found 3 or 4-byte start codes exactly at the end of previous PES packet
242
+ lastUnitStart = 0;
243
+ // NALu type is value read from offset 0
244
+ lastUnitType = array[0] & 0x1f;
245
+ state = 0;
246
+ i = 1;
245
247
  }
246
- }
247
-
248
- /**
249
- * Read a sequence parameter set and return some interesting video
250
- * properties. A sequence parameter set is the H264 metadata that
251
- * describes the properties of upcoming video frames.
252
- * @returns an object with configuration parsed from the
253
- * sequence parameter set, including the dimensions of the
254
- * associated video frames.
255
- */
256
- readSPS(sps: Uint8Array): {
257
- width: number;
258
- height: number;
259
- pixelRatio: [number, number];
260
- } {
261
- const eg = new ExpGolomb(sps);
262
- let frameCropLeftOffset = 0;
263
- let frameCropRightOffset = 0;
264
- let frameCropTopOffset = 0;
265
- let frameCropBottomOffset = 0;
266
- let numRefFramesInPicOrderCntCycle;
267
- let scalingListCount;
268
- let i;
269
- const readUByte = eg.readUByte.bind(eg);
270
- const readBits = eg.readBits.bind(eg);
271
- const readUEG = eg.readUEG.bind(eg);
272
- const readBoolean = eg.readBoolean.bind(eg);
273
- const skipBits = eg.skipBits.bind(eg);
274
- const skipEG = eg.skipEG.bind(eg);
275
- const skipUEG = eg.skipUEG.bind(eg);
276
- const skipScalingList = this.skipScalingList.bind(this);
277
248
 
278
- readUByte();
279
- const profileIdc = readUByte(); // profile_idc
280
- readBits(5); // profileCompat constraint_set[0-4]_flag, u(5)
281
- skipBits(3); // reserved_zero_3bits u(3),
282
- readUByte(); // level_idc u(8)
283
- skipUEG(); // seq_parameter_set_id
284
- // some profiles have more optional data we don't need
285
- if (
286
- profileIdc === 100 ||
287
- profileIdc === 110 ||
288
- profileIdc === 122 ||
289
- profileIdc === 244 ||
290
- profileIdc === 44 ||
291
- profileIdc === 83 ||
292
- profileIdc === 86 ||
293
- profileIdc === 118 ||
294
- profileIdc === 128
295
- ) {
296
- const chromaFormatIdc = readUEG();
297
- if (chromaFormatIdc === 3) {
298
- skipBits(1);
299
- } // separate_colour_plane_flag
249
+ while (i < len) {
250
+ value = array[i++];
251
+ // optimization. state 0 and 1 are the predominant case. let's handle them outside of the switch/case
252
+ if (!state) {
253
+ state = value ? 0 : 1;
254
+ continue;
255
+ }
256
+ if (state === 1) {
257
+ state = value ? 0 : 2;
258
+ continue;
259
+ }
260
+ // here we have state either equal to 2 or 3
261
+ if (!value) {
262
+ state = 3;
263
+ } else if (value === 1) {
264
+ overflow = i - state - 1;
265
+ if (lastUnitStart >= 0) {
266
+ const unit: VideoSampleUnit = {
267
+ data: array.subarray(lastUnitStart, overflow),
268
+ type: lastUnitType,
269
+ };
270
+ // logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);
271
+ units.push(unit);
272
+ } else {
273
+ // lastUnitStart is undefined => this is the first start code found in this PES packet
274
+ // first check if start code delimiter is overlapping between 2 PES packets,
275
+ // ie it started in last packet (lastState not zero)
276
+ // and ended at the beginning of this PES packet (i <= 4 - lastState)
277
+ const lastUnit = this.getLastNalUnit(track.samples);
278
+ if (lastUnit) {
279
+ if (lastState && i <= 4 - lastState) {
280
+ // start delimiter overlapping between PES packets
281
+ // strip start delimiter bytes from the end of last NAL unit
282
+ // check if lastUnit had a state different from zero
283
+ if (lastUnit.state) {
284
+ // strip last bytes
285
+ lastUnit.data = lastUnit.data.subarray(
286
+ 0,
287
+ lastUnit.data.byteLength - lastState,
288
+ );
289
+ }
290
+ }
291
+ // If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.
300
292
 
301
- skipUEG(); // bit_depth_luma_minus8
302
- skipUEG(); // bit_depth_chroma_minus8
303
- skipBits(1); // qpprime_y_zero_transform_bypass_flag
304
- if (readBoolean()) {
305
- // seq_scaling_matrix_present_flag
306
- scalingListCount = chromaFormatIdc !== 3 ? 8 : 12;
307
- for (i = 0; i < scalingListCount; i++) {
308
- if (readBoolean()) {
309
- // seq_scaling_list_present_flag[ i ]
310
- if (i < 6) {
311
- skipScalingList(16, eg);
312
- } else {
313
- skipScalingList(64, eg);
293
+ if (overflow > 0) {
294
+ // logger.log('first NALU found with overflow:' + overflow);
295
+ lastUnit.data = appendUint8Array(
296
+ lastUnit.data,
297
+ array.subarray(0, overflow),
298
+ );
299
+ lastUnit.state = 0;
314
300
  }
315
301
  }
316
302
  }
303
+ // check if we can read unit type
304
+ if (i < len) {
305
+ unitType = array[i] & 0x1f;
306
+ // logger.log('find NALU @ offset:' + i + ',type:' + unitType);
307
+ lastUnitStart = i;
308
+ lastUnitType = unitType;
309
+ state = 0;
310
+ } else {
311
+ // not enough byte to read unit type. let's read it on next PES parsing
312
+ state = -1;
313
+ }
314
+ } else {
315
+ state = 0;
317
316
  }
318
317
  }
319
- skipUEG(); // log2_max_frame_num_minus4
320
- const picOrderCntType = readUEG();
321
- if (picOrderCntType === 0) {
322
- readUEG(); // log2_max_pic_order_cnt_lsb_minus4
323
- } else if (picOrderCntType === 1) {
324
- skipBits(1); // delta_pic_order_always_zero_flag
325
- skipEG(); // offset_for_non_ref_pic
326
- skipEG(); // offset_for_top_to_bottom_field
327
- numRefFramesInPicOrderCntCycle = readUEG();
328
- for (i = 0; i < numRefFramesInPicOrderCntCycle; i++) {
329
- skipEG();
330
- } // offset_for_ref_frame[ i ]
331
- }
332
- skipUEG(); // max_num_ref_frames
333
- skipBits(1); // gaps_in_frame_num_value_allowed_flag
334
- const picWidthInMbsMinus1 = readUEG();
335
- const picHeightInMapUnitsMinus1 = readUEG();
336
- const frameMbsOnlyFlag = readBits(1);
337
- if (frameMbsOnlyFlag === 0) {
338
- skipBits(1);
339
- } // mb_adaptive_frame_field_flag
340
-
341
- skipBits(1); // direct_8x8_inference_flag
342
- if (readBoolean()) {
343
- // frame_cropping_flag
344
- frameCropLeftOffset = readUEG();
345
- frameCropRightOffset = readUEG();
346
- frameCropTopOffset = readUEG();
347
- frameCropBottomOffset = readUEG();
318
+ if (lastUnitStart >= 0 && state >= 0) {
319
+ const unit: VideoSampleUnit = {
320
+ data: array.subarray(lastUnitStart, len),
321
+ type: lastUnitType,
322
+ state: state,
323
+ };
324
+ units.push(unit);
325
+ // logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
348
326
  }
349
- let pixelRatio: [number, number] = [1, 1];
350
- if (readBoolean()) {
351
- // vui_parameters_present_flag
352
- if (readBoolean()) {
353
- // aspect_ratio_info_present_flag
354
- const aspectRatioIdc = readUByte();
355
- switch (aspectRatioIdc) {
356
- case 1:
357
- pixelRatio = [1, 1];
358
- break;
359
- case 2:
360
- pixelRatio = [12, 11];
361
- break;
362
- case 3:
363
- pixelRatio = [10, 11];
364
- break;
365
- case 4:
366
- pixelRatio = [16, 11];
367
- break;
368
- case 5:
369
- pixelRatio = [40, 33];
370
- break;
371
- case 6:
372
- pixelRatio = [24, 11];
373
- break;
374
- case 7:
375
- pixelRatio = [20, 11];
376
- break;
377
- case 8:
378
- pixelRatio = [32, 11];
379
- break;
380
- case 9:
381
- pixelRatio = [80, 33];
382
- break;
383
- case 10:
384
- pixelRatio = [18, 11];
385
- break;
386
- case 11:
387
- pixelRatio = [15, 11];
388
- break;
389
- case 12:
390
- pixelRatio = [64, 33];
391
- break;
392
- case 13:
393
- pixelRatio = [160, 99];
394
- break;
395
- case 14:
396
- pixelRatio = [4, 3];
397
- break;
398
- case 15:
399
- pixelRatio = [3, 2];
400
- break;
401
- case 16:
402
- pixelRatio = [2, 1];
403
- break;
404
- case 255: {
405
- pixelRatio = [
406
- (readUByte() << 8) | readUByte(),
407
- (readUByte() << 8) | readUByte(),
408
- ];
409
- break;
410
- }
411
- }
327
+ // no NALu found
328
+ if (units.length === 0) {
329
+ // append pes.data to previous NAL unit
330
+ const lastUnit = this.getLastNalUnit(track.samples);
331
+ if (lastUnit) {
332
+ lastUnit.data = appendUint8Array(lastUnit.data, array);
412
333
  }
413
334
  }
414
- return {
415
- width: Math.ceil(
416
- (picWidthInMbsMinus1 + 1) * 16 -
417
- frameCropLeftOffset * 2 -
418
- frameCropRightOffset * 2,
419
- ),
420
- height:
421
- (2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16 -
422
- (frameMbsOnlyFlag ? 2 : 4) *
423
- (frameCropTopOffset + frameCropBottomOffset),
424
- pixelRatio: pixelRatio,
425
- };
335
+ track.naluState = state;
336
+ return units;
426
337
  }
427
338
  }
428
339
 
@@ -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;