@svta/cml-iso-bmff 1.0.0-alpha.1 → 1.0.0-alpha.3
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.
- package/README.md +2 -2
- package/dist/index.d.ts +253 -140
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1061 -928
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
import { UTF_8, decodeText, encodeText } from "@svta/cml-utils";
|
|
2
2
|
|
|
3
|
+
//#region src/utils/createWriterConfig.ts
|
|
4
|
+
function createWriterConfig(config) {
|
|
5
|
+
return { writers: config?.writers ?? {} };
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
//#endregion
|
|
3
9
|
//#region src/utils/CONTAINERS.ts
|
|
10
|
+
/**
|
|
11
|
+
* List of container box types
|
|
12
|
+
*
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
4
15
|
const CONTAINERS = [
|
|
5
16
|
"dinf",
|
|
6
17
|
"edts",
|
|
7
|
-
"enca",
|
|
8
|
-
"encv",
|
|
9
18
|
"grpl",
|
|
10
19
|
"mdia",
|
|
11
20
|
"meco",
|
|
12
|
-
"meta",
|
|
13
21
|
"mfra",
|
|
14
22
|
"minf",
|
|
15
23
|
"moof",
|
|
16
24
|
"moov",
|
|
17
25
|
"mvex",
|
|
18
|
-
"prsl",
|
|
19
26
|
"schi",
|
|
20
27
|
"sinf",
|
|
21
28
|
"stbl",
|
|
@@ -42,6 +49,15 @@ function isContainer(box) {
|
|
|
42
49
|
return "boxes" in box || CONTAINERS.includes(box.type);
|
|
43
50
|
}
|
|
44
51
|
|
|
52
|
+
//#endregion
|
|
53
|
+
//#region src/fields/TEMPLATE.ts
|
|
54
|
+
/**
|
|
55
|
+
* The template field type
|
|
56
|
+
*
|
|
57
|
+
* @public
|
|
58
|
+
*/
|
|
59
|
+
const TEMPLATE = "template";
|
|
60
|
+
|
|
45
61
|
//#endregion
|
|
46
62
|
//#region src/fields/UINT.ts
|
|
47
63
|
/**
|
|
@@ -130,12 +146,15 @@ var IsoBoxWriteView = class {
|
|
|
130
146
|
this.writeUint(0, 1);
|
|
131
147
|
};
|
|
132
148
|
this.writeBytes = (data) => {
|
|
133
|
-
|
|
134
|
-
|
|
149
|
+
if (!Array.isArray(data)) data = [data];
|
|
150
|
+
for (const bytes of data) {
|
|
151
|
+
new Uint8Array(this.dataView.buffer).set(bytes, this.cursor);
|
|
152
|
+
this.cursor += bytes.length;
|
|
153
|
+
}
|
|
135
154
|
};
|
|
136
|
-
this.writeArray = (data, type$1, size$1) => {
|
|
137
|
-
const write = type$1 === UINT ? this.writeUint : this.writeInt;
|
|
138
|
-
for (
|
|
155
|
+
this.writeArray = (data, type$1, size$1, length) => {
|
|
156
|
+
const write = type$1 === UINT ? this.writeUint : type$1 === TEMPLATE ? this.writeTemplate : this.writeInt;
|
|
157
|
+
for (let i = 0; i < length; i++) write(data[i] ?? 0, size$1);
|
|
139
158
|
};
|
|
140
159
|
this.writeTemplate = (value, size$1) => {
|
|
141
160
|
const shift = size$1 === 4 ? 16 : 8;
|
|
@@ -193,7 +212,43 @@ var IsoBoxWriteView = class {
|
|
|
193
212
|
};
|
|
194
213
|
|
|
195
214
|
//#endregion
|
|
196
|
-
//#region src/
|
|
215
|
+
//#region src/utils/writeBoxes.ts
|
|
216
|
+
/**
|
|
217
|
+
* Write boxes to an array of Uint8Arrays.
|
|
218
|
+
*
|
|
219
|
+
* @param boxes - The boxes to write
|
|
220
|
+
* @param config - The configuration for the writer
|
|
221
|
+
*
|
|
222
|
+
* @returns The written boxes
|
|
223
|
+
*
|
|
224
|
+
* @internal
|
|
225
|
+
*/
|
|
226
|
+
function writeBoxes(boxes, config) {
|
|
227
|
+
return Array.from(boxes, (box) => writeBox(box, config));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
//#endregion
|
|
231
|
+
//#region src/utils/writeChildBoxes.ts
|
|
232
|
+
/**
|
|
233
|
+
* Write child boxes
|
|
234
|
+
*
|
|
235
|
+
* @param boxes - The boxes to write
|
|
236
|
+
* @param config - The configuration for the writer
|
|
237
|
+
*
|
|
238
|
+
* @returns The byte arrays and total size of the written boxes
|
|
239
|
+
*
|
|
240
|
+
* @internal
|
|
241
|
+
*/
|
|
242
|
+
function writeChildBoxes(boxes, config) {
|
|
243
|
+
const bytes = writeBoxes(boxes, config);
|
|
244
|
+
return {
|
|
245
|
+
bytes,
|
|
246
|
+
size: bytes.reduce((size, byte) => size + byte.byteLength, 0)
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
//#endregion
|
|
251
|
+
//#region src/utils/writeContainerBox.ts
|
|
197
252
|
/**
|
|
198
253
|
* Write a ContainerBox to an IsoBmffWriter.
|
|
199
254
|
*
|
|
@@ -203,43 +258,37 @@ var IsoBoxWriteView = class {
|
|
|
203
258
|
* @param box - The ContainerBox to write
|
|
204
259
|
*
|
|
205
260
|
* @returns An IsoBmffWriter containing the encoded box
|
|
261
|
+
*
|
|
262
|
+
* @internal
|
|
206
263
|
*/
|
|
207
|
-
function writeContainerBox(box,
|
|
208
|
-
const children = [];
|
|
264
|
+
function writeContainerBox(box, config) {
|
|
209
265
|
const headerSize = 8;
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
const view = writeIsoBox(childBox, writers);
|
|
213
|
-
childrenSize += view.byteLength;
|
|
214
|
-
children.push(view);
|
|
215
|
-
}
|
|
216
|
-
const totalSize = headerSize + childrenSize;
|
|
266
|
+
const { bytes, size } = writeChildBoxes(box.boxes, config);
|
|
267
|
+
const totalSize = headerSize + size;
|
|
217
268
|
const writer = new IsoBoxWriteView(box.type, totalSize);
|
|
218
|
-
|
|
269
|
+
writer.writeBytes(bytes);
|
|
219
270
|
return writer;
|
|
220
271
|
}
|
|
221
272
|
|
|
222
273
|
//#endregion
|
|
223
|
-
//#region src/
|
|
274
|
+
//#region src/utils/writeBox.ts
|
|
224
275
|
/**
|
|
225
|
-
* Write
|
|
276
|
+
* Write a box to a Uint8Array.
|
|
226
277
|
*
|
|
227
278
|
* @param box - The box to write
|
|
228
279
|
* @param writers - The writers to use
|
|
229
280
|
* @returns The written box
|
|
230
281
|
*
|
|
231
|
-
* @
|
|
282
|
+
* @internal
|
|
232
283
|
*/
|
|
233
|
-
function
|
|
284
|
+
function writeBox(box, config) {
|
|
234
285
|
let view = null;
|
|
235
286
|
if ("type" in box) {
|
|
236
287
|
const { type } = box;
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
else if ("view" in box) view = box.view;
|
|
242
|
-
}
|
|
288
|
+
const writer = config.writers?.[type];
|
|
289
|
+
if (writer) view = writer(box, config);
|
|
290
|
+
else if (isContainer(box)) view = writeContainerBox(box, config);
|
|
291
|
+
else if ("view" in box) view = box.view;
|
|
243
292
|
if (!view) throw new Error(`No writer found for box type: ${type}`);
|
|
244
293
|
}
|
|
245
294
|
if ("buffer" in box) view = box;
|
|
@@ -247,6 +296,22 @@ function writeIsoBox(box, writers) {
|
|
|
247
296
|
return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
|
|
248
297
|
}
|
|
249
298
|
|
|
299
|
+
//#endregion
|
|
300
|
+
//#region src/writeIsoBox.ts
|
|
301
|
+
/**
|
|
302
|
+
* Write an ISO box to a Uint8Array.
|
|
303
|
+
*
|
|
304
|
+
* @param box - The box to write
|
|
305
|
+
* @param config - The configuration for the writer
|
|
306
|
+
*
|
|
307
|
+
* @returns The written box
|
|
308
|
+
*
|
|
309
|
+
* @public
|
|
310
|
+
*/
|
|
311
|
+
function writeIsoBox(box, config) {
|
|
312
|
+
return writeBox(box, createWriterConfig(config));
|
|
313
|
+
}
|
|
314
|
+
|
|
250
315
|
//#endregion
|
|
251
316
|
//#region src/IsoBoxReadableStream.ts
|
|
252
317
|
/**
|
|
@@ -263,13 +328,13 @@ var IsoBoxReadableStream = class extends ReadableStream {
|
|
|
263
328
|
*/
|
|
264
329
|
constructor(boxes, config = {}) {
|
|
265
330
|
const iterator = boxes[Symbol.iterator]();
|
|
266
|
-
const
|
|
331
|
+
const cfg = createWriterConfig(config);
|
|
267
332
|
function pull(controller) {
|
|
268
333
|
const desiredSize = controller.desiredSize ?? 0;
|
|
269
334
|
for (let i = 0; i < desiredSize; i++) {
|
|
270
335
|
const { value, done } = iterator.next();
|
|
271
336
|
if (done) controller.close();
|
|
272
|
-
else controller.enqueue(writeIsoBox(value,
|
|
337
|
+
else controller.enqueue(writeIsoBox(value, cfg));
|
|
273
338
|
}
|
|
274
339
|
}
|
|
275
340
|
super({
|
|
@@ -299,260 +364,480 @@ function createIsoBoxReadableStream(boxes, config = {}) {
|
|
|
299
364
|
}
|
|
300
365
|
|
|
301
366
|
//#endregion
|
|
302
|
-
//#region src/
|
|
367
|
+
//#region src/fields/DATA.ts
|
|
303
368
|
/**
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
* @param view - The IsoView to read data from
|
|
307
|
-
*
|
|
308
|
-
* @returns A parsed AudioRenderingIndicationBox
|
|
369
|
+
* The data field type
|
|
309
370
|
*
|
|
310
371
|
* @public
|
|
311
372
|
*/
|
|
312
|
-
|
|
313
|
-
return {
|
|
314
|
-
type: "ardi",
|
|
315
|
-
...view.readFullBox(),
|
|
316
|
-
audioRenderingIndication: view.readUint(1)
|
|
317
|
-
};
|
|
318
|
-
}
|
|
373
|
+
const DATA = "data";
|
|
319
374
|
|
|
320
375
|
//#endregion
|
|
321
|
-
//#region src/
|
|
376
|
+
//#region src/fields/INT.ts
|
|
322
377
|
/**
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
* @param view - The IsoView to read data from
|
|
326
|
-
*
|
|
327
|
-
* @returns A parsed VisualSampleEntryBox
|
|
378
|
+
* The integer field type
|
|
328
379
|
*
|
|
329
380
|
* @public
|
|
330
381
|
*/
|
|
331
|
-
|
|
332
|
-
const { readArray, readUint: readUint$1, readInt: readInt$1, readTemplate: readTemplate$1, readData: readData$1 } = view;
|
|
333
|
-
return {
|
|
334
|
-
type: "avc1",
|
|
335
|
-
reserved1: readArray(UINT, 1, 6),
|
|
336
|
-
dataReferenceIndex: readUint$1(2),
|
|
337
|
-
preDefined1: readUint$1(2),
|
|
338
|
-
reserved2: readUint$1(2),
|
|
339
|
-
preDefined2: readArray(UINT, 4, 3),
|
|
340
|
-
width: readUint$1(2),
|
|
341
|
-
height: readUint$1(2),
|
|
342
|
-
horizresolution: readTemplate$1(4),
|
|
343
|
-
vertresolution: readTemplate$1(4),
|
|
344
|
-
reserved3: readUint$1(4),
|
|
345
|
-
frameCount: readUint$1(2),
|
|
346
|
-
compressorName: readArray(UINT, 1, 32),
|
|
347
|
-
depth: readUint$1(2),
|
|
348
|
-
preDefined3: readInt$1(2),
|
|
349
|
-
config: readData$1(-1)
|
|
350
|
-
};
|
|
351
|
-
}
|
|
382
|
+
const INT = "int";
|
|
352
383
|
|
|
353
384
|
//#endregion
|
|
354
|
-
//#region src/
|
|
385
|
+
//#region src/fields/STRING.ts
|
|
355
386
|
/**
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
* @param view - The IsoView to read data from
|
|
359
|
-
*
|
|
360
|
-
* @returns A parsed VisualSampleEntryBox
|
|
387
|
+
* The string field type
|
|
361
388
|
*
|
|
362
389
|
* @public
|
|
363
390
|
*/
|
|
364
|
-
|
|
365
|
-
return {
|
|
366
|
-
...readAvc1(view),
|
|
367
|
-
type: "avc2"
|
|
368
|
-
};
|
|
369
|
-
}
|
|
391
|
+
const STRING = "string";
|
|
370
392
|
|
|
371
393
|
//#endregion
|
|
372
|
-
//#region src/
|
|
394
|
+
//#region src/fields/UTF8.ts
|
|
373
395
|
/**
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
* @param view - The IsoView to read data from
|
|
377
|
-
*
|
|
378
|
-
* @returns A parsed VisualSampleEntryBox
|
|
396
|
+
* The UTF8 field type
|
|
379
397
|
*
|
|
380
398
|
* @public
|
|
381
399
|
*/
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
400
|
+
const UTF8 = "utf8";
|
|
401
|
+
|
|
402
|
+
//#endregion
|
|
403
|
+
//#region src/utils/readData.ts
|
|
404
|
+
function readData(dataView, offset, size) {
|
|
405
|
+
const length = size > 0 ? size : dataView.byteLength - (offset - dataView.byteOffset);
|
|
406
|
+
return new Uint8Array(dataView.buffer, offset, Math.max(length, 0));
|
|
387
407
|
}
|
|
388
408
|
|
|
389
409
|
//#endregion
|
|
390
|
-
//#region src/
|
|
410
|
+
//#region src/utils/readInt.ts
|
|
411
|
+
function readInt(dataView, offset, size) {
|
|
412
|
+
let result = NaN;
|
|
413
|
+
const cursor = offset - dataView.byteOffset;
|
|
414
|
+
switch (size) {
|
|
415
|
+
case 1:
|
|
416
|
+
result = dataView.getInt8(cursor);
|
|
417
|
+
break;
|
|
418
|
+
case 2:
|
|
419
|
+
result = dataView.getInt16(cursor);
|
|
420
|
+
break;
|
|
421
|
+
case 4:
|
|
422
|
+
result = dataView.getInt32(cursor);
|
|
423
|
+
break;
|
|
424
|
+
case 8:
|
|
425
|
+
const s1 = dataView.getInt32(cursor);
|
|
426
|
+
const s2 = dataView.getInt32(cursor + 4);
|
|
427
|
+
result = s1 * Math.pow(2, 32) + s2;
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
return result;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
//#endregion
|
|
434
|
+
//#region src/utils/readUint.ts
|
|
435
|
+
function readUint(dataView, offset, size) {
|
|
436
|
+
const cursor = offset - dataView.byteOffset;
|
|
437
|
+
let value = NaN;
|
|
438
|
+
let s1;
|
|
439
|
+
let s2;
|
|
440
|
+
switch (size) {
|
|
441
|
+
case 1:
|
|
442
|
+
value = dataView.getUint8(cursor);
|
|
443
|
+
break;
|
|
444
|
+
case 2:
|
|
445
|
+
value = dataView.getUint16(cursor);
|
|
446
|
+
break;
|
|
447
|
+
case 3:
|
|
448
|
+
s1 = dataView.getUint16(cursor);
|
|
449
|
+
s2 = dataView.getUint8(cursor + 2);
|
|
450
|
+
value = (s1 << 8) + s2;
|
|
451
|
+
break;
|
|
452
|
+
case 4:
|
|
453
|
+
value = dataView.getUint32(cursor);
|
|
454
|
+
break;
|
|
455
|
+
case 8:
|
|
456
|
+
s1 = dataView.getUint32(cursor);
|
|
457
|
+
s2 = dataView.getUint32(cursor + 4);
|
|
458
|
+
value = s1 * Math.pow(2, 32) + s2;
|
|
459
|
+
break;
|
|
460
|
+
}
|
|
461
|
+
return value;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
//#endregion
|
|
465
|
+
//#region src/utils/readString.ts
|
|
466
|
+
function readString(dataView, offset, length) {
|
|
467
|
+
let str = "";
|
|
468
|
+
for (let c = 0; c < length; c++) {
|
|
469
|
+
const char = readUint(dataView, offset + c, 1);
|
|
470
|
+
str += String.fromCharCode(char);
|
|
471
|
+
}
|
|
472
|
+
return str;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
//#endregion
|
|
476
|
+
//#region src/utils/readTemplate.ts
|
|
477
|
+
function readTemplate(dataView, offset, size) {
|
|
478
|
+
const half = size / 2;
|
|
479
|
+
return readUint(dataView, offset, half) + readUint(dataView, offset + half, half) / Math.pow(2, half);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
//#endregion
|
|
483
|
+
//#region src/utils/readTerminatedString.ts
|
|
484
|
+
function readTerminatedString(dataView, offset) {
|
|
485
|
+
let str = "";
|
|
486
|
+
let cursor = offset;
|
|
487
|
+
while (cursor - dataView.byteOffset < dataView.byteLength) {
|
|
488
|
+
const char = readUint(dataView, cursor, 1);
|
|
489
|
+
if (char === 0) break;
|
|
490
|
+
str += String.fromCharCode(char);
|
|
491
|
+
cursor++;
|
|
492
|
+
}
|
|
493
|
+
return str;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
//#endregion
|
|
497
|
+
//#region src/utils/readUtf8String.ts
|
|
391
498
|
/**
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
* @param view - The IsoView to read data from
|
|
499
|
+
* Reads a UTF-8 string from a data view.
|
|
395
500
|
*
|
|
396
|
-
* @
|
|
501
|
+
* @param dataView - The data view to read from.
|
|
502
|
+
* @param offset - The offset to start reading from.
|
|
503
|
+
* @returns The UTF-8 string.
|
|
397
504
|
*
|
|
398
|
-
* @
|
|
505
|
+
* @internal
|
|
399
506
|
*/
|
|
400
|
-
function
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
type: "avc4"
|
|
404
|
-
};
|
|
507
|
+
function readUtf8String(dataView, offset) {
|
|
508
|
+
const length = dataView.byteLength - (offset - dataView.byteOffset);
|
|
509
|
+
return length > 0 ? decodeText(new DataView(dataView.buffer, offset, length), { encoding: UTF_8 }) : "";
|
|
405
510
|
}
|
|
406
511
|
|
|
407
512
|
//#endregion
|
|
408
|
-
//#region src/
|
|
513
|
+
//#region src/utils/readUtf8TerminatedString.ts
|
|
409
514
|
/**
|
|
410
|
-
*
|
|
411
|
-
*
|
|
412
|
-
* @param view - The IsoView to read data from
|
|
515
|
+
* Reads a UTF-8 terminated string from a data view.
|
|
413
516
|
*
|
|
414
|
-
* @
|
|
517
|
+
* @param dataView - The data view to read from.
|
|
518
|
+
* @param offset - The offset to start reading from.
|
|
519
|
+
* @returns The UTF-8 terminated string.
|
|
415
520
|
*
|
|
416
|
-
* @
|
|
521
|
+
* @internal
|
|
417
522
|
*/
|
|
418
|
-
function
|
|
419
|
-
const
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
sampleCount: view.readUint(4),
|
|
429
|
-
sampleOffset: read(4)
|
|
430
|
-
}))
|
|
431
|
-
};
|
|
523
|
+
function readUtf8TerminatedString(dataView, offset) {
|
|
524
|
+
const length = dataView.byteLength - (offset - dataView.byteOffset);
|
|
525
|
+
let data = "";
|
|
526
|
+
if (length > 0) {
|
|
527
|
+
const view = new DataView(dataView.buffer, offset, length);
|
|
528
|
+
let l = 0;
|
|
529
|
+
for (; l < length; l++) if (view.getUint8(l) === 0) break;
|
|
530
|
+
data = decodeText(new DataView(dataView.buffer, offset, l), { encoding: UTF_8 });
|
|
531
|
+
}
|
|
532
|
+
return data;
|
|
432
533
|
}
|
|
433
534
|
|
|
434
535
|
//#endregion
|
|
435
|
-
//#region src/
|
|
536
|
+
//#region src/IsoBoxReadView.ts
|
|
436
537
|
/**
|
|
437
|
-
*
|
|
438
|
-
*
|
|
439
|
-
* @param view - The IsoView to read data from
|
|
440
|
-
*
|
|
441
|
-
* @returns A parsed DataReferenceBox
|
|
538
|
+
* ISO BMFF data view. Similar to DataView, but with additional methods for reading ISO BMFF data.
|
|
539
|
+
* It implements the iterator protocol, so it can be used in a for...of loop.
|
|
442
540
|
*
|
|
443
541
|
* @public
|
|
444
542
|
*/
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
543
|
+
var IsoBoxReadView = class IsoBoxReadView {
|
|
544
|
+
/**
|
|
545
|
+
* Creates a new IsoView instance. Similar to DataView, but with additional
|
|
546
|
+
* methods for reading ISO BMFF data. It implements the iterator protocol,
|
|
547
|
+
* so it can be used in a for...of loop.
|
|
548
|
+
*
|
|
549
|
+
* @param raw - The raw data to view.
|
|
550
|
+
* @param config - The configuration for the IsoView.
|
|
551
|
+
*/
|
|
552
|
+
constructor(raw, config) {
|
|
553
|
+
this.truncated = false;
|
|
554
|
+
this.slice = (offset, size) => {
|
|
555
|
+
const isoView = new IsoBoxReadView(new DataView(this.dataView.buffer, offset, size), this.config);
|
|
556
|
+
const headerSize = this.offset - offset;
|
|
557
|
+
const bodySize = size - headerSize;
|
|
558
|
+
this.offset += bodySize;
|
|
559
|
+
isoView.jump(headerSize);
|
|
560
|
+
return isoView;
|
|
561
|
+
};
|
|
562
|
+
this.read = (type, size = 0) => {
|
|
563
|
+
const { dataView, offset } = this;
|
|
564
|
+
let result;
|
|
565
|
+
let cursor = size;
|
|
566
|
+
switch (type) {
|
|
567
|
+
case UINT:
|
|
568
|
+
result = readUint(dataView, offset, size);
|
|
569
|
+
break;
|
|
570
|
+
case INT:
|
|
571
|
+
result = readInt(dataView, offset, size);
|
|
572
|
+
break;
|
|
573
|
+
case TEMPLATE:
|
|
574
|
+
result = readTemplate(dataView, offset, size);
|
|
575
|
+
break;
|
|
576
|
+
case STRING:
|
|
577
|
+
if (size === -1) {
|
|
578
|
+
result = readTerminatedString(dataView, offset);
|
|
579
|
+
cursor = result.length + 1;
|
|
580
|
+
} else result = readString(dataView, offset, size);
|
|
581
|
+
break;
|
|
582
|
+
case DATA:
|
|
583
|
+
result = readData(dataView, offset, size);
|
|
584
|
+
cursor = result.length;
|
|
585
|
+
break;
|
|
586
|
+
case UTF8:
|
|
587
|
+
if (size === -1) {
|
|
588
|
+
result = readUtf8TerminatedString(dataView, offset);
|
|
589
|
+
cursor = result.length + 1;
|
|
590
|
+
} else result = readUtf8String(dataView, offset);
|
|
591
|
+
break;
|
|
592
|
+
default: result = -1;
|
|
593
|
+
}
|
|
594
|
+
this.offset += cursor;
|
|
595
|
+
return result;
|
|
596
|
+
};
|
|
597
|
+
this.readUint = (size) => {
|
|
598
|
+
return this.read(UINT, size);
|
|
599
|
+
};
|
|
600
|
+
this.readInt = (size) => {
|
|
601
|
+
return this.read(INT, size);
|
|
602
|
+
};
|
|
603
|
+
this.readString = (size) => {
|
|
604
|
+
return this.read(STRING, size);
|
|
605
|
+
};
|
|
606
|
+
this.readTemplate = (size) => {
|
|
607
|
+
return this.read(TEMPLATE, size);
|
|
608
|
+
};
|
|
609
|
+
this.readData = (size) => {
|
|
610
|
+
return this.read(DATA, size);
|
|
611
|
+
};
|
|
612
|
+
this.readUtf8 = (size) => {
|
|
613
|
+
return this.read(UTF8, size);
|
|
614
|
+
};
|
|
615
|
+
this.readFullBox = () => {
|
|
616
|
+
return {
|
|
617
|
+
version: this.readUint(1),
|
|
618
|
+
flags: this.readUint(3)
|
|
619
|
+
};
|
|
620
|
+
};
|
|
621
|
+
this.readArray = (type, size, length) => {
|
|
622
|
+
const value = [];
|
|
623
|
+
for (let i = 0; i < length; i++) value.push(this.read(type, size));
|
|
624
|
+
return value;
|
|
625
|
+
};
|
|
626
|
+
this.jump = (size) => {
|
|
627
|
+
this.offset += size;
|
|
628
|
+
};
|
|
629
|
+
this.readBox = () => {
|
|
630
|
+
const { dataView, offset } = this;
|
|
631
|
+
let cursor = 0;
|
|
632
|
+
const size = readUint(dataView, offset, 4);
|
|
633
|
+
const type = readString(dataView, offset + 4, 4);
|
|
634
|
+
const box = {
|
|
635
|
+
size,
|
|
636
|
+
type
|
|
637
|
+
};
|
|
638
|
+
cursor += 8;
|
|
639
|
+
if (box.size === 1) {
|
|
640
|
+
box.largesize = readUint(dataView, offset + cursor, 8);
|
|
641
|
+
cursor += 8;
|
|
642
|
+
}
|
|
643
|
+
const actualSize = box.size === 0 ? this.bytesRemaining : box.largesize ?? box.size;
|
|
644
|
+
if (this.cursor + actualSize > dataView.byteLength) {
|
|
645
|
+
this.truncated = true;
|
|
646
|
+
throw new Error("Truncated box");
|
|
647
|
+
}
|
|
648
|
+
this.jump(cursor);
|
|
649
|
+
if (type === "uuid") box.usertype = this.readArray("uint", 1, 16);
|
|
650
|
+
box.view = this.slice(offset, actualSize);
|
|
651
|
+
return box;
|
|
652
|
+
};
|
|
653
|
+
this.readBoxes = (length = -1) => {
|
|
654
|
+
const result = [];
|
|
655
|
+
for (const box of this) {
|
|
656
|
+
result.push(box);
|
|
657
|
+
if (length > 0 && result.length >= length) break;
|
|
658
|
+
}
|
|
659
|
+
return result;
|
|
660
|
+
};
|
|
661
|
+
this.readEntries = (length, map) => {
|
|
662
|
+
const result = [];
|
|
663
|
+
for (let i = 0; i < length; i++) result.push(map());
|
|
664
|
+
return result;
|
|
665
|
+
};
|
|
666
|
+
this.dataView = raw instanceof ArrayBuffer ? new DataView(raw) : raw instanceof DataView ? raw : new DataView(raw.buffer, raw.byteOffset, raw.byteLength);
|
|
667
|
+
this.offset = this.dataView.byteOffset;
|
|
668
|
+
this.config = config || { readers: {} };
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* The buffer of the data view.
|
|
672
|
+
*/
|
|
673
|
+
get buffer() {
|
|
674
|
+
return this.dataView.buffer;
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* The byte offset of the data view.
|
|
678
|
+
*/
|
|
679
|
+
get byteOffset() {
|
|
680
|
+
return this.dataView.byteOffset;
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* The byte length of the data view.
|
|
684
|
+
*/
|
|
685
|
+
get byteLength() {
|
|
686
|
+
return this.dataView.byteLength;
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* The current byteoffset in the data view.
|
|
690
|
+
*/
|
|
691
|
+
get cursor() {
|
|
692
|
+
return this.offset - this.dataView.byteOffset;
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* Whether the end of the data view has been reached.
|
|
696
|
+
*/
|
|
697
|
+
get done() {
|
|
698
|
+
return this.cursor >= this.dataView.byteLength || this.truncated;
|
|
699
|
+
}
|
|
700
|
+
/**
|
|
701
|
+
* The number of bytes remaining in the data view.
|
|
702
|
+
*/
|
|
703
|
+
get bytesRemaining() {
|
|
704
|
+
return this.dataView.byteLength - this.cursor;
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* Iterates over the boxes in the data view.
|
|
708
|
+
*
|
|
709
|
+
* @returns A generator of boxes.
|
|
710
|
+
*/
|
|
711
|
+
*[Symbol.iterator]() {
|
|
712
|
+
const { readers = {} } = this.config;
|
|
713
|
+
while (!this.done) try {
|
|
714
|
+
const box = this.readBox();
|
|
715
|
+
const { type, view } = box;
|
|
716
|
+
const parser = readers[type] || readers[type.trim()];
|
|
717
|
+
if (parser) Object.assign(box, parser(view));
|
|
718
|
+
if (isContainer(box) && !box.boxes) {
|
|
719
|
+
const boxes = [];
|
|
720
|
+
for (const child of view) boxes.push(child);
|
|
721
|
+
box.boxes = boxes;
|
|
722
|
+
}
|
|
723
|
+
yield box;
|
|
724
|
+
} catch (error) {
|
|
725
|
+
if (error instanceof Error && error.message === "Truncated box") break;
|
|
726
|
+
throw error;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
};
|
|
456
730
|
|
|
457
731
|
//#endregion
|
|
458
|
-
//#region src/
|
|
732
|
+
//#region src/readIsoBoxes.ts
|
|
459
733
|
/**
|
|
460
|
-
*
|
|
734
|
+
* Reads ISO boxes from a data source.
|
|
461
735
|
*
|
|
462
|
-
* @param
|
|
736
|
+
* @param raw - The raw ISO data
|
|
737
|
+
* @param config - The configuration for the IsoView
|
|
463
738
|
*
|
|
464
|
-
* @returns
|
|
739
|
+
* @returns The parsed boxes
|
|
740
|
+
*
|
|
741
|
+
* @example
|
|
742
|
+
* {@includeCode ../test/readIsoBoxes.test.ts#example}
|
|
465
743
|
*
|
|
466
744
|
* @public
|
|
467
745
|
*/
|
|
468
|
-
function
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
extendedLanguage: view.readUtf8(-1)
|
|
473
|
-
};
|
|
746
|
+
function readIsoBoxes(raw, config) {
|
|
747
|
+
const boxes = [];
|
|
748
|
+
for (const box of new IsoBoxReadView(raw, config)) boxes.push(box);
|
|
749
|
+
return boxes;
|
|
474
750
|
}
|
|
475
751
|
|
|
476
752
|
//#endregion
|
|
477
|
-
//#region src/
|
|
753
|
+
//#region src/traverseIsoBoxes.ts
|
|
478
754
|
/**
|
|
479
|
-
*
|
|
755
|
+
* Traverse ISO boxes
|
|
480
756
|
*
|
|
481
|
-
* @param
|
|
757
|
+
* @param boxes - The boxes to traverse
|
|
758
|
+
* @param depthFirst - Whether to traverse the boxes depth-first or breadth-first
|
|
759
|
+
* @param maxDepth - The maximum depth to traverse. A value of 0 will only traverse the root boxes.
|
|
482
760
|
*
|
|
483
|
-
* @returns A
|
|
761
|
+
* @returns A generator of boxes
|
|
762
|
+
*
|
|
763
|
+
* @example
|
|
764
|
+
* {@includeCode ../test/traverseIsoBoxes.test.ts#example}
|
|
484
765
|
*
|
|
485
766
|
* @public
|
|
486
767
|
*/
|
|
487
|
-
function
|
|
488
|
-
|
|
489
|
-
const
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
768
|
+
function* traverseIsoBoxes(boxes, depthFirst = true, maxDepth = Infinity) {
|
|
769
|
+
if (maxDepth < 0 || typeof maxDepth !== "number" || Number.isNaN(maxDepth)) return;
|
|
770
|
+
const queue = [[boxes, 0]];
|
|
771
|
+
while (queue.length > 0) {
|
|
772
|
+
const item = queue.shift();
|
|
773
|
+
if (!item) continue;
|
|
774
|
+
const [children, depth] = item;
|
|
775
|
+
for (const child of children) {
|
|
776
|
+
yield child;
|
|
777
|
+
if (depth >= maxDepth) continue;
|
|
778
|
+
if (isContainer(child) && child.boxes) {
|
|
779
|
+
const next = child.boxes;
|
|
780
|
+
if (depthFirst) yield* traverseIsoBoxes(next, depthFirst, maxDepth - 1);
|
|
781
|
+
else queue.push([next, depth + 1]);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
}
|
|
503
785
|
}
|
|
504
786
|
|
|
505
787
|
//#endregion
|
|
506
|
-
//#region src/
|
|
788
|
+
//#region src/writeIsoBoxes.ts
|
|
507
789
|
/**
|
|
508
|
-
*
|
|
790
|
+
* Writes ISO boxes to a readable stream.
|
|
791
|
+
*
|
|
792
|
+
* @param boxes - The boxes to write
|
|
793
|
+
* @param config - The configuration for the readable stream
|
|
794
|
+
*
|
|
795
|
+
* @returns A readable stream of the written boxes
|
|
796
|
+
*
|
|
797
|
+
* @example
|
|
798
|
+
* {@includeCode ../test/writeIsoBoxes.test.ts#example}
|
|
799
|
+
*
|
|
800
|
+
* @public
|
|
801
|
+
*/
|
|
802
|
+
function writeIsoBoxes(boxes, config) {
|
|
803
|
+
return writeBoxes(boxes, createWriterConfig(config));
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
//#endregion
|
|
807
|
+
//#region src/readers/readArdi.ts
|
|
808
|
+
/**
|
|
809
|
+
* Parse a AudioRenderingIndicationBox from an IsoView
|
|
509
810
|
*
|
|
510
811
|
* @param view - The IsoView to read data from
|
|
511
812
|
*
|
|
512
|
-
* @returns A parsed
|
|
813
|
+
* @returns A parsed AudioRenderingIndicationBox
|
|
513
814
|
*
|
|
514
815
|
* @public
|
|
515
816
|
*/
|
|
516
|
-
function
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
817
|
+
function readArdi(view) {
|
|
818
|
+
return {
|
|
819
|
+
type: "ardi",
|
|
820
|
+
...view.readFullBox(),
|
|
821
|
+
audioRenderingIndication: view.readUint(1)
|
|
521
822
|
};
|
|
522
|
-
if (result.version == 1) {
|
|
523
|
-
result.timescale = readUint$1(4);
|
|
524
|
-
result.presentationTime = readUint$1(8);
|
|
525
|
-
result.eventDuration = readUint$1(4);
|
|
526
|
-
result.id = readUint$1(4);
|
|
527
|
-
result.schemeIdUri = readString$1(-1);
|
|
528
|
-
result.value = readString$1(-1);
|
|
529
|
-
} else {
|
|
530
|
-
result.schemeIdUri = readString$1(-1);
|
|
531
|
-
result.value = readString$1(-1);
|
|
532
|
-
result.timescale = readUint$1(4);
|
|
533
|
-
result.presentationTimeDelta = readUint$1(4);
|
|
534
|
-
result.eventDuration = readUint$1(4);
|
|
535
|
-
result.id = readUint$1(4);
|
|
536
|
-
}
|
|
537
|
-
result.messageData = readData$1(-1);
|
|
538
|
-
return result;
|
|
539
823
|
}
|
|
540
824
|
|
|
541
825
|
//#endregion
|
|
542
|
-
//#region src/readers/
|
|
826
|
+
//#region src/readers/readAudioSampleEntryBox.ts
|
|
543
827
|
/**
|
|
544
|
-
* Parse
|
|
828
|
+
* Parse a AudioSampleEntryBox from an IsoView
|
|
545
829
|
*
|
|
830
|
+
* @param type - The type of AudioSampleEntryBox to read
|
|
546
831
|
* @param view - The IsoView to read data from
|
|
547
832
|
*
|
|
548
|
-
* @returns A parsed
|
|
833
|
+
* @returns A parsed AudioSampleEntryBox
|
|
549
834
|
*
|
|
550
835
|
* @public
|
|
551
836
|
*/
|
|
552
|
-
function
|
|
553
|
-
const { readArray, readUint: readUint$1, readTemplate: readTemplate$1,
|
|
837
|
+
function readAudioSampleEntryBox(type, view) {
|
|
838
|
+
const { readArray, readUint: readUint$1, readTemplate: readTemplate$1, readBoxes } = view;
|
|
554
839
|
return {
|
|
555
|
-
type
|
|
840
|
+
type,
|
|
556
841
|
reserved1: readArray(UINT, 1, 6),
|
|
557
842
|
dataReferenceIndex: readUint$1(2),
|
|
558
843
|
reserved2: readArray(UINT, 4, 2),
|
|
@@ -561,30 +846,46 @@ function readMp4a(view) {
|
|
|
561
846
|
preDefined: readUint$1(2),
|
|
562
847
|
reserved3: readUint$1(2),
|
|
563
848
|
samplerate: readTemplate$1(4),
|
|
564
|
-
|
|
849
|
+
boxes: readBoxes()
|
|
565
850
|
};
|
|
566
851
|
}
|
|
567
852
|
|
|
568
853
|
//#endregion
|
|
569
|
-
//#region src/readers/
|
|
854
|
+
//#region src/readers/readVisualSampleEntryBox.ts
|
|
570
855
|
/**
|
|
571
|
-
* Parse
|
|
856
|
+
* Parse a VisualSampleEntryBox from an IsoView
|
|
572
857
|
*
|
|
858
|
+
* @param type - The type of VisualSampleEntryBox to read
|
|
573
859
|
* @param view - The IsoView to read data from
|
|
574
860
|
*
|
|
575
|
-
* @returns A parsed
|
|
861
|
+
* @returns A parsed VisualSampleEntryBox
|
|
576
862
|
*
|
|
577
863
|
* @public
|
|
578
864
|
*/
|
|
579
|
-
function
|
|
865
|
+
function readVisualSampleEntryBox(type, view) {
|
|
866
|
+
const { readArray, readUint: readUint$1, readInt: readInt$1, readTemplate: readTemplate$1, readBoxes } = view;
|
|
580
867
|
return {
|
|
581
|
-
|
|
582
|
-
|
|
868
|
+
type,
|
|
869
|
+
reserved1: readArray(UINT, 1, 6),
|
|
870
|
+
dataReferenceIndex: readUint$1(2),
|
|
871
|
+
preDefined1: readUint$1(2),
|
|
872
|
+
reserved2: readUint$1(2),
|
|
873
|
+
preDefined2: readArray(UINT, 4, 3),
|
|
874
|
+
width: readUint$1(2),
|
|
875
|
+
height: readUint$1(2),
|
|
876
|
+
horizresolution: readTemplate$1(4),
|
|
877
|
+
vertresolution: readTemplate$1(4),
|
|
878
|
+
reserved3: readUint$1(4),
|
|
879
|
+
frameCount: readUint$1(2),
|
|
880
|
+
compressorName: readArray(UINT, 1, 32),
|
|
881
|
+
depth: readUint$1(2),
|
|
882
|
+
preDefined3: readInt$1(2),
|
|
883
|
+
boxes: readBoxes()
|
|
583
884
|
};
|
|
584
885
|
}
|
|
585
886
|
|
|
586
887
|
//#endregion
|
|
587
|
-
//#region src/readers/
|
|
888
|
+
//#region src/readers/readAvc1.ts
|
|
588
889
|
/**
|
|
589
890
|
* Parse a VisualSampleEntryBox from an IsoView
|
|
590
891
|
*
|
|
@@ -594,175 +895,366 @@ function readEnca(view) {
|
|
|
594
895
|
*
|
|
595
896
|
* @public
|
|
596
897
|
*/
|
|
597
|
-
function
|
|
598
|
-
return
|
|
599
|
-
...readAvc1(view),
|
|
600
|
-
type: "encv"
|
|
601
|
-
};
|
|
898
|
+
function readAvc1(view) {
|
|
899
|
+
return readVisualSampleEntryBox("avc1", view);
|
|
602
900
|
}
|
|
603
901
|
|
|
604
902
|
//#endregion
|
|
605
|
-
//#region src/readers/
|
|
903
|
+
//#region src/readers/readAvc2.ts
|
|
606
904
|
/**
|
|
607
|
-
* Parse a
|
|
905
|
+
* Parse a VisualSampleEntryBox from an IsoView
|
|
608
906
|
*
|
|
609
907
|
* @param view - The IsoView to read data from
|
|
610
908
|
*
|
|
611
|
-
* @returns A parsed
|
|
909
|
+
* @returns A parsed VisualSampleEntryBox
|
|
612
910
|
*
|
|
613
911
|
* @public
|
|
614
912
|
*/
|
|
615
|
-
function
|
|
616
|
-
return
|
|
617
|
-
type: "free",
|
|
618
|
-
data: view.readData(-1)
|
|
619
|
-
};
|
|
913
|
+
function readAvc2(view) {
|
|
914
|
+
return readVisualSampleEntryBox("avc2", view);
|
|
620
915
|
}
|
|
621
916
|
|
|
622
917
|
//#endregion
|
|
623
|
-
//#region src/readers/
|
|
918
|
+
//#region src/readers/readAvc3.ts
|
|
624
919
|
/**
|
|
625
|
-
* Parse
|
|
920
|
+
* Parse a VisualSampleEntryBox from an IsoView
|
|
626
921
|
*
|
|
627
922
|
* @param view - The IsoView to read data from
|
|
628
923
|
*
|
|
629
|
-
* @returns A parsed
|
|
924
|
+
* @returns A parsed VisualSampleEntryBox
|
|
630
925
|
*
|
|
631
926
|
* @public
|
|
632
927
|
*/
|
|
633
|
-
function
|
|
634
|
-
return
|
|
635
|
-
type: "frma",
|
|
636
|
-
dataFormat: view.readUint(4)
|
|
637
|
-
};
|
|
928
|
+
function readAvc3(view) {
|
|
929
|
+
return readVisualSampleEntryBox("avc3", view);
|
|
638
930
|
}
|
|
639
931
|
|
|
640
932
|
//#endregion
|
|
641
|
-
//#region src/
|
|
642
|
-
/**
|
|
643
|
-
* The string field type
|
|
644
|
-
*
|
|
645
|
-
* @public
|
|
646
|
-
*/
|
|
647
|
-
const STRING = "string";
|
|
648
|
-
|
|
649
|
-
//#endregion
|
|
650
|
-
//#region src/readers/readFtyp.ts
|
|
933
|
+
//#region src/readers/readAvc4.ts
|
|
651
934
|
/**
|
|
652
|
-
* Parse a
|
|
935
|
+
* Parse a VisualSampleEntryBox from an IsoView
|
|
653
936
|
*
|
|
654
937
|
* @param view - The IsoView to read data from
|
|
655
938
|
*
|
|
656
|
-
* @returns A parsed
|
|
939
|
+
* @returns A parsed VisualSampleEntryBox
|
|
657
940
|
*
|
|
658
941
|
* @public
|
|
659
942
|
*/
|
|
660
|
-
function
|
|
661
|
-
|
|
662
|
-
const majorBrand = view.readString(4);
|
|
663
|
-
const minorVersion = view.readUint(4);
|
|
664
|
-
const length = view.bytesRemaining / size;
|
|
665
|
-
return {
|
|
666
|
-
type: "ftyp",
|
|
667
|
-
majorBrand,
|
|
668
|
-
minorVersion,
|
|
669
|
-
compatibleBrands: view.readArray(STRING, size, length)
|
|
670
|
-
};
|
|
943
|
+
function readAvc4(view) {
|
|
944
|
+
return readVisualSampleEntryBox("avc4", view);
|
|
671
945
|
}
|
|
672
946
|
|
|
673
947
|
//#endregion
|
|
674
|
-
//#region src/readers/
|
|
948
|
+
//#region src/readers/readCtts.ts
|
|
675
949
|
/**
|
|
676
|
-
* Parse a
|
|
950
|
+
* Parse a CompositionTimeToSampleBox from an IsoView
|
|
677
951
|
*
|
|
678
952
|
* @param view - The IsoView to read data from
|
|
679
953
|
*
|
|
680
|
-
* @returns A parsed
|
|
954
|
+
* @returns A parsed CompositionTimeToSampleBox
|
|
681
955
|
*
|
|
682
956
|
* @public
|
|
683
957
|
*/
|
|
684
|
-
function
|
|
958
|
+
function readCtts(view) {
|
|
959
|
+
const { version, flags } = view.readFullBox();
|
|
960
|
+
const read = version === 1 ? view.readInt : view.readUint;
|
|
961
|
+
const entryCount = view.readUint(4);
|
|
685
962
|
return {
|
|
686
|
-
type: "
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
963
|
+
type: "ctts",
|
|
964
|
+
version,
|
|
965
|
+
flags,
|
|
966
|
+
entryCount,
|
|
967
|
+
entries: view.readEntries(entryCount, () => ({
|
|
968
|
+
sampleCount: view.readUint(4),
|
|
969
|
+
sampleOffset: read(4)
|
|
970
|
+
}))
|
|
692
971
|
};
|
|
693
972
|
}
|
|
694
973
|
|
|
695
974
|
//#endregion
|
|
696
|
-
//#region src/readers/
|
|
975
|
+
//#region src/readers/readDref.ts
|
|
697
976
|
/**
|
|
698
|
-
* Parse a
|
|
977
|
+
* Parse a DataReferenceBox from an IsoView
|
|
699
978
|
*
|
|
700
979
|
* @param view - The IsoView to read data from
|
|
701
980
|
*
|
|
702
|
-
* @returns A parsed
|
|
981
|
+
* @returns A parsed DataReferenceBox
|
|
703
982
|
*
|
|
704
983
|
* @public
|
|
705
984
|
*/
|
|
706
|
-
function
|
|
985
|
+
function readDref(view) {
|
|
986
|
+
const { version, flags } = view.readFullBox();
|
|
987
|
+
const entryCount = view.readUint(4);
|
|
707
988
|
return {
|
|
708
|
-
|
|
709
|
-
|
|
989
|
+
type: "dref",
|
|
990
|
+
version,
|
|
991
|
+
flags,
|
|
992
|
+
entryCount,
|
|
993
|
+
entries: view.readBoxes(entryCount)
|
|
710
994
|
};
|
|
711
995
|
}
|
|
712
996
|
|
|
713
997
|
//#endregion
|
|
714
|
-
//#region src/readers/
|
|
998
|
+
//#region src/readers/readElng.ts
|
|
715
999
|
/**
|
|
716
|
-
* Parse a
|
|
1000
|
+
* Parse a ExtendedLanguageBox from an IsoView
|
|
717
1001
|
*
|
|
718
1002
|
* @param view - The IsoView to read data from
|
|
719
1003
|
*
|
|
720
|
-
* @returns A parsed
|
|
1004
|
+
* @returns A parsed ExtendedLanguageBox
|
|
721
1005
|
*
|
|
722
1006
|
* @public
|
|
723
1007
|
*/
|
|
724
|
-
function
|
|
1008
|
+
function readElng(view) {
|
|
725
1009
|
return {
|
|
726
|
-
|
|
727
|
-
|
|
1010
|
+
type: "elng",
|
|
1011
|
+
...view.readFullBox(),
|
|
1012
|
+
extendedLanguage: view.readUtf8(-1)
|
|
728
1013
|
};
|
|
729
1014
|
}
|
|
730
1015
|
|
|
731
1016
|
//#endregion
|
|
732
|
-
//#region src/readers/
|
|
1017
|
+
//#region src/readers/readElst.ts
|
|
733
1018
|
/**
|
|
734
|
-
* Parse a
|
|
1019
|
+
* Parse a Box from an IsoView
|
|
735
1020
|
*
|
|
736
1021
|
* @param view - The IsoView to read data from
|
|
737
1022
|
*
|
|
738
|
-
* @returns A parsed
|
|
1023
|
+
* @returns A parsed Box
|
|
739
1024
|
*
|
|
740
1025
|
* @public
|
|
741
1026
|
*/
|
|
742
|
-
function
|
|
1027
|
+
function readElst(view) {
|
|
1028
|
+
const { version, flags } = view.readFullBox();
|
|
1029
|
+
const size = version === 1 ? 8 : 4;
|
|
1030
|
+
const entryCount = view.readUint(4);
|
|
743
1031
|
return {
|
|
744
|
-
type: "
|
|
745
|
-
|
|
1032
|
+
type: "elst",
|
|
1033
|
+
version,
|
|
1034
|
+
flags,
|
|
1035
|
+
entryCount,
|
|
1036
|
+
entries: view.readEntries(entryCount, () => ({
|
|
1037
|
+
segmentDuration: view.readUint(size),
|
|
1038
|
+
mediaTime: view.readInt(size),
|
|
1039
|
+
mediaRateInteger: view.readInt(2),
|
|
1040
|
+
mediaRateFraction: view.readInt(2)
|
|
1041
|
+
}))
|
|
746
1042
|
};
|
|
747
1043
|
}
|
|
748
1044
|
|
|
749
1045
|
//#endregion
|
|
750
|
-
//#region src/readers/
|
|
1046
|
+
//#region src/readers/readEmsg.ts
|
|
751
1047
|
/**
|
|
752
|
-
* Parse
|
|
1048
|
+
* Parse an EventMessageBox from an IsoView
|
|
753
1049
|
*
|
|
754
1050
|
* @param view - The IsoView to read data from
|
|
755
1051
|
*
|
|
756
|
-
* @returns A parsed
|
|
1052
|
+
* @returns A parsed EventMessageBox
|
|
757
1053
|
*
|
|
758
1054
|
* @public
|
|
759
1055
|
*/
|
|
760
|
-
function
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
};
|
|
1056
|
+
function readEmsg(view) {
|
|
1057
|
+
const { readUint: readUint$1, readString: readString$1, readData: readData$1 } = view;
|
|
1058
|
+
const result = {
|
|
1059
|
+
type: "emsg",
|
|
1060
|
+
...view.readFullBox()
|
|
1061
|
+
};
|
|
1062
|
+
if (result.version == 1) {
|
|
1063
|
+
result.timescale = readUint$1(4);
|
|
1064
|
+
result.presentationTime = readUint$1(8);
|
|
1065
|
+
result.eventDuration = readUint$1(4);
|
|
1066
|
+
result.id = readUint$1(4);
|
|
1067
|
+
result.schemeIdUri = readString$1(-1);
|
|
1068
|
+
result.value = readString$1(-1);
|
|
1069
|
+
} else {
|
|
1070
|
+
result.schemeIdUri = readString$1(-1);
|
|
1071
|
+
result.value = readString$1(-1);
|
|
1072
|
+
result.timescale = readUint$1(4);
|
|
1073
|
+
result.presentationTimeDelta = readUint$1(4);
|
|
1074
|
+
result.eventDuration = readUint$1(4);
|
|
1075
|
+
result.id = readUint$1(4);
|
|
1076
|
+
}
|
|
1077
|
+
result.messageData = readData$1(-1);
|
|
1078
|
+
return result;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
//#endregion
|
|
1082
|
+
//#region src/readers/readEnca.ts
|
|
1083
|
+
/**
|
|
1084
|
+
* Parse an AudioSampleEntry from an IsoView
|
|
1085
|
+
*
|
|
1086
|
+
* @param view - The IsoView to read data from
|
|
1087
|
+
*
|
|
1088
|
+
* @returns A parsed AudioSampleEntry
|
|
1089
|
+
*
|
|
1090
|
+
* @public
|
|
1091
|
+
*/
|
|
1092
|
+
function readEnca(view) {
|
|
1093
|
+
return readAudioSampleEntryBox("enca", view);
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
//#endregion
|
|
1097
|
+
//#region src/readers/readEncv.ts
|
|
1098
|
+
/**
|
|
1099
|
+
* Parse a VisualSampleEntryBox from an IsoView
|
|
1100
|
+
*
|
|
1101
|
+
* @param view - The IsoView to read data from
|
|
1102
|
+
*
|
|
1103
|
+
* @returns A parsed VisualSampleEntryBox
|
|
1104
|
+
*
|
|
1105
|
+
* @public
|
|
1106
|
+
*/
|
|
1107
|
+
function readEncv(view) {
|
|
1108
|
+
return readVisualSampleEntryBox("encv", view);
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
//#endregion
|
|
1112
|
+
//#region src/readers/readFree.ts
|
|
1113
|
+
/**
|
|
1114
|
+
* Parse a Box from an IsoView
|
|
1115
|
+
*
|
|
1116
|
+
* @param view - The IsoView to read data from
|
|
1117
|
+
*
|
|
1118
|
+
* @returns A parsed Box
|
|
1119
|
+
*
|
|
1120
|
+
* @public
|
|
1121
|
+
*/
|
|
1122
|
+
function readFree(view) {
|
|
1123
|
+
return {
|
|
1124
|
+
type: "free",
|
|
1125
|
+
data: view.readData(-1)
|
|
1126
|
+
};
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
//#endregion
|
|
1130
|
+
//#region src/readers/readFrma.ts
|
|
1131
|
+
/**
|
|
1132
|
+
* Parse an OriginalFormatBox from an IsoView
|
|
1133
|
+
*
|
|
1134
|
+
* @param view - The IsoView to read data from
|
|
1135
|
+
*
|
|
1136
|
+
* @returns A parsed OriginalFormatBox
|
|
1137
|
+
*
|
|
1138
|
+
* @public
|
|
1139
|
+
*/
|
|
1140
|
+
function readFrma(view) {
|
|
1141
|
+
return {
|
|
1142
|
+
type: "frma",
|
|
1143
|
+
dataFormat: view.readUint(4)
|
|
1144
|
+
};
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
//#endregion
|
|
1148
|
+
//#region src/readers/readFtyp.ts
|
|
1149
|
+
/**
|
|
1150
|
+
* Parse a FileTypeBox from an IsoView
|
|
1151
|
+
*
|
|
1152
|
+
* @param view - The IsoView to read data from
|
|
1153
|
+
*
|
|
1154
|
+
* @returns A parsed FileTypeBox
|
|
1155
|
+
*
|
|
1156
|
+
* @public
|
|
1157
|
+
*/
|
|
1158
|
+
function readFtyp(view) {
|
|
1159
|
+
const size = 4;
|
|
1160
|
+
const majorBrand = view.readString(4);
|
|
1161
|
+
const minorVersion = view.readUint(4);
|
|
1162
|
+
const length = view.bytesRemaining / size;
|
|
1163
|
+
return {
|
|
1164
|
+
type: "ftyp",
|
|
1165
|
+
majorBrand,
|
|
1166
|
+
minorVersion,
|
|
1167
|
+
compatibleBrands: view.readArray(STRING, size, length)
|
|
1168
|
+
};
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
//#endregion
|
|
1172
|
+
//#region src/readers/readHdlr.ts
|
|
1173
|
+
/**
|
|
1174
|
+
* Parse a HandlerReferenceBox from an IsoView
|
|
1175
|
+
*
|
|
1176
|
+
* @param view - The IsoView to read data from
|
|
1177
|
+
*
|
|
1178
|
+
* @returns A parsed HandlerReferenceBox
|
|
1179
|
+
*
|
|
1180
|
+
* @public
|
|
1181
|
+
*/
|
|
1182
|
+
function readHdlr(view) {
|
|
1183
|
+
return {
|
|
1184
|
+
type: "hdlr",
|
|
1185
|
+
...view.readFullBox(),
|
|
1186
|
+
preDefined: view.readUint(4),
|
|
1187
|
+
handlerType: view.readString(4),
|
|
1188
|
+
reserved: view.readArray(UINT, 4, 3),
|
|
1189
|
+
name: view.readString(-1)
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
//#endregion
|
|
1194
|
+
//#region src/readers/readHev1.ts
|
|
1195
|
+
/**
|
|
1196
|
+
* Parse a VisualSampleEntryBox from an IsoView
|
|
1197
|
+
*
|
|
1198
|
+
* @param view - The IsoView to read data from
|
|
1199
|
+
*
|
|
1200
|
+
* @returns A parsed VisualSampleEntryBox
|
|
1201
|
+
*
|
|
1202
|
+
* @public
|
|
1203
|
+
*/
|
|
1204
|
+
function readHev1(view) {
|
|
1205
|
+
return readVisualSampleEntryBox("hev1", view);
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
//#endregion
|
|
1209
|
+
//#region src/readers/readHvc1.ts
|
|
1210
|
+
/**
|
|
1211
|
+
* Parse a VisualSampleEntryBox from an IsoView
|
|
1212
|
+
*
|
|
1213
|
+
* @param view - The IsoView to read data from
|
|
1214
|
+
*
|
|
1215
|
+
* @returns A parsed VisualSampleEntryBox
|
|
1216
|
+
*
|
|
1217
|
+
* @public
|
|
1218
|
+
*/
|
|
1219
|
+
function readHvc1(view) {
|
|
1220
|
+
return readVisualSampleEntryBox("hvc1", view);
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
//#endregion
|
|
1224
|
+
//#region src/readers/readIden.ts
|
|
1225
|
+
/**
|
|
1226
|
+
* Parse a WebVTTCueIdBox from an IsoView
|
|
1227
|
+
*
|
|
1228
|
+
* @param view - The IsoView to read data from
|
|
1229
|
+
*
|
|
1230
|
+
* @returns A parsed WebVTTCueIdBox
|
|
1231
|
+
*
|
|
1232
|
+
* @public
|
|
1233
|
+
*/
|
|
1234
|
+
function readIden(view) {
|
|
1235
|
+
return {
|
|
1236
|
+
type: "iden",
|
|
1237
|
+
cueId: view.readUtf8(-1)
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
//#endregion
|
|
1242
|
+
//#region src/readers/readImda.ts
|
|
1243
|
+
/**
|
|
1244
|
+
* Parse a IdentifiedMediaDataBox from an IsoView
|
|
1245
|
+
*
|
|
1246
|
+
* @param view - The IsoView to read data from
|
|
1247
|
+
*
|
|
1248
|
+
* @returns A parsed IdentifiedMediaDataBox
|
|
1249
|
+
*
|
|
1250
|
+
* @public
|
|
1251
|
+
*/
|
|
1252
|
+
function readImda(view) {
|
|
1253
|
+
return {
|
|
1254
|
+
type: "imda",
|
|
1255
|
+
imdaIdentifier: view.readUint(4),
|
|
1256
|
+
data: view.readData(-1)
|
|
1257
|
+
};
|
|
766
1258
|
}
|
|
767
1259
|
|
|
768
1260
|
//#endregion
|
|
@@ -936,6 +1428,21 @@ function readMfro(view) {
|
|
|
936
1428
|
};
|
|
937
1429
|
}
|
|
938
1430
|
|
|
1431
|
+
//#endregion
|
|
1432
|
+
//#region src/readers/readMp4a.ts
|
|
1433
|
+
/**
|
|
1434
|
+
* Parse an AudioSampleEntry from an IsoView
|
|
1435
|
+
*
|
|
1436
|
+
* @param view - The IsoView to read data from
|
|
1437
|
+
*
|
|
1438
|
+
* @returns A parsed AudioSampleEntry
|
|
1439
|
+
*
|
|
1440
|
+
* @public
|
|
1441
|
+
*/
|
|
1442
|
+
function readMp4a(view) {
|
|
1443
|
+
return readAudioSampleEntryBox("mp4a", view);
|
|
1444
|
+
}
|
|
1445
|
+
|
|
939
1446
|
//#endregion
|
|
940
1447
|
//#region src/readers/readMvhd.ts
|
|
941
1448
|
/**
|
|
@@ -963,7 +1470,7 @@ function readMvhd(view) {
|
|
|
963
1470
|
volume: readTemplate$1(2),
|
|
964
1471
|
reserved1: readUint$1(2),
|
|
965
1472
|
reserved2: readArray(UINT, 4, 2),
|
|
966
|
-
matrix: readArray(
|
|
1473
|
+
matrix: readArray(TEMPLATE, 4, 9),
|
|
967
1474
|
preDefined: readArray(UINT, 4, 6),
|
|
968
1475
|
nextTrackId: readUint$1(4)
|
|
969
1476
|
};
|
|
@@ -1035,7 +1542,8 @@ function readPrsl(view) {
|
|
|
1035
1542
|
entities: view.readEntries(numEntitiesInGroup, () => ({ entityId: view.readUint(4) })),
|
|
1036
1543
|
preselectionTag: flags & 4096 ? view.readUtf8(-1) : void 0,
|
|
1037
1544
|
selectionPriority: flags & 8192 ? view.readUint(1) : void 0,
|
|
1038
|
-
interleavingTag: flags & 16384 ? view.readUtf8(-1) : void 0
|
|
1545
|
+
interleavingTag: flags & 16384 ? view.readUtf8(-1) : void 0,
|
|
1546
|
+
boxes: view.readBoxes()
|
|
1039
1547
|
};
|
|
1040
1548
|
}
|
|
1041
1549
|
|
|
@@ -1500,15 +2008,6 @@ function readTfra(view) {
|
|
|
1500
2008
|
};
|
|
1501
2009
|
}
|
|
1502
2010
|
|
|
1503
|
-
//#endregion
|
|
1504
|
-
//#region src/fields/TEMPLATE.ts
|
|
1505
|
-
/**
|
|
1506
|
-
* The template field type
|
|
1507
|
-
*
|
|
1508
|
-
* @public
|
|
1509
|
-
*/
|
|
1510
|
-
const TEMPLATE = "template";
|
|
1511
|
-
|
|
1512
2011
|
//#endregion
|
|
1513
2012
|
//#region src/readers/readTkhd.ts
|
|
1514
2013
|
/**
|
|
@@ -1576,586 +2075,154 @@ function readTrex(view) {
|
|
|
1576
2075
|
* @returns A parsed TrackRunBox
|
|
1577
2076
|
*
|
|
1578
2077
|
* @public
|
|
1579
|
-
*/
|
|
1580
|
-
function readTrun(view) {
|
|
1581
|
-
const { version, flags } = view.readFullBox();
|
|
1582
|
-
const sampleCount = view.readUint(4);
|
|
1583
|
-
let dataOffset;
|
|
1584
|
-
let firstSampleFlags;
|
|
1585
|
-
if (flags & 1) dataOffset = view.readInt(4);
|
|
1586
|
-
if (flags & 4) firstSampleFlags = view.readUint(4);
|
|
1587
|
-
const samples = view.readEntries(sampleCount, () => {
|
|
1588
|
-
const sample = {};
|
|
1589
|
-
if (flags & 256) sample.sampleDuration = view.readUint(4);
|
|
1590
|
-
if (flags & 512) sample.sampleSize = view.readUint(4);
|
|
1591
|
-
if (flags & 1024) sample.sampleFlags = view.readUint(4);
|
|
1592
|
-
if (flags & 2048) sample.sampleCompositionTimeOffset = version === 1 ? view.readInt(4) : view.readUint(4);
|
|
1593
|
-
return sample;
|
|
1594
|
-
});
|
|
1595
|
-
return {
|
|
1596
|
-
type: "trun",
|
|
1597
|
-
version,
|
|
1598
|
-
flags,
|
|
1599
|
-
sampleCount,
|
|
1600
|
-
dataOffset,
|
|
1601
|
-
firstSampleFlags,
|
|
1602
|
-
samples
|
|
1603
|
-
};
|
|
1604
|
-
}
|
|
1605
|
-
|
|
1606
|
-
//#endregion
|
|
1607
|
-
//#region src/readers/readUrl.ts
|
|
1608
|
-
/**
|
|
1609
|
-
* Parse a UrlBox from an IsoView
|
|
1610
|
-
*
|
|
1611
|
-
* @param view - The IsoView to read data from
|
|
1612
|
-
*
|
|
1613
|
-
* @returns A parsed UrlBox
|
|
1614
|
-
*
|
|
1615
|
-
* @public
|
|
1616
|
-
*/
|
|
1617
|
-
function readUrl(view) {
|
|
1618
|
-
return {
|
|
1619
|
-
type: "url ",
|
|
1620
|
-
...view.readFullBox(),
|
|
1621
|
-
location: view.readString(-1)
|
|
1622
|
-
};
|
|
1623
|
-
}
|
|
1624
|
-
|
|
1625
|
-
//#endregion
|
|
1626
|
-
//#region src/readers/readUrn.ts
|
|
1627
|
-
/**
|
|
1628
|
-
* Parse a UrnBox from an IsoView
|
|
1629
|
-
*
|
|
1630
|
-
* @param view - The IsoView to read data from
|
|
1631
|
-
*
|
|
1632
|
-
* @returns A parsed UrnBox
|
|
1633
|
-
*
|
|
1634
|
-
* @public
|
|
1635
|
-
*/
|
|
1636
|
-
function readUrn(view) {
|
|
1637
|
-
return {
|
|
1638
|
-
type: "urn ",
|
|
1639
|
-
...view.readFullBox(),
|
|
1640
|
-
name: view.readString(-1),
|
|
1641
|
-
location: view.readString(-1)
|
|
1642
|
-
};
|
|
1643
|
-
}
|
|
1644
|
-
|
|
1645
|
-
//#endregion
|
|
1646
|
-
//#region src/readers/readVlab.ts
|
|
1647
|
-
/**
|
|
1648
|
-
* Parse a WebVTTSourceLabelBox from an IsoView
|
|
1649
|
-
*
|
|
1650
|
-
* @param view - The IsoView to read data from
|
|
1651
|
-
*
|
|
1652
|
-
* @returns A parsed WebVTTSourceLabelBox
|
|
1653
|
-
*
|
|
1654
|
-
* @public
|
|
1655
|
-
*/
|
|
1656
|
-
function readVlab(view) {
|
|
1657
|
-
return {
|
|
1658
|
-
type: "vlab",
|
|
1659
|
-
sourceLabel: view.readUtf8(-1)
|
|
1660
|
-
};
|
|
1661
|
-
}
|
|
1662
|
-
|
|
1663
|
-
//#endregion
|
|
1664
|
-
//#region src/readers/readVmhd.ts
|
|
1665
|
-
/**
|
|
1666
|
-
* Parse a VideoMediaHeaderBox from an IsoView
|
|
1667
|
-
*
|
|
1668
|
-
* @param view - The IsoView to read data from
|
|
1669
|
-
*
|
|
1670
|
-
* @returns A parsed VideoMediaHeaderBox
|
|
1671
|
-
*
|
|
1672
|
-
* @public
|
|
1673
|
-
*/
|
|
1674
|
-
function readVmhd(view) {
|
|
1675
|
-
return {
|
|
1676
|
-
type: "vmhd",
|
|
1677
|
-
...view.readFullBox(),
|
|
1678
|
-
graphicsmode: view.readUint(2),
|
|
1679
|
-
opcolor: view.readArray(UINT, 2, 3)
|
|
1680
|
-
};
|
|
1681
|
-
}
|
|
1682
|
-
|
|
1683
|
-
//#endregion
|
|
1684
|
-
//#region src/readers/readVttC.ts
|
|
1685
|
-
/**
|
|
1686
|
-
* Parse a WebVTTConfigurationBox from an IsoView
|
|
1687
|
-
*
|
|
1688
|
-
* @param view - The IsoView to read data from
|
|
1689
|
-
*
|
|
1690
|
-
* @returns A parsed WebVttConfigurationBox
|
|
1691
|
-
*
|
|
1692
|
-
* @public
|
|
1693
|
-
*/
|
|
1694
|
-
function readVttC(view) {
|
|
1695
|
-
return {
|
|
1696
|
-
type: "vttC",
|
|
1697
|
-
config: view.readUtf8()
|
|
1698
|
-
};
|
|
1699
|
-
}
|
|
1700
|
-
|
|
1701
|
-
//#endregion
|
|
1702
|
-
//#region src/readers/readVtte.ts
|
|
1703
|
-
/**
|
|
1704
|
-
* Parse a WebVTT Empty Sample Box from an IsoView
|
|
1705
|
-
*
|
|
1706
|
-
* @returns A parsed WebVTT Empty Sample Box
|
|
1707
|
-
*
|
|
1708
|
-
* @public
|
|
1709
|
-
*/
|
|
1710
|
-
function readVtte(_) {
|
|
1711
|
-
return { type: "vtte" };
|
|
1712
|
-
}
|
|
1713
|
-
|
|
1714
|
-
//#endregion
|
|
1715
|
-
//#region src/fields/DATA.ts
|
|
1716
|
-
/**
|
|
1717
|
-
* The data field type
|
|
1718
|
-
*
|
|
1719
|
-
* @public
|
|
1720
|
-
*/
|
|
1721
|
-
const DATA = "data";
|
|
1722
|
-
|
|
1723
|
-
//#endregion
|
|
1724
|
-
//#region src/fields/INT.ts
|
|
1725
|
-
/**
|
|
1726
|
-
* The integer field type
|
|
1727
|
-
*
|
|
1728
|
-
* @public
|
|
1729
|
-
*/
|
|
1730
|
-
const INT = "int";
|
|
1731
|
-
|
|
1732
|
-
//#endregion
|
|
1733
|
-
//#region src/fields/UTF8.ts
|
|
1734
|
-
/**
|
|
1735
|
-
* The UTF8 field type
|
|
1736
|
-
*
|
|
1737
|
-
* @public
|
|
1738
|
-
*/
|
|
1739
|
-
const UTF8 = "utf8";
|
|
1740
|
-
|
|
1741
|
-
//#endregion
|
|
1742
|
-
//#region src/utils/readData.ts
|
|
1743
|
-
function readData(dataView, offset, size) {
|
|
1744
|
-
const length = size > 0 ? size : dataView.byteLength - (offset - dataView.byteOffset);
|
|
1745
|
-
return new Uint8Array(dataView.buffer, offset, Math.max(length, 0));
|
|
1746
|
-
}
|
|
1747
|
-
|
|
1748
|
-
//#endregion
|
|
1749
|
-
//#region src/utils/readInt.ts
|
|
1750
|
-
function readInt(dataView, offset, size) {
|
|
1751
|
-
let result = NaN;
|
|
1752
|
-
const cursor = offset - dataView.byteOffset;
|
|
1753
|
-
switch (size) {
|
|
1754
|
-
case 1:
|
|
1755
|
-
result = dataView.getInt8(cursor);
|
|
1756
|
-
break;
|
|
1757
|
-
case 2:
|
|
1758
|
-
result = dataView.getInt16(cursor);
|
|
1759
|
-
break;
|
|
1760
|
-
case 4:
|
|
1761
|
-
result = dataView.getInt32(cursor);
|
|
1762
|
-
break;
|
|
1763
|
-
case 8:
|
|
1764
|
-
const s1 = dataView.getInt32(cursor);
|
|
1765
|
-
const s2 = dataView.getInt32(cursor + 4);
|
|
1766
|
-
result = s1 * Math.pow(2, 32) + s2;
|
|
1767
|
-
break;
|
|
1768
|
-
}
|
|
1769
|
-
return result;
|
|
1770
|
-
}
|
|
1771
|
-
|
|
1772
|
-
//#endregion
|
|
1773
|
-
//#region src/utils/readUint.ts
|
|
1774
|
-
function readUint(dataView, offset, size) {
|
|
1775
|
-
const cursor = offset - dataView.byteOffset;
|
|
1776
|
-
let value = NaN;
|
|
1777
|
-
let s1;
|
|
1778
|
-
let s2;
|
|
1779
|
-
switch (size) {
|
|
1780
|
-
case 1:
|
|
1781
|
-
value = dataView.getUint8(cursor);
|
|
1782
|
-
break;
|
|
1783
|
-
case 2:
|
|
1784
|
-
value = dataView.getUint16(cursor);
|
|
1785
|
-
break;
|
|
1786
|
-
case 3:
|
|
1787
|
-
s1 = dataView.getUint16(cursor);
|
|
1788
|
-
s2 = dataView.getUint8(cursor + 2);
|
|
1789
|
-
value = (s1 << 8) + s2;
|
|
1790
|
-
break;
|
|
1791
|
-
case 4:
|
|
1792
|
-
value = dataView.getUint32(cursor);
|
|
1793
|
-
break;
|
|
1794
|
-
case 8:
|
|
1795
|
-
s1 = dataView.getUint32(cursor);
|
|
1796
|
-
s2 = dataView.getUint32(cursor + 4);
|
|
1797
|
-
value = s1 * Math.pow(2, 32) + s2;
|
|
1798
|
-
break;
|
|
1799
|
-
}
|
|
1800
|
-
return value;
|
|
1801
|
-
}
|
|
1802
|
-
|
|
1803
|
-
//#endregion
|
|
1804
|
-
//#region src/utils/readString.ts
|
|
1805
|
-
function readString(dataView, offset, length) {
|
|
1806
|
-
let str = "";
|
|
1807
|
-
for (let c = 0; c < length; c++) {
|
|
1808
|
-
const char = readUint(dataView, offset + c, 1);
|
|
1809
|
-
str += String.fromCharCode(char);
|
|
1810
|
-
}
|
|
1811
|
-
return str;
|
|
1812
|
-
}
|
|
1813
|
-
|
|
1814
|
-
//#endregion
|
|
1815
|
-
//#region src/utils/readTemplate.ts
|
|
1816
|
-
function readTemplate(dataView, offset, size) {
|
|
1817
|
-
const half = size / 2;
|
|
1818
|
-
return readUint(dataView, offset, half) + readUint(dataView, offset + half, half) / Math.pow(2, half);
|
|
1819
|
-
}
|
|
1820
|
-
|
|
1821
|
-
//#endregion
|
|
1822
|
-
//#region src/utils/readTerminatedString.ts
|
|
1823
|
-
function readTerminatedString(dataView, offset) {
|
|
1824
|
-
let str = "";
|
|
1825
|
-
let cursor = offset;
|
|
1826
|
-
while (cursor - dataView.byteOffset < dataView.byteLength) {
|
|
1827
|
-
const char = readUint(dataView, cursor, 1);
|
|
1828
|
-
if (char === 0) break;
|
|
1829
|
-
str += String.fromCharCode(char);
|
|
1830
|
-
cursor++;
|
|
1831
|
-
}
|
|
1832
|
-
return str;
|
|
1833
|
-
}
|
|
1834
|
-
|
|
1835
|
-
//#endregion
|
|
1836
|
-
//#region src/utils/readUtf8String.ts
|
|
1837
|
-
/**
|
|
1838
|
-
* Reads a UTF-8 string from a data view.
|
|
1839
|
-
*
|
|
1840
|
-
* @param dataView - The data view to read from.
|
|
1841
|
-
* @param offset - The offset to start reading from.
|
|
1842
|
-
* @returns The UTF-8 string.
|
|
1843
|
-
*
|
|
1844
|
-
* @internal
|
|
1845
|
-
*/
|
|
1846
|
-
function readUtf8String(dataView, offset) {
|
|
1847
|
-
const length = dataView.byteLength - (offset - dataView.byteOffset);
|
|
1848
|
-
return length > 0 ? decodeText(new DataView(dataView.buffer, offset, length), { encoding: UTF_8 }) : "";
|
|
1849
|
-
}
|
|
1850
|
-
|
|
1851
|
-
//#endregion
|
|
1852
|
-
//#region src/utils/readUtf8TerminatedString.ts
|
|
1853
|
-
/**
|
|
1854
|
-
* Reads a UTF-8 terminated string from a data view.
|
|
1855
|
-
*
|
|
1856
|
-
* @param dataView - The data view to read from.
|
|
1857
|
-
* @param offset - The offset to start reading from.
|
|
1858
|
-
* @returns The UTF-8 terminated string.
|
|
1859
|
-
*
|
|
1860
|
-
* @internal
|
|
1861
|
-
*/
|
|
1862
|
-
function readUtf8TerminatedString(dataView, offset) {
|
|
1863
|
-
const length = dataView.byteLength - (offset - dataView.byteOffset);
|
|
1864
|
-
let data = "";
|
|
1865
|
-
if (length > 0) {
|
|
1866
|
-
const view = new DataView(dataView.buffer, offset, length);
|
|
1867
|
-
let l = 0;
|
|
1868
|
-
for (; l < length; l++) if (view.getUint8(l) === 0) break;
|
|
1869
|
-
data = decodeText(new DataView(dataView.buffer, offset, l), { encoding: UTF_8 });
|
|
1870
|
-
}
|
|
1871
|
-
return data;
|
|
1872
|
-
}
|
|
1873
|
-
|
|
1874
|
-
//#endregion
|
|
1875
|
-
//#region src/IsoBoxReadView.ts
|
|
1876
|
-
/**
|
|
1877
|
-
* ISO BMFF data view. Similar to DataView, but with additional methods for reading ISO BMFF data.
|
|
1878
|
-
* It implements the iterator protocol, so it can be used in a for...of loop.
|
|
1879
|
-
*
|
|
1880
|
-
* @public
|
|
1881
|
-
*/
|
|
1882
|
-
var IsoBoxReadView = class IsoBoxReadView {
|
|
1883
|
-
/**
|
|
1884
|
-
* Creates a new IsoView instance. Similar to DataView, but with additional
|
|
1885
|
-
* methods for reading ISO BMFF data. It implements the iterator protocol,
|
|
1886
|
-
* so it can be used in a for...of loop.
|
|
1887
|
-
*
|
|
1888
|
-
* @param raw - The raw data to view.
|
|
1889
|
-
* @param config - The configuration for the IsoView.
|
|
1890
|
-
*/
|
|
1891
|
-
constructor(raw, config) {
|
|
1892
|
-
this.truncated = false;
|
|
1893
|
-
this.slice = (offset, size) => {
|
|
1894
|
-
const isoView = new IsoBoxReadView(new DataView(this.dataView.buffer, offset, size), this.config);
|
|
1895
|
-
const headerSize = this.offset - offset;
|
|
1896
|
-
const bodySize = size - headerSize;
|
|
1897
|
-
this.offset += bodySize;
|
|
1898
|
-
isoView.jump(headerSize);
|
|
1899
|
-
return isoView;
|
|
1900
|
-
};
|
|
1901
|
-
this.read = (type, size = 0) => {
|
|
1902
|
-
const { dataView, offset } = this;
|
|
1903
|
-
let result;
|
|
1904
|
-
let cursor = size;
|
|
1905
|
-
switch (type) {
|
|
1906
|
-
case UINT:
|
|
1907
|
-
result = readUint(dataView, offset, size);
|
|
1908
|
-
break;
|
|
1909
|
-
case INT:
|
|
1910
|
-
result = readInt(dataView, offset, size);
|
|
1911
|
-
break;
|
|
1912
|
-
case TEMPLATE:
|
|
1913
|
-
result = readTemplate(dataView, offset, size);
|
|
1914
|
-
break;
|
|
1915
|
-
case STRING:
|
|
1916
|
-
if (size === -1) {
|
|
1917
|
-
result = readTerminatedString(dataView, offset);
|
|
1918
|
-
cursor = result.length + 1;
|
|
1919
|
-
} else result = readString(dataView, offset, size);
|
|
1920
|
-
break;
|
|
1921
|
-
case DATA:
|
|
1922
|
-
result = readData(dataView, offset, size);
|
|
1923
|
-
cursor = result.length;
|
|
1924
|
-
break;
|
|
1925
|
-
case UTF8:
|
|
1926
|
-
if (size === -1) {
|
|
1927
|
-
result = readUtf8TerminatedString(dataView, offset);
|
|
1928
|
-
cursor = result.length + 1;
|
|
1929
|
-
} else result = readUtf8String(dataView, offset);
|
|
1930
|
-
break;
|
|
1931
|
-
default: result = -1;
|
|
1932
|
-
}
|
|
1933
|
-
this.offset += cursor;
|
|
1934
|
-
return result;
|
|
1935
|
-
};
|
|
1936
|
-
this.readUint = (size) => {
|
|
1937
|
-
return this.read(UINT, size);
|
|
1938
|
-
};
|
|
1939
|
-
this.readInt = (size) => {
|
|
1940
|
-
return this.read(INT, size);
|
|
1941
|
-
};
|
|
1942
|
-
this.readString = (size) => {
|
|
1943
|
-
return this.read(STRING, size);
|
|
1944
|
-
};
|
|
1945
|
-
this.readTemplate = (size) => {
|
|
1946
|
-
return this.read(TEMPLATE, size);
|
|
1947
|
-
};
|
|
1948
|
-
this.readData = (size) => {
|
|
1949
|
-
return this.read(DATA, size);
|
|
1950
|
-
};
|
|
1951
|
-
this.readUtf8 = (size) => {
|
|
1952
|
-
return this.read(UTF8, size);
|
|
1953
|
-
};
|
|
1954
|
-
this.readFullBox = () => {
|
|
1955
|
-
return {
|
|
1956
|
-
version: this.readUint(1),
|
|
1957
|
-
flags: this.readUint(3)
|
|
1958
|
-
};
|
|
1959
|
-
};
|
|
1960
|
-
this.readArray = (type, size, length) => {
|
|
1961
|
-
const value = [];
|
|
1962
|
-
for (let i = 0; i < length; i++) value.push(this.read(type, size));
|
|
1963
|
-
return value;
|
|
1964
|
-
};
|
|
1965
|
-
this.jump = (size) => {
|
|
1966
|
-
this.offset += size;
|
|
1967
|
-
};
|
|
1968
|
-
this.readBox = () => {
|
|
1969
|
-
const { dataView, offset } = this;
|
|
1970
|
-
let cursor = 0;
|
|
1971
|
-
const size = readUint(dataView, offset, 4);
|
|
1972
|
-
const type = readString(dataView, offset + 4, 4);
|
|
1973
|
-
const box = {
|
|
1974
|
-
size,
|
|
1975
|
-
type
|
|
1976
|
-
};
|
|
1977
|
-
cursor += 8;
|
|
1978
|
-
if (box.size === 1) {
|
|
1979
|
-
box.largesize = readUint(dataView, offset + cursor, 8);
|
|
1980
|
-
cursor += 8;
|
|
1981
|
-
}
|
|
1982
|
-
const actualSize = box.size === 0 ? this.bytesRemaining : box.largesize ?? box.size;
|
|
1983
|
-
if (this.cursor + actualSize > dataView.byteLength) {
|
|
1984
|
-
this.truncated = true;
|
|
1985
|
-
throw new Error("Truncated box");
|
|
1986
|
-
}
|
|
1987
|
-
this.jump(cursor);
|
|
1988
|
-
if (type === "uuid") box.usertype = this.readArray("uint", 1, 16);
|
|
1989
|
-
box.view = this.slice(offset, actualSize);
|
|
1990
|
-
return box;
|
|
1991
|
-
};
|
|
1992
|
-
this.readBoxes = (length = -1) => {
|
|
1993
|
-
const result = [];
|
|
1994
|
-
for (const box of this) {
|
|
1995
|
-
result.push(box);
|
|
1996
|
-
if (length > 0 && result.length >= length) break;
|
|
1997
|
-
}
|
|
1998
|
-
return result;
|
|
1999
|
-
};
|
|
2000
|
-
this.readEntries = (length, map) => {
|
|
2001
|
-
const result = [];
|
|
2002
|
-
for (let i = 0; i < length; i++) result.push(map());
|
|
2003
|
-
return result;
|
|
2004
|
-
};
|
|
2005
|
-
this.dataView = raw instanceof ArrayBuffer ? new DataView(raw) : raw instanceof DataView ? raw : new DataView(raw.buffer, raw.byteOffset, raw.byteLength);
|
|
2006
|
-
this.offset = this.dataView.byteOffset;
|
|
2007
|
-
this.config = config || { readers: {} };
|
|
2008
|
-
}
|
|
2009
|
-
/**
|
|
2010
|
-
* The buffer of the data view.
|
|
2011
|
-
*/
|
|
2012
|
-
get buffer() {
|
|
2013
|
-
return this.dataView.buffer;
|
|
2014
|
-
}
|
|
2015
|
-
/**
|
|
2016
|
-
* The byte offset of the data view.
|
|
2017
|
-
*/
|
|
2018
|
-
get byteOffset() {
|
|
2019
|
-
return this.dataView.byteOffset;
|
|
2020
|
-
}
|
|
2021
|
-
/**
|
|
2022
|
-
* The byte length of the data view.
|
|
2023
|
-
*/
|
|
2024
|
-
get byteLength() {
|
|
2025
|
-
return this.dataView.byteLength;
|
|
2026
|
-
}
|
|
2027
|
-
/**
|
|
2028
|
-
* The current byteoffset in the data view.
|
|
2029
|
-
*/
|
|
2030
|
-
get cursor() {
|
|
2031
|
-
return this.offset - this.dataView.byteOffset;
|
|
2032
|
-
}
|
|
2033
|
-
/**
|
|
2034
|
-
* Whether the end of the data view has been reached.
|
|
2035
|
-
*/
|
|
2036
|
-
get done() {
|
|
2037
|
-
return this.cursor >= this.dataView.byteLength || this.truncated;
|
|
2038
|
-
}
|
|
2039
|
-
/**
|
|
2040
|
-
* The number of bytes remaining in the data view.
|
|
2041
|
-
*/
|
|
2042
|
-
get bytesRemaining() {
|
|
2043
|
-
return this.dataView.byteLength - this.cursor;
|
|
2044
|
-
}
|
|
2045
|
-
/**
|
|
2046
|
-
* Iterates over the boxes in the data view.
|
|
2047
|
-
*
|
|
2048
|
-
* @returns A generator of boxes.
|
|
2049
|
-
*/
|
|
2050
|
-
*[Symbol.iterator]() {
|
|
2051
|
-
const { readers = {} } = this.config;
|
|
2052
|
-
while (!this.done) try {
|
|
2053
|
-
const box = this.readBox();
|
|
2054
|
-
const { type, view } = box;
|
|
2055
|
-
const parser = readers[type] || readers[type.trim()];
|
|
2056
|
-
if (parser) Object.assign(box, parser(view));
|
|
2057
|
-
if (isContainer(box) && !box.boxes) {
|
|
2058
|
-
const boxes = [];
|
|
2059
|
-
for (const child of view) boxes.push(child);
|
|
2060
|
-
box.boxes = boxes;
|
|
2061
|
-
}
|
|
2062
|
-
yield box;
|
|
2063
|
-
} catch (error) {
|
|
2064
|
-
if (error instanceof Error && error.message === "Truncated box") break;
|
|
2065
|
-
throw error;
|
|
2066
|
-
}
|
|
2067
|
-
}
|
|
2068
|
-
};
|
|
2078
|
+
*/
|
|
2079
|
+
function readTrun(view) {
|
|
2080
|
+
const { version, flags } = view.readFullBox();
|
|
2081
|
+
const sampleCount = view.readUint(4);
|
|
2082
|
+
let dataOffset;
|
|
2083
|
+
let firstSampleFlags;
|
|
2084
|
+
if (flags & 1) dataOffset = view.readInt(4);
|
|
2085
|
+
if (flags & 4) firstSampleFlags = view.readUint(4);
|
|
2086
|
+
const samples = view.readEntries(sampleCount, () => {
|
|
2087
|
+
const sample = {};
|
|
2088
|
+
if (flags & 256) sample.sampleDuration = view.readUint(4);
|
|
2089
|
+
if (flags & 512) sample.sampleSize = view.readUint(4);
|
|
2090
|
+
if (flags & 1024) sample.sampleFlags = view.readUint(4);
|
|
2091
|
+
if (flags & 2048) sample.sampleCompositionTimeOffset = version === 1 ? view.readInt(4) : view.readUint(4);
|
|
2092
|
+
return sample;
|
|
2093
|
+
});
|
|
2094
|
+
return {
|
|
2095
|
+
type: "trun",
|
|
2096
|
+
version,
|
|
2097
|
+
flags,
|
|
2098
|
+
sampleCount,
|
|
2099
|
+
dataOffset,
|
|
2100
|
+
firstSampleFlags,
|
|
2101
|
+
samples
|
|
2102
|
+
};
|
|
2103
|
+
}
|
|
2069
2104
|
|
|
2070
2105
|
//#endregion
|
|
2071
|
-
//#region src/
|
|
2106
|
+
//#region src/readers/readUrl.ts
|
|
2072
2107
|
/**
|
|
2073
|
-
*
|
|
2108
|
+
* Parse a UrlBox from an IsoView
|
|
2074
2109
|
*
|
|
2075
|
-
* @param
|
|
2076
|
-
* @param config - The configuration for the IsoView
|
|
2110
|
+
* @param view - The IsoView to read data from
|
|
2077
2111
|
*
|
|
2078
|
-
* @returns
|
|
2112
|
+
* @returns A parsed UrlBox
|
|
2079
2113
|
*
|
|
2080
|
-
* @
|
|
2081
|
-
|
|
2114
|
+
* @public
|
|
2115
|
+
*/
|
|
2116
|
+
function readUrl(view) {
|
|
2117
|
+
return {
|
|
2118
|
+
type: "url ",
|
|
2119
|
+
...view.readFullBox(),
|
|
2120
|
+
location: view.readString(-1)
|
|
2121
|
+
};
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
//#endregion
|
|
2125
|
+
//#region src/readers/readUrn.ts
|
|
2126
|
+
/**
|
|
2127
|
+
* Parse a UrnBox from an IsoView
|
|
2128
|
+
*
|
|
2129
|
+
* @param view - The IsoView to read data from
|
|
2130
|
+
*
|
|
2131
|
+
* @returns A parsed UrnBox
|
|
2082
2132
|
*
|
|
2083
2133
|
* @public
|
|
2084
2134
|
*/
|
|
2085
|
-
function
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2135
|
+
function readUrn(view) {
|
|
2136
|
+
return {
|
|
2137
|
+
type: "urn ",
|
|
2138
|
+
...view.readFullBox(),
|
|
2139
|
+
name: view.readString(-1),
|
|
2140
|
+
location: view.readString(-1)
|
|
2141
|
+
};
|
|
2089
2142
|
}
|
|
2090
2143
|
|
|
2091
2144
|
//#endregion
|
|
2092
|
-
//#region src/
|
|
2145
|
+
//#region src/readers/readVlab.ts
|
|
2093
2146
|
/**
|
|
2094
|
-
*
|
|
2147
|
+
* Parse a WebVTTSourceLabelBox from an IsoView
|
|
2095
2148
|
*
|
|
2096
|
-
* @param
|
|
2097
|
-
* @param depthFirst - Whether to traverse the boxes depth-first or breadth-first
|
|
2098
|
-
* @param maxDepth - The maximum depth to traverse. A value of 0 will only traverse the root boxes.
|
|
2149
|
+
* @param view - The IsoView to read data from
|
|
2099
2150
|
*
|
|
2100
|
-
* @returns A
|
|
2151
|
+
* @returns A parsed WebVTTSourceLabelBox
|
|
2101
2152
|
*
|
|
2102
|
-
* @
|
|
2103
|
-
|
|
2153
|
+
* @public
|
|
2154
|
+
*/
|
|
2155
|
+
function readVlab(view) {
|
|
2156
|
+
return {
|
|
2157
|
+
type: "vlab",
|
|
2158
|
+
sourceLabel: view.readUtf8(-1)
|
|
2159
|
+
};
|
|
2160
|
+
}
|
|
2161
|
+
|
|
2162
|
+
//#endregion
|
|
2163
|
+
//#region src/readers/readVmhd.ts
|
|
2164
|
+
/**
|
|
2165
|
+
* Parse a VideoMediaHeaderBox from an IsoView
|
|
2166
|
+
*
|
|
2167
|
+
* @param view - The IsoView to read data from
|
|
2168
|
+
*
|
|
2169
|
+
* @returns A parsed VideoMediaHeaderBox
|
|
2104
2170
|
*
|
|
2105
2171
|
* @public
|
|
2106
2172
|
*/
|
|
2107
|
-
function
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
for (const child of children) {
|
|
2115
|
-
yield child;
|
|
2116
|
-
if (depth >= maxDepth) continue;
|
|
2117
|
-
if (isContainer(child) && child.boxes) {
|
|
2118
|
-
const next = child.boxes;
|
|
2119
|
-
if (depthFirst) yield* traverseIsoBoxes(next, depthFirst, maxDepth - 1);
|
|
2120
|
-
else queue.push([next, depth + 1]);
|
|
2121
|
-
}
|
|
2122
|
-
}
|
|
2123
|
-
}
|
|
2173
|
+
function readVmhd(view) {
|
|
2174
|
+
return {
|
|
2175
|
+
type: "vmhd",
|
|
2176
|
+
...view.readFullBox(),
|
|
2177
|
+
graphicsmode: view.readUint(2),
|
|
2178
|
+
opcolor: view.readArray(UINT, 2, 3)
|
|
2179
|
+
};
|
|
2124
2180
|
}
|
|
2125
2181
|
|
|
2126
2182
|
//#endregion
|
|
2127
|
-
//#region src/
|
|
2183
|
+
//#region src/readers/readVttC.ts
|
|
2128
2184
|
/**
|
|
2129
|
-
*
|
|
2185
|
+
* Parse a WebVTTConfigurationBox from an IsoView
|
|
2130
2186
|
*
|
|
2131
|
-
* @param
|
|
2187
|
+
* @param view - The IsoView to read data from
|
|
2132
2188
|
*
|
|
2133
|
-
* @returns
|
|
2189
|
+
* @returns A parsed WebVttConfigurationBox
|
|
2134
2190
|
*
|
|
2135
2191
|
* @public
|
|
2136
2192
|
*/
|
|
2137
|
-
function
|
|
2138
|
-
return
|
|
2193
|
+
function readVttC(view) {
|
|
2194
|
+
return {
|
|
2195
|
+
type: "vttC",
|
|
2196
|
+
config: view.readUtf8()
|
|
2197
|
+
};
|
|
2139
2198
|
}
|
|
2140
2199
|
|
|
2141
2200
|
//#endregion
|
|
2142
|
-
//#region src/
|
|
2201
|
+
//#region src/readers/readVtte.ts
|
|
2143
2202
|
/**
|
|
2144
|
-
*
|
|
2203
|
+
* Parse a WebVTT Empty Sample Box from an IsoView
|
|
2145
2204
|
*
|
|
2146
|
-
* @
|
|
2147
|
-
* @param config - The configuration for the readable stream
|
|
2205
|
+
* @returns A parsed WebVTT Empty Sample Box
|
|
2148
2206
|
*
|
|
2149
|
-
* @
|
|
2207
|
+
* @public
|
|
2208
|
+
*/
|
|
2209
|
+
function readVtte(_) {
|
|
2210
|
+
return { type: "vtte" };
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
//#endregion
|
|
2214
|
+
//#region src/utils/isFullBox.ts
|
|
2215
|
+
/**
|
|
2216
|
+
* Check if a box is a full box
|
|
2150
2217
|
*
|
|
2151
|
-
* @
|
|
2152
|
-
*
|
|
2218
|
+
* @param box - The box to check
|
|
2219
|
+
*
|
|
2220
|
+
* @returns `true` if the box is a full box, `false` otherwise
|
|
2153
2221
|
*
|
|
2154
2222
|
* @public
|
|
2155
2223
|
*/
|
|
2156
|
-
function
|
|
2157
|
-
|
|
2158
|
-
return Array.from(boxes, (box) => writeIsoBox(box, writers));
|
|
2224
|
+
function isFullBox(box) {
|
|
2225
|
+
return "version" in box && "flags" in box;
|
|
2159
2226
|
}
|
|
2160
2227
|
|
|
2161
2228
|
//#endregion
|
|
@@ -2176,6 +2243,45 @@ function writeArdi(box) {
|
|
|
2176
2243
|
return writer;
|
|
2177
2244
|
}
|
|
2178
2245
|
|
|
2246
|
+
//#endregion
|
|
2247
|
+
//#region src/writers/writeAudioSampleEntryBox.ts
|
|
2248
|
+
/**
|
|
2249
|
+
* Write an AudioSampleEntryBox to an IsoDataWriter.
|
|
2250
|
+
*
|
|
2251
|
+
* ISO/IEC 14496-12:2012 - 12.2.3 Audio Sample Entry
|
|
2252
|
+
*
|
|
2253
|
+
* @param box - The AudioSampleEntryBox fields to write
|
|
2254
|
+
* @param config - The IsoBoxWriteViewConfig to use
|
|
2255
|
+
*
|
|
2256
|
+
* @returns An IsoDataWriter containing the encoded box
|
|
2257
|
+
*
|
|
2258
|
+
* @public
|
|
2259
|
+
*/
|
|
2260
|
+
function writeAudioSampleEntryBox(box, config) {
|
|
2261
|
+
const headerSize = 8;
|
|
2262
|
+
const reserved1Size = 6;
|
|
2263
|
+
const dataReferenceIndexSize = 2;
|
|
2264
|
+
const reserved2Size = 8;
|
|
2265
|
+
const channelcountSize = 2;
|
|
2266
|
+
const samplesizeSize = 2;
|
|
2267
|
+
const preDefinedSize = 2;
|
|
2268
|
+
const reserved3Size = 2;
|
|
2269
|
+
const samplerateSize = 4;
|
|
2270
|
+
const { bytes, size } = writeChildBoxes(box.boxes, config);
|
|
2271
|
+
const totalSize = headerSize + reserved1Size + dataReferenceIndexSize + reserved2Size + channelcountSize + samplesizeSize + preDefinedSize + reserved3Size + samplerateSize + size;
|
|
2272
|
+
const writer = new IsoBoxWriteView(box.type, totalSize);
|
|
2273
|
+
writer.writeArray(box.reserved1, UINT, 1, 6);
|
|
2274
|
+
writer.writeUint(box.dataReferenceIndex, 2);
|
|
2275
|
+
writer.writeArray(box.reserved2, UINT, 4, 2);
|
|
2276
|
+
writer.writeUint(box.channelcount, 2);
|
|
2277
|
+
writer.writeUint(box.samplesize, 2);
|
|
2278
|
+
writer.writeUint(box.preDefined, 2);
|
|
2279
|
+
writer.writeUint(box.reserved3, 2);
|
|
2280
|
+
writer.writeTemplate(box.samplerate, 4);
|
|
2281
|
+
writer.writeBytes(bytes);
|
|
2282
|
+
return writer;
|
|
2283
|
+
}
|
|
2284
|
+
|
|
2179
2285
|
//#endregion
|
|
2180
2286
|
//#region src/writers/writeVisualSampleEntryBox.ts
|
|
2181
2287
|
/**
|
|
@@ -2184,13 +2290,13 @@ function writeArdi(box) {
|
|
|
2184
2290
|
* ISO/IEC 14496-12:2012 - 12.1.3 Visual Sample Entry
|
|
2185
2291
|
*
|
|
2186
2292
|
* @param box - The VisualSampleEntryBox fields to write
|
|
2187
|
-
* @param
|
|
2293
|
+
* @param config - The configuration for the writer
|
|
2188
2294
|
*
|
|
2189
2295
|
* @returns An IsoDataWriter containing the encoded box
|
|
2190
2296
|
*
|
|
2191
2297
|
* @public
|
|
2192
2298
|
*/
|
|
2193
|
-
function writeVisualSampleEntryBox(box,
|
|
2299
|
+
function writeVisualSampleEntryBox(box, config) {
|
|
2194
2300
|
const headerSize = 8;
|
|
2195
2301
|
const reserved1Size = 6;
|
|
2196
2302
|
const dataReferenceIndexSize = 2;
|
|
@@ -2206,23 +2312,24 @@ function writeVisualSampleEntryBox(box, type) {
|
|
|
2206
2312
|
const compressorNameSize = 32;
|
|
2207
2313
|
const depthSize = 2;
|
|
2208
2314
|
const preDefined3Size = 2;
|
|
2209
|
-
const
|
|
2210
|
-
const
|
|
2211
|
-
|
|
2315
|
+
const { bytes, size } = writeChildBoxes(box.boxes, config);
|
|
2316
|
+
const totalSize = headerSize + reserved1Size + dataReferenceIndexSize + preDefined1Size + reserved2Size + preDefined2Size + widthSize + heightSize + horizresolutionSize + vertresolutionSize + reserved3Size + frameCountSize + compressorNameSize + depthSize + preDefined3Size + size;
|
|
2317
|
+
const writer = new IsoBoxWriteView(box.type, totalSize);
|
|
2318
|
+
writer.writeArray(box.reserved1, UINT, 1, 6);
|
|
2212
2319
|
writer.writeUint(box.dataReferenceIndex, 2);
|
|
2213
2320
|
writer.writeUint(box.preDefined1, 2);
|
|
2214
2321
|
writer.writeUint(box.reserved2, 2);
|
|
2215
|
-
|
|
2322
|
+
writer.writeArray(box.preDefined2, UINT, 4, 3);
|
|
2216
2323
|
writer.writeUint(box.width, 2);
|
|
2217
2324
|
writer.writeUint(box.height, 2);
|
|
2218
2325
|
writer.writeTemplate(box.horizresolution, 4);
|
|
2219
2326
|
writer.writeTemplate(box.vertresolution, 4);
|
|
2220
2327
|
writer.writeUint(box.reserved3, 4);
|
|
2221
2328
|
writer.writeUint(box.frameCount, 2);
|
|
2222
|
-
|
|
2329
|
+
writer.writeArray(box.compressorName, UINT, 1, 32);
|
|
2223
2330
|
writer.writeUint(box.depth, 2);
|
|
2224
2331
|
writer.writeUint(box.preDefined3 & 65535, 2);
|
|
2225
|
-
writer.writeBytes(
|
|
2332
|
+
writer.writeBytes(bytes);
|
|
2226
2333
|
return writer;
|
|
2227
2334
|
}
|
|
2228
2335
|
|
|
@@ -2234,13 +2341,14 @@ function writeVisualSampleEntryBox(box, type) {
|
|
|
2234
2341
|
* ISO/IEC 14496-12:2012 - 12.1.3 Visual Sample Entry
|
|
2235
2342
|
*
|
|
2236
2343
|
* @param box - The VisualSampleEntryBox fields to write
|
|
2344
|
+
* @param config - The IsoBoxWriteViewConfig to use
|
|
2237
2345
|
*
|
|
2238
2346
|
* @returns An IsoDataWriter containing the encoded box
|
|
2239
2347
|
*
|
|
2240
2348
|
* @public
|
|
2241
2349
|
*/
|
|
2242
|
-
function writeAvc1(box) {
|
|
2243
|
-
return writeVisualSampleEntryBox(box,
|
|
2350
|
+
function writeAvc1(box, config) {
|
|
2351
|
+
return writeVisualSampleEntryBox(box, config);
|
|
2244
2352
|
}
|
|
2245
2353
|
|
|
2246
2354
|
//#endregion
|
|
@@ -2249,13 +2357,14 @@ function writeAvc1(box) {
|
|
|
2249
2357
|
* Write a VisualSampleEntryBox (avc2) to an IsoDataWriter.
|
|
2250
2358
|
*
|
|
2251
2359
|
* @param box - The VisualSampleEntryBox fields to write
|
|
2360
|
+
* @param config - The IsoBoxWriteViewConfig to use
|
|
2252
2361
|
*
|
|
2253
2362
|
* @returns An IsoDataWriter containing the encoded box
|
|
2254
2363
|
*
|
|
2255
2364
|
* @public
|
|
2256
2365
|
*/
|
|
2257
|
-
function writeAvc2(box) {
|
|
2258
|
-
return writeVisualSampleEntryBox(box,
|
|
2366
|
+
function writeAvc2(box, config) {
|
|
2367
|
+
return writeVisualSampleEntryBox(box, config);
|
|
2259
2368
|
}
|
|
2260
2369
|
|
|
2261
2370
|
//#endregion
|
|
@@ -2264,13 +2373,14 @@ function writeAvc2(box) {
|
|
|
2264
2373
|
* Write a VisualSampleEntryBox (avc3) to an IsoDataWriter.
|
|
2265
2374
|
*
|
|
2266
2375
|
* @param box - The VisualSampleEntryBox fields to write
|
|
2376
|
+
* @param config - The IsoBoxWriteViewConfig to use
|
|
2267
2377
|
*
|
|
2268
2378
|
* @returns An IsoDataWriter containing the encoded box
|
|
2269
2379
|
*
|
|
2270
2380
|
* @public
|
|
2271
2381
|
*/
|
|
2272
|
-
function writeAvc3(box) {
|
|
2273
|
-
return writeVisualSampleEntryBox(box,
|
|
2382
|
+
function writeAvc3(box, config) {
|
|
2383
|
+
return writeVisualSampleEntryBox(box, config);
|
|
2274
2384
|
}
|
|
2275
2385
|
|
|
2276
2386
|
//#endregion
|
|
@@ -2279,13 +2389,14 @@ function writeAvc3(box) {
|
|
|
2279
2389
|
* Write a VisualSampleEntryBox (avc4) to an IsoDataWriter.
|
|
2280
2390
|
*
|
|
2281
2391
|
* @param box - The VisualSampleEntryBox fields to write
|
|
2392
|
+
* @param config - The IsoBoxWriteViewConfig to use
|
|
2282
2393
|
*
|
|
2283
2394
|
* @returns An IsoDataWriter containing the encoded box
|
|
2284
2395
|
*
|
|
2285
2396
|
* @public
|
|
2286
2397
|
*/
|
|
2287
|
-
function writeAvc4(box) {
|
|
2288
|
-
return writeVisualSampleEntryBox(box,
|
|
2398
|
+
function writeAvc4(box, config) {
|
|
2399
|
+
return writeVisualSampleEntryBox(box, config);
|
|
2289
2400
|
}
|
|
2290
2401
|
|
|
2291
2402
|
//#endregion
|
|
@@ -2316,6 +2427,31 @@ function writeCtts(box) {
|
|
|
2316
2427
|
return writer;
|
|
2317
2428
|
}
|
|
2318
2429
|
|
|
2430
|
+
//#endregion
|
|
2431
|
+
//#region src/writers/writeDref.ts
|
|
2432
|
+
/**
|
|
2433
|
+
* Write a DataReferenceBox to an IsoDataWriter.
|
|
2434
|
+
*
|
|
2435
|
+
* @param box - The DataReferenceBox fields to write
|
|
2436
|
+
* @param config - The IsoBoxWriteViewConfig to use
|
|
2437
|
+
*
|
|
2438
|
+
* @returns An IsoDataWriter containing the encoded box
|
|
2439
|
+
*
|
|
2440
|
+
* @public
|
|
2441
|
+
*/
|
|
2442
|
+
function writeDref(box, config) {
|
|
2443
|
+
const headerSize = 8;
|
|
2444
|
+
const fullBoxSize = 4;
|
|
2445
|
+
const entryCountSize = 4;
|
|
2446
|
+
const entryCount = box.entries.length;
|
|
2447
|
+
const { bytes, size } = writeChildBoxes(box.entries, config);
|
|
2448
|
+
const writer = new IsoBoxWriteView("dref", headerSize + fullBoxSize + entryCountSize + size);
|
|
2449
|
+
writer.writeFullBox(box.version, box.flags);
|
|
2450
|
+
writer.writeUint(entryCount, 4);
|
|
2451
|
+
writer.writeBytes(bytes);
|
|
2452
|
+
return writer;
|
|
2453
|
+
}
|
|
2454
|
+
|
|
2319
2455
|
//#endregion
|
|
2320
2456
|
//#region src/writers/writeElng.ts
|
|
2321
2457
|
/**
|
|
@@ -2418,33 +2554,14 @@ function writeEmsg(box) {
|
|
|
2418
2554
|
* Write an AudioSampleEntryBox (enca) to an IsoDataWriter.
|
|
2419
2555
|
*
|
|
2420
2556
|
* @param box - The AudioSampleEntryBox fields to write
|
|
2557
|
+
* @param config - The IsoBoxWriteViewConfig to use
|
|
2421
2558
|
*
|
|
2422
2559
|
* @returns An IsoDataWriter containing the encoded box
|
|
2423
2560
|
*
|
|
2424
2561
|
* @public
|
|
2425
2562
|
*/
|
|
2426
|
-
function writeEnca(box) {
|
|
2427
|
-
|
|
2428
|
-
const reserved1Size = 6;
|
|
2429
|
-
const dataReferenceIndexSize = 2;
|
|
2430
|
-
const reserved2Size = 8;
|
|
2431
|
-
const channelcountSize = 2;
|
|
2432
|
-
const samplesizeSize = 2;
|
|
2433
|
-
const preDefinedSize = 2;
|
|
2434
|
-
const reserved3Size = 2;
|
|
2435
|
-
const samplerateSize = 4;
|
|
2436
|
-
const esdsSize = box.esds.length;
|
|
2437
|
-
const writer = new IsoBoxWriteView("enca", headerSize + reserved1Size + dataReferenceIndexSize + reserved2Size + channelcountSize + samplesizeSize + preDefinedSize + reserved3Size + samplerateSize + esdsSize);
|
|
2438
|
-
for (let i = 0; i < 6; i++) writer.writeUint(box.reserved1[i] ?? 0, 1);
|
|
2439
|
-
writer.writeUint(box.dataReferenceIndex, 2);
|
|
2440
|
-
for (let i = 0; i < 2; i++) writer.writeUint(box.reserved2[i] ?? 0, 4);
|
|
2441
|
-
writer.writeUint(box.channelcount, 2);
|
|
2442
|
-
writer.writeUint(box.samplesize, 2);
|
|
2443
|
-
writer.writeUint(box.preDefined, 2);
|
|
2444
|
-
writer.writeUint(box.reserved3, 2);
|
|
2445
|
-
writer.writeTemplate(box.samplerate, 4);
|
|
2446
|
-
writer.writeBytes(box.esds);
|
|
2447
|
-
return writer;
|
|
2563
|
+
function writeEnca(box, config) {
|
|
2564
|
+
return writeAudioSampleEntryBox(box, config);
|
|
2448
2565
|
}
|
|
2449
2566
|
|
|
2450
2567
|
//#endregion
|
|
@@ -2453,13 +2570,14 @@ function writeEnca(box) {
|
|
|
2453
2570
|
* Write a VisualSampleEntryBox (encv) to an IsoDataWriter.
|
|
2454
2571
|
*
|
|
2455
2572
|
* @param box - The VisualSampleEntryBox fields to write
|
|
2573
|
+
* @param config - The IsoBoxWriteViewConfig to use
|
|
2456
2574
|
*
|
|
2457
2575
|
* @returns An IsoDataWriter containing the encoded box
|
|
2458
2576
|
*
|
|
2459
2577
|
* @public
|
|
2460
2578
|
*/
|
|
2461
|
-
function writeEncv(box) {
|
|
2462
|
-
return writeVisualSampleEntryBox(box,
|
|
2579
|
+
function writeEncv(box, config) {
|
|
2580
|
+
return writeVisualSampleEntryBox(box, config);
|
|
2463
2581
|
}
|
|
2464
2582
|
|
|
2465
2583
|
//#endregion
|
|
@@ -2549,7 +2667,7 @@ function writeHdlr(box) {
|
|
|
2549
2667
|
writer.writeFullBox(box.version, box.flags);
|
|
2550
2668
|
writer.writeUint(box.preDefined, 4);
|
|
2551
2669
|
writer.writeString(box.handlerType);
|
|
2552
|
-
|
|
2670
|
+
writer.writeArray(box.reserved, UINT, 4, 3);
|
|
2553
2671
|
writer.writeTerminatedString(box.name);
|
|
2554
2672
|
return writer;
|
|
2555
2673
|
}
|
|
@@ -2560,13 +2678,14 @@ function writeHdlr(box) {
|
|
|
2560
2678
|
* Write a VisualSampleEntryBox (hev1) to an IsoDataWriter.
|
|
2561
2679
|
*
|
|
2562
2680
|
* @param box - The VisualSampleEntryBox fields to write
|
|
2681
|
+
* @param config - The IsoBoxWriteViewConfig to use
|
|
2563
2682
|
*
|
|
2564
2683
|
* @returns An IsoDataWriter containing the encoded box
|
|
2565
2684
|
*
|
|
2566
2685
|
* @public
|
|
2567
2686
|
*/
|
|
2568
|
-
function writeHev1(box) {
|
|
2569
|
-
return writeVisualSampleEntryBox(box,
|
|
2687
|
+
function writeHev1(box, config) {
|
|
2688
|
+
return writeVisualSampleEntryBox(box, config);
|
|
2570
2689
|
}
|
|
2571
2690
|
|
|
2572
2691
|
//#endregion
|
|
@@ -2575,13 +2694,14 @@ function writeHev1(box) {
|
|
|
2575
2694
|
* Write a VisualSampleEntryBox (hvc1) to an IsoDataWriter.
|
|
2576
2695
|
*
|
|
2577
2696
|
* @param box - The VisualSampleEntryBox fields to write
|
|
2697
|
+
* @param config - The IsoBoxWriteViewConfig to use
|
|
2578
2698
|
*
|
|
2579
2699
|
* @returns An IsoDataWriter containing the encoded box
|
|
2580
2700
|
*
|
|
2581
2701
|
* @public
|
|
2582
2702
|
*/
|
|
2583
|
-
function writeHvc1(box) {
|
|
2584
|
-
return writeVisualSampleEntryBox(box,
|
|
2703
|
+
function writeHvc1(box, config) {
|
|
2704
|
+
return writeVisualSampleEntryBox(box, config);
|
|
2585
2705
|
}
|
|
2586
2706
|
|
|
2587
2707
|
//#endregion
|
|
@@ -2755,14 +2875,19 @@ function writeMehd(box) {
|
|
|
2755
2875
|
* ISO/IEC 14496-12:2012 - 8.11.1 Meta Box
|
|
2756
2876
|
*
|
|
2757
2877
|
* @param box - The MetaBox fields to write
|
|
2878
|
+
* @param config - The IsoBoxWriteViewConfig to use
|
|
2758
2879
|
*
|
|
2759
2880
|
* @returns An IsoDataWriter containing the encoded box
|
|
2760
2881
|
*
|
|
2761
2882
|
* @public
|
|
2762
2883
|
*/
|
|
2763
|
-
function writeMeta(box) {
|
|
2764
|
-
const
|
|
2884
|
+
function writeMeta(box, config) {
|
|
2885
|
+
const headerSize = 8;
|
|
2886
|
+
const fullBoxSize = 4;
|
|
2887
|
+
const { bytes, size } = writeChildBoxes(box.boxes, config);
|
|
2888
|
+
const writer = new IsoBoxWriteView("meta", headerSize + fullBoxSize + size);
|
|
2765
2889
|
writer.writeFullBox(box.version, box.flags);
|
|
2890
|
+
writer.writeBytes(bytes);
|
|
2766
2891
|
return writer;
|
|
2767
2892
|
}
|
|
2768
2893
|
|
|
@@ -2819,28 +2944,8 @@ function writeMfro(box) {
|
|
|
2819
2944
|
*
|
|
2820
2945
|
* @public
|
|
2821
2946
|
*/
|
|
2822
|
-
function writeMp4a(box) {
|
|
2823
|
-
|
|
2824
|
-
const reserved1Size = 6;
|
|
2825
|
-
const dataReferenceIndexSize = 2;
|
|
2826
|
-
const reserved2Size = 8;
|
|
2827
|
-
const channelcountSize = 2;
|
|
2828
|
-
const samplesizeSize = 2;
|
|
2829
|
-
const preDefinedSize = 2;
|
|
2830
|
-
const reserved3Size = 2;
|
|
2831
|
-
const samplerateSize = 4;
|
|
2832
|
-
const esdsSize = box.esds.length;
|
|
2833
|
-
const writer = new IsoBoxWriteView("mp4a", headerSize + reserved1Size + dataReferenceIndexSize + reserved2Size + channelcountSize + samplesizeSize + preDefinedSize + reserved3Size + samplerateSize + esdsSize);
|
|
2834
|
-
for (let i = 0; i < 6; i++) writer.writeUint(box.reserved1[i] ?? 0, 1);
|
|
2835
|
-
writer.writeUint(box.dataReferenceIndex, 2);
|
|
2836
|
-
for (let i = 0; i < 2; i++) writer.writeUint(box.reserved2[i] ?? 0, 4);
|
|
2837
|
-
writer.writeUint(box.channelcount, 2);
|
|
2838
|
-
writer.writeUint(box.samplesize, 2);
|
|
2839
|
-
writer.writeUint(box.preDefined, 2);
|
|
2840
|
-
writer.writeUint(box.reserved3, 2);
|
|
2841
|
-
writer.writeTemplate(box.samplerate, 4);
|
|
2842
|
-
writer.writeBytes(box.esds);
|
|
2843
|
-
return writer;
|
|
2947
|
+
function writeMp4a(box, config) {
|
|
2948
|
+
return writeAudioSampleEntryBox(box, config);
|
|
2844
2949
|
}
|
|
2845
2950
|
|
|
2846
2951
|
//#endregion
|
|
@@ -2870,9 +2975,9 @@ function writeMvhd(box) {
|
|
|
2870
2975
|
writer.writeTemplate(box.rate, 4);
|
|
2871
2976
|
writer.writeTemplate(box.volume, 2);
|
|
2872
2977
|
writer.writeUint(box.reserved1, 2);
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2978
|
+
writer.writeArray(box.reserved2, UINT, 4, 2);
|
|
2979
|
+
writer.writeArray(box.matrix, TEMPLATE, 4, 9);
|
|
2980
|
+
writer.writeArray(box.preDefined, UINT, 4, 6);
|
|
2876
2981
|
writer.writeUint(box.nextTrackId, 4);
|
|
2877
2982
|
return writer;
|
|
2878
2983
|
}
|
|
@@ -2924,12 +3029,13 @@ function writePrft(box) {
|
|
|
2924
3029
|
* Write a PreselectionGroupBox to an IsoDataWriter.
|
|
2925
3030
|
*
|
|
2926
3031
|
* @param box - The PreselectionGroupBox fields to write
|
|
3032
|
+
* @param config - The IsoBoxWriteViewConfig to use
|
|
2927
3033
|
*
|
|
2928
3034
|
* @returns An IsoDataWriter containing the encoded box
|
|
2929
3035
|
*
|
|
2930
3036
|
* @public
|
|
2931
3037
|
*/
|
|
2932
|
-
function writePrsl(box) {
|
|
3038
|
+
function writePrsl(box, config) {
|
|
2933
3039
|
const preselectionTagBytes = box.flags & 4096 && box.preselectionTag ? encodeText(box.preselectionTag) : null;
|
|
2934
3040
|
const interleavingTagBytes = box.flags & 16384 && box.interleavingTag ? encodeText(box.interleavingTag) : null;
|
|
2935
3041
|
const headerSize = 8;
|
|
@@ -2940,7 +3046,8 @@ function writePrsl(box) {
|
|
|
2940
3046
|
const preselectionTagSize = preselectionTagBytes ? preselectionTagBytes.length + 1 : 0;
|
|
2941
3047
|
const selectionPrioritySize = box.flags & 8192 ? 1 : 0;
|
|
2942
3048
|
const interleavingTagSize = interleavingTagBytes ? interleavingTagBytes.length + 1 : 0;
|
|
2943
|
-
const
|
|
3049
|
+
const { bytes, size } = writeChildBoxes(box.boxes, config);
|
|
3050
|
+
const writer = new IsoBoxWriteView("prsl", headerSize + fullBoxSize + groupIdSize + numEntitiesInGroupSize + entitiesSize + preselectionTagSize + selectionPrioritySize + interleavingTagSize + size);
|
|
2944
3051
|
writer.writeFullBox(box.version, box.flags);
|
|
2945
3052
|
writer.writeUint(box.groupId, 4);
|
|
2946
3053
|
writer.writeUint(box.numEntitiesInGroup, 4);
|
|
@@ -2948,6 +3055,7 @@ function writePrsl(box) {
|
|
|
2948
3055
|
if (preselectionTagBytes && box.preselectionTag) writer.writeUtf8TerminatedString(box.preselectionTag);
|
|
2949
3056
|
if (box.flags & 8192) writer.writeUint(box.selectionPriority ?? 0, 1);
|
|
2950
3057
|
if (interleavingTagBytes && box.interleavingTag) writer.writeUtf8TerminatedString(box.interleavingTag);
|
|
3058
|
+
writer.writeBytes(bytes);
|
|
2951
3059
|
return writer;
|
|
2952
3060
|
}
|
|
2953
3061
|
|
|
@@ -2974,13 +3082,13 @@ function writePssh(box) {
|
|
|
2974
3082
|
const dataSize = box.dataSize;
|
|
2975
3083
|
const writer = new IsoBoxWriteView("pssh", headerSize + fullBoxSize + systemIdSize + kidCountSize + kidSize + dataSizeField + dataSize);
|
|
2976
3084
|
writer.writeFullBox(box.version, box.flags);
|
|
2977
|
-
|
|
3085
|
+
writer.writeArray(box.systemId, UINT, 1, 16);
|
|
2978
3086
|
if (box.version > 0) {
|
|
2979
3087
|
writer.writeUint(box.kidCount, 4);
|
|
2980
|
-
|
|
3088
|
+
writer.writeArray(box.kid, UINT, 1, box.kidCount);
|
|
2981
3089
|
}
|
|
2982
3090
|
writer.writeUint(box.dataSize, 4);
|
|
2983
|
-
|
|
3091
|
+
writer.writeArray(box.data, UINT, 1, box.dataSize);
|
|
2984
3092
|
return writer;
|
|
2985
3093
|
}
|
|
2986
3094
|
|
|
@@ -3170,6 +3278,31 @@ function writeSthd(box) {
|
|
|
3170
3278
|
return writer;
|
|
3171
3279
|
}
|
|
3172
3280
|
|
|
3281
|
+
//#endregion
|
|
3282
|
+
//#region src/writers/writeStsd.ts
|
|
3283
|
+
/**
|
|
3284
|
+
* Write a SampleDescriptionBox to an IsoDataWriter.
|
|
3285
|
+
*
|
|
3286
|
+
* @param box - The SampleDescriptionBox fields to write
|
|
3287
|
+
* @param config - The IsoBoxWriteViewConfig to use
|
|
3288
|
+
*
|
|
3289
|
+
* @returns An IsoDataWriter containing the encoded box
|
|
3290
|
+
*
|
|
3291
|
+
* @public
|
|
3292
|
+
*/
|
|
3293
|
+
function writeStsd(box, config) {
|
|
3294
|
+
const headerSize = 8;
|
|
3295
|
+
const fullBoxSize = 4;
|
|
3296
|
+
const entryCountSize = 4;
|
|
3297
|
+
const entryCount = box.entries.length;
|
|
3298
|
+
const { bytes, size } = writeChildBoxes(box.entries, config);
|
|
3299
|
+
const writer = new IsoBoxWriteView("stsd", headerSize + fullBoxSize + entryCountSize + size);
|
|
3300
|
+
writer.writeFullBox(box.version, box.flags);
|
|
3301
|
+
writer.writeUint(entryCount, 4);
|
|
3302
|
+
writer.writeBytes(bytes);
|
|
3303
|
+
return writer;
|
|
3304
|
+
}
|
|
3305
|
+
|
|
3173
3306
|
//#endregion
|
|
3174
3307
|
//#region src/writers/writeStss.ts
|
|
3175
3308
|
/**
|
|
@@ -3320,7 +3453,7 @@ function writeTenc(box) {
|
|
|
3320
3453
|
writer.writeFullBox(box.version, box.flags);
|
|
3321
3454
|
writer.writeUint(box.defaultIsEncrypted, 3);
|
|
3322
3455
|
writer.writeUint(box.defaultIvSize, 1);
|
|
3323
|
-
|
|
3456
|
+
writer.writeArray(box.defaultKid, UINT, 1, 16);
|
|
3324
3457
|
return writer;
|
|
3325
3458
|
}
|
|
3326
3459
|
|
|
@@ -3444,12 +3577,12 @@ function writeTkhd(box) {
|
|
|
3444
3577
|
writer.writeUint(box.trackId, 4);
|
|
3445
3578
|
writer.writeUint(box.reserved1, 4);
|
|
3446
3579
|
writer.writeUint(box.duration, size);
|
|
3447
|
-
|
|
3580
|
+
writer.writeArray(box.reserved2, UINT, 4, 2);
|
|
3448
3581
|
writer.writeUint(box.layer, 2);
|
|
3449
3582
|
writer.writeUint(box.alternateGroup, 2);
|
|
3450
3583
|
writer.writeTemplate(box.volume, 2);
|
|
3451
3584
|
writer.writeUint(box.reserved3, 2);
|
|
3452
|
-
|
|
3585
|
+
writer.writeArray(box.matrix, TEMPLATE, 4, 9);
|
|
3453
3586
|
writer.writeTemplate(box.width, 4);
|
|
3454
3587
|
writer.writeTemplate(box.height, 4);
|
|
3455
3588
|
return writer;
|
|
@@ -3600,7 +3733,7 @@ function writeVmhd(box) {
|
|
|
3600
3733
|
const writer = new IsoBoxWriteView("vmhd", 20);
|
|
3601
3734
|
writer.writeFullBox(box.version, box.flags);
|
|
3602
3735
|
writer.writeUint(box.graphicsmode, 2);
|
|
3603
|
-
|
|
3736
|
+
writer.writeArray(box.opcolor, UINT, 2, 3);
|
|
3604
3737
|
return writer;
|
|
3605
3738
|
}
|
|
3606
3739
|
|
|
@@ -3636,5 +3769,5 @@ function writeVtte(_) {
|
|
|
3636
3769
|
}
|
|
3637
3770
|
|
|
3638
3771
|
//#endregion
|
|
3639
|
-
export { IsoBoxReadableStream, createIsoBoxReadableStream, isContainer, isFullBox, readArdi, readAvc1, readAvc2, readAvc3, readAvc4, readCtts, readDref, readElng, readElst, readEmsg, readEnca, readEncv, readFree, readFrma, readFtyp, readHdlr, readHev1, readHvc1, readIden, readImda, readIsoBoxes, readKind, readLabl, readMdat, readMdhd, readMehd, readMeta, readMfhd, readMfro, readMp4a, readMvhd, readPayl, readPrft, readPrsl, readPssh, readSchm, readSdtp, readSidx, readSkip, readSmhd, readSsix, readSthd, readStsd, readStss, readSttg, readStts, readStyp, readSubs, readTenc, readTfdt, readTfhd, readTfra, readTkhd, readTrex, readTrun, readUrl, readUrn, readVlab, readVmhd, readVttC, readVtte, traverseIsoBoxes, writeArdi, writeAvc1, writeAvc2, writeAvc3, writeAvc4, writeCtts, writeElng, writeElst, writeEmsg, writeEnca, writeEncv, writeFree, writeFrma, writeFtyp, writeHdlr, writeHev1, writeHvc1, writeIden, writeImda, writeIsoBox, writeIsoBoxes, writeKind, writeLabl, writeMdat, writeMdhd, writeMehd, writeMeta, writeMfhd, writeMfro, writeMp4a, writeMvhd, writePayl, writePrft, writePrsl, writePssh, writeSchm, writeSdtp, writeSidx, writeSkip, writeSmhd, writeSsix, writeSthd, writeStss, writeSttg, writeStts, writeStyp, writeSubs, writeTenc, writeTfdt, writeTfhd, writeTfra, writeTkhd, writeTrex, writeTrun, writeUrl, writeUrn, writeVisualSampleEntryBox, writeVlab, writeVmhd, writeVttC, writeVtte };
|
|
3772
|
+
export { CONTAINERS, IsoBoxReadableStream, createIsoBoxReadableStream, isContainer, isFullBox, readArdi, readAudioSampleEntryBox, readAvc1, readAvc2, readAvc3, readAvc4, readCtts, readDref, readElng, readElst, readEmsg, readEnca, readEncv, readFree, readFrma, readFtyp, readHdlr, readHev1, readHvc1, readIden, readImda, readIsoBoxes, readKind, readLabl, readMdat, readMdhd, readMehd, readMeta, readMfhd, readMfro, readMp4a, readMvhd, readPayl, readPrft, readPrsl, readPssh, readSchm, readSdtp, readSidx, readSkip, readSmhd, readSsix, readSthd, readStsd, readStss, readSttg, readStts, readStyp, readSubs, readTenc, readTfdt, readTfhd, readTfra, readTkhd, readTrex, readTrun, readUrl, readUrn, readVisualSampleEntryBox, readVlab, readVmhd, readVttC, readVtte, traverseIsoBoxes, writeArdi, writeAudioSampleEntryBox, writeAvc1, writeAvc2, writeAvc3, writeAvc4, writeCtts, writeDref, writeElng, writeElst, writeEmsg, writeEnca, writeEncv, writeFree, writeFrma, writeFtyp, writeHdlr, writeHev1, writeHvc1, writeIden, writeImda, writeIsoBox, writeIsoBoxes, writeKind, writeLabl, writeMdat, writeMdhd, writeMehd, writeMeta, writeMfhd, writeMfro, writeMp4a, writeMvhd, writePayl, writePrft, writePrsl, writePssh, writeSchm, writeSdtp, writeSidx, writeSkip, writeSmhd, writeSsix, writeSthd, writeStsd, writeStss, writeSttg, writeStts, writeStyp, writeSubs, writeTenc, writeTfdt, writeTfhd, writeTfra, writeTkhd, writeTrex, writeTrun, writeUrl, writeUrn, writeVisualSampleEntryBox, writeVlab, writeVmhd, writeVttC, writeVtte };
|
|
3640
3773
|
//# sourceMappingURL=index.js.map
|