video-fps-probe 0.2.0 → 0.4.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/README.md +33 -15
  3. package/dist/api/codes.d.ts +6 -0
  4. package/dist/api/codes.js +88 -0
  5. package/dist/api/errors.js +1 -1
  6. package/dist/api/guards.d.ts +2 -0
  7. package/dist/api/guards.js +2 -1
  8. package/dist/check/index.js +12 -2
  9. package/dist/cjs/analyze.d.cts +9 -0
  10. package/dist/cjs/api/agreement.d.cts +18 -0
  11. package/dist/cjs/api/codes.d.cts +6 -0
  12. package/dist/cjs/api/errors.d.cts +12 -0
  13. package/dist/cjs/api/guards.d.cts +4 -0
  14. package/dist/cjs/api/summary.d.cts +22 -0
  15. package/dist/cjs/check/index.d.cts +60 -0
  16. package/dist/cjs/check.cjs +1 -0
  17. package/dist/cjs/chunks/build-CT5g6_bs.cjs +1 -0
  18. package/dist/cjs/chunks/compare-D7RVqlqf.cjs +1 -0
  19. package/dist/cjs/chunks/errors-0oBg1Ai6.cjs +1 -0
  20. package/dist/cjs/chunks/fallback-D9Ak2zFv.cjs +1 -0
  21. package/dist/cjs/chunks/guards-Dqpjtkdn.cjs +1 -0
  22. package/dist/cjs/chunks/inline-Bx-TQg8f.cjs +1 -0
  23. package/dist/cjs/chunks/isobmff-B_bb5rS5.cjs +1 -0
  24. package/dist/cjs/chunks/matroska-CLoGzfKA.cjs +1 -0
  25. package/dist/cjs/chunks/probe-DDLUfr23.cjs +1 -0
  26. package/dist/cjs/chunks/rational-Dq5Vza-Q.cjs +1 -0
  27. package/dist/cjs/chunks/reader-DNLR-_tm.cjs +1 -0
  28. package/dist/cjs/chunks/rfps-C-pyKnu8.cjs +1 -0
  29. package/dist/cjs/chunks/runtime-DtgT0xzU.cjs +1 -0
  30. package/dist/cjs/chunks/segments-i-hPN7H3.cjs +1 -0
  31. package/dist/cjs/chunks/sniff-CXwqOGwh.cjs +1 -0
  32. package/dist/cjs/chunks/stats-D68frkk2.cjs +1 -0
  33. package/dist/cjs/client/types.d.cts +96 -0
  34. package/dist/cjs/core/reader.d.cts +47 -0
  35. package/dist/cjs/core/types.d.cts +149 -0
  36. package/dist/cjs/engines/types.d.cts +69 -0
  37. package/dist/cjs/header/index.d.cts +25 -0
  38. package/dist/cjs/header/limits.d.cts +25 -0
  39. package/dist/cjs/header.cjs +1 -0
  40. package/dist/cjs/index.cjs +1 -0
  41. package/dist/cjs/index.d.cts +13 -0
  42. package/dist/cjs/plugins/types.d.cts +17 -0
  43. package/dist/cjs/presets/index.d.cts +19 -0
  44. package/dist/cjs/presets.cjs +1 -0
  45. package/dist/cjs/probe.d.cts +3 -0
  46. package/dist/cjs/url/index.d.cts +47 -0
  47. package/dist/cjs/url.cjs +1 -0
  48. package/dist/cjs/worker/protocol.d.cts +47 -0
  49. package/dist/client/compare.js +2 -2
  50. package/dist/client/create.d.ts +3 -0
  51. package/dist/client/create.js +8 -0
  52. package/dist/client/fallback.js +2 -2
  53. package/dist/client/index.d.ts +1 -1
  54. package/dist/client/index.js +1 -1
  55. package/dist/client/inline.js +1 -1
  56. package/dist/client/lazy.js +1 -1
  57. package/dist/client/probe-client.js +4 -0
  58. package/dist/client/probe.js +23 -22
  59. package/dist/client/route.js +20 -0
  60. package/dist/client/split.js +9 -0
  61. package/dist/client/stub.js +2 -2
  62. package/dist/client/types.d.ts +1 -0
  63. package/dist/core/analyze.js +4 -78
  64. package/dist/core/dispatch.js +65 -0
  65. package/dist/core/isobmff/boxes.js +6 -8
  66. package/dist/core/isobmff/build.js +398 -0
  67. package/dist/core/isobmff/header.js +654 -0
  68. package/dist/core/isobmff/index.js +9 -378
  69. package/dist/core/isobmff/model.js +1 -1
  70. package/dist/core/isobmff/moof.js +2 -2
  71. package/dist/core/isobmff/moov.js +14 -9
  72. package/dist/core/isobmff/track.js +4 -2
  73. package/dist/core/matroska/ebml.js +1 -1
  74. package/dist/core/matroska/header.js +9 -4
  75. package/dist/core/matroska/index.js +7 -3
  76. package/dist/core/reader.d.ts +3 -12
  77. package/dist/core/reader.js +21 -32
  78. package/dist/core/result.js +1 -0
  79. package/dist/core/stats.js +3 -0
  80. package/dist/core/types.d.ts +15 -1
  81. package/dist/engines/common.js +8 -0
  82. package/dist/engines/mediabunny.js +17 -4
  83. package/dist/engines/mp4box.js +2 -1
  84. package/dist/header/index.d.ts +25 -0
  85. package/dist/header/index.js +146 -0
  86. package/dist/header/limits.d.ts +25 -0
  87. package/dist/header/limits.js +140 -0
  88. package/dist/index.d.ts +1 -0
  89. package/dist/index.js +1 -0
  90. package/dist/plugins/own.js +5 -2
  91. package/dist/presets/index.d.ts +1 -0
  92. package/dist/presets/sources.json +8 -0
  93. package/dist/probe.js +2 -1
  94. package/dist/react/store.js +1 -1
  95. package/dist/standalone/own-isobmff.worker.js +1 -0
  96. package/dist/standalone/own-matroska.worker.js +1 -0
  97. package/dist/standalone/own.worker.js +1 -1
  98. package/dist/url/index.d.ts +47 -0
  99. package/dist/url/index.js +335 -0
  100. package/dist/worker/own-isobmff.worker.js +4 -0
  101. package/dist/worker/own-matroska.worker.js +4 -0
  102. package/dist/worker/runtime.d.ts +2 -3
  103. package/dist/worker/runtime.js +2 -97
  104. package/dist/worker/serve.d.ts +3 -0
  105. package/dist/worker/serve.js +97 -0
  106. package/dist/worker/single.js +14 -0
  107. package/package.json +85 -2
  108. package/dist/client/inline.d.ts +0 -19
  109. package/dist/client/pool.d.ts +0 -29
  110. package/dist/client/probe.d.ts +0 -29
