@remotion/media-parser 4.0.201 → 4.0.204
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/dist/av1-codec-string.d.ts +0 -5
- package/dist/av1-codec-string.js +1 -18
- package/dist/boxes/iso-base-media/ftype.d.ts +9 -0
- package/dist/boxes/iso-base-media/ftype.js +31 -0
- package/dist/boxes/iso-base-media/get-sample-positions-from-track.d.ts +4 -0
- package/dist/boxes/iso-base-media/get-sample-positions-from-track.js +48 -0
- package/dist/boxes/iso-base-media/mvhd.js +2 -2
- package/dist/boxes/iso-base-media/stsd/keys.js +1 -1
- package/dist/boxes/iso-base-media/tfdt.d.ts +12 -0
- package/dist/boxes/iso-base-media/tfdt.js +20 -0
- package/dist/boxes/iso-base-media/tfhd.d.ts +16 -0
- package/dist/boxes/iso-base-media/tfhd.js +41 -0
- package/dist/boxes/iso-base-media/trun.d.ts +21 -0
- package/dist/boxes/iso-base-media/trun.js +44 -0
- package/dist/boxes/webm/av1-codec-private.js +1 -1
- package/dist/boxes/webm/bitstream/av1.js +1 -10
- package/dist/boxes/webm/description.d.ts +2 -2
- package/dist/boxes/webm/description.js +2 -2
- package/dist/boxes/webm/ebml.d.ts +2 -2
- package/dist/boxes/webm/ebml.js +23 -1
- package/dist/boxes/webm/get-ready-tracks.d.ts +1 -1
- package/dist/boxes/webm/get-ready-tracks.js +3 -3
- package/dist/boxes/webm/get-sample-from-block.d.ts +17 -0
- package/dist/boxes/webm/get-sample-from-block.js +78 -0
- package/dist/boxes/webm/get-track.d.ts +2 -2
- package/dist/boxes/webm/get-track.js +26 -25
- package/dist/boxes/webm/make-header.d.ts +3 -8
- package/dist/boxes/webm/make-header.js +43 -20
- package/dist/boxes/webm/parse-ebml.d.ts +9 -4
- package/dist/boxes/webm/parse-ebml.js +122 -13
- package/dist/boxes/webm/segments/all-segments.d.ts +421 -107
- package/dist/boxes/webm/segments/all-segments.js +260 -33
- package/dist/boxes/webm/segments/track-entry.d.ts +3 -191
- package/dist/boxes/webm/segments/track-entry.js +2 -456
- package/dist/boxes/webm/segments.d.ts +3 -16
- package/dist/boxes/webm/segments.js +12 -196
- package/dist/boxes/webm/tracks.d.ts +8 -0
- package/dist/boxes/webm/tracks.js +21 -0
- package/dist/boxes/webm/traversal.d.ts +5 -6
- package/dist/boxes/webm/traversal.js +6 -6
- package/dist/buffer-iterator.d.ts +1 -1
- package/dist/buffer-iterator.js +3 -3
- package/dist/from-web.js +6 -15
- package/dist/get-audio-codec.d.ts +1 -1
- package/dist/get-audio-codec.js +13 -13
- package/dist/get-duration.js +12 -14
- package/dist/get-tracks.js +2 -2
- package/dist/get-video-codec.js +13 -13
- package/dist/get-video-metadata.d.ts +2 -0
- package/dist/get-video-metadata.js +44 -0
- package/dist/parse-media.js +4 -1
- package/dist/parser-context.d.ts +1 -0
- package/dist/parser-state.js +3 -2
- package/dist/read-and-increment-offset.d.ts +28 -0
- package/dist/read-and-increment-offset.js +177 -0
- package/dist/samples-from-moof.d.ts +6 -0
- package/dist/samples-from-moof.js +74 -0
- package/dist/traversal.d.ts +19 -17
- package/dist/traversal.js +38 -39
- package/dist/understand-vorbis.d.ts +1 -0
- package/dist/understand-vorbis.js +12 -0
- package/input.webm +0 -0
- package/package.json +2 -2
- package/src/boxes/iso-base-media/get-sample-positions-from-track.ts +69 -0
- package/src/boxes/iso-base-media/make-track.ts +4 -45
- package/src/boxes/iso-base-media/mdat/mdat.ts +33 -24
- package/src/boxes/iso-base-media/mdhd.ts +10 -7
- package/src/boxes/iso-base-media/mvhd.ts +17 -16
- package/src/boxes/iso-base-media/process-box.ts +42 -0
- package/src/boxes/iso-base-media/stsd/keys.ts +1 -1
- package/src/boxes/iso-base-media/tfdt.ts +37 -0
- package/src/boxes/iso-base-media/tfhd.ts +66 -0
- package/src/boxes/iso-base-media/tkhd.ts +11 -13
- package/src/boxes/iso-base-media/trun.ts +74 -0
- package/src/boxes/webm/av1-codec-private.ts +1 -1
- package/src/boxes/webm/description.ts +7 -4
- package/src/boxes/webm/ebml.ts +24 -4
- package/src/boxes/webm/get-ready-tracks.ts +4 -4
- package/src/boxes/webm/get-sample-from-block.ts +125 -0
- package/src/boxes/webm/get-track.ts +40 -33
- package/src/boxes/webm/make-header.ts +58 -51
- package/src/boxes/webm/parse-ebml.ts +170 -16
- package/src/boxes/webm/segments/all-segments.ts +379 -62
- package/src/boxes/webm/segments/track-entry.ts +3 -846
- package/src/boxes/webm/segments.ts +18 -410
- package/src/boxes/webm/traversal.ts +17 -17
- package/src/buffer-iterator.ts +8 -6
- package/src/get-audio-codec.ts +14 -16
- package/src/get-duration.ts +55 -21
- package/src/get-tracks.ts +6 -6
- package/src/get-video-codec.ts +13 -15
- package/src/has-all-info.ts +1 -1
- package/src/parse-media.ts +7 -2
- package/src/parse-result.ts +7 -1
- package/src/parser-context.ts +1 -0
- package/src/parser-state.ts +2 -2
- package/src/samples-from-moof.ts +101 -0
- package/src/test/create-matroska.test.ts +237 -23
- package/src/test/matroska.test.ts +283 -348
- package/src/test/mvhd.test.ts +1 -1
- package/src/test/parse-esds.test.ts +2 -2
- package/src/test/parse-stco.test.ts +2 -2
- package/src/test/parse-stsc.test.ts +2 -2
- package/src/test/parse-stsz.test.ts +2 -2
- package/src/test/parse-stts.test.ts +1 -1
- package/src/test/samples-from-moof.test.ts +2496 -0
- package/src/test/stream-local.test.ts +28 -30
- package/src/test/stream-samples.test.ts +153 -231
- package/src/test/stsd.test.ts +4 -2
- package/src/test/tkhd.test.ts +1 -1
- package/src/traversal.ts +118 -86
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/bitstream/av1.d.ts +0 -2
- package/dist/bitstream/av1.js +0 -12
- package/dist/boxes/iso-base-media/avcc-hvcc.d.ts +0 -20
- package/dist/boxes/iso-base-media/avcc-hvcc.js +0 -73
- package/dist/boxes/iso-base-media/avcc.d.ts +0 -18
- package/dist/boxes/iso-base-media/avcc.js +0 -27
- package/dist/boxes/iso-base-media/esds-descriptors.d.ts +0 -21
- package/dist/boxes/iso-base-media/esds-descriptors.js +0 -62
- package/dist/boxes/iso-base-media/esds.d.ts +0 -15
- package/dist/boxes/iso-base-media/esds.js +0 -27
- package/dist/from-input-type-file.d.ts +0 -2
- package/dist/from-input-type-file.js +0 -37
- package/dist/get-codec.d.ts +0 -4
- package/dist/get-codec.js +0 -22
- package/dist/web-file.d.ts +0 -2
- package/dist/web-file.js +0 -37
- package/src/boxes/webm/segments/duration.ts +0 -29
- package/src/boxes/webm/segments/info.ts +0 -34
- package/src/boxes/webm/segments/main.ts +0 -6
- package/src/boxes/webm/segments/muxing.ts +0 -18
- package/src/boxes/webm/segments/seek-head.ts +0 -34
- package/src/boxes/webm/segments/seek-position.ts +0 -18
- package/src/boxes/webm/segments/seek.ts +0 -55
- package/src/boxes/webm/segments/timestamp-scale.ts +0 -17
- package/src/boxes/webm/segments/tracks.ts +0 -32
- package/src/boxes/webm/segments/void.ts +0 -18
- package/src/boxes/webm/segments/writing.ts +0 -18
- package/src/combine-uint8array.ts +0 -13
- /package/dist/{get-samples.d.ts → boxes/webm/bitstream/av1/frame.d.ts} +0 -0
- /package/dist/{get-samples.js → boxes/webm/bitstream/av1/frame.js} +0 -0
- /package/dist/{sample-aspect-ratio.d.ts → boxes/webm/bitstream/h264/get-h264-descriptor.d.ts} +0 -0
- /package/dist/{sample-aspect-ratio.js → boxes/webm/bitstream/h264/get-h264-descriptor.js} +0 -0
|
@@ -1,133 +1,10 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {ParserContext} from '../../../parser-context';
|
|
3
|
-
import type {VideoSample} from '../../../webcodec-sample-types';
|
|
4
|
-
import type {MatroskaSegment} from '../segments';
|
|
5
|
-
import type {matroskaElements} from './all-segments';
|
|
6
|
-
import {parseBlockFlags} from './block-simple-block-flags';
|
|
7
|
-
import {expectChildren} from './parse-children';
|
|
8
|
-
|
|
9
|
-
export type TrackEntrySegment = {
|
|
10
|
-
type: 'track-entry-segment';
|
|
11
|
-
children: MatroskaSegment[];
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export const parseTrackEntry = async (
|
|
15
|
-
iterator: BufferIterator,
|
|
16
|
-
length: number,
|
|
17
|
-
parserContext: ParserContext,
|
|
18
|
-
): Promise<TrackEntrySegment> => {
|
|
19
|
-
const children = await expectChildren({
|
|
20
|
-
iterator,
|
|
21
|
-
length,
|
|
22
|
-
initialChildren: [],
|
|
23
|
-
wrap: null,
|
|
24
|
-
parserContext,
|
|
25
|
-
});
|
|
26
|
-
if (children.status === 'incomplete') {
|
|
27
|
-
throw new Error('Incomplete children ' + length);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
type: 'track-entry-segment',
|
|
32
|
-
children: children.segments as MatroskaSegment[],
|
|
33
|
-
};
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
export type TrackNumberSegment = {
|
|
37
|
-
type: 'track-number-segment';
|
|
38
|
-
trackNumber: number;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export type TrackUIDSegment = {
|
|
42
|
-
type: 'track-uid-segment';
|
|
43
|
-
trackUid: string;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export const parseTrackUID = (
|
|
47
|
-
iterator: BufferIterator,
|
|
48
|
-
length: number,
|
|
49
|
-
): TrackUIDSegment => {
|
|
50
|
-
const bytes = iterator.getSlice(length);
|
|
51
|
-
|
|
52
|
-
const asString = [...bytes]
|
|
53
|
-
.map((b) => b.toString(16).padStart(2, '0'))
|
|
54
|
-
.join('');
|
|
55
|
-
return {
|
|
56
|
-
type: 'track-uid-segment',
|
|
57
|
-
trackUid: asString,
|
|
58
|
-
};
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
export type FlagLacingSegment = {
|
|
62
|
-
type: 'flag-lacing-segment';
|
|
63
|
-
lacing: boolean;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
export const parseFlagLacing = (
|
|
67
|
-
iterator: BufferIterator,
|
|
68
|
-
length: number,
|
|
69
|
-
): FlagLacingSegment => {
|
|
70
|
-
if (length !== 1) {
|
|
71
|
-
throw new Error('Expected flag lacing to be 1 byte');
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const bytes = iterator.getSlice(length);
|
|
75
|
-
|
|
76
|
-
if (bytes[0] !== 1 && bytes[0] !== 0) {
|
|
77
|
-
throw new Error('Expected lacing to be 1 or 0');
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return {
|
|
81
|
-
type: 'flag-lacing-segment',
|
|
82
|
-
lacing: Boolean(bytes[0]),
|
|
83
|
-
};
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
export type LanguageSegment = {
|
|
87
|
-
type: 'language-segment';
|
|
88
|
-
language: string;
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
export const parseLanguageSegment = (
|
|
92
|
-
iterator: BufferIterator,
|
|
93
|
-
length: number,
|
|
94
|
-
): LanguageSegment => {
|
|
95
|
-
if (length !== 3) {
|
|
96
|
-
throw new Error('Expected language segment to be 3 bytes');
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const language = iterator.getByteString(length);
|
|
100
|
-
|
|
101
|
-
return {
|
|
102
|
-
type: 'language-segment',
|
|
103
|
-
language,
|
|
104
|
-
};
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
export type CodecSegment = {
|
|
108
|
-
type: 'codec-segment';
|
|
109
|
-
codec: string;
|
|
110
|
-
};
|
|
1
|
+
import type {TrackEntry} from './all-segments';
|
|
111
2
|
|
|
112
3
|
export type TrackInfo = {
|
|
113
4
|
codec: string;
|
|
114
5
|
trackTimescale: number | null;
|
|
115
6
|
};
|
|
116
7
|
|
|
117
|
-
export const parseCodecSegment = (
|
|
118
|
-
iterator: BufferIterator,
|
|
119
|
-
length: number,
|
|
120
|
-
): CodecSegment => {
|
|
121
|
-
// Could make a TypeScript enum with it
|
|
122
|
-
// https://www.matroska.org/technical/codec_specs.html
|
|
123
|
-
const codec = iterator.getByteString(length);
|
|
124
|
-
|
|
125
|
-
return {
|
|
126
|
-
type: 'codec-segment',
|
|
127
|
-
codec,
|
|
128
|
-
};
|
|
129
|
-
};
|
|
130
|
-
|
|
131
8
|
type TrackType =
|
|
132
9
|
| 'video'
|
|
133
10
|
| 'audio'
|
|
@@ -137,12 +14,7 @@ type TrackType =
|
|
|
137
14
|
| 'control'
|
|
138
15
|
| 'metadata';
|
|
139
16
|
|
|
140
|
-
export
|
|
141
|
-
type: 'track-type-segment';
|
|
142
|
-
trackType: TrackType;
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
const trackTypeToString = (trackType: number): TrackType => {
|
|
17
|
+
export const trackTypeToString = (trackType: number): TrackType => {
|
|
146
18
|
switch (trackType) {
|
|
147
19
|
case 1:
|
|
148
20
|
return 'video';
|
|
@@ -163,719 +35,4 @@ const trackTypeToString = (trackType: number): TrackType => {
|
|
|
163
35
|
}
|
|
164
36
|
};
|
|
165
37
|
|
|
166
|
-
export
|
|
167
|
-
iterator: BufferIterator,
|
|
168
|
-
length: number,
|
|
169
|
-
): TrackTypeSegment => {
|
|
170
|
-
if (length !== 1) {
|
|
171
|
-
throw new Error('Expected track type segment to be 1 byte');
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const trackType = iterator.getUint8();
|
|
175
|
-
|
|
176
|
-
const trackTypeString = trackTypeToString(trackType);
|
|
177
|
-
|
|
178
|
-
// Could make the return type nicer
|
|
179
|
-
/* 1 - video,
|
|
180
|
-
2 - audio,
|
|
181
|
-
3 - complex,
|
|
182
|
-
16 - logo,
|
|
183
|
-
17 - subtitle,
|
|
184
|
-
18 - buttons,
|
|
185
|
-
32 - control,
|
|
186
|
-
33 - metadata;
|
|
187
|
-
*/
|
|
188
|
-
return {
|
|
189
|
-
type: 'track-type-segment',
|
|
190
|
-
trackType: trackTypeString,
|
|
191
|
-
};
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
export type DefaultDurationSegment = {
|
|
195
|
-
type: 'default-duration-segment';
|
|
196
|
-
defaultDuration: number;
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
export const parseDefaultDurationSegment = (
|
|
200
|
-
iterator: BufferIterator,
|
|
201
|
-
length: number,
|
|
202
|
-
): DefaultDurationSegment => {
|
|
203
|
-
const defaultDuration = iterator.getUint(length);
|
|
204
|
-
|
|
205
|
-
return {
|
|
206
|
-
type: 'default-duration-segment',
|
|
207
|
-
defaultDuration,
|
|
208
|
-
};
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
export type VideoSegment = {
|
|
212
|
-
type: 'video-segment';
|
|
213
|
-
children: MatroskaSegment[];
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
export const parseVideoSegment = async (
|
|
217
|
-
iterator: BufferIterator,
|
|
218
|
-
length: number,
|
|
219
|
-
parserContext: ParserContext,
|
|
220
|
-
): Promise<VideoSegment> => {
|
|
221
|
-
const children = await expectChildren({
|
|
222
|
-
iterator,
|
|
223
|
-
length,
|
|
224
|
-
initialChildren: [],
|
|
225
|
-
wrap: null,
|
|
226
|
-
parserContext,
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
if (children.status === 'incomplete') {
|
|
230
|
-
throw new Error('Incomplete children');
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
return {
|
|
234
|
-
type: 'video-segment',
|
|
235
|
-
children: children.segments as MatroskaSegment[],
|
|
236
|
-
};
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
export type AudioSegment = {
|
|
240
|
-
type: 'audio-segment';
|
|
241
|
-
children: MatroskaSegment[];
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
export const parseAudioSegment = async (
|
|
245
|
-
iterator: BufferIterator,
|
|
246
|
-
length: number,
|
|
247
|
-
parserContext: ParserContext,
|
|
248
|
-
): Promise<AudioSegment> => {
|
|
249
|
-
const children = await expectChildren({
|
|
250
|
-
iterator,
|
|
251
|
-
length,
|
|
252
|
-
initialChildren: [],
|
|
253
|
-
wrap: null,
|
|
254
|
-
parserContext,
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
if (children.status === 'incomplete') {
|
|
258
|
-
throw new Error('Incomplete children');
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
return {
|
|
262
|
-
type: 'audio-segment',
|
|
263
|
-
children: children.segments as MatroskaSegment[],
|
|
264
|
-
};
|
|
265
|
-
};
|
|
266
|
-
|
|
267
|
-
export type WidthSegment = {
|
|
268
|
-
type: 'width-segment';
|
|
269
|
-
width: number;
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
export const parseWidthSegment = (
|
|
273
|
-
iterator: BufferIterator,
|
|
274
|
-
length: number,
|
|
275
|
-
): WidthSegment => {
|
|
276
|
-
if (length !== 2) {
|
|
277
|
-
throw new Error('Expected width segment to be 2 bytes');
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
const width = iterator.getUint16();
|
|
281
|
-
|
|
282
|
-
return {
|
|
283
|
-
type: 'width-segment',
|
|
284
|
-
width,
|
|
285
|
-
};
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
export type HeightSegment = {
|
|
289
|
-
type: 'height-segment';
|
|
290
|
-
height: number;
|
|
291
|
-
};
|
|
292
|
-
|
|
293
|
-
export const parseHeightSegment = (
|
|
294
|
-
iterator: BufferIterator,
|
|
295
|
-
length: number,
|
|
296
|
-
): HeightSegment => {
|
|
297
|
-
if (length !== 2) {
|
|
298
|
-
throw new Error('Expected height segment to be 2 bytes');
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
const height = iterator.getUint16();
|
|
302
|
-
|
|
303
|
-
return {
|
|
304
|
-
type: 'height-segment',
|
|
305
|
-
height,
|
|
306
|
-
};
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
export type DisplayWidthSegment = {
|
|
310
|
-
type: 'display-width-segment';
|
|
311
|
-
displayWidth: number;
|
|
312
|
-
};
|
|
313
|
-
|
|
314
|
-
export const parseDisplayWidthSegment = (
|
|
315
|
-
iterator: BufferIterator,
|
|
316
|
-
length: number,
|
|
317
|
-
): DisplayWidthSegment => {
|
|
318
|
-
if (length !== 2) {
|
|
319
|
-
throw new Error(
|
|
320
|
-
`Expected display width segment to be 2 bytes, got ${length}`,
|
|
321
|
-
);
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
const displayWidth = iterator.getUint16();
|
|
325
|
-
|
|
326
|
-
return {
|
|
327
|
-
type: 'display-width-segment',
|
|
328
|
-
displayWidth,
|
|
329
|
-
};
|
|
330
|
-
};
|
|
331
|
-
|
|
332
|
-
export type DisplayHeightSegment = {
|
|
333
|
-
type: 'display-height-segment';
|
|
334
|
-
displayHeight: number;
|
|
335
|
-
};
|
|
336
|
-
|
|
337
|
-
export const parseDisplayHeightSegment = (
|
|
338
|
-
iterator: BufferIterator,
|
|
339
|
-
length: number,
|
|
340
|
-
): DisplayHeightSegment => {
|
|
341
|
-
if (length !== 2) {
|
|
342
|
-
throw new Error(
|
|
343
|
-
`Expected display height segment to be 2 bytes, got ${length}`,
|
|
344
|
-
);
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
const displayHeight = iterator.getUint16();
|
|
348
|
-
|
|
349
|
-
return {
|
|
350
|
-
type: 'display-height-segment',
|
|
351
|
-
displayHeight,
|
|
352
|
-
};
|
|
353
|
-
};
|
|
354
|
-
|
|
355
|
-
export type AlphaModeSegment = {
|
|
356
|
-
type: 'alpha-mode-segment';
|
|
357
|
-
alphaMode: number;
|
|
358
|
-
};
|
|
359
|
-
|
|
360
|
-
export const parseAlphaModeSegment = (
|
|
361
|
-
iterator: BufferIterator,
|
|
362
|
-
length: number,
|
|
363
|
-
): AlphaModeSegment => {
|
|
364
|
-
if (length !== 1) {
|
|
365
|
-
throw new Error('Expected alpha mode segment to be 1 byte');
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
const alphaMode = iterator.getUint8();
|
|
369
|
-
|
|
370
|
-
return {
|
|
371
|
-
type: 'alpha-mode-segment',
|
|
372
|
-
alphaMode,
|
|
373
|
-
};
|
|
374
|
-
};
|
|
375
|
-
|
|
376
|
-
export type MaxBlockAdditionId = {
|
|
377
|
-
type: 'max-block-addition-id-segment';
|
|
378
|
-
maxBlockAdditionId: number;
|
|
379
|
-
};
|
|
380
|
-
|
|
381
|
-
export const parseMaxBlockAdditionId = (
|
|
382
|
-
iterator: BufferIterator,
|
|
383
|
-
length: number,
|
|
384
|
-
): MaxBlockAdditionId => {
|
|
385
|
-
if (length !== 1) {
|
|
386
|
-
throw new Error('Expected alpha mode segment to be 1 byte');
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
const maxBlockAdditionId = iterator.getUint8();
|
|
390
|
-
|
|
391
|
-
return {
|
|
392
|
-
type: 'max-block-addition-id-segment',
|
|
393
|
-
maxBlockAdditionId,
|
|
394
|
-
};
|
|
395
|
-
};
|
|
396
|
-
|
|
397
|
-
export type ColorSegment = {
|
|
398
|
-
type: 'color-segment';
|
|
399
|
-
length: number;
|
|
400
|
-
};
|
|
401
|
-
|
|
402
|
-
export const parseColorSegment = (
|
|
403
|
-
iterator: BufferIterator,
|
|
404
|
-
length: number,
|
|
405
|
-
): ColorSegment => {
|
|
406
|
-
iterator.discard(length);
|
|
407
|
-
|
|
408
|
-
return {
|
|
409
|
-
type: 'color-segment',
|
|
410
|
-
length,
|
|
411
|
-
};
|
|
412
|
-
};
|
|
413
|
-
|
|
414
|
-
export type TitleSegment = {
|
|
415
|
-
type: 'title-segment';
|
|
416
|
-
title: string;
|
|
417
|
-
};
|
|
418
|
-
|
|
419
|
-
export const parseTitleSegment = (
|
|
420
|
-
iterator: BufferIterator,
|
|
421
|
-
length: number,
|
|
422
|
-
): TitleSegment => {
|
|
423
|
-
const title = iterator.getByteString(length);
|
|
424
|
-
|
|
425
|
-
return {
|
|
426
|
-
type: 'title-segment',
|
|
427
|
-
title,
|
|
428
|
-
};
|
|
429
|
-
};
|
|
430
|
-
|
|
431
|
-
export type InterlacedSegment = {
|
|
432
|
-
type: 'interlaced-segment';
|
|
433
|
-
interlaced: boolean;
|
|
434
|
-
};
|
|
435
|
-
|
|
436
|
-
export const parseInterlacedSegment = (
|
|
437
|
-
iterator: BufferIterator,
|
|
438
|
-
length: number,
|
|
439
|
-
): InterlacedSegment => {
|
|
440
|
-
if (length !== 1) {
|
|
441
|
-
throw new Error(
|
|
442
|
-
'Expected interlaced segment to be 1 byte, but is ' + length,
|
|
443
|
-
);
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
const interlaced = iterator.getUint8();
|
|
447
|
-
|
|
448
|
-
return {
|
|
449
|
-
type: 'interlaced-segment',
|
|
450
|
-
interlaced: Boolean(interlaced),
|
|
451
|
-
};
|
|
452
|
-
};
|
|
453
|
-
|
|
454
|
-
export type CodecPrivateSegment = {
|
|
455
|
-
type: 'codec-private-segment';
|
|
456
|
-
codecPrivateData: Uint8Array;
|
|
457
|
-
};
|
|
458
|
-
|
|
459
|
-
export const parseCodecPrivateSegment = (
|
|
460
|
-
iterator: BufferIterator,
|
|
461
|
-
length: number,
|
|
462
|
-
): CodecPrivateSegment => {
|
|
463
|
-
return {
|
|
464
|
-
type: 'codec-private-segment',
|
|
465
|
-
codecPrivateData: iterator.getSlice(length),
|
|
466
|
-
};
|
|
467
|
-
};
|
|
468
|
-
|
|
469
|
-
export type Crc32Segment = {
|
|
470
|
-
type: 'crc32-segment';
|
|
471
|
-
crc32: number[];
|
|
472
|
-
};
|
|
473
|
-
|
|
474
|
-
export const parseCrc32Segment = (
|
|
475
|
-
iterator: BufferIterator,
|
|
476
|
-
length: number,
|
|
477
|
-
): Crc32Segment => {
|
|
478
|
-
return {
|
|
479
|
-
type: 'crc32-segment',
|
|
480
|
-
crc32: [...iterator.getSlice(length)],
|
|
481
|
-
};
|
|
482
|
-
};
|
|
483
|
-
|
|
484
|
-
export type SegmentUUIDSegment = {
|
|
485
|
-
type: 'segment-uuid-segment';
|
|
486
|
-
segmentUUID: string;
|
|
487
|
-
};
|
|
488
|
-
|
|
489
|
-
export const parseSegmentUUIDSegment = (
|
|
490
|
-
iterator: BufferIterator,
|
|
491
|
-
length: number,
|
|
492
|
-
): SegmentUUIDSegment => {
|
|
493
|
-
return {
|
|
494
|
-
type: 'segment-uuid-segment',
|
|
495
|
-
segmentUUID: iterator.getSlice(length).toString(),
|
|
496
|
-
};
|
|
497
|
-
};
|
|
498
|
-
|
|
499
|
-
export type DefaultFlagSegment = {
|
|
500
|
-
type: 'default-flag-segment';
|
|
501
|
-
defaultFlag: boolean;
|
|
502
|
-
};
|
|
503
|
-
|
|
504
|
-
export const parseDefaultFlagSegment = (
|
|
505
|
-
iterator: BufferIterator,
|
|
506
|
-
length: number,
|
|
507
|
-
): DefaultFlagSegment => {
|
|
508
|
-
if (length !== 1) {
|
|
509
|
-
throw new Error('Expected default flag segment to be 1 byte');
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
return {
|
|
513
|
-
type: 'default-flag-segment',
|
|
514
|
-
defaultFlag: Boolean(iterator.getUint8()),
|
|
515
|
-
};
|
|
516
|
-
};
|
|
517
|
-
|
|
518
|
-
export type TagsSegment = {
|
|
519
|
-
type: 'tags-segment';
|
|
520
|
-
children: MatroskaSegment[];
|
|
521
|
-
};
|
|
522
|
-
|
|
523
|
-
export const parseTagsSegment = async (
|
|
524
|
-
iterator: BufferIterator,
|
|
525
|
-
length: number,
|
|
526
|
-
parserContext: ParserContext,
|
|
527
|
-
): Promise<TagsSegment> => {
|
|
528
|
-
const children = await expectChildren({
|
|
529
|
-
iterator,
|
|
530
|
-
length,
|
|
531
|
-
initialChildren: [],
|
|
532
|
-
wrap: null,
|
|
533
|
-
parserContext,
|
|
534
|
-
});
|
|
535
|
-
|
|
536
|
-
if (children.status === 'incomplete') {
|
|
537
|
-
throw new Error('Incomplete children');
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
return {
|
|
541
|
-
type: 'tags-segment',
|
|
542
|
-
children: children.segments as MatroskaSegment[],
|
|
543
|
-
};
|
|
544
|
-
};
|
|
545
|
-
|
|
546
|
-
export type TagSegment = {
|
|
547
|
-
type: 'tag-segment';
|
|
548
|
-
length: number;
|
|
549
|
-
};
|
|
550
|
-
|
|
551
|
-
export const parseTagSegment = (
|
|
552
|
-
iterator: BufferIterator,
|
|
553
|
-
length: number,
|
|
554
|
-
): TagSegment => {
|
|
555
|
-
iterator.discard(length);
|
|
556
|
-
|
|
557
|
-
return {
|
|
558
|
-
type: 'tag-segment',
|
|
559
|
-
length,
|
|
560
|
-
};
|
|
561
|
-
};
|
|
562
|
-
|
|
563
|
-
export type ClusterSegment = {
|
|
564
|
-
type: 'cluster-segment';
|
|
565
|
-
children: MatroskaSegment[];
|
|
566
|
-
};
|
|
567
|
-
|
|
568
|
-
export type TimestampSegment = {
|
|
569
|
-
type: 'timestamp-segment';
|
|
570
|
-
timestamp: number;
|
|
571
|
-
};
|
|
572
|
-
|
|
573
|
-
export const parseTimestampSegment = (
|
|
574
|
-
iterator: BufferIterator,
|
|
575
|
-
length: number,
|
|
576
|
-
): TimestampSegment => {
|
|
577
|
-
return {
|
|
578
|
-
type: 'timestamp-segment',
|
|
579
|
-
timestamp: iterator.getUint(length),
|
|
580
|
-
};
|
|
581
|
-
};
|
|
582
|
-
|
|
583
|
-
export type SimpleBlockOrBlockSegment = {
|
|
584
|
-
type: 'simple-block-or-block-segment';
|
|
585
|
-
length: number;
|
|
586
|
-
trackNumber: number;
|
|
587
|
-
timecodeInMicroseconds: number;
|
|
588
|
-
keyframe: boolean | null;
|
|
589
|
-
lacing: number;
|
|
590
|
-
invisible: boolean;
|
|
591
|
-
videoSample: Omit<VideoSample, 'type'> | null;
|
|
592
|
-
};
|
|
593
|
-
|
|
594
|
-
export type GetTracks = () => TrackEntrySegment[];
|
|
595
|
-
|
|
596
|
-
export const parseSimpleBlockOrBlockSegment = async ({
|
|
597
|
-
iterator,
|
|
598
|
-
length,
|
|
599
|
-
parserContext,
|
|
600
|
-
type,
|
|
601
|
-
}: {
|
|
602
|
-
iterator: BufferIterator;
|
|
603
|
-
length: number;
|
|
604
|
-
parserContext: ParserContext;
|
|
605
|
-
type:
|
|
606
|
-
| (typeof matroskaElements)['Block']
|
|
607
|
-
| (typeof matroskaElements)['SimpleBlock'];
|
|
608
|
-
}): Promise<SimpleBlockOrBlockSegment> => {
|
|
609
|
-
const start = iterator.counter.getOffset();
|
|
610
|
-
const trackNumber = iterator.getVint();
|
|
611
|
-
if (trackNumber === null) {
|
|
612
|
-
throw new Error('Not enough data to get track number, should not happen');
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
const timecodeRelativeToCluster = iterator.getUint16();
|
|
616
|
-
|
|
617
|
-
const {invisible, lacing, keyframe} = parseBlockFlags(iterator, type);
|
|
618
|
-
|
|
619
|
-
const {codec, trackTimescale} =
|
|
620
|
-
parserContext.parserState.getTrackInfoByNumber(trackNumber);
|
|
621
|
-
|
|
622
|
-
const clusterOffset =
|
|
623
|
-
parserContext.parserState.getTimestampOffsetForByteOffset(
|
|
624
|
-
iterator.counter.getOffset(),
|
|
625
|
-
);
|
|
626
|
-
|
|
627
|
-
const timescale = parserContext.parserState.getTimescale();
|
|
628
|
-
|
|
629
|
-
if (clusterOffset === undefined) {
|
|
630
|
-
throw new Error(
|
|
631
|
-
'Could not find offset for byte offset ' + iterator.counter.getOffset(),
|
|
632
|
-
);
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
// https://github.com/hubblec4/Matroska-Chapters-Specs/blob/master/notes.md/#timestampscale
|
|
636
|
-
// The TimestampScale Element is used to calculate the Raw Timestamp of a Block. The timestamp is obtained by adding the Block's timestamp to the Cluster's Timestamp Element, and then multiplying that result by the TimestampScale. The result will be the Block's Raw Timestamp in nanoseconds.
|
|
637
|
-
const timecodeInNanoSeconds =
|
|
638
|
-
(timecodeRelativeToCluster + clusterOffset) *
|
|
639
|
-
timescale *
|
|
640
|
-
(trackTimescale ?? 1);
|
|
641
|
-
|
|
642
|
-
// Timecode should be in microseconds
|
|
643
|
-
const timecodeInMicroseconds = timecodeInNanoSeconds / 1000;
|
|
644
|
-
|
|
645
|
-
if (!codec) {
|
|
646
|
-
throw new Error('Could not find codec for track ' + trackNumber);
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
const remainingNow = length - (iterator.counter.getOffset() - start);
|
|
650
|
-
|
|
651
|
-
let videoSample: Omit<VideoSample, 'type'> | null = null;
|
|
652
|
-
|
|
653
|
-
if (codec.startsWith('V_')) {
|
|
654
|
-
const partialVideoSample: Omit<VideoSample, 'type'> = {
|
|
655
|
-
data: iterator.getSlice(remainingNow),
|
|
656
|
-
cts: null,
|
|
657
|
-
dts: null,
|
|
658
|
-
duration: undefined,
|
|
659
|
-
trackId: trackNumber,
|
|
660
|
-
timestamp: timecodeInMicroseconds,
|
|
661
|
-
};
|
|
662
|
-
|
|
663
|
-
if (keyframe === null) {
|
|
664
|
-
// If we don't know if this is a keyframe, we know after we emit the BlockGroup
|
|
665
|
-
videoSample = partialVideoSample;
|
|
666
|
-
} else {
|
|
667
|
-
const sample: VideoSample = {
|
|
668
|
-
...partialVideoSample,
|
|
669
|
-
type: keyframe ? 'key' : 'delta',
|
|
670
|
-
};
|
|
671
|
-
|
|
672
|
-
await parserContext.parserState.onVideoSample(trackNumber, sample);
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
if (codec.startsWith('A_')) {
|
|
677
|
-
await parserContext.parserState.onAudioSample(trackNumber, {
|
|
678
|
-
data: iterator.getSlice(remainingNow),
|
|
679
|
-
trackId: trackNumber,
|
|
680
|
-
timestamp: timecodeInMicroseconds,
|
|
681
|
-
type: 'key',
|
|
682
|
-
});
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
const remainingNowAfter = length - (iterator.counter.getOffset() - start);
|
|
686
|
-
if (remainingNowAfter > 0) {
|
|
687
|
-
iterator.discard(remainingNowAfter);
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
return {
|
|
691
|
-
type: 'simple-block-or-block-segment',
|
|
692
|
-
length,
|
|
693
|
-
trackNumber,
|
|
694
|
-
timecodeInMicroseconds,
|
|
695
|
-
keyframe,
|
|
696
|
-
lacing,
|
|
697
|
-
invisible,
|
|
698
|
-
videoSample,
|
|
699
|
-
};
|
|
700
|
-
};
|
|
701
|
-
|
|
702
|
-
export const parseTrackNumber = (
|
|
703
|
-
iterator: BufferIterator,
|
|
704
|
-
length: number,
|
|
705
|
-
): TrackNumberSegment => {
|
|
706
|
-
if (length !== 1) {
|
|
707
|
-
throw new Error('Expected track number to be 1 byte');
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
const trackNumber = iterator.getUint8();
|
|
711
|
-
|
|
712
|
-
return {
|
|
713
|
-
type: 'track-number-segment',
|
|
714
|
-
trackNumber,
|
|
715
|
-
};
|
|
716
|
-
};
|
|
717
|
-
|
|
718
|
-
export type BlockGroupSegment = {
|
|
719
|
-
type: 'block-group-segment';
|
|
720
|
-
children: MatroskaSegment[];
|
|
721
|
-
};
|
|
722
|
-
|
|
723
|
-
export const parseBlockGroupSegment = async (
|
|
724
|
-
iterator: BufferIterator,
|
|
725
|
-
length: number,
|
|
726
|
-
parserContext: ParserContext,
|
|
727
|
-
): Promise<BlockGroupSegment> => {
|
|
728
|
-
const children = await expectChildren({
|
|
729
|
-
iterator,
|
|
730
|
-
length,
|
|
731
|
-
initialChildren: [],
|
|
732
|
-
wrap: null,
|
|
733
|
-
parserContext,
|
|
734
|
-
});
|
|
735
|
-
if (children.status === 'incomplete') {
|
|
736
|
-
throw new Error('Incomplete boxes are not allowed');
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
return {
|
|
740
|
-
type: 'block-group-segment',
|
|
741
|
-
children: children.segments as MatroskaSegment[],
|
|
742
|
-
};
|
|
743
|
-
};
|
|
744
|
-
|
|
745
|
-
export type ReferenceBlockSegment = {
|
|
746
|
-
type: 'reference-block-segment';
|
|
747
|
-
referenceBlock: number;
|
|
748
|
-
};
|
|
749
|
-
|
|
750
|
-
export const parseReferenceBlockSegment = (
|
|
751
|
-
iterator: BufferIterator,
|
|
752
|
-
length: number,
|
|
753
|
-
): ReferenceBlockSegment => {
|
|
754
|
-
if (length > 4) {
|
|
755
|
-
throw new Error(
|
|
756
|
-
`Expected reference block segment to be 4 bytes, but got ${length}`,
|
|
757
|
-
);
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
const referenceBlock =
|
|
761
|
-
length === 4
|
|
762
|
-
? iterator.getUint32()
|
|
763
|
-
: length === 3
|
|
764
|
-
? iterator.getUint24()
|
|
765
|
-
: length === 2
|
|
766
|
-
? iterator.getUint16()
|
|
767
|
-
: iterator.getUint8();
|
|
768
|
-
|
|
769
|
-
return {
|
|
770
|
-
type: 'reference-block-segment',
|
|
771
|
-
referenceBlock,
|
|
772
|
-
};
|
|
773
|
-
};
|
|
774
|
-
|
|
775
|
-
export type BlockAdditionsSegment = {
|
|
776
|
-
type: 'block-additions-segment';
|
|
777
|
-
blockAdditions: Uint8Array;
|
|
778
|
-
};
|
|
779
|
-
|
|
780
|
-
export const parseBlockAdditionsSegment = (
|
|
781
|
-
iterator: BufferIterator,
|
|
782
|
-
length: number,
|
|
783
|
-
): BlockAdditionsSegment => {
|
|
784
|
-
const blockAdditions = iterator.getSlice(length);
|
|
785
|
-
|
|
786
|
-
return {
|
|
787
|
-
type: 'block-additions-segment',
|
|
788
|
-
blockAdditions,
|
|
789
|
-
};
|
|
790
|
-
};
|
|
791
|
-
|
|
792
|
-
export type BlockElement = {
|
|
793
|
-
type: 'block-element-segment';
|
|
794
|
-
length: number;
|
|
795
|
-
};
|
|
796
|
-
|
|
797
|
-
export const parseBlockElementSegment = (
|
|
798
|
-
iterator: BufferIterator,
|
|
799
|
-
length: number,
|
|
800
|
-
): BlockElement => {
|
|
801
|
-
iterator.discard(length);
|
|
802
|
-
|
|
803
|
-
return {
|
|
804
|
-
type: 'block-element-segment',
|
|
805
|
-
length,
|
|
806
|
-
};
|
|
807
|
-
};
|
|
808
|
-
|
|
809
|
-
export type SamplingFrequencySegment = {
|
|
810
|
-
type: 'sampling-frequency-segment';
|
|
811
|
-
samplingFrequency: number;
|
|
812
|
-
};
|
|
813
|
-
|
|
814
|
-
export const parseSamplingFrequencySegment = (
|
|
815
|
-
iterator: BufferIterator,
|
|
816
|
-
length: number,
|
|
817
|
-
): SamplingFrequencySegment => {
|
|
818
|
-
if (length === 4) {
|
|
819
|
-
return {
|
|
820
|
-
type: 'sampling-frequency-segment',
|
|
821
|
-
samplingFrequency: iterator.getFloat32(),
|
|
822
|
-
};
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
if (length === 8) {
|
|
826
|
-
return {
|
|
827
|
-
type: 'sampling-frequency-segment',
|
|
828
|
-
samplingFrequency: iterator.getFloat64(),
|
|
829
|
-
};
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
throw new Error(
|
|
833
|
-
`Expected length of sampling frequency segment to be 4 or 8, got ${length}`,
|
|
834
|
-
);
|
|
835
|
-
};
|
|
836
|
-
|
|
837
|
-
export type ChannelsSegment = {
|
|
838
|
-
type: 'channels-segment';
|
|
839
|
-
channels: number;
|
|
840
|
-
};
|
|
841
|
-
|
|
842
|
-
export const parseChannelsSegment = (
|
|
843
|
-
iterator: BufferIterator,
|
|
844
|
-
length: number,
|
|
845
|
-
): ChannelsSegment => {
|
|
846
|
-
if (length !== 1) {
|
|
847
|
-
throw new Error(
|
|
848
|
-
`Expected length of channels segment to be 1, got ${length}`,
|
|
849
|
-
);
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
const channels = iterator.getUint8();
|
|
853
|
-
|
|
854
|
-
return {
|
|
855
|
-
type: 'channels-segment',
|
|
856
|
-
channels,
|
|
857
|
-
};
|
|
858
|
-
};
|
|
859
|
-
|
|
860
|
-
export type BitDepthSegment = {
|
|
861
|
-
type: 'bit-depth-segment';
|
|
862
|
-
bitDepth: number;
|
|
863
|
-
};
|
|
864
|
-
|
|
865
|
-
export const parseBitDepthSegment = (
|
|
866
|
-
iterator: BufferIterator,
|
|
867
|
-
length: number,
|
|
868
|
-
): BitDepthSegment => {
|
|
869
|
-
if (length !== 1) {
|
|
870
|
-
throw new Error(
|
|
871
|
-
`Expected length of bit depth segment to be 1, got ${length}`,
|
|
872
|
-
);
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
const bitDepth = iterator.getUint8();
|
|
876
|
-
|
|
877
|
-
return {
|
|
878
|
-
type: 'bit-depth-segment',
|
|
879
|
-
bitDepth,
|
|
880
|
-
};
|
|
881
|
-
};
|
|
38
|
+
export type GetTracks = () => TrackEntry[];
|