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