@@ -2,10 +2,11 @@ import { ProbeError } from "../api/errors.js";
2
2
  import { WorkerPool, workerFailed } from "./pool.js";
3
3
  const notRegistered = (id, message = `engine ${id} is not registered`) => new ProbeError('engine-not-registered', message, { engine: id });
4
4
  export const nameOf = (file) => (typeof File !== 'undefined' && file instanceof File ? file.name : '');
5
- const loadOwnInThread = async () => (await import("../worker/runtime.js")).ownEngine;
5
+ const loadOwnInThread = () => import("../worker/runtime.js").then((m) => m.ownEngine);
6
6
  export function createProbeCore(options) {
7
- const { worker, engines: descriptors = [], engine: defaultEngine = 'own', fallback: defaultFallback = [], workers, idleTimeoutMs, timeoutMs: defaultTimeout, defaults } = options;
7
+ const { worker, engines: descriptors = [], engine: defaultEngine = 'own', fallback: defaultFallback = [], workers, idleTimeoutMs, timeoutMs: defaultTimeout, defaults, split } = options;
8
8
  const custom = typeof worker === 'object' ? worker : null;
9
+ const byContainer = custom?.byContainer;
9
10
  const inline = worker === 'inline' || typeof Worker === 'undefined';
10
11
  const pools = new Map();
11
12
  const byId = new Map();
@@ -21,27 +22,29 @@ export function createProbeCore(options) {
21
22
  stop();
22
23
  chunk.then(resolve, (e) => reject(workerFailed(String(e), 'load', engine, e))).finally(() => life.signal.removeEventListener('abort', stop));
23
24
  });
