@remotion/media-parser 4.0.199 → 4.0.201

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/dist/av1-codec-string.d.ts +5 -0
  2. package/dist/av1-codec-string.js +18 -1
  3. package/dist/bitstream/av1.d.ts +2 -0
  4. package/dist/bitstream/av1.js +12 -0
  5. package/dist/boxes/iso-base-media/avcc-hvcc.d.ts +20 -0
  6. package/dist/boxes/iso-base-media/avcc-hvcc.js +73 -0
  7. package/dist/boxes/iso-base-media/avcc.d.ts +18 -0
  8. package/dist/boxes/iso-base-media/avcc.js +27 -0
  9. package/dist/boxes/iso-base-media/esds-descriptors.d.ts +21 -0
  10. package/dist/boxes/iso-base-media/esds-descriptors.js +62 -0
  11. package/dist/boxes/iso-base-media/esds.d.ts +15 -0
  12. package/dist/boxes/iso-base-media/esds.js +27 -0
  13. package/dist/boxes/iso-base-media/mdat/mdat.js +2 -2
  14. package/dist/boxes/iso-base-media/moov/moov.js +1 -0
  15. package/dist/boxes/iso-base-media/process-box.d.ts +4 -2
  16. package/dist/boxes/iso-base-media/process-box.js +56 -40
  17. package/dist/boxes/iso-base-media/stsd/mebx.d.ts +2 -1
  18. package/dist/boxes/iso-base-media/stsd/mebx.js +2 -1
  19. package/dist/boxes/iso-base-media/stsd/samples.js +3 -0
  20. package/dist/boxes/iso-base-media/stsd/stco.d.ts +3 -2
  21. package/dist/boxes/iso-base-media/stsd/stco.js +2 -2
  22. package/dist/boxes/iso-base-media/trak/trak.js +1 -0
  23. package/dist/boxes/webm/bitstream/av1.js +10 -1
  24. package/dist/boxes/webm/ebml.d.ts +2 -0
  25. package/dist/boxes/webm/ebml.js +72 -0
  26. package/dist/boxes/webm/make-header.d.ts +9 -0
  27. package/dist/boxes/webm/make-header.js +79 -0
  28. package/dist/boxes/webm/parse-ebml.d.ts +7 -0
  29. package/dist/boxes/webm/parse-ebml.js +66 -0
  30. package/dist/boxes/webm/parse-webm-header.js +8 -9
  31. package/dist/boxes/webm/segments/all-segments.d.ts +262 -0
  32. package/dist/boxes/webm/segments/all-segments.js +130 -1
  33. package/dist/boxes/webm/segments/block-simple-block-flags.d.ts +9 -0
  34. package/dist/boxes/webm/segments/block-simple-block-flags.js +38 -0
  35. package/dist/boxes/webm/segments/seek-position.js +1 -1
  36. package/dist/boxes/webm/segments/seek.d.ts +1 -1
  37. package/dist/boxes/webm/segments/seek.js +8 -2
  38. package/dist/boxes/webm/segments/timestamp-scale.js +1 -1
  39. package/dist/boxes/webm/segments/track-entry.d.ts +25 -9
  40. package/dist/boxes/webm/segments/track-entry.js +73 -33
  41. package/dist/boxes/webm/segments.d.ts +3 -3
  42. package/dist/boxes/webm/segments.js +64 -30
  43. package/dist/boxes/webm/traversal.d.ts +1 -0
  44. package/dist/boxes/webm/traversal.js +12 -1
  45. package/dist/buffer-iterator.d.ts +10 -6
  46. package/dist/buffer-iterator.js +92 -9
  47. package/dist/from-fetch.js +13 -3
  48. package/dist/from-input-type-file.d.ts +2 -0
  49. package/dist/from-input-type-file.js +37 -0
  50. package/dist/from-node.js +9 -2
  51. package/dist/from-web-file.js +6 -1
  52. package/dist/from-web.js +15 -6
  53. package/dist/get-codec.d.ts +4 -0
  54. package/dist/get-codec.js +22 -0
  55. package/dist/get-sample-positions.js +1 -1
  56. package/dist/has-all-info.js +1 -1
  57. package/dist/options.d.ts +3 -2
  58. package/dist/parse-media.js +13 -9
  59. package/dist/parse-video.js +16 -0
  60. package/dist/parser-state.d.ts +8 -9
  61. package/dist/parser-state.js +39 -19
  62. package/dist/reader.d.ts +1 -1
  63. package/dist/web-file.d.ts +2 -0
  64. package/dist/web-file.js +37 -0
  65. package/dist/webcodec-sample-types.d.ts +0 -1
  66. package/package.json +2 -2
  67. package/src/boxes/iso-base-media/mdat/mdat.ts +2 -2
  68. package/src/boxes/iso-base-media/moov/moov.ts +1 -0
  69. package/src/boxes/iso-base-media/process-box.ts +70 -40
  70. package/src/boxes/iso-base-media/stsd/mebx.ts +3 -0
  71. package/src/boxes/iso-base-media/stsd/samples.ts +3 -0
  72. package/src/boxes/iso-base-media/stsd/stco.ts +5 -3
  73. package/src/boxes/iso-base-media/trak/trak.ts +1 -0
  74. package/src/boxes/webm/ebml.ts +78 -0
  75. package/src/boxes/webm/make-header.ts +138 -0
  76. package/src/boxes/webm/parse-ebml.ts +93 -0
  77. package/src/boxes/webm/parse-webm-header.ts +8 -12
  78. package/src/boxes/webm/segments/all-segments.ts +226 -0
  79. package/src/boxes/webm/segments/block-simple-block-flags.ts +52 -0
  80. package/src/boxes/webm/segments/seek-position.ts +1 -1
  81. package/src/boxes/webm/segments/seek.ts +12 -2
  82. package/src/boxes/webm/segments/timestamp-scale.ts +1 -1
  83. package/src/boxes/webm/segments/track-entry.ts +125 -41
  84. package/src/boxes/webm/segments.ts +107 -40
  85. package/src/boxes/webm/traversal.ts +13 -0
  86. package/src/buffer-iterator.ts +110 -10
  87. package/src/from-fetch.ts +22 -3
  88. package/src/from-node.ts +18 -4
  89. package/src/from-web-file.ts +11 -1
  90. package/src/get-sample-positions.ts +1 -1
  91. package/src/has-all-info.ts +1 -1
  92. package/src/options.ts +3 -2
  93. package/src/parse-media.ts +14 -8
  94. package/src/parse-video.ts +17 -0
  95. package/src/parser-state.ts +52 -25
  96. package/src/reader.ts +1 -0
  97. package/src/test/create-matroska.test.ts +48 -0
  98. package/src/test/matroska.test.ts +144 -127
  99. package/src/test/parse-stco.test.ts +2 -0
  100. package/src/test/stream-local.test.ts +70 -14
  101. package/src/test/stream-remote.test.ts +23 -19
  102. package/src/test/stsd.test.ts +2 -0
  103. package/src/webcodec-sample-types.ts +0 -1
  104. package/tsconfig.tsbuildinfo +1 -1
  105. package/dist/boxes/iso-base-media/ftype.d.ts +0 -9
  106. package/dist/boxes/iso-base-media/ftype.js +0 -31
  107. package/dist/get-video-metadata.d.ts +0 -2
  108. package/dist/get-video-metadata.js +0 -44
  109. package/dist/read-and-increment-offset.d.ts +0 -28
  110. package/dist/read-and-increment-offset.js +0 -177
  111. package/dist/understand-vorbis.d.ts +0 -1
  112. package/dist/understand-vorbis.js +0 -12
  113. package/src/boxes/webm/segments/unknown.ts +0 -19
  114. /package/dist/{boxes/webm/bitstream/av1/frame.d.ts → get-samples.d.ts} +0 -0
  115. /package/dist/{boxes/webm/bitstream/av1/frame.js → get-samples.js} +0 -0
  116. /package/dist/{boxes/webm/bitstream/h264/get-h264-descriptor.d.ts → sample-aspect-ratio.d.ts} +0 -0
  117. /package/dist/{boxes/webm/bitstream/h264/get-h264-descriptor.js → sample-aspect-ratio.js} +0 -0
