@remotion/media-parser 4.0.192 → 4.0.193
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/boxes.json +1 -0
- package/dist/boxes/iso-base-media/esds/esds-descriptors.d.ts +21 -0
- package/dist/boxes/iso-base-media/esds/esds-descriptors.js +62 -0
- package/dist/boxes/iso-base-media/esds/esds.d.ts +15 -0
- package/dist/boxes/iso-base-media/esds/esds.js +27 -0
- 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/process-box.js +17 -0
- package/dist/boxes/iso-base-media/stsd/samples.d.ts +2 -0
- package/dist/boxes/iso-base-media/stsd/samples.js +27 -8
- package/dist/boxes/webm/parse-webm-header.js +3 -3
- package/dist/boxes/webm/segments/track-entry.d.ts +20 -0
- package/dist/boxes/webm/segments/track-entry.js +37 -2
- package/dist/boxes/webm/segments.d.ts +2 -2
- package/dist/boxes/webm/segments.js +12 -0
- package/dist/buffer-iterator.d.ts +2 -1
- package/dist/buffer-iterator.js +27 -8
- package/dist/from-node.js +6 -2
- package/dist/from-web.js +6 -1
- package/dist/get-audio-codec.d.ts +4 -0
- package/dist/get-audio-codec.js +106 -0
- package/dist/get-dimensions.js +6 -2
- package/dist/get-fps.d.ts +1 -0
- package/dist/get-fps.js +34 -1
- package/dist/get-video-codec.js +3 -0
- package/dist/get-video-metadata.d.ts +2 -0
- package/dist/get-video-metadata.js +44 -0
- package/dist/has-all-info.d.ts +1 -1
- package/dist/has-all-info.js +4 -0
- package/dist/options.d.ts +7 -3
- package/dist/parse-media.js +23 -6
- package/dist/parse-result.d.ts +2 -1
- package/dist/read-and-increment-offset.d.ts +28 -0
- package/dist/read-and-increment-offset.js +177 -0
- package/dist/reader.d.ts +5 -1
- package/package.json +2 -2
- package/src/boxes/iso-base-media/esds/esds-descriptors.ts +104 -0
- package/src/boxes/iso-base-media/esds/esds.ts +49 -0
- package/src/boxes/iso-base-media/process-box.ts +20 -0
- package/src/boxes/iso-base-media/stsd/samples.ts +35 -8
- package/src/boxes/webm/parse-webm-header.ts +3 -3
- package/src/boxes/webm/segments/track-entry.ts +66 -1
- package/src/boxes/webm/segments.ts +29 -1
- package/src/buffer-iterator.ts +34 -10
- package/src/from-node.ts +6 -4
- package/src/from-web.ts +8 -1
- package/src/get-audio-codec.ts +143 -0
- package/src/get-dimensions.ts +11 -4
- package/src/get-fps.ts +48 -0
- package/src/get-video-codec.ts +4 -0
- package/src/has-all-info.ts +14 -2
- package/src/options.ts +18 -3
- package/src/parse-media.ts +30 -7
- package/src/parse-result.ts +3 -1
- package/src/reader.ts +5 -1
- package/src/test/matroska.test.ts +6 -7
- package/src/test/parse-esds.test.ts +75 -0
- package/src/test/stream-local.test.ts +79 -2
- package/src/test/stsd.test.ts +52 -5
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/get-codec.d.ts +0 -4
- package/dist/get-codec.js +0 -22
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type {BufferIterator} from '../../../buffer-iterator';
|
|
2
|
+
|
|
3
|
+
type AudioObjectType = 'aac' | 'mp3' | 'unknown';
|
|
4
|
+
|
|
5
|
+
type DecoderConfigDescriptor = {
|
|
6
|
+
type: 'decoder-config-descriptor';
|
|
7
|
+
objectTypeIndication: AudioObjectType;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const mapToObjectAudioIndicator = (num: number): AudioObjectType => {
|
|
11
|
+
// https://chromium.googlesource.com/chromium/src/media/+/master/formats/mp4/es_descriptor.h
|
|
12
|
+
// http://netmedia.zju.edu.cn/multimedia2013/mpeg-4/ISO%20IEC%2014496-1%20MPEG-4%20System%20Standard.pdf
|
|
13
|
+
// Page 42, table 8
|
|
14
|
+
if (num === 0x40) {
|
|
15
|
+
return 'aac';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (num === 0x6b) {
|
|
19
|
+
return 'mp3';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return 'unknown';
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
type SlConfigDescriptor = {
|
|
26
|
+
type: 'sl-config-descriptor';
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
type UnknownDescriptor = {
|
|
30
|
+
type: 'unknown-descriptor';
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type Descriptor =
|
|
34
|
+
| DecoderConfigDescriptor
|
|
35
|
+
| SlConfigDescriptor
|
|
36
|
+
| UnknownDescriptor;
|
|
37
|
+
|
|
38
|
+
type DescriptorAndNext = {
|
|
39
|
+
descriptor: Descriptor | null;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const processDescriptor = ({
|
|
43
|
+
iterator,
|
|
44
|
+
}: {
|
|
45
|
+
iterator: BufferIterator;
|
|
46
|
+
}): DescriptorAndNext => {
|
|
47
|
+
const tag = iterator.getUint8();
|
|
48
|
+
|
|
49
|
+
if (tag === 4) {
|
|
50
|
+
const size = iterator.getPaddedFourByteNumber();
|
|
51
|
+
const initialOffset = iterator.counter.getOffset();
|
|
52
|
+
|
|
53
|
+
const objectTypeIndication = iterator.getUint8();
|
|
54
|
+
|
|
55
|
+
const remaining = size - (iterator.counter.getOffset() - initialOffset);
|
|
56
|
+
iterator.discard(remaining);
|
|
57
|
+
return {
|
|
58
|
+
descriptor: {
|
|
59
|
+
type: 'decoder-config-descriptor',
|
|
60
|
+
objectTypeIndication: mapToObjectAudioIndicator(objectTypeIndication),
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (tag === 6) {
|
|
66
|
+
const size = iterator.getPaddedFourByteNumber();
|
|
67
|
+
|
|
68
|
+
iterator.discard(size);
|
|
69
|
+
return {
|
|
70
|
+
descriptor: {
|
|
71
|
+
type: 'sl-config-descriptor',
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
descriptor: null,
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const parseDescriptors = (
|
|
82
|
+
iterator: BufferIterator,
|
|
83
|
+
maxBytes: number,
|
|
84
|
+
): Descriptor[] => {
|
|
85
|
+
const descriptors: Descriptor[] = [];
|
|
86
|
+
const initialOffset = iterator.counter.getOffset();
|
|
87
|
+
|
|
88
|
+
while (
|
|
89
|
+
iterator.bytesRemaining() > 0 &&
|
|
90
|
+
iterator.counter.getOffset() - initialOffset < maxBytes
|
|
91
|
+
) {
|
|
92
|
+
const {descriptor} = processDescriptor({
|
|
93
|
+
iterator,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (descriptor) {
|
|
97
|
+
descriptors.push(descriptor);
|
|
98
|
+
} else {
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return descriptors;
|
|
104
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type {BufferIterator} from '../../../buffer-iterator';
|
|
2
|
+
import type {Descriptor} from './esds-descriptors';
|
|
3
|
+
import {parseDescriptors} from './esds-descriptors';
|
|
4
|
+
|
|
5
|
+
export interface EsdsBox {
|
|
6
|
+
type: 'esds-box';
|
|
7
|
+
version: number;
|
|
8
|
+
tag: number;
|
|
9
|
+
sizeOfInstance: number;
|
|
10
|
+
esId: number;
|
|
11
|
+
descriptors: Descriptor[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const parseEsds = ({
|
|
15
|
+
data,
|
|
16
|
+
size,
|
|
17
|
+
fileOffset,
|
|
18
|
+
}: {
|
|
19
|
+
data: BufferIterator;
|
|
20
|
+
size: number;
|
|
21
|
+
fileOffset: number;
|
|
22
|
+
}): EsdsBox => {
|
|
23
|
+
const version = data.getUint8();
|
|
24
|
+
// Flags, we discard them
|
|
25
|
+
data.discard(3);
|
|
26
|
+
const tag = data.getUint8();
|
|
27
|
+
|
|
28
|
+
const sizeOfInstance = data.getPaddedFourByteNumber();
|
|
29
|
+
const esId = data.getUint16();
|
|
30
|
+
|
|
31
|
+
// disard 1 byte, currently unknown
|
|
32
|
+
data.discard(1);
|
|
33
|
+
|
|
34
|
+
const remaining = size - (data.counter.getOffset() - fileOffset);
|
|
35
|
+
const descriptors = parseDescriptors(data, remaining);
|
|
36
|
+
|
|
37
|
+
const remainingNow = size - (data.counter.getOffset() - fileOffset);
|
|
38
|
+
|
|
39
|
+
data.discard(remainingNow);
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
type: 'esds-box',
|
|
43
|
+
version,
|
|
44
|
+
tag,
|
|
45
|
+
sizeOfInstance,
|
|
46
|
+
esId,
|
|
47
|
+
descriptors,
|
|
48
|
+
};
|
|
49
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type {BufferIterator} from '../../buffer-iterator';
|
|
2
2
|
import type {IsoBaseMediaBox, ParseResult} from '../../parse-result';
|
|
3
3
|
import type {BoxAndNext} from '../../parse-video';
|
|
4
|
+
import {parseEsds} from './esds/esds';
|
|
4
5
|
import {parseFtyp} from './ftyp';
|
|
5
6
|
import {parseMdhd} from './mdhd';
|
|
6
7
|
import {parseMoov} from './moov/moov';
|
|
@@ -25,6 +26,7 @@ const getChildren = ({
|
|
|
25
26
|
boxType === 'minf' ||
|
|
26
27
|
boxType === 'stbl' ||
|
|
27
28
|
boxType === 'dims' ||
|
|
29
|
+
boxType === 'wave' ||
|
|
28
30
|
boxType === 'stsb';
|
|
29
31
|
|
|
30
32
|
if (parseChildren) {
|
|
@@ -42,6 +44,10 @@ const getChildren = ({
|
|
|
42
44
|
return parsed.segments;
|
|
43
45
|
}
|
|
44
46
|
|
|
47
|
+
if (bytesRemainingInBox < 0) {
|
|
48
|
+
throw new Error('Box size is too big ' + JSON.stringify({boxType}));
|
|
49
|
+
}
|
|
50
|
+
|
|
45
51
|
iterator.discard(bytesRemainingInBox);
|
|
46
52
|
return [];
|
|
47
53
|
};
|
|
@@ -177,6 +183,20 @@ const processBox = ({
|
|
|
177
183
|
};
|
|
178
184
|
}
|
|
179
185
|
|
|
186
|
+
if (boxType === 'esds') {
|
|
187
|
+
const box = parseEsds({
|
|
188
|
+
data: iterator,
|
|
189
|
+
size: boxSize,
|
|
190
|
+
fileOffset,
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
type: 'complete',
|
|
195
|
+
box,
|
|
196
|
+
size: boxSize,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
180
200
|
const bytesRemainingInBox =
|
|
181
201
|
boxSize - (iterator.counter.getOffset() - fileOffset);
|
|
182
202
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type {BufferIterator} from '../../../buffer-iterator';
|
|
2
|
+
import type {AnySegment} from '../../../parse-result';
|
|
3
|
+
import {parseBoxes} from '../process-box';
|
|
2
4
|
|
|
3
5
|
type SampleBase = {
|
|
4
6
|
format: string;
|
|
@@ -21,6 +23,7 @@ type AudioSample = SampleBase & {
|
|
|
21
23
|
bytesPerPacket: number | null;
|
|
22
24
|
bytesPerFrame: number | null;
|
|
23
25
|
bitsPerSample: number | null;
|
|
26
|
+
children: AnySegment[];
|
|
24
27
|
};
|
|
25
28
|
|
|
26
29
|
type VideoSample = SampleBase & {
|
|
@@ -164,7 +167,16 @@ export const processSample = ({
|
|
|
164
167
|
|
|
165
168
|
const bytesRemainingInBox =
|
|
166
169
|
boxSize - (iterator.counter.getOffset() - fileOffset);
|
|
167
|
-
|
|
170
|
+
const children = parseBoxes({
|
|
171
|
+
iterator,
|
|
172
|
+
allowIncompleteBoxes: false,
|
|
173
|
+
maxBytes: bytesRemainingInBox,
|
|
174
|
+
initialBoxes: [],
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
if (children.status === 'incomplete') {
|
|
178
|
+
throw new Error('Incomplete boxes are not allowed');
|
|
179
|
+
}
|
|
168
180
|
|
|
169
181
|
return {
|
|
170
182
|
sample: {
|
|
@@ -185,6 +197,7 @@ export const processSample = ({
|
|
|
185
197
|
bytesPerPacket: null,
|
|
186
198
|
bytesPerFrame: null,
|
|
187
199
|
bitsPerSample: null,
|
|
200
|
+
children: children.segments,
|
|
188
201
|
},
|
|
189
202
|
};
|
|
190
203
|
}
|
|
@@ -192,17 +205,29 @@ export const processSample = ({
|
|
|
192
205
|
if (version === 1) {
|
|
193
206
|
const numberOfChannels = iterator.getUint16();
|
|
194
207
|
const sampleSize = iterator.getUint16();
|
|
195
|
-
const compressionId = iterator.
|
|
208
|
+
const compressionId = iterator.getInt16();
|
|
196
209
|
const packetSize = iterator.getUint16();
|
|
197
210
|
const sampleRate = iterator.getFixedPoint1616Number();
|
|
198
|
-
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
const
|
|
211
|
+
|
|
212
|
+
const samplesPerPacket = iterator.getUint32();
|
|
213
|
+
|
|
214
|
+
const bytesPerPacket = iterator.getUint32();
|
|
215
|
+
const bytesPerFrame = iterator.getUint32();
|
|
216
|
+
const bytesPerSample = iterator.getUint32();
|
|
202
217
|
|
|
203
218
|
const bytesRemainingInBox =
|
|
204
219
|
boxSize - (iterator.counter.getOffset() - fileOffset);
|
|
205
|
-
|
|
220
|
+
|
|
221
|
+
const children = parseBoxes({
|
|
222
|
+
iterator,
|
|
223
|
+
allowIncompleteBoxes: false,
|
|
224
|
+
maxBytes: bytesRemainingInBox,
|
|
225
|
+
initialBoxes: [],
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
if (children.status === 'incomplete') {
|
|
229
|
+
throw new Error('Incomplete boxes are not allowed');
|
|
230
|
+
}
|
|
206
231
|
|
|
207
232
|
return {
|
|
208
233
|
sample: {
|
|
@@ -222,7 +247,8 @@ export const processSample = ({
|
|
|
222
247
|
samplesPerPacket,
|
|
223
248
|
bytesPerPacket,
|
|
224
249
|
bytesPerFrame,
|
|
225
|
-
bitsPerSample,
|
|
250
|
+
bitsPerSample: bytesPerSample,
|
|
251
|
+
children: children.segments,
|
|
226
252
|
},
|
|
227
253
|
};
|
|
228
254
|
}
|
|
@@ -245,6 +271,7 @@ export const processSample = ({
|
|
|
245
271
|
|
|
246
272
|
const bytesRemainingInBox =
|
|
247
273
|
boxSize - (iterator.counter.getOffset() - fileOffset);
|
|
274
|
+
|
|
248
275
|
iterator.discard(bytesRemainingInBox);
|
|
249
276
|
|
|
250
277
|
return {
|
|
@@ -7,12 +7,12 @@ export const parseWebm = (counter: BufferIterator): ParseResult => {
|
|
|
7
7
|
counter.discard(4);
|
|
8
8
|
const length = counter.getVint();
|
|
9
9
|
|
|
10
|
-
if (length !== 31) {
|
|
11
|
-
throw new Error(`Expected header length 31, got ${length}`);
|
|
10
|
+
if (length !== 31 && length !== 35) {
|
|
11
|
+
throw new Error(`Expected header length 31 or 25, got ${length}`);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
// Discard header for now
|
|
15
|
-
counter.discard(
|
|
15
|
+
counter.discard(length);
|
|
16
16
|
|
|
17
17
|
return {status: 'done', segments: [expectSegment(counter)]};
|
|
18
18
|
};
|
|
@@ -278,7 +278,7 @@ export type ColorSegment = {
|
|
|
278
278
|
export const parseColorSegment = (iterator: BufferIterator): ColorSegment => {
|
|
279
279
|
const length = iterator.getVint();
|
|
280
280
|
|
|
281
|
-
iterator.discard(length
|
|
281
|
+
iterator.discard(length);
|
|
282
282
|
|
|
283
283
|
return {
|
|
284
284
|
type: 'color-segment',
|
|
@@ -320,3 +320,68 @@ export const parseInterlacedSegment = (
|
|
|
320
320
|
interlaced: Boolean(interlaced),
|
|
321
321
|
};
|
|
322
322
|
};
|
|
323
|
+
|
|
324
|
+
export type CodecPrivateSegment = {
|
|
325
|
+
type: 'codec-private-segment';
|
|
326
|
+
codecPrivateData: number[];
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
export const parseCodecPrivateSegment = (
|
|
330
|
+
iterator: BufferIterator,
|
|
331
|
+
): CodecPrivateSegment => {
|
|
332
|
+
const length = iterator.getVint();
|
|
333
|
+
|
|
334
|
+
return {
|
|
335
|
+
type: 'codec-private-segment',
|
|
336
|
+
codecPrivateData: [...iterator.getSlice(length)],
|
|
337
|
+
};
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
export type Crc32Segment = {
|
|
341
|
+
type: 'crc32-segment';
|
|
342
|
+
crc32: number[];
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
export const parseCrc32Segment = (iterator: BufferIterator): Crc32Segment => {
|
|
346
|
+
const length = iterator.getVint();
|
|
347
|
+
|
|
348
|
+
return {
|
|
349
|
+
type: 'crc32-segment',
|
|
350
|
+
crc32: [...iterator.getSlice(length)],
|
|
351
|
+
};
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
export type SegmentUUIDSegment = {
|
|
355
|
+
type: 'segment-uuid-segment';
|
|
356
|
+
segmentUUID: string;
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
export const parseSegmentUUIDSegment = (
|
|
360
|
+
iterator: BufferIterator,
|
|
361
|
+
): SegmentUUIDSegment => {
|
|
362
|
+
const length = iterator.getVint();
|
|
363
|
+
|
|
364
|
+
return {
|
|
365
|
+
type: 'segment-uuid-segment',
|
|
366
|
+
segmentUUID: iterator.getSlice(length).toString(),
|
|
367
|
+
};
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
export type DefaultFlagSegment = {
|
|
371
|
+
type: 'default-flag-segment';
|
|
372
|
+
defaultFlag: boolean;
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
export const parseDefaultFlagSegment = (
|
|
376
|
+
iterator: BufferIterator,
|
|
377
|
+
): DefaultFlagSegment => {
|
|
378
|
+
const length = iterator.getVint();
|
|
379
|
+
if (length !== 1) {
|
|
380
|
+
throw new Error('Expected default flag segment to be 1 byte');
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
return {
|
|
384
|
+
type: 'default-flag-segment',
|
|
385
|
+
defaultFlag: Boolean(iterator.getUint8()),
|
|
386
|
+
};
|
|
387
|
+
};
|
|
@@ -17,14 +17,18 @@ import type {TimestampScaleSegment} from './segments/timestamp-scale';
|
|
|
17
17
|
import {parseTimestampScaleSegment} from './segments/timestamp-scale';
|
|
18
18
|
import type {
|
|
19
19
|
AlphaModeSegment,
|
|
20
|
+
CodecPrivateSegment,
|
|
20
21
|
CodecSegment,
|
|
21
22
|
ColorSegment,
|
|
23
|
+
Crc32Segment,
|
|
22
24
|
DefaultDurationSegment,
|
|
25
|
+
DefaultFlagSegment,
|
|
23
26
|
FlagLacingSegment,
|
|
24
27
|
HeightSegment,
|
|
25
28
|
InterlacedSegment,
|
|
26
29
|
LanguageSegment,
|
|
27
30
|
MaxBlockAdditionId,
|
|
31
|
+
SegmentUUIDSegment,
|
|
28
32
|
TitleSegment,
|
|
29
33
|
TrackEntrySegment,
|
|
30
34
|
TrackNumberSegment,
|
|
@@ -35,14 +39,18 @@ import type {
|
|
|
35
39
|
} from './segments/track-entry';
|
|
36
40
|
import {
|
|
37
41
|
parseAlphaModeSegment,
|
|
42
|
+
parseCodecPrivateSegment,
|
|
38
43
|
parseCodecSegment,
|
|
39
44
|
parseColorSegment,
|
|
45
|
+
parseCrc32Segment,
|
|
40
46
|
parseDefaultDurationSegment,
|
|
47
|
+
parseDefaultFlagSegment,
|
|
41
48
|
parseFlagLacing,
|
|
42
49
|
parseHeightSegment,
|
|
43
50
|
parseInterlacedSegment,
|
|
44
51
|
parseLanguageSegment,
|
|
45
52
|
parseMaxBlockAdditionId,
|
|
53
|
+
parseSegmentUUIDSegment,
|
|
46
54
|
parseTitleSegment,
|
|
47
55
|
parseTrackEntry,
|
|
48
56
|
parseTrackNumber,
|
|
@@ -88,7 +96,11 @@ export type MatroskaSegment =
|
|
|
88
96
|
| MaxBlockAdditionId
|
|
89
97
|
| ColorSegment
|
|
90
98
|
| TitleSegment
|
|
91
|
-
| InterlacedSegment
|
|
99
|
+
| InterlacedSegment
|
|
100
|
+
| CodecPrivateSegment
|
|
101
|
+
| Crc32Segment
|
|
102
|
+
| SegmentUUIDSegment
|
|
103
|
+
| DefaultFlagSegment;
|
|
92
104
|
|
|
93
105
|
export const expectSegment = (iterator: BufferIterator): MatroskaSegment => {
|
|
94
106
|
const segmentId = iterator.getMatroskaSegmentId();
|
|
@@ -203,10 +215,26 @@ export const expectSegment = (iterator: BufferIterator): MatroskaSegment => {
|
|
|
203
215
|
return parseAlphaModeSegment(iterator);
|
|
204
216
|
}
|
|
205
217
|
|
|
218
|
+
if (segmentId === '0x63a2') {
|
|
219
|
+
return parseCodecPrivateSegment(iterator);
|
|
220
|
+
}
|
|
221
|
+
|
|
206
222
|
if (segmentId === '0x7ba9') {
|
|
207
223
|
return parseTitleSegment(iterator);
|
|
208
224
|
}
|
|
209
225
|
|
|
226
|
+
if (segmentId === '0xbf') {
|
|
227
|
+
return parseCrc32Segment(iterator);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (segmentId === '0x73a4') {
|
|
231
|
+
return parseSegmentUUIDSegment(iterator);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (segmentId === '0x88') {
|
|
235
|
+
return parseDefaultFlagSegment(iterator);
|
|
236
|
+
}
|
|
237
|
+
|
|
210
238
|
const length = iterator.getVint();
|
|
211
239
|
|
|
212
240
|
const bytesRemaining = iterator.byteLength() - iterator.counter.getOffset();
|
package/src/buffer-iterator.ts
CHANGED
|
@@ -48,8 +48,16 @@ const makeOffsetCounter = (): OffsetCounter => {
|
|
|
48
48
|
return new OffsetCounter(0);
|
|
49
49
|
};
|
|
50
50
|
|
|
51
|
-
export const getArrayBufferIterator = (
|
|
52
|
-
|
|
51
|
+
export const getArrayBufferIterator = (
|
|
52
|
+
initialData: Uint8Array,
|
|
53
|
+
maxBytes?: number,
|
|
54
|
+
) => {
|
|
55
|
+
const buf = new ArrayBuffer(initialData.byteLength, {
|
|
56
|
+
maxByteLength: maxBytes ?? 1_000_000_000,
|
|
57
|
+
});
|
|
58
|
+
let data = new Uint8Array(buf);
|
|
59
|
+
data.set(initialData);
|
|
60
|
+
|
|
53
61
|
let view = new DataView(data.buffer);
|
|
54
62
|
const counter = makeOffsetCounter();
|
|
55
63
|
|
|
@@ -76,6 +84,15 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
76
84
|
);
|
|
77
85
|
};
|
|
78
86
|
|
|
87
|
+
const getPaddedFourByteNumber = () => {
|
|
88
|
+
let lastInt = 128;
|
|
89
|
+
while (((lastInt = getUint8()), lastInt === 128)) {
|
|
90
|
+
// Do nothing
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return lastInt;
|
|
94
|
+
};
|
|
95
|
+
|
|
79
96
|
const getUint32 = () => {
|
|
80
97
|
const val = view.getUint32(counter.getDiscardedOffset());
|
|
81
98
|
counter.increment(4);
|
|
@@ -83,11 +100,11 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
83
100
|
};
|
|
84
101
|
|
|
85
102
|
const addData = (newData: Uint8Array) => {
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
);
|
|
89
|
-
newArray
|
|
90
|
-
newArray.set(
|
|
103
|
+
const oldLength = buf.byteLength;
|
|
104
|
+
const newLength = oldLength + newData.byteLength;
|
|
105
|
+
buf.resize(newLength);
|
|
106
|
+
const newArray = new Uint8Array(buf);
|
|
107
|
+
newArray.set(newData, oldLength);
|
|
91
108
|
data = newArray;
|
|
92
109
|
view = new DataView(data.buffer);
|
|
93
110
|
};
|
|
@@ -111,9 +128,9 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
111
128
|
const removeBytesRead = () => {
|
|
112
129
|
const bytesToRemove = counter.getDiscardedOffset();
|
|
113
130
|
counter.discardBytes(bytesToRemove);
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
131
|
+
const newData = data.slice(bytesToRemove);
|
|
132
|
+
data.set(newData);
|
|
133
|
+
buf.resize(newData.byteLength);
|
|
117
134
|
view = new DataView(data.buffer);
|
|
118
135
|
};
|
|
119
136
|
|
|
@@ -134,6 +151,7 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
134
151
|
const atom = getSlice(4);
|
|
135
152
|
return new TextDecoder().decode(atom);
|
|
136
153
|
},
|
|
154
|
+
getPaddedFourByteNumber,
|
|
137
155
|
getMatroskaSegmentId: () => {
|
|
138
156
|
const first = getSlice(1);
|
|
139
157
|
const firstOneString = `0x${Array.from(new Uint8Array(first))
|
|
@@ -155,6 +173,9 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
155
173
|
'0xb0',
|
|
156
174
|
'0xba',
|
|
157
175
|
'0x9a',
|
|
176
|
+
'0xe1',
|
|
177
|
+
'0xbf',
|
|
178
|
+
'0x88',
|
|
158
179
|
];
|
|
159
180
|
if (knownIdsWithOneLength.includes(firstOneString)) {
|
|
160
181
|
return firstOneString;
|
|
@@ -174,6 +195,8 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
174
195
|
'0x55ee',
|
|
175
196
|
'0x55b0',
|
|
176
197
|
'0x7ba9',
|
|
198
|
+
'0x63a2',
|
|
199
|
+
'0x73a4',
|
|
177
200
|
];
|
|
178
201
|
|
|
179
202
|
const firstTwoString = `${firstOneString}${Array.from(
|
|
@@ -267,6 +290,7 @@ export const getArrayBufferIterator = (initialData: Uint8Array) => {
|
|
|
267
290
|
counter.increment(2);
|
|
268
291
|
return val;
|
|
269
292
|
},
|
|
293
|
+
|
|
270
294
|
getInt16: () => {
|
|
271
295
|
const val = view.getInt16(counter.getDiscardedOffset());
|
|
272
296
|
counter.increment(2);
|
package/src/from-node.ts
CHANGED
|
@@ -4,16 +4,18 @@ import {Readable} from 'stream';
|
|
|
4
4
|
import type {ReaderInterface} from './reader';
|
|
5
5
|
|
|
6
6
|
export const nodeReader: ReaderInterface = {
|
|
7
|
-
read: (src, range) => {
|
|
7
|
+
read: async (src, range) => {
|
|
8
8
|
const stream = createReadStream(src, {
|
|
9
9
|
start: range === null ? 0 : range[0],
|
|
10
10
|
end: range === null ? Infinity : range[1],
|
|
11
11
|
});
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
const stats = await stat(src);
|
|
13
|
+
return {
|
|
14
|
+
reader: Readable.toWeb(
|
|
14
15
|
stream,
|
|
15
16
|
).getReader() as ReadableStreamDefaultReader<Uint8Array>,
|
|
16
|
-
|
|
17
|
+
contentLength: stats.size,
|
|
18
|
+
};
|
|
17
19
|
},
|
|
18
20
|
getLength: async (src) => {
|
|
19
21
|
const stats = await stat(src);
|
package/src/from-web.ts
CHANGED
|
@@ -31,9 +31,16 @@ export const webReader: ReaderInterface = {
|
|
|
31
31
|
throw new Error('No body');
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
const length = res.headers.get('content-length');
|
|
35
|
+
if (!length) {
|
|
36
|
+
throw new Error('No content-length');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const contentLength = length === null ? null : parseInt(length, 10);
|
|
40
|
+
|
|
34
41
|
const reader = res.body.getReader();
|
|
35
42
|
|
|
36
|
-
return reader;
|
|
43
|
+
return {reader, contentLength};
|
|
37
44
|
},
|
|
38
45
|
getLength: async (src) => {
|
|
39
46
|
const res = await fetch(src, {
|