24
- const poolOf = (kind, create) => ({
25
- kind,
26
- pool: () => {
27
- let pool = pools.get(kind);
28
- if (!pool)
29
- pools.set(kind, (pool = new WorkerPool({ create, size: workers, idleTimeoutMs })));
30
- return pool;
31
- },
32
- });
25
+ const poolFor = (key, create) => {
26
+ let pool = pools.get(key);
27
+ if (!pool)
28
+ pools.set(key, (pool = new WorkerPool({ create, size: workers, idleTimeoutMs })));
29
+ return pool;
30
+ };
31
+ const poolOf = (kind, create) => ({ kind, pool: () => poolFor(kind, create) });
33
32
  const servedBy = (d, key) => {
34
33
  const load = d?.[key];
35
34
  if (!d || !load)
36
35
  return null;
37
- return !inline && d.thread === 'worker' && d.createWorker ? poolOf(d.id, d.createWorker) : { load };
36
+ if (inline || d.thread !== 'worker')
37
+ return { load };
38
+ if (d.createWorker)
39
+ return poolOf(d.id, d.createWorker);
40
+ return (d.createWorkers && split?.(d.id, d.createWorkers, poolFor, lazy, life.signal)) || { load };
38
41
  };
39
42
  const routeOf = (id) => {
40
43
  const listed = !custom?.engines.includes(id)
41
44
  ? null
42
45
  : inline
43
46
  ? { error: new ProbeError('unsupported-environment', `engine ${id} runs in a worker and Worker is not available`, { engine: id }) }
44
- : poolOf('custom', custom.create);
47
+ : (id === 'own' && byContainer && split?.('custom', byContainer, poolFor, lazy, life.signal, custom.create)) || poolOf('custom', custom.create);
45
48
  if (listed && 'pool' in listed)
46
49
  return listed;
47
50
  const route = id === 'own'
@@ -106,13 +109,14 @@ export function createProbeCore(options) {
106
109
  continue;
107
110
  if ('load' in route)
108
111
  jobs.push(lazy(route.load(), id).then((m) => m.warm?.(containers)));
109
- else {
110
- const pool = route.pool();
111
- warm.set(pool, [...(warm.get(pool) ?? []), id]);
112
- }
112
+ else
113
+ for (const [pool, families] of route.warmPools ? route.warmPools(containers) : [[route.pool(), containers]]) {
114
+ const [engines, union] = warm.get(pool) ?? [[], []];
115
+ warm.set(pool, [[...engines, id], [...new Set([...union, ...families])]]);
116
+ }
113
117
  }
114
- for (const [pool, engines] of warm)
115
- jobs.push(pool.run({ type: 'warm', engines, containers }, { timeoutMs: defaultTimeout }));
118
+ for (const [pool, [engines, union]] of warm)
119
+ jobs.push(pool.run({ type: 'warm', engines, containers: union }, { timeoutMs: defaultTimeout }));
116
120
  await Promise.allSettled(jobs);
117
121
  },
118
122
  dispose() {
@@ -126,6 +130,3 @@ export function createProbeCore(options) {
126
130
  },
127
131
  };
128
132
  }