@@ -0,0 +1,138 @@
1
+ import {getVariableInt} from './ebml';
2
+ import type {
3
+ Ebml,
4
+ EbmlWithChildren,
5
+ EbmlWithHexString,
6
+ EbmlWithString,
7
+ EbmlWithUint8,
8
+ EmblTypes,
9
+ HeaderStructure,
10
+ matroskaElements,
11
+ } from './segments/all-segments';
12
+ import {getIdForName} from './segments/all-segments';
13
+
14
+ export const webmPattern = new Uint8Array([0x1a, 0x45, 0xdf, 0xa3]);
15
+
16
+ const matroskaToHex = (
17
+ matrId: (typeof matroskaElements)[keyof typeof matroskaElements],
18
+ ) => {
19
+ const numbers: Uint8Array = new Uint8Array((matrId.length - 2) / 2);
20
+
21
+ for (let i = 2; i < matrId.length; i += 2) {
22
+ const hex = matrId.substring(i, i + 2);
23
+ numbers[(i - 2) / 2] = parseInt(hex, 16);
24
+ }
25
+
26
+ return numbers;
27
+ };
28
+
29
+ type Numbers = '0' | '1' | '2' | '3' | '4' | '5' | '6';
30
+
31
+ type ChildFields<Struct extends HeaderStructure> = {
32
+ [key in keyof Struct &
33
+ Numbers as Struct[key]['name']]: EmblTypes[Struct[key]['type']];
34
+ };
35
+
36
+ type SerializeValue<Struct extends Ebml> = Struct extends EbmlWithChildren
37
+ ? ChildFields<Struct['children']>
38
+ : Struct extends EbmlWithString
39
+ ? string
40
+ : Struct extends EbmlWithUint8
41
+ ? number
42
+ : Struct extends EbmlWithHexString
43
+ ? string
44
+ : undefined;
45
+
46
+ function putUintDynamic(number: number) {
47
+ if (number < 0) {
48
+ throw new Error(
49
+ 'This function is designed for non-negative integers only.',
50
+ );
51
+ }
52
+
53
+ // Calculate the minimum number of bytes needed to store the integer
54
+ const length = Math.ceil(Math.log2(number + 1) / 8);
55
+ const bytes = new Uint8Array(length);
56
+
57
+ for (let i = 0; i < length; i++) {
58
+ // Extract each byte from the number
59
+ bytes[length - 1 - i] = (number >> (8 * i)) & 0xff;
60
+ }
61
+
62
+ return bytes;
63
+ }
64
+
65
+ const makeFromHeaderStructure = <Struct extends Ebml>(
66
+ struct: Struct,
67
+ fields: SerializeValue<Struct>,
68
+ ): Uint8Array => {
69
+ const arrays: Uint8Array[] = [];
70
+
71
+ if (struct.type === 'children') {
72
+ for (const item of struct.children) {
73
+ arrays.push(
74
+ makeMatroskaHeader(
75
+ item,
76
+ // @ts-expect-error
77
+ fields[item.name],
78
+ ),
79
+ );
80
+ }
81
+
82
+ return combineUint8Arrays(arrays);
83
+ }
84
+
85
+ if (struct.type === 'string') {
86
+ return new TextEncoder().encode(fields as string);
87
+ }
88
+
89
+ if (struct.type === 'uint') {
90
+ return putUintDynamic(fields as number);
91
+ }
92
+
93
+ if (struct.type === 'hex-string') {
94
+ const hex = (fields as string).substring(2);
95
+ const arr = new Uint8Array(hex.length / 2);
96
+ for (let i = 0; i < hex.length; i += 2) {
97
+ const byte = parseInt(hex.substring(i, i + 2), 16);
98
+ arr[i / 2] = byte;
99
+ }
100
+
101
+ return arr;
102
+ }
103
+
104
+ if (struct.type === 'void') {
105
+ throw new Error('Serializing Void is not implemented');
106
+ }
107
+
108
+ throw new Error('Unexpected type');
109
+ };
110
+
111
+ export const makeMatroskaHeader = <Struct extends Ebml>(
112
+ struct: Struct,
113
+ fields: SerializeValue<Struct>,
114
+ ) => {
115
+ const value = makeFromHeaderStructure(struct, fields);
116
+
117
+ return combineUint8Arrays([
118
+ matroskaToHex(getIdForName(struct.name)),
119
+ getVariableInt(value.length),
120
+ value,
121
+ ]);
122
+ };
123
+
124
+ const combineUint8Arrays = (arrays: Uint8Array[]) => {
125
+ let totalLength = 0;
126
+ for (const array of arrays) {
127
+ totalLength += array.length;
128
+ }
129
+
130
+ const result = new Uint8Array(totalLength);
131
+ let offset = 0;
132
+ for (const array of arrays) {
133
+ result.set(array, offset);
134
+ offset += array.length;
135
+ }
136
+
137
+ return result;
138
+ };
@@ -0,0 +1,93 @@
1
+ import type {BufferIterator} from '../../buffer-iterator';
2
+ import type {PossibleEbml} from './segments/all-segments';
3
+ import {ebmlMap, type Ebml, type EbmlParsed} from './segments/all-segments';
4
+
5
+ type Prettify<T> = {
6
+ [K in keyof T]: T[K];
7
+ } & {};
8
+
9
+ export const parseEbml = (iterator: BufferIterator): Prettify<PossibleEbml> => {
10
+ const hex = iterator.getMatroskaSegmentId();
11
+ if (hex === null) {
12
+ throw new Error(
13
+ 'Not enough bytes left to parse EBML - this should not happen',
14
+ );
15
+ }
16
+
17
+ const hasInMap = ebmlMap[hex as keyof typeof ebmlMap];
18
+ if (!hasInMap) {
19
+ throw new Error(
20
+ `Don't know how to parse EBML hex ID ${JSON.stringify(hex)}`,
21
+ );
22
+ }
23
+
24
+ const size = iterator.getVint();
25
+ if (size === null) {
26
+ throw new Error(
27
+ 'Not enough bytes left to parse EBML - this should not happen',
28
+ );
29
+ }
30
+
31
+ if (hasInMap.type === 'uint') {
32
+ const value = iterator.getUint(size);
33
+
34
+ return {type: hasInMap.name, value, hex};
35
+ }
36
+
37
+ if (hasInMap.type === 'string') {
38
+ const value = iterator.getByteString(size);
39
+
40
+ return {
41
+ type: hasInMap.name,
42
+ value,
43
+ hex,
44
+ };
45
+ }
46
+
47
+ if (hasInMap.type === 'float') {
48
+ const value = size === 4 ? iterator.getFloat32() : iterator.getFloat64();
49
+
50
+ return {
51
+ type: hasInMap.name,
52
+ value,
53
+ hex,
54
+ };
55
+ }
56
+
57
+ if (hasInMap.type === 'void') {
58
+ iterator.discard(size);
59
+
60
+ return {
61
+ type: hasInMap.name,
62
+ value: undefined,
63
+ hex,
64
+ };
65
+ }
66
+
67
+ if (hasInMap.type === 'children') {
68
+ const children: EbmlParsed<Ebml>[] = [];
69
+ const startOffset = iterator.counter.getOffset();
70
+
71
+ // eslint-disable-next-line no-constant-condition
72
+ while (true) {
73
+ const value = parseEbml(iterator);
74
+ children.push(value);
75
+ const offsetNow = iterator.counter.getOffset();
76
+
77
+ if (offsetNow - startOffset > size) {
78
+ throw new Error(
79
+ `Offset ${offsetNow - startOffset} is larger than the length of the hex ${size}`,
80
+ );
81
+ }
82
+
83
+ if (offsetNow - startOffset === size) {
84
+ break;
85
+ }
86
+ }
87
+
88
+ return {type: hasInMap.name, value: children as EbmlParsed<Ebml>[], hex};
89
+ }
90
+
91
+ // @ts-expect-error
92
+ throw new Error(`Unknown segment type ${hasInMap.type}`);
93
+ };
@@ -1,22 +1,18 @@
1
1
  import type {BufferIterator} from '../../buffer-iterator';
