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.
- package/dist/detections/chunked-detection-frame-source.d.ts.map +1 -1
- package/dist/index.d.ts +11 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8856 -4559
- package/dist/index.js.map +1 -1
- package/dist/mask-preparation.worker.js +310 -164
- 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-condition-probe.d.ts +51 -0
- package/dist/media/media-condition-probe.d.ts.map +1 -0
- package/dist/media/media-conditions.d.ts +28 -0
- package/dist/media/media-conditions.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.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 +44 -0
- package/dist/media/video-engine-media-source.d.ts.map +1 -0
- package/dist/render-preparation/mask-frame-artifact.d.ts +46 -12
- package/dist/render-preparation/mask-frame-artifact.d.ts.map +1 -1
- package/dist/render-preparation/mask-frame-compositor.d.ts +5 -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 +12 -3
- package/dist/render-preparation/mask-preparation-worker-protocol.d.ts.map +1 -1
- package/dist/render-preparation/prepared-render-window.d.ts +23 -0
- 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/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.map +1 -1
- package/dist/renderers/media-renderer-scene.d.ts +37 -0
- package/dist/renderers/media-renderer-scene.d.ts.map +1 -1
- package/dist/renderers/media-renderer-state.d.ts +11 -1
- package/dist/renderers/media-renderer-state.d.ts.map +1 -1
- package/dist/renderers/media-renderer-transport.d.ts +59 -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 +18 -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 +12 -2
- 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 +13 -2
- package/dist/renderers/pixi-interaction-presentation-layer.d.ts.map +1 -1
- package/dist/renderers/pixi-mask-halo.d.ts +24 -0
- package/dist/renderers/pixi-mask-halo.d.ts.map +1 -1
- package/dist/renderers/pixi-mask-layer.d.ts +71 -8
- 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 +7 -2
- package/dist/renderers/pixi-polygon-layer.d.ts.map +1 -1
- package/dist/renderers/pixi-region-coverage-mask.d.ts +91 -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 +68 -2
- package/dist/renderers/pixi-region-layer.d.ts.map +1 -1
- 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 +107 -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 +58 -3
- package/dist/tracking.worker.js.map +1 -1
- package/dist/types/media-conditions.d.ts +149 -0
- package/dist/types/media-conditions.d.ts.map +1 -0
- 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 -8
- package/dist/types/media-session.d.ts.map +1 -1
- package/dist/types/render-preparation.d.ts +101 -4
- package/dist/types/render-preparation.d.ts.map +1 -1
- package/dist/web-video-engine/analysis-session.d.ts +76 -0
- package/dist/web-video-engine/analysis-session.d.ts.map +1 -0
- package/dist/web-video-engine/analysis.d.ts +7 -0
- package/dist/web-video-engine/analysis.d.ts.map +1 -0
- package/dist/web-video-engine/analysis.js +1678 -0
- package/dist/web-video-engine/analysis.js.map +1 -0
- package/dist/web-video-engine/cache-budget.d.ts +19 -0
- package/dist/web-video-engine/cache-budget.d.ts.map +1 -0
- package/dist/web-video-engine/canvas-sink-scrub-cursor.d.ts +90 -0
- package/dist/web-video-engine/canvas-sink-scrub-cursor.d.ts.map +1 -0
- package/dist/web-video-engine/clock.d.ts +83 -0
- package/dist/web-video-engine/clock.d.ts.map +1 -0
- package/dist/web-video-engine/constants.d.ts +253 -0
- package/dist/web-video-engine/constants.d.ts.map +1 -0
- package/dist/web-video-engine/create-scrub-cursor.d.ts +62 -0
- package/dist/web-video-engine/create-scrub-cursor.d.ts.map +1 -0
- package/dist/web-video-engine/decode-resolution.d.ts +115 -0
- package/dist/web-video-engine/decode-resolution.d.ts.map +1 -0
- package/dist/web-video-engine/decode-scheduler.d.ts +356 -0
- package/dist/web-video-engine/decode-scheduler.d.ts.map +1 -0
- package/dist/web-video-engine/decode-session.d.ts +276 -0
- package/dist/web-video-engine/decode-session.d.ts.map +1 -0
- package/dist/web-video-engine/decode-source.d.ts +250 -0
- package/dist/web-video-engine/decode-source.d.ts.map +1 -0
- package/dist/web-video-engine/diagnostics-store.d.ts +18 -0
- package/dist/web-video-engine/diagnostics-store.d.ts.map +1 -0
- package/dist/web-video-engine/diagnostics.d.ts +316 -0
- package/dist/web-video-engine/diagnostics.d.ts.map +1 -0
- package/dist/web-video-engine/embedded-engine-worker.d.ts +2 -0
- package/dist/web-video-engine/embedded-engine-worker.d.ts.map +1 -0
- package/dist/web-video-engine/engine-core.d.ts +258 -0
- package/dist/web-video-engine/engine-core.d.ts.map +1 -0
- package/dist/web-video-engine/engine.d.ts +26 -0
- package/dist/web-video-engine/engine.d.ts.map +1 -0
- package/dist/web-video-engine/engine.js +873 -0
- package/dist/web-video-engine/engine.js.map +1 -0
- package/dist/web-video-engine/engine.worker.d.ts +2 -0
- package/dist/web-video-engine/engine.worker.d.ts.map +1 -0
- package/dist/web-video-engine/engine.worker.js +31320 -0
- package/dist/web-video-engine/engine.worker.js.map +1 -0
- package/dist/web-video-engine/frame-cache.d.ts +129 -0
- package/dist/web-video-engine/frame-cache.d.ts.map +1 -0
- package/dist/web-video-engine/frame-extractor.d.ts +28 -0
- package/dist/web-video-engine/frame-extractor.d.ts.map +1 -0
- package/dist/web-video-engine/frame-timeline-GINI8Gum.js +560 -0
- package/dist/web-video-engine/frame-timeline-GINI8Gum.js.map +1 -0
- package/dist/web-video-engine/frame-timeline.d.ts +71 -0
- package/dist/web-video-engine/frame-timeline.d.ts.map +1 -0
- package/dist/web-video-engine/frame-walker.d.ts +74 -0
- package/dist/web-video-engine/frame-walker.d.ts.map +1 -0
- package/dist/web-video-engine/index.d.ts +3 -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 +65 -0
- package/dist/web-video-engine/key-packet.d.ts.map +1 -0
- package/dist/web-video-engine/keyframe-index.d.ts +91 -0
- package/dist/web-video-engine/keyframe-index.d.ts.map +1 -0
- package/dist/web-video-engine/mirror-store.d.ts +56 -0
- package/dist/web-video-engine/mirror-store.d.ts.map +1 -0
- package/dist/web-video-engine/renderer.d.ts +94 -0
- package/dist/web-video-engine/renderer.d.ts.map +1 -0
- package/dist/web-video-engine/rotation.d.ts +35 -0
- package/dist/web-video-engine/rotation.d.ts.map +1 -0
- package/dist/web-video-engine/scrub-controller.d.ts +376 -0
- package/dist/web-video-engine/scrub-controller.d.ts.map +1 -0
- package/dist/web-video-engine/scrub-cursor.d.ts +342 -0
- package/dist/web-video-engine/scrub-cursor.d.ts.map +1 -0
- package/dist/web-video-engine/scrub-trajectory.d.ts +30 -0
- package/dist/web-video-engine/scrub-trajectory.d.ts.map +1 -0
- package/dist/web-video-engine/source-residency.d.ts +57 -0
- package/dist/web-video-engine/source-residency.d.ts.map +1 -0
- package/dist/web-video-engine/trace-recorder.d.ts +164 -0
- package/dist/web-video-engine/trace-recorder.d.ts.map +1 -0
- package/dist/web-video-engine/types.d.ts +204 -0
- package/dist/web-video-engine/types.d.ts.map +1 -0
- package/dist/web-video-engine/video-engine.d.ts +426 -0
- package/dist/web-video-engine/video-engine.d.ts.map +1 -0
- package/dist/web-video-engine/webgpu-renderer.d.ts +62 -0
- package/dist/web-video-engine/webgpu-renderer.d.ts.map +1 -0
- package/dist/web-video-engine/worker-bridge.d.ts +12 -0
- package/dist/web-video-engine/worker-bridge.d.ts.map +1 -0
- package/dist/web-video-engine/worker-dispatch.d.ts +17 -0
- package/dist/web-video-engine/worker-dispatch.d.ts.map +1 -0
- package/dist/web-video-engine/worker-protocol.d.ts +267 -0
- package/dist/web-video-engine/worker-protocol.d.ts.map +1 -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 +4 -3
- package/node_modules/supervision-js-core/dist/index.d.ts.map +1 -1
- package/node_modules/supervision-js-core/dist/index.js +1075 -266
- 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 +179 -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 +78 -2
- 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 +16 -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 +15 -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 +22 -1
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* READ_AHEAD_CANVAS is the playback decode-ahead depth: how many decoded frames
|
|
3
|
+
* the controller keeps queued ahead of the playhead so a decode that overruns a
|
|
4
|
+
* frame interval does not starve the next tick (the cause of stutter even on
|
|
5
|
+
* small, well-encoded clips, where playback otherwise pulls one frame per paint
|
|
6
|
+
* with no cushion). Applies to canvas blits, which are independent and cheap to
|
|
7
|
+
* hold; sample (zero-copy) frames pin a decoder slot each, so the controller
|
|
8
|
+
* keeps those at a depth of one to spare the WebCodecs pool.
|
|
9
|
+
*
|
|
10
|
+
* REANCHOR_STALL_MS is the wall time past which a picture standing still stops
|
|
11
|
+
* being a hitch to work through and becomes a stretch to re-anchor across. Two
|
|
12
|
+
* gaps are measured against it, and they settle in opposite directions.
|
|
13
|
+
*
|
|
14
|
+
* A gap between playing render ticks is a loop nothing was driving, which a
|
|
15
|
+
* hidden tab produces. Nobody was watching, so the clock is the truth and the
|
|
16
|
+
* walk seeks forward onto the playhead.
|
|
17
|
+
*
|
|
18
|
+
* A gap between the walk's deliveries is a pipeline with nothing to show while
|
|
19
|
+
* the loop ran, which a seek onto unbuffered ground produces. The viewer sat
|
|
20
|
+
* through it waiting on a position they asked for, so the frame is the truth
|
|
21
|
+
* and the clock is pulled back onto it. Left to catch up instead, the walk
|
|
22
|
+
* replays the whole wait at decode speed on its way to the playhead: measured
|
|
23
|
+
* against the deployed demo over six seeks, a mean 2.4x for a second, peaking
|
|
24
|
+
* at 24x, with 44 source frames flashed past.
|
|
25
|
+
*
|
|
26
|
+
* Wall time is the reading in both, so a high rate legitimately moving the
|
|
27
|
+
* media clock several frames per gap is not read as an absence.
|
|
28
|
+
*
|
|
29
|
+
* Half a second is where the tick-gap costs cross at 1x. A backlog costs one
|
|
30
|
+
* decode per source frame in it, measured at 240 frames a second on the 30fps
|
|
31
|
+
* demo clip (4.2ms each), against a keyframe-anchored seek at p95 47ms on the
|
|
32
|
+
* same clip: half a second of 30fps backlog is 15 frames, so 63ms of decode
|
|
33
|
+
* against that 47ms, and every higher rate puts more frames in the same gap. It
|
|
34
|
+
* clears the worst legitimate gap of either kind by the same order: a foreground
|
|
35
|
+
* loop leaves a long task or a GC pause to the frame-by-frame path, and forty
|
|
36
|
+
* seconds of network-fed playback of the demo clip held its picture still for at
|
|
37
|
+
* most 51ms.
|
|
38
|
+
*
|
|
39
|
+
* The present cadence is how often playback puts a frame on screen: the rate's
|
|
40
|
+
* whole demand cut to the share of it the machine has been paying for, and never
|
|
41
|
+
* under the source's own frame rate. At a full share the pump declines nothing,
|
|
42
|
+
* which is where a machine with headroom stays at every rate.
|
|
43
|
+
* A step moves the share by PRESENT_CADENCE_STEP, taking a quarter off it when
|
|
44
|
+
* the pipeline has fallen behind the playhead and putting that same quarter back
|
|
45
|
+
* when it has room to spare. The share bottoms out at one over
|
|
46
|
+
* PLAYBACK_RATE.MAX, which is the deepest cut that means anything: below it even
|
|
47
|
+
* the fastest rate asks for less than the source rate the cadence floors at.
|
|
48
|
+
*
|
|
49
|
+
* What takes the share down is a running bill, in frames, between what the clock
|
|
50
|
+
* asked the pipeline for and what the play walk delivered. The bill accumulates
|
|
51
|
+
* rather than being read per tick, which is what tells a shortfall from noise:
|
|
52
|
+
* counting whole frames against a fractional demand leaves every tick out by up
|
|
53
|
+
* to one either way and those cancel, while a machine that cannot sustain the
|
|
54
|
+
* rate falls short every tick and adds up. Measured over 100ms windows on an M3
|
|
55
|
+
* Max at rates 2x to 8x, a pipeline with headroom stayed inside 1.5 frames of
|
|
56
|
+
* its demand either way, so a bill of PRESENT_CADENCE_EVIDENCE_FRAMES frames is
|
|
57
|
+
* one it cannot run up.
|
|
58
|
+
*
|
|
59
|
+
* What puts the share back is the walk holding a frame the clock has not run
|
|
60
|
+
* past, unbroken for the wall time the source takes to produce that many frames.
|
|
61
|
+
* That is the only evidence a pipeline can offer that it has room to spare: a
|
|
62
|
+
* machine at equilibrium delivers exactly what the clock asks for however much
|
|
63
|
+
* headroom it has, so waiting for a surplus in the bill would leave every
|
|
64
|
+
* machine at whatever its worst stretch measured. It is a live reading and the
|
|
65
|
+
* bill is a cumulative one, which is why each takes one direction: ground lost
|
|
66
|
+
* still reads lost once the walk is keeping up again, and catch-up pulls are
|
|
67
|
+
* what carry the walk back onto the playhead.
|
|
68
|
+
*
|
|
69
|
+
* Neither reading is the depth of the decode-ahead queue, which belongs to the
|
|
70
|
+
* decode path and not to the machine: on the zero-copy path, which pins a
|
|
71
|
+
* decoder slot per queued frame and so buffers one, a single frame in hand is
|
|
72
|
+
* full depth and one tick from empty alike.
|
|
73
|
+
*
|
|
74
|
+
* How far behind the machine is therefore sets the pace rather than the size of
|
|
75
|
+
* the step: the bigger the shortfall the sooner the bill reaches that figure and
|
|
76
|
+
* the sooner the next step lands. Zeroing on each step makes the next one gather
|
|
77
|
+
* its own evidence, which is what stops a share sitting at the machine's limit
|
|
78
|
+
* from pulsing.
|
|
79
|
+
*
|
|
80
|
+
* Frames the clock passed, frames the walk delivered and wall time on the
|
|
81
|
+
* playhead: nothing either reading is made of knows what the panel refreshes at,
|
|
82
|
+
* so one machine lands on one cadence on any panel. A faster panel offers more
|
|
83
|
+
* slots and a machine with the headroom fills them; what it cannot do is hold
|
|
84
|
+
* the pump above what the machine pays for, because the share comes down until
|
|
85
|
+
* the pipeline is back on the playhead.
|
|
86
|
+
*
|
|
87
|
+
* PRESENT_CADENCE_SLACK is how far under the interval still counts as a full
|
|
88
|
+
* one. Presents land on display ticks, so a panel refreshing at the ceiling
|
|
89
|
+
* measures each gap as one interval give or take rAF jitter, and an exact
|
|
90
|
+
* comparison would decline every second frame there. A quarter leaves 4.2ms of
|
|
91
|
+
* jitter room at 60Hz.
|
|
92
|
+
*
|
|
93
|
+
* PRESENT_CADENCE_HZ is the demand above which frames the pump culled or
|
|
94
|
+
* declined dominate the dropped-frame ledger, so the discarded-frames rule in
|
|
95
|
+
* evaluateWarnings stands down rather than reading a count it cannot attribute.
|
|
96
|
+
*/
|
|
97
|
+
const PLAYBACK = {
|
|
98
|
+
READ_AHEAD_CANVAS: 3};
|
|
99
|
+
/**
|
|
100
|
+
* Forward playback-rate range the engine accepts. Reverse playback needs a
|
|
101
|
+
* backwards decode strategy the runtime does not have, so zero and negative
|
|
102
|
+
* rates are refused rather than approximated.
|
|
103
|
+
*
|
|
104
|
+
* MAX is an API bound, not a promise that every source plays smoothly there.
|
|
105
|
+
* Sustaining rate r means decoding r x nativeFps frames a second, and the
|
|
106
|
+
* decode-ahead cushion is fixed at PLAYBACK.READ_AHEAD_CANVAS frames (raising it
|
|
107
|
+
* would outrun the CanvasSink pool and tear), so how high a given source really
|
|
108
|
+
* goes is a property of that source's frame size and encode. The engine measures
|
|
109
|
+
* it instead of guessing: DiagnosticsSnapshot carries the commanded rate beside
|
|
110
|
+
* the presented one, and PLAYBACK_RATE_NOT_SUSTAINED fires when they diverge.
|
|
111
|
+
* SUSTAINED_SHORTFALL is the share of the commanded rate the presented one has
|
|
112
|
+
* to hold to count as sustained.
|
|
113
|
+
*/
|
|
114
|
+
const PLAYBACK_RATE = {
|
|
115
|
+
MIN: 0.25,
|
|
116
|
+
MAX: 8,
|
|
117
|
+
SUSTAINED_SHORTFALL: 0.8,
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* CanvasSink frame-pool size: how many decoded canvases the sink recycles
|
|
121
|
+
* round-robin. The pool has no backpressure (a new decode overwrites the oldest
|
|
122
|
+
* slot rather than blocking), and the playback queue hands the raw pool canvas
|
|
123
|
+
* straight to the painter, so the pool must outnumber every canvas outstanding at
|
|
124
|
+
* once: the full play read-ahead, the one in flight, and the one being painted.
|
|
125
|
+
* Sized below that, a fresh decode stomps the pixels of a still-queued frame
|
|
126
|
+
* before it paints (silent tearing). The cache is unaffected; it copies into its
|
|
127
|
+
* own OffscreenCanvas. Derived from the read-ahead so the two cannot drift.
|
|
128
|
+
*/
|
|
129
|
+
const SCRUB = {
|
|
130
|
+
DEFAULT_POOL_SIZE: PLAYBACK.READ_AHEAD_CANVAS + 2,
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Bounds on building a track's frame timeline, the presentation-order table of
|
|
134
|
+
* every frame's timestamp in the container's own integer grain.
|
|
135
|
+
*
|
|
136
|
+
* MAX_FRAMES caps the metadata walk that builds it. A 70-second 30fps source
|
|
137
|
+
* walks 2113 packets in a measured 5.7ms; the cap is four hundred times that,
|
|
138
|
+
* which no ordinary file reaches and a fragmented or endless source does. Past
|
|
139
|
+
* it the load fails, so nothing silently runs without frame identity.
|
|
140
|
+
*
|
|
141
|
+
* FALLBACK_TICK_RATE is for a track backing that cannot state its grain. A
|
|
142
|
+
* microsecond is the finest timestamp WebCodecs carries, so no real timestamp is
|
|
143
|
+
* lost at that rate; what is lost is the guarantee that every timestamp is a
|
|
144
|
+
* whole tick.
|
|
145
|
+
*/
|
|
146
|
+
const FRAME_TIMELINE = {
|
|
147
|
+
MAX_FRAMES: 1_000_000,
|
|
148
|
+
FALLBACK_TICK_RATE: 1e6,
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* Diagnostics instrument tunables. Inert unless a consumer opts in: the worker
|
|
152
|
+
* broadcasts a snapshot at BROADCAST_HZ only while subscribed, the trace rings
|
|
153
|
+
* allocate only while armed, and SCRUB_LATENCY_RING bounds the percentile sample.
|
|
154
|
+
*/
|
|
155
|
+
const DIAGNOSTICS = {
|
|
156
|
+
BROADCAST_HZ: 10,
|
|
157
|
+
TRACE_EVENT_CAP: 2000,
|
|
158
|
+
TRACE_SNAPSHOT_CAP: 600,
|
|
159
|
+
SCRUB_LATENCY_RING: 64,
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* What an armed capture actually keeps. The snapshot ring is fed at the fixed
|
|
163
|
+
* broadcast rate, so its capacity converts to a wall-clock window; the event
|
|
164
|
+
* ring is fed by paints and gestures at no fixed rate, so its bound is a count
|
|
165
|
+
* and nothing more. A readout that states one number for "the capture" is
|
|
166
|
+
* describing neither ring.
|
|
167
|
+
*/
|
|
168
|
+
const TRACE_RING_BOUNDS = {
|
|
169
|
+
snapshotWindowMs: (DIAGNOSTICS.TRACE_SNAPSHOT_CAP / DIAGNOSTICS.BROADCAST_HZ) * 1000,
|
|
170
|
+
snapshotCap: DIAGNOSTICS.TRACE_SNAPSHOT_CAP,
|
|
171
|
+
eventCap: DIAGNOSTICS.TRACE_EVENT_CAP,
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* Hang-recovery bounds for the worker video runtime. mediabunny's getCanvas/
|
|
175
|
+
* getSample take no AbortSignal, so a decode that never settles cannot be
|
|
176
|
+
* cancelled. These two timeouts bound the damage: a decode that outruns its
|
|
177
|
+
* ceiling is abandoned and its provider rebuilt, and a main-thread caller
|
|
178
|
+
* blocked on a wedged worker surfaces an error.
|
|
179
|
+
*
|
|
180
|
+
* DECODE_HANG_TIMEOUT_MS bounds a random-access decode operation, not a single
|
|
181
|
+
* frame. A seek or a play-start lands mid-GOP and decodes the whole
|
|
182
|
+
* keyframe-to-target prefix, so an 8-second GOP of 8MP frames legitimately runs
|
|
183
|
+
* tens of seconds. A ceiling sized for one frame fires on healthy progress and
|
|
184
|
+
* kills the decode it exists to protect.
|
|
185
|
+
*
|
|
186
|
+
* SEED_HANG_TIMEOUT_MS bounds the first-frame seed alone, which is why it is a
|
|
187
|
+
* fraction of the figure above: the seed anchors on the track's own first
|
|
188
|
+
* sample, so it walks no GOP prefix, and the one cost it carries that a later
|
|
189
|
+
* decode does not is the decoder's cold hardware configuration. A re-anchored
|
|
190
|
+
* decode of a 2840x2840 source measured 49ms mean / 80ms worst, so this leaves
|
|
191
|
+
* two orders of magnitude of headroom over the decode plus its cold start, and
|
|
192
|
+
* SEED_DECODE_ATTEMPTS of it still finish inside WORKER_COMMAND_TIMEOUT_MS with
|
|
193
|
+
* the rebuilds between them. That is what lets a decoder which never starts
|
|
194
|
+
* reach the caller as an error rather than as the facade giving up.
|
|
195
|
+
*
|
|
196
|
+
* That budget is the mediabunny sink paths', which carry no ceiling of their
|
|
197
|
+
* own. The long-lived decode session bounds its own wait for output more
|
|
198
|
+
* tightly and can tell a decoder that never started from one that went quiet
|
|
199
|
+
* after working, so on that path the seed ends on the session's word and these
|
|
200
|
+
* attempts go unspent.
|
|
201
|
+
*
|
|
202
|
+
* WORKER_COMMAND_TIMEOUT_MS is the main-thread backstop for an awaitable command
|
|
203
|
+
* (load, commit, step). It derives from the decode ceiling so the two cannot
|
|
204
|
+
* drift: the worker has to be able to reach its own hang path, recover, and
|
|
205
|
+
* reply before the facade gives up on it.
|
|
206
|
+
*/
|
|
207
|
+
const DECODE_HANG_TIMEOUT_MS = 30_000;
|
|
208
|
+
const HANG_RECOVERY = {
|
|
209
|
+
WORKER_COMMAND_TIMEOUT_MS: DECODE_HANG_TIMEOUT_MS + 15_000,
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
const asSec = (n) => n;
|
|
213
|
+
const asFps = (n) => n;
|
|
214
|
+
const asPaintSeq = (n) => n;
|
|
215
|
+
var SourceKind;
|
|
216
|
+
(function (SourceKind) {
|
|
217
|
+
SourceKind["Url"] = "url";
|
|
218
|
+
SourceKind["Blob"] = "blob";
|
|
219
|
+
SourceKind["Stream"] = "stream";
|
|
220
|
+
})(SourceKind || (SourceKind = {}));
|
|
221
|
+
/**
|
|
222
|
+
* Coarse-grained engine status. Updates rarely (load, play, pause, end,
|
|
223
|
+
* error). Sits on its own emit channel so subscribers do not wake up on
|
|
224
|
+
* 60Hz time ticks.
|
|
225
|
+
*/
|
|
226
|
+
var PlaybackStatus;
|
|
227
|
+
(function (PlaybackStatus) {
|
|
228
|
+
PlaybackStatus["Idle"] = "IDLE";
|
|
229
|
+
PlaybackStatus["Loading"] = "LOADING";
|
|
230
|
+
PlaybackStatus["Ready"] = "READY";
|
|
231
|
+
PlaybackStatus["Playing"] = "PLAYING";
|
|
232
|
+
PlaybackStatus["Paused"] = "PAUSED";
|
|
233
|
+
PlaybackStatus["Seeking"] = "SEEKING";
|
|
234
|
+
PlaybackStatus["Ended"] = "ENDED";
|
|
235
|
+
PlaybackStatus["Errored"] = "ERRORED";
|
|
236
|
+
})(PlaybackStatus || (PlaybackStatus = {}));
|
|
237
|
+
var VideoEngineErrorCode;
|
|
238
|
+
(function (VideoEngineErrorCode) {
|
|
239
|
+
VideoEngineErrorCode["DecodeUnsupported"] = "DECODE_UNSUPPORTED";
|
|
240
|
+
VideoEngineErrorCode["SourceUnreadable"] = "SOURCE_UNREADABLE";
|
|
241
|
+
/**
|
|
242
|
+
* The demuxer refused the file outright: its container is not one this build
|
|
243
|
+
* reads, so no track was ever listed and no decoder was ever asked.
|
|
244
|
+
*/
|
|
245
|
+
VideoEngineErrorCode["ContainerUnreadable"] = "CONTAINER_UNREADABLE";
|
|
246
|
+
/**
|
|
247
|
+
* The container opened and the demuxer parsed no track at all out of it. The
|
|
248
|
+
* file's streams are in formats it does not carry, so their video cannot be
|
|
249
|
+
* reached even though it is there.
|
|
250
|
+
*/
|
|
251
|
+
VideoEngineErrorCode["VideoTrackUnreadable"] = "VIDEO_TRACK_UNREADABLE";
|
|
252
|
+
/**
|
|
253
|
+
* The container opened, its tracks listed, and none of them is video. This
|
|
254
|
+
* is the only case where the file itself is what lacks video.
|
|
255
|
+
*/
|
|
256
|
+
VideoEngineErrorCode["NoVideoTrack"] = "NO_VIDEO_TRACK";
|
|
257
|
+
VideoEngineErrorCode["BackendCrashed"] = "BACKEND_CRASHED";
|
|
258
|
+
VideoEngineErrorCode["Aborted"] = "ABORTED";
|
|
259
|
+
/** A canvas was offered to an engine loaded in "frames" presentation mode,
|
|
260
|
+
* where the host owns the only canvas. */
|
|
261
|
+
VideoEngineErrorCode["PresentationMismatch"] = "PRESENTATION_MISMATCH";
|
|
262
|
+
/**
|
|
263
|
+
* The decoder cannot decode this source at all: it refused to configure, it
|
|
264
|
+
* errored, or it acknowledged decode requests and never produced a frame.
|
|
265
|
+
* Distinct from BackendCrashed, which a rebuild can recover; this one
|
|
266
|
+
* survives every rebuild, so the runtime stops rebuilding and says so. The
|
|
267
|
+
* usual cause is outside the page: another tab holding every hardware
|
|
268
|
+
* decoder session the machine has.
|
|
269
|
+
*/
|
|
270
|
+
VideoEngineErrorCode["DecoderStalled"] = "DECODER_STALLED";
|
|
271
|
+
/** A playback rate outside the forward range the engine supports. */
|
|
272
|
+
VideoEngineErrorCode["RateUnsupported"] = "RATE_UNSUPPORTED";
|
|
273
|
+
})(VideoEngineErrorCode || (VideoEngineErrorCode = {}));
|
|
274
|
+
/**
|
|
275
|
+
* Thrown by createScrubCursor / VideoEngine.load when decode is unsupported
|
|
276
|
+
* or the source is unreadable. Branch on `error.code` (VideoEngineErrorCode)
|
|
277
|
+
* to differentiate decode failures from network failures.
|
|
278
|
+
*/
|
|
279
|
+
class VideoEngineError extends Error {
|
|
280
|
+
code;
|
|
281
|
+
cause;
|
|
282
|
+
constructor(code, message, cause) {
|
|
283
|
+
super(message);
|
|
284
|
+
this.code = code;
|
|
285
|
+
this.cause = cause;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
/** Shared by the facade and the core so a host gets the same refusal wherever
|
|
289
|
+
* its canvas is caught. */
|
|
290
|
+
function canvasBindingRefused() {
|
|
291
|
+
return new VideoEngineError(VideoEngineErrorCode.PresentationMismatch, 'presentation "frames" leaves the canvas to the host: this engine paints nothing and hands out VideoFrames instead');
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Validates a requested playback rate and returns it. The facade and the core
|
|
295
|
+
* both call it, so a rate is refused at whichever boundary it arrives at and
|
|
296
|
+
* with the same message: the facade posts fire-and-forget, so a refusal raised
|
|
297
|
+
* only in the worker would reach nobody.
|
|
298
|
+
*
|
|
299
|
+
* Reverse is rejected, not clamped: backwards playback is a different decode
|
|
300
|
+
* problem, and a -1 quietly serviced as +0.25 plays the wrong direction while
|
|
301
|
+
* reporting success.
|
|
302
|
+
*/
|
|
303
|
+
function resolvePlaybackRate(rate) {
|
|
304
|
+
if (!Number.isFinite(rate) ||
|
|
305
|
+
rate < PLAYBACK_RATE.MIN ||
|
|
306
|
+
rate > PLAYBACK_RATE.MAX) {
|
|
307
|
+
throw new VideoEngineError(VideoEngineErrorCode.RateUnsupported, `playback rate ${rate} is outside the supported forward range ${PLAYBACK_RATE.MIN}-${PLAYBACK_RATE.MAX}; reverse playback is not supported`);
|
|
308
|
+
}
|
|
309
|
+
return rate;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Decode-resolution strategies. A strategy decides the pixel width each video
|
|
314
|
+
* frame is decoded to, independent of the source's native resolution. Height
|
|
315
|
+
* follows from native aspect, so a strategy only ever returns a width.
|
|
316
|
+
*
|
|
317
|
+
* Decoding below native trades preview sharpness for paint cost and frame-cache
|
|
318
|
+
* memory. It does NOT cut decode cost: the codec decodes the full coded frame
|
|
319
|
+
* regardless of target width, and CanvasSink resizes the result afterward. The
|
|
320
|
+
* win scales with the gap between source resolution and the on-screen box: a 4K
|
|
321
|
+
* source shown in a 640px surface still pays full 4K decode, but the smaller
|
|
322
|
+
* surface cuts the per-frame paint work and the cached blit size.
|
|
323
|
+
*
|
|
324
|
+
* A strategy applies wherever frames decode through this seam: the live scrub
|
|
325
|
+
* surface and the analysis / extraction path alike. AnalysisSession decodes at
|
|
326
|
+
* whatever strategy it is given (native when omitted), so a thumbnail pass can
|
|
327
|
+
* cache a small blit instead of a native-size one.
|
|
328
|
+
*/
|
|
329
|
+
/** Decode at native resolution. The conservative default. */
|
|
330
|
+
function nativeResolution() {
|
|
331
|
+
return { kind: "native" };
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Decode at the on-screen size: canvas CSS width times devicePixelRatio. Best
|
|
335
|
+
* for fixed-size surfaces fed by a much larger source (frame sampler, inline
|
|
336
|
+
* players). Falls back to native while the box is unmeasured.
|
|
337
|
+
*
|
|
338
|
+
* The box it reads is the one bindCanvas measures, so this strategy resolves to
|
|
339
|
+
* native under presentation "frames", where the engine holds no canvas and
|
|
340
|
+
* nothing ever measures one. A frames-mode consumer passes displayBoxResolution
|
|
341
|
+
* instead.
|
|
342
|
+
*/
|
|
343
|
+
function viewportResolution(options = {}) {
|
|
344
|
+
return {
|
|
345
|
+
kind: "viewport",
|
|
346
|
+
maxDevicePixelRatio: options.maxDevicePixelRatio ?? 2,
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Decode at no more than maxWidth regardless of display size. For consumers
|
|
351
|
+
* with a hard throughput or memory ceiling (batch surfaces, thumbnail farms).
|
|
352
|
+
*/
|
|
353
|
+
function cappedResolution(maxWidth) {
|
|
354
|
+
return { kind: "capped", maxWidth };
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Decode at the size the frame will actually occupy inside a box the consumer
|
|
358
|
+
* describes: native aspect fitted into boxWidth x boxHeight, times the clamped
|
|
359
|
+
* device pixel ratio. Letterboxing is why the box is two numbers and not one,
|
|
360
|
+
* since a portrait source in a landscape box paints far narrower than the box.
|
|
361
|
+
*
|
|
362
|
+
* This is the strategy for presentation "frames". There the consumer owns the
|
|
363
|
+
* compositor, so it is the only side that knows the box, and viewportResolution
|
|
364
|
+
* has nothing to read.
|
|
365
|
+
*/
|
|
366
|
+
function displayBoxResolution(options) {
|
|
367
|
+
return {
|
|
368
|
+
kind: "displayBox",
|
|
369
|
+
boxWidth: options.boxWidth,
|
|
370
|
+
boxHeight: options.boxHeight,
|
|
371
|
+
devicePixelRatio: options.devicePixelRatio,
|
|
372
|
+
maxDevicePixelRatio: options.maxDevicePixelRatio ?? 2,
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
/** Runs the descriptor against a context to produce a target decode width. */
|
|
376
|
+
function strategyWidth(strategy, ctx) {
|
|
377
|
+
switch (strategy.kind) {
|
|
378
|
+
case "native":
|
|
379
|
+
return ctx.nativeWidth;
|
|
380
|
+
case "viewport": {
|
|
381
|
+
if (ctx.displayWidth === null || ctx.displayWidth <= 0)
|
|
382
|
+
return ctx.nativeWidth;
|
|
383
|
+
const dpr = clampDpr(ctx.devicePixelRatio, strategy.maxDevicePixelRatio);
|
|
384
|
+
return Math.ceil(ctx.displayWidth * dpr);
|
|
385
|
+
}
|
|
386
|
+
case "capped":
|
|
387
|
+
return Math.min(strategy.maxWidth, ctx.nativeWidth);
|
|
388
|
+
case "displayBox": {
|
|
389
|
+
const { boxWidth, boxHeight } = strategy;
|
|
390
|
+
if (!(boxWidth > 0) || !(boxHeight > 0))
|
|
391
|
+
return ctx.nativeWidth;
|
|
392
|
+
const fit = Math.min(boxWidth / ctx.nativeWidth, boxHeight / ctx.nativeHeight);
|
|
393
|
+
const dpr = clampDpr(strategy.devicePixelRatio, strategy.maxDevicePixelRatio);
|
|
394
|
+
return Math.ceil(ctx.nativeWidth * fit * dpr);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Runs a strategy and returns native-bounded, aspect-preserving integer
|
|
400
|
+
* dimensions safe to hand to CanvasSink and to size a canvas backing store.
|
|
401
|
+
* A strategy that returns garbage (non-finite, non-positive) falls back to
|
|
402
|
+
* native rather than producing a broken surface.
|
|
403
|
+
*/
|
|
404
|
+
function resolveDecodeDimensions(strategy, ctx) {
|
|
405
|
+
const nativeWidth = Math.max(1, Math.round(ctx.nativeWidth));
|
|
406
|
+
const nativeHeight = Math.max(1, Math.round(ctx.nativeHeight));
|
|
407
|
+
const raw = strategyWidth(strategy, ctx);
|
|
408
|
+
const width = Number.isFinite(raw) && raw > 0
|
|
409
|
+
? Math.min(Math.round(raw), nativeWidth)
|
|
410
|
+
: nativeWidth;
|
|
411
|
+
const height = Math.max(1, Math.round((width * nativeHeight) / nativeWidth));
|
|
412
|
+
return { width, height };
|
|
413
|
+
}
|
|
414
|
+
function clampDpr(dpr, maxDpr) {
|
|
415
|
+
if (!Number.isFinite(dpr) || dpr <= 0)
|
|
416
|
+
return 1;
|
|
417
|
+
return Math.min(dpr, maxDpr);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* One entry per presentation instant.
|
|
422
|
+
*
|
|
423
|
+
* A container may carry several coded pictures on one timestamp, and they
|
|
424
|
+
* occupy no time between them: a decode for that instant answers with a single
|
|
425
|
+
* picture, so the rest are frames no reader can reach or name. Counting them
|
|
426
|
+
* would leave a step across the group moving the picture nowhere, and a search
|
|
427
|
+
* for a time inside it answering with the group's last entry whatever it was
|
|
428
|
+
* asked.
|
|
429
|
+
*/
|
|
430
|
+
function oneEntryPerInstant(data) {
|
|
431
|
+
const { ticks } = data;
|
|
432
|
+
let at = 1;
|
|
433
|
+
while (at < ticks.length && ticks[at] !== ticks[at - 1])
|
|
434
|
+
at += 1;
|
|
435
|
+
if (at === ticks.length)
|
|
436
|
+
return data;
|
|
437
|
+
const distinct = new Float64Array(ticks.length);
|
|
438
|
+
distinct.set(ticks.subarray(0, at));
|
|
439
|
+
let size = at;
|
|
440
|
+
for (let i = at + 1; i < ticks.length; i += 1) {
|
|
441
|
+
if (ticks[i] === distinct[size - 1])
|
|
442
|
+
continue;
|
|
443
|
+
distinct[size] = ticks[i];
|
|
444
|
+
size += 1;
|
|
445
|
+
}
|
|
446
|
+
return { ...data, ticks: distinct.slice(0, size) };
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Every real frame of one track, in presentation order, by its container tick
|
|
450
|
+
* timestamp.
|
|
451
|
+
*
|
|
452
|
+
* A container states its timestamps as integer multiples of 1/tickRate, so a
|
|
453
|
+
* frame's tick count is exact and comparisons between two readers of the same
|
|
454
|
+
* container are integer comparisons. `timeAt` is the same division of the same
|
|
455
|
+
* two integers the demuxer itself performs, which is what lets a consumer
|
|
456
|
+
* holding only seconds match a producer's frame with `===`.
|
|
457
|
+
*/
|
|
458
|
+
class FrameTimeline {
|
|
459
|
+
data;
|
|
460
|
+
ticksArray;
|
|
461
|
+
constructor(data) {
|
|
462
|
+
this.data = data;
|
|
463
|
+
this.ticksArray = data.ticks;
|
|
464
|
+
}
|
|
465
|
+
static from(data) {
|
|
466
|
+
if (data.ticks.length === 0) {
|
|
467
|
+
throw new RangeError("FrameTimeline: a track with no frames has no timeline");
|
|
468
|
+
}
|
|
469
|
+
if (!(data.tickRate > 0)) {
|
|
470
|
+
throw new RangeError(`FrameTimeline: tick rate ${data.tickRate} is not positive`);
|
|
471
|
+
}
|
|
472
|
+
return new FrameTimeline(oneEntryPerInstant(data));
|
|
473
|
+
}
|
|
474
|
+
/** A synthetic constant-rate table. Tests and fakes only. The default tick
|
|
475
|
+
* rate is a whole multiple of `fps`, so no test table needs rounding. */
|
|
476
|
+
static uniform(fps, frameCount, tickRate = fps * 1000) {
|
|
477
|
+
const step = tickRate / fps;
|
|
478
|
+
const ticks = Float64Array.from({ length: frameCount }, (_, index) => index * step);
|
|
479
|
+
return FrameTimeline.from({ lastDurationTicks: step, tickRate, ticks });
|
|
480
|
+
}
|
|
481
|
+
get tickRate() {
|
|
482
|
+
return this.data.tickRate;
|
|
483
|
+
}
|
|
484
|
+
get frameCount() {
|
|
485
|
+
return this.ticksArray.length;
|
|
486
|
+
}
|
|
487
|
+
toData() {
|
|
488
|
+
return this.data;
|
|
489
|
+
}
|
|
490
|
+
ticksAt(index) {
|
|
491
|
+
return this.ticksArray[this.clampIndex(index)];
|
|
492
|
+
}
|
|
493
|
+
timeAt(index) {
|
|
494
|
+
return asSec(this.ticksAt(index) / this.data.tickRate);
|
|
495
|
+
}
|
|
496
|
+
idAt(index) {
|
|
497
|
+
const at = this.clampIndex(index);
|
|
498
|
+
return { index: at, ticks: this.ticksArray[at] };
|
|
499
|
+
}
|
|
500
|
+
landingAt(index) {
|
|
501
|
+
const at = this.clampIndex(index);
|
|
502
|
+
return { frame: this.idAt(at), mediaTimeS: this.timeAt(at) };
|
|
503
|
+
}
|
|
504
|
+
/** Ticks the frame at `index` ends at, which is where the next one starts. */
|
|
505
|
+
endTicksAt(index) {
|
|
506
|
+
const at = this.clampIndex(index);
|
|
507
|
+
return at + 1 < this.ticksArray.length
|
|
508
|
+
? this.ticksArray[at + 1]
|
|
509
|
+
: this.ticksArray[at] + this.data.lastDurationTicks;
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* The frame covering `timeS`, which is what a decode for it returns.
|
|
513
|
+
*
|
|
514
|
+
* The comparison divides, as `timeAt` does, so a frame's own published
|
|
515
|
+
* second answers with that frame.
|
|
516
|
+
*/
|
|
517
|
+
indexAtOrBefore(timeS) {
|
|
518
|
+
let low = 0;
|
|
519
|
+
let high = this.ticksArray.length - 1;
|
|
520
|
+
let found = 0;
|
|
521
|
+
while (low <= high) {
|
|
522
|
+
const mid = (low + high) >> 1;
|
|
523
|
+
if (this.ticksArray[mid] / this.data.tickRate <= timeS) {
|
|
524
|
+
found = mid;
|
|
525
|
+
low = mid + 1;
|
|
526
|
+
}
|
|
527
|
+
else {
|
|
528
|
+
high = mid - 1;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
return found;
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* The frame a decoded sample is.
|
|
535
|
+
*
|
|
536
|
+
* A decoded timestamp has been through the WebCodecs microsecond plane, so
|
|
537
|
+
* it can miss its own tick by up to half a microsecond. Snapping to the
|
|
538
|
+
* nearer neighbour absorbs that by four orders of magnitude, since the
|
|
539
|
+
* narrowest real frame gap measured across the fixtures is 31667 us.
|
|
540
|
+
*/
|
|
541
|
+
indexOfDecoded(timeS) {
|
|
542
|
+
const wanted = Math.round(timeS * this.data.tickRate);
|
|
543
|
+
const at = this.indexAtOrBefore(wanted / this.data.tickRate);
|
|
544
|
+
const next = at + 1;
|
|
545
|
+
if (next >= this.ticksArray.length)
|
|
546
|
+
return at;
|
|
547
|
+
return wanted - this.ticksArray[at] <= this.ticksArray[next] - wanted
|
|
548
|
+
? at
|
|
549
|
+
: next;
|
|
550
|
+
}
|
|
551
|
+
clampIndex(index) {
|
|
552
|
+
if (index < 0)
|
|
553
|
+
return 0;
|
|
554
|
+
const last = this.ticksArray.length - 1;
|
|
555
|
+
return index > last ? last : index;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
export { DIAGNOSTICS as D, FRAME_TIMELINE as F, HANG_RECOVERY as H, PlaybackStatus as P, SCRUB as S, TRACE_RING_BOUNDS as T, VideoEngineError as V, VideoEngineErrorCode as a, asSec as b, SourceKind as c, FrameTimeline as d, asPaintSeq as e, canvasBindingRefused as f, resolvePlaybackRate as g, PLAYBACK_RATE as h, asFps as i, cappedResolution as j, displayBoxResolution as k, nativeResolution as n, resolveDecodeDimensions as r, viewportResolution as v };
|
|
560
|
+
//# sourceMappingURL=frame-timeline-GINI8Gum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame-timeline-GINI8Gum.js","sources":["../src/constants.ts","../src/types.ts","../src/decode-resolution.ts","../src/frame-timeline.ts"],"sourcesContent":[null,null,null,null],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { type Sec } from "./types";
|
|
2
|
+
/** Ticks per second, from the container's own timing grain. */
|
|
3
|
+
export type TickRate = number;
|
|
4
|
+
/**
|
|
5
|
+
* A frame of the source, named twice: by its position in presentation order and
|
|
6
|
+
* by its presentation timestamp in the track's own integer grain.
|
|
7
|
+
*/
|
|
8
|
+
export interface FrameId {
|
|
9
|
+
readonly index: number;
|
|
10
|
+
readonly ticks: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Where the transport has settled: the frame, and the one seconds value anyone
|
|
14
|
+
* publishes for it. Nothing else on the wire carries a media position.
|
|
15
|
+
*/
|
|
16
|
+
export interface FrameLanding {
|
|
17
|
+
readonly frame: FrameId;
|
|
18
|
+
readonly mediaTimeS: number;
|
|
19
|
+
}
|
|
20
|
+
/** The clone-safe shape the timeline crosses a worker boundary as. */
|
|
21
|
+
export interface FrameTimelineData {
|
|
22
|
+
readonly tickRate: TickRate;
|
|
23
|
+
readonly ticks: Float64Array;
|
|
24
|
+
readonly lastDurationTicks: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Every real frame of one track, in presentation order, by its container tick
|
|
28
|
+
* timestamp.
|
|
29
|
+
*
|
|
30
|
+
* A container states its timestamps as integer multiples of 1/tickRate, so a
|
|
31
|
+
* frame's tick count is exact and comparisons between two readers of the same
|
|
32
|
+
* container are integer comparisons. `timeAt` is the same division of the same
|
|
33
|
+
* two integers the demuxer itself performs, which is what lets a consumer
|
|
34
|
+
* holding only seconds match a producer's frame with `===`.
|
|
35
|
+
*/
|
|
36
|
+
export declare class FrameTimeline {
|
|
37
|
+
private readonly data;
|
|
38
|
+
private readonly ticksArray;
|
|
39
|
+
private constructor();
|
|
40
|
+
static from(data: FrameTimelineData): FrameTimeline;
|
|
41
|
+
/** A synthetic constant-rate table. Tests and fakes only. The default tick
|
|
42
|
+
* rate is a whole multiple of `fps`, so no test table needs rounding. */
|
|
43
|
+
static uniform(fps: number, frameCount: number, tickRate?: TickRate): FrameTimeline;
|
|
44
|
+
get tickRate(): TickRate;
|
|
45
|
+
get frameCount(): number;
|
|
46
|
+
toData(): FrameTimelineData;
|
|
47
|
+
ticksAt(index: number): number;
|
|
48
|
+
timeAt(index: number): Sec;
|
|
49
|
+
idAt(index: number): FrameId;
|
|
50
|
+
landingAt(index: number): FrameLanding;
|
|
51
|
+
/** Ticks the frame at `index` ends at, which is where the next one starts. */
|
|
52
|
+
endTicksAt(index: number): number;
|
|
53
|
+
/**
|
|
54
|
+
* The frame covering `timeS`, which is what a decode for it returns.
|
|
55
|
+
*
|
|
56
|
+
* The comparison divides, as `timeAt` does, so a frame's own published
|
|
57
|
+
* second answers with that frame.
|
|
58
|
+
*/
|
|
59
|
+
indexAtOrBefore(timeS: number): number;
|
|
60
|
+
/**
|
|
61
|
+
* The frame a decoded sample is.
|
|
62
|
+
*
|
|
63
|
+
* A decoded timestamp has been through the WebCodecs microsecond plane, so
|
|
64
|
+
* it can miss its own tick by up to half a microsecond. Snapping to the
|
|
65
|
+
* nearer neighbour absorbs that by four orders of magnitude, since the
|
|
66
|
+
* narrowest real frame gap measured across the fixtures is 31667 us.
|
|
67
|
+
*/
|
|
68
|
+
indexOfDecoded(timeS: number): number;
|
|
69
|
+
private clampIndex;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=frame-timeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame-timeline.d.ts","sourceRoot":"","sources":["../src/frame-timeline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,GAAG,EAAE,MAAM,SAAS,CAAC;AAE1C,+DAA+D;AAC/D,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE9B;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,sEAAsE;AACtE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACpC;AA4BD;;;;;;;;;GASG;AACH,qBAAa,aAAa;IAGJ,OAAO,CAAC,QAAQ,CAAC,IAAI;IAFzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAe;IAE1C,OAAO;IAIP,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,iBAAiB,GAAG,aAAa;IAcnD;8EAC0E;IAC1E,MAAM,CAAC,OAAO,CACZ,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,QAAQ,GAAE,QAAqB,GAC9B,aAAa;IAShB,IAAI,QAAQ,IAAI,QAAQ,CAEvB;IAED,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,MAAM,IAAI,iBAAiB;IAI3B,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAI9B,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG;IAI1B,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAK5B,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY;IAKtC,8EAA8E;IAC9E,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAOjC;;;;;OAKG;IACH,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAgBtC;;;;;;;OAOG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAUrC,OAAO,CAAC,UAAU;CAKnB"}
|