@zenvor/hls.js 1.0.0

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 (159) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +472 -0
  3. package/dist/hls-demo.js +26995 -0
  4. package/dist/hls-demo.js.map +1 -0
  5. package/dist/hls.d.mts +4204 -0
  6. package/dist/hls.d.ts +4204 -0
  7. package/dist/hls.js +40050 -0
  8. package/dist/hls.js.d.ts +4204 -0
  9. package/dist/hls.js.map +1 -0
  10. package/dist/hls.light.js +27145 -0
  11. package/dist/hls.light.js.map +1 -0
  12. package/dist/hls.light.min.js +2 -0
  13. package/dist/hls.light.min.js.map +1 -0
  14. package/dist/hls.light.mjs +26392 -0
  15. package/dist/hls.light.mjs.map +1 -0
  16. package/dist/hls.min.js +2 -0
  17. package/dist/hls.min.js.map +1 -0
  18. package/dist/hls.mjs +38956 -0
  19. package/dist/hls.mjs.map +1 -0
  20. package/dist/hls.worker.js +2 -0
  21. package/dist/hls.worker.js.map +1 -0
  22. package/package.json +143 -0
  23. package/src/config.ts +794 -0
  24. package/src/controller/abr-controller.ts +1019 -0
  25. package/src/controller/algo-data-controller.ts +794 -0
  26. package/src/controller/audio-stream-controller.ts +1099 -0
  27. package/src/controller/audio-track-controller.ts +454 -0
  28. package/src/controller/base-playlist-controller.ts +438 -0
  29. package/src/controller/base-stream-controller.ts +2526 -0
  30. package/src/controller/buffer-controller.ts +2015 -0
  31. package/src/controller/buffer-operation-queue.ts +159 -0
  32. package/src/controller/cap-level-controller.ts +367 -0
  33. package/src/controller/cmcd-controller.ts +422 -0
  34. package/src/controller/content-steering-controller.ts +622 -0
  35. package/src/controller/eme-controller.ts +1617 -0
  36. package/src/controller/error-controller.ts +627 -0
  37. package/src/controller/fps-controller.ts +146 -0
  38. package/src/controller/fragment-finders.ts +256 -0
  39. package/src/controller/fragment-tracker.ts +567 -0
  40. package/src/controller/gap-controller.ts +719 -0
  41. package/src/controller/id3-track-controller.ts +488 -0
  42. package/src/controller/interstitial-player.ts +302 -0
  43. package/src/controller/interstitials-controller.ts +2895 -0
  44. package/src/controller/interstitials-schedule.ts +698 -0
  45. package/src/controller/latency-controller.ts +294 -0
  46. package/src/controller/level-controller.ts +776 -0
  47. package/src/controller/stream-controller.ts +1597 -0
  48. package/src/controller/subtitle-stream-controller.ts +508 -0
  49. package/src/controller/subtitle-track-controller.ts +617 -0
  50. package/src/controller/timeline-controller.ts +677 -0
  51. package/src/crypt/aes-crypto.ts +36 -0
  52. package/src/crypt/aes-decryptor.ts +339 -0
  53. package/src/crypt/decrypter-aes-mode.ts +4 -0
  54. package/src/crypt/decrypter.ts +225 -0
  55. package/src/crypt/fast-aes-key.ts +39 -0
  56. package/src/define-plugin.d.ts +17 -0
  57. package/src/demux/audio/aacdemuxer.ts +126 -0
  58. package/src/demux/audio/ac3-demuxer.ts +170 -0
  59. package/src/demux/audio/adts.ts +249 -0
  60. package/src/demux/audio/base-audio-demuxer.ts +205 -0
  61. package/src/demux/audio/dolby.ts +21 -0
  62. package/src/demux/audio/mp3demuxer.ts +85 -0
  63. package/src/demux/audio/mpegaudio.ts +177 -0
  64. package/src/demux/chunk-cache.ts +42 -0
  65. package/src/demux/dummy-demuxed-track.ts +13 -0
  66. package/src/demux/inject-worker.ts +75 -0
  67. package/src/demux/mp4demuxer.ts +234 -0
  68. package/src/demux/sample-aes.ts +198 -0
  69. package/src/demux/transmuxer-interface.ts +449 -0
  70. package/src/demux/transmuxer-worker.ts +221 -0
  71. package/src/demux/transmuxer.ts +560 -0
  72. package/src/demux/tsdemuxer.ts +1256 -0
  73. package/src/demux/video/avc-video-parser.ts +401 -0
  74. package/src/demux/video/base-video-parser.ts +198 -0
  75. package/src/demux/video/exp-golomb.ts +153 -0
  76. package/src/demux/video/hevc-video-parser.ts +736 -0
  77. package/src/empty-es.js +5 -0
  78. package/src/empty.js +3 -0
  79. package/src/errors.ts +107 -0
  80. package/src/events.ts +548 -0
  81. package/src/exports-default.ts +3 -0
  82. package/src/exports-named.ts +81 -0
  83. package/src/hls.ts +1613 -0
  84. package/src/is-supported.ts +54 -0
  85. package/src/loader/date-range.ts +207 -0
  86. package/src/loader/fragment-loader.ts +403 -0
  87. package/src/loader/fragment.ts +487 -0
  88. package/src/loader/interstitial-asset-list.ts +162 -0
  89. package/src/loader/interstitial-event.ts +337 -0
  90. package/src/loader/key-loader.ts +439 -0
  91. package/src/loader/level-details.ts +203 -0
  92. package/src/loader/level-key.ts +259 -0
  93. package/src/loader/load-stats.ts +17 -0
  94. package/src/loader/m3u8-parser.ts +1072 -0
  95. package/src/loader/playlist-loader.ts +839 -0
  96. package/src/polyfills/number.ts +15 -0
  97. package/src/remux/aac-helper.ts +81 -0
  98. package/src/remux/mp4-generator.ts +1380 -0
  99. package/src/remux/mp4-remuxer.ts +1261 -0
  100. package/src/remux/passthrough-remuxer.ts +434 -0
  101. package/src/task-loop.ts +130 -0
  102. package/src/types/algo.ts +44 -0
  103. package/src/types/buffer.ts +105 -0
  104. package/src/types/component-api.ts +20 -0
  105. package/src/types/demuxer.ts +208 -0
  106. package/src/types/events.ts +574 -0
  107. package/src/types/fragment-tracker.ts +23 -0
  108. package/src/types/level.ts +268 -0
  109. package/src/types/loader.ts +198 -0
  110. package/src/types/media-playlist.ts +92 -0
  111. package/src/types/network-details.ts +3 -0
  112. package/src/types/remuxer.ts +104 -0
  113. package/src/types/track.ts +12 -0
  114. package/src/types/transmuxer.ts +46 -0
  115. package/src/types/tuples.ts +6 -0
  116. package/src/types/vtt.ts +11 -0
  117. package/src/utils/arrays.ts +22 -0
  118. package/src/utils/attr-list.ts +192 -0
  119. package/src/utils/binary-search.ts +46 -0
  120. package/src/utils/buffer-helper.ts +173 -0
  121. package/src/utils/cea-608-parser.ts +1413 -0
  122. package/src/utils/chunker.ts +41 -0
  123. package/src/utils/codecs.ts +314 -0
  124. package/src/utils/cues.ts +96 -0
  125. package/src/utils/discontinuities.ts +174 -0
  126. package/src/utils/encryption-methods-util.ts +21 -0
  127. package/src/utils/error-helper.ts +95 -0
  128. package/src/utils/event-listener-helper.ts +16 -0
  129. package/src/utils/ewma-bandwidth-estimator.ts +97 -0
  130. package/src/utils/ewma.ts +43 -0
  131. package/src/utils/fetch-loader.ts +331 -0
  132. package/src/utils/global.ts +2 -0
  133. package/src/utils/hash.ts +10 -0
  134. package/src/utils/hdr.ts +67 -0
  135. package/src/utils/hex.ts +32 -0
  136. package/src/utils/imsc1-ttml-parser.ts +261 -0
  137. package/src/utils/keysystem-util.ts +45 -0
  138. package/src/utils/level-helper.ts +629 -0
  139. package/src/utils/logger.ts +120 -0
  140. package/src/utils/media-option-attributes.ts +49 -0
  141. package/src/utils/mediacapabilities-helper.ts +301 -0
  142. package/src/utils/mediakeys-helper.ts +210 -0
  143. package/src/utils/mediasource-helper.ts +37 -0
  144. package/src/utils/mp4-tools.ts +1473 -0
  145. package/src/utils/number.ts +3 -0
  146. package/src/utils/numeric-encoding-utils.ts +26 -0
  147. package/src/utils/output-filter.ts +46 -0
  148. package/src/utils/rendition-helper.ts +505 -0
  149. package/src/utils/safe-json-stringify.ts +22 -0
  150. package/src/utils/texttrack-utils.ts +164 -0
  151. package/src/utils/time-ranges.ts +17 -0
  152. package/src/utils/timescale-conversion.ts +46 -0
  153. package/src/utils/utf8-utils.ts +18 -0
  154. package/src/utils/variable-substitution.ts +105 -0
  155. package/src/utils/vttcue.ts +384 -0
  156. package/src/utils/vttparser.ts +497 -0
  157. package/src/utils/webvtt-parser.ts +166 -0
  158. package/src/utils/xhr-loader.ts +337 -0
  159. package/src/version.ts +1 -0
