@bubo-squared/gyroview 0.3.0 → 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 +49 -0
- package/README.md +20 -11
- package/dist/index.d.ts +56 -2
- package/dist/index.js +2 -2
- 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 +16 -5
- package/dist/packages/adapters/webcodecs/src/colorSpaceOf.js +32 -0
- package/dist/packages/core/src/application/playback/probeDecoding.js +2 -2
- 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 +7 -3
- package/dist/packages/core/src/shared/errors/GyroViewError.js +55 -3
- 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/packages/player/src/controls/messages.js +2 -1
- package/dist/standalone.js +211 -100
- package/package.json +4 -4
|
@@ -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
|
-
import { GYRO_VIEW_ERROR_CODES, GyroViewError, asGyroViewError, ensureIndexInRange, ensureInvariant, hasErrorCode, isAbortError, isGyroViewErrorCode, messageOf } from "./shared/errors/GyroViewError.js";
|
|
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_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 };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region ../../packages/core/src/shared/errors/GyroViewError.ts
|
|
2
2
|
/**
|
|
3
|
-
* Stable machine-readable failure
|
|
3
|
+
* Stable machine-readable failure codes. Embedders switch on these; messages are for humans.
|
|
4
4
|
*/
|
|
5
5
|
var GYRO_VIEW_ERROR_CODES = [
|
|
6
6
|
"binary-out-of-bounds",
|
|
@@ -30,17 +30,69 @@ var GYRO_VIEW_ERROR_CODES = [
|
|
|
30
30
|
"unsupported-container",
|
|
31
31
|
"unsupported-gyro-record",
|
|
32
32
|
"unsupported-info-format",
|
|
33
|
-
"unsupported-layout"
|
|
33
|
+
"unsupported-layout",
|
|
34
|
+
"webcodecs-unavailable"
|
|
34
35
|
];
|
|
36
|
+
/**
|
|
37
|
+
* Whose side a failure is on, for embedders that handle failures by kind: the browser cannot
|
|
38
|
+
* decode or draw the recording, the file is not one the player can play, its bytes could not be
|
|
39
|
+
* read, the page misused the API, or the player failed in a way it did not expect.
|
|
40
|
+
*/
|
|
41
|
+
var GYRO_VIEW_ERROR_CATEGORIES = [
|
|
42
|
+
"browser",
|
|
43
|
+
"recording",
|
|
44
|
+
"source",
|
|
45
|
+
"usage",
|
|
46
|
+
"internal"
|
|
47
|
+
];
|
|
48
|
+
/**
|
|
49
|
+
* A record, so a new code cannot be added without its category.
|
|
50
|
+
*/
|
|
51
|
+
var CATEGORY_OF_CODE = {
|
|
52
|
+
"binary-out-of-bounds": "recording",
|
|
53
|
+
"binary-unsafe-integer": "recording",
|
|
54
|
+
"codec-unsupported": "browser",
|
|
55
|
+
cors: "source",
|
|
56
|
+
decode: "browser",
|
|
57
|
+
"embed-destroyed": "usage",
|
|
58
|
+
"index-out-of-range": "internal",
|
|
59
|
+
"invalid-argument": "usage",
|
|
60
|
+
"invalid-byte-range": "recording",
|
|
61
|
+
"invalid-calibration": "recording",
|
|
62
|
+
"invalid-protobuf": "recording",
|
|
63
|
+
"invalid-trailer": "recording",
|
|
64
|
+
"invariant-violation": "internal",
|
|
65
|
+
"missing-second-file": "recording",
|
|
66
|
+
"no-calibration": "recording",
|
|
67
|
+
"no-info-record": "recording",
|
|
68
|
+
"no-key-frame": "recording",
|
|
69
|
+
"playback-blocked": "browser",
|
|
70
|
+
"range-unsupported": "source",
|
|
71
|
+
"render-unavailable": "browser",
|
|
72
|
+
"source-changed": "source",
|
|
73
|
+
"source-truncated": "source",
|
|
74
|
+
"source-unreadable": "source",
|
|
75
|
+
"unsupported-calibration": "recording",
|
|
76
|
+
"unsupported-container": "recording",
|
|
77
|
+
"unsupported-gyro-record": "recording",
|
|
78
|
+
"unsupported-info-format": "recording",
|
|
79
|
+
"unsupported-layout": "recording",
|
|
80
|
+
"webcodecs-unavailable": "browser"
|
|
81
|
+
};
|
|
35
82
|
function isGyroViewErrorCode(value) {
|
|
36
83
|
return typeof value === "string" && GYRO_VIEW_ERROR_CODES.includes(value);
|
|
37
84
|
}
|
|
38
85
|
var GyroViewError = class extends Error {
|
|
39
86
|
code;
|
|
87
|
+
/**
|
|
88
|
+
* Its own property rather than a getter, so a serialized or logged copy of the error keeps it.
|
|
89
|
+
*/
|
|
90
|
+
category;
|
|
40
91
|
constructor(code, message, options) {
|
|
41
92
|
super(message, options);
|
|
42
93
|
this.code = code;
|
|
43
94
|
this.name = "GyroViewError";
|
|
95
|
+
this.category = CATEGORY_OF_CODE[code];
|
|
44
96
|
}
|
|
45
97
|
};
|
|
46
98
|
/**
|
|
@@ -79,4 +131,4 @@ function ensureIndexInRange(index, length, subject) {
|
|
|
79
131
|
if (!Number.isSafeInteger(index) || index < 0 || index >= length) throw new GyroViewError("index-out-of-range", `${subject} index ${index} is outside 0..${length - 1}`);
|
|
80
132
|
}
|
|
81
133
|
//#endregion
|
|
82
|
-
export { GYRO_VIEW_ERROR_CODES, GyroViewError, asGyroViewError, ensureIndexInRange, ensureInvariant, hasErrorCode, isAbortError, isGyroViewErrorCode, messageOf };
|
|
134
|
+
export { GYRO_VIEW_ERROR_CATEGORIES, GYRO_VIEW_ERROR_CODES, GyroViewError, asGyroViewError, ensureIndexInRange, ensureInvariant, hasErrorCode, isAbortError, isGyroViewErrorCode, messageOf };
|
|
@@ -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();
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region ../../packages/core/src/shared/protobuf/wireFormat.ts
|
|
2
|
+
/**
|
|
3
|
+
* The Protocol Buffers wire format (protobuf encoding spec, "Message Structure"): the wire types
|
|
4
|
+
* a field key names and how keys and varints are laid out. The decoder and the fixtures' encoder
|
|
5
|
+
* share it, so that the two cannot disagree on a byte.
|
|
6
|
+
*
|
|
7
|
+
* The wire types the info record uses; groups (3, 4) are obsolete, and the decoder rejects them.
|
|
8
|
+
*/
|
|
9
|
+
var WireType = {
|
|
10
|
+
Varint: 0,
|
|
11
|
+
Fixed64: 1,
|
|
12
|
+
LengthDelimited: 2,
|
|
13
|
+
Fixed32: 5
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
export { WireType };
|
|
@@ -122,7 +122,8 @@ function wallClock(warning) {
|
|
|
122
122
|
function stitchingSetupOf(opened) {
|
|
123
123
|
return buildStitchingSetup({
|
|
124
124
|
calibration: opened.calibration,
|
|
125
|
-
layout: opened.layout
|
|
125
|
+
layout: opened.layout,
|
|
126
|
+
displayConversions: opened.displayConversions
|
|
126
127
|
});
|
|
127
128
|
}
|
|
128
129
|
function sinkOver(renderer, opened) {
|
|
@@ -3,6 +3,7 @@ import { seconds } from "../../../core/src/shared/units/time.js";
|
|
|
3
3
|
import { timeRecording } from "../../../core/src/application/recording/timeRecording.js";
|
|
4
4
|
import { detectLensLayout } from "../../../core/src/domain/format/layout/detectLensLayout.js";
|
|
5
5
|
import { lensFrameOrder } from "../../../core/src/domain/stitching/StitchingSetup.js";
|
|
6
|
+
import { displayConversionsOf } from "../../../core/src/domain/colour/DisplayConversion.js";
|
|
6
7
|
import { startFileDownload } from "../../../core/src/application/download/startFileDownload.js";
|
|
7
8
|
import { downloadPolicyFor } from "../../../core/src/domain/download/DownloadPolicy.js";
|
|
8
9
|
import { RecordingBuffer } from "../../../core/src/application/download/RecordingBuffer.js";
|
|
@@ -77,18 +78,20 @@ function calibrationOf(recording) {
|
|
|
77
78
|
function assemble(parts, packager, disposables) {
|
|
78
79
|
const { read, files, layout, frameSources, calibration, timing } = parts;
|
|
79
80
|
const duration = seconds(Math.min(...files.map((file) => file.duration)));
|
|
81
|
+
const display = displayConversionsOf(frameSources.map((source) => source.description.colour));
|
|
80
82
|
const [sound] = files.flatMap((file) => file.audioTracks);
|
|
81
83
|
return {
|
|
82
84
|
recording: read.recording,
|
|
83
85
|
layout,
|
|
84
86
|
frameSources,
|
|
85
87
|
calibration,
|
|
88
|
+
displayConversions: display.conversions,
|
|
86
89
|
duration,
|
|
87
90
|
frameTimes: timing.frameTimes,
|
|
88
91
|
motion: timing.motion,
|
|
89
92
|
soundSegments: sound && (() => packager.segmentsOf(sound.samples, sound.configuration)),
|
|
90
93
|
metadata: metadataOf(parts, duration, sound !== void 0),
|
|
91
|
-
warnings: timing.warnings,
|
|
94
|
+
warnings: [...timing.warnings, ...display.warnings],
|
|
92
95
|
readAhead: () => {
|
|
93
96
|
for (const file of files) file.download.startReadingAhead();
|
|
94
97
|
},
|
|
@@ -78,7 +78,8 @@ var DEFAULT_MESSAGES = {
|
|
|
78
78
|
"unsupported-container": UNREADABLE,
|
|
79
79
|
"unsupported-gyro-record": UNREADABLE,
|
|
80
80
|
"unsupported-info-format": UNREADABLE,
|
|
81
|
-
"unsupported-layout": UNREADABLE
|
|
81
|
+
"unsupported-layout": UNREADABLE,
|
|
82
|
+
"webcodecs-unavailable": UNSUPPORTED_BROWSER
|
|
82
83
|
}
|
|
83
84
|
};
|
|
84
85
|
/**
|