2
2
  import type {ParseResult} from '../../parse-result';
3
3
  import type {ParserContext} from '../../parser-context';
4
- import {expectSegment} from './segments';
4
+ import {expectChildren} from './segments/parse-children';
5
5
 
6
6
  // Parsing according to https://darkcoding.net/software/reading-mediarecorders-webm-opus-output/
7
7
  export const parseWebm = (
8
8
  counter: BufferIterator,
9
9
  parserContext: ParserContext,
10
10
  ): Promise<ParseResult> => {
11
- counter.discard(4);
12
- const length = counter.getVint();
13
-
14
- if (length !== 31 && length !== 35) {
15
- throw new Error(`Expected header length 31 or 25, got ${length}`);
16
- }
17
-
18
- // Discard header for now
19
- counter.discard(length);
20
-
21
- return expectSegment(counter, parserContext);
11
+ return expectChildren({
12
+ iterator: counter,
13
+ length: Infinity,
14
+ initialChildren: [],
15
+ wrap: null,
16
+ parserContext,
17
+ });
22
18
  };
@@ -1,6 +1,12 @@
1
1
  export const matroskaElements = {
2
+ Header: '0x1a45dfa3',
2
3
  EBMLMaxIDLength: '0x42f2',
4
+ EBMLVersion: '0x4286',
5
+ EBMLReadVersion: '0x42f7',
3
6
  EBMLMaxSizeLength: '0x42f3',
7
+ DocType: '0x4282',
8
+ DocTypeVersion: '0x4287',
9
+ DocTypeReadVersion: '0x4285',
4
10
  Segment: '0x18538067',
5
11
  SeekHead: '0x114d9b74',
6
12
  Seek: '0x4dbb',
@@ -283,3 +289,223 @@ export const getSegmentName = (id: string) => {
283
289
  ([, value]) => value === id,
284
290
  )?.[0];
285
291
  };
