supervision 0.1.7 → 0.2.0-next.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 (215) hide show
  1. package/dist/detections/chunked-detection-frame-source.d.ts.map +1 -1
  2. package/dist/index.d.ts +11 -4
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +8856 -4559
  5. package/dist/index.js.map +1 -1
  6. package/dist/mask-preparation.worker.js +310 -164
  7. package/dist/mask-preparation.worker.js.map +1 -1
  8. package/dist/media/display-pixel-ratio.d.ts +15 -0
  9. package/dist/media/display-pixel-ratio.d.ts.map +1 -0
  10. package/dist/media/engine-import-failure.d.ts +16 -0
  11. package/dist/media/engine-import-failure.d.ts.map +1 -0
  12. package/dist/media/media-condition-probe.d.ts +51 -0
  13. package/dist/media/media-condition-probe.d.ts.map +1 -0
  14. package/dist/media/media-conditions.d.ts +28 -0
  15. package/dist/media/media-conditions.d.ts.map +1 -0
  16. package/dist/media/media-errors.d.ts +6 -0
  17. package/dist/media/media-errors.d.ts.map +1 -1
  18. package/dist/media/media-normalization.d.ts.map +1 -1
  19. package/dist/media/media-probe.d.ts.map +1 -1
  20. package/dist/media/media-source.d.ts +17 -0
  21. package/dist/media/media-source.d.ts.map +1 -1
  22. package/dist/media/mediabunny-media-source.d.ts.map +1 -1
  23. package/dist/media/video-engine-media-source.d.ts +44 -0
  24. package/dist/media/video-engine-media-source.d.ts.map +1 -0
  25. package/dist/render-preparation/mask-frame-artifact.d.ts +46 -12
  26. package/dist/render-preparation/mask-frame-artifact.d.ts.map +1 -1
  27. package/dist/render-preparation/mask-frame-compositor.d.ts +5 -5
  28. package/dist/render-preparation/mask-frame-compositor.d.ts.map +1 -1
  29. package/dist/render-preparation/mask-frame-preparer.d.ts.map +1 -1
  30. package/dist/render-preparation/mask-preparation-worker-count.d.ts +4 -4
  31. package/dist/render-preparation/mask-preparation-worker-protocol.d.ts +12 -3
  32. package/dist/render-preparation/mask-preparation-worker-protocol.d.ts.map +1 -1
  33. package/dist/render-preparation/prepared-render-window.d.ts +23 -0
  34. package/dist/render-preparation/prepared-render-window.d.ts.map +1 -1
  35. package/dist/render-preparation/prepared-window-timeline.d.ts +2 -6
  36. package/dist/render-preparation/prepared-window-timeline.d.ts.map +1 -1
  37. package/dist/renderers/mask-palette.d.ts +14 -0
  38. package/dist/renderers/mask-palette.d.ts.map +1 -0
  39. package/dist/renderers/mask-vertex.d.ts +14 -0
  40. package/dist/renderers/mask-vertex.d.ts.map +1 -0
  41. package/dist/renderers/media-renderer-core.d.ts.map +1 -1
  42. package/dist/renderers/media-renderer-scene.d.ts +37 -0
  43. package/dist/renderers/media-renderer-scene.d.ts.map +1 -1
  44. package/dist/renderers/media-renderer-state.d.ts +11 -1
  45. package/dist/renderers/media-renderer-state.d.ts.map +1 -1
  46. package/dist/renderers/media-renderer-transport.d.ts +59 -0
  47. package/dist/renderers/media-renderer-transport.d.ts.map +1 -0
  48. package/dist/renderers/pixi-box-layer.d.ts +5 -0
  49. package/dist/renderers/pixi-box-layer.d.ts.map +1 -1
  50. package/dist/renderers/pixi-focus-layer.d.ts +18 -2
  51. package/dist/renderers/pixi-focus-layer.d.ts.map +1 -1
  52. package/dist/renderers/pixi-frame-present.d.ts +77 -0
  53. package/dist/renderers/pixi-frame-present.d.ts.map +1 -0
  54. package/dist/renderers/pixi-id-mask-shader.d.ts +12 -2
  55. package/dist/renderers/pixi-id-mask-shader.d.ts.map +1 -1
  56. package/dist/renderers/pixi-interaction-layer.d.ts.map +1 -1
  57. package/dist/renderers/pixi-interaction-presentation-layer.d.ts +13 -2
  58. package/dist/renderers/pixi-interaction-presentation-layer.d.ts.map +1 -1
  59. package/dist/renderers/pixi-mask-halo.d.ts +24 -0
  60. package/dist/renderers/pixi-mask-halo.d.ts.map +1 -1
  61. package/dist/renderers/pixi-mask-layer.d.ts +71 -8
  62. package/dist/renderers/pixi-mask-layer.d.ts.map +1 -1
  63. package/dist/renderers/pixi-media-scene.d.ts +67 -0
  64. package/dist/renderers/pixi-media-scene.d.ts.map +1 -1
  65. package/dist/renderers/pixi-polygon-layer.d.ts +7 -2
  66. package/dist/renderers/pixi-polygon-layer.d.ts.map +1 -1
  67. package/dist/renderers/pixi-region-coverage-mask.d.ts +91 -0
  68. package/dist/renderers/pixi-region-coverage-mask.d.ts.map +1 -0
  69. package/dist/renderers/pixi-region-effect.d.ts +42 -0
  70. package/dist/renderers/pixi-region-effect.d.ts.map +1 -0
  71. package/dist/renderers/pixi-region-layer.d.ts +68 -2
  72. package/dist/renderers/pixi-region-layer.d.ts.map +1 -1
  73. package/dist/renderers/pixi-vector-layer.d.ts.map +1 -1
  74. package/dist/renderers/prepared-annotation-window.d.ts +47 -0
  75. package/dist/renderers/prepared-annotation-window.d.ts.map +1 -0
  76. package/dist/renderers/presented-frame-channel.d.ts +107 -0
  77. package/dist/renderers/presented-frame-channel.d.ts.map +1 -0
  78. package/dist/renderers/scene-render-scheduler.d.ts +20 -0
  79. package/dist/renderers/scene-render-scheduler.d.ts.map +1 -0
  80. package/dist/sessions/media-session-defaults.d.ts +10 -6
  81. package/dist/sessions/media-session-defaults.d.ts.map +1 -1
  82. package/dist/sessions/media-session-media.d.ts.map +1 -1
  83. package/dist/sessions/media-session-state.d.ts.map +1 -1
  84. package/dist/sessions/media-session.d.ts.map +1 -1
  85. package/dist/tracking.worker.js +58 -3
  86. package/dist/tracking.worker.js.map +1 -1
  87. package/dist/types/media-conditions.d.ts +149 -0
  88. package/dist/types/media-conditions.d.ts.map +1 -0
  89. package/dist/types/media-normalization.d.ts +34 -0
  90. package/dist/types/media-normalization.d.ts.map +1 -1
  91. package/dist/types/media-renderer.d.ts +31 -1
  92. package/dist/types/media-renderer.d.ts.map +1 -1
  93. package/dist/types/media-session.d.ts +89 -8
  94. package/dist/types/media-session.d.ts.map +1 -1
  95. package/dist/types/render-preparation.d.ts +101 -4
  96. package/dist/types/render-preparation.d.ts.map +1 -1
  97. package/dist/web-video-engine/analysis-session.d.ts +76 -0
  98. package/dist/web-video-engine/analysis-session.d.ts.map +1 -0
  99. package/dist/web-video-engine/analysis.d.ts +7 -0
  100. package/dist/web-video-engine/analysis.d.ts.map +1 -0
  101. package/dist/web-video-engine/analysis.js +1678 -0
  102. package/dist/web-video-engine/analysis.js.map +1 -0
  103. package/dist/web-video-engine/cache-budget.d.ts +19 -0
  104. package/dist/web-video-engine/cache-budget.d.ts.map +1 -0
  105. package/dist/web-video-engine/canvas-sink-scrub-cursor.d.ts +90 -0
  106. package/dist/web-video-engine/canvas-sink-scrub-cursor.d.ts.map +1 -0
  107. package/dist/web-video-engine/clock.d.ts +83 -0
  108. package/dist/web-video-engine/clock.d.ts.map +1 -0
  109. package/dist/web-video-engine/constants.d.ts +253 -0
  110. package/dist/web-video-engine/constants.d.ts.map +1 -0
  111. package/dist/web-video-engine/create-scrub-cursor.d.ts +62 -0
  112. package/dist/web-video-engine/create-scrub-cursor.d.ts.map +1 -0
  113. package/dist/web-video-engine/decode-resolution.d.ts +115 -0
  114. package/dist/web-video-engine/decode-resolution.d.ts.map +1 -0
  115. package/dist/web-video-engine/decode-scheduler.d.ts +356 -0
  116. package/dist/web-video-engine/decode-scheduler.d.ts.map +1 -0
  117. package/dist/web-video-engine/decode-session.d.ts +276 -0
  118. package/dist/web-video-engine/decode-session.d.ts.map +1 -0
  119. package/dist/web-video-engine/decode-source.d.ts +250 -0
  120. package/dist/web-video-engine/decode-source.d.ts.map +1 -0
  121. package/dist/web-video-engine/diagnostics-store.d.ts +18 -0
  122. package/dist/web-video-engine/diagnostics-store.d.ts.map +1 -0
  123. package/dist/web-video-engine/diagnostics.d.ts +316 -0
  124. package/dist/web-video-engine/diagnostics.d.ts.map +1 -0
  125. package/dist/web-video-engine/embedded-engine-worker.d.ts +2 -0
  126. package/dist/web-video-engine/embedded-engine-worker.d.ts.map +1 -0
  127. package/dist/web-video-engine/engine-core.d.ts +258 -0
  128. package/dist/web-video-engine/engine-core.d.ts.map +1 -0
  129. package/dist/web-video-engine/engine.d.ts +26 -0
  130. package/dist/web-video-engine/engine.d.ts.map +1 -0
  131. package/dist/web-video-engine/engine.js +873 -0
  132. package/dist/web-video-engine/engine.js.map +1 -0
  133. package/dist/web-video-engine/engine.worker.d.ts +2 -0
  134. package/dist/web-video-engine/engine.worker.d.ts.map +1 -0
  135. package/dist/web-video-engine/engine.worker.js +31320 -0
  136. package/dist/web-video-engine/engine.worker.js.map +1 -0
  137. package/dist/web-video-engine/frame-cache.d.ts +129 -0
  138. package/dist/web-video-engine/frame-cache.d.ts.map +1 -0
  139. package/dist/web-video-engine/frame-extractor.d.ts +28 -0
  140. package/dist/web-video-engine/frame-extractor.d.ts.map +1 -0
  141. package/dist/web-video-engine/frame-timeline-GINI8Gum.js +560 -0
  142. package/dist/web-video-engine/frame-timeline-GINI8Gum.js.map +1 -0
  143. package/dist/web-video-engine/frame-timeline.d.ts +71 -0
  144. package/dist/web-video-engine/frame-timeline.d.ts.map +1 -0
  145. package/dist/web-video-engine/frame-walker.d.ts +74 -0
  146. package/dist/web-video-engine/frame-walker.d.ts.map +1 -0
  147. package/dist/web-video-engine/index.d.ts +3 -0
  148. package/dist/web-video-engine/index.d.ts.map +1 -0
  149. package/dist/web-video-engine/index.js +3 -0
  150. package/dist/web-video-engine/index.js.map +1 -0
  151. package/dist/web-video-engine/key-packet.d.ts +65 -0
  152. package/dist/web-video-engine/key-packet.d.ts.map +1 -0
  153. package/dist/web-video-engine/keyframe-index.d.ts +91 -0
  154. package/dist/web-video-engine/keyframe-index.d.ts.map +1 -0
  155. package/dist/web-video-engine/mirror-store.d.ts +56 -0
  156. package/dist/web-video-engine/mirror-store.d.ts.map +1 -0
  157. package/dist/web-video-engine/renderer.d.ts +94 -0
  158. package/dist/web-video-engine/renderer.d.ts.map +1 -0
  159. package/dist/web-video-engine/rotation.d.ts +35 -0
  160. package/dist/web-video-engine/rotation.d.ts.map +1 -0
  161. package/dist/web-video-engine/scrub-controller.d.ts +376 -0
  162. package/dist/web-video-engine/scrub-controller.d.ts.map +1 -0
  163. package/dist/web-video-engine/scrub-cursor.d.ts +342 -0
  164. package/dist/web-video-engine/scrub-cursor.d.ts.map +1 -0
  165. package/dist/web-video-engine/scrub-trajectory.d.ts +30 -0
  166. package/dist/web-video-engine/scrub-trajectory.d.ts.map +1 -0
  167. package/dist/web-video-engine/source-residency.d.ts +57 -0
  168. package/dist/web-video-engine/source-residency.d.ts.map +1 -0
  169. package/dist/web-video-engine/trace-recorder.d.ts +164 -0
  170. package/dist/web-video-engine/trace-recorder.d.ts.map +1 -0
  171. package/dist/web-video-engine/types.d.ts +204 -0
  172. package/dist/web-video-engine/types.d.ts.map +1 -0
  173. package/dist/web-video-engine/video-engine.d.ts +426 -0
  174. package/dist/web-video-engine/video-engine.d.ts.map +1 -0
  175. package/dist/web-video-engine/webgpu-renderer.d.ts +62 -0
  176. package/dist/web-video-engine/webgpu-renderer.d.ts.map +1 -0
  177. package/dist/web-video-engine/worker-bridge.d.ts +12 -0
  178. package/dist/web-video-engine/worker-bridge.d.ts.map +1 -0
  179. package/dist/web-video-engine/worker-dispatch.d.ts +17 -0
  180. package/dist/web-video-engine/worker-dispatch.d.ts.map +1 -0
  181. package/dist/web-video-engine/worker-protocol.d.ts +267 -0
  182. package/dist/web-video-engine/worker-protocol.d.ts.map +1 -0
  183. package/node_modules/supervision-js-core/dist/detections/buffered-detection-timeline.d.ts.map +1 -1
  184. package/node_modules/supervision-js-core/dist/detections/composite-detection-frame-source.d.ts.map +1 -1
  185. package/node_modules/supervision-js-core/dist/index.d.ts +4 -3
  186. package/node_modules/supervision-js-core/dist/index.d.ts.map +1 -1
  187. package/node_modules/supervision-js-core/dist/index.js +1075 -266
  188. package/node_modules/supervision-js-core/dist/index.js.map +1 -1
  189. package/node_modules/supervision-js-core/dist/styles/default-annotation-presentation.d.ts.map +1 -1
  190. package/node_modules/supervision-js-core/dist/styles/interaction-style.d.ts +4 -36
  191. package/node_modules/supervision-js-core/dist/styles/interaction-style.d.ts.map +1 -1
  192. package/node_modules/supervision-js-core/dist/styles/polyline-style.d.ts +5 -0
  193. package/node_modules/supervision-js-core/dist/styles/polyline-style.d.ts.map +1 -1
  194. package/node_modules/supervision-js-core/dist/types/annotation-renderer.d.ts +92 -7
  195. package/node_modules/supervision-js-core/dist/types/annotation-renderer.d.ts.map +1 -1
  196. package/node_modules/supervision-js-core/dist/types/detection-timeline.d.ts +179 -17
  197. package/node_modules/supervision-js-core/dist/types/detection-timeline.d.ts.map +1 -1
  198. package/node_modules/supervision-js-core/dist/types/media-rendering.d.ts +78 -2
  199. package/node_modules/supervision-js-core/dist/types/media-rendering.d.ts.map +1 -1
  200. package/node_modules/supervision-js-core/dist/types/polyline-style.d.ts +2 -0
  201. package/node_modules/supervision-js-core/dist/types/polyline-style.d.ts.map +1 -1
  202. package/node_modules/supervision-js-core/dist/types/session-lifecycle.d.ts +16 -0
  203. package/node_modules/supervision-js-core/dist/types/session-lifecycle.d.ts.map +1 -1
  204. package/node_modules/supervision-js-core/dist/utils/detection-conversions.d.ts.map +1 -1
  205. package/node_modules/supervision-js-core/dist/utils/detection-frames.d.ts +5 -0
  206. package/node_modules/supervision-js-core/dist/utils/detection-frames.d.ts.map +1 -1
  207. package/node_modules/supervision-js-core/dist/utils/detection-masks.d.ts +9 -0
  208. package/node_modules/supervision-js-core/dist/utils/detection-masks.d.ts.map +1 -1
  209. package/node_modules/supervision-js-core/dist/utils/detection-ranges.d.ts +18 -0
  210. package/node_modules/supervision-js-core/dist/utils/detection-ranges.d.ts.map +1 -0
  211. package/node_modules/supervision-js-core/dist/utils/id-mask-frame.d.ts +15 -2
  212. package/node_modules/supervision-js-core/dist/utils/id-mask-frame.d.ts.map +1 -1
  213. package/node_modules/supervision-js-core/dist/utils/wait-bound.d.ts +7 -0
  214. package/node_modules/supervision-js-core/dist/utils/wait-bound.d.ts.map +1 -0
  215. package/package.json +22 -1
