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,376 @@
1
+ import type { MediaClock } from "./clock";
2
+ import type { RendererName } from "./diagnostics";
3
+ import { type FrameQuality, type ScrubCursor, type ScrubFrame } from "./scrub-cursor";
4
+ import type { PresentationMode } from "./types";
5
+ export declare function setDiagnosticsEnabled(enabled: boolean): void;
6
+ /** Per-rAF realtime needles, collected only while diagnostics are enabled. ticks
7
+ * is every loop turn; paints is every frame drawn; lateFrames is a playing frame
8
+ * more than one interval behind the clock; stalls is a playing tick with no frame
9
+ * to paint; catchUpMs is how far the clock has run past the last painted frame.
10
+ * playQueueDepth is the decode-ahead buffer's current length: a live read, not a
11
+ * per-tick accumulator, so 0 while playing means the pipeline ran dry. */
12
+ export interface RealtimeStats {
13
+ readonly ticks: number;
14
+ readonly paints: number;
15
+ readonly lateFrames: number;
16
+ readonly stalls: number;
17
+ readonly catchUpMs: number;
18
+ readonly playQueueDepth: number;
19
+ readonly endedFired: boolean;
20
+ /** Decoded frames thrown away before reaching the canvas: ones that arrived
21
+ * for a position playback had left, buffered ones overtaken by the clock
22
+ * moving backwards, and the ones the present cadence declines once the rate
23
+ * asks for more frames a second than it. All three cost a full decode. The
24
+ * first two are decode bandwidth spent on nothing; the third is the cadence
25
+ * doing its job, and at a high rate it dominates the count. */
26
+ readonly droppedFrames: number;
27
+ /** Same fact accumulated over the source's lifetime for the pipeline
28
+ * ledger, so it can sit beside the other monotonic counters. */
29
+ readonly droppedFramesTotal: number;
30
+ }
31
+ /**
32
+ * Render loop. One rAF tick. Mode-aware:
33
+ *
34
+ * - Playing: the catch-up loop from the mediabunny media-player example.
35
+ * On each tick read clock.now(); if the stashed nextFrame's timestamp
36
+ * has arrived, paint it, then pull forward from the cursor in a
37
+ * while-loop. Late frames paint immediately; the first future-timestamped
38
+ * frame is stashed for the next tick. This matches Vanilagy's reference
39
+ * pattern and prevents visible skips when the decoder lags behind the clock.
40
+ *
41
+ * - Paused: the cursor's most recent emission is whatever the latest
42
+ * seek landed on. Tick paints it once, nulls nextFrame, and never
43
+ * touches the iterator. Subsequent user input that calls seekTo
44
+ * emits a fresh frame, the listener stashes it, and the next tick
45
+ * paints it.
46
+ *
47
+ * No backup setInterval. rAF is enough: tab backgrounding will pause the
48
+ * loop, but pause is the right behavior because nothing should advance
49
+ * media time while the surface is not visible.
50
+ *
51
+ * Runs worker-side. It renders frames through a Renderer (the 2D canvas path
52
+ * today, swappable for WebGPU behind the same seam); the cursor owns the frame
53
+ * cache and fills it as it decodes, so this loop only reads it through
54
+ * peekCached. The only way out is the onPaint callback, which EngineCore turns
55
+ * into serializable state emits. No DOM, no React, no main-thread reference
56
+ * ever reaches this loop.
57
+ */
58
+ export interface ScrubControllerDeps {
59
+ cursor: ScrubCursor;
60
+ clock: MediaClock;
61
+ /** catchUpMs is supplied only while diagnostics are enabled and playing, so
62
+ * the engine can fold it onto the broadcast frame event; undefined otherwise.
63
+ * presented carries the pixels when the sink handed them out instead of
64
+ * painting them, and transfers ownership of that frame with the call. */
65
+ onPaint: (frame: ScrubFrame, catchUpMs?: number, presented?: VideoFrame | null) => void;
66
+ /** Fired when playback runs past the source duration so the engine can
67
+ * transition to Ended status. Without this the iterator yields done
68
+ * forever and the play UI stays stuck on Playing while the canvas freezes. */
69
+ onEnded: () => void;
70
+ /** Cache lookups whose resolved entry is closer than this to whatever
71
+ * the visible canvas already shows are rejected. Forces a fresh decode
72
+ * on small movements (frame-step gestures) so the user sees the actual
73
+ * next/prev frame, not the cached neighbor. */
74
+ cacheSkipNearMs: number;
75
+ /** Pin the 2D renderer; unset prefers WebGPU, falling back to 2D when unavailable. */
76
+ prefer2d?: boolean;
77
+ /** Defaults to "canvas". Under "frames" the loop binds no canvas and every
78
+ * paint yields its pixels to onPaint instead. */
79
+ presentation?: PresentationMode;
80
+ }
81
+ export declare class ScrubController {
82
+ private readonly deps;
83
+ private rafHandle;
84
+ /** Paused/seek path: the single most-recent landed frame. */
85
+ private nextFrame;
86
+ /** Playing path: a bounded decode-ahead buffer so a decode that overruns a
87
+ * frame interval does not starve the next tick. Drained one frame per tick,
88
+ * refilled toward the read-ahead depth. */
89
+ private playQueue;
90
+ private sink;
91
+ /** The canvas the latest bind targeted; guards the async renderer race. */
92
+ private boundCanvas;
93
+ private disposed;
94
+ private unsub;
95
+ /** Milliseconds-rounded timestamp of whatever the visible canvas
96
+ * currently shows. Updated on every paint (cursor emit OR cache hit).
97
+ * Drives the skip-near-current check in tryPaintFromCache. */
98
+ private lastPaintedMs;
99
+ /** Quality of what the canvas shows, so a repaint can be judged on sharpness
100
+ * as well as position. */
101
+ private lastPaintedQuality;
102
+ /** Set true when runTick detects clock past duration so we only emit
103
+ * the onEnded transition once per playback session. */
104
+ private endedFired;
105
+ private ticks;
106
+ private paints;
107
+ private lateFrames;
108
+ private stalls;
109
+ private catchUpMs;
110
+ private droppedFrames;
111
+ /** Lifetime companion to droppedFrames for the pipeline ledger: never reset
112
+ * by a play session and not gated on diagnostics, so the ledger is honest
113
+ * even about what happened before the HUD opened. */
114
+ private droppedFramesTotal;
115
+ /** False from every attach of the play walk until its first frame paints.
116
+ * The bootstrap pull is async, so the opening ticks find nextFrame null
117
+ * and would each book a stall the user never saw. */
118
+ private paintedSincePlay;
119
+ /** Whether a play session the user started is still running. A seek while
120
+ * playing re-attaches the walk through endPlay and beginPlay without ever
121
+ * stopping the transport, and a drag stops the transport for the length of
122
+ * the gesture and walks the playhead across the source under it. Neither is
123
+ * the user putting the picture down, and the per-session needles count the
124
+ * session the user is watching, not the walk. */
125
+ private playSessionLive;
126
+ /** Clock reading the transport stopped at, or null while it runs. A stopped
127
+ * clock moves only by being seeked, so a stopped tick reading anything else
128
+ * is a seek, which is why the comparison against it is exact. */
129
+ private stoppedAtS;
130
+ /** Media time the current play session was attached at, which is what makes
131
+ * a frame produced for a position the session has left recognisable. */
132
+ private playAnchorS;
133
+ /** Media time the previous playing tick read, so a tick can price its own
134
+ * span in source frames. Null until the session's second tick. */
135
+ private lastTickS;
136
+ /** Clock reading at the play walk's last delivery, or null when no walk is
137
+ * attached. Set at the attach too, so the walk's opening frame is priced
138
+ * against the wait for it. */
139
+ private lastDeliveryS;
140
+ /** Source frames this tick may pull past the one it paints, refreshed per
141
+ * tick from the span the clock covered. Sourced from ticks so a loop that
142
+ * stops (a hidden tab parks rAF) takes the pull chain down with it. */
143
+ private catchUpBudget;
144
+ /** Clock reading at the last paint this play session put on screen, which is
145
+ * what the wall-time gap between presents is measured from. Null until the
146
+ * session's first paint, so an opening frame is never held for cadence. */
147
+ private lastPresentTickS;
148
+ /** The share of the rate's demand the pump allows itself to present. Held as
149
+ * a share rather than a frames-a-second figure so it survives a rate change
150
+ * as the same statement about the machine: a pipeline that was keeping up
151
+ * at 1x opens 4x at everything 4x asks for, with no ramp to climb. */
152
+ private presentShare;
153
+ /** Frames the running play walk has delivered into the queue, and the two
154
+ * readings the cadence loop last took: the clock, and that same count.
155
+ * Between them a tick knows what it asked the pipeline for and what it got. */
156
+ private walkDelivered;
157
+ private cadenceTickS;
158
+ private cadenceDeliveredAt;
159
+ /** Frames the pipeline owes the playhead since the cadence last moved: what
160
+ * the clock has asked for, less what the walk delivered. Zeroed on every
161
+ * move, so it holds the evidence for the next one rather than the ground
162
+ * lost over the session. */
163
+ private cadenceBacklog;
164
+ /** Wall seconds the walk has held a frame the clock has not run past, without
165
+ * a break, which is the only evidence a pipeline can offer that it has room
166
+ * to spare. */
167
+ private cadenceCushionS;
168
+ constructor(deps: ScrubControllerDeps);
169
+ /**
170
+ * Routes an arriving frame. While playing it appends to the decode-ahead
171
+ * queue and chains another pull until the read-ahead depth is reached (the
172
+ * cursor's one-in-flight latch makes the extra pulls free no-ops). While
173
+ * paused it replaces the single stashed frame, closing the superseded one
174
+ * when it is an unpainted sample so a fast drag does not leak VideoSamples.
175
+ */
176
+ private stash;
177
+ /**
178
+ * Decoded frames to keep queued ahead of the playhead. The decode path
179
+ * decides it, not the shape of the frame: reading it off the frame treated
180
+ * every sample-carrying path as pool-bound, which the long-lived decode
181
+ * session is not, so the default path ran with a queue of one and no cushion
182
+ * at all. A cushion is the whole point, it is what stops a decode that
183
+ * overruns one frame interval from starving the next paint.
184
+ */
185
+ private readAhead;
186
+ /**
187
+ * Whether a frame arriving while the clock runs belongs to the running play
188
+ * session. The controller receives every frame the cursor emits, not only
189
+ * the ones its own pulls asked for, so a seek still landing when playback
190
+ * resumes delivers a frame for a position the session has already left.
191
+ * Queued, that frame sits at the head never due, which blocks the paint and
192
+ * the refill alike, and playback resumes only once the clock has run all the
193
+ * way to it: exactly as long as the jump the user just made.
194
+ */
195
+ private belongsToPlaySession;
196
+ /**
197
+ * Whether a queued frame is further ahead of the clock than playback can
198
+ * legitimately buffer. Play frames come from an iterator anchored at the
199
+ * playhead, so the buffer leads the clock by its own depth and no more. A
200
+ * frame past that either arrived for a position the session has left, or was
201
+ * overtaken when the clock moved backwards under the queue, which a step or
202
+ * a seek during playback both do.
203
+ */
204
+ private beyondPlayHorizon;
205
+ /**
206
+ * Discards every queued frame the clock has already run past except the last
207
+ * one, which is the frame that belongs on screen now.
208
+ *
209
+ * A tick can only present one frame, so whenever more than one falls due in
210
+ * the same tick the surplus has nowhere to go. Serving them one a tick
211
+ * instead makes the picture drift further behind the playhead every tick,
212
+ * which is what a rate past display-refresh over source-fps produces on a
213
+ * pipeline that is otherwise keeping up perfectly. Skipping keeps the picture
214
+ * on the playhead and charges the difference to the dropped-frame ledger,
215
+ * where a consumer can see what the rate cost.
216
+ */
217
+ private dropFramesTheClockHasPassed;
218
+ /**
219
+ * Source frames this tick may pull past the one it paints, measured as the
220
+ * span the clock covered. One of them covers that span, which is what a rate
221
+ * demanding more than a frame per tick needs and cannot get from a queue
222
+ * bounded by read-ahead depth; the rest work off a backlog, so a pipeline a
223
+ * slow stretch knocked behind can return to the playhead.
224
+ */
225
+ private catchUpAllowance;
226
+ /**
227
+ * Presents a wall second the pump allows itself right now: the rate's demand
228
+ * cut to the share the machine has been paying for, and never under the
229
+ * source's own frame rate. Rate 1 asks for exactly the source rate, so its
230
+ * floor and its demand are the same figure and no share can come between
231
+ * them, which is what leaves 1x painting every frame of every source.
232
+ */
233
+ private presentCadence;
234
+ /** Forgets what the cadence loop had gathered. The walk is about to be
235
+ * attached somewhere else, and a span across that move charges the pipeline
236
+ * for frames it was never asked to have ready. */
237
+ private resetCadenceTracking;
238
+ /**
239
+ * Prices this tick against the pipeline and moves the share one step once
240
+ * either reading has gathered the evidence a step takes.
241
+ *
242
+ * What takes the share down is a running bill, in frames, between what the
243
+ * clock passed and what the play walk delivered over the same span.
244
+ * Accumulating rather than thresholding each tick is what tells a shortfall
245
+ * from noise: counting whole frames against a fractional demand leaves every
246
+ * tick out by up to one either way and those cancel, while a machine that
247
+ * cannot sustain the rate falls short every tick and adds up. A machine that
248
+ * can sustain it has no way to run the bill up, since the queue only takes a
249
+ * frame as the clock passes one and catch-up pulls repay any span the walk
250
+ * came up short on, which bounds the bill by the depth being held.
251
+ *
252
+ * What puts the share back is the walk holding a frame the clock has not run
253
+ * past, unbroken for the wall time the source takes to produce that many.
254
+ * Nothing else would do, since a machine at equilibrium delivers exactly what
255
+ * the clock asks for however much headroom it has, so a surplus never appears
256
+ * in the bill to be read.
257
+ *
258
+ * Neither reading is the depth of the decode-ahead queue, which belongs to
259
+ * the decode path and not to the machine: on the zero-copy path, which
260
+ * buffers one frame, a single frame in hand is full depth and one tick from
261
+ * empty alike.
262
+ *
263
+ * Nothing either reading is made of knows what the panel refreshes at, so one
264
+ * machine lands on one cadence on any panel; a present the share declines
265
+ * hands its time back to decode, so the loop this closes is a negative one;
266
+ * and zeroing both on each step makes the next one gather its own evidence,
267
+ * which is what a share sitting at the machine's limit needs to stop it
268
+ * pulsing.
269
+ */
270
+ private observePresentCadence;
271
+ /**
272
+ * Whether the frame that is due arrives too soon after the last painted one
273
+ * to earn the screen. Wall time, read as the media span over the clock's
274
+ * slope, so the same gap decides at every rate. The pump paints at most one
275
+ * frame per display tick, so it can only decline one on a panel whose ticks
276
+ * fall closer together than the interval it compares against.
277
+ *
278
+ * A cadence sitting at its ceiling never reaches the wall-time test, so a
279
+ * machine keeping up declines nothing at any rate, and the ceiling equals the
280
+ * demand at rate 1, which paints every frame of every source. A clock that
281
+ * moved backwards under the pump reads as a non-positive span and paints,
282
+ * which is what stops a step or a seek during playback from holding the
283
+ * picture for the length of the jump it made.
284
+ */
285
+ private skipsForPresentCadence;
286
+ /**
287
+ * Re-anchors the playback walk when the clock ran further past the previous
288
+ * tick than a loop that was actually running could have let it, and reports
289
+ * whether it did.
290
+ *
291
+ * A hidden tab parks rAF while the clock keeps wall time, so the tick that
292
+ * resumes finds a backlog as deep as the whole absence. Walked, it costs one
293
+ * decode per frame nobody was there to see, and the picture replays the
294
+ * absence at decode rate on its way to the playhead: 30 seconds hidden
295
+ * measured 4961ms of 8x fast-forward. Anchoring at the playhead lands the
296
+ * frame that walk was travelling toward for one keyframe seek, flat in how
297
+ * far the clock went.
298
+ *
299
+ * Dividing the span by the clock's slope is what makes the reading wall time,
300
+ * so a high rate legitimately moving the clock several frames per tick is not
301
+ * read as a loop nobody was driving.
302
+ */
303
+ private reanchorParkedWalk;
304
+ /**
305
+ * Puts the clock back onto the frame a starved walk has just delivered.
306
+ *
307
+ * A seek onto unbuffered ground leaves the render loop ticking with nothing
308
+ * to paint, so no tick gap ever opens and reanchorParkedWalk never sees it;
309
+ * what stopped is the walk. The clock runs through the whole wait, so the
310
+ * frame the viewer asked for arrives that far behind it, and a walk left to
311
+ * catch up spends the wait replaying it at decode speed: the position they
312
+ * asked to see, flashed past on the way to one they did not.
313
+ */
314
+ private reanchorStarvedWalk;
315
+ /**
316
+ * Whether the newest decoded frame is already older than the clock, which
317
+ * makes the queue a backlog and the next pull catch-up. Read-ahead depth
318
+ * cannot bound catch-up as well: a path that holds one frame consumes one
319
+ * source frame per tick, which pins the picture to tick rate over source fps
320
+ * whatever rate was commanded.
321
+ */
322
+ private trailsTheClock;
323
+ /** Drops every queued play frame, closing any that are unpainted samples. */
324
+ private clearPlayQueue;
325
+ bindCanvas(el: OffscreenCanvas | null): void;
326
+ /** The active render backend, for diagnostics; null until it resolves. */
327
+ rendererName(): RendererName | null;
328
+ private attachRenderer;
329
+ dispose(): void;
330
+ /** Drops the stashed frame, closing it if it is an unpainted sample. */
331
+ private clearStash;
332
+ /**
333
+ * Millisecond timestamp of whatever the visible canvas currently shows.
334
+ * Engine.step uses this as the base for "next frame after current" so
335
+ * step lands on the actual neighbor frame, not on a 1/fps arithmetic
336
+ * guess from store.timeMs (which holds user intent during scrub).
337
+ */
338
+ getLastPaintedMs(): number | null;
339
+ getLastPaintedQuality(): FrameQuality;
340
+ /**
341
+ * Called by the engine on play(), and again by a seek that re-anchors a walk
342
+ * already running. Attaches the cursor's forward iterator at the current
343
+ * media time and kicks the bootstrap pull. Also clears the EOF latch so a
344
+ * play-restart from past-end can fire onEnded again the next time the clock
345
+ * crosses the duration.
346
+ */
347
+ beginPlay(startS: number): void;
348
+ /** Called by the engine on pause(), and by a seek re-anchoring a running
349
+ * walk. Detaches the iterator and drops the read-ahead so paused ticks
350
+ * never paint a stale play frame. */
351
+ endPlay(): void;
352
+ /**
353
+ * Cache lookup helper used by the engine on scrub. Asks the cursor for a
354
+ * cached frame near the target and, if it is far enough from what the canvas
355
+ * already shows, paints it and returns true. Either way the engine still
356
+ * calls cursor.seekTo to land the full-res frame; the cursor's emit listener
357
+ * stashes it for the next tick.
358
+ *
359
+ * The skip-near-current check rejects hits whose timestamp falls within
360
+ * cacheSkipNearMs of the currently-displayed frame. This is the knob
361
+ * consumers tune to control single-frame-step UX: a higher value forces a
362
+ * fresh decode on tighter movements, a value of 0 always serves the cache.
363
+ */
364
+ tryPaintFromCache(timestampMs: number): boolean;
365
+ private start;
366
+ private runTick;
367
+ private paint;
368
+ /** Frame interval in seconds; the source rate when known, else a 30fps
369
+ * fallback. Used to decide whether a playing frame painted late. */
370
+ private frameIntervalS;
371
+ /** Realtime needles for the diagnostics snapshot. Plain reads; the worker
372
+ * broadcaster calls this synchronously. */
373
+ getRealtimeStats(): RealtimeStats;
374
+ private stop;
375
+ }
376
+ //# sourceMappingURL=scrub-controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scrub-controller.d.ts","sourceRoot":"","sources":["../src/scrub-controller.ts"],"names":[],"mappings":"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"}