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,276 @@
1
+ import { type Rotation } from "./rotation";
2
+ import type { VideoSampleLike } from "./scrub-cursor";
3
+ /**
4
+ * One packet as the session submits it. Mirrors the fields of mediabunny's
5
+ * EncodedPacket the decoder needs, so the session never imports mediabunny.
6
+ */
7
+ export interface EncodedPacketLike {
8
+ readonly data: Uint8Array;
9
+ readonly type: "key" | "delta";
10
+ readonly timestamp: number;
11
+ readonly duration: number;
12
+ }
13
+ export interface PacketRetrievalOptionsLike {
14
+ readonly metadataOnly?: boolean;
15
+ readonly verifyKeyPackets?: boolean;
16
+ }
17
+ /** The slice of mediabunny's EncodedPacketSink the session decodes through. */
18
+ export interface PacketSource {
19
+ getKeyPacket(timestamp: number, options?: PacketRetrievalOptionsLike): Promise<EncodedPacketLike | null>;
20
+ getNextKeyPacket(packet: EncodedPacketLike, options?: PacketRetrievalOptionsLike): Promise<EncodedPacketLike | null>;
21
+ packets(startPacket?: EncodedPacketLike, endPacket?: EncodedPacketLike, options?: PacketRetrievalOptionsLike): AsyncGenerator<EncodedPacketLike, void, unknown>;
22
+ }
23
+ /** The slice of WebCodecs' VideoDecoder the session drives. Chunks cross as
24
+ * inits so the session never reaches for a platform constructor. */
25
+ export interface VideoDecoderLike {
26
+ configure(config: VideoDecoderConfig): void;
27
+ decode(chunk: EncodedVideoChunkInit): void;
28
+ flush(): Promise<void>;
29
+ reset(): void;
30
+ close(): void;
31
+ }
32
+ export interface DecodeSessionOptions {
33
+ readonly packets: PacketSource;
34
+ readonly config: VideoDecoderConfig;
35
+ readonly createDecoder: (init: VideoDecoderInit) => VideoDecoderLike;
36
+ /**
37
+ * The track's quarter turn, which the session's frames carry and its draw
38
+ * applies. A raw decoded picture holds the stored pixels and nothing about
39
+ * the display matrix, so this is the only route the turn has here, and a
40
+ * caller that forgets it paints every portrait recording sideways.
41
+ */
42
+ readonly rotation: Rotation;
43
+ /**
44
+ * Ceiling on waiting for one decoder output while chunks are in flight;
45
+ * defaults to OUTPUT_TIMEOUT_MS. Overridable so a test can drive the
46
+ * silent-decoder path without waiting out the production ceiling.
47
+ */
48
+ readonly outputTimeoutMs?: number;
49
+ }
50
+ /**
51
+ * Whether the session can drive a track with this decoder config. The gate that
52
+ * routes a source here and the constructor that refuses everything else read the
53
+ * same predicate.
54
+ */
55
+ export declare function sessionDrivable(config: VideoDecoderConfig): boolean;
56
+ /**
57
+ * The three retrievals the session answers, mirror for mirror with the sink
58
+ * slices the other decode paths ride. Held as an interface so the provider that
59
+ * wraps it stays fake-injectable under test.
60
+ */
61
+ export interface SessionFrameSource {
62
+ frameAt(targetS: number): Promise<VideoSampleLike | null>;
63
+ framesFrom(startS: number): AsyncGenerator<VideoSampleLike, void, unknown>;
64
+ framesCovering(startS: number, endS: number): AsyncGenerator<VideoSampleLike, void, unknown>;
65
+ /** Earliest position still reachable without re-anchoring, or -Infinity when
66
+ * the session has not been positioned yet. A decoder only moves forward, so
67
+ * asking for anything below this costs a walk from the enclosing keyframe. */
68
+ readonly reachableFromS: number;
69
+ /** Every frame the decoder has output since open, discarded pre-roll
70
+ * included; monotonic. */
71
+ readonly framesDecoded: number;
72
+ }
73
+ /**
74
+ * One long-lived VideoDecoder, held across seeks.
75
+ *
76
+ * A decoder can only ever move forward, and every flush re-arms its demand for a
77
+ * key frame, so a runtime that flushes per retrieval pays a walk back to the
78
+ * nearest true IDR on every seek. This session flushes only at end of stream:
79
+ * a seek at-or-ahead of the read head, inside the current anchor span, decodes
80
+ * only the packets between the two, and a backward jump or a jump past the span
81
+ * re-anchors. Positioning is the only thing that costs a walk.
82
+ *
83
+ * One decoder serving several readers is the whole point, and it is also the
84
+ * hazard: a scrub's frameAt and playback's framesFrom drive the same decoder,
85
+ * the same packet iterator, and the same queue of decoded frames. So every
86
+ * retrieval takes the decoder exclusively for the length of one frame, and a
87
+ * reader displaced by someone else's re-anchor is told, rather than left to read
88
+ * the emptied queue as end of stream and stop for good.
89
+ *
90
+ * Frames are handed out as VideoSampleLike and their close is the caller's, the
91
+ * same obligation the zero-copy sample path carries.
92
+ */
93
+ export declare class DecodeSession implements SessionFrameSource {
94
+ private readonly options;
95
+ private readonly keyPacket;
96
+ private readonly prefixWidth;
97
+ private decoder;
98
+ private iterator;
99
+ private peeked;
100
+ /** Timestamp of the key packet after the anchor: the end of the span a
101
+ * forward seek can reach without re-anchoring. */
102
+ private spanEndS;
103
+ private exhausted;
104
+ /** Timings the decoder still owes pictures for, in presentation order. */
105
+ private readonly pending;
106
+ private readonly decoded;
107
+ private wake;
108
+ /**
109
+ * Latched once the decoder is judged unable to decode this source at all.
110
+ * Every later retrieval refuses with it instead of re-anchoring onto the
111
+ * same failure, which is what turns a silent forever-retry into one honest
112
+ * error the caller can show.
113
+ */
114
+ private stalledError;
115
+ /**
116
+ * The current entry point's failure, held only until the walk that is owed a
117
+ * picture decides what it means. It condemns the anchor, never the session:
118
+ * a source whose sync table names one bad entry point still decodes from
119
+ * every other one, and latching the first failure is what turned a seek into
120
+ * a poisoned GOP into a player that never painted again.
121
+ */
122
+ private anchorError;
123
+ /** The entry currently feeding the decoder, or null before the first one. */
124
+ private entry;
125
+ /** Entry points a decoder error has ruled out, by whole-microsecond
126
+ * timestamp. Only ever grows: a bitstream does not change. */
127
+ private readonly rejectedAnchors;
128
+ /** Where the live retrieval wants to be, so a re-anchor after a failed entry
129
+ * aims at the position the caller asked for rather than the anchor's. */
130
+ private entryTargetS;
131
+ /** The last picture handed out since the caller last chose a position, so a
132
+ * re-anchor mid-walk resumes rather than replays. */
133
+ private servedS;
134
+ private closed;
135
+ private anchors;
136
+ private framesDecodedCount;
137
+ /** Where the decoder sits, kept in step with what it hands out. Read
138
+ * synchronously by callers deciding what to ask for, so it cannot await. */
139
+ private reachable;
140
+ /** Serializes retrievals; see the class note on shared-decoder exclusivity. */
141
+ private tail;
142
+ /** Bumped by every re-anchor, so a reader can tell whether the decoder is
143
+ * still where it left it or has been moved under it by another reader. */
144
+ private epoch;
145
+ private readonly outputTimeoutMs;
146
+ private readonly rotation;
147
+ constructor(options: DecodeSessionOptions);
148
+ /** Times the session has configured the decoder onto an anchor. */
149
+ get anchorCount(): number;
150
+ /** Every frame the decoder has ever output, including walk pre-roll that is
151
+ * discarded before the target: the honest denominator for what a paint
152
+ * actually cost. Monotonic for the session's lifetime. */
153
+ get framesDecoded(): number;
154
+ /** See SessionFrameSource. The oldest frame decoded but not yet handed out
155
+ * when there is one, since those are still servable, else the last position
156
+ * handed out. */
157
+ get reachableFromS(): number;
158
+ /** The frame at or before `targetS`, or null when nothing precedes it. */
159
+ frameAt(targetS: number): Promise<VideoSampleLike | null>;
160
+ /**
161
+ * Frames from `startS` onward, beginning at the frame at or before it. The
162
+ * walk from the anchor up to `startS` is decoded but not yielded, since the
163
+ * caller asked to start there.
164
+ *
165
+ * Playback rides this for the length of a session, so it outlives any number
166
+ * of scrubs. When one of those moved the decoder, the walk resumes from the
167
+ * last frame it handed out rather than ending.
168
+ */
169
+ framesFrom(startS: number): AsyncGenerator<VideoSampleLike, void, unknown>;
170
+ /**
171
+ * Every frame decoded while covering `[startS, endS]`, including the walk
172
+ * from the anchor. Those prefix frames cost the same decode either way, so
173
+ * yielding them hands the caller a span of frames for the price of the one
174
+ * it asked for.
175
+ *
176
+ * This serves speculative sweeps, so a re-anchor by anyone else ends it:
177
+ * chasing the span back would spend a foreground decode's worth of decoder
178
+ * time on frames nobody is waiting for.
179
+ */
180
+ framesCovering(startS: number, endS: number): AsyncGenerator<VideoSampleLike, void, unknown>;
181
+ /**
182
+ * Runs `op` with the decoder to itself. Retrievals interleave at frame
183
+ * granularity, which bounds how long a foreground seek waits behind a
184
+ * background sweep at one frame, while keeping any one walk's view of the
185
+ * packet iterator, the in-flight count, and the decoded queue consistent.
186
+ */
187
+ private exclusive;
188
+ /**
189
+ * The first frame after `afterS` once another reader has moved the decoder.
190
+ * Re-positions and discards the frames already handed out, so a walk picks
191
+ * up exactly where it left off however far away the decoder was taken.
192
+ */
193
+ private resumeAfter;
194
+ close(): void;
195
+ /** Decodes through `targetS` and returns the last frame at or before it,
196
+ * closing the frames walked past. */
197
+ private land;
198
+ private positionFor;
199
+ /** The earliest position still reachable without re-anchoring: the oldest
200
+ * frame decoded but not yet handed out, or the next packet in line when
201
+ * there is none. Decode runs ahead of the read, so the packet alone would
202
+ * put the head past frames the session can still serve. */
203
+ private readHeadS;
204
+ private anchorAt;
205
+ /**
206
+ * The packet to open a decode of `targetS` from: the container's own sync
207
+ * sample, unless a decoder has already proved that one is not a legal entry
208
+ * point, in which case the last verified IDR at or before the target.
209
+ *
210
+ * A sync sample that is itself an IDR is already the furthest-back entry
211
+ * worth reaching for, so a failure there is a failure of the source.
212
+ */
213
+ private resolveEntry;
214
+ /**
215
+ * Where the span a forward seek can reach without re-anchoring ends: the
216
+ * first sync sample past the target that is still worth anchoring at.
217
+ *
218
+ * Skipping the rejected ones is what keeps the pre-roll paid for once. Ending
219
+ * the span at an entry point already known not to decode would send the very
220
+ * next seek into that GOP back to the same rejected anchor and back through
221
+ * the same walk to recover from it.
222
+ */
223
+ private spanEndAfter;
224
+ /** Drops the work in flight and the frames it produced, in one turn, so no
225
+ * output from the old anchor can land against the new one. */
226
+ private quiesce;
227
+ private configureDecoder;
228
+ /** One frame at or before `boundS`, or null once the bound is passed. A frame
229
+ * decoded past the bound stays queued for the next read rather than being
230
+ * handed out or thrown away. */
231
+ private pull;
232
+ /**
233
+ * Re-opens the decode from the last entry point ahead of the failed one,
234
+ * which for an open GOP means the previous IDR plus a walk to the target.
235
+ *
236
+ * The failed anchor is struck off for the life of the session, so the cost is
237
+ * paid once per bad entry point rather than once per seek into it. When there
238
+ * is nothing further back to enter from, the failure is the source's and it
239
+ * latches here.
240
+ */
241
+ private enterFurtherBack;
242
+ /**
243
+ * Keeps the decoder's pipeline fed, regardless of which frame is being read.
244
+ * A decoder emits nothing until it holds enough pictures, so submitting only
245
+ * as far as the requested frame leaves the session waiting on output it is
246
+ * refusing to make possible. Feeding stops once the frames already decoded
247
+ * pile up, which is what bounds the memory the session holds.
248
+ */
249
+ private fill;
250
+ private peek;
251
+ private drain;
252
+ private awaitOutput;
253
+ /**
254
+ * Files a submitted chunk's timing in presentation order, which is the order
255
+ * pictures come back in and is not the order chunks go in on a B-frame
256
+ * source.
257
+ */
258
+ private awaitTiming;
259
+ /**
260
+ * A decoder that echoes the timestamp it was handed names its own pending
261
+ * entry, which survives an output being dropped. One that counts from an
262
+ * origin of its own names nothing, and position is all that is left. Taking
263
+ * position alone would let a single dropped output shift every picture after
264
+ * it onto the wrong detections, permanently and without a symptom.
265
+ */
266
+ private claimTiming;
267
+ private receive;
268
+ private fail;
269
+ /** Latches the terminal failure and returns it. First writer wins, so the
270
+ * cause a caller is handed is the one that started the failure rather than
271
+ * whichever consequence surfaced last. */
272
+ private stall;
273
+ private latch;
274
+ private discardDecoded;
275
+ }
276
+ //# sourceMappingURL=decode-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode-session.d.ts","sourceRoot":"","sources":["../src/decode-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,250 @@
1
+ import { BlobSource, ReadableStreamSource, UrlSource } from "mediabunny";
2
+ import type { CreateScrubCursorOptions } from "./create-scrub-cursor";
3
+ import { type SessionFrameSource } from "./decode-session";
4
+ import type { SourceResidency } from "./source-residency";
5
+ import type { KeyframeProbe } from "./keyframe-index";
6
+ import { type ScrubTrackInfo, type VideoSampleLike } from "./scrub-cursor";
7
+ import { type DecodePath, type UrlSourceReadConfig, type UrlVideoSource, type VideoSource } from "./types";
8
+ /**
9
+ * A decoded frame handle: the slice of mediabunny's WrappedCanvas the runtime
10
+ * paints, caches, and extracts. Only the canvas and its presentation timestamp
11
+ * matter.
12
+ */
13
+ export interface WrappedCanvasLike {
14
+ readonly canvas: OffscreenCanvas | HTMLCanvasElement;
15
+ readonly timestamp: number;
16
+ }
17
+ /**
18
+ * The slice of mediabunny's CanvasSink the runtime decodes through. getCanvas
19
+ * does the random-access keyframe walk and GOP decode internally; canvases
20
+ * streams forward for playback and stepping; canvasesAtTimestamps decodes a set
21
+ * of sorted timestamps in one pass (the prefetch window and frame extraction).
22
+ */
23
+ export interface CanvasFrameSource {
24
+ getCanvas(timestampS: number): Promise<WrappedCanvasLike | null>;
25
+ canvases(startS: number): AsyncGenerator<WrappedCanvasLike, void, unknown>;
26
+ canvasesAtTimestamps(timestamps: Iterable<number>): AsyncGenerator<WrappedCanvasLike | null, void, unknown>;
27
+ }
28
+ /**
29
+ * The opened decode primitives for one source: resolved track facts plus the
30
+ * two sinks the runtime rides. Built once by openDecodeSource, so a consumer
31
+ * never imports mediabunny and stays fake-injectable under test. This seam is
32
+ * shared by the playback cursors and the playback-independent AnalysisSession,
33
+ * so it lives here next to its producer rather than inside any one consumer.
34
+ */
35
+ export interface DecodeSourceHandle {
36
+ readonly track: ScrubTrackInfo;
37
+ readonly sink: CanvasFrameSource;
38
+ readonly keyframeProbe: KeyframeProbe;
39
+ dispose(): Promise<void>;
40
+ }
41
+ /**
42
+ * The slice of mediabunny's VideoSampleSink the runtime decodes through, mirror
43
+ * for mirror with CanvasFrameSource but yielding live VideoSamples the zero-copy
44
+ * WebGPU path imports directly. The sink yields raw samples; the cursor wraps
45
+ * each in idempotentSample before emitting so the close obligation is safe to
46
+ * discharge from every path.
47
+ */
48
+ export interface SampleFrameSource {
49
+ getSample(timestampS: number): Promise<VideoSampleLike | null>;
50
+ samples(startS: number): AsyncGenerator<VideoSampleLike, void, unknown>;
51
+ samplesAtTimestamps(timestamps: Iterable<number>): AsyncGenerator<VideoSampleLike | null, void, unknown>;
52
+ }
53
+ /**
54
+ * The opened decode primitives for the zero-copy sample path: the same resolved
55
+ * track facts and keyframe probe as DecodeSourceHandle, with the VideoSampleSink
56
+ * standing in for the CanvasSink. Built only where zeroCopyViable approves the
57
+ * path, so the rest of the runtime never reaches it by accident.
58
+ */
59
+ export interface SampleSourceHandle {
60
+ readonly track: ScrubTrackInfo;
61
+ readonly sampleSink: SampleFrameSource;
62
+ readonly keyframeProbe: KeyframeProbe;
63
+ dispose(): Promise<void>;
64
+ }
65
+ /**
66
+ * The opened decode primitives for the long-lived-decoder path: the same
67
+ * resolved track facts and keyframe probe as the sink handles, with a
68
+ * DecodeSession standing in for the sink. Built only where decodeSessionViable
69
+ * approves the path.
70
+ */
71
+ export interface SessionSourceHandle {
72
+ readonly track: ScrubTrackInfo;
73
+ readonly session: SessionFrameSource;
74
+ readonly keyframeProbe: KeyframeProbe;
75
+ dispose(): Promise<void>;
76
+ }
77
+ /**
78
+ * One decoded frame, tagged by which sink produced it. A canvas frame from the
79
+ * CanvasSink path; a sample frame from the VideoSampleSink path, carrying a live
80
+ * VideoSample the cursor owns the close of. The cursor turns each into the
81
+ * matching ScrubFrame kind, so the canvas-vs-sample branch lives in one place
82
+ * rather than forking every cursor method.
83
+ */
84
+ export type DecodedFrame = {
85
+ readonly kind: "canvas";
86
+ readonly canvas: OffscreenCanvas | HTMLCanvasElement;
87
+ readonly timestamp: number;
88
+ } | {
89
+ readonly kind: "sample";
90
+ readonly sample: VideoSampleLike;
91
+ readonly timestamp: number;
92
+ };
93
+ /**
94
+ * The decode seam both cursors ride, normalized over the two sink kinds: a
95
+ * random-access read, a forward stream, and a sorted-timestamp batch, each
96
+ * yielding a DecodedFrame. The provider also names the path it was built over,
97
+ * which the scheduler reports so a human can see which machinery is decoding.
98
+ */
99
+ export interface FrameProvider {
100
+ readonly decodePath: DecodePath;
101
+ readonly track: ScrubTrackInfo;
102
+ readonly keyframeProbe: KeyframeProbe;
103
+ getFrame(timestampS: number): Promise<DecodedFrame | null>;
104
+ frames(startS: number): AsyncGenerator<DecodedFrame, void, unknown>;
105
+ framesAt(timestamps: Iterable<number>): AsyncGenerator<DecodedFrame | null, void, unknown>;
106
+ /**
107
+ * Whether reaching `timestampS` would restart this provider from a keyframe
108
+ * and decode everything in between. Only the long-lived decode session ever
109
+ * answers true: the sink paths re-position per retrieval, so nothing they
110
+ * are asked for is dearer than anything else.
111
+ */
112
+ wouldReanchor(timestampS: number): boolean;
113
+ /**
114
+ * Decoded frames a consumer may hold ahead of the playhead. Only the
115
+ * zero-copy sample sink is constrained here: each of its frames pins a slot
116
+ * in a fixed pool, so a deep queue starves the decoder that fills it. The
117
+ * other paths hand out frames they own, and a cushion is what stops a decode
118
+ * that overruns one frame interval from starving the next paint.
119
+ */
120
+ readonly playReadAhead: number;
121
+ /**
122
+ * Frames the decode machinery has produced since open, monotonic. On the
123
+ * session path this counts every decoder output including discarded walk
124
+ * pre-roll; the sink paths can only count what mediabunny yields, so their
125
+ * figure is a floor, not the decoder's true output.
126
+ */
127
+ framesDecoded(): number;
128
+ dispose(): Promise<void>;
129
+ }
130
+ /**
131
+ * The forward-sample seam a batch range walk reads: the track's own timing
132
+ * origin and one stream of its frames in presentation order. Both sample-
133
+ * yielding paths present this shape, so the walk never branches on which decoder
134
+ * it got, and every sample it hands over carries a close obligation.
135
+ */
136
+ export interface WalkFrameSource {
137
+ readonly track: ScrubTrackInfo;
138
+ framesFrom(startS: number): AsyncGenerator<VideoSampleLike, void, unknown>;
139
+ }
140
+ /** A walk source and its disposal, held by whoever opened it. */
141
+ export interface WalkSourceHandle extends WalkFrameSource {
142
+ dispose(): Promise<void>;
143
+ }
144
+ /** Discriminates the opened-source handle shapes at the cursor boundary. */
145
+ export type AnySourceHandle = DecodeSourceHandle | SampleSourceHandle | SessionSourceHandle;
146
+ /**
147
+ * Wraps any opened-source handle in the unified FrameProvider. The two sample
148
+ * paths wrap each yielded VideoSample in idempotentSample so the cursor can
149
+ * discharge the close obligation from any path without double-free.
150
+ */
151
+ export declare function openFrameProvider(handle: AnySourceHandle): FrameProvider;
152
+ /**
153
+ * Opens a source on the CanvasSink path, the one every decodable source
154
+ * supports. Track facts are resolved here too, so the consumer receives a fully
155
+ * described handle and never touches mediabunny or the resolution math. Playback
156
+ * consumers call openScrubSource instead and take whatever path the source
157
+ * supports; this is for consumers that want canvases specifically.
158
+ */
159
+ export declare function openDecodeSource(options: CreateScrubCursorOptions): Promise<DecodeSourceHandle>;
160
+ /**
161
+ * Opens a source and routes it to the fastest decode path it supports: the
162
+ * long-lived DecodeSession, then the zero-copy VideoSampleSink, then the
163
+ * CanvasSink.
164
+ *
165
+ * The session's condition is the track's codec, which nothing can answer until
166
+ * the container has been read, so the input opens first and the path is chosen
167
+ * against what the opened track reports. The one input then serves whichever
168
+ * path won.
169
+ */
170
+ export declare function openScrubSource(options: CreateScrubCursorOptions): Promise<AnySourceHandle>;
171
+ /**
172
+ * Opens a source for a batch walk over its frames, on its own input and its own
173
+ * decoder. A walk reads thousands of frames in a row and a playback cursor is
174
+ * serving a screen, so the two never share: whatever a walk does to its read
175
+ * head, no gesture is waiting behind it.
176
+ *
177
+ * The CanvasSink path is not offered here. It yields recycled canvases with no
178
+ * duration and no close, and a walk's whole contract is real frames with the
179
+ * timing they were encoded with, so a source that cannot present samples cannot
180
+ * be walked. Frames arrive at the source's native resolution; nothing downscales
181
+ * them on the way out.
182
+ */
183
+ export declare function openWalkSource(source: VideoSource): Promise<WalkSourceHandle>;
184
+ /**
185
+ * Inputs the zero-copy gate reasons over. Held as data, not probed live, so the
186
+ * predicate is pure and unit-testable: the caller measures the realm once and
187
+ * passes the facts in.
188
+ */
189
+ export interface ZeroCopyContext {
190
+ /** True when the consumer pinned the 2D renderer. */
191
+ readonly prefer2d: boolean;
192
+ /** Whether decode runs at the source's native size (the strategy requests no
193
+ * downscale). A downscale rules the path out: the sample arrives native, so
194
+ * importing it zero-copy would paint at the wrong resolution. */
195
+ readonly decodesNative: boolean;
196
+ /** Whether the worker realm has WebGPU with importExternalTexture, the API
197
+ * the zero-copy import needs. */
198
+ readonly webgpuImportAvailable: boolean;
199
+ }
200
+ /**
201
+ * The gate. True only when every condition holds: the 2D path is not pinned, the
202
+ * strategy decodes at native (no downscale), and the realm offers WebGPU's
203
+ * importExternalTexture. False keeps the byte-identical CanvasSink path; this is
204
+ * the one place the additive path is allowed to switch on.
205
+ */
206
+ export declare function zeroCopyViable(ctx: ZeroCopyContext): boolean;
207
+ /**
208
+ * Inputs the long-lived-decoder gate reasons over, held as data for the same
209
+ * reason ZeroCopyContext is.
210
+ *
211
+ * Decode resolution is deliberately absent. The session owns its decoder and
212
+ * always decodes at the source's native size, so a requested downscale is a
213
+ * canvas and cache concern rather than a reason to refuse the path.
214
+ */
215
+ export interface DecodeSessionContext {
216
+ /** Whether this realm has WebCodecs. The session builds and drives its own
217
+ * VideoDecoder rather than decoding through a mediabunny sink. */
218
+ readonly videoDecoderAvailable: boolean;
219
+ /** The opened track's decoder config, which decides whether the session's
220
+ * anchor trick applies to this bitstream. */
221
+ readonly decoderConfig: VideoDecoderConfig;
222
+ }
223
+ /**
224
+ * The gate. The session reaches a non-IDR anchor by declaring it a recovery
225
+ * point, which only holds for AVCC-framed H.264 carrying its parameter sets, so
226
+ * every other source keeps the mediabunny sinks.
227
+ */
228
+ export declare function decodeSessionViable(ctx: DecodeSessionContext): boolean;
229
+ /** Whether this realm exposes the WebCodecs decoder the session constructs. */
230
+ export declare function detectVideoDecoder(): boolean;
231
+ /**
232
+ * Probes the worker realm for WebGPU with importExternalTexture. Checks for the
233
+ * method on the prototype rather than acquiring a device, so it is synchronous
234
+ * and cheap; the actual device acquisition still happens (and can still fail
235
+ * back to 2D) in the renderer.
236
+ */
237
+ export declare function detectWebgpuImport(): boolean;
238
+ export declare function urlRequestInit(crossOrigin: UrlVideoSource["crossOrigin"]): {
239
+ requestInit: RequestInit;
240
+ } | undefined;
241
+ export declare function toMediabunnySource(source: VideoSource, residency?: SourceResidency, urlSource?: UrlSourceReadConfig): UrlSource | BlobSource | ReadableStreamSource;
242
+ /**
243
+ * Whether a source can be opened a second time, which the hang-recovery path
244
+ * needs to rebuild a wedged decoder. A URL re-fetches and a Blob re-reads, so
245
+ * both re-open cleanly. A ReadableStream is consumed once and cannot be rewound,
246
+ * so a rebuild on it would open onto an exhausted stream; the watchdog falls back
247
+ * to a degraded-but-alive state instead of rebuilding for that kind.
248
+ */
249
+ export declare function isReopenableSource(source: VideoSource): boolean;
250
+ //# sourceMappingURL=decode-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode-source.d.ts","sourceRoot":"","sources":["../src/decode-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,UAAU,EAIV,oBAAoB,EAEpB,SAAS,EAEV,MAAM,YAAY,CAAC;AAGpB,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAGL,KAAK,kBAAkB,EAExB,MAAM,kBAAkB,CAAC;AAO1B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAKL,KAAK,UAAU,EACf,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,WAAW,EACjB,MAAM,SAAS,CAAC;AAEjB;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,eAAe,GAAG,iBAAiB,CAAC;IACrD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IACjE,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAAC,iBAAiB,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC3E,oBAAoB,CAClB,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,GAC3B,cAAc,CAAC,iBAAiB,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;CAC5D;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IAC/D,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAAC,eAAe,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACxE,mBAAmB,CACjB,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,GAC3B,cAAc,CAAC,eAAe,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;CAC1D;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC;IACvC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,GACpB;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,eAAe,GAAG,iBAAiB,CAAC;IACrD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEN;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAC3D,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAAC,YAAY,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACpE,QAAQ,CACN,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,GAC3B,cAAc,CAAC,YAAY,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACtD;;;;;OAKG;IACH,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3C;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B;;;;;OAKG;IACH,aAAa,IAAI,MAAM,CAAC;IACxB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAAC,eAAe,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;CAC5E;AAED,iEAAiE;AACjE,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,4EAA4E;AAC5E,MAAM,MAAM,eAAe,GACzB,kBAAkB,GAAG,kBAAkB,GAAG,mBAAmB,CAAC;AAYhE;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,eAAe,GAAG,aAAa,CAIxE;AAgHD;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,kBAAkB,CAAC,CAK7B;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,eAAe,CAAC,CAsB1B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,gBAAgB,CAAC,CAe3B;AA2QD;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B;;sEAEkE;IAClE,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC;sCACkC;IAClC,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAC;CACzC;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAK5D;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,oBAAoB;IACnC;uEACmE;IACnE,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAC;IACxC;kDAC8C;IAC9C,QAAQ,CAAC,aAAa,EAAE,kBAAkB,CAAC;CAC5C;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,oBAAoB,GAAG,OAAO,CAGtE;AAED,+EAA+E;AAC/E,wBAAgB,kBAAkB,IAAI,OAAO,CAK5C;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAQ5C;AAED,wBAAgB,cAAc,CAC5B,WAAW,EAAE,cAAc,CAAC,aAAa,CAAC,GACzC;IAAE,WAAW,EAAE,WAAW,CAAA;CAAE,GAAG,SAAS,CAQ1C;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,WAAW,EACnB,SAAS,CAAC,EAAE,eAAe,EAC3B,SAAS,CAAC,EAAE,mBAAmB,GAC9B,SAAS,GAAG,UAAU,GAAG,oBAAoB,CAuB/C;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAE/D"}
@@ -0,0 +1,18 @@
1
+ import type { DiagnosticsSnapshot } from "./diagnostics";
2
+ /**
3
+ * Sibling of MirrorStore for the diagnostics broadcast plane. A single
4
+ * channel holding the latest snapshot, shaped for useSyncExternalStore. Fed only
5
+ * by the 'diag' event; the playback mirror store and its subscribers never touch
6
+ * it, so a 10Hz diagnostics push never wakes a playback consumer.
7
+ *
8
+ * getSnapshot returns the same reference between writes, so a selector using
9
+ * Object.is short-circuits when nothing changed.
10
+ */
11
+ export declare class DiagnosticsStore {
12
+ private snapshot;
13
+ private readonly listeners;
14
+ getSnapshot(): DiagnosticsSnapshot | null;
15
+ write(snapshot: DiagnosticsSnapshot): void;
16
+ subscribe(listener: () => void): () => void;
17
+ }
18
+ //# sourceMappingURL=diagnostics-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics-store.d.ts","sourceRoot":"","sources":["../src/diagnostics-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEzD;;;;;;;;GAQG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAoC;IACpD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyB;IAEnD,WAAW,IAAI,mBAAmB,GAAG,IAAI;IAIzC,KAAK,CAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI;IAK1C,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;CAM5C"}