129
- export function createProbeClient(options) {
130
- return createProbeCore(options);
131
- }
@@ -0,0 +1,20 @@
1
+ import { splitBy } from "./split.js";
2
+ export const EBML = [0x1a, 0x45, 0xdf, 0xa3];
3
+ export const familyOf = (file, signal) => new Promise((resolve) => {
4
+ const iso = () => resolve('isobmff');
5
+ if (signal?.aborted)
6
+ return iso();
7
+ signal?.addEventListener('abort', iso);
8
+ Promise.resolve()
9
+ .then(() => file.slice(0, 4).arrayBuffer())
10
+ .then((b) => {
11
+ const head = new Uint8Array(b);
12
+ return EBML.every((x, i) => head[i] === x) ? 'matroska' : 'isobmff';
13
+ })
14
+ .then(resolve, iso)
15
+ .finally(() => signal?.removeEventListener('abort', iso));
16
+ });
17
+ export const runByHead = (pool, lazy, life) => ({
18
+ run: (request, options) => lazy(familyOf(request.file, options.signal), request.engine).then((family) => (life.aborted ? lazy(Promise.reject(), request.engine) : pool(family).run(request, options))),
19
+ });
20
+ export const splitRoute = splitBy(runByHead);
@@ -0,0 +1,9 @@
1
+ const FAMILIES = ['isobmff', 'matroska'];
2
+ export const splitBy = (runner) => (kind, byFamily, pools, lazy, life, create) => {
3
+ const pool = (family) => {
4
+ const own = byFamily[family];
5
+ return own ? pools(`${kind}-${family}`, own) : pools(kind, create);
6
+ };
7
+ const run = runner(pool, lazy, life);
8
+ return { kind, pool: () => run, warmPools: (containers) => FAMILIES.filter((f) => containers.includes(f)).map((f) => [pool(f), [f]]) };
9
+ };
@@ -1,5 +1,5 @@
1
1
  import { ProbeError } from "../api/errors.js";
2
- export const knownEngines = (worker, descriptors = []) => [...new Set(['own', ...(typeof worker === 'object' ? worker.engines : []), ...descriptors.map((d) => d.id)])];
2
+ export const knownEngines = (worker, descriptors = []) => [...new Set(['own', ...(worker?.engines ?? []), ...descriptors.map((d) => d.id)])];
3
3
  export function lazyStub(factory, known) {
4
4
  let probe = null;
5
5
  let loading = null;
@@ -11,7 +11,7 @@ export function lazyStub(factory, known) {
11
11
  return (probe = p);
12
12
  }, (e) => {
13
13
  loading = null;
14
- throw e instanceof ProbeError ? e : Object.assign(new ProbeError('worker-failed', String(e), { cause: e }), { reason: 'load' });
14
+ throw e?.name === 'ProbeError' && typeof e.code === 'string' ? e : Object.assign(new ProbeError('worker-failed', String(e), { cause: e }), { reason: 'load' });
15
15
  }));
