@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,866 @@
1
+ /*
2
+ * Copyright (C) 2016 Bilibili. All Rights Reserved.
3
+ *
4
+ * This file is derived from dailymotion's hls.js library (hls.js/src/remux/mp4-generator.js)
5
+ * @author zheng qian <xqq@xqq.im>
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+
20
+ // MP4 boxes generator for ISO BMFF (ISO Base Media File Format, defined in ISO/IEC 14496-12)
21
+ class MP4 {
22
+
23
+ static init() {
24
+ MP4.types = {
25
+ avc1: [], avcC: [], btrt: [], dinf: [],
26
+ dref: [], esds: [], ftyp: [], hdlr: [],
27
+ hvc1: [], hvcC: [], av01: [], av1C: [],
28
+ mdat: [], mdhd: [], mdia: [], mfhd: [],
29
+ minf: [], moof: [], moov: [], mp4a: [],
30
+ mvex: [], mvhd: [], sdtp: [], stbl: [],
31
+ stco: [], stsc: [], stsd: [], stsz: [],
32
+ stts: [], tfdt: [], tfhd: [], traf: [],
33
+ trak: [], trun: [], trex: [], tkhd: [],
34
+ vmhd: [], smhd: [], chnl: [],
35
+ '.mp3': [],
36
+ Opus: [], dOps: [], fLaC: [], dfLa: [],
37
+ ipcm: [], pcmC: [],
38
+ 'ac-3': [], dac3: [], 'ec-3': [], dec3: [],
39
+ };
40
+
41
+ for (let name in MP4.types) {
42
+ if (MP4.types.hasOwnProperty(name)) {
43
+ MP4.types[name] = [
44
+ name.charCodeAt(0),
45
+ name.charCodeAt(1),
46
+ name.charCodeAt(2),
47
+ name.charCodeAt(3)
48
+ ];
49
+ }
50
+ }
51
+
52
+ let constants = MP4.constants = {};
53
+
54
+ constants.FTYP = new Uint8Array([
55
+ 0x69, 0x73, 0x6F, 0x6D, // major_brand: isom
56
+ 0x0, 0x0, 0x0, 0x1, // minor_version: 0x01
57
+ 0x69, 0x73, 0x6F, 0x6D, // isom
58
+ 0x61, 0x76, 0x63, 0x31 // avc1
59
+ ]);
60
+
61
+ constants.STSD_PREFIX = new Uint8Array([
62
+ 0x00, 0x00, 0x00, 0x00, // version(0) + flags
63
+ 0x00, 0x00, 0x00, 0x01 // entry_count
64
+ ]);
65
+
66
+ constants.STTS = new Uint8Array([
67
+ 0x00, 0x00, 0x00, 0x00, // version(0) + flags
68
+ 0x00, 0x00, 0x00, 0x00 // entry_count
69
+ ]);
70
+
71
+ constants.STSC = constants.STCO = constants.STTS;
72
+
73
+ constants.STSZ = new Uint8Array([
74
+ 0x00, 0x00, 0x00, 0x00, // version(0) + flags
75
+ 0x00, 0x00, 0x00, 0x00, // sample_size
76
+ 0x00, 0x00, 0x00, 0x00 // sample_count
77
+ ]);
78
+
79
+ constants.HDLR_VIDEO = new Uint8Array([
80
+ 0x00, 0x00, 0x00, 0x00, // version(0) + flags
81
+ 0x00, 0x00, 0x00, 0x00, // pre_defined
82
+ 0x76, 0x69, 0x64, 0x65, // handler_type: 'vide'
83
+ 0x00, 0x00, 0x00, 0x00, // reserved: 3 * 4 bytes
84
+ 0x00, 0x00, 0x00, 0x00,
85
+ 0x00, 0x00, 0x00, 0x00,
86
+ 0x56, 0x69, 0x64, 0x65,
87
+ 0x6F, 0x48, 0x61, 0x6E,
88
+ 0x64, 0x6C, 0x65, 0x72, 0x00 // name: VideoHandler
89
+ ]);
90
+
91
+ constants.HDLR_AUDIO = new Uint8Array([
92
+ 0x00, 0x00, 0x00, 0x00, // version(0) + flags
93
+ 0x00, 0x00, 0x00, 0x00, // pre_defined
94
+ 0x73, 0x6F, 0x75, 0x6E, // handler_type: 'soun'
95
+ 0x00, 0x00, 0x00, 0x00, // reserved: 3 * 4 bytes
96
+ 0x00, 0x00, 0x00, 0x00,
97
+ 0x00, 0x00, 0x00, 0x00,
98
+ 0x53, 0x6F, 0x75, 0x6E,
99
+ 0x64, 0x48, 0x61, 0x6E,
100
+ 0x64, 0x6C, 0x65, 0x72, 0x00 // name: SoundHandler
101
+ ]);
102
+
103
+ constants.DREF = new Uint8Array([
104
+ 0x00, 0x00, 0x00, 0x00, // version(0) + flags
105
+ 0x00, 0x00, 0x00, 0x01, // entry_count
106
+ 0x00, 0x00, 0x00, 0x0C, // entry_size
107
+ 0x75, 0x72, 0x6C, 0x20, // type 'url '
108
+ 0x00, 0x00, 0x00, 0x01 // version(0) + flags
109
+ ]);
110
+
111
+ // Sound media header
112
+ constants.SMHD = new Uint8Array([
113
+ 0x00, 0x00, 0x00, 0x00, // version(0) + flags
114
+ 0x00, 0x00, 0x00, 0x00 // balance(2) + reserved(2)
115
+ ]);
116
+
117
+ // video media header
118
+ constants.VMHD = new Uint8Array([
119
+ 0x00, 0x00, 0x00, 0x01, // version(0) + flags
120
+ 0x00, 0x00, // graphicsmode: 2 bytes
121
+ 0x00, 0x00, 0x00, 0x00, // opcolor: 3 * 2 bytes
122
+ 0x00, 0x00
123
+ ]);
124
+ }
125
+
126
+ // Generate a box
127
+ static box(type) {
128
+ let size = 8;
129
+ let result = null;
130
+ let datas = Array.prototype.slice.call(arguments, 1);
131
+ let arrayCount = datas.length;
132
+
133
+ for (let i = 0; i < arrayCount; i++) {
134
+ size += datas[i].byteLength;
135
+ }
136
+
137
+ result = new Uint8Array(size);
138
+ result[0] = (size >>> 24) & 0xFF; // size
139
+ result[1] = (size >>> 16) & 0xFF;
140
+ result[2] = (size >>> 8) & 0xFF;
141
+ result[3] = (size) & 0xFF;
142
+
143
+ result.set(type, 4); // type
144
+
145
+ let offset = 8;
146
+ for (let i = 0; i < arrayCount; i++) { // data body
147
+ result.set(datas[i], offset);
148
+ offset += datas[i].byteLength;
149
+ }
150
+
151
+ return result;
152
+ }
153
+
154
+ // emit ftyp & moov
155
+ static generateInitSegment(meta) {
156
+ let ftyp = MP4.box(MP4.types.ftyp, MP4.constants.FTYP);
157
+ let moov = MP4.moov(meta);
158
+
159
+ let result = new Uint8Array(ftyp.byteLength + moov.byteLength);
160
+ result.set(ftyp, 0);
161
+ result.set(moov, ftyp.byteLength);
162
+ return result;
163
+ }
164
+
165
+ // Movie metadata box
166
+ static moov(meta) {
167
+ let mvhd = MP4.mvhd(meta.timescale, meta.duration);
168
+ let trak = MP4.trak(meta);
169
+ let mvex = MP4.mvex(meta);
170
+ return MP4.box(MP4.types.moov, mvhd, trak, mvex);
171
+ }
172
+
173
+ // Movie header box
174
+ static mvhd(timescale, duration) {
175
+ return MP4.box(MP4.types.mvhd, new Uint8Array([
176
+ 0x00, 0x00, 0x00, 0x00, // version(0) + flags
177
+ 0x00, 0x00, 0x00, 0x00, // creation_time
178
+ 0x00, 0x00, 0x00, 0x00, // modification_time
179
+ (timescale >>> 24) & 0xFF, // timescale: 4 bytes
180
+ (timescale >>> 16) & 0xFF,
181
+ (timescale >>> 8) & 0xFF,
182
+ (timescale) & 0xFF,
183
+ (duration >>> 24) & 0xFF, // duration: 4 bytes
184
+ (duration >>> 16) & 0xFF,
185
+ (duration >>> 8) & 0xFF,
186
+ (duration) & 0xFF,
187
+ 0x00, 0x01, 0x00, 0x00, // Preferred rate: 1.0
188
+ 0x01, 0x00, 0x00, 0x00, // PreferredVolume(1.0, 2bytes) + reserved(2bytes)
189
+ 0x00, 0x00, 0x00, 0x00, // reserved: 4 + 4 bytes
190
+ 0x00, 0x00, 0x00, 0x00,
191
+ 0x00, 0x01, 0x00, 0x00, // ----begin composition matrix----
192
+ 0x00, 0x00, 0x00, 0x00,
193
+ 0x00, 0x00, 0x00, 0x00,
194
+ 0x00, 0x00, 0x00, 0x00,
195
+ 0x00, 0x01, 0x00, 0x00,
196
+ 0x00, 0x00, 0x00, 0x00,
197
+ 0x00, 0x00, 0x00, 0x00,
198
+ 0x00, 0x00, 0x00, 0x00,
199
+ 0x40, 0x00, 0x00, 0x00, // ----end composition matrix----
200
+ 0x00, 0x00, 0x00, 0x00, // ----begin pre_defined 6 * 4 bytes----
201
+ 0x00, 0x00, 0x00, 0x00,
202
+ 0x00, 0x00, 0x00, 0x00,
203
+ 0x00, 0x00, 0x00, 0x00,
204
+ 0x00, 0x00, 0x00, 0x00,
205
+ 0x00, 0x00, 0x00, 0x00, // ----end pre_defined 6 * 4 bytes----
206
+ 0xFF, 0xFF, 0xFF, 0xFF // next_track_ID
207
+ ]));
208
+ }
209
+
210
+ // Track box
211
+ static trak(meta) {
212
+ return MP4.box(MP4.types.trak, MP4.tkhd(meta), MP4.mdia(meta));
213
+ }
214
+
215
+ // Track header box
216
+ static tkhd(meta) {
217
+ let trackId = meta.id, duration = meta.duration;
218
+ let width = meta.presentWidth, height = meta.presentHeight;
219
+
220
+ return MP4.box(MP4.types.tkhd, new Uint8Array([
221
+ 0x00, 0x00, 0x00, 0x07, // version(0) + flags
222
+ 0x00, 0x00, 0x00, 0x00, // creation_time
223
+ 0x00, 0x00, 0x00, 0x00, // modification_time
224
+ (trackId >>> 24) & 0xFF, // track_ID: 4 bytes
225
+ (trackId >>> 16) & 0xFF,
226
+ (trackId >>> 8) & 0xFF,
227
+ (trackId) & 0xFF,
228
+ 0x00, 0x00, 0x00, 0x00, // reserved: 4 bytes
229
+ (duration >>> 24) & 0xFF, // duration: 4 bytes
230
+ (duration >>> 16) & 0xFF,
231
+ (duration >>> 8) & 0xFF,
232
+ (duration) & 0xFF,
233
+ 0x00, 0x00, 0x00, 0x00, // reserved: 2 * 4 bytes
234
+ 0x00, 0x00, 0x00, 0x00,
235
+ 0x00, 0x00, 0x00, 0x00, // layer(2bytes) + alternate_group(2bytes)
236
+ 0x00, 0x00, 0x00, 0x00, // volume(2bytes) + reserved(2bytes)
237
+ 0x00, 0x01, 0x00, 0x00, // ----begin composition matrix----
238
+ 0x00, 0x00, 0x00, 0x00,
239
+ 0x00, 0x00, 0x00, 0x00,
240
+ 0x00, 0x00, 0x00, 0x00,
241
+ 0x00, 0x01, 0x00, 0x00,
242
+ 0x00, 0x00, 0x00, 0x00,
243
+ 0x00, 0x00, 0x00, 0x00,
244
+ 0x00, 0x00, 0x00, 0x00,
245
+ 0x40, 0x00, 0x00, 0x00, // ----end composition matrix----
246
+ (width >>> 8) & 0xFF, // width and height
247
+ (width) & 0xFF,
248
+ 0x00, 0x00,
249
+ (height >>> 8) & 0xFF,
250
+ (height) & 0xFF,
251
+ 0x00, 0x00
252
+ ]));
253
+ }
254
+
255
+ // Media Box
256
+ static mdia(meta) {
257
+ return MP4.box(MP4.types.mdia, MP4.mdhd(meta), MP4.hdlr(meta), MP4.minf(meta));
258
+ }
259
+
260
+ // Media header box
261
+ static mdhd(meta) {
262
+ let timescale = meta.timescale;
263
+ let duration = meta.duration;
264
+ return MP4.box(MP4.types.mdhd, new Uint8Array([
265
+ 0x00, 0x00, 0x00, 0x00, // version(0) + flags
266
+ 0x00, 0x00, 0x00, 0x00, // creation_time
267
+ 0x00, 0x00, 0x00, 0x00, // modification_time
268
+ (timescale >>> 24) & 0xFF, // timescale: 4 bytes
269
+ (timescale >>> 16) & 0xFF,
270
+ (timescale >>> 8) & 0xFF,
271
+ (timescale) & 0xFF,
272
+ (duration >>> 24) & 0xFF, // duration: 4 bytes
273
+ (duration >>> 16) & 0xFF,
274
+ (duration >>> 8) & 0xFF,
275
+ (duration) & 0xFF,
276
+ 0x55, 0xC4, // language: und (undetermined)
277
+ 0x00, 0x00 // pre_defined = 0
278
+ ]));
279
+ }
280
+
281
+ // Media handler reference box
282
+ static hdlr(meta) {
283
+ let data = null;
284
+ if (meta.type === 'audio') {
285
+ data = MP4.constants.HDLR_AUDIO;
286
+ } else {
287
+ data = MP4.constants.HDLR_VIDEO;
288
+ }
289
+ return MP4.box(MP4.types.hdlr, data);
290
+ }
291
+
292
+ // Media infomation box
293
+ static minf(meta) {
294
+ let xmhd = null;
295
+ if (meta.type === 'audio') {
296
+ xmhd = MP4.box(MP4.types.smhd, MP4.constants.SMHD);
297
+ } else {
298
+ xmhd = MP4.box(MP4.types.vmhd, MP4.constants.VMHD);
299
+ }
300
+ return MP4.box(MP4.types.minf, xmhd, MP4.dinf(), MP4.stbl(meta));
301
+ }
302
+
303
+ // Data infomation box
304
+ static dinf() {
305
+ let result = MP4.box(MP4.types.dinf,
306
+ MP4.box(MP4.types.dref, MP4.constants.DREF)
307
+ );
308
+ return result;
309
+ }
310
+
311
+ // Sample table box
312
+ static stbl(meta) {
313
+ let result = MP4.box(MP4.types.stbl, // type: stbl
314
+ MP4.stsd(meta), // Sample Description Table
315
+ MP4.box(MP4.types.stts, MP4.constants.STTS), // Time-To-Sample
316
+ MP4.box(MP4.types.stsc, MP4.constants.STSC), // Sample-To-Chunk
317
+ MP4.box(MP4.types.stsz, MP4.constants.STSZ), // Sample size
318
+ MP4.box(MP4.types.stco, MP4.constants.STCO) // Chunk offset
319
+ );
320
+ return result;
321
+ }
322
+
323
+ // Sample description box
324
+ static stsd(meta) {
325
+ if (meta.type === 'audio') {
326
+ if (meta.codec === 'mp3') {
327
+ return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.mp3(meta));
328
+ } else if (meta.codec === 'ac-3') {
329
+ return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.ac3(meta));
330
+ } else if (meta.codec === 'ec-3') {
331
+ return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.ec3(meta));
332
+ } else if(meta.codec === 'opus') {
333
+ return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.Opus(meta));
334
+ } else if (meta.codec == 'flac') {
335
+ return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.fLaC(meta));
336
+ } else if (meta.codec == 'ipcm') {
337
+ return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.ipcm(meta));
338
+ }
339
+ // else: aac -> mp4a
340
+ return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.mp4a(meta));
341
+ } else if (meta.type === 'video' && meta.codec.startsWith('hvc1')) {
342
+ return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.hvc1(meta));
343
+ } else if (meta.type === 'video' && meta.codec.startsWith('av01')) {
344
+ return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.av01(meta));
345
+ } else {
346
+ return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.avc1(meta));
347
+ }
348
+ }
349
+
350
+ static mp3(meta) {
351
+ let channelCount = meta.channelCount;
352
+ let sampleRate = meta.audioSampleRate;
353
+
354
+ let data = new Uint8Array([
355
+ 0x00, 0x00, 0x00, 0x00, // reserved(4)
356
+ 0x00, 0x00, 0x00, 0x01, // reserved(2) + data_reference_index(2)
357
+ 0x00, 0x00, 0x00, 0x00, // reserved: 2 * 4 bytes
358
+ 0x00, 0x00, 0x00, 0x00,
359
+ 0x00, channelCount, // channelCount(2)
360
+ 0x00, 0x10, // sampleSize(2)
361
+ 0x00, 0x00, 0x00, 0x00, // reserved(4)
362
+ (sampleRate >>> 8) & 0xFF, // Audio sample rate
363
+ (sampleRate) & 0xFF,
364
+ 0x00, 0x00
365
+ ]);
366
+
367
+ return MP4.box(MP4.types['.mp3'], data);
368
+ }
369
+
370
+ static mp4a(meta) {
371
+ let channelCount = meta.channelCount;
372
+ let sampleRate = meta.audioSampleRate;
373
+
374
+ let data = new Uint8Array([
375
+ 0x00, 0x00, 0x00, 0x00, // reserved(4)
376
+ 0x00, 0x00, 0x00, 0x01, // reserved(2) + data_reference_index(2)
377
+ 0x00, 0x00, 0x00, 0x00, // reserved: 2 * 4 bytes
378
+ 0x00, 0x00, 0x00, 0x00,
379
+ 0x00, channelCount, // channelCount(2)
380
+ 0x00, 0x10, // sampleSize(2)
381
+ 0x00, 0x00, 0x00, 0x00, // reserved(4)
382
+ (sampleRate >>> 8) & 0xFF, // Audio sample rate
383
+ (sampleRate) & 0xFF,
384
+ 0x00, 0x00
385
+ ]);
386
+
387
+ return MP4.box(MP4.types.mp4a, data, MP4.esds(meta));
388
+ }
389
+
390
+ static ac3(meta) {
391
+ let channelCount = meta.channelCount;
392
+ let sampleRate = meta.audioSampleRate;
393
+
394
+ let data = new Uint8Array([
395
+ 0x00, 0x00, 0x00, 0x00, // reserved(4)
396
+ 0x00, 0x00, 0x00, 0x01, // reserved(2) + data_reference_index(2)
397
+ 0x00, 0x00, 0x00, 0x00, // reserved: 2 * 4 bytes
398
+ 0x00, 0x00, 0x00, 0x00,
399
+ 0x00, channelCount, // channelCount(2)
400
+ 0x00, 0x10, // sampleSize(2)
401
+ 0x00, 0x00, 0x00, 0x00, // reserved(4)
402
+ (sampleRate >>> 8) & 0xFF, // Audio sample rate
403
+ (sampleRate) & 0xFF,
404
+ 0x00, 0x00
405
+ ]);
406
+
407
+ return MP4.box(MP4.types['ac-3'], data, MP4.box(MP4.types.dac3, new Uint8Array(meta.config)));
408
+ }
409
+
410
+ static ec3(meta) {
411
+ let channelCount = meta.channelCount;
412
+ let sampleRate = meta.audioSampleRate;
413
+
414
+ let data = new Uint8Array([
415
+ 0x00, 0x00, 0x00, 0x00, // reserved(4)
416
+ 0x00, 0x00, 0x00, 0x01, // reserved(2) + data_reference_index(2)
417
+ 0x00, 0x00, 0x00, 0x00, // reserved: 2 * 4 bytes
418
+ 0x00, 0x00, 0x00, 0x00,
419
+ 0x00, channelCount, // channelCount(2)
420
+ 0x00, 0x10, // sampleSize(2)
421
+ 0x00, 0x00, 0x00, 0x00, // reserved(4)
422
+ (sampleRate >>> 8) & 0xFF, // Audio sample rate
423
+ (sampleRate) & 0xFF,
424
+ 0x00, 0x00
425
+ ]);
426
+
427
+ return MP4.box(MP4.types['ec-3'], data, MP4.box(MP4.types.dec3, new Uint8Array(meta.config)));
428
+ }
429
+
430
+ static esds(meta) {
431
+ let config = meta.config || [];
432
+ let configSize = config.length;
433
+ let data = new Uint8Array([
434
+ 0x00, 0x00, 0x00, 0x00, // version 0 + flags
435
+
436
+ 0x03, // descriptor_type
437
+ 0x17 + configSize, // length3
438
+ 0x00, 0x01, // es_id
439
+ 0x00, // stream_priority
440
+
441
+ 0x04, // descriptor_type
442
+ 0x0F + configSize, // length
443
+ 0x40, // codec: mpeg4_audio
444
+ 0x15, // stream_type: Audio
445
+ 0x00, 0x00, 0x00, // buffer_size
446
+ 0x00, 0x00, 0x00, 0x00, // maxBitrate
447
+ 0x00, 0x00, 0x00, 0x00, // avgBitrate
448
+
449
+ 0x05 // descriptor_type
450
+ ].concat([
451
+ configSize
452
+ ]).concat(
453
+ config
454
+ ).concat([
455
+ 0x06, 0x01, 0x02 // GASpecificConfig
456
+ ]));
457
+ return MP4.box(MP4.types.esds, data);
458
+ }
459
+
460
+ static Opus(meta) {
461
+ let channelCount = meta.channelCount;
462
+ let sampleRate = meta.audioSampleRate;
463
+
464
+ let data = new Uint8Array([
465
+ 0x00, 0x00, 0x00, 0x00, // reserved(4)
466
+ 0x00, 0x00, 0x00, 0x01, // reserved(2) + data_reference_index(2)
467
+ 0x00, 0x00, 0x00, 0x00, // reserved: 2 * 4 bytes
468
+ 0x00, 0x00, 0x00, 0x00,
469
+ 0x00, channelCount, // channelCount(2)
470
+ 0x00, 0x10, // sampleSize(2)
471
+ 0x00, 0x00, 0x00, 0x00, // reserved(4)
472
+ (sampleRate >>> 8) & 0xFF, // Audio sample rate
473
+ (sampleRate) & 0xFF,
474
+ 0x00, 0x00
475
+ ]);
476
+
477
+ return MP4.box(MP4.types.Opus, data, MP4.dOps(meta));
478
+ }
479
+
480
+ static dOps(meta) {
481
+ let channelCount = meta.channelCount;
482
+ let channelConfigCode = meta.channelConfigCode;
483
+ let sampleRate = meta.audioSampleRate;
484
+
485
+ if (meta.config) {
486
+ return MP4.box(MP4.types.dOps, meta.config);
487
+ }
488
+
489
+ let mapping = [];
490
+ switch (channelConfigCode) {
491
+ case 0x01:
492
+ case 0x02:
493
+ mapping = [0x0];
494
+ break;
495
+ case 0x00: // dualmono
496
+ mapping = [0xFF, 1, 1, 0, 1];
497
+ break;
498
+ case 0x80: // dualmono
499
+ mapping = [0xFF, 2, 0, 0, 1];
500
+ break;
501
+ case 0x03:
502
+ mapping = [0x01, 2, 1, 0, 2, 1];
503
+ break;
504
+ case 0x04:
505
+ mapping = [0x01, 2, 2, 0, 1, 2, 3];
506
+ break;
507
+ case 0x05:
508
+ mapping = [0x01, 3, 2, 0, 4, 1, 2, 3];
509
+ break;
510
+ case 0x06:
511
+ mapping = [0x01, 4, 2, 0, 4, 1, 2, 3, 5];
512
+ break;
513
+ case 0x07:
514
+ mapping = [0x01, 4, 2, 0, 4, 1, 2, 3, 5, 6];
515
+ break;
516
+ case 0x08:
517
+ mapping = [0x01, 5, 3, 0, 6, 1, 2, 3, 4, 5, 7];
518
+ break;
519
+ case 0x82:
520
+ mapping = [0x01, 1, 2, 0, 1];
521
+ break;
522
+ case 0x83:
523
+ mapping = [0x01, 1, 3, 0, 1, 2];
524
+ break;
525
+ case 0x84:
526
+ mapping = [0x01, 1, 4, 0, 1, 2, 3];
527
+ break;
528
+ case 0x85:
529
+ mapping = [0x01, 1, 5, 0, 1, 2, 3, 4];
530
+ break;
531
+ case 0x86:
532
+ mapping = [0x01, 1, 6, 0, 1, 2, 3, 4, 5];
533
+ break;
534
+ case 0x87:
535
+ mapping = [0x01, 1, 7, 0, 1, 2, 3, 4, 5, 6];
536
+ break;
537
+ case 0x88:
538
+ mapping = [0x01, 1, 8, 0, 1, 2, 3, 4, 5, 6, 7];
539
+ break;
540
+ }
541
+
542
+ let data = new Uint8Array([
543
+ 0x00, // Version (1)
544
+ channelCount, // OutputChannelCount: 2
545
+ 0x00, 0x00, // PreSkip: 2
546
+ (sampleRate >>> 24) & 0xFF, // Audio sample rate: 4
547
+ (sampleRate >>> 17) & 0xFF,
548
+ (sampleRate >>> 8) & 0xFF,
549
+ (sampleRate >>> 0) & 0xFF,
550
+ 0x00, 0x00, // Global Gain : 2
551
+ ... mapping
552
+ ]);
553
+ return MP4.box(MP4.types.dOps, data);
554
+ }
555
+
556
+ static fLaC(meta) {
557
+ let channelCount = meta.channelCount;
558
+ let sampleRate = Math.min(meta.audioSampleRate, 65535);
559
+ let sampleSize = meta.sampleSize;
560
+
561
+ let data = new Uint8Array([
562
+ 0x00, 0x00, 0x00, 0x00, // reserved(4)
563
+ 0x00, 0x00, 0x00, 0x01, // reserved(2) + data_reference_index(2)
564
+ 0x00, 0x00, 0x00, 0x00, // reserved: 2 * 4 bytes
565
+ 0x00, 0x00, 0x00, 0x00,
566
+ 0x00, channelCount, // channelCount(2)
567
+ 0x00, (sampleSize), // sampleSize(2)
568
+ 0x00, 0x00, 0x00, 0x00, // reserved(4)
569
+ (sampleRate >>> 8) & 0xFF, // Audio sample rate
570
+ (sampleRate) & 0xFF,
571
+ 0x00, 0x00
572
+ ]);
573
+
574
+ return MP4.box(MP4.types.fLaC, data, MP4.dfLa(meta));
575
+ }
576
+
577
+ static dfLa(meta) {
578
+ let data = new Uint8Array([
579
+ 0x00, 0x00, 0x00, 0x00, // version, flag
580
+ ... meta.config
581
+ ]);
582
+ return MP4.box(MP4.types.dfLa, data);
583
+ }
584
+
585
+ static ipcm(meta) {
586
+ let channelCount = meta.channelCount;
587
+ let sampleRate = Math.min(meta.audioSampleRate, 65535);
588
+ let sampleSize = meta.sampleSize;
589
+
590
+ let data = new Uint8Array([
591
+ 0x00, 0x00, 0x00, 0x00, // reserved(4)
592
+ 0x00, 0x00, 0x00, 0x01, // reserved(2) + data_reference_index(2)
593
+ 0x00, 0x00, 0x00, 0x00, // reserved: 2 * 4 bytes
594
+ 0x00, 0x00, 0x00, 0x00,
595
+ 0x00, channelCount, // channelCount(2)
596
+ 0x00, (sampleSize), // sampleSize(2)
597
+ 0x00, 0x00, 0x00, 0x00, // reserved(4)
598
+ (sampleRate >>> 8) & 0xFF, // Audio sample rate
599
+ (sampleRate) & 0xFF,
600
+ 0x00, 0x00
601
+ ]);
602
+
603
+ if (meta.channelCount === 1) {
604
+ return MP4.box(MP4.types.ipcm, data, MP4.pcmC(meta));
605
+ } else {
606
+ return MP4.box(MP4.types.ipcm, data, MP4.chnl(meta), MP4.pcmC(meta));
607
+ }
608
+ }
609
+
610
+ static chnl(meta) {
611
+ let data = new Uint8Array([
612
+ 0x00, 0x00, 0x00, 0x00, // version, flag
613
+ 0x01, // Channel Based Layout
614
+ meta.channelCount, // AudioConfiguration
615
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // omittedChannelsMap
616
+ ]);
617
+ return MP4.box(MP4.types.chnl, data);
618
+ }
619
+
620
+ static pcmC(meta) {
621
+ let littleEndian = meta.littleEndian ? 0x01 : 0x00
622
+ let sampleSize = meta.sampleSize;
623
+ let data = new Uint8Array([
624
+ 0x00, 0x00, 0x00, 0x00, // version, flag
625
+ littleEndian, sampleSize
626
+ ]);
627
+ return MP4.box(MP4.types.pcmC, data);
628
+ }
629
+
630
+ static avc1(meta) {
631
+ let avcc = meta.avcc;
632
+ let width = meta.codecWidth, height = meta.codecHeight;
633
+
634
+ let data = new Uint8Array([
635
+ 0x00, 0x00, 0x00, 0x00, // reserved(4)
636
+ 0x00, 0x00, 0x00, 0x01, // reserved(2) + data_reference_index(2)
637
+ 0x00, 0x00, 0x00, 0x00, // pre_defined(2) + reserved(2)
638
+ 0x00, 0x00, 0x00, 0x00, // pre_defined: 3 * 4 bytes
639
+ 0x00, 0x00, 0x00, 0x00,
640
+ 0x00, 0x00, 0x00, 0x00,
641
+ (width >>> 8) & 0xFF, // width: 2 bytes
642
+ (width) & 0xFF,
643
+ (height >>> 8) & 0xFF, // height: 2 bytes
644
+ (height) & 0xFF,
645
+ 0x00, 0x48, 0x00, 0x00, // horizresolution: 4 bytes
646
+ 0x00, 0x48, 0x00, 0x00, // vertresolution: 4 bytes
647
+ 0x00, 0x00, 0x00, 0x00, // reserved: 4 bytes
648
+ 0x00, 0x01, // frame_count
649
+ 0x0A, // strlen
650
+ 0x78, 0x71, 0x71, 0x2F, // compressorname: 32 bytes
651
+ 0x66, 0x6C, 0x76, 0x2E,
652
+ 0x6A, 0x73, 0x00, 0x00,
653
+ 0x00, 0x00, 0x00, 0x00,
654
+ 0x00, 0x00, 0x00, 0x00,
655
+ 0x00, 0x00, 0x00, 0x00,
656
+ 0x00, 0x00, 0x00, 0x00,
657
+ 0x00, 0x00, 0x00,
658
+ 0x00, 0x18, // depth
659
+ 0xFF, 0xFF // pre_defined = -1
660
+ ]);
661
+ return MP4.box(MP4.types.avc1, data, MP4.box(MP4.types.avcC, avcc));
662
+ }
663
+
664
+ static hvc1(meta) {
665
+ let hvcc = meta.hvcc;
666
+ let width = meta.codecWidth, height = meta.codecHeight;
667
+
668
+ let data = new Uint8Array([
669
+ 0x00, 0x00, 0x00, 0x00, // reserved(4)
670
+ 0x00, 0x00, 0x00, 0x01, // reserved(2) + data_reference_index(2)
671
+ 0x00, 0x00, 0x00, 0x00, // pre_defined(2) + reserved(2)
672
+ 0x00, 0x00, 0x00, 0x00, // pre_defined: 3 * 4 bytes
673
+ 0x00, 0x00, 0x00, 0x00,
674
+ 0x00, 0x00, 0x00, 0x00,
675
+ (width >>> 8) & 0xFF, // width: 2 bytes
676
+ (width) & 0xFF,
677
+ (height >>> 8) & 0xFF, // height: 2 bytes
678
+ (height) & 0xFF,
679
+ 0x00, 0x48, 0x00, 0x00, // horizresolution: 4 bytes
680
+ 0x00, 0x48, 0x00, 0x00, // vertresolution: 4 bytes
681
+ 0x00, 0x00, 0x00, 0x00, // reserved: 4 bytes
682
+ 0x00, 0x01, // frame_count
683
+ 0x0A, // strlen
684
+ 0x78, 0x71, 0x71, 0x2F, // compressorname: 32 bytes
685
+ 0x66, 0x6C, 0x76, 0x2E,
686
+ 0x6A, 0x73, 0x00, 0x00,
687
+ 0x00, 0x00, 0x00, 0x00,
688
+ 0x00, 0x00, 0x00, 0x00,
689
+ 0x00, 0x00, 0x00, 0x00,
690
+ 0x00, 0x00, 0x00, 0x00,
691
+ 0x00, 0x00, 0x00,
692
+ 0x00, 0x18, // depth
693
+ 0xFF, 0xFF // pre_defined = -1
694
+ ]);
695
+ return MP4.box(MP4.types.hvc1, data, MP4.box(MP4.types.hvcC, hvcc));
696
+ }
697
+
698
+ static av01(meta) {
699
+ let av1c = meta.av1c;
700
+ let width = meta.codecWidth || 192, height = meta.codecHeight || 108;
701
+
702
+ let data = new Uint8Array([
703
+ 0x00, 0x00, 0x00, 0x00, // reserved(4)
704
+ 0x00, 0x00, 0x00, 0x01, // reserved(2) + data_reference_index(2)
705
+ 0x00, 0x00, 0x00, 0x00, // pre_defined(2) + reserved(2)
706
+ 0x00, 0x00, 0x00, 0x00, // pre_defined: 3 * 4 bytes
707
+ 0x00, 0x00, 0x00, 0x00,
708
+ 0x00, 0x00, 0x00, 0x00,
709
+ (width >>> 8) & 0xFF, // width: 2 bytes
710
+ (width) & 0xFF,
711
+ (height >>> 8) & 0xFF, // height: 2 bytes
712
+ (height) & 0xFF,
713
+ 0x00, 0x48, 0x00, 0x00, // horizresolution: 4 bytes
714
+ 0x00, 0x48, 0x00, 0x00, // vertresolution: 4 bytes
715
+ 0x00, 0x00, 0x00, 0x00, // reserved: 4 bytes
716
+ 0x00, 0x01, // frame_count
717
+ 0x0A, // strlen
718
+ 0x78, 0x71, 0x71, 0x2F, // compressorname: 32 bytes
719
+ 0x66, 0x6C, 0x76, 0x2E,
720
+ 0x6A, 0x73, 0x00, 0x00,
721
+ 0x00, 0x00, 0x00, 0x00,
722
+ 0x00, 0x00, 0x00, 0x00,
723
+ 0x00, 0x00, 0x00, 0x00,
724
+ 0x00, 0x00, 0x00, 0x00,
725
+ 0x00, 0x00, 0x00,
726
+ 0x00, 0x18, // depth
727
+ 0xFF, 0xFF // pre_defined = -1
728
+ ]);
729
+ return MP4.box(MP4.types.av01, data, MP4.box(MP4.types.av1C, av1c));
730
+ }
731
+
732
+ // Movie Extends box
733
+ static mvex(meta) {
734
+ return MP4.box(MP4.types.mvex, MP4.trex(meta));
735
+ }
736
+
737
+ // Track Extends box
738
+ static trex(meta) {
739
+ let trackId = meta.id;
740
+ let data = new Uint8Array([
741
+ 0x00, 0x00, 0x00, 0x00, // version(0) + flags
742
+ (trackId >>> 24) & 0xFF, // track_ID
743
+ (trackId >>> 16) & 0xFF,
744
+ (trackId >>> 8) & 0xFF,
745
+ (trackId) & 0xFF,
746
+ 0x00, 0x00, 0x00, 0x01, // default_sample_description_index
747
+ 0x00, 0x00, 0x00, 0x00, // default_sample_duration
748
+ 0x00, 0x00, 0x00, 0x00, // default_sample_size
749
+ 0x00, 0x01, 0x00, 0x01 // default_sample_flags
750
+ ]);
751
+ return MP4.box(MP4.types.trex, data);
752
+ }
753
+
754
+ // Movie fragment box
755
+ static moof(track, baseMediaDecodeTime) {
756
+ return MP4.box(MP4.types.moof, MP4.mfhd(track.sequenceNumber), MP4.traf(track, baseMediaDecodeTime));
757
+ }
758
+
759
+ static mfhd(sequenceNumber) {
760
+ let data = new Uint8Array([
761
+ 0x00, 0x00, 0x00, 0x00,
762
+ (sequenceNumber >>> 24) & 0xFF, // sequence_number: int32
763
+ (sequenceNumber >>> 16) & 0xFF,
764
+ (sequenceNumber >>> 8) & 0xFF,
765
+ (sequenceNumber) & 0xFF
766
+ ]);
767
+ return MP4.box(MP4.types.mfhd, data);
768
+ }
769
+
770
+ // Track fragment box
771
+ static traf(track, baseMediaDecodeTime) {
772
+ let trackId = track.id;
773
+
774
+ // Track fragment header box
775
+ let tfhd = MP4.box(MP4.types.tfhd, new Uint8Array([
776
+ 0x00, 0x00, 0x00, 0x00, // version(0) & flags
777
+ (trackId >>> 24) & 0xFF, // track_ID
778
+ (trackId >>> 16) & 0xFF,
779
+ (trackId >>> 8) & 0xFF,
780
+ (trackId) & 0xFF
781
+ ]));
782
+ // Track Fragment Decode Time
783
+ let tfdt = MP4.box(MP4.types.tfdt, new Uint8Array([
784
+ 0x00, 0x00, 0x00, 0x00, // version(0) & flags
785
+ (baseMediaDecodeTime >>> 24) & 0xFF, // baseMediaDecodeTime: int32
786
+ (baseMediaDecodeTime >>> 16) & 0xFF,
787
+ (baseMediaDecodeTime >>> 8) & 0xFF,
788
+ (baseMediaDecodeTime) & 0xFF
789
+ ]));
790
+ let sdtp = MP4.sdtp(track);
791
+ let trun = MP4.trun(track, sdtp.byteLength + 16 + 16 + 8 + 16 + 8 + 8);
792
+
793
+ return MP4.box(MP4.types.traf, tfhd, tfdt, trun, sdtp);
794
+ }
795
+
796
+ // Sample Dependency Type box
797
+ static sdtp(track) {
798
+ let samples = track.samples || [];
799
+ let sampleCount = samples.length;
800
+ let data = new Uint8Array(4 + sampleCount);
801
+ // 0~4 bytes: version(0) & flags
802
+ for (let i = 0; i < sampleCount; i++) {
803
+ let flags = samples[i].flags;
804
+ data[i + 4] = (flags.isLeading << 6) // is_leading: 2 (bit)
805
+ | (flags.dependsOn << 4) // sample_depends_on
806
+ | (flags.isDependedOn << 2) // sample_is_depended_on
807
+ | (flags.hasRedundancy); // sample_has_redundancy
808
+ }
809
+ return MP4.box(MP4.types.sdtp, data);
810
+ }
811
+
812
+ // Track fragment run box
813
+ static trun(track, offset) {
814
+ let samples = track.samples || [];
815
+ let sampleCount = samples.length;
816
+ let dataSize = 12 + 16 * sampleCount;
817
+ let data = new Uint8Array(dataSize);
818
+ offset += 8 + dataSize;
819
+
820
+ data.set([
821
+ 0x00, 0x00, 0x0F, 0x01, // version(0) & flags
822
+ (sampleCount >>> 24) & 0xFF, // sample_count
823
+ (sampleCount >>> 16) & 0xFF,
824
+ (sampleCount >>> 8) & 0xFF,
825
+ (sampleCount) & 0xFF,
826
+ (offset >>> 24) & 0xFF, // data_offset
827
+ (offset >>> 16) & 0xFF,
828
+ (offset >>> 8) & 0xFF,
829
+ (offset) & 0xFF
830
+ ], 0);
831
+
832
+ for (let i = 0; i < sampleCount; i++) {
833
+ let duration = samples[i].duration;
834
+ let size = samples[i].size;
835
+ let flags = samples[i].flags;
836
+ let cts = samples[i].cts;
837
+ data.set([
838
+ (duration >>> 24) & 0xFF, // sample_duration
839
+ (duration >>> 16) & 0xFF,
840
+ (duration >>> 8) & 0xFF,
841
+ (duration) & 0xFF,
842
+ (size >>> 24) & 0xFF, // sample_size
843
+ (size >>> 16) & 0xFF,
844
+ (size >>> 8) & 0xFF,
845
+ (size) & 0xFF,
846
+ (flags.isLeading << 2) | flags.dependsOn, // sample_flags
847
+ (flags.isDependedOn << 6) | (flags.hasRedundancy << 4) | flags.isNonSync,
848
+ 0x00, 0x00, // sample_degradation_priority
849
+ (cts >>> 24) & 0xFF, // sample_composition_time_offset
850
+ (cts >>> 16) & 0xFF,
851
+ (cts >>> 8) & 0xFF,
852
+ (cts) & 0xFF
853
+ ], 12 + 16 * i);
854
+ }
855
+ return MP4.box(MP4.types.trun, data);
856
+ }
857
+
858
+ static mdat(data) {
859
+ return MP4.box(MP4.types.mdat, data);
860
+ }
861
+
862
+ }
863
+
864
+ MP4.init();
865
+
866
+ export default MP4;