292
+
293
+ export const getIdForName = (name: string) => {
294
+ const value = Object.entries(matroskaElements).find(
295
+ ([key]) => key === name,
296
+ )?.[1];
297
+ if (!value) {
298
+ throw new Error(`Could not find id for name ${name}`);
299
+ }
300
+
301
+ return value;
302
+ };
303
+
304
+ export type MatroskaKey = keyof typeof matroskaElements;
305
+
306
+ export type MatroskaElement = (typeof matroskaElements)[MatroskaKey];
307
+
308
+ type EbmlType = 'string';
309
+
310
+ export type EbmlWithChildren = {
311
+ name: MatroskaKey;
312
+ type: 'children';
313
+ children: HeaderStructure;
314
+ };
315
+
316
+ export type EbmlWithUint8 = {
317
+ name: MatroskaKey;
318
+ type: 'uint';
319
+ };
320
+
321
+ export type EbmlWithHexString = {
322
+ name: MatroskaKey;
323
+ type: 'hex-string';
324
+ };
325
+
326
+ export type EbmlWithString = {
327
+ name: MatroskaKey;
328
+ type: EbmlType;
329
+ };
330
+
331
+ export type EbmlWithVoid = {
332
+ name: MatroskaKey;
333
+ type: 'void';
334
+ };
335
+
336
+ export type EbmlWithFloat = {
337
+ name: MatroskaKey;
338
+ type: 'float';
339
+ };
340
+
341
+ export type Ebml =
342
+ | EbmlWithString
343
+ | EbmlWithUint8
344
+ | EbmlWithChildren
345
+ | EbmlWithVoid
346
+ | EbmlWithFloat
347
+ | EbmlWithHexString;
348
+
349
+ export const ebmlVersion = {
350
+ name: 'EBMLVersion',
351
+ type: 'uint',
352
+ } satisfies Ebml;
353
+
354
+ export const ebmlReadVersion = {
355
+ name: 'EBMLReadVersion',
356
+ type: 'uint',
357
+ } satisfies Ebml;
358
+
359
+ export const ebmlMaxIdLength = {
360
+ name: 'EBMLMaxIDLength',
361
+ type: 'uint',
362
+ } satisfies Ebml;
363
+
364
+ export const ebmlMaxSizeLength = {
365
+ name: 'EBMLMaxSizeLength',
366
+ type: 'uint',
367
+ } satisfies Ebml;
368
+
369
+ export const docType = {
370
+ name: 'DocType',
371
+ type: 'string',
372
+ } satisfies Ebml;
373
+
374
+ export const docTypeVersion = {
375
+ name: 'DocTypeVersion',
376
+ type: 'uint',
377
+ } satisfies Ebml;
378
+
379
+ export const docTypeReadVersion = {
380
+ name: 'DocTypeReadVersion',
381
+ type: 'uint',
382
+ } satisfies Ebml;
383
+
384
+ export const voidEbml = {
385
+ name: 'Void',
386
+ type: 'void',
387
+ } satisfies Ebml;
388
+
389
+ export type EmblTypes = {
390
+ uint: number;
391
+ float: number;
392
+ string: string;
393
+ children: HeaderStructure;
394
+ void: undefined;
395
+ 'hex-string': string;
396
+ };
397
+
398
+ export type HeaderStructure = Ebml[];
399
+
400
+ export const matroskaHeaderStructure = [
401
+ ebmlVersion,
402
+ ebmlReadVersion,
403
+ ebmlMaxIdLength,
404
+ ebmlMaxSizeLength,
405
+ docType,
406
+ docTypeVersion,
407
+ docTypeReadVersion,
408
+ ] as const satisfies HeaderStructure;
409
+
410
+ export const matroskaHeader = {
411
+ name: 'Header',
412
+ type: 'children',
413
+ children: matroskaHeaderStructure,
414
+ } as const satisfies Ebml;
415
+
416
+ export const seekId = {
417
+ name: 'SeekID',
418
+ type: 'hex-string',
419
+ } as const satisfies Ebml;
420
+
421
+ export const seekPosition = {
422
+ name: 'SeekPosition',
423
+ type: 'uint',
424
+ } as const satisfies Ebml;
425
+
426
+ export const seek = {
427
+ name: 'Seek',
428
+ type: 'children',
429
+ children: [seekId, seekPosition],
430
+ } as const satisfies Ebml;
431
+
432
+ export const voidHeader = {
433
+ name: 'Void',
434
+ type: 'void',
435
+ } as const satisfies Ebml;
436
+
437
+ export type EbmlValue<T extends Ebml> = T extends EbmlWithUint8
438
+ ? number
439
+ : T extends EbmlWithVoid
440
+ ? undefined
441
+ : T extends EbmlWithString
442
+ ? string
443
+ : T extends EbmlWithFloat
444
+ ? number
445
+ : EbmlParsed<Ebml>[];
446
+
447
+ export type EbmlParsed<T extends Ebml> = {
448
+ type: T['name'];
449
+ value: EbmlValue<T>;
450
+ hex: string;
451
+ };
452
+
453
+ export const ebmlMap = {
454
+ [matroskaElements.Header]: matroskaHeader,
455
+ [matroskaElements.DocType]: docType,
456
+ [matroskaElements.DocTypeVersion]: docTypeVersion,
457
+ [matroskaElements.DocTypeReadVersion]: docTypeReadVersion,
458
+ [matroskaElements.EBMLVersion]: ebmlVersion,
459
+ [matroskaElements.EBMLReadVersion]: ebmlReadVersion,
460
+ [matroskaElements.EBMLMaxIDLength]: ebmlMaxIdLength,
461
+ [matroskaElements.EBMLMaxSizeLength]: ebmlMaxSizeLength,
462
+ [matroskaElements.Void]: voidEbml,
463
+ [matroskaElements.Cues]: {
464
+ name: 'Cues',
465
+ type: 'void',
466
+ },
467
+ [matroskaElements.DateUTC]: {
468
+ name: 'DateUTC',
469
+ type: 'void',
470
+ },
471
+ [matroskaElements.TrackTimestampScale]: {
472
+ name: 'TrackTimestampScale',
473
+ type: 'float',
474
+ },
475
+ [matroskaElements.CodecDelay]: {
476
+ name: 'CodecDelay',
477
+ type: 'void',
478
+ },
479
+ [matroskaElements.SeekPreRoll]: {
480
+ name: 'SeekPreRoll',
481
+ type: 'void',
482
+ },
483
+ [matroskaElements.DiscardPadding]: {
484
+ name: 'DiscardPadding',
485
+ type: 'void',
486
+ },
487
+ [matroskaElements.OutputSamplingFrequency]: {
488
+ name: 'OutputSamplingFrequency',
489
+ type: 'void',
490
+ },
491
+ [matroskaElements.CodecName]: {
492
+ name: 'CodecName',
493
+ type: 'void',
494
+ },
495
+ [matroskaElements.Position]: {
496
+ name: 'Position',
497
+ type: 'void',
498
+ },
499
+ [matroskaElements.SliceDuration]: {
500
+ name: 'SliceDuration',
501
+ type: 'void',
502
+ },
503
+ } as const satisfies Partial<Record<MatroskaElement, Ebml>>;
504
+
505
+ export type PossibleEbml = {
506
+ [key in keyof typeof ebmlMap]: {
507
+ type: (typeof ebmlMap)[key]['name'];
508
+ value: EbmlValue<(typeof ebmlMap)[key]>;
509
+ hex: string;
510
+ };
511
+ }[keyof typeof ebmlMap];
@@ -0,0 +1,52 @@
1
+ import type {BufferIterator} from '../../../buffer-iterator';
2
+ import {matroskaElements} from './all-segments';
3
+
4
+ type BlockFlags = {
5
+ invisible: boolean;
6
+ lacing: number;
7
+ keyframe: boolean | null;
8
+ };
9
+
10
+ export const parseBlockFlags = (
11
+ iterator: BufferIterator,
12
+ type:
13
+ | (typeof matroskaElements)['Block']
14
+ | (typeof matroskaElements)['SimpleBlock'],
15
+ ): BlockFlags => {
16
+ if (type === matroskaElements.Block) {
17
+ iterator.startReadingBits();
18
+ // Reserved
19
+ iterator.getBits(4);
20
+ const invisible = Boolean(iterator.getBits(1));
21
+ const lacing = iterator.getBits(2);
22
+ // unused
23
+ iterator.getBits(1);
24
+ iterator.stopReadingBits();
25
+ return {
26
+ invisible,
27
+ lacing,
28
+ keyframe: null,
29
+ };
30
+ }
31
+
32
+ if (type === matroskaElements.SimpleBlock) {
33
+ iterator.startReadingBits();
34
+
35
+ const keyframe = Boolean(iterator.getBits(1));
36
+ // Reserved
37
+ iterator.getBits(3);
38
+ const invisible = Boolean(iterator.getBits(1));
39
+ const lacing = iterator.getBits(2);
40
+ iterator.getBits(1);
41
+
42
+ iterator.stopReadingBits();
43
+
44
+ return {
45
+ invisible,
46
+ lacing,
47
+ keyframe,
48
+ };
49
+ }
50
+
51
+ throw new Error('Unexpected type');
52
+ };
@@ -9,7 +9,7 @@ export const parseSeekPositionSegment = (
9
9
  iterator: BufferIterator,
10
10
  length: number,
11
11
  ): SeekPositionSegment => {
12
- const seekPosition = iterator.getDecimalBytes(length);
12
+ const seekPosition = iterator.getUint(length);
13
13
 
14
14
  return {
15
15
  type: 'seek-position-segment',
@@ -35,8 +35,18 @@ export type SeekIdSegment = {
35
35
  seekId: string;
36
36
  };
37
37
 
38
- export const parseSeekIdSegment = (iterator: BufferIterator): SeekIdSegment => {
39
- const seekId = iterator.getMatroskaSegmentId();
38
+ export const parseSeekIdSegment = (
39
+ iterator: BufferIterator,
40
+ length: number,
41
+ ): SeekIdSegment => {
42
+ const seekId =
43
+ '0x' +
44
+ [...iterator.getSlice(length)]
45
+ .map((b) => b.toString(16).padStart(2, '0'))
46
+ .join('');
47
+ if (seekId === null) {
48
+ throw new Error('Not enough bytes to parse seek id');
49
+ }
40
50
 
41
51
  return {
42
52
  type: 'seek-id-segment',
@@ -8,7 +8,7 @@ export type TimestampScaleSegment = {
8
8
  export const parseTimestampScaleSegment = (
9
9
  iterator: BufferIterator,
10
10
  ): TimestampScaleSegment => {
11
- const timestampScale = iterator.getDecimalBytes(3);
11
+ const timestampScale = iterator.getUint(3);
12
12
 
13
13
  return {
14
14
  type: 'timestamp-scale-segment',