@alessmicrosystems/mpegts.js 1.8.1

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 (121) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +158 -0
  3. package/README_ja.md +153 -0
  4. package/README_zh.md +157 -0
  5. package/d.ts/mpegts.d.ts +524 -0
  6. package/d.ts/src/core/mse-events.d.ts +9 -0
  7. package/d.ts/src/core/transmuxing-events.d.ts +24 -0
  8. package/d.ts/src/demux/aac.d.ts +44 -0
  9. package/d.ts/src/demux/ac3.d.ts +70 -0
  10. package/d.ts/src/demux/av1-parser.d.ts +77 -0
  11. package/d.ts/src/demux/av1.d.ts +11 -0
  12. package/d.ts/src/demux/base-demuxer.d.ts +55 -0
  13. package/d.ts/src/demux/h264.d.ts +40 -0
  14. package/d.ts/src/demux/h265.d.ts +65 -0
  15. package/d.ts/src/demux/klv.d.ts +17 -0
  16. package/d.ts/src/demux/mp3.d.ts +6 -0
  17. package/d.ts/src/demux/mpeg4-audio.d.ts +28 -0
  18. package/d.ts/src/demux/pat-pmt-pes.d.ts +106 -0
  19. package/d.ts/src/demux/patpmt.d.ts +40 -0
  20. package/d.ts/src/demux/pes-private-data.d.ts +14 -0
  21. package/d.ts/src/demux/pgs-data.d.ts +9 -0
  22. package/d.ts/src/demux/scte35.d.ts +250 -0
  23. package/d.ts/src/demux/sei.d.ts +8 -0
  24. package/d.ts/src/demux/smpte2038.d.ts +22 -0
  25. package/d.ts/src/demux/ts-demuxer.d.ts +124 -0
  26. package/d.ts/src/player/live-latency-chaser.d.ts +10 -0
  27. package/d.ts/src/player/live-latency-synchronizer.d.ts +10 -0
  28. package/d.ts/src/player/loading-controller.d.ts +19 -0
  29. package/d.ts/src/player/mse-player.d.ts +30 -0
  30. package/d.ts/src/player/player-engine-dedicated-thread-worker.d.ts +2 -0
  31. package/d.ts/src/player/player-engine-dedicated-thread.d.ts +48 -0
  32. package/d.ts/src/player/player-engine-main-thread.d.ts +50 -0
  33. package/d.ts/src/player/player-engine-worker-cmd-def.d.ts +25 -0
  34. package/d.ts/src/player/player-engine-worker-msg-def.d.ts +54 -0
  35. package/d.ts/src/player/player-engine-worker.d.ts +2 -0
  36. package/d.ts/src/player/player-engine.d.ts +16 -0
  37. package/d.ts/src/player/player-events.d.ts +21 -0
  38. package/d.ts/src/player/seeking-handler.d.ts +22 -0
  39. package/d.ts/src/player/startup-stall-jumper.d.ts +14 -0
  40. package/d.ts/src/utils/typedarray-equality.d.ts +2 -0
  41. package/dist/mpegts.js +3 -0
  42. package/dist/mpegts.js.LICENSE.txt +7 -0
  43. package/dist/mpegts.js.map +1 -0
  44. package/package.json +53 -0
  45. package/src/config.js +67 -0
  46. package/src/core/features.js +88 -0
  47. package/src/core/media-info.js +127 -0
  48. package/src/core/media-segment-info.js +230 -0
  49. package/src/core/mse-controller.js +599 -0
  50. package/src/core/mse-events.ts +28 -0
  51. package/src/core/transmuxer.js +346 -0
  52. package/src/core/transmuxing-controller.js +628 -0
  53. package/src/core/transmuxing-events.ts +43 -0
  54. package/src/core/transmuxing-worker.js +286 -0
  55. package/src/demux/aac.ts +397 -0
  56. package/src/demux/ac3.ts +335 -0
  57. package/src/demux/amf-parser.js +243 -0
  58. package/src/demux/av1-parser.ts +629 -0
  59. package/src/demux/av1.ts +103 -0
  60. package/src/demux/base-demuxer.ts +69 -0
  61. package/src/demux/demux-errors.js +26 -0
  62. package/src/demux/exp-golomb.js +116 -0
  63. package/src/demux/flv-demuxer.js +1854 -0
  64. package/src/demux/h264.ts +187 -0
  65. package/src/demux/h265-parser.js +501 -0
  66. package/src/demux/h265.ts +214 -0
  67. package/src/demux/klv.ts +40 -0
  68. package/src/demux/mp3.ts +7 -0
  69. package/src/demux/mpeg4-audio.ts +45 -0
  70. package/src/demux/pat-pmt-pes.ts +132 -0
  71. package/src/demux/pes-private-data.ts +16 -0
  72. package/src/demux/pgs-data.ts +11 -0
  73. package/src/demux/scte35.ts +723 -0
  74. package/src/demux/sei.ts +99 -0
  75. package/src/demux/smpte2038.ts +89 -0
  76. package/src/demux/sps-parser.js +298 -0
  77. package/src/demux/ts-demuxer.ts +2405 -0
  78. package/src/index.js +4 -0
  79. package/src/io/fetch-stream-loader.js +266 -0
  80. package/src/io/io-controller.js +647 -0
  81. package/src/io/loader.js +134 -0
  82. package/src/io/param-seek-handler.js +85 -0
  83. package/src/io/range-seek-handler.js +52 -0
  84. package/src/io/speed-sampler.js +93 -0
  85. package/src/io/websocket-loader.js +151 -0
  86. package/src/io/xhr-moz-chunked-loader.js +211 -0
  87. package/src/io/xhr-msstream-loader.js +307 -0
  88. package/src/io/xhr-range-loader.js +366 -0
  89. package/src/mpegts.js +95 -0
  90. package/src/player/live-latency-chaser.ts +66 -0
  91. package/src/player/live-latency-synchronizer.ts +79 -0
  92. package/src/player/loading-controller.ts +142 -0
  93. package/src/player/mse-player.ts +150 -0
  94. package/src/player/native-player.js +262 -0
  95. package/src/player/player-engine-dedicated-thread.ts +479 -0
  96. package/src/player/player-engine-main-thread.ts +463 -0
  97. package/src/player/player-engine-worker-cmd-def.ts +62 -0
  98. package/src/player/player-engine-worker-msg-def.ts +102 -0
  99. package/src/player/player-engine-worker.ts +370 -0
  100. package/src/player/player-engine.ts +35 -0
  101. package/src/player/player-errors.js +39 -0
  102. package/src/player/player-events.ts +40 -0
  103. package/src/player/seeking-handler.ts +205 -0
  104. package/src/player/startup-stall-jumper.ts +86 -0
  105. package/src/remux/aac-silent.js +56 -0
  106. package/src/remux/mp4-generator.js +866 -0
  107. package/src/remux/mp4-remuxer.js +778 -0
  108. package/src/utils/browser.js +128 -0
  109. package/src/utils/exception.js +73 -0
  110. package/src/utils/logger.js +140 -0
  111. package/src/utils/logging-control.js +165 -0
  112. package/src/utils/polyfill.js +68 -0
  113. package/src/utils/typedarray-equality.ts +69 -0
  114. package/src/utils/utf8-conv.js +84 -0
  115. package/src/utils/webworkify-webpack.js +202 -0
  116. package/tsconfig.json +16 -0
  117. package/tslint.json +1 -0
  118. package/types/index.d.ts +3 -0
  119. package/types/test-flv.ts +8 -0
  120. package/types/tsconfig.json +24 -0
  121. package/webpack.config.js +55 -0
