@bubo-squared/gyroview 0.3.1 → 0.4.0
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 +33 -0
- package/README.md +1 -1
- package/dist/index.d.ts +36 -0
- package/dist/packages/adapters/mediabunny/src/MediabunnyAudioPackager.js +49 -15
- package/dist/packages/adapters/mediabunny/src/MediabunnyCodecReader.js +3 -1
- package/dist/packages/adapters/mediabunny/src/decoderConfigurations.js +2 -2
- package/dist/packages/adapters/mediabunny/src/trackColour.js +21 -0
- package/dist/packages/adapters/mse-audio/src/SourceBufferFeeder.js +12 -1
- package/dist/packages/adapters/three/src/ThreeFrameRenderer.js +3 -0
- package/dist/packages/adapters/three/src/conversionUniforms.js +61 -0
- package/dist/packages/adapters/three/src/glslLiterals.js +10 -0
- package/dist/packages/adapters/three/src/matrixCorrections.js +35 -0
- package/dist/packages/adapters/three/src/rendererUniforms.js +33 -12
- package/dist/packages/adapters/three/src/shaderPrograms.js +4 -2
- package/dist/packages/adapters/three/src/shaders/analysis.frag.js +1 -1
- package/dist/packages/adapters/three/src/shaders/displayConversion.js +4 -0
- package/dist/packages/adapters/three/src/shaders/lensModels.js +1 -1
- package/dist/packages/adapters/three/src/shaders/lensSampling.js +1 -1
- package/dist/packages/adapters/three/src/shaders/rawLenses.frag.js +1 -1
- package/dist/packages/adapters/three/src/shaders/stitch.frag.js +1 -1
- package/dist/packages/adapters/three/src/threeMatrix.js +10 -0
- package/dist/packages/adapters/webcodecs/src/WebCodecsVideoDecoderPort.js +4 -2
- package/dist/packages/adapters/webcodecs/src/colorSpaceOf.js +32 -0
- package/dist/packages/core/src/application/recording/frameTimesOf.js +0 -1
- package/dist/packages/core/src/domain/colour/DisplayConversion.js +137 -0
- package/dist/packages/core/src/domain/colour/TrackColour.js +38 -0
- package/dist/packages/core/src/domain/colour/matrixCorrection.js +76 -0
- package/dist/packages/core/src/domain/format/calibration/CalibrationVersion.js +7 -4
- package/dist/packages/core/src/domain/format/calibration/layouts/CalibrationStringLayout.js +1 -1
- package/dist/packages/core/src/domain/format/calibration/layouts/LegacyCalibrationLayout.js +1 -0
- package/dist/packages/core/src/domain/format/calibration/layouts/MeiCalibrationLayout.js +109 -35
- package/dist/packages/core/src/domain/format/calibration/layouts/PolynomialCalibrationLayout.js +1 -0
- package/dist/packages/core/src/domain/format/calibration/offsetTokens.js +33 -4
- package/dist/packages/core/src/domain/format/calibration/parseOffsetString.js +22 -17
- package/dist/packages/core/src/domain/format/calibration/selectCalibration.js +28 -15
- package/dist/packages/core/src/domain/format/calibration/v6TermReading.js +20 -0
- package/dist/packages/core/src/domain/format/info/calibrationSources.js +27 -0
- package/dist/packages/core/src/domain/format/info/infoFields.js +8 -2
- package/dist/packages/core/src/domain/format/info/parseInfoRecord.js +11 -6
- package/dist/packages/core/src/domain/motion/imu/ImuFrame.js +17 -8
- package/dist/packages/core/src/domain/motion/timing/FrameTimes.js +1 -3
- package/dist/packages/core/src/domain/motion/timing/frameTimeSources.js +0 -3
- package/dist/packages/core/src/domain/optics/MeiDistortion.js +43 -0
- package/dist/packages/core/src/domain/optics/MeiModel.js +6 -14
- package/dist/packages/core/src/domain/optics/scaledProjection.js +30 -0
- package/dist/packages/core/src/domain/stitching/StitchingSetup.js +13 -4
- package/dist/packages/core/src/index.js +6 -2
- package/dist/packages/core/src/shared/index.js +11 -0
- package/dist/packages/core/src/shared/mapRecord.js +11 -0
- package/dist/packages/core/src/shared/protobuf/ProtobufMessage.js +12 -26
- package/dist/packages/core/src/shared/protobuf/wireFormat.js +16 -0
- package/dist/packages/player/src/composition/buildPipeline.js +2 -1
- package/dist/packages/player/src/composition/openInputs.js +4 -1
- package/dist/standalone.js +211 -100
- package/package.json +4 -4
|
@@ -1,40 +1,45 @@
|
|
|
1
1
|
import "./layouts/CalibrationStringLayout.js";
|
|
2
2
|
import { LEGACY_CALIBRATION_LAYOUT } from "./layouts/LegacyCalibrationLayout.js";
|
|
3
|
-
import { MEI_CALIBRATION_LAYOUT } from "./layouts/MeiCalibrationLayout.js";
|
|
4
|
-
import { POLYNOMIAL_CALIBRATION_LAYOUT } from "./layouts/PolynomialCalibrationLayout.js";
|
|
5
3
|
import { GyroViewError } from "../../../shared/errors/GyroViewError.js";
|
|
4
|
+
import { EXTENDED_MEI_CALIBRATION_LAYOUT, MEI_CALIBRATION_LAYOUT } from "./layouts/MeiCalibrationLayout.js";
|
|
5
|
+
import { POLYNOMIAL_CALIBRATION_LAYOUT } from "./layouts/PolynomialCalibrationLayout.js";
|
|
6
6
|
//#region ../../packages/core/src/domain/format/calibration/parseOffsetString.ts
|
|
7
7
|
var TOKEN_SEPARATOR = "_";
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Every calibration string version the player reads; their token counts never coincide for a
|
|
10
|
+
* lens count.
|
|
11
|
+
*/
|
|
12
|
+
var CALIBRATION_LAYOUTS = [
|
|
9
13
|
LEGACY_CALIBRATION_LAYOUT,
|
|
10
14
|
POLYNOMIAL_CALIBRATION_LAYOUT,
|
|
11
|
-
MEI_CALIBRATION_LAYOUT
|
|
15
|
+
MEI_CALIBRATION_LAYOUT,
|
|
16
|
+
EXTENDED_MEI_CALIBRATION_LAYOUT
|
|
12
17
|
];
|
|
13
18
|
/**
|
|
14
|
-
* Parses
|
|
15
|
-
*
|
|
16
|
-
* recognised and rejected explicitly.
|
|
19
|
+
* Parses a calibration string of any version into a calibration set with its version, the layout
|
|
20
|
+
* detected from the token count among `layouts`: the player's, or a measurement's own readings.
|
|
17
21
|
*/
|
|
18
|
-
function parseOffsetString(text) {
|
|
19
|
-
const numbers = text.split(TOKEN_SEPARATOR).map((token) => parseNumber(token
|
|
22
|
+
function parseOffsetString(text, layouts = CALIBRATION_LAYOUTS) {
|
|
23
|
+
const numbers = text.split(TOKEN_SEPARATOR).map((token) => parseNumber(token));
|
|
20
24
|
const lensCount = numbers[0] ?? 0;
|
|
21
|
-
const layout = detectLayout(
|
|
25
|
+
const layout = detectLayout(layouts, numbers);
|
|
22
26
|
ensureVersionWordFits(layout, numbers.at(-1) ?? 0);
|
|
23
27
|
const blocks = Array.from({ length: lensCount }, (_unused, lensIndex) => lensBlock(numbers, 1 + lensIndex * layout.lensTokens));
|
|
24
28
|
return {
|
|
25
29
|
version: layout.version,
|
|
26
30
|
canvas: layout.canvasOf(numbers, blocks),
|
|
27
|
-
lenses: blocks.map((block, lensIndex) => layout.parseLens(block, lensIndex))
|
|
31
|
+
lenses: blocks.map((block, lensIndex) => layout.parseLens(block, lensIndex)),
|
|
32
|
+
radialScale: layout.radialScale
|
|
28
33
|
};
|
|
29
34
|
}
|
|
30
35
|
function tokenCountFor(lensCount, lensTokens, trailingTokens) {
|
|
31
36
|
return 1 + lensCount * lensTokens + trailingTokens;
|
|
32
37
|
}
|
|
33
|
-
function detectLayout(
|
|
34
|
-
const
|
|
38
|
+
function detectLayout(layouts, numbers) {
|
|
39
|
+
const lensCount = numbers[0] ?? 0;
|
|
40
|
+
const layout = layouts.find((candidate) => numbers.length === tokenCountFor(lensCount, candidate.lensTokens, candidate.trailingTokens));
|
|
35
41
|
if (layout) return layout;
|
|
36
|
-
|
|
37
|
-
throw new GyroViewError("invalid-calibration", `calibration string has ${tokenCount} tokens for ${lensCount} lenses, matching no known layout: ${text}`);
|
|
42
|
+
throw new GyroViewError("invalid-calibration", `calibration string has ${numbers.length} tokens for ${lensCount} lenses, matching no known layout`);
|
|
38
43
|
}
|
|
39
44
|
function ensureVersionWordFits(layout, versionWord) {
|
|
40
45
|
const problem = layout.versionWordProblem?.(versionWord);
|
|
@@ -43,9 +48,9 @@ function ensureVersionWordFits(layout, versionWord) {
|
|
|
43
48
|
function lensBlock(numbers, start) {
|
|
44
49
|
return (token) => numbers[start + token] ?? NaN;
|
|
45
50
|
}
|
|
46
|
-
function parseNumber(token
|
|
51
|
+
function parseNumber(token) {
|
|
47
52
|
const value = Number(token);
|
|
48
|
-
if (token.trim() === "" || !Number.isFinite(value)) throw new GyroViewError("invalid-calibration", `calibration token "${token}" is not a finite number
|
|
53
|
+
if (token.trim() === "" || !Number.isFinite(value)) throw new GyroViewError("invalid-calibration", `calibration token "${token}" is not a finite number`);
|
|
49
54
|
return value;
|
|
50
55
|
}
|
|
51
56
|
//#endregion
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { GyroViewError } from "../../../shared/errors/GyroViewError.js";
|
|
2
2
|
import { parseOffsetString } from "./parseOffsetString.js";
|
|
3
|
+
import { CALIBRATION_SOURCES } from "../info/calibrationSources.js";
|
|
3
4
|
//#region ../../packages/core/src/domain/format/calibration/selectCalibration.ts
|
|
4
5
|
/**
|
|
5
6
|
* Only these failures mean "this string is unusable, try the next one"; anything else is a bug
|
|
@@ -7,22 +8,25 @@ import { parseOffsetString } from "./parseOffsetString.js";
|
|
|
7
8
|
*/
|
|
8
9
|
var SKIPPABLE = /* @__PURE__ */ new Set(["invalid-calibration", "unsupported-calibration"]);
|
|
9
10
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
|
|
11
|
+
* The order the calibration strings are tried in: the legacy string first, whose equidistant
|
|
12
|
+
* reading is the one Insta360's own stitch agrees with on the far field (ADR 0023), then, for a
|
|
13
|
+
* recording without it, the Mei strings, the newer fit (v6) before the older (v3), and the
|
|
14
|
+
* polynomial (v2) last.
|
|
15
|
+
*/
|
|
16
|
+
var CALIBRATION_PREFERENCE = [
|
|
17
|
+
"offset",
|
|
18
|
+
"offsetV6",
|
|
19
|
+
"offsetV3",
|
|
20
|
+
"offsetV2"
|
|
21
|
+
];
|
|
22
|
+
/**
|
|
23
|
+
* Picks the calibration a recording is stitched through, the first usable string in
|
|
24
|
+
* {@link CALIBRATION_PREFERENCE}. Strings that cannot be used are reported, not silently
|
|
25
|
+
* dropped; having none is reported as absence, not as a failure.
|
|
15
26
|
*/
|
|
16
27
|
function selectCalibration(strings) {
|
|
17
|
-
const candidates = [
|
|
18
|
-
["offset", strings.offset],
|
|
19
|
-
["offset_v3", strings.offsetV3],
|
|
20
|
-
["offset_v2", strings.offsetV2]
|
|
21
|
-
];
|
|
22
28
|
const warnings = [];
|
|
23
|
-
for (const
|
|
24
|
-
if (text === void 0) continue;
|
|
25
|
-
const attempt = tryParse(name, text);
|
|
29
|
+
for (const attempt of attemptsOf(strings)) {
|
|
26
30
|
if ("calibration" in attempt) return {
|
|
27
31
|
calibration: attempt.calibration,
|
|
28
32
|
warnings
|
|
@@ -34,7 +38,16 @@ function selectCalibration(strings) {
|
|
|
34
38
|
warnings
|
|
35
39
|
};
|
|
36
40
|
}
|
|
37
|
-
|
|
41
|
+
/**
|
|
42
|
+
* The strings the recording carries, each parsed when asked for, in preference order.
|
|
43
|
+
*/
|
|
44
|
+
function* attemptsOf(strings) {
|
|
45
|
+
for (const key of CALIBRATION_PREFERENCE) {
|
|
46
|
+
const text = strings[key];
|
|
47
|
+
if (text !== void 0) yield tryParse(CALIBRATION_SOURCES[key], text);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function tryParse({ name }, text) {
|
|
38
51
|
try {
|
|
39
52
|
return { calibration: parseOffsetString(text) };
|
|
40
53
|
} catch (error) {
|
|
@@ -43,4 +56,4 @@ function tryParse(name, text) {
|
|
|
43
56
|
}
|
|
44
57
|
}
|
|
45
58
|
//#endregion
|
|
46
|
-
export { selectCalibration };
|
|
59
|
+
export { CALIBRATION_PREFERENCE, selectCalibration };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region ../../packages/core/src/domain/format/calibration/v6TermReading.ts
|
|
2
|
+
/**
|
|
3
|
+
* The five radial terms and the first tangential pair, the terms v3 carries too and reads the
|
|
4
|
+
* same way: on the X5, whose v3 and v6 strings describe the same lenses, this reading draws
|
|
5
|
+
* v3's image to about two canvas pixels. `p3`, `p4` and `s1` to `s4` are left out until real
|
|
6
|
+
* footage says how Insta360's stitch reads them.
|
|
7
|
+
*/
|
|
8
|
+
var RADIAL_AND_FIRST_PAIR = ({ radial, tangential }) => {
|
|
9
|
+
const [p1, p2] = tangential;
|
|
10
|
+
return {
|
|
11
|
+
radial,
|
|
12
|
+
tangential: [{
|
|
13
|
+
p1,
|
|
14
|
+
p2
|
|
15
|
+
}],
|
|
16
|
+
thinPrism: []
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
//#endregion
|
|
20
|
+
export { RADIAL_AND_FIRST_PAIR };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { InfoField } from "./infoFields.js";
|
|
2
|
+
//#region ../../packages/core/src/domain/format/info/calibrationSources.ts
|
|
3
|
+
/**
|
|
4
|
+
* Every calibration string the player reads, declared once: the parser reads the strings by it,
|
|
5
|
+
* and the calibration's selection names them by it. The record's type makes the compiler refuse
|
|
6
|
+
* a string of {@link CalibrationStrings} without a source.
|
|
7
|
+
*/
|
|
8
|
+
var CALIBRATION_SOURCES = {
|
|
9
|
+
offset: {
|
|
10
|
+
field: InfoField.Offset,
|
|
11
|
+
name: "offset"
|
|
12
|
+
},
|
|
13
|
+
offsetV2: {
|
|
14
|
+
field: InfoField.OffsetV2,
|
|
15
|
+
name: "offset_v2"
|
|
16
|
+
},
|
|
17
|
+
offsetV3: {
|
|
18
|
+
field: InfoField.OffsetV3,
|
|
19
|
+
name: "offset_v3"
|
|
20
|
+
},
|
|
21
|
+
offsetV6: {
|
|
22
|
+
field: InfoField.OffsetV6,
|
|
23
|
+
name: "offset_v6"
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
//#endregion
|
|
27
|
+
export { CALIBRATION_SOURCES };
|
|
@@ -45,7 +45,7 @@ var InfoField = {
|
|
|
45
45
|
*/
|
|
46
46
|
OffsetV2: 53,
|
|
47
47
|
/**
|
|
48
|
-
Unified (MEI) camera model calibration string (v3
|
|
48
|
+
Unified (MEI) camera model calibration string (v3).
|
|
49
49
|
*/
|
|
50
50
|
OffsetV3: 54,
|
|
51
51
|
IsRawGyro: 62,
|
|
@@ -64,7 +64,13 @@ var InfoField = {
|
|
|
64
64
|
/**
|
|
65
65
|
Observed (insta360-rs): 1 = track 0 is stream 10, 2 = track 0 is stream 00.
|
|
66
66
|
*/
|
|
67
|
-
TrackOrder: 80
|
|
67
|
+
TrackOrder: 80,
|
|
68
|
+
/**
|
|
69
|
+
Unified (MEI) camera model calibration string with more distortion terms (v6, 27 tokens a
|
|
70
|
+
lens). Named "current V6 calibration" by insta360-rs; observed beside v1 to v3 on the X5, and
|
|
71
|
+
as the only calibration string of the X6.
|
|
72
|
+
*/
|
|
73
|
+
OffsetV6: 111
|
|
68
74
|
};
|
|
69
75
|
var DimensionField = {
|
|
70
76
|
Width: 1,
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { GyroViewError } from "../../../shared/errors/GyroViewError.js";
|
|
2
2
|
import { DimensionField, FileLayoutValue, GyroConfigField, InfoField, PtsType, TrackOrderValue, WindowCropField } from "./infoFields.js";
|
|
3
|
+
import { CALIBRATION_SOURCES } from "./calibrationSources.js";
|
|
3
4
|
import { InfoRecordFormat } from "../constants.js";
|
|
4
5
|
import { ProtobufMessage } from "../../../shared/protobuf/ProtobufMessage.js";
|
|
6
|
+
import { mapRecord } from "../../../shared/mapRecord.js";
|
|
5
7
|
import { milliseconds, millisecondsToSeconds } from "../../../shared/units/time.js";
|
|
6
8
|
//#region ../../packages/core/src/domain/format/info/parseInfoRecord.ts
|
|
7
9
|
/**
|
|
@@ -22,7 +24,7 @@ function parseInfoRecord(payload, format) {
|
|
|
22
24
|
firstFrameTimestamp: message.varint(InfoField.FirstFrameTimestamp),
|
|
23
25
|
readoutTime: secondsFromMilliseconds(message.double(InfoField.RollingShutterTimeMs)),
|
|
24
26
|
windowCrop: windowCropOf(message.message(InfoField.WindowCropInfo)),
|
|
25
|
-
gyroOffset:
|
|
27
|
+
gyroOffset: gyroOffsetOf(message),
|
|
26
28
|
gyroType: message.varint(InfoField.GyroType),
|
|
27
29
|
isRawGyro: message.boolean(InfoField.IsRawGyro),
|
|
28
30
|
preferredFrameTimeSource: frameTimeSourceOf(message.varint(InfoField.PtsType)),
|
|
@@ -34,6 +36,13 @@ function parseInfoRecord(payload, format) {
|
|
|
34
36
|
function secondsFromMilliseconds(value) {
|
|
35
37
|
return value === void 0 ? void 0 : millisecondsToSeconds(milliseconds(value));
|
|
36
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* The gyro's offset from the frames, only where the camera says it measured one (field 29), as
|
|
41
|
+
* telemetry-parser reads it: a value in field 28 without that is not one.
|
|
42
|
+
*/
|
|
43
|
+
function gyroOffsetOf(message) {
|
|
44
|
+
return message.boolean(InfoField.HasGyroTimestamp) === true ? optionalMilliseconds(message.double(InfoField.GyroTimestampMs)) : void 0;
|
|
45
|
+
}
|
|
37
46
|
function optionalMilliseconds(value) {
|
|
38
47
|
return value === void 0 ? void 0 : milliseconds(value);
|
|
39
48
|
}
|
|
@@ -56,11 +65,7 @@ function trackOrderOf(value) {
|
|
|
56
65
|
return value === TrackOrderValue.Stream00First ? "stream-00-first" : void 0;
|
|
57
66
|
}
|
|
58
67
|
function calibrationStringsOf(message) {
|
|
59
|
-
return
|
|
60
|
-
offset: message.string(InfoField.Offset),
|
|
61
|
-
offsetV2: message.string(InfoField.OffsetV2),
|
|
62
|
-
offsetV3: message.string(InfoField.OffsetV3)
|
|
63
|
-
};
|
|
68
|
+
return mapRecord(CALIBRATION_SOURCES, (source) => message.string(source.field));
|
|
64
69
|
}
|
|
65
70
|
function dimensionOf(message) {
|
|
66
71
|
const width = message?.varint(DimensionField.Width);
|
|
@@ -82,16 +82,25 @@ function toBodyFrame(frame, imuVector) {
|
|
|
82
82
|
return transformVector(frame.toBody, imuVector);
|
|
83
83
|
}
|
|
84
84
|
/**
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* is the IMU's minus y. Chosen by the world-stillness ranking in
|
|
88
|
-
* `tools/integration/src/measure/imuFrameRanking.test.ts`, which every other arrangement loses.
|
|
85
|
+
* The IMU rotated a quarter turn about the camera's lateral axis: the body's down is the IMU's z
|
|
86
|
+
* and the body's forward is the IMU's minus y.
|
|
89
87
|
*/
|
|
90
|
-
var
|
|
88
|
+
var QUARTER_TURN_ABOUT_LATERAL = [
|
|
91
89
|
"x",
|
|
92
90
|
"z",
|
|
93
91
|
"-y"
|
|
94
|
-
]
|
|
92
|
+
];
|
|
93
|
+
/**
|
|
94
|
+
* Measured on two X5 recordings (firmware 1.7 and 1.11, ADR 0009), chosen by the world-stillness
|
|
95
|
+
* ranking in `tools/integration/src/measure/imuFrameRanking.test.ts`, which every other
|
|
96
|
+
* arrangement loses.
|
|
97
|
+
*/
|
|
98
|
+
var X5_IMU_FRAME = measuredImuFrame("X5", QUARTER_TURN_ABOUT_LATERAL);
|
|
99
|
+
/**
|
|
100
|
+
* Measured on one X6 recording (ADR 0009): the X5's arrangement, which the same ranking puts
|
|
101
|
+
* first by half the unstabilized movement, the runner-up close to none.
|
|
102
|
+
*/
|
|
103
|
+
var X6_IMU_FRAME = measuredImuFrame("X6", QUARTER_TURN_ABOUT_LATERAL);
|
|
95
104
|
/**
|
|
96
105
|
* Until a recording proves otherwise, the IMU is assumed aligned with the body.
|
|
97
106
|
*/
|
|
@@ -100,7 +109,7 @@ var ALIGNED_IMU_FRAME = assumedImuFrame("aligned (unverified)", [
|
|
|
100
109
|
"y",
|
|
101
110
|
"z"
|
|
102
111
|
]);
|
|
103
|
-
var IMU_FRAMES_BY_MODEL = [["Insta360 X5", X5_IMU_FRAME]];
|
|
112
|
+
var IMU_FRAMES_BY_MODEL = [["Insta360 X5", X5_IMU_FRAME], ["Insta360 X6", X6_IMU_FRAME]];
|
|
104
113
|
/**
|
|
105
114
|
* The IMU frame for a recording, chosen from the camera model the file names. A starting point
|
|
106
115
|
* the recording's own data can be checked against with the ranking test, never the last word.
|
|
@@ -109,4 +118,4 @@ function imuFrameFor(hints) {
|
|
|
109
118
|
return IMU_FRAMES_BY_MODEL.find(([prefix]) => hints.model?.startsWith(prefix))?.[1] ?? ALIGNED_IMU_FRAME;
|
|
110
119
|
}
|
|
111
120
|
//#endregion
|
|
112
|
-
export { ALIGNED_IMU_FRAME, X5_IMU_FRAME, assumedImuFrame, imuFrameFor, isProperRotation, toBodyFrame };
|
|
121
|
+
export { ALIGNED_IMU_FRAME, X5_IMU_FRAME, X6_IMU_FRAME, assumedImuFrame, imuFrameFor, isProperRotation, toBodyFrame };
|
|
@@ -11,7 +11,6 @@ var GRID_TOLERANCE_FRAMES = .01;
|
|
|
11
11
|
* Capture timing of every encoded frame, in frame order.
|
|
12
12
|
*/
|
|
13
13
|
var FrameTimes = class FrameTimes {
|
|
14
|
-
readoutTime;
|
|
15
14
|
clock;
|
|
16
15
|
captureTimes;
|
|
17
16
|
shutterTimes;
|
|
@@ -21,7 +20,6 @@ var FrameTimes = class FrameTimes {
|
|
|
21
20
|
this.clock = parts.clock;
|
|
22
21
|
this.captureTimes = parts.captureTimes;
|
|
23
22
|
this.shutterTimes = parts.shutterTimes;
|
|
24
|
-
this.readoutTime = parts.readoutTime ?? seconds(0);
|
|
25
23
|
this.frameDuration = parts.frameDuration;
|
|
26
24
|
}
|
|
27
25
|
/**
|
|
@@ -47,7 +45,7 @@ var FrameTimes = class FrameTimes {
|
|
|
47
45
|
captureTime,
|
|
48
46
|
videoTime,
|
|
49
47
|
shutterTime,
|
|
50
|
-
midExposureVideoTime: seconds(videoTime + (shutterTime ?? 0) / 2
|
|
48
|
+
midExposureVideoTime: seconds(videoTime + (shutterTime ?? 0) / 2)
|
|
51
49
|
};
|
|
52
50
|
}
|
|
53
51
|
/**
|
|
@@ -15,7 +15,6 @@ function fromExposureRecord(context) {
|
|
|
15
15
|
clock,
|
|
16
16
|
captureTimes: Float64Array.from(frames.captureTimes),
|
|
17
17
|
shutterTimes: Float64Array.from(frames.shutterTimes),
|
|
18
|
-
readoutTime: context.readoutTime,
|
|
19
18
|
frameDuration: context.frameDuration
|
|
20
19
|
});
|
|
21
20
|
}
|
|
@@ -30,7 +29,6 @@ function fromTrackTimestamps(context) {
|
|
|
30
29
|
return FrameTimes.withoutShutterTimes({
|
|
31
30
|
clock,
|
|
32
31
|
captureTimes,
|
|
33
|
-
readoutTime: context.readoutTime,
|
|
34
32
|
frameDuration: context.frameDuration
|
|
35
33
|
});
|
|
36
34
|
}
|
|
@@ -45,7 +43,6 @@ function fromNominalRate(context) {
|
|
|
45
43
|
return FrameTimes.withoutShutterTimes({
|
|
46
44
|
clock,
|
|
47
45
|
captureTimes,
|
|
48
|
-
readoutTime: context.readoutTime,
|
|
49
46
|
frameDuration: context.frameDuration
|
|
50
47
|
});
|
|
51
48
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ensureInvariant } from "../../shared/errors/GyroViewError.js";
|
|
2
|
+
//#region ../../packages/core/src/domain/optics/MeiDistortion.ts
|
|
3
|
+
/**
|
|
4
|
+
* The most terms of each family a calibration string carries (`offset_v6`: five radial terms,
|
|
5
|
+
* two tangential pairs, two thin-prism orders): what a renderer must hold room for.
|
|
6
|
+
*/
|
|
7
|
+
var MEI_TERM_CAPACITY = {
|
|
8
|
+
radial: 5,
|
|
9
|
+
tangential: 2,
|
|
10
|
+
thinPrism: 2
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Refuses a distortion with more terms of a family than {@link MEI_TERM_CAPACITY} holds: a
|
|
14
|
+
* defect of the reading that made it, found where the string is read rather than when a
|
|
15
|
+
* renderer packs it.
|
|
16
|
+
*/
|
|
17
|
+
function ensureWithinTermCapacity(distortion) {
|
|
18
|
+
ensureFamilyFits("radial", distortion.radial.length);
|
|
19
|
+
ensureFamilyFits("tangential", distortion.tangential.length);
|
|
20
|
+
ensureFamilyFits("thinPrism", distortion.thinPrism.length);
|
|
21
|
+
}
|
|
22
|
+
function ensureFamilyFits(family, count) {
|
|
23
|
+
const capacity = MEI_TERM_CAPACITY[family];
|
|
24
|
+
ensureInvariant(count <= capacity, `a Mei distortion has ${count} ${family} terms, more than the ${capacity} a string carries`);
|
|
25
|
+
}
|
|
26
|
+
function distortMei(distortion, point) {
|
|
27
|
+
const [x, y] = point;
|
|
28
|
+
const r2 = x * x + y * y;
|
|
29
|
+
const radial = 1 + r2 * seriesIn(r2, distortion.radial, (k) => k);
|
|
30
|
+
const p1 = seriesIn(r2, distortion.tangential, (pair) => pair.p1);
|
|
31
|
+
const p2 = seriesIn(r2, distortion.tangential, (pair) => pair.p2);
|
|
32
|
+
const prismX = r2 * seriesIn(r2, distortion.thinPrism, (term) => term.x);
|
|
33
|
+
const prismY = r2 * seriesIn(r2, distortion.thinPrism, (term) => term.y);
|
|
34
|
+
return [radial * x + 2 * p1 * x * y + p2 * (r2 + 2 * x * x) + prismX, radial * y + p1 * (r2 + 2 * y * y) + 2 * p2 * x * y + prismY];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* `c0 + c1 r² + c2 r⁴ + ...` of the terms' coefficients, by Horner's rule.
|
|
38
|
+
*/
|
|
39
|
+
function seriesIn(r2, terms, coefficientOf) {
|
|
40
|
+
return terms.reduceRight((sum, term) => sum * r2 + coefficientOf(term), 0);
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { MEI_TERM_CAPACITY, distortMei, ensureWithinTermCapacity };
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { HALF_FIELD_OF_VIEW } from "./opticsConstants.js";
|
|
2
|
+
import { distortMei, ensureWithinTermCapacity } from "./MeiDistortion.js";
|
|
2
3
|
//#region ../../packages/core/src/domain/optics/MeiModel.ts
|
|
3
4
|
/**
|
|
4
|
-
* Unified (Mei) omnidirectional camera model with radial
|
|
5
|
-
* `offset_v3`. A direction is projected onto the unit sphere, then from a point
|
|
6
|
-
* sphere centre onto the normalised image plane, then distorted and scaled.
|
|
5
|
+
* Unified (Mei) omnidirectional camera model with radial, tangential and thin-prism distortion,
|
|
6
|
+
* as stored in `offset_v3` and `offset_v6`. A direction is projected onto the unit sphere, then from a point
|
|
7
|
+
* `xi` behind the sphere centre onto the normalised image plane, then distorted and scaled.
|
|
7
8
|
*/
|
|
8
9
|
var MeiModel = class {
|
|
9
10
|
parameters;
|
|
@@ -12,6 +13,7 @@ var MeiModel = class {
|
|
|
12
13
|
principalPoint;
|
|
13
14
|
constructor(parameters) {
|
|
14
15
|
this.parameters = parameters;
|
|
16
|
+
ensureWithinTermCapacity(parameters.distortion);
|
|
15
17
|
this.principalPoint = parameters.principalPoint;
|
|
16
18
|
}
|
|
17
19
|
get projection() {
|
|
@@ -24,22 +26,12 @@ var MeiModel = class {
|
|
|
24
26
|
const [x, y, z] = direction;
|
|
25
27
|
const depth = z + this.parameters.xi;
|
|
26
28
|
if (depth <= 0 || Math.atan2(Math.hypot(x, y), z) > this.halfFieldOfView) return void 0;
|
|
27
|
-
const
|
|
28
|
-
const [distortedX, distortedY] = this.distort(normalised);
|
|
29
|
+
const [distortedX, distortedY] = distortMei(this.parameters.distortion, [x / depth, y / depth]);
|
|
29
30
|
return {
|
|
30
31
|
x: this.parameters.focal[0] * distortedX + this.principalPoint.x,
|
|
31
32
|
y: this.parameters.focal[1] * distortedY + this.principalPoint.y
|
|
32
33
|
};
|
|
33
34
|
}
|
|
34
|
-
distort([mx, my]) {
|
|
35
|
-
const [k1, k2, k3] = this.parameters.radial;
|
|
36
|
-
const [p1, p2] = this.parameters.tangential;
|
|
37
|
-
const r2 = mx * mx + my * my;
|
|
38
|
-
const radial = 1 + k1 * r2 + k2 * r2 * r2 + k3 * r2 * r2 * r2;
|
|
39
|
-
const tangentialX = 2 * p1 * mx * my + p2 * (r2 + 2 * mx * mx);
|
|
40
|
-
const tangentialY = p1 * (r2 + 2 * my * my) + 2 * p2 * mx * my;
|
|
41
|
-
return [radial * mx + tangentialX, radial * my + tangentialY];
|
|
42
|
-
}
|
|
43
35
|
};
|
|
44
36
|
//#endregion
|
|
45
37
|
export { MeiModel };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region ../../packages/core/src/domain/optics/scaledProjection.ts
|
|
2
|
+
/**
|
|
3
|
+
* The projection with every image radius multiplied by `scale` about the principal point: the
|
|
4
|
+
* Mei model's focal lengths, or the radial polynomial's coefficients. Exact at a scale of 1.
|
|
5
|
+
*/
|
|
6
|
+
function scaledProjection(projection, scale) {
|
|
7
|
+
switch (projection.kind) {
|
|
8
|
+
case "mei": {
|
|
9
|
+
const [fx, fy] = projection.focal;
|
|
10
|
+
return {
|
|
11
|
+
...projection,
|
|
12
|
+
focal: [fx * scale, fy * scale]
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
case "radial-polynomial": {
|
|
16
|
+
const [c1, c2, c3, c4] = projection.coefficients;
|
|
17
|
+
return {
|
|
18
|
+
...projection,
|
|
19
|
+
coefficients: [
|
|
20
|
+
c1 * scale,
|
|
21
|
+
c2 * scale,
|
|
22
|
+
c3 * scale,
|
|
23
|
+
c4 * scale
|
|
24
|
+
]
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { scaledProjection };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { degrees, degreesToRadians } from "../../shared/units/angle.js";
|
|
2
|
-
import { GyroViewError } from "../../shared/errors/GyroViewError.js";
|
|
2
|
+
import { GyroViewError, ensureInvariant } from "../../shared/errors/GyroViewError.js";
|
|
3
3
|
import { lensRotation } from "../optics/lensPose.js";
|
|
4
4
|
import { SEAM_RING_ANGLE } from "./seamRing.js";
|
|
5
|
+
import { scaledProjection } from "../optics/scaledProjection.js";
|
|
5
6
|
//#region ../../packages/core/src/domain/stitching/StitchingSetup.ts
|
|
6
7
|
/**
|
|
7
8
|
* Two 200-degree lenses overlap between 80 and 100 degrees from their axes; the blend spans 5
|
|
@@ -33,23 +34,31 @@ function buildStitchingSetup(inputs) {
|
|
|
33
34
|
const { calibration, layout } = inputs;
|
|
34
35
|
if (calibration.lenses.length !== layout.sources.length) throw new GyroViewError("unsupported-layout", `the calibration describes ${calibration.lenses.length} lenses but the layout has ${layout.sources.length}`);
|
|
35
36
|
const frames = lensFrameOrder(layout);
|
|
37
|
+
ensureInvariant(inputs.displayConversions.length === frames.length, `${inputs.displayConversions.length} display conversions for ${frames.length} frame sources`);
|
|
36
38
|
return {
|
|
37
39
|
lenses: layout.sources.map((source) => {
|
|
38
40
|
const lens = lensOf(calibration, source.lensIndex);
|
|
41
|
+
const frameSlot = frames.findIndex((key) => isSameSource(key, source));
|
|
39
42
|
return {
|
|
40
43
|
lensIndex: source.lensIndex,
|
|
41
|
-
frameSlot
|
|
44
|
+
frameSlot,
|
|
42
45
|
region: source.region,
|
|
43
46
|
window: canvasWindowOf(calibration, lens),
|
|
44
47
|
rotation: lensRotation(lens),
|
|
45
|
-
projection: lens.model.projection,
|
|
46
|
-
halfFieldOfView: lens.model.halfFieldOfView
|
|
48
|
+
projection: scaledProjection(lens.model.projection, calibration.radialScale),
|
|
49
|
+
halfFieldOfView: lens.model.halfFieldOfView,
|
|
50
|
+
displayConversion: conversionAt(inputs.displayConversions, frameSlot)
|
|
47
51
|
};
|
|
48
52
|
}),
|
|
49
53
|
frameSlotCount: frames.length,
|
|
50
54
|
feather: DEFAULT_FEATHER
|
|
51
55
|
};
|
|
52
56
|
}
|
|
57
|
+
function conversionAt(conversions, frameSlot) {
|
|
58
|
+
const conversion = conversions[frameSlot];
|
|
59
|
+
ensureInvariant(conversion !== void 0, `no display conversion for frame slot ${frameSlot}`);
|
|
60
|
+
return conversion;
|
|
61
|
+
}
|
|
53
62
|
function isSameSource(key, source) {
|
|
54
63
|
return key.inputIndex === source.inputIndex && key.trackIndex === source.trackIndex;
|
|
55
64
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { degrees } from "./shared/units/angle.js";
|
|
2
|
-
import "./domain/optics/EquidistantModel.js";
|
|
3
2
|
import "./domain/format/calibration/CalibrationVersion.js";
|
|
4
3
|
import { GYRO_VIEW_ERROR_CATEGORIES, GYRO_VIEW_ERROR_CODES, GyroViewError, asGyroViewError, ensureIndexInRange, ensureInvariant, hasErrorCode, isAbortError, isGyroViewErrorCode, messageOf } from "./shared/errors/GyroViewError.js";
|
|
4
|
+
import { MEI_TERM_CAPACITY } from "./domain/optics/MeiDistortion.js";
|
|
5
5
|
import { lazy } from "./shared/lazy.js";
|
|
6
6
|
import { microseconds, microsecondsToSeconds, milliseconds, seconds, secondsToMicroseconds } from "./shared/units/time.js";
|
|
7
7
|
import "./domain/motion/exposure/ExposureRecord.js";
|
|
@@ -48,8 +48,12 @@ import "./domain/stitching/seamMismatch.js";
|
|
|
48
48
|
import "./domain/stitching/seamDisparity.js";
|
|
49
49
|
import "./domain/stitching/seamDisparityField.js";
|
|
50
50
|
import "./domain/stitching/seamJoin.js";
|
|
51
|
+
import { COLOUR_PRIMARIES, MATRIX_COEFFICIENTS, TRANSFER_CHARACTERISTICS, namedOrUnspecified } from "./domain/colour/TrackColour.js";
|
|
52
|
+
import { BT709_LUMINANCE, HLG_OETF, displayConversionsOf } from "./domain/colour/DisplayConversion.js";
|
|
53
|
+
import { matrixCorrectionOf } from "./domain/colour/matrixCorrection.js";
|
|
51
54
|
import { keysOf } from "./shared/keysOf.js";
|
|
52
55
|
import { Outbox } from "./shared/events/Outbox.js";
|
|
56
|
+
import "./shared/index.js";
|
|
53
57
|
import { Ending, ITERATION_END } from "./shared/async/iteration.js";
|
|
54
58
|
import { SourceByteStream } from "./application/download/SourceByteStream.js";
|
|
55
59
|
import { startFileDownload } from "./application/download/startFileDownload.js";
|
|
@@ -64,4 +68,4 @@ import { WallClock } from "./application/playback/WallClock.js";
|
|
|
64
68
|
import { isFlowing } from "./domain/playback/PlayerState.js";
|
|
65
69
|
import { TypedEmitter } from "./shared/events/TypedEmitter.js";
|
|
66
70
|
import { PlaybackSession } from "./application/playback/PlaybackSession.js";
|
|
67
|
-
export { ByteRange, DEFAULT_FRAMING, DEFAULT_PICTURE_QUALITY, DEFAULT_STABILIZATION_MODE, DEFAULT_VIEW_MODE, Deferred, Ending, GYRO_VIEW_ERROR_CATEGORIES, GYRO_VIEW_ERROR_CODES, GainMatchingFrameSink, GyroViewError, IDENTITY_MATRIX3, ITERATION_END, Outbox, PICTURE_QUALITIES, PlaybackSession, RecordingBuffer, RunStop, SCREEN_CENTRE, STABILIZATION_MODES, STOPPED, SourceByteStream, StabilizingFrameSink, TypedEmitter, VIEW_MODES, WallClock, asGyroViewError, aspectOf, aspectOfArea, buildStitchingSetup, clamp, clampView, degrees, detectLensLayout, downloadPolicyFor, ensureIndexInRange, ensureInvariant, fileNameOfUrl, hasErrorCode, inspectRecording, isAbortError, isFlowing, isGyroViewErrorCode, isSameFraming, isSameView, keysOf, lazy, lensFrameOrder, locateOtherLensFile, lookAt, messageOf, microseconds, microsecondsToSeconds, milliseconds, pixelRatioCapOf, planeHalfExtentOf, probeDecoding, readRecording, readSampleTable, seconds, secondsToMicroseconds, stabilizerFor, startFileDownload, timeRecording, viewModeRulesFor, zoomStepsForPinch };
|
|
71
|
+
export { BT709_LUMINANCE, ByteRange, COLOUR_PRIMARIES, DEFAULT_FRAMING, DEFAULT_PICTURE_QUALITY, DEFAULT_STABILIZATION_MODE, DEFAULT_VIEW_MODE, Deferred, Ending, GYRO_VIEW_ERROR_CATEGORIES, GYRO_VIEW_ERROR_CODES, GainMatchingFrameSink, GyroViewError, HLG_OETF, IDENTITY_MATRIX3, ITERATION_END, MATRIX_COEFFICIENTS, MEI_TERM_CAPACITY, Outbox, PICTURE_QUALITIES, PlaybackSession, RecordingBuffer, RunStop, SCREEN_CENTRE, STABILIZATION_MODES, STOPPED, SourceByteStream, StabilizingFrameSink, TRANSFER_CHARACTERISTICS, TypedEmitter, VIEW_MODES, WallClock, asGyroViewError, aspectOf, aspectOfArea, buildStitchingSetup, clamp, clampView, degrees, detectLensLayout, displayConversionsOf, downloadPolicyFor, ensureIndexInRange, ensureInvariant, fileNameOfUrl, hasErrorCode, inspectRecording, isAbortError, isFlowing, isGyroViewErrorCode, isSameFraming, isSameView, keysOf, lazy, lensFrameOrder, locateOtherLensFile, lookAt, matrixCorrectionOf, messageOf, microseconds, microsecondsToSeconds, milliseconds, namedOrUnspecified, pixelRatioCapOf, planeHalfExtentOf, probeDecoding, readRecording, readSampleTable, seconds, secondsToMicroseconds, stabilizerFor, startFileDownload, timeRecording, viewModeRulesFor, zoomStepsForPinch };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { degrees } from "./units/angle.js";
|
|
2
|
+
import { GYRO_VIEW_ERROR_CATEGORIES, GYRO_VIEW_ERROR_CODES, GyroViewError, asGyroViewError, ensureIndexInRange, ensureInvariant, hasErrorCode, isAbortError, isGyroViewErrorCode, messageOf } from "./errors/GyroViewError.js";
|
|
3
|
+
import { lazy } from "./lazy.js";
|
|
4
|
+
import { microseconds, microsecondsToSeconds, milliseconds, seconds, secondsToMicroseconds } from "./units/time.js";
|
|
5
|
+
import "./math/Vector3.js";
|
|
6
|
+
import { clamp } from "./math/clamp.js";
|
|
7
|
+
import { IDENTITY_MATRIX3 } from "./math/Matrix3.js";
|
|
8
|
+
import "./math/Quaternion.js";
|
|
9
|
+
import { keysOf } from "./keysOf.js";
|
|
10
|
+
import { Outbox } from "./events/Outbox.js";
|
|
11
|
+
export { GYRO_VIEW_ERROR_CATEGORIES, GYRO_VIEW_ERROR_CODES, GyroViewError, IDENTITY_MATRIX3, Outbox, asGyroViewError, clamp, degrees, ensureIndexInRange, ensureInvariant, hasErrorCode, isAbortError, isGyroViewErrorCode, keysOf, lazy, messageOf, microseconds, microsecondsToSeconds, milliseconds, seconds, secondsToMicroseconds };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region ../../packages/core/src/shared/mapRecord.ts
|
|
2
|
+
/**
|
|
3
|
+
* A record with each value of `every` turned by `map`, under the same keys: a table declared once
|
|
4
|
+
* becomes a record of what it describes, and the record's type keeps every key of the table.
|
|
5
|
+
*/
|
|
6
|
+
function mapRecord(every, map) {
|
|
7
|
+
const entries = Object.entries(every).map(([key, value]) => [key, map(value, key)]);
|
|
8
|
+
return Object.fromEntries(entries);
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { mapRecord };
|
|
@@ -1,24 +1,10 @@
|
|
|
1
1
|
import { GyroViewError } from "../errors/GyroViewError.js";
|
|
2
2
|
import { ByteReader } from "../binary/ByteReader.js";
|
|
3
3
|
import { decodeUtf8 } from "../text/utf8.js";
|
|
4
|
+
import { WireType } from "./wireFormat.js";
|
|
4
5
|
//#region ../../packages/core/src/shared/protobuf/ProtobufMessage.ts
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
*/
|
|
8
|
-
var WireType = {
|
|
9
|
-
Varint: 0,
|
|
10
|
-
Fixed64: 1,
|
|
11
|
-
LengthDelimited: 2,
|
|
12
|
-
Fixed32: 5
|
|
13
|
-
};
|
|
14
|
-
var FIELD_NUMBER_SHIFT = 3;
|
|
15
|
-
var WIRE_TYPE_MASK = 7;
|
|
16
|
-
var VARINT_PAYLOAD_BITS = 7n;
|
|
17
|
-
var VARINT_PAYLOAD_MASK = 127n;
|
|
18
|
-
var VARINT_CONTINUATION_BIT = 128;
|
|
19
|
-
var FIXED64_SIZE = 8;
|
|
20
|
-
var FIXED32_SIZE = 4;
|
|
21
|
-
var MAX_VARINT_BYTES = 10;
|
|
6
|
+
var VARINT_SHIFT = BigInt(7);
|
|
7
|
+
var VARINT_MASK = BigInt(127);
|
|
22
8
|
var MAX_SAFE = BigInt(Number.MAX_SAFE_INTEGER);
|
|
23
9
|
/**
|
|
24
10
|
* A schema-less view of one encoded protobuf message: fields are looked up by number and unknown
|
|
@@ -93,8 +79,8 @@ var Cursor = class {
|
|
|
93
79
|
}
|
|
94
80
|
readField() {
|
|
95
81
|
const key = this.readVarint();
|
|
96
|
-
const number = Number(key >> BigInt(
|
|
97
|
-
const wireType = Number(key & BigInt(
|
|
82
|
+
const number = Number(key >> BigInt(3));
|
|
83
|
+
const wireType = Number(key & BigInt(7));
|
|
98
84
|
return {
|
|
99
85
|
number,
|
|
100
86
|
value: this.readValue(wireType, number)
|
|
@@ -108,11 +94,11 @@ var Cursor = class {
|
|
|
108
94
|
};
|
|
109
95
|
case WireType.Fixed64: return {
|
|
110
96
|
kind: "fixed64",
|
|
111
|
-
bytes: this.readBytes(
|
|
97
|
+
bytes: this.readBytes(8)
|
|
112
98
|
};
|
|
113
99
|
case WireType.Fixed32: return {
|
|
114
100
|
kind: "fixed32",
|
|
115
|
-
bytes: this.readBytes(
|
|
101
|
+
bytes: this.readBytes(4)
|
|
116
102
|
};
|
|
117
103
|
case WireType.LengthDelimited: return {
|
|
118
104
|
kind: "bytes",
|
|
@@ -124,13 +110,13 @@ var Cursor = class {
|
|
|
124
110
|
readVarint() {
|
|
125
111
|
let result = 0n;
|
|
126
112
|
let shift = 0n;
|
|
127
|
-
for (let consumed = 0; consumed <
|
|
113
|
+
for (let consumed = 0; consumed < 10; consumed += 1) {
|
|
128
114
|
const byte = this.readByte();
|
|
129
|
-
result |= (BigInt(byte) &
|
|
130
|
-
if ((byte &
|
|
131
|
-
shift +=
|
|
115
|
+
result |= (BigInt(byte) & VARINT_MASK) << shift;
|
|
116
|
+
if ((byte & 128) === 0) return result;
|
|
117
|
+
shift += VARINT_SHIFT;
|
|
132
118
|
}
|
|
133
|
-
throw new GyroViewError("invalid-protobuf", `varint longer than
|
|
119
|
+
throw new GyroViewError("invalid-protobuf", `varint longer than 10 bytes at byte ${this.position}`);
|
|
134
120
|
}
|
|
135
121
|
readLength() {
|
|
136
122
|
const length = this.readVarint();
|