@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.
- package/dist/av1-codec-string.d.ts +5 -0
- package/dist/av1-codec-string.js +18 -1
- package/dist/bitstream/av1.d.ts +2 -0
- package/dist/bitstream/av1.js +12 -0
- package/dist/boxes/iso-base-media/avcc-hvcc.d.ts +20 -0
- package/dist/boxes/iso-base-media/avcc-hvcc.js +73 -0
- package/dist/boxes/iso-base-media/avcc.d.ts +18 -0
- package/dist/boxes/iso-base-media/avcc.js +27 -0
- package/dist/boxes/iso-base-media/esds-descriptors.d.ts +21 -0
- package/dist/boxes/iso-base-media/esds-descriptors.js +62 -0
- package/dist/boxes/iso-base-media/esds.d.ts +15 -0
- package/dist/boxes/iso-base-media/esds.js +27 -0
- package/dist/boxes/iso-base-media/mdat/mdat.js +2 -2
- package/dist/boxes/iso-base-media/moov/moov.js +1 -0
- package/dist/boxes/iso-base-media/process-box.d.ts +4 -2
- package/dist/boxes/iso-base-media/process-box.js +56 -40
- package/dist/boxes/iso-base-media/stsd/mebx.d.ts +2 -1
- package/dist/boxes/iso-base-media/stsd/mebx.js +2 -1
- package/dist/boxes/iso-base-media/stsd/samples.js +3 -0
- package/dist/boxes/iso-base-media/stsd/stco.d.ts +3 -2
- package/dist/boxes/iso-base-media/stsd/stco.js +2 -2
- package/dist/boxes/iso-base-media/trak/trak.js +1 -0
- package/dist/boxes/webm/bitstream/av1.js +10 -1
- package/dist/boxes/webm/ebml.d.ts +2 -0
- package/dist/boxes/webm/ebml.js +72 -0
- package/dist/boxes/webm/make-header.d.ts +9 -0
- package/dist/boxes/webm/make-header.js +79 -0
- package/dist/boxes/webm/parse-ebml.d.ts +7 -0
- package/dist/boxes/webm/parse-ebml.js +66 -0
- package/dist/boxes/webm/parse-webm-header.js +8 -9
- package/dist/boxes/webm/segments/all-segments.d.ts +262 -0
- package/dist/boxes/webm/segments/all-segments.js +130 -1
- package/dist/boxes/webm/segments/block-simple-block-flags.d.ts +9 -0
- package/dist/boxes/webm/segments/block-simple-block-flags.js +38 -0
- package/dist/boxes/webm/segments/seek-position.js +1 -1
- package/dist/boxes/webm/segments/seek.d.ts +1 -1
- package/dist/boxes/webm/segments/seek.js +8 -2
- package/dist/boxes/webm/segments/timestamp-scale.js +1 -1
- package/dist/boxes/webm/segments/track-entry.d.ts +25 -9
- package/dist/boxes/webm/segments/track-entry.js +73 -33
- package/dist/boxes/webm/segments.d.ts +3 -3
- package/dist/boxes/webm/segments.js +64 -30
- package/dist/boxes/webm/traversal.d.ts +1 -0
- package/dist/boxes/webm/traversal.js +12 -1
- package/dist/buffer-iterator.d.ts +10 -6
- package/dist/buffer-iterator.js +92 -9
- package/dist/from-fetch.js +13 -3
- package/dist/from-input-type-file.d.ts +2 -0
- package/dist/from-input-type-file.js +37 -0
- package/dist/from-node.js +9 -2
- package/dist/from-web-file.js +6 -1
- package/dist/from-web.js +15 -6
- package/dist/get-codec.d.ts +4 -0
- package/dist/get-codec.js +22 -0
- package/dist/get-sample-positions.js +1 -1
- package/dist/has-all-info.js +1 -1
- package/dist/options.d.ts +3 -2
- package/dist/parse-media.js +13 -9
- package/dist/parse-video.js +16 -0
- package/dist/parser-state.d.ts +8 -9
- package/dist/parser-state.js +39 -19
- package/dist/reader.d.ts +1 -1
- package/dist/web-file.d.ts +2 -0
- package/dist/web-file.js +37 -0
- package/dist/webcodec-sample-types.d.ts +0 -1
- package/package.json +2 -2
- package/src/boxes/iso-base-media/mdat/mdat.ts +2 -2
- package/src/boxes/iso-base-media/moov/moov.ts +1 -0
- package/src/boxes/iso-base-media/process-box.ts +70 -40
- package/src/boxes/iso-base-media/stsd/mebx.ts +3 -0
- package/src/boxes/iso-base-media/stsd/samples.ts +3 -0
- package/src/boxes/iso-base-media/stsd/stco.ts +5 -3
- package/src/boxes/iso-base-media/trak/trak.ts +1 -0
- package/src/boxes/webm/ebml.ts +78 -0
- package/src/boxes/webm/make-header.ts +138 -0
- package/src/boxes/webm/parse-ebml.ts +93 -0
- package/src/boxes/webm/parse-webm-header.ts +8 -12
- package/src/boxes/webm/segments/all-segments.ts +226 -0
- package/src/boxes/webm/segments/block-simple-block-flags.ts +52 -0
- package/src/boxes/webm/segments/seek-position.ts +1 -1
- package/src/boxes/webm/segments/seek.ts +12 -2
- package/src/boxes/webm/segments/timestamp-scale.ts +1 -1
- package/src/boxes/webm/segments/track-entry.ts +125 -41
- package/src/boxes/webm/segments.ts +107 -40
- package/src/boxes/webm/traversal.ts +13 -0
- package/src/buffer-iterator.ts +110 -10
- package/src/from-fetch.ts +22 -3
- package/src/from-node.ts +18 -4
- package/src/from-web-file.ts +11 -1
- package/src/get-sample-positions.ts +1 -1
- package/src/has-all-info.ts +1 -1
- package/src/options.ts +3 -2
- package/src/parse-media.ts +14 -8
- package/src/parse-video.ts +17 -0
- package/src/parser-state.ts +52 -25
- package/src/reader.ts +1 -0
- package/src/test/create-matroska.test.ts +48 -0
- package/src/test/matroska.test.ts +144 -127
- package/src/test/parse-stco.test.ts +2 -0
- package/src/test/stream-local.test.ts +70 -14
- package/src/test/stream-remote.test.ts +23 -19
- package/src/test/stsd.test.ts +2 -0
- package/src/webcodec-sample-types.ts +0 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/boxes/iso-base-media/ftype.d.ts +0 -9
- package/dist/boxes/iso-base-media/ftype.js +0 -31
- package/dist/get-video-metadata.d.ts +0 -2
- package/dist/get-video-metadata.js +0 -44
- package/dist/read-and-increment-offset.d.ts +0 -28
- package/dist/read-and-increment-offset.js +0 -177
- package/dist/understand-vorbis.d.ts +0 -1
- package/dist/understand-vorbis.js +0 -12
- package/src/boxes/webm/segments/unknown.ts +0 -19
- /package/dist/{boxes/webm/bitstream/av1/frame.d.ts → get-samples.d.ts} +0 -0
- /package/dist/{boxes/webm/bitstream/av1/frame.js → get-samples.js} +0 -0
- /package/dist/{boxes/webm/bitstream/h264/get-h264-descriptor.d.ts → sample-aspect-ratio.d.ts} +0 -0
- /package/dist/{boxes/webm/bitstream/h264/get-h264-descriptor.js → sample-aspect-ratio.js} +0 -0
package/dist/parser-state.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.makeParserState = void 0;
|
|
4
4
|
const traversal_1 = require("./boxes/webm/traversal");
|
|
5
5
|
const traversal_2 = require("./traversal");
|
|
6
|
-
const makeParserState = ({ hasAudioCallbacks, hasVideoCallbacks, }) => {
|
|
6
|
+
const makeParserState = ({ hasAudioCallbacks, hasVideoCallbacks, signal, }) => {
|
|
7
7
|
const trackEntries = {};
|
|
8
8
|
const onTrackEntrySegment = (trackEntry) => {
|
|
9
9
|
const trackId = (0, traversal_2.getTrackId)(trackEntry);
|
|
@@ -17,24 +17,48 @@ const makeParserState = ({ hasAudioCallbacks, hasVideoCallbacks, }) => {
|
|
|
17
17
|
if (!codec) {
|
|
18
18
|
throw new Error('Expected codec');
|
|
19
19
|
}
|
|
20
|
-
|
|
20
|
+
const trackTimescale = (0, traversal_1.getTrackTimestampScale)(trackEntry);
|
|
21
|
+
trackEntries[trackId] = {
|
|
22
|
+
codec: codec.codec,
|
|
23
|
+
trackTimescale,
|
|
24
|
+
};
|
|
21
25
|
};
|
|
22
26
|
const videoSampleCallbacks = {};
|
|
23
27
|
const audioSampleCallbacks = {};
|
|
24
|
-
let samplesThatHadToBeQueued = 0;
|
|
25
28
|
const queuedAudioSamples = {};
|
|
26
29
|
const queuedVideoSamples = {};
|
|
27
30
|
const declinedTrackNumbers = [];
|
|
28
31
|
let timescale = null;
|
|
29
32
|
const getTimescale = () => {
|
|
33
|
+
// https://www.matroska.org/technical/notes.html
|
|
34
|
+
// When using the default value of TimestampScale of “1,000,000”, one Segment Tick represents one millisecond.
|
|
30
35
|
if (timescale === null) {
|
|
31
|
-
|
|
36
|
+
return 1000000;
|
|
32
37
|
}
|
|
33
38
|
return timescale;
|
|
34
39
|
};
|
|
35
40
|
const setTimescale = (newTimescale) => {
|
|
36
41
|
timescale = newTimescale;
|
|
37
42
|
};
|
|
43
|
+
const timestampMap = new Map();
|
|
44
|
+
const setTimestampOffset = (byteOffset, timestamp) => {
|
|
45
|
+
timestampMap.set(byteOffset, timestamp);
|
|
46
|
+
};
|
|
47
|
+
const getTimestampOffsetForByteOffset = (byteOffset) => {
|
|
48
|
+
const entries = Array.from(timestampMap.entries());
|
|
49
|
+
const sortedByByteOffset = entries
|
|
50
|
+
.sort((a, b) => {
|
|
51
|
+
return a[0] - b[0];
|
|
52
|
+
})
|
|
53
|
+
.reverse();
|
|
54
|
+
for (const [offset, timestamp] of sortedByByteOffset) {
|
|
55
|
+
if (offset >= byteOffset) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
return timestamp;
|
|
59
|
+
}
|
|
60
|
+
return timestampMap.get(byteOffset);
|
|
61
|
+
};
|
|
38
62
|
return {
|
|
39
63
|
onTrackEntrySegment,
|
|
40
64
|
getTrackInfoByNumber: (id) => trackEntries[id],
|
|
@@ -51,6 +75,8 @@ const makeParserState = ({ hasAudioCallbacks, hasVideoCallbacks, }) => {
|
|
|
51
75
|
}
|
|
52
76
|
queuedVideoSamples[id] = [];
|
|
53
77
|
},
|
|
78
|
+
setTimestampOffset,
|
|
79
|
+
getTimestampOffsetForByteOffset,
|
|
54
80
|
registerAudioSampleCallback: async (id, callback) => {
|
|
55
81
|
var _a;
|
|
56
82
|
if (callback === null) {
|
|
@@ -65,7 +91,9 @@ const makeParserState = ({ hasAudioCallbacks, hasVideoCallbacks, }) => {
|
|
|
65
91
|
queuedAudioSamples[id] = [];
|
|
66
92
|
},
|
|
67
93
|
onAudioSample: async (trackId, audioSample) => {
|
|
68
|
-
|
|
94
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
95
|
+
throw new Error('Aborted');
|
|
96
|
+
}
|
|
69
97
|
const callback = audioSampleCallbacks[trackId];
|
|
70
98
|
if (callback) {
|
|
71
99
|
await callback(audioSample);
|
|
@@ -75,15 +103,14 @@ const makeParserState = ({ hasAudioCallbacks, hasVideoCallbacks, }) => {
|
|
|
75
103
|
return;
|
|
76
104
|
}
|
|
77
105
|
if (!hasAudioCallbacks) {
|
|
78
|
-
|
|
106
|
+
throw new Error('No audio callbacks registered');
|
|
79
107
|
}
|
|
80
|
-
(_a = queuedAudioSamples[trackId]) !== null && _a !== void 0 ? _a : (queuedAudioSamples[trackId] = []);
|
|
81
|
-
queuedAudioSamples[trackId].push(audioSample);
|
|
82
|
-
samplesThatHadToBeQueued++;
|
|
83
108
|
}
|
|
84
109
|
},
|
|
85
110
|
onVideoSample: async (trackId, videoSample) => {
|
|
86
|
-
|
|
111
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
112
|
+
throw new Error('Aborted');
|
|
113
|
+
}
|
|
87
114
|
const callback = videoSampleCallbacks[trackId];
|
|
88
115
|
if (callback) {
|
|
89
116
|
await callback(videoSample);
|
|
@@ -93,18 +120,11 @@ const makeParserState = ({ hasAudioCallbacks, hasVideoCallbacks, }) => {
|
|
|
93
120
|
return;
|
|
94
121
|
}
|
|
95
122
|
if (!hasVideoCallbacks) {
|
|
96
|
-
|
|
123
|
+
throw new Error('No video callbacks registered');
|
|
97
124
|
}
|
|
98
|
-
(_a = queuedVideoSamples[trackId]) !== null && _a !== void 0 ? _a : (queuedVideoSamples[trackId] = []);
|
|
99
|
-
queuedVideoSamples[trackId].push(videoSample);
|
|
100
|
-
samplesThatHadToBeQueued++;
|
|
101
125
|
}
|
|
102
126
|
},
|
|
103
|
-
getInternalStats: () => {
|
|
104
|
-
return {
|
|
105
|
-
samplesThatHadToBeQueued,
|
|
106
|
-
};
|
|
107
|
-
},
|
|
127
|
+
getInternalStats: () => ({}),
|
|
108
128
|
getTimescale,
|
|
109
129
|
setTimescale,
|
|
110
130
|
};
|
package/dist/reader.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ type ReadResult = {
|
|
|
2
2
|
reader: ReadableStreamDefaultReader<Uint8Array>;
|
|
3
3
|
contentLength: number | null;
|
|
4
4
|
};
|
|
5
|
-
type ReadContent = (src: string | File, range: [number, number] | number | null) => Promise<ReadResult>;
|
|
5
|
+
type ReadContent = (src: string | File, range: [number, number] | number | null, signal: AbortSignal | undefined) => Promise<ReadResult>;
|
|
6
6
|
type GetLength = (src: string | File) => Promise<number>;
|
|
7
7
|
export type ReaderInterface = {
|
|
8
8
|
read: ReadContent;
|
package/dist/web-file.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.inputTypeFileReader = void 0;
|
|
4
|
+
exports.inputTypeFileReader = {
|
|
5
|
+
read: (file, range) => {
|
|
6
|
+
if (typeof file === 'string') {
|
|
7
|
+
throw new Error('`inputTypeFileReader` only supports `File` objects');
|
|
8
|
+
}
|
|
9
|
+
if (range !== null) {
|
|
10
|
+
throw new Error('`inputTypeFileReader` does not support `range`');
|
|
11
|
+
}
|
|
12
|
+
const part = range === null
|
|
13
|
+
? file
|
|
14
|
+
: typeof range === 'number'
|
|
15
|
+
? file.slice(range)
|
|
16
|
+
: file.slice(range[0], range[1]);
|
|
17
|
+
const reader = new FileReader();
|
|
18
|
+
reader.readAsArrayBuffer(file);
|
|
19
|
+
return new Promise((resolve, reject) => {
|
|
20
|
+
reader.onload = () => {
|
|
21
|
+
resolve({
|
|
22
|
+
reader: part.stream().getReader(),
|
|
23
|
+
contentLength: file.size,
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
reader.onerror = (error) => {
|
|
27
|
+
reject(error);
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
getLength: (src) => {
|
|
32
|
+
if (typeof src === 'string') {
|
|
33
|
+
throw new Error('`inputTypeFileReader` only supports `File` objects');
|
|
34
|
+
}
|
|
35
|
+
return Promise.resolve(src.size);
|
|
36
|
+
},
|
|
37
|
+
};
|
package/package.json
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
"url": "https://github.com/remotion-dev/remotion/tree/main/packages/media-parser"
|
|
4
4
|
},
|
|
5
5
|
"name": "@remotion/media-parser",
|
|
6
|
-
"version": "4.0.
|
|
6
|
+
"version": "4.0.201",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"sideEffects": false,
|
|
9
9
|
"devDependencies": {
|
|
10
|
-
"@remotion/renderer": "4.0.
|
|
10
|
+
"@remotion/renderer": "4.0.201"
|
|
11
11
|
},
|
|
12
12
|
"publishConfig": {
|
|
13
13
|
"access": "public"
|
|
@@ -26,7 +26,7 @@ export const parseMdat = async ({
|
|
|
26
26
|
}): Promise<MdatBox> => {
|
|
27
27
|
const alreadyHas = hasTracks(existingBoxes);
|
|
28
28
|
if (!alreadyHas) {
|
|
29
|
-
data.discard(size -
|
|
29
|
+
data.discard(size - (data.counter.getOffset() - fileOffset));
|
|
30
30
|
return Promise.resolve({
|
|
31
31
|
type: 'mdat-box',
|
|
32
32
|
boxSize: size,
|
|
@@ -91,7 +91,6 @@ export const parseMdat = async ({
|
|
|
91
91
|
await options.parserState.onAudioSample(sampleWithIndex.track.trackId, {
|
|
92
92
|
data: bytes,
|
|
93
93
|
timestamp: sampleWithIndex.samplePosition.offset,
|
|
94
|
-
offset: data.counter.getOffset(),
|
|
95
94
|
trackId: sampleWithIndex.track.trackId,
|
|
96
95
|
type: sampleWithIndex.samplePosition.isKeyframe ? 'key' : 'delta',
|
|
97
96
|
});
|
|
@@ -117,6 +116,7 @@ export const parseMdat = async ({
|
|
|
117
116
|
}
|
|
118
117
|
|
|
119
118
|
const remaining = size - (data.counter.getOffset() - fileOffset);
|
|
119
|
+
data.removeBytesRead();
|
|
120
120
|
if (remaining === 0) {
|
|
121
121
|
break;
|
|
122
122
|
}
|
|
@@ -37,11 +37,13 @@ const getChildren = async ({
|
|
|
37
37
|
iterator,
|
|
38
38
|
bytesRemainingInBox,
|
|
39
39
|
options,
|
|
40
|
+
littleEndian,
|
|
40
41
|
}: {
|
|
41
42
|
boxType: string;
|
|
42
43
|
iterator: BufferIterator;
|
|
43
44
|
bytesRemainingInBox: number;
|
|
44
45
|
options: ParserContext;
|
|
46
|
+
littleEndian: boolean;
|
|
45
47
|
}) => {
|
|
46
48
|
const parseChildren =
|
|
47
49
|
boxType === 'mdia' ||
|
|
@@ -59,6 +61,7 @@ const getChildren = async ({
|
|
|
59
61
|
initialBoxes: [],
|
|
60
62
|
options,
|
|
61
63
|
continueMdat: false,
|
|
64
|
+
littleEndian,
|
|
62
65
|
});
|
|
63
66
|
|
|
64
67
|
if (parsed.status === 'incomplete') {
|
|
@@ -121,17 +124,37 @@ export const processBox = async ({
|
|
|
121
124
|
allowIncompleteBoxes,
|
|
122
125
|
parsedBoxes,
|
|
123
126
|
options,
|
|
127
|
+
littleEndian,
|
|
124
128
|
}: {
|
|
125
129
|
iterator: BufferIterator;
|
|
126
130
|
allowIncompleteBoxes: boolean;
|
|
127
131
|
parsedBoxes: AnySegment[];
|
|
128
132
|
options: ParserContext;
|
|
133
|
+
littleEndian: boolean;
|
|
129
134
|
}): Promise<BoxAndNext> => {
|
|
130
135
|
const fileOffset = iterator.counter.getOffset();
|
|
131
136
|
const bytesRemaining = iterator.bytesRemaining();
|
|
132
137
|
|
|
133
|
-
const
|
|
134
|
-
|
|
138
|
+
const boxSizeRaw = iterator.getFourByteNumber(littleEndian);
|
|
139
|
+
|
|
140
|
+
// If `boxSize === 1`, the 8 bytes after the box type are the size of the box.
|
|
141
|
+
if (
|
|
142
|
+
(boxSizeRaw === 1 && iterator.bytesRemaining() < 12) ||
|
|
143
|
+
iterator.bytesRemaining() < 4
|
|
144
|
+
) {
|
|
145
|
+
iterator.counter.decrement(iterator.counter.getOffset() - fileOffset);
|
|
146
|
+
if (allowIncompleteBoxes) {
|
|
147
|
+
return {
|
|
148
|
+
type: 'incomplete',
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
throw new Error(
|
|
153
|
+
`Expected box size of ${bytesRemaining}, got ${boxSizeRaw}. Incomplete boxes are not allowed.`,
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (boxSizeRaw === 0) {
|
|
135
158
|
return {
|
|
136
159
|
type: 'complete',
|
|
137
160
|
box: {
|
|
@@ -143,42 +166,41 @@ export const processBox = async ({
|
|
|
143
166
|
};
|
|
144
167
|
}
|
|
145
168
|
|
|
169
|
+
const boxType = iterator.getByteString(4);
|
|
170
|
+
|
|
171
|
+
const boxSize =
|
|
172
|
+
boxSizeRaw === 1 ? iterator.getEightByteNumber(littleEndian) : boxSizeRaw;
|
|
173
|
+
|
|
146
174
|
if (bytesRemaining < boxSize) {
|
|
147
|
-
if (
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
},
|
|
168
|
-
size: boxSize,
|
|
169
|
-
skipTo: fileOffset + boxSize,
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
} else {
|
|
173
|
-
iterator.discard(4);
|
|
174
|
-
return parseMdatPartially({
|
|
175
|
-
iterator,
|
|
176
|
-
boxSize,
|
|
177
|
-
fileOffset,
|
|
178
|
-
parsedBoxes,
|
|
179
|
-
options,
|
|
180
|
-
});
|
|
175
|
+
if (boxType === 'mdat') {
|
|
176
|
+
const shouldSkip = options.canSkipVideoData || !hasTracks(parsedBoxes);
|
|
177
|
+
|
|
178
|
+
if (shouldSkip) {
|
|
179
|
+
const skipTo = fileOffset + boxSize;
|
|
180
|
+
const bytesToSkip = skipTo - iterator.counter.getOffset();
|
|
181
|
+
|
|
182
|
+
// If there is a huge mdat chunk, we can skip it because we don't need it for the metadata
|
|
183
|
+
if (bytesToSkip > 1_000_000) {
|
|
184
|
+
return {
|
|
185
|
+
type: 'complete',
|
|
186
|
+
box: {
|
|
187
|
+
type: 'mdat-box',
|
|
188
|
+
boxSize,
|
|
189
|
+
fileOffset,
|
|
190
|
+
samplesProcessed: false,
|
|
191
|
+
},
|
|
192
|
+
size: boxSize,
|
|
193
|
+
skipTo: fileOffset + boxSize,
|
|
194
|
+
};
|
|
181
195
|
}
|
|
196
|
+
} else {
|
|
197
|
+
return parseMdatPartially({
|
|
198
|
+
iterator,
|
|
199
|
+
boxSize,
|
|
200
|
+
fileOffset,
|
|
201
|
+
parsedBoxes,
|
|
202
|
+
options,
|
|
203
|
+
});
|
|
182
204
|
}
|
|
183
205
|
}
|
|
184
206
|
|
|
@@ -194,8 +216,6 @@ export const processBox = async ({
|
|
|
194
216
|
);
|
|
195
217
|
}
|
|
196
218
|
|
|
197
|
-
const boxType = iterator.getByteString(4);
|
|
198
|
-
|
|
199
219
|
if (boxType === 'ftyp') {
|
|
200
220
|
const box = parseFtyp({iterator, size: boxSize, offset: fileOffset});
|
|
201
221
|
return {
|
|
@@ -271,11 +291,12 @@ export const processBox = async ({
|
|
|
271
291
|
};
|
|
272
292
|
}
|
|
273
293
|
|
|
274
|
-
if (boxType === 'stco') {
|
|
294
|
+
if (boxType === 'stco' || boxType === 'co64') {
|
|
275
295
|
const box = parseStco({
|
|
276
296
|
iterator,
|
|
277
297
|
offset: fileOffset,
|
|
278
298
|
size: boxSize,
|
|
299
|
+
mode64Bit: boxType === 'co64',
|
|
279
300
|
});
|
|
280
301
|
|
|
281
302
|
return {
|
|
@@ -352,6 +373,7 @@ export const processBox = async ({
|
|
|
352
373
|
offset: fileOffset,
|
|
353
374
|
size: boxSize,
|
|
354
375
|
options,
|
|
376
|
+
littleEndian,
|
|
355
377
|
});
|
|
356
378
|
|
|
357
379
|
return {
|
|
@@ -525,6 +547,7 @@ export const processBox = async ({
|
|
|
525
547
|
iterator,
|
|
526
548
|
bytesRemainingInBox,
|
|
527
549
|
options,
|
|
550
|
+
littleEndian,
|
|
528
551
|
});
|
|
529
552
|
|
|
530
553
|
return {
|
|
@@ -548,6 +571,7 @@ export const parseBoxes = async ({
|
|
|
548
571
|
initialBoxes,
|
|
549
572
|
options,
|
|
550
573
|
continueMdat,
|
|
574
|
+
littleEndian,
|
|
551
575
|
}: {
|
|
552
576
|
iterator: BufferIterator;
|
|
553
577
|
maxBytes: number;
|
|
@@ -555,6 +579,7 @@ export const parseBoxes = async ({
|
|
|
555
579
|
initialBoxes: IsoBaseMediaBox[];
|
|
556
580
|
options: ParserContext;
|
|
557
581
|
continueMdat: false | PartialMdatBox;
|
|
582
|
+
littleEndian: boolean;
|
|
558
583
|
}): Promise<ParseResult> => {
|
|
559
584
|
let boxes: IsoBaseMediaBox[] = initialBoxes;
|
|
560
585
|
const initialOffset = iterator.counter.getOffset();
|
|
@@ -577,6 +602,7 @@ export const parseBoxes = async ({
|
|
|
577
602
|
allowIncompleteBoxes,
|
|
578
603
|
parsedBoxes: initialBoxes,
|
|
579
604
|
options,
|
|
605
|
+
littleEndian,
|
|
580
606
|
});
|
|
581
607
|
|
|
582
608
|
if (result.type === 'incomplete') {
|
|
@@ -595,6 +621,7 @@ export const parseBoxes = async ({
|
|
|
595
621
|
initialBoxes: boxes,
|
|
596
622
|
options,
|
|
597
623
|
continueMdat: false,
|
|
624
|
+
littleEndian,
|
|
598
625
|
});
|
|
599
626
|
},
|
|
600
627
|
skipTo: null,
|
|
@@ -614,6 +641,7 @@ export const parseBoxes = async ({
|
|
|
614
641
|
initialBoxes: boxes,
|
|
615
642
|
options,
|
|
616
643
|
continueMdat: result,
|
|
644
|
+
littleEndian,
|
|
617
645
|
}),
|
|
618
646
|
);
|
|
619
647
|
},
|
|
@@ -641,13 +669,14 @@ export const parseBoxes = async ({
|
|
|
641
669
|
initialBoxes: boxes,
|
|
642
670
|
options,
|
|
643
671
|
continueMdat: false,
|
|
672
|
+
littleEndian,
|
|
644
673
|
});
|
|
645
674
|
},
|
|
646
675
|
skipTo: result.skipTo,
|
|
647
676
|
};
|
|
648
677
|
}
|
|
649
678
|
|
|
650
|
-
iterator.
|
|
679
|
+
iterator.removeBytesRead();
|
|
651
680
|
}
|
|
652
681
|
|
|
653
682
|
const mdatState = hasSkippedMdatProcessing(boxes);
|
|
@@ -663,6 +692,7 @@ export const parseBoxes = async ({
|
|
|
663
692
|
initialBoxes: boxes,
|
|
664
693
|
options,
|
|
665
694
|
continueMdat: false,
|
|
695
|
+
littleEndian,
|
|
666
696
|
});
|
|
667
697
|
},
|
|
668
698
|
skipTo: mdatState.fileOffset,
|
|
@@ -16,11 +16,13 @@ export const parseMebx = async ({
|
|
|
16
16
|
offset,
|
|
17
17
|
size,
|
|
18
18
|
options,
|
|
19
|
+
littleEndian,
|
|
19
20
|
}: {
|
|
20
21
|
iterator: BufferIterator;
|
|
21
22
|
offset: number;
|
|
22
23
|
size: number;
|
|
23
24
|
options: ParserContext;
|
|
25
|
+
littleEndian: boolean;
|
|
24
26
|
}): Promise<MebxBox> => {
|
|
25
27
|
// reserved, 6 bit
|
|
26
28
|
iterator.discard(6);
|
|
@@ -34,6 +36,7 @@ export const parseMebx = async ({
|
|
|
34
36
|
initialBoxes: [],
|
|
35
37
|
options,
|
|
36
38
|
continueMdat: false,
|
|
39
|
+
littleEndian,
|
|
37
40
|
});
|
|
38
41
|
|
|
39
42
|
if (children.status === 'incomplete') {
|
|
@@ -179,6 +179,7 @@ export const processSample = async ({
|
|
|
179
179
|
initialBoxes: [],
|
|
180
180
|
options,
|
|
181
181
|
continueMdat: false,
|
|
182
|
+
littleEndian: false,
|
|
182
183
|
});
|
|
183
184
|
|
|
184
185
|
if (children.status === 'incomplete') {
|
|
@@ -232,6 +233,7 @@ export const processSample = async ({
|
|
|
232
233
|
initialBoxes: [],
|
|
233
234
|
options,
|
|
234
235
|
continueMdat: false,
|
|
236
|
+
littleEndian: false,
|
|
235
237
|
});
|
|
236
238
|
|
|
237
239
|
if (children.status === 'incomplete') {
|
|
@@ -288,6 +290,7 @@ export const processSample = async ({
|
|
|
288
290
|
initialBoxes: [],
|
|
289
291
|
options,
|
|
290
292
|
continueMdat: false,
|
|
293
|
+
littleEndian: false,
|
|
291
294
|
});
|
|
292
295
|
|
|
293
296
|
if (children.status === 'incomplete') {
|
|
@@ -6,17 +6,19 @@ export interface StcoBox extends BaseBox {
|
|
|
6
6
|
version: number;
|
|
7
7
|
flags: number[];
|
|
8
8
|
entryCount: number;
|
|
9
|
-
entries: number[];
|
|
9
|
+
entries: (number | bigint)[];
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export const parseStco = ({
|
|
13
13
|
iterator,
|
|
14
14
|
offset,
|
|
15
15
|
size,
|
|
16
|
+
mode64Bit,
|
|
16
17
|
}: {
|
|
17
18
|
iterator: BufferIterator;
|
|
18
19
|
offset: number;
|
|
19
20
|
size: number;
|
|
21
|
+
mode64Bit: boolean;
|
|
20
22
|
}): StcoBox => {
|
|
21
23
|
const version = iterator.getUint8();
|
|
22
24
|
if (version !== 0) {
|
|
@@ -26,14 +28,14 @@ export const parseStco = ({
|
|
|
26
28
|
const flags = iterator.getSlice(3);
|
|
27
29
|
const entryCount = iterator.getUint32();
|
|
28
30
|
|
|
29
|
-
const entries: number[] = [];
|
|
31
|
+
const entries: (number | bigint)[] = [];
|
|
30
32
|
for (let i = 0; i < entryCount; i++) {
|
|
31
33
|
const bytesRemaining = size - (iterator.counter.getOffset() - offset);
|
|
32
34
|
if (bytesRemaining < 4) {
|
|
33
35
|
break;
|
|
34
36
|
}
|
|
35
37
|
|
|
36
|
-
entries.push(iterator.getUint32());
|
|
38
|
+
entries.push(mode64Bit ? iterator.getUint64() : iterator.getUint32());
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
iterator.discard(size - (iterator.counter.getOffset() - offset));
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// https://github.com/Vanilagy/webm-muxer/blob/main/src/ebml.ts#L101
|
|
2
|
+
|
|
3
|
+
export const measureEBMLVarInt = (value: number) => {
|
|
4
|
+
if (value < (1 << 7) - 1) {
|
|
5
|
+
/** Top bit is set, leaving 7 bits to hold the integer, but we can't store
|
|
6
|
+
* 127 because "all bits set to one" is a reserved value. Same thing for the
|
|
7
|
+
* other cases below:
|
|
8
|
+
*/
|
|
9
|
+
return 1;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (value < (1 << 14) - 1) {
|
|
13
|
+
return 2;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (value < (1 << 21) - 1) {
|
|
17
|
+
return 3;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (value < (1 << 28) - 1) {
|
|
21
|
+
return 4;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (value < 2 ** 35 - 1) {
|
|
25
|
+
return 5;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (value < 2 ** 42 - 1) {
|
|
29
|
+
return 6;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
throw new Error('EBML VINT size not supported ' + value);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const getVariableInt = (
|
|
36
|
+
value: number,
|
|
37
|
+
width: number = measureEBMLVarInt(value),
|
|
38
|
+
) => {
|
|
39
|
+
switch (width) {
|
|
40
|
+
case 1:
|
|
41
|
+
return new Uint8Array([(1 << 7) | value]);
|
|
42
|
+
case 2:
|
|
43
|
+
return new Uint8Array([(1 << 6) | (value >> 8), value]);
|
|
44
|
+
case 3:
|
|
45
|
+
return new Uint8Array([(1 << 5) | (value >> 16), value >> 8, value]);
|
|
46
|
+
case 4:
|
|
47
|
+
return new Uint8Array([
|
|
48
|
+
(1 << 4) | (value >> 24),
|
|
49
|
+
value >> 16,
|
|
50
|
+
value >> 8,
|
|
51
|
+
value,
|
|
52
|
+
]);
|
|
53
|
+
case 5:
|
|
54
|
+
/**
|
|
55
|
+
* JavaScript converts its doubles to 32-bit integers for bitwise
|
|
56
|
+
* operations, so we need to do a division by 2^32 instead of a
|
|
57
|
+
* right-shift of 32 to retain those top 3 bits
|
|
58
|
+
*/
|
|
59
|
+
return new Uint8Array([
|
|
60
|
+
(1 << 3) | ((value / 2 ** 32) & 0x7),
|
|
61
|
+
value >> 24,
|
|
62
|
+
value >> 16,
|
|
63
|
+
value >> 8,
|
|
64
|
+
value,
|
|
65
|
+
]);
|
|
66
|
+
case 6:
|
|
67
|
+
return new Uint8Array([
|
|
68
|
+
(1 << 2) | ((value / 2 ** 40) & 0x3),
|
|
69
|
+
(value / 2 ** 32) | 0,
|
|
70
|
+
value >> 24,
|
|
71
|
+
value >> 16,
|
|
72
|
+
value >> 8,
|
|
73
|
+
value,
|
|
74
|
+
]);
|
|
75
|
+
default:
|
|
76
|
+
throw new Error('Bad EBML VINT size ' + width);
|
|
77
|
+
}
|
|
78
|
+
};
|