@@ -0,0 +1,723 @@
1
+ import ExpGolomb from './exp-golomb.js';
2
+
3
+ export type SCTE35Data = {
4
+ splice_command_type: SCTE35CommandType.kSpliceInsert
5
+ pts?: number,
6
+ nearest_pts?: number
7
+ auto_return?: boolean
8
+ duraiton?: number,
9
+ detail: SCTE35Detail
10
+ data: Uint8Array
11
+ } | {
12
+ splice_command_type: SCTE35CommandType.kTimeSignal
13
+ pts?: number,
14
+ nearest_pts?: number
15
+ detail: SCTE35Detail
16
+ data: Uint8Array
17
+ } | {
18
+ splice_command_type: SCTE35CommandType.kSpliceNull | SCTE35CommandType.kBandwidthReservation | SCTE35CommandType.kSpliceSchedule | SCTE35CommandType.kPrivateCommand
19
+ pts: undefined,
20
+ nearest_pts?: number
21
+ detail: SCTE35Detail
22
+ data: Uint8Array
23
+ }
24
+
25
+ type SCTE35Detail = {
26
+ table_id: number
27
+ section_syntax_indicator: boolean
28
+ private_indicator: boolean
29
+ section_length: number
30
+ protocol_version: number
31
+ encrypted_packet: boolean
32
+ encryption_algorithm: number
33
+ pts_adjustment: number
34
+ cw_index: number
35
+ tier: number
36
+ splice_command_length: number
37
+ splice_command_type: SCTE35CommandType.kSpliceNull
38
+ splice_command: SpliceNull
39
+ descriptor_loop_length: number
40
+ splice_descriptors: SpliceDescriptor[]
41
+ E_CRC32?: number
42
+ CRC32: number
43
+ } | {
44
+ table_id: number
45
+ section_syntax_indicator: boolean
46
+ private_indicator: boolean
47
+ section_length: number
48
+ protocol_version: number
49
+ encrypted_packet: boolean
50
+ encryption_algorithm: number
51
+ pts_adjustment: number
52
+ cw_index: number
53
+ tier: number
54
+ splice_command_length: number
55
+ splice_command_type: SCTE35CommandType.kSpliceSchedule
56
+ splice_command: SpliceSchedule
57
+ descriptor_loop_length: number
58
+ splice_descriptors: SpliceDescriptor[]
59
+ E_CRC32?: number
60
+ CRC32: number
61
+ } | {
62
+ table_id: number
63
+ section_syntax_indicator: boolean
64
+ private_indicator: boolean
65
+ section_length: number
66
+ protocol_version: number
67
+ encrypted_packet: boolean
68
+ encryption_algorithm: number
69
+ pts_adjustment: number
70
+ cw_index: number
71
+ tier: number
72
+ splice_command_length: number
73
+ splice_command_type: SCTE35CommandType.kSpliceInsert
74
+ splice_command: SpliceInsert
75
+ descriptor_loop_length: number
76
+ splice_descriptors: SpliceDescriptor[]
77
+ E_CRC32?: number
78
+ CRC32: number
79
+ } | {
80
+ table_id: number
81
+ section_syntax_indicator: boolean
82
+ private_indicator: boolean
83
+ section_length: number
84
+ protocol_version: number
85
+ encrypted_packet: boolean
86
+ encryption_algorithm: number
87
+ pts_adjustment: number
88
+ cw_index: number
89
+ tier: number
90
+ splice_command_length: number
91
+ splice_command_type: SCTE35CommandType.kTimeSignal
92
+ splice_command: TimeSignal
93
+ descriptor_loop_length: number
94
+ splice_descriptors: SpliceDescriptor[]
95
+ E_CRC32?: number
96
+ CRC32: number
97
+ } | {
98
+ table_id: number
99
+ section_syntax_indicator: boolean
100
+ private_indicator: boolean
101
+ section_length: number
102
+ protocol_version: number
103
+ encrypted_packet: boolean
104
+ encryption_algorithm: number
105
+ pts_adjustment: number
106
+ cw_index: number
107
+ tier: number
108
+ splice_command_length: number
109
+ splice_command_type: SCTE35CommandType.kBandwidthReservation
110
+ splice_command: BandwidthReservation
111
+ descriptor_loop_length: number
112
+ splice_descriptors: SpliceDescriptor[]
113
+ E_CRC32?: number
114
+ CRC32: number
115
+ } | {
116
+ table_id: number
117
+ section_syntax_indicator: boolean
118
+ private_indicator: boolean
119
+ section_length: number
120
+ protocol_version: number
121
+ encrypted_packet: boolean
122
+ encryption_algorithm: number
123
+ pts_adjustment: number
124
+ cw_index: number
125
+ tier: number
126
+ splice_command_length: number
127
+ splice_command_type: SCTE35CommandType.kPrivateCommand
128
+ splice_command: PrivateCommand
129
+ descriptor_loop_length: number
130
+ splice_descriptors: SpliceDescriptor[],
131
+ E_CRC32?: number
132
+ CRC32: number
133
+ };
134
+
135
+ export enum SCTE35CommandType {
136
+ kSpliceNull = 0x0,
137
+ kSpliceSchedule = 0x4,
138
+ kSpliceInsert = 0x5,
139
+ kTimeSignal = 0x6,
140
+ kBandwidthReservation = 0x07,
141
+ kPrivateCommand = 0xff
142
+ }
143
+
144
+ type SpliceTime = {
145
+ time_specified_flag: boolean,
146
+ pts_time?: number
147
+ }
148
+
149
+ const parseSpliceTime = (reader: ExpGolomb): SpliceTime => {
150
+ const time_specified_flag = reader.readBool()
151
+
152
+ if (!time_specified_flag) {
153
+ reader.readBits(7);
154
+ return { time_specified_flag }
155
+ } else {
156
+ reader.readBits(6)
157
+ const pts_time = reader.readBits(31) * 4 + reader.readBits(2);
158
+ return {
159
+ time_specified_flag,
160
+ pts_time
161
+ }
162
+ }
163
+ }
164
+
165
+ type BreakDuration = {
166
+ auto_return: boolean,
167
+ duration: number
168
+ }
169
+ const parseBreakDuration = (reader: ExpGolomb): BreakDuration => {
170
+ const auto_return = reader.readBool();
171
+ reader.readBits(6);
172
+ const duration = reader.readBits(31) * 4 + reader.readBits(2);
173
+ return {
174
+ auto_return,
175
+ duration
176
+ };
177
+ }
178
+
179
+ type SpliceInsertComponent = {
180
+ component_tag: number,
181
+ splice_time?: SpliceTime
182
+ }
183
+ const parseSpliceInsertComponent = (splice_immediate_flag: boolean, reader: ExpGolomb): SpliceInsertComponent => {
184
+ const component_tag = reader.readBits(8);
185
+ if (splice_immediate_flag) {
186
+ return { component_tag };
187
+ }
188
+
189
+ const splice_time = parseSpliceTime(reader);
190
+ return {
191
+ component_tag,
192
+ splice_time
193
+ };
194
+ }
195
+ type SpliceScheduleEventComponent = {
196
+ component_tag: number,
197
+ utc_splice_time: number
198
+ }
199
+ const parseSpliceScheduleEventComponent = (reader: ExpGolomb): SpliceScheduleEventComponent => {
200
+ const component_tag = reader.readBits(8);
201
+ const utc_splice_time = reader.readBits(32);
202
+ return {
203
+ component_tag,
204
+ utc_splice_time
205
+ };
206
+ }
207
+
208
+ type SpliceScheduleEvent = {
209
+ splice_event_id: number,
210
+ splice_event_cancel_indicator: boolean,
211
+ out_of_network_indicator?: boolean,
212
+ program_splice_flag?: boolean,
213
+ duration_flag?: boolean,
214
+ utc_splice_time?: number,
215
+ component_count?: number,
216
+ components?: SpliceScheduleEventComponent[]
217
+ break_duration?: BreakDuration,
218
+ unique_program_id?: number
219
+ avail_num?: number,
220
+ avails_expected?: number
221
+ }
222
+ const parseSpliceScheduleEvent = (reader: ExpGolomb): SpliceScheduleEvent => {
223
+ const splice_event_id = reader.readBits(32);
224
+ const splice_event_cancel_indicator = reader.readBool();
225
+ reader.readBits(7);
226
+
227
+ const spliceScheduleEvent: SpliceScheduleEvent = {
228
+ splice_event_id,
229
+ splice_event_cancel_indicator
230
+ }
231
+
232
+ if (splice_event_cancel_indicator) {
233
+ return spliceScheduleEvent;
234
+ }
235
+
236
+ spliceScheduleEvent.out_of_network_indicator = reader.readBool()
237
+ spliceScheduleEvent.program_splice_flag = reader.readBool()
238
+ spliceScheduleEvent.duration_flag = reader.readBool()
239
+ reader.readBits(5)
240
+
241
+ if (spliceScheduleEvent.program_splice_flag) {
242
+ spliceScheduleEvent.utc_splice_time = reader.readBits(32);
243
+ } else {
244
+ spliceScheduleEvent.component_count = reader.readBits(8);
245
+ spliceScheduleEvent.components = [];
246
+ for (let i = 0; i < spliceScheduleEvent.component_count; i++) {
247
+ spliceScheduleEvent.components.push(parseSpliceScheduleEventComponent(reader));
248
+ }
249
+ }
250
+
251
+ if (spliceScheduleEvent.duration_flag) {
252
+ spliceScheduleEvent.break_duration = parseBreakDuration(reader);
253
+ }
254
+
255
+ spliceScheduleEvent.unique_program_id = reader.readBits(16);
256
+ spliceScheduleEvent.avail_num = reader.readBits(8);
257
+ spliceScheduleEvent.avails_expected = reader.readBits(8);
258
+
259
+ return spliceScheduleEvent;
260
+ }
261
+
262
+ type SpliceNull = {}
263
+ type SpliceSchedule = {
264
+ splice_count: number,
265
+ events: SpliceScheduleEvent[],
266
+ }
267
+ type SpliceInsert = {
268
+ splice_event_id: number,
269
+ splice_event_cancel_indicator: boolean,
270
+ out_of_network_indicator?: boolean,
271
+ program_splice_flag?: boolean,
272
+ duration_flag?: boolean,
273
+ splice_immediate_flag?: boolean,
274
+ splice_time?: SpliceTime,
275
+ component_count?: number,
276
+ components?: SpliceInsertComponent[],
277
+ break_duration?: BreakDuration,
278
+ unique_program_id?: number,
279
+ avail_num?: number,
280
+ avails_expected?: number
281
+ }
282
+ type TimeSignal = {
283
+ splice_time: SpliceTime
284
+ }
285
+ type BandwidthReservation = {}
286
+ type PrivateCommand = {
287
+ identifier: string,
288
+ private_data: ArrayBuffer
289
+ }
290
+
291
+ type SpliceCommand = SpliceNull | SpliceSchedule | SpliceInsert | TimeSignal | BandwidthReservation | PrivateCommand
292
+
293
+ const parseSpliceNull = (): SpliceNull => {
294
+ return {};
295
+ };
296
+ const parseSpliceSchedule = (reader: ExpGolomb): SpliceSchedule => {
297
+ const splice_count = reader.readBits(8)
298
+ const events: SpliceScheduleEvent[] = [];
299
+ for (let i = 0; i < splice_count; i++) {
300
+ events.push(parseSpliceScheduleEvent(reader));
301
+ }
302
+ return {
303
+ splice_count,
304
+ events
305
+ };
306
+ }
307
+ const parseSpliceInsert = (reader: ExpGolomb): SpliceInsert => {
308
+ const splice_event_id = reader.readBits(32);
309
+ const splice_event_cancel_indicator = reader.readBool();
310
+ reader.readBits(7);
311
+
312
+ const spliceInsert: SpliceInsert = {
313
+ splice_event_id,
314
+ splice_event_cancel_indicator
315
+ }
316
+
317
+ if (splice_event_cancel_indicator) {
318
+ return spliceInsert;
319
+ }
320
+
321
+ spliceInsert.out_of_network_indicator = reader.readBool()
322
+ spliceInsert.program_splice_flag = reader.readBool()
323
+ spliceInsert.duration_flag = reader.readBool()
324
+ spliceInsert.splice_immediate_flag = reader.readBool()
325
+ reader.readBits(4)
326
+
327
+ if (spliceInsert.program_splice_flag && !spliceInsert.splice_immediate_flag) {
328
+ spliceInsert.splice_time = parseSpliceTime(reader);
329
+ }
330
+ if (!spliceInsert.program_splice_flag) {
331
+ spliceInsert.component_count = reader.readBits(8)
332
+ spliceInsert.components = [];
333
+ for (let i = 0; i < spliceInsert.component_count; i++) {
334
+ spliceInsert.components.push(parseSpliceInsertComponent(spliceInsert.splice_immediate_flag, reader));
335
+ }
336
+ }
337
+
338
+ if (spliceInsert.duration_flag) {
339
+ spliceInsert.break_duration = parseBreakDuration(reader);
340
+ }
341
+
342
+ spliceInsert.unique_program_id = reader.readBits(16);
343
+ spliceInsert.avail_num = reader.readBits(8);
344
+ spliceInsert.avails_expected = reader.readBits(8);
345
+
346
+ return spliceInsert;
347
+ }
348
+ const parseTimeSignal = (reader: ExpGolomb): TimeSignal => {
349
+ return {
350
+ splice_time: parseSpliceTime(reader)
351
+ };
352
+ }
353
+ const parseBandwidthReservation = (): BandwidthReservation => {
354
+ return {};
355
+ }
356
+ const parsePrivateCommand = (splice_command_length: number, reader: ExpGolomb): PrivateCommand => {
357
+ const identifier = String.fromCharCode(reader.readBits(8), reader.readBits(8), reader.readBits(8), reader.readBits(8))
358
+ const data = new Uint8Array(splice_command_length - 4);
359
+ for (let i = 0; i < splice_command_length - 4; i++) {
360
+ data[i] = reader.readBits(8);
361
+ }
362
+
363
+ return {
364
+ identifier,
365
+ private_data: data.buffer
366
+ }
367
+ }
368
+
369
+ type Descriptor = {
370
+ descriptor_tag: number,
371
+ descriptor_length: number,
372
+ identifier: string
373
+ }
374
+ type AvailDescriptor = Descriptor & {
375
+ provider_avail_id: number
376
+ }
377
+ const parseAvailDescriptor = (descriptor_tag: number, descriptor_length: number, identifier: string, reader: ExpGolomb): AvailDescriptor => {
378
+ const provider_avail_id = reader.readBits(32);
379
+
380
+ return {
381
+ descriptor_tag,
382
+ descriptor_length,
383
+ identifier,
384
+ provider_avail_id
385
+ }
386
+ }
387
+ type DTMFDescriptor = Descriptor & {
388
+ preroll: number,
389
+ dtmf_count: number,
390
+ DTMF_char: string
391
+ }
392
+ const parseDTMFDescriptor = (descriptor_tag: number, descriptor_length: number, identifier: string, reader: ExpGolomb): DTMFDescriptor => {
393
+ const preroll = reader.readBits(8);
394
+ const dtmf_count = reader.readBits(3);
395
+ reader.readBits(5);
396
+ let DTMF_char = '';
397
+ for (let i = 0; i < dtmf_count; i++) {
398
+ DTMF_char += String.fromCharCode(reader.readBits(8));
399
+ }
400
+
401
+ return {
402
+ descriptor_tag,
403
+ descriptor_length,
404
+ identifier,
405
+ preroll,
406
+ dtmf_count,
407
+ DTMF_char
408
+ };
409
+ }
410
+ type SegmentationDescriptorComponent = {
411
+ component_tag: number,
412
+ pts_offset: number
413
+ }
414
+ const parseSegmentationDescriptorComponent = (reader: ExpGolomb): SegmentationDescriptorComponent => {
415
+ const component_tag = reader.readBits(8);
416
+ reader.readBits(7)
417
+ const pts_offset = reader.readBits(31) * 4 + reader.readBits(2);
418
+ return {
419
+ component_tag,
420
+ pts_offset
421
+ };
422
+ }
423
+ type SegmentationDescriptor = Descriptor & {
424
+ segmentation_event_id: number,
425
+ segmentation_event_cancel_indicator: boolean,
426
+ program_segmentation_flag?: boolean,
427
+ segmentation_duration_flag?: boolean
428
+ delivery_not_restricted_flag?: boolean
429
+ web_delivery_allowed_flag?: boolean
430
+ no_regional_blackout_flag?: boolean,
431
+ archive_allowed_flag?: boolean,
432
+ device_restrictions?: number
433
+ component_count?: number,
434
+ components?: any[]
435
+ segmentation_duration?: number
436
+ segmentation_upid_type?: number,
437
+ segmentation_upid_length?: number,
438
+ segmentation_upid?: ArrayBuffer,
439
+ segmentation_type_id?: number,
440
+ segment_num?: number,
441
+ segments_expected?: number,
442
+ sub_segment_num?: number,
443
+ sub_segments_expected?: number
444
+ }
445
+ const parseSegmentationDescriptor = (descriptor_tag: number, descriptor_length: number, identifier: string, reader: ExpGolomb): SegmentationDescriptor => {
446
+ const segmentation_event_id = reader.readBits(32);
447
+ const segmentation_event_cancel_indicator = reader.readBool();
448
+ reader.readBits(7);
449
+
450
+ const segmentationDescriptor: SegmentationDescriptor = {
451
+ descriptor_tag,
452
+ descriptor_length,
453
+ identifier,
454
+ segmentation_event_id,
455
+ segmentation_event_cancel_indicator
456
+ }
457
+
458
+ if (segmentation_event_cancel_indicator) {
459
+ return segmentationDescriptor;
460
+ }
461
+
462
+ segmentationDescriptor.program_segmentation_flag = reader.readBool();
463
+ segmentationDescriptor.segmentation_duration_flag = reader.readBool();
464
+ segmentationDescriptor.delivery_not_restricted_flag = reader.readBool();
465
+
466
+ if (!segmentationDescriptor.delivery_not_restricted_flag) {
467
+ segmentationDescriptor.web_delivery_allowed_flag = reader.readBool();
468
+ segmentationDescriptor.no_regional_blackout_flag = reader.readBool();
469
+ segmentationDescriptor.archive_allowed_flag = reader.readBool();
470
+ segmentationDescriptor.device_restrictions = reader.readBits(2);
471
+ } else {
472
+ reader.readBits(5);
473
+ }
474
+
475
+ if (!segmentationDescriptor.program_segmentation_flag) {
476
+ segmentationDescriptor.component_count = reader.readBits(8);
477
+ segmentationDescriptor.components = [];
478
+ for (let i = 0; i < segmentationDescriptor.component_count; i++) {
479
+ segmentationDescriptor.components.push(parseSegmentationDescriptorComponent(reader));
480
+ }
481
+ }
482
+
483
+ if (segmentationDescriptor.segmentation_duration_flag) {
484
+ segmentationDescriptor.segmentation_duration = reader.readBits(40);
485
+ }
486
+
487
+ segmentationDescriptor.segmentation_upid_type = reader.readBits(8);
488
+ segmentationDescriptor.segmentation_upid_length = reader.readBits(8);
489
+ {
490
+ const upid = new Uint8Array(segmentationDescriptor.segmentation_upid_length)
491
+ for (let i = 0; i < segmentationDescriptor.segmentation_upid_length; i++) {
492
+ upid[i] = reader.readBits(8);
493
+ }
494
+ segmentationDescriptor.segmentation_upid = upid.buffer;
495
+ }
496
+ segmentationDescriptor.segmentation_type_id = reader.readBits(8);
497
+ segmentationDescriptor.segment_num = reader.readBits(8);
498
+ segmentationDescriptor.segments_expected = reader.readBits(8);
499
+ if (
500
+ segmentationDescriptor.segmentation_type_id === 0x34 ||
501
+ segmentationDescriptor.segmentation_type_id === 0x36 ||
502
+ segmentationDescriptor.segmentation_type_id === 0x38 ||
503
+ segmentationDescriptor.segmentation_type_id === 0x3A
504
+ ) {
505
+ segmentationDescriptor.sub_segment_num = reader.readBits(8);
506
+ segmentationDescriptor.sub_segments_expected = reader.readBits(8);
507
+ }
508
+
509
+ return segmentationDescriptor;
510
+ }
511
+ type TimeDescriptor = Descriptor & {
512
+ TAI_seconds: number,
513
+ TAI_ns: number,
514
+ UTC_offset: number
515
+ }
516
+ const parseTimeDescriptor = (descriptor_tag: number, descriptor_length: number, identifier: string, reader: ExpGolomb): TimeDescriptor => {
517
+ const TAI_seconds = reader.readBits(48);
518
+ const TAI_ns = reader.readBits(32);
519
+ const UTC_offset = reader.readBits(16);
520
+
521
+ return {
522
+ descriptor_tag,
523
+ descriptor_length,
524
+ identifier,
525
+ TAI_seconds,
526
+ TAI_ns,
527
+ UTC_offset
528
+ };
529
+ }
530
+ type AudioDescriptorComponent = {
531
+ component_tag: number,
532
+ ISO_code: string
533
+ Bit_Stream_Mode: number
534
+ Num_Channels: number,
535
+ Full_Srvc_Audio: boolean
536
+ }
537
+ const parseAudioDescriptorComponent = (reader: ExpGolomb): AudioDescriptorComponent => {
538
+ const component_tag = reader.readBits(8)
539
+ const ISO_code = String.fromCharCode(reader.readBits(8), reader.readBits(8), reader.readBits(8));
540
+ const Bit_Stream_Mode = reader.readBits(3);
541
+ const Num_Channels = reader.readBits(4);
542
+ const Full_Srvc_Audio = reader.readBool();
543
+
544
+ return {
545
+ component_tag,
546
+ ISO_code,
547
+ Bit_Stream_Mode,
548
+ Num_Channels,
549
+ Full_Srvc_Audio
550
+ };
551
+ }
552
+ type AudioDescriptor = Descriptor & {
553
+ audio_count: number,
554
+ components: AudioDescriptorComponent[]
555
+ }
556
+ const parseAudioDescriptor = (descriptor_tag: number, descriptor_length: number, identifier: string, reader: ExpGolomb): AudioDescriptor => {
557
+ const audio_count = reader.readBits(4);
558
+ const components: AudioDescriptorComponent[] = [];
559
+ for (let i = 0; i < audio_count; i++) {
560
+ components.push(parseAudioDescriptorComponent(reader));
561
+ }
562
+
563
+ return {
564
+ descriptor_tag,
565
+ descriptor_length,
566
+ identifier,
567
+ audio_count,
568
+ components
569
+ };
570
+ }
571
+
572
+ type SpliceDescriptor = AvailDescriptor | DTMFDescriptor | SegmentationDescriptor | TimeDescriptor | AudioDescriptor;
573
+
574
+ export const readSCTE35 = (data: Uint8Array): SCTE35Data => {
575
+ const reader = new ExpGolomb(data);
576
+
577
+ const table_id = reader.readBits(8);
578
+ const section_syntax_indicator = reader.readBool();
579
+ const private_indicator = reader.readBool();
580
+ reader.readBits(2);
581
+ const section_length = reader.readBits(12);
582
+ const protocol_version = reader.readBits(8);
583
+ const encrypted_packet = reader.readBool();
584
+ const encryption_algorithm = reader.readBits(6);
585
+ const pts_adjustment = reader.readBits(31) * 4 + reader.readBits(2);
586
+ const cw_index = reader.readBits(8);
587
+ const tier = reader.readBits(12);
588
+ const splice_command_length = reader.readBits(12)
589
+ const splice_command_type = reader.readBits(8)
590
+
591
+ let splice_command: SpliceCommand | null = null;
592
+ if (splice_command_type === SCTE35CommandType.kSpliceNull) {
593
+ splice_command = parseSpliceNull();
594
+ } else if (splice_command_type === SCTE35CommandType.kSpliceSchedule) {
595
+ splice_command = parseSpliceSchedule(reader);
596
+ } else if (splice_command_type === SCTE35CommandType.kSpliceInsert) {
597
+ splice_command = parseSpliceInsert(reader);
598
+ } else if (splice_command_type === SCTE35CommandType.kTimeSignal) {
599
+ splice_command = parseTimeSignal(reader);
600
+ } else if (splice_command_type === SCTE35CommandType.kBandwidthReservation) {
601
+ splice_command = parseBandwidthReservation();
602
+ } else if (splice_command_type === SCTE35CommandType.kPrivateCommand) {
603
+ splice_command = parsePrivateCommand(splice_command_length, reader)
604
+ } else {
605
+ reader.readBits(splice_command_length * 8);
606
+ }
607
+
608
+ const splice_descriptors: SpliceDescriptor[] = [];
609
+
610
+ const descriptor_loop_length = reader.readBits(16);
611
+ for (let length = 0; length < descriptor_loop_length;) {
612
+ const descriptor_tag = reader.readBits(8);
613
+ const descriptor_length = reader.readBits(8);
614
+ const identifier = String.fromCharCode(reader.readBits(8), reader.readBits(8), reader.readBits(8), reader.readBits(8));
615
+
616
+ if (descriptor_tag === 0x00) {
617
+ splice_descriptors.push(parseAvailDescriptor(descriptor_tag, descriptor_length, identifier, reader));
618
+ } else if (descriptor_tag === 0x01) {
619
+ splice_descriptors.push(parseDTMFDescriptor(descriptor_tag, descriptor_length, identifier, reader));
620
+ } else if (descriptor_tag === 0x02) {
621
+ splice_descriptors.push(parseSegmentationDescriptor(descriptor_tag, descriptor_length, identifier, reader));
622
+ } else if (descriptor_tag === 0x03) {
623
+ splice_descriptors.push(parseTimeDescriptor(descriptor_tag, descriptor_length, identifier, reader));
624
+ } else if (descriptor_tag === 0x04) {
625
+ splice_descriptors.push(parseAudioDescriptor(descriptor_tag, descriptor_length, identifier, reader));
626
+ } else {
627
+ reader.readBits((descriptor_length - 4) * 8);
628
+ }
629
+
630
+ length += 2 + descriptor_length;
631
+ }
632
+
633
+ const E_CRC32 = encrypted_packet ? reader.readBits(32) : undefined;
634
+ const CRC32 = reader.readBits(32);
635
+
636
+ const detail = {
637
+ table_id,
638
+ section_syntax_indicator,
639
+ private_indicator,
640
+ section_length,
641
+ protocol_version,
642
+ encrypted_packet,
643
+ encryption_algorithm,
644
+ pts_adjustment,
645
+ cw_index,
646
+ tier,
647
+ splice_command_length,
648
+ splice_command_type,
649
+ splice_command,
650
+ descriptor_loop_length,
651
+ splice_descriptors,
652
+ E_CRC32,
653
+ CRC32
654
+ };
655
+
656
+ if (splice_command_type === SCTE35CommandType.kSpliceInsert) {
657
+ const spliceInsert = splice_command as SpliceInsert;
658
+
659
+ if (spliceInsert.splice_event_cancel_indicator) {
660
+ return {
661
+ splice_command_type,
662
+ detail,
663
+ data
664
+ }
665
+ } else if (spliceInsert.program_splice_flag && !spliceInsert.splice_immediate_flag) {
666
+ const auto_return = spliceInsert.duration_flag ? spliceInsert.break_duration.auto_return : undefined;
667
+ const duraiton = spliceInsert.duration_flag ? spliceInsert.break_duration.duration / 90 : undefined;
668
+
669
+ if (spliceInsert.splice_time.time_specified_flag) {
670
+ return {
671
+ splice_command_type,
672
+ pts: (pts_adjustment + spliceInsert.splice_time.pts_time) % (2 ** 33),
673
+ auto_return,
674
+ duraiton,
675
+ detail,
676
+ data
677
+ }
678
+ } else {
679
+ return {
680
+ splice_command_type,
681
+ auto_return,
682
+ duraiton,
683
+ detail,
684
+ data
685
+ }
686
+ }
687
+ } else {
688
+ const auto_return = spliceInsert.duration_flag ? spliceInsert.break_duration.auto_return : undefined;
689
+ const duraiton = spliceInsert.duration_flag ? spliceInsert.break_duration.duration / 90 : undefined;
690
+
691
+ return {
692
+ splice_command_type,
693
+ auto_return,
694
+ duraiton,
695
+ detail,
696
+ data
697
+ }
698
+ }
699
+ } else if (splice_command_type === SCTE35CommandType.kTimeSignal) {
700
+ const timeSignal = splice_command as TimeSignal;
701
+
702
+ if (timeSignal.splice_time.time_specified_flag) {
703
+ return {
704
+ splice_command_type,
705
+ pts: (pts_adjustment + timeSignal.splice_time.pts_time) % (2 ** 33),
706
+ detail,
707
+ data
708
+ }
709
+ } else {
710
+ return {
711
+ splice_command_type,
712
+ detail,
713
+ data
714
+ }
715
+ }
716
+ } else {
717
+ return {
718
+ splice_command_type,
719
+ detail,
720
+ data
721
+ }
722
+ }
723
+ }