@@ -0,0 +1,74 @@
1
+ import { type WalkFrameSource, type WalkSourceHandle } from "./decode-source";
2
+ import type { VideoSampleLike } from "./scrub-cursor";
3
+ import type { VideoSource } from "./types";
4
+ /**
5
+ * One frame of a walk.
6
+ *
7
+ * `frameIndex` counts real frames from the start of the walked range, so the
8
+ * same frame carries the same number whatever stride was taken, and
9
+ * `timestampMs` is the sample's own.
10
+ *
11
+ * `sample` is live and closing it is the caller's, the obligation every
12
+ * VideoSampleLike carries. One dropped without close holds a decoder frame until
13
+ * garbage collection, which WebCodecs complains about on the console and which
14
+ * starves the decoder long before that.
15
+ */
16
+ export interface WalkedFrame {
17
+ readonly frameIndex: number;
18
+ readonly timestampMs: number;
19
+ readonly durationMs: number;
20
+ readonly sample: VideoSampleLike;
21
+ }
22
+ export interface FrameWalkRange {
23
+ /** Inclusive start; the track's first timestamp when omitted. */
24
+ readonly startMs?: number;
25
+ /** Exclusive end, so two abutting ranges walk every frame once between them;
26
+ * the end of the source when omitted. */
27
+ readonly endMs?: number;
28
+ /** Yield every Nth real frame. Counted in frames, not in time, so the spacing
29
+ * holds on a variable-rate source and cannot accumulate drift. */
30
+ readonly stride?: number;
31
+ }
32
+ export interface FrameWalkMetadata {
33
+ readonly durationS: number;
34
+ readonly width: number;
35
+ readonly height: number;
36
+ readonly nativeFps: number | null;
37
+ readonly firstTimestampS: number;
38
+ }
39
+ /**
40
+ * Every real decoded frame of a range, in presentation order, exactly once.
41
+ *
42
+ * Nothing here is synthesized: the walk reads the source's own frames and counts
43
+ * them. Timestamps built from a frame rate and resolved through at-or-before
44
+ * extraction cannot promise that. One falling a float's width short of a sample
45
+ * lands on the frame before it, so the caller gets that frame twice and never
46
+ * sees the one it was aiming at.
47
+ *
48
+ * Every sample the walk decodes and does not yield is closed here: the frames
49
+ * before the range, the ones stride skips, and the first one past the end.
50
+ * Breaking out of the walk returns the underlying stream, which releases the
51
+ * decoder's read of the source; the sample in the caller's hand at that moment
52
+ * is still the caller's to close.
53
+ */
54
+ export declare function walkFrames(source: WalkFrameSource, range?: FrameWalkRange): AsyncGenerator<WalkedFrame, void, unknown>;
55
+ /**
56
+ * A batch consumer's entry to the runtime: opens a source, walks its real
57
+ * frames, and disposes what it opened. It spins no worker, binds no canvas, and
58
+ * runs no clock, and it decodes on an input of its own, so a walk and a playing
59
+ * engine never contend for one decoder's read head.
60
+ *
61
+ * A walk in flight ends when the walker is closed, the same way extraction does,
62
+ * so a consumer that abandons a job mid-range has one call to make.
63
+ */
64
+ export declare class FrameWalker {
65
+ private readonly handle;
66
+ private closed;
67
+ constructor(handle: WalkSourceHandle);
68
+ /** Opens a source for walking; the returned walker owns it. */
69
+ static open(source: VideoSource): Promise<FrameWalker>;
70
+ get metadata(): FrameWalkMetadata;
71
+ walkFrames(range?: FrameWalkRange): AsyncGenerator<WalkedFrame, void, unknown>;
72
+ close(): Promise<void>;
73
+ }
74
+ //# sourceMappingURL=frame-walker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-walker.d.ts","sourceRoot":"","sources":["../src/frame-walker.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAQ3C;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;CAClC;AAED,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B;8CAC0C;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;uEACmE;IACnE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAuB,UAAU,CAC/B,MAAM,EAAE,eAAe,EACvB,KAAK,GAAE,cAAmB,GACzB,cAAc,CAAC,WAAW,EAAE,IAAI,EAAE,OAAO,CAAC,CA8C5C;AAED;;;;;;;;GAQG;AACH,qBAAa,WAAW;IAGV,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,OAAO,CAAC,MAAM,CAAS;gBAEM,MAAM,EAAE,gBAAgB;IAErD,+DAA+D;WAClD,IAAI,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAI5D,IAAI,QAAQ,IAAI,iBAAiB,CAShC;IAEM,UAAU,CACf,KAAK,GAAE,cAAmB,GACzB,cAAc,CAAC,WAAW,EAAE,IAAI,EAAE,OAAO,CAAC;IAoBvC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B"}
@@ -0,0 +1,3 @@
1
+ export * from "#web-video-engine";
2
+ export { createVideoEngineMediaRendererSource, openVideoEngineMediaSource, type VideoEngineMediaSource, type VideoEngineMediaSourceOptions, } from "supervision";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/web-video-engine/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,OAAO,EACL,oCAAoC,EACpC,0BAA0B,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,6BAA6B,GACnC,MAAM,aAAa,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './engine.js';
2
+ export { createVideoEngineMediaRendererSource, openVideoEngineMediaSource } from '../index.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * An H.264 sync sample that is not an IDR frame cannot open a WebCodecs decode
3
+ * session: Chrome rejects the chunk with "An EncodedVideoChunk was marked as
4
+ * type key but wasn't a key frame" and emits no frames. Adding a recovery-point
5
+ * SEI to the access unit declares it a valid entry point, which is enough for the
6
+ * decoder to accept it and decode forward from there.
7
+ *
8
+ * The decoder demands an entry point for exactly one chunk, the first after
9
+ * configure() or flush(), and putting the SEI on any other chunk misdescribes
10
+ * the stream. KeyPacketRequirement is what tracks which chunk that is.
11
+ */
12
+ /**
13
+ * Width of the AVCC length prefix this track frames every NAL with, read from
14
+ * its avcC record, or null when the description names no usable width. Files
15
+ * carry 1, 2, and 4, so nothing downstream may assume one of them.
16
+ */
17
+ export declare function nalPrefixWidth(description: VideoDecoderConfig["description"]): number | null;
18
+ /**
19
+ * Whether this access unit carries an IDR slice.
20
+ *
21
+ * A container's sync table names sync samples, and an H.264 sync sample is
22
+ * usually an ordinary I picture rather than an IDR. The two differ in what a
23
+ * decoder may assume about the pictures that follow: an IDR empties the
24
+ * reference list, so nothing after it can name a picture from before it, while
25
+ * an I picture leaves the list standing and the next reference frame is free to
26
+ * name pictures the entry point never decoded. Only the IDR is an entry point
27
+ * the bitstream cannot invalidate.
28
+ *
29
+ * Unreadable framing reads as not-IDR: the caller's fallback is to enter
30
+ * further back, which costs a walk and is never wrong.
31
+ */
32
+ export declare function isIdrAccessUnit(packetBytes: Uint8Array, prefixWidth: number): boolean;
33
+ /**
34
+ * The access unit as the chunk that opens a decode, carrying the recovery-point
35
+ * SEI that makes it a legal entry point.
36
+ *
37
+ * Where the SEI goes is the whole of it: an access unit delimiter, when the
38
+ * packet has one, is required to be the access unit's first NAL, so the SEI goes
39
+ * behind it. Ahead of it the access unit is malformed, and a decoder reading the
40
+ * opening chunk to decide whether it is really a key frame is entitled to say it
41
+ * is not.
42
+ */
43
+ export declare function openingKeyPacket(packetBytes: Uint8Array, prefixWidth: number): Uint8Array;
44
+ /**
45
+ * WebCodecs' standing demand for a key frame, which configure() and flush()
46
+ * both arm and the next submitted chunk clears.
47
+ */
48
+ export declare class KeyPacketRequirement {
49
+ private readonly prefixWidth;
50
+ private pending;
51
+ constructor(prefixWidth: number);
52
+ /** Whether the demand still stands, so the chunk about to satisfy it can
53
+ * also be typed as the key chunk the decoder is waiting for. */
54
+ get armed(): boolean;
55
+ /** Call after every configure() and flush(). */
56
+ rearm(): void;
57
+ /**
58
+ * Bytes to submit for the next packet in decode order, carrying the
59
+ * recovery-point SEI while the demand stands. The container reports sync
60
+ * samples, never IDR frames, so the SEI goes on without inspecting the
61
+ * packet; ahead of a true IDR it is a NAL the decoder ignores.
62
+ */
63
+ satisfy(packetBytes: Uint8Array): Uint8Array;
64
+ }
65
+ //# sourceMappingURL=key-packet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-packet.d.ts","sourceRoot":"","sources":["../src/key-packet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAyCH;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,kBAAkB,CAAC,aAAa,CAAC,GAC7C,MAAM,GAAG,IAAI,CAOf;AAqED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,UAAU,EACvB,WAAW,EAAE,MAAM,GAClB,OAAO,CAIT;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,UAAU,EACvB,WAAW,EAAE,MAAM,GAClB,UAAU,CAWZ;AAaD;;;GAGG;AACH,qBAAa,oBAAoB;IAGnB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAFxC,OAAO,CAAC,OAAO,CAAQ;gBAEM,WAAW,EAAE,MAAM;IAEhD;qEACiE;IACjE,IAAI,KAAK,IAAI,OAAO,CAEnB;IAED,gDAAgD;IAChD,KAAK,IAAI,IAAI;IAIb;;;;;OAKG;IACH,OAAO,CAAC,WAAW,EAAE,UAAU,GAAG,UAAU;CAK7C"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Lazy index of a video track's keyframe timestamps, in seconds.
3
+ *
4
+ * Seeking decodes forward from the keyframe at-or-before the target, so every
5
+ * seek needs that anchor. Resolving one costs a container round-trip, so the
6
+ * index remembers each keyframe it discovers; repeated seeks around the same
7
+ * region then resolve synchronously through `cachedAtOrBefore`.
8
+ */
9
+ /**
10
+ * Opaque packet handle. Only `timestamp` is read; the object is threaded back
11
+ * into `getNextKeyPacket` unchanged so the probe's hidden packet fields survive.
12
+ */
13
+ export interface KeyframePacketLike {
14
+ readonly timestamp: number;
15
+ }
16
+ interface KeyframeRetrievalOptions {
17
+ readonly metadataOnly?: boolean;
18
+ }
19
+ /** The slice of mediabunny's `EncodedPacketSink` the index depends on. */
20
+ export interface KeyframeProbe {
21
+ getKeyPacket(timestamp: number, options?: KeyframeRetrievalOptions): Promise<KeyframePacketLike | null>;
22
+ getNextKeyPacket(packet: KeyframePacketLike, options?: KeyframeRetrievalOptions): Promise<KeyframePacketLike | null>;
23
+ }
24
+ /**
25
+ * Distribution of the gaps between discovered keyframes, in seconds. A long
26
+ * maxGopS (or a high stddev) is the badly-encoded-source tell: an off-anchor
27
+ * seek must decode forward from the prior keyframe, so a long GOP is a wall of
28
+ * frames every scrub pays for. Zeros when fewer than two keyframes are known.
29
+ */
30
+ export interface GopStats {
31
+ readonly count: number;
32
+ readonly avgGopS: number;
33
+ readonly maxGopS: number;
34
+ readonly minGopS: number;
35
+ readonly stddevS: number;
36
+ readonly densityPerS: number;
37
+ }
38
+ export declare class KeyframeIndex {
39
+ private readonly probe;
40
+ private readonly times;
41
+ private probeRoundTrips;
42
+ /** Set once a full walk has completed, so a second call is a free no-op. */
43
+ private fullyIndexed;
44
+ constructor(probe: KeyframeProbe);
45
+ /** Keyframe timestamps discovered so far, ascending and deduplicated. */
46
+ get known(): readonly number[];
47
+ /** Container queries the index has made; the rest resolve from memory. */
48
+ get probeCount(): number;
49
+ /**
50
+ * GOP-gap distribution over the keyframes discovered so far. Pass the track
51
+ * duration so density reflects keyframes across the whole clip, not just the
52
+ * clustered swept span; without it a few discovered keyframes in one region
53
+ * would read as a high density that does not hold track-wide.
54
+ */
55
+ gopStats(durationS?: number): GopStats;
56
+ /**
57
+ * Nearest keyframe at or before `tSec`, the anchor a seek decodes forward
58
+ * from. Null when `tSec` precedes the first keyframe.
59
+ */
60
+ keyframeAtOrBefore(tSec: number): Promise<number | null>;
61
+ /**
62
+ * First keyframe strictly after `tSec`, the boundary a forward decode runs
63
+ * up to. Null when no keyframe follows, or when `tSec` precedes the first
64
+ * keyframe (no anchor to step from).
65
+ */
66
+ nextKeyframeAfter(tSec: number): Promise<number | null>;
67
+ /**
68
+ * Every keyframe needed to decode the window `[startS, endS]`: the anchor at
69
+ * or before `startS` plus each keyframe up to `endS`. Empty when `startS`
70
+ * precedes the first keyframe.
71
+ */
72
+ keyframesCovering(startS: number, endS: number): Promise<readonly number[]>;
73
+ /**
74
+ * Walks the whole track once, recording every keyframe timestamp. Metadata
75
+ * only: it threads the same getKeyPacket / getNextKeyPacket pattern as the
76
+ * lazy probes, so it never decodes a pixel. Idempotent: a second call after a
77
+ * completed walk returns at once. Meant for the diagnostics lane, off the hot
78
+ * seek path, so the purple lane reflects the whole file rather than only the
79
+ * regions a scrub has visited.
80
+ */
81
+ ensureFullyIndexed(fromS?: number): Promise<void>;
82
+ /**
83
+ * Largest discovered keyframe at or before `tSec`, resolved synchronously
84
+ * from memory. Null when nothing at or before `tSec` has been discovered
85
+ * yet; callers fall back to the async probes above.
86
+ */
87
+ cachedAtOrBefore(tSec: number): number | null;
88
+ private record;
89
+ }
90
+ export {};
91
+ //# sourceMappingURL=keyframe-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyframe-index.d.ts","sourceRoot":"","sources":["../src/keyframe-index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,UAAU,wBAAwB;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC5B,YAAY,CACV,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,wBAAwB,GACjC,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;IACtC,gBAAgB,CACd,MAAM,EAAE,kBAAkB,EAC1B,OAAO,CAAC,EAAE,wBAAwB,GACjC,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;CACvC;AAKD;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,qBAAa,aAAa;IAMZ,OAAO,CAAC,QAAQ,CAAC,KAAK;IALlC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IACtC,OAAO,CAAC,eAAe,CAAK;IAC5B,4EAA4E;IAC5E,OAAO,CAAC,YAAY,CAAS;gBAEA,KAAK,EAAE,aAAa;IAEjD,yEAAyE;IACzE,IAAI,KAAK,IAAI,SAAS,MAAM,EAAE,CAE7B;IAED,0EAA0E;IAC1E,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ;IAwCtC;;;OAGG;IACG,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAQ9D;;;;OAIG;IACG,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAY7D;;;;OAIG;IACG,iBAAiB,CACrB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC;IAc7B;;;;;;;OAOG;IACG,kBAAkB,CAAC,KAAK,SAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAYlD;;;;OAIG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAK7C,OAAO,CAAC,MAAM;CAKf"}
@@ -0,0 +1,56 @@
1
+ import type { FrameId, FrameLanding } from "./frame-timeline";
2
+ import { type EngineChannel, type PaintSeq, type PlaybackState, PlaybackStatus } from "./types";
3
+ /**
4
+ * Tiny external store powering useSyncExternalStore subscriptions. Five
5
+ * emit channels by mutation cadence:
6
+ *
7
+ * - time: emits when the playhead moves to a different frame. Consumers
8
+ * wanting a slower rerender cadence apply their own selector.
9
+ * - frame: emits on every settled cursor-yielded frame, for marker rails.
10
+ * - state: status transitions only. Rare. Driven by load, play, pause,
11
+ * seek, end, error.
12
+ * - duration: emits once per loaded source.
13
+ * - seeking: emits when the cursor transitions in/out of an in-flight
14
+ * scrub. Powers an opt-in scrub-in-flight indicator. Cache-hit
15
+ * scrubs typically don't trip this because the cache paint is
16
+ * synchronous, so the engine writes true only when the cursor
17
+ * is actually doing a decode walk.
18
+ * - rate: emits on a playback-rate change. Rarest channel of the six.
19
+ *
20
+ * Channels are separate so a status-only consumer does not wake up at
21
+ * 60Hz when only time advances.
22
+ */
23
+ export declare class MirrorStore {
24
+ private playhead;
25
+ private paintSeq;
26
+ private durationMs;
27
+ private status;
28
+ private error;
29
+ private seeking;
30
+ private rate;
31
+ private playbackStateSnapshot;
32
+ private readonly channelListeners;
33
+ getPlayhead(): FrameLanding;
34
+ getDurationMs(): number;
35
+ getStatus(): PlaybackStatus;
36
+ getError(): PlaybackState["error"];
37
+ getPaintSeq(): PaintSeq;
38
+ getPlaybackState(): PlaybackState;
39
+ getSeeking(): boolean;
40
+ getRate(): number;
41
+ /**
42
+ * Moves the playhead onto a frame. Ticks are integers, so the same frame
43
+ * arriving twice is recognised as the same frame and wakes nobody; the
44
+ * millisecond plane this replaced could not tell two positions apart at all,
45
+ * and emitted on every paint.
46
+ */
47
+ writePlayhead(frame: FrameId, mediaTimeS: number): void;
48
+ writePaintSeq(value: PaintSeq): void;
49
+ writeDurationMs(value: number): void;
50
+ writeStatus(status: PlaybackStatus, error?: PlaybackState["error"]): void;
51
+ writeSeeking(isSeeking: boolean): void;
52
+ writeRate(value: number): void;
53
+ subscribe(channel: EngineChannel, listener: () => void): () => void;
54
+ private emit;
55
+ }
56
+ //# sourceMappingURL=mirror-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mirror-store.d.ts","sourceRoot":"","sources":["../src/mirror-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,cAAc,EACf,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAGd;IACF,OAAO,CAAC,QAAQ,CAA2B;IAC3C,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,IAAI,CAAK;IAIjB,OAAO,CAAC,qBAAqB,CAG3B;IAEF,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAO/B;IAEF,WAAW,IAAI,YAAY;IAG3B,aAAa,IAAI,MAAM;IAGvB,SAAS,IAAI,cAAc;IAG3B,QAAQ,IAAI,aAAa,CAAC,OAAO,CAAC;IAGlC,WAAW,IAAI,QAAQ;IAGvB,gBAAgB,IAAI,aAAa;IAGjC,UAAU,IAAI,OAAO;IAGrB,OAAO,IAAI,MAAM;IAIjB;;;;;OAKG;IACH,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAMvD,aAAa,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAMpC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAMpC,WAAW,CACT,MAAM,EAAE,cAAc,EACtB,KAAK,GAAE,aAAa,CAAC,OAAO,CAAQ,GACnC,IAAI;IAQP,YAAY,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI;IAMtC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAM9B,SAAS,CAAC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAOnE,OAAO,CAAC,IAAI;CAGb"}
@@ -0,0 +1,94 @@
1
+ import type { RendererName } from "./diagnostics";
2
+ import type { ScrubFrame } from "./scrub-cursor";
3
+ /**
4
+ * The colour space every render surface declares. A decoded frame carries its
5
+ * own and the browser converts it into whatever the destination names, but only
6
+ * on the canvas routes: the zero-copy import converts to sRGB whatever colour
7
+ * space it is asked for. A wider value here would therefore reach some routes
8
+ * and not others, on the same frame.
9
+ */
10
+ export declare const DISPLAY_COLOR_SPACE: PredefinedColorSpace;
11
+ /**
12
+ * The render seam: turns a decoded frame into pixels on the display canvas. The
13
+ * render loop owns timing and frame selection; a Renderer owns only how a frame
14
+ * reaches the screen, so the 2D and WebGPU paths are interchangeable behind it
15
+ * without the loop knowing which is in play.
16
+ */
17
+ export interface Renderer {
18
+ /** Which backend this is, for diagnostics. */
19
+ readonly name: RendererName;
20
+ /**
21
+ * Paint one frame to fill the canvas, replacing whatever it last showed.
22
+ * A canvas frame carries a CanvasImageSource (a CanvasSink decode or a cache
23
+ * blit); a sample frame carries a live VideoSample the WebGPU path can import
24
+ * zero-copy. The controller owns the sample's lifetime and close, so a
25
+ * renderer never closes the frame it is handed.
26
+ */
27
+ draw(frame: ScrubFrame): void;
28
+ dispose(): void;
29
+ }
30
+ /**
31
+ * 2D-canvas renderer: one blit of an already-decoded frame through a 2D context.
32
+ * It is the graceful-degradation fallback wherever WebGPU is unavailable and the
33
+ * path prefer2d pins. Per the Renderer contract the loop owns cadence, so a draw
34
+ * happens only when a new frame is decoded. This is not a re-decode and not a
35
+ * per-tick repaint; it differs from the WebGPU path only in compositing a frame
36
+ * through a 2D context rather than on the GPU. Canvas dimensions are read live,
37
+ * so a resize between draws is picked up on the next frame.
38
+ */
39
+ export declare class CanvasRenderer implements Renderer {
40
+ private readonly canvas;
41
+ readonly name: "2d";
42
+ private readonly ctx;
43
+ constructor(canvas: OffscreenCanvas);
44
+ draw(frame: ScrubFrame): void;
45
+ dispose(): void;
46
+ }
47
+ /**
48
+ * The presentation seam: what one paint does with a frame's pixels. The render
49
+ * loop decides which frame is presented and when, and keeps the same books
50
+ * either way; a sink decides only where the pixels go, so the engine's own
51
+ * display canvas and a host compositor are interchangeable behind it.
52
+ *
53
+ * present returns a frame when the pixels left the worker instead of reaching a
54
+ * canvas. That frame has exactly one owner from then on: the sink keeps no
55
+ * reference and never closes it.
56
+ */
57
+ export interface FrameSink {
58
+ /** The render backend behind this sink, for diagnostics; null when the sink
59
+ * renders nothing. */
60
+ readonly name: RendererName | null;
61
+ present(frame: ScrubFrame): VideoFrame | null;
62
+ dispose(): void;
63
+ }
64
+ /** Pixels to the engine's display canvas, through the resolved Renderer. */
65
+ export declare class RendererFrameSink implements FrameSink {
66
+ private readonly renderer;
67
+ constructor(renderer: Renderer);
68
+ get name(): RendererName;
69
+ present(frame: ScrubFrame): null;
70
+ dispose(): void;
71
+ }
72
+ /**
73
+ * Pixels out of the worker as a VideoFrame, for a host that owns the canvas.
74
+ * A sample hands over its own frame, so a live decode reaches the host without
75
+ * a detour through a canvas. A cache blit has only canvas pixels to give, and
76
+ * the wrap has to be told the media time, which canvas pixels do not carry.
77
+ */
78
+ export declare class TransferFrameSink implements FrameSink {
79
+ readonly name: null;
80
+ present(frame: ScrubFrame): VideoFrame;
81
+ dispose(): void;
82
+ }
83
+ export interface RendererOptions {
84
+ /** Pin the 2D renderer. Unset, WebGPU is preferred and used when available,
85
+ * falling back to 2D otherwise, so it is not a guarantee of WebGPU. */
86
+ prefer2d?: boolean;
87
+ }
88
+ /**
89
+ * Chooses the render backend for a canvas. WebGPU is the default and probed at
90
+ * runtime; an explicit prefer2d, or any failure to acquire a device, yields the
91
+ * 2D renderer instead, so a caller always gets a working renderer.
92
+ */
93
+ export declare function createRenderer(canvas: OffscreenCanvas, options?: RendererOptions): Promise<Renderer>;
94
+ //# sourceMappingURL=renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGjD;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,EAAE,oBAA6B,CAAC;AAEhE;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B;;;;;;OAMG;IACH,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,qBAAa,cAAe,YAAW,QAAQ;IAIjC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,QAAQ,CAAC,IAAI,EAAG,IAAI,CAAU;IAC9B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA2C;gBAElC,MAAM,EAAE,eAAe;IAQpD,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAc7B,OAAO,IAAI,IAAI;CAChB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,SAAS;IACxB;2BACuB;IACvB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IACnC,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,GAAG,IAAI,CAAC;IAC9C,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,4EAA4E;AAC5E,qBAAa,iBAAkB,YAAW,SAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,QAAQ;IAE/C,IAAI,IAAI,IAAI,YAAY,CAEvB;IAED,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAKhC,OAAO,IAAI,IAAI;CAGhB;AAED;;;;;GAKG;AACH,qBAAa,iBAAkB,YAAW,SAAS;IACjD,QAAQ,CAAC,IAAI,OAAQ;IAErB,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU;IAOtC,OAAO,IAAI,IAAI;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B;4EACwE;IACxE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,eAAe,EACvB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,QAAQ,CAAC,CASnB"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * A quarter turn, in degrees clockwise, that stored pixels still need before
3
+ * they face the way the container says they should. Every phone recording held
4
+ * in portrait carries one: the sensor stores landscape and the track's display
5
+ * matrix names the turn.
6
+ *
7
+ * The sign is mediabunny's, read straight off the track. ffprobe prints the
8
+ * opposite sign for the same file, so a clip ffprobe calls +90 is 270 here.
9
+ */
10
+ export type Rotation = 0 | 90 | 180 | 270;
11
+ /**
12
+ * Draws an image upright into a destination box, mirroring the transform
13
+ * mediabunny's own VideoSample.draw applies so a frame decoded by the runtime
14
+ * and a frame decoded by a mediabunny sink land the same pixels.
15
+ *
16
+ * dWidth and dHeight name the destination AFTER the turn, which is what the
17
+ * track's display size already is. So on a quarter turn the source is drawn at
18
+ * swapped extents inside the turned frame, and the scale below undoes the
19
+ * aspect that swap introduces.
20
+ */
21
+ export declare function drawRotated(context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D, image: CanvasImageSource, rotation: Rotation, dx: number, dy: number, dWidth: number, dHeight: number): void;
22
+ /**
23
+ * The 2x2 rotation, row-major, that turns a destination texture coordinate
24
+ * about (0.5, 0.5) into the source coordinate to sample. Each entry is
25
+ * [cos -sin; sin cos] evaluated at MINUS the rotation, written out because a
26
+ * quarter turn is exact and trig at these angles is not.
27
+ *
28
+ * The negation is the whole point: sampling turns opposite to the picture, so
29
+ * showing a frame turned clockwise by R means reading it counter-clockwise by
30
+ * R. The unit square is closed under quarter turns about its centre, so the
31
+ * whole source still maps onto the whole destination and the shader's existing
32
+ * stretch-to-fill absorbs the aspect change for free.
33
+ */
34
+ export declare function uvRotationMatrix(rotation: Rotation): readonly [number, number, number, number];
35
+ //# sourceMappingURL=rotation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rotation.d.ts","sourceRoot":"","sources":["../src/rotation.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,CAAC;AAE1C;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,wBAAwB,GAAG,iCAAiC,EACrE,KAAK,EAAE,iBAAiB,EACxB,QAAQ,EAAE,QAAQ,EAClB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,IAAI,CAYN;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,QAAQ,GACjB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAE3C"}