@bubo-squared/gyroview 0.1.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.
Files changed (228) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/LICENSE +21 -0
  3. package/README.md +216 -0
  4. package/dist/define.d.ts +3 -0
  5. package/dist/define.js +4 -0
  6. package/dist/index.d.ts +959 -0
  7. package/dist/index.js +13 -0
  8. package/dist/packages/adapters/blob/src/BlobRandomAccessSource.js +37 -0
  9. package/dist/packages/adapters/blob/src/index.js +2 -0
  10. package/dist/packages/adapters/fetch/src/HttpRangeSource.js +194 -0
  11. package/dist/packages/adapters/fetch/src/HttpResourceLocator.js +35 -0
  12. package/dist/packages/adapters/fetch/src/httpRequest.js +126 -0
  13. package/dist/packages/adapters/fetch/src/index.js +3 -0
  14. package/dist/packages/adapters/mediabunny/src/MediabunnyAudioSegments.js +133 -0
  15. package/dist/packages/adapters/mediabunny/src/MediabunnyDemuxer.js +63 -0
  16. package/dist/packages/adapters/mediabunny/src/MediabunnyVideoTrackReader.js +84 -0
  17. package/dist/packages/adapters/mediabunny/src/SegmentChannel.js +84 -0
  18. package/dist/packages/adapters/mediabunny/src/bufferSources.js +12 -0
  19. package/dist/packages/adapters/mediabunny/src/index.js +2 -0
  20. package/dist/packages/adapters/mse-audio/src/MediaSourceAudioClock.js +139 -0
  21. package/dist/packages/adapters/mse-audio/src/SourceBufferFeeder.js +174 -0
  22. package/dist/packages/adapters/mse-audio/src/events.js +26 -0
  23. package/dist/packages/adapters/mse-audio/src/index.js +2 -0
  24. package/dist/packages/adapters/mse-audio/src/mediaSourceSupport.js +82 -0
  25. package/dist/packages/adapters/three/src/ThreeFrameRenderer.js +274 -0
  26. package/dist/packages/adapters/three/src/compileAndProve.js +14 -0
  27. package/dist/packages/adapters/three/src/fullscreenPass.js +52 -0
  28. package/dist/packages/adapters/three/src/index.js +2 -0
  29. package/dist/packages/adapters/three/src/lensTextures.js +25 -0
  30. package/dist/packages/adapters/three/src/pictureMaterials.js +44 -0
  31. package/dist/packages/adapters/three/src/renderInto.js +15 -0
  32. package/dist/packages/adapters/three/src/rendererUniforms.js +157 -0
  33. package/dist/packages/adapters/three/src/samplingStrategies.js +26 -0
  34. package/dist/packages/adapters/three/src/seamMeter/SeamMeterPass.js +79 -0
  35. package/dist/packages/adapters/three/src/seamMeter/rowMeans.js +38 -0
  36. package/dist/packages/adapters/three/src/shaderPrograms.js +66 -0
  37. package/dist/packages/adapters/three/src/shaders/analysis.frag.js +4 -0
  38. package/dist/packages/adapters/three/src/shaders/equirectangularRays.js +4 -0
  39. package/dist/packages/adapters/three/src/shaders/fixedJoin.js +4 -0
  40. package/dist/packages/adapters/three/src/shaders/fullscreen.vert.js +4 -0
  41. package/dist/packages/adapters/three/src/shaders/header.js +4 -0
  42. package/dist/packages/adapters/three/src/shaders/lensModels.js +4 -0
  43. package/dist/packages/adapters/three/src/shaders/lensSampling.js +4 -0
  44. package/dist/packages/adapters/three/src/shaders/lensTextures.js +4 -0
  45. package/dist/packages/adapters/three/src/shaders/rawLenses.frag.js +4 -0
  46. package/dist/packages/adapters/three/src/shaders/rectilinearRays.js +4 -0
  47. package/dist/packages/adapters/three/src/shaders/screenAreas.js +4 -0
  48. package/dist/packages/adapters/three/src/shaders/stitch.frag.js +4 -0
  49. package/dist/packages/adapters/three/src/webglRenderer.js +37 -0
  50. package/dist/packages/adapters/webcodecs/src/WebCodecsVideoDecoderPort.js +135 -0
  51. package/dist/packages/adapters/webcodecs/src/index.js +2 -0
  52. package/dist/packages/core/src/application/gainMatching/GainMatching.js +66 -0
  53. package/dist/packages/core/src/application/gainMatching/GainMatchingFrameSink.js +62 -0
  54. package/dist/packages/core/src/application/playback/ClockWatch.js +76 -0
  55. package/dist/packages/core/src/application/playback/DecodePipeline.js +188 -0
  56. package/dist/packages/core/src/application/playback/DecodeRun.js +93 -0
  57. package/dist/packages/core/src/application/playback/FramePairQueue.js +93 -0
  58. package/dist/packages/core/src/application/playback/FramePairer.js +60 -0
  59. package/dist/packages/core/src/application/playback/PlaybackSession.js +417 -0
  60. package/dist/packages/core/src/application/playback/SeekOrder.js +36 -0
  61. package/dist/packages/core/src/application/playback/SessionLifecycle.js +42 -0
  62. package/dist/packages/core/src/application/playback/StartGate.js +55 -0
  63. package/dist/packages/core/src/application/playback/TimeUpdates.js +31 -0
  64. package/dist/packages/core/src/application/playback/WallClock.js +46 -0
  65. package/dist/packages/core/src/application/playback/keyframeTimeAt.js +15 -0
  66. package/dist/packages/core/src/application/playback/probeDecoding.js +168 -0
  67. package/dist/packages/core/src/application/recording/frameTimesOf.js +22 -0
  68. package/dist/packages/core/src/application/recording/inspectLayout.js +21 -0
  69. package/dist/packages/core/src/application/recording/inspectRecording.js +124 -0
  70. package/dist/packages/core/src/application/recording/locateOtherLensFile.js +18 -0
  71. package/dist/packages/core/src/application/recording/motionOf.js +39 -0
  72. package/dist/packages/core/src/application/recording/readRecording.js +31 -0
  73. package/dist/packages/core/src/application/recording/timeRecording.js +57 -0
  74. package/dist/packages/core/src/application/stabilization/StabilizingFrameSink.js +31 -0
  75. package/dist/packages/core/src/domain/format/boxes/BoxLayout.js +7 -0
  76. package/dist/packages/core/src/domain/format/boxes/boxConstants.js +16 -0
  77. package/dist/packages/core/src/domain/format/boxes/scanBoxes.js +59 -0
  78. package/dist/packages/core/src/domain/format/calibration/CalibrationVersion.js +13 -0
  79. package/dist/packages/core/src/domain/format/calibration/layouts/CalibrationStringLayout.js +34 -0
  80. package/dist/packages/core/src/domain/format/calibration/layouts/LegacyCalibrationLayout.js +44 -0
  81. package/dist/packages/core/src/domain/format/calibration/layouts/MeiCalibrationLayout.js +45 -0
  82. package/dist/packages/core/src/domain/format/calibration/layouts/PolynomialCalibrationLayout.js +44 -0
  83. package/dist/packages/core/src/domain/format/calibration/offsetTokens.js +65 -0
  84. package/dist/packages/core/src/domain/format/calibration/parseOffsetString.js +52 -0
  85. package/dist/packages/core/src/domain/format/calibration/selectCalibration.js +46 -0
  86. package/dist/packages/core/src/domain/format/captureOrigin.js +20 -0
  87. package/dist/packages/core/src/domain/format/constants.js +33 -0
  88. package/dist/packages/core/src/domain/format/info/infoFields.js +110 -0
  89. package/dist/packages/core/src/domain/format/info/parseInfoRecord.js +90 -0
  90. package/dist/packages/core/src/domain/format/info/readInfoRecord.js +14 -0
  91. package/dist/packages/core/src/domain/format/layout/detectLensLayout.js +122 -0
  92. package/dist/packages/core/src/domain/format/naming/RecordingFileName.js +67 -0
  93. package/dist/packages/core/src/domain/format/records/TrailerRecords.js +83 -0
  94. package/dist/packages/core/src/domain/format/records/exposure/parseExposureRecord.js +48 -0
  95. package/dist/packages/core/src/domain/format/records/gyro/FloatGyroSampleLayout.js +39 -0
  96. package/dist/packages/core/src/domain/format/records/gyro/RawGyroSampleLayout.js +55 -0
  97. package/dist/packages/core/src/domain/format/records/gyro/SampleColumns.js +82 -0
  98. package/dist/packages/core/src/domain/format/records/gyro/gyroLayouts.js +12 -0
  99. package/dist/packages/core/src/domain/format/records/gyro/parseGyroRecord.js +129 -0
  100. package/dist/packages/core/src/domain/format/trailer/RecordHeader.js +23 -0
  101. package/dist/packages/core/src/domain/format/trailer/Trailer.js +23 -0
  102. package/dist/packages/core/src/domain/format/trailer/TrailerFooter.js +27 -0
  103. package/dist/packages/core/src/domain/format/trailer/locateRecords.js +80 -0
  104. package/dist/packages/core/src/domain/format/trailer/parseRecordIndex.js +28 -0
  105. package/dist/packages/core/src/domain/format/trailer/readTrailer.js +32 -0
  106. package/dist/packages/core/src/domain/motion/exposure/ExposureRecord.js +53 -0
  107. package/dist/packages/core/src/domain/motion/gyro/GyroTrack.js +60 -0
  108. package/dist/packages/core/src/domain/motion/gyro/medianStep.js +11 -0
  109. package/dist/packages/core/src/domain/motion/gyro/repairedTimeline.js +101 -0
  110. package/dist/packages/core/src/domain/motion/imu/ImuFrame.js +112 -0
  111. package/dist/packages/core/src/domain/motion/orientation/OrientationTrack.js +146 -0
  112. package/dist/packages/core/src/domain/motion/orientation/estimateGyroBias.js +64 -0
  113. package/dist/packages/core/src/domain/motion/orientation/gravity.js +97 -0
  114. package/dist/packages/core/src/domain/motion/stabilization/Stabilizer.js +13 -0
  115. package/dist/packages/core/src/domain/motion/stabilization/stabilizers.js +86 -0
  116. package/dist/packages/core/src/domain/motion/timing/CaptureClock.js +41 -0
  117. package/dist/packages/core/src/domain/motion/timing/FrameTimes.js +92 -0
  118. package/dist/packages/core/src/domain/motion/timing/frameTimeSources.js +61 -0
  119. package/dist/packages/core/src/domain/motion/timing/resolveFrameTimes.js +68 -0
  120. package/dist/packages/core/src/domain/optics/EquidistantModel.js +39 -0
  121. package/dist/packages/core/src/domain/optics/MeiModel.js +45 -0
  122. package/dist/packages/core/src/domain/optics/PolynomialModel.js +44 -0
  123. package/dist/packages/core/src/domain/optics/gainMatch.js +62 -0
  124. package/dist/packages/core/src/domain/optics/lensGeometry.js +18 -0
  125. package/dist/packages/core/src/domain/optics/lensPose.js +35 -0
  126. package/dist/packages/core/src/domain/optics/opticsConstants.js +5 -0
  127. package/dist/packages/core/src/domain/playback/PlayerState.js +83 -0
  128. package/dist/packages/core/src/domain/stitching/LensLayout.js +21 -0
  129. package/dist/packages/core/src/domain/stitching/StitchingSetup.js +78 -0
  130. package/dist/packages/core/src/domain/stitching/seamDisparity.js +4 -0
  131. package/dist/packages/core/src/domain/stitching/seamDisparityField.js +5 -0
  132. package/dist/packages/core/src/domain/stitching/seamJoin.js +16 -0
  133. package/dist/packages/core/src/domain/stitching/seamMismatch.js +1 -0
  134. package/dist/packages/core/src/domain/stitching/seamRing.js +4 -0
  135. package/dist/packages/core/src/domain/stitching/seamStrip.js +26 -0
  136. package/dist/packages/core/src/domain/view/Framing.js +31 -0
  137. package/dist/packages/core/src/domain/view/PictureQuality.js +26 -0
  138. package/dist/packages/core/src/domain/view/ViewMode.js +9 -0
  139. package/dist/packages/core/src/domain/view/ViewState.js +48 -0
  140. package/dist/packages/core/src/domain/view/lensTilesView.js +63 -0
  141. package/dist/packages/core/src/domain/view/magnification.js +103 -0
  142. package/dist/packages/core/src/domain/view/normalView.js +29 -0
  143. package/dist/packages/core/src/domain/view/panoramaView.js +99 -0
  144. package/dist/packages/core/src/domain/view/rectilinear.js +40 -0
  145. package/dist/packages/core/src/domain/view/screenLayout.js +113 -0
  146. package/dist/packages/core/src/domain/view/viewGestures.js +98 -0
  147. package/dist/packages/core/src/domain/view/viewModes.js +14 -0
  148. package/dist/packages/core/src/index.js +59 -0
  149. package/dist/packages/core/src/ports/FramePair.js +6 -0
  150. package/dist/packages/core/src/shared/async/Deferred.js +42 -0
  151. package/dist/packages/core/src/shared/async/RunStop.js +40 -0
  152. package/dist/packages/core/src/shared/binary/ByteRange.js +38 -0
  153. package/dist/packages/core/src/shared/binary/ByteReader.js +77 -0
  154. package/dist/packages/core/src/shared/errors/GyroViewError.js +81 -0
  155. package/dist/packages/core/src/shared/errors/reportLater.js +11 -0
  156. package/dist/packages/core/src/shared/events/Outbox.js +68 -0
  157. package/dist/packages/core/src/shared/events/TypedEmitter.js +55 -0
  158. package/dist/packages/core/src/shared/keysOf.js +10 -0
  159. package/dist/packages/core/src/shared/lazy.js +11 -0
  160. package/dist/packages/core/src/shared/math/Matrix3.js +93 -0
  161. package/dist/packages/core/src/shared/math/Quaternion.js +133 -0
  162. package/dist/packages/core/src/shared/math/Vector3.js +54 -0
  163. package/dist/packages/core/src/shared/math/clamp.js +9 -0
  164. package/dist/packages/core/src/shared/protobuf/ProtobufMessage.js +157 -0
  165. package/dist/packages/core/src/shared/text/urlPath.js +31 -0
  166. package/dist/packages/core/src/shared/text/utf8.js +12 -0
  167. package/dist/packages/core/src/shared/units/angle.js +22 -0
  168. package/dist/packages/core/src/shared/units/time.js +13 -0
  169. package/dist/packages/player/src/PlayerSource.js +15 -0
  170. package/dist/packages/player/src/browserPlayer.js +18 -0
  171. package/dist/packages/player/src/choices.js +25 -0
  172. package/dist/packages/player/src/composition/Disposables.js +31 -0
  173. package/dist/packages/player/src/composition/browserPorts.js +46 -0
  174. package/dist/packages/player/src/composition/buildPipeline.js +153 -0
  175. package/dist/packages/player/src/composition/ensureDecodable.js +63 -0
  176. package/dist/packages/player/src/composition/openInputs.js +179 -0
  177. package/dist/packages/player/src/composition/openRecording.js +42 -0
  178. package/dist/packages/player/src/controls/ChoiceMenu.js +113 -0
  179. package/dist/packages/player/src/controls/PictureMenus.js +47 -0
  180. package/dist/packages/player/src/controls/SeekBar.js +125 -0
  181. package/dist/packages/player/src/controls/SoundControls.js +41 -0
  182. package/dist/packages/player/src/controls/TransportButtons.js +31 -0
  183. package/dist/packages/player/src/controls/ViewGestures.js +136 -0
  184. package/dist/packages/player/src/controls/Wording.js +78 -0
  185. package/dist/packages/player/src/controls/controlParts.js +36 -0
  186. package/dist/packages/player/src/controls/controls.js +4 -0
  187. package/dist/packages/player/src/controls/controlsBar.js +23 -0
  188. package/dist/packages/player/src/controls/controlsMarkup.js +85 -0
  189. package/dist/packages/player/src/controls/customControls.js +59 -0
  190. package/dist/packages/player/src/controls/formatTime.js +19 -0
  191. package/dist/packages/player/src/controls/icons.js +40 -0
  192. package/dist/packages/player/src/controls/keyboard.js +118 -0
  193. package/dist/packages/player/src/controls/messages.js +94 -0
  194. package/dist/packages/player/src/controls/parseMarkup.js +31 -0
  195. package/dist/packages/player/src/controls/viewButtons.js +14 -0
  196. package/dist/packages/player/src/element/ElementLoads.js +119 -0
  197. package/dist/packages/player/src/element/FullscreenToggle.js +39 -0
  198. package/dist/packages/player/src/element/GyroViewElement.js +313 -0
  199. package/dist/packages/player/src/element/IdleWatcher.js +71 -0
  200. package/dist/packages/player/src/element/TypedEventElement.js +22 -0
  201. package/dist/packages/player/src/element/accessibleRegion.js +19 -0
  202. package/dist/packages/player/src/element/attributeNames.js +51 -0
  203. package/dist/packages/player/src/element/attributes.js +101 -0
  204. package/dist/packages/player/src/element/defineGyroView.js +21 -0
  205. package/dist/packages/player/src/element/earlyProperties.js +36 -0
  206. package/dist/packages/player/src/element/elementSource.js +23 -0
  207. package/dist/packages/player/src/element/liveSettings.js +138 -0
  208. package/dist/packages/player/src/element/playbackAttributes.js +53 -0
  209. package/dist/packages/player/src/element/playerEventMirror.js +33 -0
  210. package/dist/packages/player/src/element/reflectedProperties.js +78 -0
  211. package/dist/packages/player/src/element/styles.js +4 -0
  212. package/dist/packages/player/src/element/template.js +47 -0
  213. package/dist/packages/player/src/index.js +10 -0
  214. package/dist/packages/player/src/inspectRecording.js +22 -0
  215. package/dist/packages/player/src/player/DrawingBufferFit.js +77 -0
  216. package/dist/packages/player/src/player/FrameLoop.js +40 -0
  217. package/dist/packages/player/src/player/PictureSettings.js +60 -0
  218. package/dist/packages/player/src/player/Player.js +377 -0
  219. package/dist/packages/player/src/player/PlayerEvents.js +28 -0
  220. package/dist/packages/player/src/player/PlayerPhase.js +21 -0
  221. package/dist/packages/player/src/player/PlayerSound.js +61 -0
  222. package/dist/packages/player/src/player/PlayerView.js +113 -0
  223. package/dist/packages/player/src/player/SessionRelay.js +66 -0
  224. package/dist/packages/player/src/player/ensureFinite.js +26 -0
  225. package/dist/packages/player/src/player/loadRecording.js +65 -0
  226. package/dist/packages/player/src/player/transportEvents.js +29 -0
  227. package/dist/standalone.js +4919 -0
  228. package/package.json +73 -0
