supervision 0.1.7 → 0.2.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants/media-renderer.d.ts +3 -0
- package/dist/constants/media-renderer.d.ts.map +1 -1
- package/dist/detections/chunked-detection-frame-source.d.ts.map +1 -1
- package/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9281 -5038
- package/dist/index.js.map +1 -1
- package/dist/mask-preparation.worker.js +409 -185
- package/dist/mask-preparation.worker.js.map +1 -1
- package/dist/media/display-pixel-ratio.d.ts +15 -0
- package/dist/media/display-pixel-ratio.d.ts.map +1 -0
- package/dist/media/engine-import-failure.d.ts +16 -0
- package/dist/media/engine-import-failure.d.ts.map +1 -0
- package/dist/media/media-errors.d.ts +6 -0
- package/dist/media/media-errors.d.ts.map +1 -1
- package/dist/media/media-normalization.d.ts.map +1 -1
- package/dist/media/media-probe.d.ts.map +1 -1
- package/dist/media/media-source-state.d.ts.map +1 -1
- package/dist/media/media-source.d.ts +17 -0
- package/dist/media/media-source.d.ts.map +1 -1
- package/dist/media/mediabunny-media-source.d.ts.map +1 -1
- package/dist/media/video-engine-media-source.d.ts +54 -0
- package/dist/media/video-engine-media-source.d.ts.map +1 -0
- package/dist/media/video-engine-media-source.js +3 -0
- package/dist/media/video-engine-media-source.js.map +1 -0
- package/dist/playback/media-playback-controller.d.ts +7 -1
- package/dist/playback/media-playback-controller.d.ts.map +1 -1
- package/dist/render-preparation/mask-frame-artifact.d.ts +48 -12
- package/dist/render-preparation/mask-frame-artifact.d.ts.map +1 -1
- package/dist/render-preparation/mask-frame-compositor.d.ts +12 -5
- package/dist/render-preparation/mask-frame-compositor.d.ts.map +1 -1
- package/dist/render-preparation/mask-frame-preparer.d.ts.map +1 -1
- package/dist/render-preparation/mask-preparation-worker-count.d.ts +4 -4
- package/dist/render-preparation/mask-preparation-worker-protocol.d.ts +13 -3
- package/dist/render-preparation/mask-preparation-worker-protocol.d.ts.map +1 -1
- package/dist/render-preparation/prepared-render-window.d.ts +44 -2
- package/dist/render-preparation/prepared-render-window.d.ts.map +1 -1
- package/dist/render-preparation/prepared-window-timeline.d.ts +2 -6
- package/dist/render-preparation/prepared-window-timeline.d.ts.map +1 -1
- package/dist/renderers/injected-pixi.d.ts +38 -0
- package/dist/renderers/injected-pixi.d.ts.map +1 -0
- package/dist/renderers/mask-palette.d.ts +14 -0
- package/dist/renderers/mask-palette.d.ts.map +1 -0
- package/dist/renderers/mask-vertex.d.ts +14 -0
- package/dist/renderers/mask-vertex.d.ts.map +1 -0
- package/dist/renderers/media-renderer-core.d.ts +9 -0
- package/dist/renderers/media-renderer-core.d.ts.map +1 -1
- package/dist/renderers/media-renderer-scene.d.ts +50 -2
- package/dist/renderers/media-renderer-scene.d.ts.map +1 -1
- package/dist/renderers/media-renderer-state.d.ts +20 -1
- package/dist/renderers/media-renderer-state.d.ts.map +1 -1
- package/dist/renderers/media-renderer-transport.d.ts +72 -0
- package/dist/renderers/media-renderer-transport.d.ts.map +1 -0
- package/dist/renderers/pixi-box-layer.d.ts +5 -0
- package/dist/renderers/pixi-box-layer.d.ts.map +1 -1
- package/dist/renderers/pixi-focus-layer.d.ts +19 -2
- package/dist/renderers/pixi-focus-layer.d.ts.map +1 -1
- package/dist/renderers/pixi-frame-present.d.ts +77 -0
- package/dist/renderers/pixi-frame-present.d.ts.map +1 -0
- package/dist/renderers/pixi-id-mask-shader.d.ts +6 -25
- package/dist/renderers/pixi-id-mask-shader.d.ts.map +1 -1
- package/dist/renderers/pixi-interaction-layer.d.ts.map +1 -1
- package/dist/renderers/pixi-interaction-presentation-layer.d.ts +12 -2
- package/dist/renderers/pixi-interaction-presentation-layer.d.ts.map +1 -1
- package/dist/renderers/pixi-mask-halo.d.ts +18 -23
- package/dist/renderers/pixi-mask-halo.d.ts.map +1 -1
- package/dist/renderers/pixi-mask-layer.d.ts +94 -32
- package/dist/renderers/pixi-mask-layer.d.ts.map +1 -1
- package/dist/renderers/pixi-media-scene.d.ts +67 -0
- package/dist/renderers/pixi-media-scene.d.ts.map +1 -1
- package/dist/renderers/pixi-polygon-layer.d.ts +9 -2
- package/dist/renderers/pixi-polygon-layer.d.ts.map +1 -1
- package/dist/renderers/pixi-region-coverage-mask.d.ts +62 -0
- package/dist/renderers/pixi-region-coverage-mask.d.ts.map +1 -0
- package/dist/renderers/pixi-region-effect.d.ts +42 -0
- package/dist/renderers/pixi-region-effect.d.ts.map +1 -0
- package/dist/renderers/pixi-region-layer.d.ts +43 -2
- package/dist/renderers/pixi-region-layer.d.ts.map +1 -1
- package/dist/renderers/pixi-shader-lifecycle.d.ts +14 -0
- package/dist/renderers/pixi-shader-lifecycle.d.ts.map +1 -0
- package/dist/renderers/pixi-vector-layer.d.ts.map +1 -1
- package/dist/renderers/prepared-annotation-window.d.ts +47 -0
- package/dist/renderers/prepared-annotation-window.d.ts.map +1 -0
- package/dist/renderers/presented-frame-channel.d.ts +138 -0
- package/dist/renderers/presented-frame-channel.d.ts.map +1 -0
- package/dist/renderers/scene-render-scheduler.d.ts +20 -0
- package/dist/renderers/scene-render-scheduler.d.ts.map +1 -0
- package/dist/sessions/media-session-defaults.d.ts +10 -6
- package/dist/sessions/media-session-defaults.d.ts.map +1 -1
- package/dist/sessions/media-session-media.d.ts.map +1 -1
- package/dist/sessions/media-session-state.d.ts.map +1 -1
- package/dist/sessions/media-session.d.ts.map +1 -1
- package/dist/tracking.worker.js +73 -4
- package/dist/tracking.worker.js.map +1 -1
- package/dist/types/media-normalization.d.ts +34 -0
- package/dist/types/media-normalization.d.ts.map +1 -1
- package/dist/types/media-renderer.d.ts +31 -1
- package/dist/types/media-renderer.d.ts.map +1 -1
- package/dist/types/media-session.d.ts +89 -15
- package/dist/types/media-session.d.ts.map +1 -1
- package/dist/types/render-preparation.d.ts +149 -5
- package/dist/types/render-preparation.d.ts.map +1 -1
- package/dist/video-engine-media-source-CUXnOJOV.js +450 -0
- package/dist/video-engine-media-source-CUXnOJOV.js.map +1 -0
- package/dist/web-video-engine/analysis-session.d.ts +75 -0
- package/dist/web-video-engine/analysis.d.ts +6 -0
- package/dist/web-video-engine/analysis.js +1850 -0
- package/dist/web-video-engine/cache-budget.d.ts +18 -0
- package/dist/web-video-engine/canvas-sink-scrub-cursor.d.ts +89 -0
- package/dist/web-video-engine/clock.d.ts +82 -0
- package/dist/web-video-engine/constants.d.ts +261 -0
- package/dist/web-video-engine/create-scrub-cursor.d.ts +65 -0
- package/dist/web-video-engine/decode-resolution.d.ts +114 -0
- package/dist/web-video-engine/decode-scheduler.d.ts +371 -0
- package/dist/web-video-engine/decode-session.d.ts +283 -0
- package/dist/web-video-engine/decode-source.d.ts +258 -0
- package/dist/web-video-engine/diagnostics-store.d.ts +17 -0
- package/dist/web-video-engine/diagnostics.d.ts +316 -0
- package/dist/web-video-engine/embedded-engine-worker.d.ts +1 -0
- package/dist/web-video-engine/engine-core.d.ts +269 -0
- package/dist/web-video-engine/engine.d.ts +25 -0
- package/dist/web-video-engine/engine.js +912 -0
- package/dist/web-video-engine/engine.worker.d.ts +1 -0
- package/dist/web-video-engine/engine.worker.js +33624 -0
- package/dist/web-video-engine/frame-cache.d.ts +236 -0
- package/dist/web-video-engine/frame-extractor.d.ts +27 -0
- package/dist/web-video-engine/frame-timeline-DreEwsRY.js +616 -0
- package/dist/web-video-engine/frame-timeline.d.ts +80 -0
- package/dist/web-video-engine/frame-walker.d.ts +73 -0
- package/dist/web-video-engine/index.d.ts +13 -0
- package/dist/web-video-engine/index.d.ts.map +1 -0
- package/dist/web-video-engine/index.js +3 -0
- package/dist/web-video-engine/index.js.map +1 -0
- package/dist/web-video-engine/key-packet.d.ts +64 -0
- package/dist/web-video-engine/keyframe-index.d.ts +90 -0
- package/dist/web-video-engine/mirror-store.d.ts +55 -0
- package/dist/web-video-engine/renderer.d.ts +93 -0
- package/dist/web-video-engine/rotation.d.ts +34 -0
- package/dist/web-video-engine/scrub-controller.d.ts +375 -0
- package/dist/web-video-engine/scrub-cursor.d.ts +347 -0
- package/dist/web-video-engine/scrub-trajectory.d.ts +29 -0
- package/dist/web-video-engine/source-residency.d.ts +91 -0
- package/dist/web-video-engine/trace-recorder.d.ts +163 -0
- package/dist/web-video-engine/types.d.ts +200 -0
- package/dist/web-video-engine/video-engine.d.ts +437 -0
- package/dist/web-video-engine/webgpu-renderer.d.ts +61 -0
- package/dist/web-video-engine/worker-bridge.d.ts +11 -0
- package/dist/web-video-engine/worker-dispatch.d.ts +16 -0
- package/dist/web-video-engine/worker-protocol.d.ts +282 -0
- package/node_modules/supervision-js-core/dist/detections/buffered-detection-timeline.d.ts.map +1 -1
- package/node_modules/supervision-js-core/dist/detections/composite-detection-frame-source.d.ts.map +1 -1
- package/node_modules/supervision-js-core/dist/index.d.ts +5 -4
- package/node_modules/supervision-js-core/dist/index.d.ts.map +1 -1
- package/node_modules/supervision-js-core/dist/index.js +1167 -280
- package/node_modules/supervision-js-core/dist/index.js.map +1 -1
- package/node_modules/supervision-js-core/dist/styles/default-annotation-presentation.d.ts.map +1 -1
- package/node_modules/supervision-js-core/dist/styles/interaction-style.d.ts +4 -36
- package/node_modules/supervision-js-core/dist/styles/interaction-style.d.ts.map +1 -1
- package/node_modules/supervision-js-core/dist/styles/polyline-style.d.ts +5 -0
- package/node_modules/supervision-js-core/dist/styles/polyline-style.d.ts.map +1 -1
- package/node_modules/supervision-js-core/dist/types/annotation-renderer.d.ts +92 -7
- package/node_modules/supervision-js-core/dist/types/annotation-renderer.d.ts.map +1 -1
- package/node_modules/supervision-js-core/dist/types/detection-timeline.d.ts +191 -17
- package/node_modules/supervision-js-core/dist/types/detection-timeline.d.ts.map +1 -1
- package/node_modules/supervision-js-core/dist/types/media-rendering.d.ts +83 -5
- package/node_modules/supervision-js-core/dist/types/media-rendering.d.ts.map +1 -1
- package/node_modules/supervision-js-core/dist/types/polyline-style.d.ts +2 -0
- package/node_modules/supervision-js-core/dist/types/polyline-style.d.ts.map +1 -1
- package/node_modules/supervision-js-core/dist/types/session-lifecycle.d.ts +32 -0
- package/node_modules/supervision-js-core/dist/types/session-lifecycle.d.ts.map +1 -1
- package/node_modules/supervision-js-core/dist/utils/detection-conversions.d.ts.map +1 -1
- package/node_modules/supervision-js-core/dist/utils/detection-frames.d.ts +5 -0
- package/node_modules/supervision-js-core/dist/utils/detection-frames.d.ts.map +1 -1
- package/node_modules/supervision-js-core/dist/utils/detection-masks.d.ts +9 -0
- package/node_modules/supervision-js-core/dist/utils/detection-masks.d.ts.map +1 -1
- package/node_modules/supervision-js-core/dist/utils/detection-ranges.d.ts +18 -0
- package/node_modules/supervision-js-core/dist/utils/detection-ranges.d.ts.map +1 -0
- package/node_modules/supervision-js-core/dist/utils/id-mask-frame.d.ts +34 -2
- package/node_modules/supervision-js-core/dist/utils/id-mask-frame.d.ts.map +1 -1
- package/node_modules/supervision-js-core/dist/utils/wait-bound.d.ts +7 -0
- package/node_modules/supervision-js-core/dist/utils/wait-bound.d.ts.map +1 -0
- package/package.json +24 -3
|
@@ -0,0 +1,258 @@
|
|
|
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
|
+
/** Platform facts used to contain decoder-output ownership to Android.
|
|
224
|
+
* Client hints win when available so desktop UA emulation cannot accidentally
|
|
225
|
+
* turn the expensive path on. */
|
|
226
|
+
export interface DecodeSessionPixelOwnershipContext {
|
|
227
|
+
readonly clientPlatform?: string;
|
|
228
|
+
readonly userAgent?: string;
|
|
229
|
+
readonly offscreenCanvasAvailable: boolean;
|
|
230
|
+
}
|
|
231
|
+
export declare function shouldOwnDecodeSessionPixels(context: DecodeSessionPixelOwnershipContext): boolean;
|
|
232
|
+
/**
|
|
233
|
+
* The gate. The session reaches a non-IDR anchor by declaring it a recovery
|
|
234
|
+
* point, which only holds for AVCC-framed H.264 carrying its parameter sets, so
|
|
235
|
+
* every other source keeps the mediabunny sinks.
|
|
236
|
+
*/
|
|
237
|
+
export declare function decodeSessionViable(ctx: DecodeSessionContext): boolean;
|
|
238
|
+
/** Whether this realm exposes the WebCodecs decoder the session constructs. */
|
|
239
|
+
export declare function detectVideoDecoder(): boolean;
|
|
240
|
+
/**
|
|
241
|
+
* Probes the worker realm for WebGPU with importExternalTexture. Checks for the
|
|
242
|
+
* method on the prototype rather than acquiring a device, so it is synchronous
|
|
243
|
+
* and cheap; the actual device acquisition still happens (and can still fail
|
|
244
|
+
* back to 2D) in the renderer.
|
|
245
|
+
*/
|
|
246
|
+
export declare function detectWebgpuImport(): boolean;
|
|
247
|
+
export declare function urlRequestInit(crossOrigin: UrlVideoSource["crossOrigin"]): {
|
|
248
|
+
requestInit: RequestInit;
|
|
249
|
+
} | undefined;
|
|
250
|
+
export declare function toMediabunnySource(source: VideoSource, residency?: SourceResidency, urlSource?: UrlSourceReadConfig): UrlSource | BlobSource | ReadableStreamSource;
|
|
251
|
+
/**
|
|
252
|
+
* Whether a source can be opened a second time, which the hang-recovery path
|
|
253
|
+
* needs to rebuild a wedged decoder. A URL re-fetches and a Blob re-reads, so
|
|
254
|
+
* both re-open cleanly. A ReadableStream is consumed once and cannot be rewound,
|
|
255
|
+
* so a rebuild on it would open onto an exhausted stream; the watchdog falls back
|
|
256
|
+
* to a degraded-but-alive state instead of rebuilding for that kind.
|
|
257
|
+
*/
|
|
258
|
+
export declare function isReopenableSource(source: VideoSource): boolean;
|
|
@@ -0,0 +1,17 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import type { FrameCacheStats } from "./frame-cache";
|
|
2
|
+
import type { FrameId } from "./frame-timeline";
|
|
3
|
+
import type { GopStats } from "./keyframe-index";
|
|
4
|
+
import type { FrameQuality, SchedulerStats } from "./scrub-cursor";
|
|
5
|
+
import type { PresentationMode } from "./types";
|
|
6
|
+
/** Which render backend is painting the display canvas. */
|
|
7
|
+
export type RendererName = "2d" | "webgpu";
|
|
8
|
+
/** Resolved track facts worth surfacing for diagnostics. decodeWidth/Height
|
|
9
|
+
* explain cache slot counts: the exact tier is RAM-budgeted, so large frames
|
|
10
|
+
* mean few slots. */
|
|
11
|
+
export interface DiagnosticsTrack {
|
|
12
|
+
readonly decodeWidth: number;
|
|
13
|
+
readonly decodeHeight: number;
|
|
14
|
+
readonly nativeFps: number | null;
|
|
15
|
+
readonly durationS: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Engine-level diagnostics snapshot the worker assembles on demand. Combines the
|
|
19
|
+
* renderer (controller-owned), track facts, and the scheduler stats (cursor-
|
|
20
|
+
* owned, null on the uncached cursor). All plain data, so it crosses the worker
|
|
21
|
+
* boundary by structured clone.
|
|
22
|
+
*
|
|
23
|
+
* What `getStats` answers with, one round trip per call and no broadcast timer
|
|
24
|
+
* required. {@link DiagnosticsSnapshot} opens with these same three fields and
|
|
25
|
+
* carries the rest of the instrument payload, but only while the diagnostics
|
|
26
|
+
* broadcast is running.
|
|
27
|
+
*/
|
|
28
|
+
export interface EngineDiagnostics {
|
|
29
|
+
readonly renderer: RendererName | null;
|
|
30
|
+
readonly track: DiagnosticsTrack | null;
|
|
31
|
+
readonly scheduler: SchedulerStats | null;
|
|
32
|
+
}
|
|
33
|
+
/** Per-paint realtime needles. effectivePaintFps is the painted rate over a
|
|
34
|
+
* trailing window of broadcast intervals (see PaintRateMeter), null unless
|
|
35
|
+
* playback was up across the whole window, so every snapshot in a series
|
|
36
|
+
* carries its own reading. ticks and paints reset at each play start, so they
|
|
37
|
+
* count the current play session rather than the source's lifetime.
|
|
38
|
+
* catchUpMs is how far the clock ran past the last painted frame.
|
|
39
|
+
* playQueueDepth is the decode-ahead buffer's current length: 0 while playing is
|
|
40
|
+
* the imminent-stall tell. */
|
|
41
|
+
export interface RealtimeDiagnostics {
|
|
42
|
+
readonly effectivePaintFps: number | null;
|
|
43
|
+
readonly catchUpMs: number;
|
|
44
|
+
readonly lateFrames: number;
|
|
45
|
+
readonly stalls: number;
|
|
46
|
+
readonly ticks: number;
|
|
47
|
+
readonly paints: number;
|
|
48
|
+
readonly playQueueDepth: number;
|
|
49
|
+
/** Decoded frames thrown away before reaching the canvas: ones that arrived
|
|
50
|
+
* for a position playback had left, buffered ones overtaken by the clock
|
|
51
|
+
* moving backwards, and the ones the present cadence declines once the rate
|
|
52
|
+
* asks for more frames a second than it. The first two are decode bandwidth
|
|
53
|
+
* spent on frames nobody ever saw; the third is the cadence doing its job,
|
|
54
|
+
* and at a high rate it dominates the count. */
|
|
55
|
+
readonly droppedFrames: number;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Lifetime frame ledger across the decode-to-screen pipe: what the decoder
|
|
59
|
+
* produced, what reached the canvas, what was discarded on the way. These three
|
|
60
|
+
* are only meaningful read together; the ratio between decoded and painted is
|
|
61
|
+
* the cost of every frame nobody saw. Monotonic from load, never reset by a
|
|
62
|
+
* play session. decodedFrames is null when the decode path cannot report it
|
|
63
|
+
* (the uncached cursor).
|
|
64
|
+
*/
|
|
65
|
+
export interface PipelineDiagnostics {
|
|
66
|
+
readonly decodedFrames: number | null;
|
|
67
|
+
readonly paintedFrames: number;
|
|
68
|
+
readonly droppedFrames: number;
|
|
69
|
+
}
|
|
70
|
+
/** Last painted frame and its quality; see DiagnosticsSnapshot.screen. */
|
|
71
|
+
export interface ScreenDiagnostics {
|
|
72
|
+
/** Which frame of the source is up, by the engine's own frame table. */
|
|
73
|
+
readonly frameId: FrameId;
|
|
74
|
+
readonly mediaTimeMs: number;
|
|
75
|
+
readonly quality: FrameQuality;
|
|
76
|
+
}
|
|
77
|
+
/** Cache occupancy in bytes, derived from resident slot counts and frame dims.
|
|
78
|
+
* exactBytesPct is the exact tier's fill against its RAM ceiling; a high value
|
|
79
|
+
* with a low hit rate is the starved-cache tell. */
|
|
80
|
+
export interface CacheBytesDiagnostics {
|
|
81
|
+
readonly exactBytes: number;
|
|
82
|
+
readonly previewBytes: number;
|
|
83
|
+
readonly exactBudgetBytes: number;
|
|
84
|
+
readonly exactBytesPct: number;
|
|
85
|
+
}
|
|
86
|
+
/** Track geometry that explains decode cost. nativeWidth/Height come from the
|
|
87
|
+
* source track (omitted when the track exposes no native dims). downscaleRatio
|
|
88
|
+
* is decodeWidth/nativeWidth; decodeVsDisplayAreaRatio compares the decoded
|
|
89
|
+
* frame area to the bound canvas area (>1 means decoding larger than painted). */
|
|
90
|
+
export interface TrackGeometryDiagnostics {
|
|
91
|
+
readonly nativeWidth: number | null;
|
|
92
|
+
readonly nativeHeight: number | null;
|
|
93
|
+
readonly decodeWidth: number;
|
|
94
|
+
readonly decodeHeight: number;
|
|
95
|
+
readonly downscaleRatio: number | null;
|
|
96
|
+
readonly decodeVsDisplayAreaRatio: number | null;
|
|
97
|
+
readonly boundCanvasWidth: number | null;
|
|
98
|
+
readonly boundCanvasHeight: number | null;
|
|
99
|
+
}
|
|
100
|
+
/** GOP distribution plus the labelled estimates. estimatedGopWalkDepthFrames is
|
|
101
|
+
* an ESTIMATE: frames a worst-case off-anchor scrub would decode, derived from
|
|
102
|
+
* avg GOP and native fps, never measured inside the decode loop. */
|
|
103
|
+
export interface GopDiagnostics extends GopStats {
|
|
104
|
+
/** Media seconds from the playhead to the closest anchor the keyframe index
|
|
105
|
+
* has discovered so far. The index fills lazily, so this reads null until it
|
|
106
|
+
* holds one and tightens as it walks further. */
|
|
107
|
+
readonly distanceToNearestKeyframeS: number | null;
|
|
108
|
+
readonly estimatedGopWalkDepthFrames: number;
|
|
109
|
+
}
|
|
110
|
+
/** Scrub responsiveness aggregates lifted from the scheduler. cacheHitRatePct
|
|
111
|
+
* reads 0 when nothing has looked the cache up yet, which is indistinguishable
|
|
112
|
+
* from every lookup missing; cacheLookups() is the denominator that tells the
|
|
113
|
+
* two apart. */
|
|
114
|
+
export interface ScrubDiagnostics {
|
|
115
|
+
readonly samples: number;
|
|
116
|
+
readonly avgMs: number;
|
|
117
|
+
readonly maxMs: number;
|
|
118
|
+
readonly p50Ms: number;
|
|
119
|
+
readonly p95Ms: number;
|
|
120
|
+
readonly targetVsLandedMs: number;
|
|
121
|
+
readonly timeToCrispMs: number;
|
|
122
|
+
readonly cacheHitRatePct: number;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Seeks served by re-anchoring the running playback walk, the path a seek
|
|
126
|
+
* issued while playing takes, with the wall time each waited for its crisp
|
|
127
|
+
* frame. They never reach the cursor, so nothing in ScrubDiagnostics and no
|
|
128
|
+
* cache lookup counts them. samples is the denominator of avgMs and maxMs: it
|
|
129
|
+
* trails seeks whenever one is superseded, or the transport stopped under it,
|
|
130
|
+
* before its crisp frame arrived.
|
|
131
|
+
*/
|
|
132
|
+
export interface PlaySeekDiagnostics {
|
|
133
|
+
readonly seeks: number;
|
|
134
|
+
readonly samples: number;
|
|
135
|
+
readonly avgMs: number;
|
|
136
|
+
readonly maxMs: number;
|
|
137
|
+
}
|
|
138
|
+
/** Decode/seek/prefetch counters lifted from the scheduler. */
|
|
139
|
+
export interface CounterDiagnostics {
|
|
140
|
+
readonly foregroundDecodes: number;
|
|
141
|
+
readonly prefetchExact: number;
|
|
142
|
+
readonly prefetchPreview: number;
|
|
143
|
+
readonly keyframeAnchored: number;
|
|
144
|
+
readonly exactSeeks: number;
|
|
145
|
+
readonly keySeeks: number;
|
|
146
|
+
readonly seekCoalesceDepth: number;
|
|
147
|
+
readonly probeRoundTrips: number;
|
|
148
|
+
readonly prefetchInFlight: boolean;
|
|
149
|
+
/**
|
|
150
|
+
* Background sweeps cancelled since the source opened, as a running total, so
|
|
151
|
+
* a rate is only ever the delta between two snapshots. Playback schedules no
|
|
152
|
+
* sweeps, so a clip that only plays never moves this.
|
|
153
|
+
*/
|
|
154
|
+
readonly prefetchGeneration: number;
|
|
155
|
+
readonly nextPending: number;
|
|
156
|
+
/** How long the cursor has been draining a seek uninterrupted, in ms; 0 when
|
|
157
|
+
* none is in flight. Every play pull is refused for the whole of it. */
|
|
158
|
+
readonly seekDrainingForMs: number;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* The page's JS heap in use. Blink exposes performance.memory on Window only,
|
|
162
|
+
* never in a worker scope, so the worker cannot read this at all: it leaves the
|
|
163
|
+
* field null and the main thread fills it on receipt, as it does
|
|
164
|
+
* webgpuAvailable. Null off Blink, and null in a trace, which is assembled
|
|
165
|
+
* inside the worker.
|
|
166
|
+
*/
|
|
167
|
+
export interface MemoryDiagnostics {
|
|
168
|
+
readonly jsHeapUsedBytes: number | null;
|
|
169
|
+
}
|
|
170
|
+
/** Severity of a diagnosis, ordered info < warn < critical for sorting. */
|
|
171
|
+
export type WarningSeverity = "info" | "warn" | "critical";
|
|
172
|
+
/**
|
|
173
|
+
* One self-explaining diagnosis. id is the stable rule key; scenario names what
|
|
174
|
+
* the runtime is doing wrong in plain language; advice is the fix; evidence is
|
|
175
|
+
* the human-readable metric values that tripped the rule, so a trace explains
|
|
176
|
+
* itself to a human or an agent without re-deriving the thresholds.
|
|
177
|
+
*/
|
|
178
|
+
export interface Warning {
|
|
179
|
+
readonly id: string;
|
|
180
|
+
readonly severity: WarningSeverity;
|
|
181
|
+
readonly title: string;
|
|
182
|
+
readonly scenario: string;
|
|
183
|
+
readonly advice: string;
|
|
184
|
+
readonly evidence: string;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Source bytes this process holds, for a host that wants to show a viewer how
|
|
188
|
+
* much of the clip is local. Null unless the engine was loaded with
|
|
189
|
+
* `sourceResidency`; nothing else in the runtime can answer it, because the
|
|
190
|
+
* demuxer's own reads and the browser cache are both opaque from here.
|
|
191
|
+
*/
|
|
192
|
+
export interface SourceResidencyDiagnostics {
|
|
193
|
+
readonly ranges: readonly {
|
|
194
|
+
readonly start: number;
|
|
195
|
+
readonly end: number;
|
|
196
|
+
}[];
|
|
197
|
+
readonly residentBytes: number;
|
|
198
|
+
readonly totalBytes: number | null;
|
|
199
|
+
readonly prefetchedBytes: number;
|
|
200
|
+
readonly warming: boolean;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* The clone-safe wire snapshot the worker broadcasts at BROADCAST_HZ. A superset
|
|
204
|
+
* of {@link EngineDiagnostics}: renderer, track and scheduler carry the same
|
|
205
|
+
* values, and it adds the realtime needles, the pipeline ledger, derived cache
|
|
206
|
+
* bytes, track geometry, GOP block, scrub aggregates, the play-time seek block,
|
|
207
|
+
* counters, memory, the clock/screen pair, and the worker-evaluated warnings.
|
|
208
|
+
* Only plain data crosses the boundary.
|
|
209
|
+
*
|
|
210
|
+
* webgpuAvailable and memory.jsHeapUsedBytes are the fields the worker leaves at
|
|
211
|
+
* their empty value for the main thread to fill after the broadcast, so a rule
|
|
212
|
+
* in evaluateWarnings (which runs in the worker) can never read them, and an
|
|
213
|
+
* exported trace, assembled worker-side, carries the unfilled value. Warnings
|
|
214
|
+
* are evaluated once, worker-side, so the HUD and an exported trace always show
|
|
215
|
+
* the same diagnoses.
|
|
216
|
+
*/
|
|
217
|
+
export interface DiagnosticsSnapshot {
|
|
218
|
+
/**
|
|
219
|
+
* Which presentation the engine was loaded for. `renderer` and the geometry
|
|
220
|
+
* fields that need a bound canvas are null for the whole life of a "frames"
|
|
221
|
+
* engine, which holds none by design; without this a reader cannot tell that
|
|
222
|
+
* from a "canvas" engine whose renderer has not resolved yet.
|
|
223
|
+
*/
|
|
224
|
+
readonly presentation: PresentationMode;
|
|
225
|
+
readonly renderer: RendererName | null;
|
|
226
|
+
readonly track: DiagnosticsTrack | null;
|
|
227
|
+
readonly scheduler: SchedulerStats | null;
|
|
228
|
+
readonly realtime: RealtimeDiagnostics;
|
|
229
|
+
readonly pipeline: PipelineDiagnostics;
|
|
230
|
+
readonly cacheBytes: CacheBytesDiagnostics;
|
|
231
|
+
readonly geometry: TrackGeometryDiagnostics;
|
|
232
|
+
readonly gop: GopDiagnostics;
|
|
233
|
+
readonly scrub: ScrubDiagnostics;
|
|
234
|
+
readonly playSeek: PlaySeekDiagnostics;
|
|
235
|
+
readonly counters: CounterDiagnostics;
|
|
236
|
+
readonly memory: MemoryDiagnostics;
|
|
237
|
+
readonly sourceResidency: SourceResidencyDiagnostics | null;
|
|
238
|
+
readonly nativeFps: number | null;
|
|
239
|
+
/** Media seconds per wall second the transport was told to run at. */
|
|
240
|
+
readonly rate: number;
|
|
241
|
+
/**
|
|
242
|
+
* The same figure measured off the canvas: media seconds of picture actually
|
|
243
|
+
* presented per wall second, over a trailing window; null unless playback was
|
|
244
|
+
* up across the whole of it. Read against `rate` it answers the one question
|
|
245
|
+
* a commanded rate cannot, which is whether the picture is really moving that
|
|
246
|
+
* fast. Falling short means frames are arriving slower than the clock wants
|
|
247
|
+
* them, so the picture lags further behind the playhead every second.
|
|
248
|
+
*
|
|
249
|
+
* It is a window over whole paints, so it quantises when paints are sparse: a
|
|
250
|
+
* slow rate on a low-fps source reads low from a healthy pipeline. Read it
|
|
251
|
+
* against catchUpMs before concluding anything from a shortfall.
|
|
252
|
+
*/
|
|
253
|
+
readonly presentedRate: number | null;
|
|
254
|
+
/** The engine clock at assembly, ms; null before load. Paused, it holds the
|
|
255
|
+
* last commanded target; playing, it advances at rate. The one value the
|
|
256
|
+
* instruments draw the playhead from, so the playhead and the coverage
|
|
257
|
+
* lanes cannot disagree about where "now" is. */
|
|
258
|
+
readonly playheadMs: number | null;
|
|
259
|
+
/** What is actually on the canvas: last painted position and its quality;
|
|
260
|
+
* null before the first paint. Its distance from playheadMs is the live
|
|
261
|
+
* landing error (paused) or catch-up depth (playing). A sampled
|
|
262
|
+
* observation for instruments; frame identity for consumers still travels
|
|
263
|
+
* only on the paint event. */
|
|
264
|
+
readonly screen: ScreenDiagnostics | null;
|
|
265
|
+
readonly status: string;
|
|
266
|
+
readonly webgpuAvailable: boolean;
|
|
267
|
+
readonly warnings: Warning[];
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Painted-frame rate over a trailing window of broadcast intervals, fed once
|
|
271
|
+
* per snapshot. A single interval can only hold whole paints, so its rate
|
|
272
|
+
* quantises hard; the trailing window smooths that without collapsing the
|
|
273
|
+
* series into a whole-capture average, which could confirm "playback is slow"
|
|
274
|
+
* but never locate it in time.
|
|
275
|
+
*/
|
|
276
|
+
export declare class PaintRateMeter {
|
|
277
|
+
private readonly windowSize;
|
|
278
|
+
private readonly samples;
|
|
279
|
+
constructor(windowSize?: number);
|
|
280
|
+
/** Rate in paints/second, or null unless playback was up across the whole
|
|
281
|
+
* window. A pause or a paints reset (each play session restarts the
|
|
282
|
+
* counter) invalidates the window, not just the sample. */
|
|
283
|
+
sample(atMs: number, paints: number, playing: boolean): number | null;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Playback speed measured off what reached the canvas: media seconds presented
|
|
287
|
+
* per wall second, over the same trailing window PaintRateMeter uses. Fed the
|
|
288
|
+
* last painted media position once per snapshot.
|
|
289
|
+
*
|
|
290
|
+
* It reads painted positions, not paint counts: a source can paint at a healthy
|
|
291
|
+
* 30fps while the clock runs at 4x, and only the distance the picture travelled
|
|
292
|
+
* shows that the two disagree.
|
|
293
|
+
*/
|
|
294
|
+
export declare class PresentedRateMeter {
|
|
295
|
+
private readonly windowSize;
|
|
296
|
+
private readonly samples;
|
|
297
|
+
constructor(windowSize?: number);
|
|
298
|
+
/** Rate in media seconds per wall second, or null unless playback was up
|
|
299
|
+
* across the whole window with the picture moving forward through it. */
|
|
300
|
+
sample(atMs: number, paintedMs: number | null, playing: boolean): number | null;
|
|
301
|
+
/** Drops the window, so a rate change is not measured across its own edge. */
|
|
302
|
+
reset(): void;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Cache lookups across every tier. Only an exact seek looks the cache up, so
|
|
306
|
+
* playback and key seeks never move this and a play-only session sits at zero.
|
|
307
|
+
* A rule or readout that reads the hit rate without this denominator reports a
|
|
308
|
+
* cold cache as a failing one.
|
|
309
|
+
*/
|
|
310
|
+
export declare function cacheLookups(cache: FrameCacheStats | null | undefined): number;
|
|
311
|
+
/**
|
|
312
|
+
* Pure threshold evaluator. Reads a snapshot and returns the active diagnoses,
|
|
313
|
+
* critical first. Used both in the worker (so the broadcast carries warnings the
|
|
314
|
+
* UI and the trace share) and in tests. No I/O, no side effects.
|
|
315
|
+
*/
|
|
316
|
+
export declare function evaluateWarnings(snapshot: DiagnosticsSnapshot): Warning[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const EMBEDDED_ENGINE_WORKER_SOURCE = "__SUPERVISION_JS_EMBEDDED_ENGINE_WORKER_SOURCE__";
|