16
16
  const loadUnlessDestroyed = () => new Promise((resolve, reject) => {
17
17
  const stop = () => reject(aborted());
@@ -20,6 +20,7 @@ export interface ProbeOptions<E extends readonly EngineDescriptor[] = []> extend
20
20
  export interface CustomWorker<W extends WorkerEngineId> {
21
21
  create: () => Worker;
22
22
  engines: readonly W[];
23
+ byContainer?: Readonly<Partial<Record<ContainerFamily, () => Worker>>>;
23
24
  }
24
25
  export interface ClientOptions<E extends readonly EngineDescriptor[] = [], W extends WorkerEngineId = never> extends BaseOptions<NoInfer<W | IdOf<E[number]> | 'own'>> {
25
26
  worker: CustomWorker<W> | 'inline';
@@ -1,8 +1,5 @@
1
- import { throwIfAborted } from "./abort.js";
2
- import { resolveOptions } from "./options.js";
3
- import { BlobReader } from "./reader.js";
4
- import { emptyAnalysis } from "./result.js";
5
- import { sniff } from "./sniff.js";
1
+ import { analyzeWith } from "./dispatch.js";
2
+ export { errorMessage, firstReadAhead, isAbortError, SINGLE_READ_MAX_BYTES } from "./dispatch.js";
6
3
  export const DEFAULT_LOADERS = {
7
4
  isobmff: async () => (await Promise.all([import("./isobmff/index.js"), import("./stats.js")]))[0].analyzeIsoBmff,
8
5
  matroska: async () => (await Promise.all([import("./matroska/index.js"), import("./stats.js")]))[0].analyzeMatroska,
@@ -11,77 +8,6 @@ export const DEFAULT_ANALYZERS = {
11
8
  isobmff: async (reader, opts) => (await DEFAULT_LOADERS.isobmff())(reader, opts),
12
9
  matroska: async (reader, opts) => (await DEFAULT_LOADERS.matroska())(reader, opts),
13
10
  };
14
- const SNIFF_BYTES = 1024;
15
- export const SINGLE_READ_MAX_BYTES = 1024 * 1024;
16
- export function firstReadAhead(size, opts) {
17
- const { perReadMs, bytesPerMs } = opts.costModel;
18
- const head = opts.readAhead.head;
19
- return size < Math.max(head, Math.min(head + perReadMs * bytesPerMs, SINGLE_READ_MAX_BYTES)) ? size : head;
20
- }
21
- export function isAbortError(e) {
22
- return typeof e === 'object' && e !== null && 'name' in e && e.name === 'AbortError';
23
- }
24
- export function errorMessage(e) {
25
- if (e instanceof Error)
26
- return e.message || e.name;
27
- return String(e);
28
- }
29
- function applyAnalysis(target, a) {
30
- target.container = a.container;
31
- target.brand = a.brand;
32
- target.formatDurationSec = a.formatDurationSec;
33
- target.scan = a.scan;
34
- target.videoTracks = a.videoTracks;
35
- target.audioTrackCount = a.audioTrackCount;
36
- target.primaryTrackId = a.primaryTrackId;
37
- target.error = a.error;
38
- target.warnings = a.warnings;
39
- }
40
- export async function analyze(blob, name, opts = {}, analyzers = DEFAULT_ANALYZERS, loaders = analyzers === DEFAULT_ANALYZERS ? DEFAULT_LOADERS : null) {
41
- const t0 = performance.now();
42
- const resolved = resolveOptions(opts);
43
- throwIfAborted(resolved.signal);
44
- const result = {
45
- name,
46
- size: blob.size,
47
- ...emptyAnalysis('unknown'),
48
- io: { reads: 0, bytesRead: 0, ms: 0 },
49
- engine: 'own',
50
- };
51
- let reader = null;
52
- let loadMs = 0;
53
- try {
54
- reader = new BlobReader(blob, { headWindow: resolved.readAhead.head, signal: resolved.signal });
55
- if (reader.size === 0) {
56
- result.error = 'not a recognised container: empty file';
57
- }
58
- else {
59
- const head = await reader.bytes(0, Math.min(SNIFF_BYTES, reader.size), firstReadAhead(reader.size, resolved));
60
- const sniffed = sniff(head);
61
- if (sniffed.kind === 'unknown') {
62
- result.error = `not a recognised container: ${sniffed.reason}`;
63
- }
64
- else {
65
- result.container = sniffed.kind === 'isobmff' ? 'mp4' : 'matroska';
66
- let analyzer = analyzers[sniffed.kind];
67
- if (loaders) {
68
- const l0 = performance.now();
69
- analyzer = await loaders[sniffed.kind]();
70
- loadMs = performance.now() - l0;
71
- }
72
- applyAnalysis(result, await analyzer(reader, resolved));
73
- }
74
- }
75
- }
76
- catch (e) {
77
- if (resolved.signal?.aborted || isAbortError(e))
78
- throw e;
79
- result.error = errorMessage(e);
80
- }
81
- if (reader) {
82
- result.io.reads = reader.reads;
83
- result.io.bytesRead = reader.bytesFetched;
84
- }
85
- result.io.ms = performance.now() - t0 - loadMs;
86
- return result;
11
+ export function analyze(blob, name, opts = {}, analyzers = DEFAULT_ANALYZERS, loaders = analyzers === DEFAULT_ANALYZERS ? DEFAULT_LOADERS : null) {
12
+ return analyzeWith(blob, name, opts, loaders ? (kind) => loaders[kind]() : (kind) => analyzers[kind]);
87
13
  }
@@ -0,0 +1,65 @@
1
+ import { throwIfAborted } from "./abort.js";
2
+ import { resolveOptions } from "./options.js";
3
+ import { BlobReader, whichErrorCode, withErrorCode } from "./reader.js";
4
+ import { emptyAnalysis } from "./result.js";
5
+ import { sniff } from "./sniff.js";
6
+ const SNIFF_BYTES = 1024;
7
+ export const SINGLE_READ_MAX_BYTES = 1024 * 1024;
8
+ export function firstReadAhead(size, opts) {
9
+ const { perReadMs, bytesPerMs } = opts.costModel;
10
+ const head = opts.readAhead.head;
11
+ return size < Math.max(head, Math.min(head + perReadMs * bytesPerMs, SINGLE_READ_MAX_BYTES)) ? size : head;
12
+ }
13
+ export function isAbortError(e) {
14
+ return e?.name === 'AbortError';
15
+ }
16
+ export function errorMessage(e) {
17
+ if (e instanceof Error)
18
+ return e.message || e.name;
19
+ return String(e);
20
+ }
21
+ export async function analyzeWith(blob, name, opts, analyzerOf) {
22
+ const t0 = performance.now();
23
+ const resolved = resolveOptions(opts);
24
+ throwIfAborted(resolved.signal);
25
+ const result = {
26
+ name,
27
+ size: blob.size,
28
+ ...emptyAnalysis('unknown'),
29
+ errorCode: null,
30
+ layout: null,
31
+ io: { reads: 0, bytesRead: 0, ms: 0 },
32
+ engine: 'own',
33
+ };
34
+ let reader = null;
35
+ let loadMs = 0;
36
+ let loading = false;
37
+ try {
38
+ reader = new BlobReader(blob, { headWindow: resolved.readAhead.head, signal: resolved.signal });
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));
52
+ }
53
+ catch (e) {
54
+ if (resolved.signal?.aborted || isAbortError(e))
55
+ throw e;
56
+ result.error = errorMessage(e);
57
+ result.errorCode = whichErrorCode(e, loading ? 'load-failed' : 'internal');
58
+ }
59
+ if (reader) {
60
+ result.io.reads = reader.reads;
61
+ result.io.bytesRead = reader.bytesFetched;
62
+ }
63
+ result.io.ms = performance.now() - t0 - loadMs;
64
+ return result;
65
+ }
@@ -1,13 +1,11 @@
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
- function printable(type) {
9
- return type.replace(/[^\x20-\x7e]/g, '?');
10
- }
11
9
  export const MAX_BOX_HEADER = 32;
12
10
  export function readBoxHeader(dv, p, parentEnd, base = 0) {
13
11
  const avail = Math.min(dv.byteLength, parentEnd);
@@ -22,7 +20,7 @@ export function readBoxHeader(dv, p, parentEnd, base = 0) {
22
20
  return null;
23
21
  const big = dv.getBigUint64(p + 8);
24
22
  if (big > BigInt(Number.MAX_SAFE_INTEGER))
25
- throw new IsoBmffError(`corrupt file: box '${printable(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`);
26
24
  size = Number(big);
27
25
  headerSize = 16;
28
26
  }
@@ -32,7 +30,7 @@ export function readBoxHeader(dv, p, parentEnd, base = 0) {
32
30
  if (type === 'uuid')
33
31
  headerSize += 16;
34
32
  if (size < headerSize)
35
- throw new IsoBmffError(`corrupt file: box '${printable(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`);
36
34
  const end = p + size;
37
35
  return { type, start: p, size, headerSize, end: Math.min(end, parentEnd), truncated: end > parentEnd };
38
36
  }
@@ -56,13 +54,13 @@ export function* childBoxes(dv, start, end, warnings) {
56
54
  export function boxU64(dv, p, box, at) {
57
55
  const v = dv.getBigUint64(p);
58
56
  if (v > BigInt(Number.MAX_SAFE_INTEGER))
59
- throw new IsoBmffError(`unsupported: box '${printable(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`);
60
58
  return Number(v);
61
59
  }
62
60
  export function boxI64(dv, p, box, at) {
63
61
  const v = dv.getBigInt64(p);
64
62
  if (v > BigInt(Number.MAX_SAFE_INTEGER) || v < -BigInt(Number.MAX_SAFE_INTEGER)) {
65
- throw new IsoBmffError(`unsupported: box '${printable(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`);
66
64
  }
67
65
  return Number(v);
68
66
  }