@@ -0,0 +1,736 @@
1
+ import BaseVideoParser from './base-video-parser';
2
+ import ExpGolomb from './exp-golomb';
3
+ import { parseSEIMessageFromNALu } from '../../utils/mp4-tools';
4
+ import type {
5
+ DemuxedUserdataTrack,
6
+ DemuxedVideoTrack,
7
+ } from '../../types/demuxer';
8
+ import type { ParsedVideoSample } from '../tsdemuxer';
9
+ import type { PES } from '../tsdemuxer';
10
+
11
+ class HevcVideoParser extends BaseVideoParser {
12
+ protected initVPS: Uint8Array | null = null;
13
+
14
+ public parsePES(
15
+ track: DemuxedVideoTrack,
16
+ textTrack: DemuxedUserdataTrack,
17
+ pes: PES,
18
+ endOfSegment: boolean,
19
+ ) {
20
+ const units = this.parseNALu(track, pes.data, endOfSegment);
21
+ let VideoSample = this.VideoSample;
22
+ let push: boolean;
23
+ let spsfound = false;
24
+ // free pes.data to save up some memory
25
+ (pes as any).data = null;
26
+
27
+ // if new NAL units found and last sample still there, let's push ...
28
+ // this helps parsing streams with missing AUD (only do this if AUD never found)
29
+ if (VideoSample && units.length && !track.audFound) {
30
+ this.pushAccessUnit(VideoSample, track);
31
+ VideoSample = this.VideoSample = this.createVideoSample(
32
+ false,
33
+ pes.pts,
34
+ pes.dts,
35
+ );
36
+ }
37
+
38
+ units.forEach((unit) => {
39
+ switch (unit.type) {
40
+ // NON-IDR, NON RANDOM ACCESS SLICE
41
+ case 0:
42
+ case 1:
43
+ case 2:
44
+ case 3:
45
+ case 4:
46
+ case 5:
47
+ case 6:
48
+ case 7:
49
+ case 8:
50
+ case 9:
51
+ if (!VideoSample) {
52
+ VideoSample = this.VideoSample = this.createVideoSample(
53
+ false,
54
+ pes.pts,
55
+ pes.dts,
56
+ );
57
+ }
58
+ VideoSample.frame = true;
59
+ push = true;
60
+ break;
61
+
62
+ // CRA, BLA (random access picture)
63
+ case 16:
64
+ case 17:
65
+ case 18:
66
+ case 21:
67
+ push = true;
68
+ if (spsfound) {
69
+ // handle PES not starting with AUD
70
+ // if we have frame data already, that cannot belong to the same frame, so force a push
71
+ if (VideoSample?.frame && !VideoSample.key) {
72
+ this.pushAccessUnit(VideoSample, track);
73
+ VideoSample = this.VideoSample = null;
74
+ }
75
+ }
76
+ if (!VideoSample) {
77
+ VideoSample = this.VideoSample = this.createVideoSample(
78
+ true,
79
+ pes.pts,
80
+ pes.dts,
81
+ );
82
+ }
83
+
84
+ VideoSample.key = true;
85
+ VideoSample.frame = true;
86
+ break;
87
+
88
+ // IDR
89
+ case 19:
90
+ case 20:
91
+ push = true;
92
+ // handle PES not starting with AUD
93
+ // if we have frame data already, that cannot belong to the same frame, so force a push
94
+ if (VideoSample?.frame && !VideoSample.key) {
95
+ this.pushAccessUnit(VideoSample, track);
96
+ VideoSample = this.VideoSample = null;
97
+ }
98
+ if (!VideoSample) {
99
+ VideoSample = this.VideoSample = this.createVideoSample(
100
+ true,
101
+ pes.pts,
102
+ pes.dts,
103
+ );
104
+ }
105
+
106
+ VideoSample.key = true;
107
+ VideoSample.frame = true;
108
+ break;
109
+
110
+ // SEI
111
+ case 39:
112
+ push = true;
113
+ parseSEIMessageFromNALu(
114
+ unit.data,
115
+ 2, // NALu header size
116
+ pes.pts as number,
117
+ textTrack.samples,
118
+ );
119
+ break;
120
+
121
+ // VPS
122
+ case 32:
123
+ push = true;
124
+ if (!track.vps) {
125
+ if (typeof track.params !== 'object') {
126
+ track.params = {};
127
+ }
128
+ track.params = Object.assign(track.params, this.readVPS(unit.data));
129
+ this.initVPS = unit.data;
130
+ }
131
+ track.vps = [unit.data];
132
+ break;
133
+
134
+ // SPS
135
+ case 33:
136
+ push = true;
137
+ spsfound = true;
138
+ if (
139
+ track.vps !== undefined &&
140
+ track.vps[0] !== this.initVPS &&
141
+ track.sps !== undefined &&
142
+ !this.matchSPS(track.sps[0], unit.data)
143
+ ) {
144
+ this.initVPS = track.vps[0];
145
+ track.sps = track.pps = undefined;
146
+ }
147
+ if (!track.sps) {
148
+ const config = this.readSPS(unit.data);
149
+ track.width = config.width;
150
+ track.height = config.height;
151
+ track.pixelRatio = config.pixelRatio;
152
+ track.codec = config.codecString;
153
+ track.sps = [];
154
+ if (typeof track.params !== 'object') {
155
+ track.params = {};
156
+ }
157
+ for (const prop in config.params) {
158
+ track.params[prop] = config.params[prop];
159
+ }
160
+ }
161
+ this.pushParameterSet(track.sps, unit.data, track.vps);
162
+ if (!VideoSample) {
163
+ VideoSample = this.VideoSample = this.createVideoSample(
164
+ true,
165
+ pes.pts,
166
+ pes.dts,
167
+ );
168
+ }
169
+ VideoSample.key = true;
170
+ break;
171
+
172
+ // PPS
173
+ case 34:
174
+ push = true;
175
+ if (typeof track.params === 'object') {
176
+ if (!track.pps) {
177
+ track.pps = [];
178
+ const config = this.readPPS(unit.data);
179
+ for (const prop in config) {
180
+ track.params[prop] = config[prop];
181
+ }
182
+ }
183
+ this.pushParameterSet(track.pps, unit.data, track.vps);
184
+ }
185
+ break;
186
+
187
+ // ACCESS UNIT DELIMITER
188
+ case 35:
189
+ push = true;
190
+ track.audFound = true;
191
+ if (VideoSample?.frame) {
192
+ this.pushAccessUnit(VideoSample, track);
193
+ VideoSample = null;
194
+ }
195
+ if (!VideoSample) {
196
+ VideoSample = this.VideoSample = this.createVideoSample(
197
+ false,
198
+ pes.pts,
199
+ pes.dts,
200
+ );
201
+ }
202
+ break;
203
+
204
+ default:
205
+ push = false;
206
+ break;
207
+ }
208
+ if (VideoSample && push) {
209
+ const units = VideoSample.units;
210
+ units.push(unit);
211
+ }
212
+ });
213
+ // if last PES packet, push samples
214
+ if (endOfSegment && VideoSample) {
215
+ this.pushAccessUnit(VideoSample, track);
216
+ this.VideoSample = null;
217
+ }
218
+ }
219
+
220
+ private pushParameterSet(
221
+ parameterSets: Uint8Array[],
222
+ data: Uint8Array,
223
+ vps: Uint8Array[] | undefined,
224
+ ) {
225
+ if ((vps && vps[0] === this.initVPS) || (!vps && !parameterSets.length)) {
226
+ parameterSets.push(data);
227
+ }
228
+ }
229
+
230
+ protected getNALuType(data: Uint8Array, offset: number): number {
231
+ return (data[offset] & 0x7e) >>> 1;
232
+ }
233
+
234
+ protected ebsp2rbsp(arr: Uint8Array): Uint8Array {
235
+ const dst = new Uint8Array(arr.byteLength);
236
+ let dstIdx = 0;
237
+ for (let i = 0; i < arr.byteLength; i++) {
238
+ if (i >= 2) {
239
+ // Unescape: Skip 0x03 after 00 00
240
+ if (arr[i] === 0x03 && arr[i - 1] === 0x00 && arr[i - 2] === 0x00) {
241
+ continue;
242
+ }
243
+ }
244
+ dst[dstIdx] = arr[i];
245
+ dstIdx++;
246
+ }
247
+ return new Uint8Array(dst.buffer, 0, dstIdx);
248
+ }
249
+
250
+ protected pushAccessUnit(
251
+ VideoSample: ParsedVideoSample,
252
+ videoTrack: DemuxedVideoTrack,
253
+ ) {
254
+ super.pushAccessUnit(VideoSample, videoTrack);
255
+ if (this.initVPS) {
256
+ this.initVPS = null; // null initVPS to prevent possible track's sps/pps growth until next VPS
257
+ }
258
+ }
259
+
260
+ readVPS(vps: Uint8Array): {
261
+ numTemporalLayers: number;
262
+ temporalIdNested: boolean;
263
+ } {
264
+ const eg = new ExpGolomb(vps);
265
+ // remove header
266
+ eg.readUByte();
267
+ eg.readUByte();
268
+
269
+ eg.readBits(4); // video_parameter_set_id
270
+ eg.skipBits(2);
271
+ eg.readBits(6); // max_layers_minus1
272
+ const max_sub_layers_minus1 = eg.readBits(3);
273
+ const temporal_id_nesting_flag = eg.readBoolean();
274
+ // ...vui fps can be here, but empty fps value is not critical for metadata
275
+
276
+ return {
277
+ numTemporalLayers: max_sub_layers_minus1 + 1,
278
+ temporalIdNested: temporal_id_nesting_flag,
279
+ };
280
+ }
281
+
282
+ readSPS(sps: Uint8Array): {
283
+ codecString: string;
284
+ params: object;
285
+ width: number;
286
+ height: number;
287
+ pixelRatio: [number, number];
288
+ } {
289
+ const eg = new ExpGolomb(this.ebsp2rbsp(sps));
290
+ eg.readUByte();
291
+ eg.readUByte();
292
+
293
+ eg.readBits(4); //video_parameter_set_id
294
+ const max_sub_layers_minus1 = eg.readBits(3);
295
+ eg.readBoolean(); // temporal_id_nesting_flag
296
+
297
+ // profile_tier_level
298
+ const general_profile_space = eg.readBits(2);
299
+ const general_tier_flag = eg.readBoolean();
300
+ const general_profile_idc = eg.readBits(5);
301
+ const general_profile_compatibility_flags_1 = eg.readUByte();
302
+ const general_profile_compatibility_flags_2 = eg.readUByte();
303
+ const general_profile_compatibility_flags_3 = eg.readUByte();
304
+ const general_profile_compatibility_flags_4 = eg.readUByte();
305
+ const general_constraint_indicator_flags_1 = eg.readUByte();
306
+ const general_constraint_indicator_flags_2 = eg.readUByte();
307
+ const general_constraint_indicator_flags_3 = eg.readUByte();
308
+ const general_constraint_indicator_flags_4 = eg.readUByte();
309
+ const general_constraint_indicator_flags_5 = eg.readUByte();
310
+ const general_constraint_indicator_flags_6 = eg.readUByte();
311
+ const general_level_idc = eg.readUByte();
312
+ const sub_layer_profile_present_flags: boolean[] = [];
313
+ const sub_layer_level_present_flags: boolean[] = [];
314
+ for (let i = 0; i < max_sub_layers_minus1; i++) {
315
+ sub_layer_profile_present_flags.push(eg.readBoolean());
316
+ sub_layer_level_present_flags.push(eg.readBoolean());
317
+ }
318
+ if (max_sub_layers_minus1 > 0) {
319
+ for (let i = max_sub_layers_minus1; i < 8; i++) {
320
+ eg.readBits(2);
321
+ }
322
+ }
323
+ for (let i = 0; i < max_sub_layers_minus1; i++) {
324
+ if (sub_layer_profile_present_flags[i]) {
325
+ eg.readUByte(); // sub_layer_profile_space, sub_layer_tier_flag, sub_layer_profile_idc
326
+ eg.readUByte();
327
+ eg.readUByte();
328
+ eg.readUByte();
329
+ eg.readUByte(); // sub_layer_profile_compatibility_flag
330
+ eg.readUByte();
331
+ eg.readUByte();
332
+ eg.readUByte();
333
+ eg.readUByte();
334
+ eg.readUByte();
335
+ eg.readUByte();
336
+ }
337
+ if (sub_layer_level_present_flags[i]) {
338
+ eg.readUByte();
339
+ }
340
+ }
341
+
342
+ eg.readUEG(); // seq_parameter_set_id
343
+ const chroma_format_idc = eg.readUEG();
344
+ if (chroma_format_idc == 3) {
345
+ eg.skipBits(1); //separate_colour_plane_flag
346
+ }
347
+ const pic_width_in_luma_samples = eg.readUEG();
348
+ const pic_height_in_luma_samples = eg.readUEG();
349
+ const conformance_window_flag = eg.readBoolean();
350
+ let pic_left_offset = 0,
351
+ pic_right_offset = 0,
352
+ pic_top_offset = 0,
353
+ pic_bottom_offset = 0;
354
+ if (conformance_window_flag) {
355
+ pic_left_offset += eg.readUEG();
356
+ pic_right_offset += eg.readUEG();
357
+ pic_top_offset += eg.readUEG();
358
+ pic_bottom_offset += eg.readUEG();
359
+ }
360
+ const bit_depth_luma_minus8 = eg.readUEG();
361
+ const bit_depth_chroma_minus8 = eg.readUEG();
362
+ const log2_max_pic_order_cnt_lsb_minus4 = eg.readUEG();
363
+ const sub_layer_ordering_info_present_flag = eg.readBoolean();
364
+ for (
365
+ let i = sub_layer_ordering_info_present_flag ? 0 : max_sub_layers_minus1;
366
+ i <= max_sub_layers_minus1;
367
+ i++
368
+ ) {
369
+ eg.skipUEG(); // max_dec_pic_buffering_minus1[i]
370
+ eg.skipUEG(); // max_num_reorder_pics[i]
371
+ eg.skipUEG(); // max_latency_increase_plus1[i]
372
+ }
373
+ eg.skipUEG(); // log2_min_luma_coding_block_size_minus3
374
+ eg.skipUEG(); // log2_diff_max_min_luma_coding_block_size
375
+ eg.skipUEG(); // log2_min_transform_block_size_minus2
376
+ eg.skipUEG(); // log2_diff_max_min_transform_block_size
377
+ eg.skipUEG(); // max_transform_hierarchy_depth_inter
378
+ eg.skipUEG(); // max_transform_hierarchy_depth_intra
379
+ const scaling_list_enabled_flag = eg.readBoolean();
380
+ if (scaling_list_enabled_flag) {
381
+ const sps_scaling_list_data_present_flag = eg.readBoolean();
382
+ if (sps_scaling_list_data_present_flag) {
383
+ for (let sizeId = 0; sizeId < 4; sizeId++) {
384
+ for (
385
+ let matrixId = 0;
386
+ matrixId < (sizeId === 3 ? 2 : 6);
387
+ matrixId++
388
+ ) {
389
+ const scaling_list_pred_mode_flag = eg.readBoolean();
390
+ if (!scaling_list_pred_mode_flag) {
391
+ eg.readUEG(); // scaling_list_pred_matrix_id_delta
392
+ } else {
393
+ const coefNum = Math.min(64, 1 << (4 + (sizeId << 1)));
394
+ if (sizeId > 1) {
395
+ eg.readEG();
396
+ }
397
+ for (let i = 0; i < coefNum; i++) {
398
+ eg.readEG();
399
+ }
400
+ }
401
+ }
402
+ }
403
+ }
404
+ }
405
+
406
+ eg.readBoolean(); // amp_enabled_flag
407
+ eg.readBoolean(); // sample_adaptive_offset_enabled_flag
408
+ const pcm_enabled_flag = eg.readBoolean();
409
+ if (pcm_enabled_flag) {
410
+ eg.readUByte();
411
+ eg.skipUEG();
412
+ eg.skipUEG();
413
+ eg.readBoolean();
414
+ }
415
+ const num_short_term_ref_pic_sets = eg.readUEG();
416
+ let num_delta_pocs = 0;
417
+ for (let i = 0; i < num_short_term_ref_pic_sets; i++) {
418
+ let inter_ref_pic_set_prediction_flag = false;
419
+ if (i !== 0) {
420
+ inter_ref_pic_set_prediction_flag = eg.readBoolean();
421
+ }
422
+ if (inter_ref_pic_set_prediction_flag) {
423
+ if (i === num_short_term_ref_pic_sets) {
424
+ eg.readUEG();
425
+ }
426
+ eg.readBoolean();
427
+ eg.readUEG();
428
+ let next_num_delta_pocs = 0;
429
+ for (let j = 0; j <= num_delta_pocs; j++) {
430
+ const used_by_curr_pic_flag = eg.readBoolean();
431
+ let use_delta_flag = false;
432
+ if (!used_by_curr_pic_flag) {
433
+ use_delta_flag = eg.readBoolean();
434
+ }
435
+ if (used_by_curr_pic_flag || use_delta_flag) {
436
+ next_num_delta_pocs++;
437
+ }
438
+ }
439
+ num_delta_pocs = next_num_delta_pocs;
440
+ } else {
441
+ const num_negative_pics = eg.readUEG();
442
+ const num_positive_pics = eg.readUEG();
443
+ num_delta_pocs = num_negative_pics + num_positive_pics;
444
+ for (let j = 0; j < num_negative_pics; j++) {
445
+ eg.readUEG();
446
+ eg.readBoolean();
447
+ }
448
+ for (let j = 0; j < num_positive_pics; j++) {
449
+ eg.readUEG();
450
+ eg.readBoolean();
451
+ }
452
+ }
453
+ }
454
+
455
+ const long_term_ref_pics_present_flag = eg.readBoolean();
456
+ if (long_term_ref_pics_present_flag) {
457
+ const num_long_term_ref_pics_sps = eg.readUEG();
458
+ for (let i = 0; i < num_long_term_ref_pics_sps; i++) {
459
+ for (let j = 0; j < log2_max_pic_order_cnt_lsb_minus4 + 4; j++) {
460
+ eg.readBits(1);
461
+ }
462
+ eg.readBits(1);
463
+ }
464
+ }
465
+
466
+ let min_spatial_segmentation_idc = 0;
467
+ let sar_width = 1,
468
+ sar_height = 1;
469
+ let fps_fixed = true,
470
+ fps_den = 1,
471
+ fps_num = 0;
472
+ eg.readBoolean(); // sps_temporal_mvp_enabled_flag
473
+ eg.readBoolean(); // strong_intra_smoothing_enabled_flag
474
+ let default_display_window_flag = false;
475
+ const vui_parameters_present_flag = eg.readBoolean();
476
+ if (vui_parameters_present_flag) {
477
+ const aspect_ratio_info_present_flag = eg.readBoolean();
478
+ if (aspect_ratio_info_present_flag) {
479
+ const aspect_ratio_idc = eg.readUByte();
480
+ const sar_width_table = [
481
+ 1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2,
482
+ ];
483
+ const sar_height_table = [
484
+ 1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1,
485
+ ];
486
+ if (aspect_ratio_idc > 0 && aspect_ratio_idc < 16) {
487
+ sar_width = sar_width_table[aspect_ratio_idc - 1];
488
+ sar_height = sar_height_table[aspect_ratio_idc - 1];
489
+ } else if (aspect_ratio_idc === 255) {
490
+ sar_width = eg.readBits(16);
491
+ sar_height = eg.readBits(16);
492
+ }
493
+ }
494
+ const overscan_info_present_flag = eg.readBoolean();
495
+ if (overscan_info_present_flag) {
496
+ eg.readBoolean();
497
+ }
498
+ const video_signal_type_present_flag = eg.readBoolean();
499
+ if (video_signal_type_present_flag) {
500
+ eg.readBits(3);
501
+ eg.readBoolean();
502
+ const colour_description_present_flag = eg.readBoolean();
503
+ if (colour_description_present_flag) {
504
+ eg.readUByte();
505
+ eg.readUByte();
506
+ eg.readUByte();
507
+ }
508
+ }
509
+ const chroma_loc_info_present_flag = eg.readBoolean();
510
+ if (chroma_loc_info_present_flag) {
511
+ eg.readUEG();
512
+ eg.readUEG();
513
+ }
514
+ eg.readBoolean(); // neutral_chroma_indication_flag
515
+ eg.readBoolean(); // field_seq_flag
516
+ eg.readBoolean(); // frame_field_info_present_flag
517
+ default_display_window_flag = eg.readBoolean();
518
+ if (default_display_window_flag) {
519
+ eg.skipUEG();
520
+ eg.skipUEG();
521
+ eg.skipUEG();
522
+ eg.skipUEG();
523
+ }
524
+ const vui_timing_info_present_flag = eg.readBoolean();
525
+ if (vui_timing_info_present_flag) {
526
+ fps_den = eg.readBits(32);
527
+ fps_num = eg.readBits(32);
528
+ const vui_poc_proportional_to_timing_flag = eg.readBoolean();
529
+ if (vui_poc_proportional_to_timing_flag) {
530
+ eg.readUEG();
531
+ }
532
+ const vui_hrd_parameters_present_flag = eg.readBoolean();
533
+ if (vui_hrd_parameters_present_flag) {
534
+ //const commonInfPresentFlag = true;
535
+ //if (commonInfPresentFlag) {
536
+ const nal_hrd_parameters_present_flag = eg.readBoolean();
537
+ const vcl_hrd_parameters_present_flag = eg.readBoolean();
538
+ let sub_pic_hrd_params_present_flag = false;
539
+ if (
540
+ nal_hrd_parameters_present_flag ||
541
+ vcl_hrd_parameters_present_flag
542
+ ) {
543
+ sub_pic_hrd_params_present_flag = eg.readBoolean();
544
+ if (sub_pic_hrd_params_present_flag) {
545
+ eg.readUByte();
546
+ eg.readBits(5);
547
+ eg.readBoolean();
548
+ eg.readBits(5);
549
+ }
550
+ eg.readBits(4); // bit_rate_scale
551
+ eg.readBits(4); // cpb_size_scale
552
+ if (sub_pic_hrd_params_present_flag) {
553
+ eg.readBits(4);
554
+ }
555
+ eg.readBits(5);
556
+ eg.readBits(5);
557
+ eg.readBits(5);
558
+ }
559
+ //}
560
+ for (let i = 0; i <= max_sub_layers_minus1; i++) {
561
+ fps_fixed = eg.readBoolean(); // fixed_pic_rate_general_flag
562
+ const fixed_pic_rate_within_cvs_flag =
563
+ fps_fixed || eg.readBoolean();
564
+ let low_delay_hrd_flag = false;
565
+ if (fixed_pic_rate_within_cvs_flag) {
566
+ eg.readEG();
567
+ } else {
568
+ low_delay_hrd_flag = eg.readBoolean();
569
+ }
570
+ const cpb_cnt = low_delay_hrd_flag ? 1 : eg.readUEG() + 1;
571
+ if (nal_hrd_parameters_present_flag) {
572
+ for (let j = 0; j < cpb_cnt; j++) {
573
+ eg.readUEG();
574
+ eg.readUEG();
575
+ if (sub_pic_hrd_params_present_flag) {
576
+ eg.readUEG();
577
+ eg.readUEG();
578
+ }
579
+ eg.skipBits(1);
580
+ }
581
+ }
582
+ if (vcl_hrd_parameters_present_flag) {
583
+ for (let j = 0; j < cpb_cnt; j++) {
584
+ eg.readUEG();
585
+ eg.readUEG();
586
+ if (sub_pic_hrd_params_present_flag) {
587
+ eg.readUEG();
588
+ eg.readUEG();
589
+ }
590
+ eg.skipBits(1);
591
+ }
592
+ }
593
+ }
594
+ }
595
+ }
596
+ const bitstream_restriction_flag = eg.readBoolean();
597
+ if (bitstream_restriction_flag) {
598
+ eg.readBoolean(); // tiles_fixed_structure_flag
599
+ eg.readBoolean(); // motion_vectors_over_pic_boundaries_flag
600
+ eg.readBoolean(); // restricted_ref_pic_lists_flag
601
+ min_spatial_segmentation_idc = eg.readUEG();
602
+ }
603
+ }
604
+
605
+ let width = pic_width_in_luma_samples,
606
+ height = pic_height_in_luma_samples;
607
+ if (conformance_window_flag) {
608
+ let chroma_scale_w = 1,
609
+ chroma_scale_h = 1;
610
+ if (chroma_format_idc === 1) {
611
+ // YUV 420
612
+ chroma_scale_w = chroma_scale_h = 2;
613
+ } else if (chroma_format_idc == 2) {
614
+ // YUV 422
615
+ chroma_scale_w = 2;
616
+ }
617
+ width =
618
+ pic_width_in_luma_samples -
619
+ chroma_scale_w * pic_right_offset -
620
+ chroma_scale_w * pic_left_offset;
621
+ height =
622
+ pic_height_in_luma_samples -
623
+ chroma_scale_h * pic_bottom_offset -
624
+ chroma_scale_h * pic_top_offset;
625
+ }
626
+
627
+ const profile_space_string = general_profile_space
628
+ ? ['A', 'B', 'C'][general_profile_space]
629
+ : '';
630
+ const profile_compatibility_buf =
631
+ (general_profile_compatibility_flags_1 << 24) |
632
+ (general_profile_compatibility_flags_2 << 16) |
633
+ (general_profile_compatibility_flags_3 << 8) |
634
+ general_profile_compatibility_flags_4;
635
+ let profile_compatibility_rev = 0;
636
+ for (let i = 0; i < 32; i++) {
637
+ profile_compatibility_rev =
638
+ (profile_compatibility_rev |
639
+ (((profile_compatibility_buf >> i) & 1) << (31 - i))) >>>
640
+ 0; // reverse bit position (and cast as UInt32)
641
+ }
642
+ let profile_compatibility_flags_string =
643
+ profile_compatibility_rev.toString(16);
644
+ if (
645
+ general_profile_idc === 1 &&
646
+ profile_compatibility_flags_string === '2'
647
+ ) {
648
+ profile_compatibility_flags_string = '6';
649
+ }
650
+ const tier_flag_string = general_tier_flag ? 'H' : 'L';
651
+
652
+ return {
653
+ codecString: `hvc1.${profile_space_string}${general_profile_idc}.${profile_compatibility_flags_string}.${tier_flag_string}${general_level_idc}.B0`,
654
+ params: {
655
+ general_tier_flag,
656
+ general_profile_idc,
657
+ general_profile_space,
658
+ general_profile_compatibility_flags: [
659
+ general_profile_compatibility_flags_1,
660
+ general_profile_compatibility_flags_2,
661
+ general_profile_compatibility_flags_3,
662
+ general_profile_compatibility_flags_4,
663
+ ],
664
+ general_constraint_indicator_flags: [
665
+ general_constraint_indicator_flags_1,
666
+ general_constraint_indicator_flags_2,
667
+ general_constraint_indicator_flags_3,
668
+ general_constraint_indicator_flags_4,
669
+ general_constraint_indicator_flags_5,
670
+ general_constraint_indicator_flags_6,
671
+ ],
672
+ general_level_idc,
673
+ bit_depth: bit_depth_luma_minus8 + 8,
674
+ bit_depth_luma_minus8,
675
+ bit_depth_chroma_minus8,
676
+ min_spatial_segmentation_idc,
677
+ chroma_format_idc: chroma_format_idc,
678
+ frame_rate: {
679
+ fixed: fps_fixed,
680
+ fps: fps_num / fps_den,
681
+ },
682
+ },
683
+ width,
684
+ height,
685
+ pixelRatio: [sar_width, sar_height],
686
+ };
687
+ }
688
+
689
+ readPPS(pps: Uint8Array): {
690
+ parallelismType: number;
691
+ } {
692
+ const eg = new ExpGolomb(this.ebsp2rbsp(pps));
693
+ eg.readUByte();
694
+ eg.readUByte();
695
+ eg.skipUEG(); // pic_parameter_set_id
696
+ eg.skipUEG(); // seq_parameter_set_id
697
+ eg.skipBits(2); // dependent_slice_segments_enabled_flag, output_flag_present_flag
698
+ eg.skipBits(3); // num_extra_slice_header_bits
699
+ eg.skipBits(2); // sign_data_hiding_enabled_flag, cabac_init_present_flag
700
+ eg.skipUEG();
701
+ eg.skipUEG();
702
+ eg.skipEG(); // init_qp_minus26
703
+ eg.skipBits(2); // constrained_intra_pred_flag, transform_skip_enabled_flag
704
+ const cu_qp_delta_enabled_flag = eg.readBoolean();
705
+ if (cu_qp_delta_enabled_flag) {
706
+ eg.skipUEG();
707
+ }
708
+ eg.skipEG(); // cb_qp_offset
709
+ eg.skipEG(); // cr_qp_offset
710
+ eg.skipBits(4); // pps_slice_chroma_qp_offsets_present_flag, weighted_pred_flag, weighted_bipred_flag, transquant_bypass_enabled_flag
711
+ const tiles_enabled_flag = eg.readBoolean();
712
+ const entropy_coding_sync_enabled_flag = eg.readBoolean();
713
+ let parallelismType = 1; // slice-based parallel decoding
714
+ if (entropy_coding_sync_enabled_flag && tiles_enabled_flag) {
715
+ parallelismType = 0; // mixed-type parallel decoding
716
+ } else if (entropy_coding_sync_enabled_flag) {
717
+ parallelismType = 3; // wavefront-based parallel decoding
718
+ } else if (tiles_enabled_flag) {
719
+ parallelismType = 2; // tile-based parallel decoding
720
+ }
721
+
722
+ return {
723
+ parallelismType,
724
+ };
725
+ }
726
+
727
+ matchSPS(sps1: Uint8Array, sps2: Uint8Array): boolean {
728
+ // compare without headers and VPS related params
729
+ return (
730
+ String.fromCharCode.apply(null, sps1).substr(3) ===
731
+ String.fromCharCode.apply(null, sps2).substr(3)
732
+ );
733
+ }
734
+ }
735
+
736
+ export default HevcVideoParser;