@@ -0,0 +1,44 @@
1
+ import { V1Token, V1Trailing } from "../offsetTokens.js";
2
+ import { eulerDegrees } from "./CalibrationStringLayout.js";
3
+ import { LEGACY_RADIUS_ANGLE } from "../../../optics/opticsConstants.js";
4
+ import { EquidistantModel } from "../../../optics/EquidistantModel.js";
5
+ import { CalibrationVersion } from "../CalibrationVersion.js";
6
+ //#region ../../packages/core/src/domain/format/calibration/layouts/LegacyCalibrationLayout.ts
7
+ /**
8
+ * The original `offset` string: `r cx cy yaw pitch roll` per lens, then canvas width and height,
9
+ * then a word whose low bits hold the lens type. The word's upper bits differ between cameras
10
+ * (1 on the X5, 3 on the ONE R), so they are not treated as a version.
11
+ */
12
+ var LEGACY_CALIBRATION_LAYOUT = {
13
+ version: CalibrationVersion.Legacy,
14
+ lensTokens: 6,
15
+ trailingTokens: 3,
16
+ parseLens(block, lensIndex) {
17
+ return {
18
+ lensIndex,
19
+ model: new EquidistantModel({
20
+ edgeRadius: block(V1Token.EdgeRadius),
21
+ radiusAngle: LEGACY_RADIUS_ANGLE,
22
+ principalPoint: {
23
+ x: block(V1Token.CenterX),
24
+ y: block(V1Token.CenterY)
25
+ }
26
+ }),
27
+ orientation: eulerDegrees(block(V1Token.Yaw), block(V1Token.Pitch), block(V1Token.Roll)),
28
+ translation: [
29
+ 0,
30
+ 0,
31
+ 0
32
+ ]
33
+ };
34
+ },
35
+ canvasOf(numbers) {
36
+ const trailingStart = 1 + (numbers[0] ?? 0) * 6;
37
+ return {
38
+ width: numbers[trailingStart + V1Trailing.CanvasWidth] ?? 0,
39
+ height: numbers[trailingStart + V1Trailing.CanvasHeight] ?? 0
40
+ };
41
+ }
42
+ };
43
+ //#endregion
44
+ export { LEGACY_CALIBRATION_LAYOUT };
@@ -0,0 +1,45 @@
1
+ import { V3Token } from "../offsetTokens.js";
2
+ import { canvasOfFirstBlock, eulerDegrees, versionWordMismatch } from "./CalibrationStringLayout.js";
3
+ import { CalibrationVersion } from "../CalibrationVersion.js";
4
+ import { MeiModel } from "../../../optics/MeiModel.js";
5
+ //#region ../../packages/core/src/domain/format/calibration/layouts/MeiCalibrationLayout.ts
6
+ /**
7
+ * `offset_v3`: `xi fx fy cx cy yaw pitch roll tx ty tz k1 k2 k3 p1 p2 width height type` per
8
+ * lens, then a version word with 3 in its high 16 bits.
9
+ */
10
+ var MEI_CALIBRATION_LAYOUT = {
11
+ version: CalibrationVersion.Mei,
12
+ lensTokens: 19,
13
+ trailingTokens: 1,
14
+ versionWordProblem: (versionWord) => versionWordMismatch(versionWord, CalibrationVersion.Mei),
15
+ parseLens(block, lensIndex) {
16
+ return {
17
+ lensIndex,
18
+ model: new MeiModel({
19
+ xi: block(V3Token.Xi),
20
+ focal: [block(V3Token.FocalX), block(V3Token.FocalY)],
21
+ principalPoint: {
22
+ x: block(V3Token.CenterX),
23
+ y: block(V3Token.CenterY)
24
+ },
25
+ radial: [
26
+ block(V3Token.K1),
27
+ block(V3Token.K2),
28
+ block(V3Token.K3)
29
+ ],
30
+ tangential: [block(V3Token.P1), block(V3Token.P2)]
31
+ }),
32
+ orientation: eulerDegrees(block(V3Token.Yaw), block(V3Token.Pitch), block(V3Token.Roll)),
33
+ translation: [
34
+ block(V3Token.TranslationX),
35
+ block(V3Token.TranslationY),
36
+ block(V3Token.TranslationZ)
37
+ ]
38
+ };
39
+ },
40
+ canvasOf(_numbers, blocks) {
41
+ return canvasOfFirstBlock(blocks, V3Token.CanvasWidth, V3Token.CanvasHeight);
42
+ }
43
+ };
44
+ //#endregion
45
+ export { MEI_CALIBRATION_LAYOUT };
@@ -0,0 +1,44 @@
1
+ import { V2Token } from "../offsetTokens.js";
2
+ import { canvasOfFirstBlock, eulerDegrees, versionWordMismatch } from "./CalibrationStringLayout.js";
3
+ import { CalibrationVersion } from "../CalibrationVersion.js";
4
+ import { PolynomialModel } from "../../../optics/PolynomialModel.js";
5
+ //#region ../../packages/core/src/domain/format/calibration/layouts/PolynomialCalibrationLayout.ts
6
+ /**
7
+ * `offset_v2`: `r cx cy yaw pitch roll tx ty tz c1 c2 c3 c4 width height type` per lens, then
8
+ * a version word with 2 in its high 16 bits.
9
+ */
10
+ var POLYNOMIAL_CALIBRATION_LAYOUT = {
11
+ version: CalibrationVersion.Polynomial,
12
+ lensTokens: 16,
13
+ trailingTokens: 1,
14
+ versionWordProblem: (versionWord) => versionWordMismatch(versionWord, CalibrationVersion.Polynomial),
15
+ parseLens(block, lensIndex) {
16
+ return {
17
+ lensIndex,
18
+ model: new PolynomialModel({
19
+ edgeRadius: block(V2Token.EdgeRadius),
20
+ principalPoint: {
21
+ x: block(V2Token.CenterX),
22
+ y: block(V2Token.CenterY)
23
+ },
24
+ coefficients: [
25
+ block(V2Token.C1),
26
+ block(V2Token.C2),
27
+ block(V2Token.C3),
28
+ block(V2Token.C4)
29
+ ]
30
+ }),
31
+ orientation: eulerDegrees(block(V2Token.Yaw), block(V2Token.Pitch), block(V2Token.Roll)),
32
+ translation: [
33
+ block(V2Token.TranslationX),
34
+ block(V2Token.TranslationY),
35
+ block(V2Token.TranslationZ)
36
+ ]
37
+ };
38
+ },
39
+ canvasOf(_numbers, blocks) {
40
+ return canvasOfFirstBlock(blocks, V2Token.CanvasWidth, V2Token.CanvasHeight);
41
+ }
42
+ };
43
+ //#endregion
44
+ export { POLYNOMIAL_CALIBRATION_LAYOUT };
@@ -0,0 +1,65 @@
1
+ //#region ../../packages/core/src/domain/format/calibration/offsetTokens.ts
2
+ /**
3
+ * Token positions inside one lens block of each calibration string version, relative to the
4
+ * block start. Sources: telemetry-parser (v3 order), insta360-rs docs (v2 order), and the X5
5
+ * recordings where the same `cx cy yaw pitch roll` values appear in all three strings, which
6
+ * pins the v1 order to `r cx cy yaw pitch roll`.
7
+ */
8
+ var V1Token = {
9
+ EdgeRadius: 0,
10
+ CenterX: 1,
11
+ CenterY: 2,
12
+ Yaw: 3,
13
+ Pitch: 4,
14
+ Roll: 5
15
+ };
16
+ var V2Token = {
17
+ EdgeRadius: 0,
18
+ CenterX: 1,
19
+ CenterY: 2,
20
+ Yaw: 3,
21
+ Pitch: 4,
22
+ Roll: 5,
23
+ TranslationX: 6,
24
+ TranslationY: 7,
25
+ TranslationZ: 8,
26
+ C1: 9,
27
+ C2: 10,
28
+ C3: 11,
29
+ C4: 12,
30
+ CanvasWidth: 13,
31
+ CanvasHeight: 14,
32
+ LensType: 15
33
+ };
34
+ var V3Token = {
35
+ Xi: 0,
36
+ FocalX: 1,
37
+ FocalY: 2,
38
+ CenterX: 3,
39
+ CenterY: 4,
40
+ Yaw: 5,
41
+ Pitch: 6,
42
+ Roll: 7,
43
+ TranslationX: 8,
44
+ TranslationY: 9,
45
+ TranslationZ: 10,
46
+ K1: 11,
47
+ K2: 12,
48
+ K3: 13,
49
+ P1: 14,
50
+ P2: 15,
51
+ CanvasWidth: 16,
52
+ CanvasHeight: 17,
53
+ LensType: 18
54
+ };
55
+ /**
56
+ * Tokens after the lens blocks. v1 ends with canvas width, canvas height and a version word;
57
+ * v2 and v3 end with the version word only.
58
+ */
59
+ var V1Trailing = {
60
+ CanvasWidth: 0,
61
+ CanvasHeight: 1,
62
+ VersionWord: 2
63
+ };
64
+ //#endregion
65
+ export { V1Token, V1Trailing, V2Token, V3Token };
@@ -0,0 +1,52 @@
1
+ import "./layouts/CalibrationStringLayout.js";
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
+ import { GyroViewError } from "../../../shared/errors/GyroViewError.js";
6
+ //#region ../../packages/core/src/domain/format/calibration/parseOffsetString.ts
7
+ var TOKEN_SEPARATOR = "_";
8
+ var LAYOUTS = [
9
+ LEGACY_CALIBRATION_LAYOUT,
10
+ POLYNOMIAL_CALIBRATION_LAYOUT,
11
+ MEI_CALIBRATION_LAYOUT
12
+ ];
13
+ /**
14
+ * Parses `offset`, `offset_v2` and `offset_v3` strings into a calibration set with its version. The
15
+ * layout is detected from the token count; the v6 layout (13 distortion coefficients per lens) is
16
+ * recognised and rejected explicitly.
17
+ */
18
+ function parseOffsetString(text) {
19
+ const numbers = text.split(TOKEN_SEPARATOR).map((token) => parseNumber(token, text));
20
+ const lensCount = numbers[0] ?? 0;
21
+ const layout = detectLayout(numbers.length, lensCount, text);
22
+ ensureVersionWordFits(layout, numbers.at(-1) ?? 0);
23
+ const blocks = Array.from({ length: lensCount }, (_unused, lensIndex) => lensBlock(numbers, 1 + lensIndex * layout.lensTokens));
24
+ return {
25
+ version: layout.version,
26
+ canvas: layout.canvasOf(numbers, blocks),
27
+ lenses: blocks.map((block, lensIndex) => layout.parseLens(block, lensIndex))
28
+ };
29
+ }
30
+ function tokenCountFor(lensCount, lensTokens, trailingTokens) {
31
+ return 1 + lensCount * lensTokens + trailingTokens;
32
+ }
33
+ function detectLayout(tokenCount, lensCount, text) {
34
+ const layout = LAYOUTS.find((candidate) => tokenCount === tokenCountFor(lensCount, candidate.lensTokens, candidate.trailingTokens));
35
+ if (layout) return layout;
36
+ if (tokenCount === tokenCountFor(lensCount, 27, 1)) throw new GyroViewError("unsupported-calibration", "calibration string uses the v6 layout (13 distortion coefficients), which is not supported yet");
37
+ throw new GyroViewError("invalid-calibration", `calibration string has ${tokenCount} tokens for ${lensCount} lenses, matching no known layout: ${text}`);
38
+ }
39
+ function ensureVersionWordFits(layout, versionWord) {
40
+ const problem = layout.versionWordProblem?.(versionWord);
41
+ if (problem !== void 0) throw new GyroViewError("invalid-calibration", `calibration string has the v${layout.version} layout but ${problem}`);
42
+ }
43
+ function lensBlock(numbers, start) {
44
+ return (token) => numbers[start + token] ?? NaN;
45
+ }
46
+ function parseNumber(token, text) {
47
+ const value = Number(token);
48
+ if (token.trim() === "" || !Number.isFinite(value)) throw new GyroViewError("invalid-calibration", `calibration token "${token}" is not a finite number in: ${text}`);
49
+ return value;
50
+ }
51
+ //#endregion
52
+ export { parseOffsetString };
@@ -0,0 +1,46 @@
1
+ import { GyroViewError } from "../../../shared/errors/GyroViewError.js";
2
+ import { parseOffsetString } from "./parseOffsetString.js";
3
+ //#region ../../packages/core/src/domain/format/calibration/selectCalibration.ts
4
+ /**
5
+ * Only these failures mean "this string is unusable, try the next one"; anything else is a bug
6
+ * and propagates.
7
+ */
8
+ var SKIPPABLE = /* @__PURE__ */ new Set(["invalid-calibration", "unsupported-calibration"]);
9
+ /**
10
+ * Picks the calibration a recording is stitched through: the legacy string first, whose
11
+ * equidistant reading is the one Insta360's own stitch agrees with on the far field
12
+ * (ADR 0023), then the Mei (v3) and polynomial (v2) strings for a recording without it. Strings
13
+ * that cannot be used are reported, not silently dropped; having none is reported as absence,
14
+ * not as a failure.
15
+ */
16
+ function selectCalibration(strings) {
17
+ const candidates = [
18
+ ["offset", strings.offset],
19
+ ["offset_v3", strings.offsetV3],
20
+ ["offset_v2", strings.offsetV2]
21
+ ];
22
+ const warnings = [];
23
+ for (const [name, text] of candidates) {
24
+ if (text === void 0) continue;
25
+ const attempt = tryParse(name, text);
26
+ if ("calibration" in attempt) return {
27
+ calibration: attempt.calibration,
28
+ warnings
29
+ };
30
+ warnings.push(attempt.warning);
31
+ }
32
+ return {
33
+ calibration: void 0,
34
+ warnings
35
+ };
36
+ }
37
+ function tryParse(name, text) {
38
+ try {
39
+ return { calibration: parseOffsetString(text) };
40
+ } catch (error) {
41
+ if (error instanceof GyroViewError && SKIPPABLE.has(error.code)) return { warning: `${name} skipped: ${error.message}` };
42
+ throw error;
43
+ }
44
+ }
45
+ //#endregion
46
+ export { selectCalibration };
@@ -0,0 +1,20 @@
1
+ import { microseconds } from "../../shared/units/time.js";
2
+ //#region ../../packages/core/src/domain/format/captureOrigin.ts
3
+ /**
4
+ * A capture-clock stamp written outside the gyro record (the first frame's, the exposure
5
+ * entries'), as a time: cameras write them in the gyro layout's unit (milliseconds for the
6
+ * float layout, as telemetry-parser reads them), microseconds without a gyro layout.
7
+ */
8
+ function captureTimeOfStamp(stamp, gyroLayout) {
9
+ return gyroLayout ? gyroLayout.captureTimeOf(stamp) : microseconds(stamp);
10
+ }
11
+ /**
12
+ * The capture-clock time of the first encoded frame, the origin of video time; undefined when
13
+ * the info record does not say.
14
+ */
15
+ function firstFrameCaptureTime(info, gyroLayout) {
16
+ const stamp = info.firstFrameTimestamp;
17
+ return stamp === void 0 ? void 0 : captureTimeOfStamp(stamp, gyroLayout);
18
+ }
19
+ //#endregion
20
+ export { captureTimeOfStamp, firstFrameCaptureTime };
@@ -0,0 +1,33 @@
1
+ //#region ../../packages/core/src/domain/format/constants.ts
2
+ /**
3
+ * Byte-level constants of the Insta360 trailer. Sources: the two X5 recordings inspected on
4
+ * 2026-09-18 (test/fixtures/x5/manifest.json), Gyroflow's telemetry-parser (src/insta360/mod.rs)
5
+ * and ExifTool (QuickTimeStream.pl, ProcessInsta360). Every number here was confirmed against
6
+ * the fixtures unless marked otherwise.
7
+ */
8
+ /**
9
+ * ASCII string that ends every Insta360 file carrying a trailer.
10
+ */
11
+ var TRAILER_MAGIC = "8db42d694ccc418790edff439fe026bf";
12
+ /**
13
+ * Record type ids observed in X5 files and documented by telemetry-parser for older cameras.
14
+ */
15
+ var RecordType = {
16
+ Index: 0,
17
+ Info: 1,
18
+ Thumbnail: 2,
19
+ Gyro: 3,
20
+ Exposure: 4,
21
+ ThumbnailExtended: 5,
22
+ FrameTimestamps: 6,
23
+ Gps: 7
24
+ };
25
+ /**
26
+ * Record formats seen in the header's first byte for the info record.
27
+ */
28
+ var InfoRecordFormat = {
29
+ Protobuf: 1,
30
+ Json: 2
31
+ };
32
+ //#endregion
33
+ export { InfoRecordFormat, RecordType, TRAILER_MAGIC };
@@ -0,0 +1,110 @@
1
+ //#region ../../packages/core/src/domain/format/info/infoFields.ts
2
+ /**
3
+ * Field numbers of the info record's protobuf message (record id 1, format 1).
4
+ * Sources: Gyroflow telemetry-parser `src/insta360/extra_info.rs` (names) and the two X5
5
+ * recordings (values confirmed on 2026-09-18). Fields marked "observed" have no published
6
+ * name; their meaning was inferred from the sample values and must be treated as provisional.
7
+ */
8
+ var InfoField = {
9
+ SerialNumber: 1,
10
+ Model: 2,
11
+ Firmware: 3,
12
+ /**
13
+ Legacy calibration string: lens count, then `r cx cy yaw pitch roll` per lens.
14
+ */
15
+ Offset: 5,
16
+ /**
17
+ Nested: 1 width, 2 height of one lens track.
18
+ */
19
+ Dimension: 19,
20
+ FrameRate: 20,
21
+ /**
22
+ Observed: "standard" on X5.
23
+ */
24
+ CaptureMode: 22,
25
+ /**
26
+ Capture-clock timestamp of the first encoded frame; unit follows the gyro record.
27
+ */
28
+ FirstFrameTimestamp: 24,
29
+ RollingShutterTimeMs: 25,
30
+ /**
31
+ Nested: 1 type, 2 index, 3 identify, 4 total. Shared by segments of one recording.
32
+ */
33
+ FileGroupInfo: 26,
34
+ /**
35
+ Nested: 1..6 sensor and crop dimensions. Observed 5376 5376 5312 5312 0 0 on X5.
36
+ */
37
+ WindowCropInfo: 27,
38
+ GyroTimestampMs: 28,
39
+ HasGyroTimestamp: 29,
40
+ TotalFrames: 40,
41
+ IsFlowstateOnline: 42,
42
+ GyroType: 51,
43
+ /**
44
+ Polynomial calibration string (v2).
45
+ */
46
+ OffsetV2: 53,
47
+ /**
48
+ Unified (MEI) camera model calibration string (v3, or v6 with more coefficients).
49
+ */
50
+ OffsetV3: 54,
51
+ IsRawGyro: 62,
52
+ /**
53
+ 1 = frame times from MP4 PTS, 2 = from the exposure record (`PtsType`).
54
+ */
55
+ PtsType: 64,
56
+ /**
57
+ Nested: 1 accelerometer range in g, 2 gyroscope range in degrees per second.
58
+ */
59
+ GyroConfig: 65,
60
+ /**
61
+ Observed (insta360-rs): 1 = split into `_00_`/`_10_` files, 2 = tracks in one file.
62
+ */
63
+ FileLayout: 79,
64
+ /**
65
+ Observed (insta360-rs): 1 = track 0 is stream 10, 2 = track 0 is stream 00.
66
+ */
67
+ TrackOrder: 80
68
+ };
69
+ var DimensionField = {
70
+ Width: 1,
71
+ Height: 2
72
+ };
73
+ var GyroConfigField = {
74
+ AccelerometerRangeG: 1,
75
+ GyroscopeRangeDps: 2
76
+ };
77
+ var WindowCropField = {
78
+ SensorWidth: 1,
79
+ SensorHeight: 2,
80
+ CropWidth: 3,
81
+ CropHeight: 4,
82
+ CropOffsetX: 5,
83
+ CropOffsetY: 6
84
+ };
85
+ /**
86
+ * Values of the `pts_type` field: where the camera says frame times come from.
87
+ */
88
+ var PtsType = {
89
+ TrackTimestamps: 1,
90
+ ExposureRecord: 2
91
+ };
92
+ /**
93
+ * Values of the file-layout field, per insta360-rs. Provisional: observed as 2 on X5 multi-track
94
+ * files, 1 is documented for `_00_`/`_10_` pairs.
95
+ */
96
+ var FileLayoutValue = {
97
+ SplitFiles: 1,
98
+ MultiTrack: 2
99
+ };
100
+ /**
101
+ * Values of the track-order field, per insta360-rs. Provisional: stream `00` is the back lens
102
+ * (calibration lens 0), stream `10` the screen-side lens. The X5 files seen so far write 1, so
103
+ * their first track is the screen-side lens.
104
+ */
105
+ var TrackOrderValue = {
106
+ Stream10First: 1,
107
+ Stream00First: 2
108
+ };
109
+ //#endregion
110
+ export { DimensionField, FileLayoutValue, GyroConfigField, InfoField, PtsType, TrackOrderValue, WindowCropField };
@@ -0,0 +1,90 @@
1
+ import { GyroViewError } from "../../../shared/errors/GyroViewError.js";
2
+ import { DimensionField, FileLayoutValue, GyroConfigField, InfoField, PtsType, TrackOrderValue, WindowCropField } from "./infoFields.js";
3
+ import { InfoRecordFormat } from "../constants.js";
4
+ import { ProtobufMessage } from "../../../shared/protobuf/ProtobufMessage.js";
5
+ import { milliseconds, millisecondsToSeconds } from "../../../shared/units/time.js";
6
+ //#region ../../packages/core/src/domain/format/info/parseInfoRecord.ts
7
+ /**
8
+ * Turns the info record into a {@link RecordingInfo}. Only the protobuf encoding (format 1) is
9
+ * understood; the JSON encoding documented for some firmware has never been observed.
10
+ */
11
+ function parseInfoRecord(payload, format) {
12
+ if (format !== InfoRecordFormat.Protobuf) throw new GyroViewError("unsupported-info-format", `info record uses format ${format}; only protobuf (${InfoRecordFormat.Protobuf}) is supported`);
13
+ const message = ProtobufMessage.decode(payload);
14
+ return {
15
+ serialNumber: message.string(InfoField.SerialNumber),
16
+ model: message.string(InfoField.Model),
17
+ firmware: message.string(InfoField.Firmware),
18
+ calibration: calibrationStringsOf(message),
19
+ dimension: dimensionOf(message.message(InfoField.Dimension)),
20
+ frameRate: message.varint(InfoField.FrameRate),
21
+ captureMode: message.string(InfoField.CaptureMode),
22
+ firstFrameTimestamp: message.varint(InfoField.FirstFrameTimestamp),
23
+ readoutTime: secondsFromMilliseconds(message.double(InfoField.RollingShutterTimeMs)),
24
+ windowCrop: windowCropOf(message.message(InfoField.WindowCropInfo)),
25
+ gyroOffset: optionalMilliseconds(message.double(InfoField.GyroTimestampMs)),
26
+ gyroType: message.varint(InfoField.GyroType),
27
+ isRawGyro: message.boolean(InfoField.IsRawGyro),
28
+ preferredFrameTimeSource: frameTimeSourceOf(message.varint(InfoField.PtsType)),
29
+ sensorRanges: sensorRangesOf(message.message(InfoField.GyroConfig)),
30
+ fileLayout: fileLayoutOf(message.varint(InfoField.FileLayout)),
31
+ trackOrder: trackOrderOf(message.varint(InfoField.TrackOrder))
32
+ };
33
+ }
34
+ function secondsFromMilliseconds(value) {
35
+ return value === void 0 ? void 0 : millisecondsToSeconds(milliseconds(value));
36
+ }
37
+ function optionalMilliseconds(value) {
38
+ return value === void 0 ? void 0 : milliseconds(value);
39
+ }
40
+ /**
41
+ * Other `pts_type` values have never been observed and say nothing to rely on.
42
+ */
43
+ function frameTimeSourceOf(ptsType) {
44
+ if (ptsType === PtsType.TrackTimestamps) return "track-timestamps";
45
+ return ptsType === PtsType.ExposureRecord ? "exposure-record" : void 0;
46
+ }
47
+ /**
48
+ * Other layout and track-order values have never been observed and say nothing to rely on.
49
+ */
50
+ function fileLayoutOf(value) {
51
+ if (value === FileLayoutValue.SplitFiles) return "split-files";
52
+ return value === FileLayoutValue.MultiTrack ? "multi-track" : void 0;
53
+ }
54
+ function trackOrderOf(value) {
55
+ if (value === TrackOrderValue.Stream10First) return "stream-10-first";
56
+ return value === TrackOrderValue.Stream00First ? "stream-00-first" : void 0;
57
+ }
58
+ function calibrationStringsOf(message) {
59
+ return {
60
+ offset: message.string(InfoField.Offset),
61
+ offsetV2: message.string(InfoField.OffsetV2),
62
+ offsetV3: message.string(InfoField.OffsetV3)
63
+ };
64
+ }
65
+ function dimensionOf(message) {
66
+ const width = message?.varint(DimensionField.Width);
67
+ const height = message?.varint(DimensionField.Height);
68
+ return width === void 0 || height === void 0 ? void 0 : {
69
+ width,
70
+ height
71
+ };
72
+ }
73
+ function windowCropOf(message) {
74
+ return message === void 0 ? void 0 : {
75
+ sensorWidth: message.varint(WindowCropField.SensorWidth),
76
+ sensorHeight: message.varint(WindowCropField.SensorHeight),
77
+ cropWidth: message.varint(WindowCropField.CropWidth),
78
+ cropHeight: message.varint(WindowCropField.CropHeight),
79
+ cropOffsetX: message.varint(WindowCropField.CropOffsetX),
80
+ cropOffsetY: message.varint(WindowCropField.CropOffsetY)
81
+ };
82
+ }
83
+ function sensorRangesOf(message) {
84
+ return message === void 0 ? void 0 : {
85
+ accelerometerG: message.varint(GyroConfigField.AccelerometerRangeG),
86
+ gyroscopeDps: message.varint(GyroConfigField.GyroscopeRangeDps)
87
+ };
88
+ }
89
+ //#endregion
90
+ export { parseInfoRecord };
@@ -0,0 +1,14 @@
1
+ import { GyroViewError } from "../../../shared/errors/GyroViewError.js";
2
+ import { RecordType } from "../constants.js";
3
+ import { parseInfoRecord } from "./parseInfoRecord.js";
4
+ //#region ../../packages/core/src/domain/format/info/readInfoRecord.ts
5
+ /**
6
+ * The info record every camera recording carries, from where the trailer says it lies.
7
+ */
8
+ async function readInfoRecord(source, trailer) {
9
+ const location = trailer.locationOf(RecordType.Info);
10
+ if (!location) throw new GyroViewError("no-info-record", "the trailer has no info record; the file is not a camera recording");
11
+ return parseInfoRecord(await source.read(location.payload), location.format);
12
+ }
13
+ //#endregion
14
+ export { readInfoRecord };