video-fps-probe 0.3.0 → 0.4.0-beta.2
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/CHANGELOG.md +72 -0
- package/README.md +19 -11
- package/dist/analyze.js +10 -1
- package/dist/api/codes.d.ts +6 -0
- package/dist/api/codes.js +90 -0
- package/dist/aspect/index.d.ts +13 -0
- package/dist/aspect/index.js +180 -0
- package/dist/aspect/rational.js +61 -0
- package/dist/cjs/analyze.d.cts +9 -0
- package/dist/cjs/api/agreement.d.cts +18 -0
- package/dist/cjs/api/codes.d.cts +6 -0
- package/dist/cjs/api/errors.d.cts +12 -0
- package/dist/cjs/api/guards.d.cts +4 -0
- package/dist/cjs/api/summary.d.cts +22 -0
- package/dist/cjs/aspect/index.d.cts +13 -0
- package/dist/cjs/aspect.cjs +1 -0
- package/dist/cjs/check/index.d.cts +60 -0
- package/dist/cjs/check.cjs +1 -0
- package/dist/cjs/chunks/boxes-B0T2nt3e.cjs +1 -0
- package/dist/cjs/chunks/build-DhETwJLO.cjs +1 -0
- package/dist/cjs/chunks/color-xqJHSfhZ.cjs +1 -0
- package/dist/cjs/chunks/compare-B_HKNwqg.cjs +1 -0
- package/dist/cjs/chunks/config-CSbXzEqr.cjs +1 -0
- package/dist/cjs/chunks/errors-0oBg1Ai6.cjs +1 -0
- package/dist/cjs/chunks/fallback-CyPIR3RM.cjs +1 -0
- package/dist/cjs/chunks/guards-DbQNcAZS.cjs +1 -0
- package/dist/cjs/chunks/inline-Bx-TQg8f.cjs +1 -0
- package/dist/cjs/chunks/isobmff-4RrRf9N-.cjs +1 -0
- package/dist/cjs/chunks/matroska-BhgWtuPU.cjs +1 -0
- package/dist/cjs/chunks/metadata-ECdzNLkE.cjs +1 -0
- package/dist/cjs/chunks/options-B_vLHxHd.cjs +1 -0
- package/dist/cjs/chunks/probe-Cn1DtL-C.cjs +1 -0
- package/dist/cjs/chunks/rational-Dq5Vza-Q.cjs +1 -0
- package/dist/cjs/chunks/reader-Dw11ozVU.cjs +1 -0
- package/dist/cjs/chunks/rfps-C-pyKnu8.cjs +1 -0
- package/dist/cjs/chunks/runtime-BgAlQQee.cjs +1 -0
- package/dist/cjs/chunks/segments-B1H6bDz-.cjs +1 -0
- package/dist/cjs/chunks/sniff-CXwqOGwh.cjs +1 -0
- package/dist/cjs/chunks/stats-DW7dVdFa.cjs +1 -0
- package/dist/cjs/client/types.d.cts +96 -0
- package/dist/cjs/color/index.d.cts +7 -0
- package/dist/cjs/color.cjs +1 -0
- package/dist/cjs/core/reader.d.cts +47 -0
- package/dist/cjs/core/types.d.cts +194 -0
- package/dist/cjs/engines/types.d.cts +69 -0
- package/dist/cjs/header/index.d.cts +28 -0
- package/dist/cjs/header/limits.d.cts +26 -0
- package/dist/cjs/header.cjs +1 -0
- package/dist/cjs/index.cjs +1 -0
- package/dist/cjs/index.d.cts +13 -0
- package/dist/cjs/plugins/types.d.cts +17 -0
- package/dist/cjs/presets/index.d.cts +19 -0
- package/dist/cjs/presets.cjs +1 -0
- package/dist/cjs/probe.d.cts +3 -0
- package/dist/cjs/url/index.d.cts +47 -0
- package/dist/cjs/url.cjs +1 -0
- package/dist/cjs/worker/protocol.d.cts +47 -0
- package/dist/color/codec-string.js +121 -0
- package/dist/color/config.js +199 -0
- package/dist/color/index.d.ts +7 -0
- package/dist/color/index.js +139 -0
- package/dist/color/names.js +33 -0
- package/dist/color/sps.js +275 -0
- package/dist/core/dispatch.js +18 -29
- package/dist/core/isobmff/boxes.js +6 -5
- package/dist/core/isobmff/build.js +401 -0
- package/dist/core/isobmff/config.js +34 -0
- package/dist/core/isobmff/header.js +677 -0
- package/dist/core/isobmff/index.js +9 -381
- package/dist/core/isobmff/moof.js +2 -2
- package/dist/core/isobmff/moov.js +3 -3
- package/dist/core/matroska/header.js +10 -4
- package/dist/core/matroska/index.js +11 -5
- package/dist/core/options.js +1 -0
- package/dist/core/reader.d.ts +3 -0
- package/dist/core/reader.js +13 -7
- package/dist/core/result.js +1 -0
- package/dist/core/stats.js +3 -0
- package/dist/core/types.d.ts +60 -1
- package/dist/engines/common.js +2 -0
- package/dist/header/index.d.ts +28 -0
- package/dist/header/index.js +182 -0
- package/dist/header/limits.d.ts +26 -0
- package/dist/header/limits.js +144 -0
- package/dist/header/metadata.js +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/standalone/own-isobmff.worker.js +1 -1
- package/dist/standalone/own-matroska.worker.js +1 -1
- package/dist/standalone/own.worker.js +1 -1
- package/dist/url/index.d.ts +47 -0
- package/dist/url/index.js +335 -0
- package/dist/worker/single.js +2 -1
- package/package.json +117 -2
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { u16 } from "./config.js";
|
|
2
|
+
const H264_HIGH_PROFILES = new Set([100, 110, 122, 244, 44, 83, 86, 118, 128, 138, 139, 134, 135, 144]);
|
|
3
|
+
const PIXEL_ASPECT = [0, 1, 1, 1, 12, 11, 10, 11, 16, 11, 40, 33, 24, 11, 20, 11, 32, 11, 80, 33, 18, 11, 15, 11, 64, 33, 160, 99, 4, 3, 3, 2, 2, 1];
|
|
4
|
+
const EXTENDED_SAR = 255;
|
|
5
|
+
const GIVE_UP = new RangeError();
|
|
6
|
+
const HEVC_SPS_NAL = 33;
|
|
7
|
+
export function unescapeRbsp(nal) {
|
|
8
|
+
const out = new Uint8Array(nal.length);
|
|
9
|
+
let n = 0;
|
|
10
|
+
let zeros = 0;
|
|
11
|
+
for (const byte of nal) {
|
|
12
|
+
if (zeros >= 2 && byte === 3) {
|
|
13
|
+
zeros = 0;
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
out[n++] = byte;
|
|
17
|
+
zeros = byte === 0 ? zeros + 1 : 0;
|
|
18
|
+
}
|
|
19
|
+
return out.subarray(0, n);
|
|
20
|
+
}
|
|
21
|
+
export function bitReader(b, start = 0) {
|
|
22
|
+
let pos = start * 8;
|
|
23
|
+
const end = b.length * 8;
|
|
24
|
+
const bit = () => {
|
|
25
|
+
check(pos < end);
|
|
26
|
+
const v = (b[pos >> 3] >> (7 - (pos & 7))) & 1;
|
|
27
|
+
pos++;
|
|
28
|
+
return v;
|
|
29
|
+
};
|
|
30
|
+
const bits = (n) => {
|
|
31
|
+
let v = 0;
|
|
32
|
+
for (let i = 0; i < n; i++)
|
|
33
|
+
v = v * 2 + bit();
|
|
34
|
+
return v;
|
|
35
|
+
};
|
|
36
|
+
const skip = (n) => {
|
|
37
|
+
check(pos + n <= end);
|
|
38
|
+
pos += n;
|
|
39
|
+
};
|
|
40
|
+
const ue = (max = 0xfffffffe) => {
|
|
41
|
+
let zeros = 0;
|
|
42
|
+
while (bit() === 0)
|
|
43
|
+
check(++zeros < 32);
|
|
44
|
+
const v = 2 ** zeros - 1 + bits(zeros);
|
|
45
|
+
check(v <= max);
|
|
46
|
+
return v;
|
|
47
|
+
};
|
|
48
|
+
const se = () => {
|
|
49
|
+
const k = ue();
|
|
50
|
+
return k & 1 ? (k + 1) / 2 : k ? -k / 2 : 0;
|
|
51
|
+
};
|
|
52
|
+
return { bit, bits, skip, ue, se };
|
|
53
|
+
}
|
|
54
|
+
function check(ok) {
|
|
55
|
+
if (!ok)
|
|
56
|
+
throw GIVE_UP;
|
|
57
|
+
}
|
|
58
|
+
function readVui(r) {
|
|
59
|
+
const { bit, bits, skip } = r;
|
|
60
|
+
const vui = { sar: null, fullRange: null, colour: null };
|
|
61
|
+
if (bit()) {
|
|
62
|
+
const idc = bits(8);
|
|
63
|
+
const sar = idc === EXTENDED_SAR ? [bits(16), bits(16)] : [PIXEL_ASPECT[idc * 2] ?? 0, PIXEL_ASPECT[idc * 2 + 1] ?? 0];
|
|
64
|
+
vui.sar = sar[0] > 0 && sar[1] > 0 ? [sar[0], sar[1]] : null;
|
|
65
|
+
}
|
|
66
|
+
if (bit())
|
|
67
|
+
skip(1);
|
|
68
|
+
if (bit()) {
|
|
69
|
+
skip(3);
|
|
70
|
+
vui.fullRange = bit() === 1;
|
|
71
|
+
if (bit())
|
|
72
|
+
vui.colour = [bits(8), bits(8), bits(8)];
|
|
73
|
+
}
|
|
74
|
+
return vui;
|
|
75
|
+
}
|
|
76
|
+
function skipH264ScalingList(r, size) {
|
|
77
|
+
const { se } = r;
|
|
78
|
+
let last = 8;
|
|
79
|
+
let next = 8;
|
|
80
|
+
for (let j = 0; j < size; j++) {
|
|
81
|
+
if (next !== 0)
|
|
82
|
+
next = (last + se() + 256) % 256;
|
|
83
|
+
last = next === 0 ? last : next;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export function parseH264Sps(nal) {
|
|
87
|
+
try {
|
|
88
|
+
const r = bitReader(unescapeRbsp(nal), 1);
|
|
89
|
+
const { bit, bits, skip, ue, se } = r;
|
|
90
|
+
const profile = bits(8);
|
|
91
|
+
skip(16);
|
|
92
|
+
ue(31);
|
|
93
|
+
let bitDepth = 8;
|
|
94
|
+
if (H264_HIGH_PROFILES.has(profile)) {
|
|
95
|
+
const chroma = ue(3);
|
|
96
|
+
if (chroma === 3)
|
|
97
|
+
skip(1);
|
|
98
|
+
bitDepth = ue(6) + 8;
|
|
99
|
+
check(ue(6) + 8 === bitDepth);
|
|
100
|
+
skip(1);
|
|
101
|
+
if (bit())
|
|
102
|
+
for (let i = 0; i < (chroma === 3 ? 12 : 8); i++)
|
|
103
|
+
if (bit())
|
|
104
|
+
skipH264ScalingList(r, i < 6 ? 16 : 64);
|
|
105
|
+
}
|
|
106
|
+
ue(12);
|
|
107
|
+
const poc = ue(2);
|
|
108
|
+
if (poc === 0)
|
|
109
|
+
ue(12);
|
|
110
|
+
else if (poc === 1) {
|
|
111
|
+
skip(1);
|
|
112
|
+
se();
|
|
113
|
+
se();
|
|
114
|
+
const cycle = ue(255);
|
|
115
|
+
for (let i = 0; i < cycle; i++)
|
|
116
|
+
se();
|
|
117
|
+
}
|
|
118
|
+
ue(16);
|
|
119
|
+
skip(1);
|
|
120
|
+
ue();
|
|
121
|
+
ue();
|
|
122
|
+
if (!bit())
|
|
123
|
+
skip(1);
|
|
124
|
+
skip(1);
|
|
125
|
+
if (bit())
|
|
126
|
+
for (let i = 0; i < 4; i++)
|
|
127
|
+
ue();
|
|
128
|
+
return { bitDepth, vui: bit() ? readVui(r) : null };
|
|
129
|
+
}
|
|
130
|
+
catch (e) {
|
|
131
|
+
if (e === GIVE_UP)
|
|
132
|
+
return null;
|
|
133
|
+
throw e;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function skipProfileTierLevel(r, maxSubLayersMinus1) {
|
|
137
|
+
const { bit, skip } = r;
|
|
138
|
+
skip(88);
|
|
139
|
+
skip(8);
|
|
140
|
+
const present = [];
|
|
141
|
+
for (let i = 0; i < maxSubLayersMinus1; i++)
|
|
142
|
+
present.push([bit(), bit()]);
|
|
143
|
+
if (maxSubLayersMinus1 > 0)
|
|
144
|
+
skip(2 * (8 - maxSubLayersMinus1));
|
|
145
|
+
for (const [profile, level] of present) {
|
|
146
|
+
if (profile)
|
|
147
|
+
skip(88);
|
|
148
|
+
if (level)
|
|
149
|
+
skip(8);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
function skipHevcScalingListData(r) {
|
|
153
|
+
const { bit, ue, se } = r;
|
|
154
|
+
for (let size = 0; size < 4; size++) {
|
|
155
|
+
for (let matrix = 0; matrix < 6; matrix += size === 3 ? 3 : 1) {
|
|
156
|
+
if (!bit()) {
|
|
157
|
+
const delta = ue();
|
|
158
|
+
check(matrix - delta * (size === 3 ? 3 : 1) >= 0);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
const coefs = Math.min(64, 1 << (4 + (size << 1)));
|
|
162
|
+
if (size > 1) {
|
|
163
|
+
const dc = se();
|
|
164
|
+
check(dc >= -7 && dc <= 247);
|
|
165
|
+
}
|
|
166
|
+
for (let i = 0; i < coefs; i++)
|
|
167
|
+
se();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const HEVC_MAX_REFS = 16;
|
|
173
|
+
const HEVC_MAX_DELTA_POCS = 32;
|
|
174
|
+
function skipShortTermRefPicSets(r, count) {
|
|
175
|
+
const { bit, skip, ue } = r;
|
|
176
|
+
const deltaPocs = [];
|
|
177
|
+
for (let idx = 0; idx < count; idx++) {
|
|
178
|
+
if (idx > 0 && bit()) {
|
|
179
|
+
skip(1);
|
|
180
|
+
ue(32767);
|
|
181
|
+
let k = 0;
|
|
182
|
+
for (let j = 0; j <= deltaPocs[idx - 1]; j++) {
|
|
183
|
+
const used = bit();
|
|
184
|
+
if (used || bit())
|
|
185
|
+
k++;
|
|
186
|
+
}
|
|
187
|
+
check(k < HEVC_MAX_DELTA_POCS);
|
|
188
|
+
deltaPocs.push(k);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
const negative = ue(HEVC_MAX_REFS - 1);
|
|
192
|
+
const positive = ue(HEVC_MAX_REFS - 1);
|
|
193
|
+
for (let i = 0; i < negative + positive; i++) {
|
|
194
|
+
ue(32767);
|
|
195
|
+
skip(1);
|
|
196
|
+
}
|
|
197
|
+
deltaPocs.push(negative + positive);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
export function parseHevcSps(nal) {
|
|
202
|
+
try {
|
|
203
|
+
const r = bitReader(unescapeRbsp(nal), 2);
|
|
204
|
+
const { bit, bits, skip, ue } = r;
|
|
205
|
+
skip(4);
|
|
206
|
+
const maxSubLayersMinus1 = bits(3);
|
|
207
|
+
check(maxSubLayersMinus1 < 7);
|
|
208
|
+
skip(1);
|
|
209
|
+
skipProfileTierLevel(r, maxSubLayersMinus1);
|
|
210
|
+
ue(15);
|
|
211
|
+
const chroma = ue(3);
|
|
212
|
+
if (chroma === 3)
|
|
213
|
+
skip(1);
|
|
214
|
+
ue();
|
|
215
|
+
ue();
|
|
216
|
+
if (bit())
|
|
217
|
+
for (let i = 0; i < 4; i++)
|
|
218
|
+
ue();
|
|
219
|
+
const bitDepth = ue(8) + 8;
|
|
220
|
+
const chromaDepth = ue(8) + 8;
|
|
221
|
+
check(chroma === 0 || chromaDepth === bitDepth);
|
|
222
|
+
const pocLsbBits = ue(12) + 4;
|
|
223
|
+
const ordering = bit();
|
|
224
|
+
for (let i = ordering ? 0 : maxSubLayersMinus1; i <= maxSubLayersMinus1; i++) {
|
|
225
|
+
ue();
|
|
226
|
+
ue();
|
|
227
|
+
ue();
|
|
228
|
+
}
|
|
229
|
+
for (let i = 0; i < 6; i++)
|
|
230
|
+
ue();
|
|
231
|
+
if (bit() && bit())
|
|
232
|
+
skipHevcScalingListData(r);
|
|
233
|
+
skip(2);
|
|
234
|
+
if (bit()) {
|
|
235
|
+
skip(8);
|
|
236
|
+
ue();
|
|
237
|
+
ue();
|
|
238
|
+
skip(1);
|
|
239
|
+
}
|
|
240
|
+
skipShortTermRefPicSets(r, ue(64));
|
|
241
|
+
if (bit()) {
|
|
242
|
+
const longTerm = ue(32);
|
|
243
|
+
for (let i = 0; i < longTerm; i++)
|
|
244
|
+
skip(pocLsbBits + 1);
|
|
245
|
+
}
|
|
246
|
+
skip(2);
|
|
247
|
+
return { bitDepth, vui: bit() ? readVui(r) : null };
|
|
248
|
+
}
|
|
249
|
+
catch (e) {
|
|
250
|
+
if (e === GIVE_UP)
|
|
251
|
+
return null;
|
|
252
|
+
throw e;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
export function avcConfigSps(b, s) {
|
|
256
|
+
const len = s.end - s.start >= 8 && b[s.start + 5] & 31 ? u16(b, s.start + 6) : -1;
|
|
257
|
+
return len >= 0 && s.start + 8 + len <= s.end ? parseH264Sps(b.subarray(s.start + 8, s.start + 8 + len)) : null;
|
|
258
|
+
}
|
|
259
|
+
export function hevcConfigSps(b, s) {
|
|
260
|
+
let q = s.start + 23;
|
|
261
|
+
for (let a = 0, arrays = s.end - s.start >= 23 ? b[s.start + 22] : 0; a < arrays && q + 3 <= s.end; a++) {
|
|
262
|
+
const type = b[q] & 63;
|
|
263
|
+
const count = u16(b, q + 1);
|
|
264
|
+
q += 3;
|
|
265
|
+
for (let i = 0; i < count && q + 2 <= s.end; i++) {
|
|
266
|
+
const len = u16(b, q);
|
|
267
|
+
if (q + 2 + len > s.end)
|
|
268
|
+
return null;
|
|
269
|
+
if (type === HEVC_SPS_NAL)
|
|
270
|
+
return parseHevcSps(b.subarray(q + 2, q + 2 + len));
|
|
271
|
+
q += 2 + len;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return null;
|
|
275
|
+
}
|
package/dist/core/dispatch.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { throwIfAborted } from "./abort.js";
|
|
2
2
|
import { resolveOptions } from "./options.js";
|
|
3
|
-
import { BlobReader } from "./reader.js";
|
|
3
|
+
import { BlobReader, whichErrorCode, withErrorCode } from "./reader.js";
|
|
4
4
|
import { emptyAnalysis } from "./result.js";
|
|
5
5
|
import { sniff } from "./sniff.js";
|
|
6
6
|
const SNIFF_BYTES = 1024;
|
|
@@ -18,17 +18,6 @@ export function errorMessage(e) {
|
|
|
18
18
|
return e.message || e.name;
|
|
19
19
|
return String(e);
|
|
20
20
|
}
|
|
21
|
-
function applyAnalysis(target, a) {
|
|
22
|
-
target.container = a.container;
|
|
23
|
-
target.brand = a.brand;
|
|
24
|
-
target.formatDurationSec = a.formatDurationSec;
|
|
25
|
-
target.scan = a.scan;
|
|
26
|
-
target.videoTracks = a.videoTracks;
|
|
27
|
-
target.audioTrackCount = a.audioTrackCount;
|
|
28
|
-
target.primaryTrackId = a.primaryTrackId;
|
|
29
|
-
target.error = a.error;
|
|
30
|
-
target.warnings = a.warnings;
|
|
31
|
-
}
|
|
32
21
|
export async function analyzeWith(blob, name, opts, analyzerOf) {
|
|
33
22
|
const t0 = performance.now();
|
|
34
23
|
const resolved = resolveOptions(opts);
|
|
@@ -37,35 +26,35 @@ export async function analyzeWith(blob, name, opts, analyzerOf) {
|
|
|
37
26
|
name,
|
|
38
27
|
size: blob.size,
|
|
39
28
|
...emptyAnalysis('unknown'),
|
|
29
|
+
errorCode: null,
|
|
30
|
+
layout: null,
|
|
40
31
|
io: { reads: 0, bytesRead: 0, ms: 0 },
|
|
41
32
|
engine: 'own',
|
|
42
33
|
};
|
|
43
34
|
let reader = null;
|
|
44
35
|
let loadMs = 0;
|
|
36
|
+
let loading = false;
|
|
45
37
|
try {
|
|
46
38
|
reader = new BlobReader(blob, { headWindow: resolved.readAhead.head, signal: resolved.signal });
|
|
47
|
-
if (reader.size === 0)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
loadMs = performance.now() - l0;
|
|
61
|
-
applyAnalysis(result, await analyzer(reader, resolved));
|
|
62
|
-
}
|
|
63
|
-
}
|
|
39
|
+
if (reader.size === 0)
|
|
40
|
+
throw withErrorCode('empty-file', 'not a recognised container: empty file');
|
|
41
|
+
const head = await reader.bytes(0, Math.min(SNIFF_BYTES, reader.size), firstReadAhead(reader.size, resolved));
|
|
42
|
+
const sniffed = sniff(head);
|
|
43
|
+
if (sniffed.kind === 'unknown')
|
|
44
|
+
throw withErrorCode('unrecognised', `not a recognised container: ${sniffed.reason}`);
|
|
45
|
+
result.container = sniffed.kind === 'isobmff' ? 'mp4' : 'matroska';
|
|
46
|
+
const l0 = performance.now();
|
|
47
|
+
loading = true;
|
|
48
|
+
const analyzer = await analyzerOf(sniffed.kind);
|
|
49
|
+
loading = false;
|
|
50
|
+
loadMs = performance.now() - l0;
|
|
51
|
+
Object.assign(result, await analyzer(reader, resolved));
|
|
64
52
|
}
|
|
65
53
|
catch (e) {
|
|
66
54
|
if (resolved.signal?.aborted || isAbortError(e))
|
|
67
55
|
throw e;
|
|
68
56
|
result.error = errorMessage(e);
|
|
57
|
+
result.errorCode = whichErrorCode(e, loading ? 'load-failed' : 'internal');
|
|
69
58
|
}
|
|
70
59
|
if (reader) {
|
|
71
60
|
result.io.reads = reader.reads;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { fourcc } from "../reader.js";
|
|
2
2
|
export class IsoBmffError extends Error {
|
|
3
|
-
constructor(message) {
|
|
3
|
+
constructor(code, message) {
|
|
4
4
|
super(message);
|
|
5
5
|
this.name = 'IsoBmffError';
|
|
6
|
+
this.errorCode = code;
|
|
6
7
|
}
|
|
7
8
|
}
|
|
8
9
|
export const MAX_BOX_HEADER = 32;
|
|
@@ -19,7 +20,7 @@ export function readBoxHeader(dv, p, parentEnd, base = 0) {
|
|
|
19
20
|
return null;
|
|
20
21
|
const big = dv.getBigUint64(p + 8);
|
|
21
22
|
if (big > BigInt(Number.MAX_SAFE_INTEGER))
|
|
22
|
-
throw new IsoBmffError(`corrupt file: box '${type}' at ${base + p} has a size above 2^53-1`);
|
|
23
|
+
throw new IsoBmffError('corrupt', `corrupt file: box '${type}' at ${base + p} has a size above 2^53-1`);
|
|
23
24
|
size = Number(big);
|
|
24
25
|
headerSize = 16;
|
|
25
26
|
}
|
|
@@ -29,7 +30,7 @@ export function readBoxHeader(dv, p, parentEnd, base = 0) {
|
|
|
29
30
|
if (type === 'uuid')
|
|
30
31
|
headerSize += 16;
|
|
31
32
|
if (size < headerSize)
|
|
32
|
-
throw new IsoBmffError(`corrupt file: box '${type}' at ${base + p} is smaller than its header`);
|
|
33
|
+
throw new IsoBmffError('corrupt', `corrupt file: box '${type}' at ${base + p} is smaller than its header`);
|
|
33
34
|
const end = p + size;
|
|
34
35
|
return { type, start: p, size, headerSize, end: Math.min(end, parentEnd), truncated: end > parentEnd };
|
|
35
36
|
}
|
|
@@ -53,13 +54,13 @@ export function* childBoxes(dv, start, end, warnings) {
|
|
|
53
54
|
export function boxU64(dv, p, box, at) {
|
|
54
55
|
const v = dv.getBigUint64(p);
|
|
55
56
|
if (v > BigInt(Number.MAX_SAFE_INTEGER))
|
|
56
|
-
throw new IsoBmffError(`unsupported: box '${box}' at ${at} holds a value above 2^53-1`);
|
|
57
|
+
throw new IsoBmffError('unsupported', `unsupported: box '${box}' at ${at} holds a value above 2^53-1`);
|
|
57
58
|
return Number(v);
|
|
58
59
|
}
|
|
59
60
|
export function boxI64(dv, p, box, at) {
|
|
60
61
|
const v = dv.getBigInt64(p);
|
|
61
62
|
if (v > BigInt(Number.MAX_SAFE_INTEGER) || v < -BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
62
|
-
throw new IsoBmffError(`unsupported: box '${box}' at ${at} holds a value beyond 2^53-1`);
|
|
63
|
+
throw new IsoBmffError('unsupported', `unsupported: box '${box}' at ${at} holds a value beyond 2^53-1`);
|
|
63
64
|
}
|
|
64
65
|
return Number(v);
|
|
65
66
|
}
|