@ksp-gonogo/kerbcast 1.11.0-rc.4 → 1.11.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/README.md +72 -0
- package/dist/__generated__/types.d.ts +40 -2
- package/dist/__generated__/types.js +11 -0
- package/dist/client.d.ts +111 -2
- package/dist/client.js +300 -7
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/testing/index.js +23 -1
- package/package.json +1 -1
- package/src/__generated__/types.ts +38 -2
- package/src/client.test.ts +309 -1
- package/src/client.ts +397 -7
- package/src/index.ts +7 -0
- package/src/testing/index.ts +24 -1
- package/src/testing.test.ts +49 -1
package/README.md
CHANGED
|
@@ -63,6 +63,11 @@ Commands can be sent as soon as `connect` resolves. Any sent before the
|
|
|
63
63
|
control channel has opened wait for it, and reject if it has not opened
|
|
64
64
|
within 10 s or the client disconnects first.
|
|
65
65
|
|
|
66
|
+
Kerbcast streams H.264 only. A browser that offers none (some Firefox builds
|
|
67
|
+
ship without OpenH264) is refused, and `connect` rejects with an
|
|
68
|
+
`OfferRefusedError` whose `code` is `ErrorCode.CodecUnsupported` and whose
|
|
69
|
+
message says what to change.
|
|
70
|
+
|
|
66
71
|
### Pre-handshake discovery
|
|
67
72
|
|
|
68
73
|
```ts
|
|
@@ -89,6 +94,65 @@ const setLayers: ClientMessage = {
|
|
|
89
94
|
controlChannel.send(JSON.stringify(setLayers));
|
|
90
95
|
```
|
|
91
96
|
|
|
97
|
+
### Encoded-frame transforms
|
|
98
|
+
|
|
99
|
+
`cam.setEncodedTransform(factory)` runs your transform on a camera's encoded
|
|
100
|
+
frames before the browser decodes them. It always runs before Kerbcast's
|
|
101
|
+
static and frame lock, so anything it does (holding frames back, dropping
|
|
102
|
+
them) shows up in `cam.mediaStream` with the static still drawn on top.
|
|
103
|
+
|
|
104
|
+
Kerbcast installs the transform on whichever receiver carries the camera. A
|
|
105
|
+
transform instance works on one receiver only, so you pass a factory:
|
|
106
|
+
Kerbcast calls it for a fresh instance when the camera is bound, again when a
|
|
107
|
+
slot rebind moves the camera to another receiver, and again after a
|
|
108
|
+
reconnect. A receiver the camera leaves goes back to passthrough, and frames
|
|
109
|
+
the old instance still holds are dropped. `setEncodedTransform(null)`
|
|
110
|
+
detaches. It works in both legacy and dynamic slot modes.
|
|
111
|
+
|
|
112
|
+
It needs `encodedTransforms: true` when the client is constructed, and
|
|
113
|
+
`setEncodedTransform` throws without it. The option gives every receiver a
|
|
114
|
+
passthrough transform from the start, because Chrome only honours a receiver
|
|
115
|
+
transform that was in place before negotiation. It costs a worker hop per
|
|
116
|
+
frame for every camera, so leave it off unless you use this. The passthrough
|
|
117
|
+
worker loads from a `blob:` URL, so a Content Security Policy must allow
|
|
118
|
+
`worker-src blob:`. `setEncodedTransform` also throws when the browser has no
|
|
119
|
+
install path; `client.encodedTransformPath` reports which one you will get:
|
|
120
|
+
|
|
121
|
+
- `"script"`: return an `RTCRtpScriptTransform` (Chrome, Safari and Firefox)
|
|
122
|
+
- `"streams"`: return a `TransformStream` of `RTCEncodedVideoFrame`, run on the main thread over `createEncodedStreams()` (older Chrome)
|
|
123
|
+
|
|
124
|
+
A one-second delay on the `"script"` path:
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
const client = new KerbcastClient({ host, port, encodedTransforms: true });
|
|
128
|
+
const worker = new Worker(new URL("./delay-worker.js", import.meta.url));
|
|
129
|
+
|
|
130
|
+
client.camera(2592004302).setEncodedTransform(({ flightId, path }) =>
|
|
131
|
+
path === "script"
|
|
132
|
+
? new RTCRtpScriptTransform(worker, { flightId, delayMs: 1000 })
|
|
133
|
+
: delayStream(1000),
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
// delay-worker.js
|
|
137
|
+
onrtctransform = ({ transformer }) => {
|
|
138
|
+
const { delayMs } = transformer.options;
|
|
139
|
+
transformer.readable
|
|
140
|
+
.pipeThrough(
|
|
141
|
+
new TransformStream({
|
|
142
|
+
transform(frame, controller) {
|
|
143
|
+
setTimeout(() => controller.enqueue(frame), delayMs);
|
|
144
|
+
},
|
|
145
|
+
}),
|
|
146
|
+
)
|
|
147
|
+
.pipeTo(transformer.writable)
|
|
148
|
+
.catch(() => {}); // a replaced instance is aborted
|
|
149
|
+
};
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
`delayStream` is the same `TransformStream` built on the main thread. A
|
|
153
|
+
factory that throws, or returns the wrong kind for the path, is reported as a
|
|
154
|
+
client `error` event carrying the camera's `flightId`.
|
|
155
|
+
|
|
92
156
|
## Per-camera capabilities
|
|
93
157
|
|
|
94
158
|
`CameraState` includes capability flags so consumers render only the
|
|
@@ -291,6 +355,14 @@ await client.setCommandAim(hill.flightId, null);
|
|
|
291
355
|
A station watching a craft is the same with
|
|
292
356
|
`{ kind: CommandVantageKind.Station, station: "KSC" }` and a `vessel` aim.
|
|
293
357
|
|
|
358
|
+
A `vessel` aim, or an `orbit` or `positionAt` aim's `subjectPersistentId`,
|
|
359
|
+
must name a craft in the camera's `commandCentre.targets`. One that is not
|
|
360
|
+
there (a craft merged into another by docking, or destroyed) makes
|
|
361
|
+
`setCommandAim` reject with a `CommandTargetUnknownError`; a call that races
|
|
362
|
+
the list changing comes back as an `error` event with code
|
|
363
|
+
`ErrorCode.CommandTargetUnknown`. Before the game has reported the camera's
|
|
364
|
+
list, the aim is sent and the game decides.
|
|
365
|
+
|
|
294
366
|
### The command lock
|
|
295
367
|
|
|
296
368
|
A mod in game can take a lock on every command camera's aim
|
|
@@ -362,6 +362,15 @@ export interface CameraState {
|
|
|
362
362
|
*/
|
|
363
363
|
operatorWidth: number;
|
|
364
364
|
operatorHeight: number;
|
|
365
|
+
/**
|
|
366
|
+
* Configured capture size: the most this camera renders at (settings.cfg
|
|
367
|
+
* `MaxQuality` or `Width`/`Height`, or a kerbal face camera's square
|
|
368
|
+
* ring). Its aspect is the feed's shape: auto-resolution picks a size at
|
|
369
|
+
* this aspect and never follows the viewer's box. Absent from a sidecar
|
|
370
|
+
* that predates the field.
|
|
371
|
+
*/
|
|
372
|
+
maxWidth?: number;
|
|
373
|
+
maxHeight?: number;
|
|
365
374
|
/**
|
|
366
375
|
* Whether the part's Hullcam module supports runtime FoV changes
|
|
367
376
|
* (i.e. it's a `MuMechModuleHullCameraZoom`, not the fixed base
|
|
@@ -623,7 +632,18 @@ export declare enum ErrorCode {
|
|
|
623
632
|
/** The named camera exists but its part is gone. */
|
|
624
633
|
CameraDestroyed = "camera-destroyed",
|
|
625
634
|
/** A command authority in game holds the command cameras' aim lock. */
|
|
626
|
-
CommandLocked = "command-locked"
|
|
635
|
+
CommandLocked = "command-locked",
|
|
636
|
+
/**
|
|
637
|
+
* A command aim names a craft that is not in the camera's latest
|
|
638
|
+
* `commandCentre.targets`, for example one merged away in a dock.
|
|
639
|
+
*/
|
|
640
|
+
CommandTargetUnknown = "command-target-unknown",
|
|
641
|
+
/**
|
|
642
|
+
* `POST /offer` refused: the offer's video carries no H.264 with
|
|
643
|
+
* packetization-mode=1, the only video Kerbcast sends. A browser
|
|
644
|
+
* without H.264 support (some Firefox builds lack OpenH264) offers none.
|
|
645
|
+
*/
|
|
646
|
+
CodecUnsupported = "codec-unsupported"
|
|
627
647
|
}
|
|
628
648
|
export interface ErrorPayload {
|
|
629
649
|
message: string;
|
|
@@ -664,6 +684,11 @@ export interface FrameStampPayload {
|
|
|
664
684
|
export interface HelloPayload {
|
|
665
685
|
sidecarVersion: string;
|
|
666
686
|
encoderBackend: string;
|
|
687
|
+
/**
|
|
688
|
+
* True when this sidecar sends `FrameStamp` to a client that asks with
|
|
689
|
+
* `SetFrameStamps`. Absent from sidecars older than 1.11.
|
|
690
|
+
*/
|
|
691
|
+
frameStamps?: boolean;
|
|
667
692
|
}
|
|
668
693
|
/**
|
|
669
694
|
* A consumer reporting its OWN current display size in px for one camera.
|
|
@@ -735,6 +760,9 @@ export interface SetFovPayload {
|
|
|
735
760
|
flightId: number;
|
|
736
761
|
fov: number;
|
|
737
762
|
}
|
|
763
|
+
export interface SetFrameStampsPayload {
|
|
764
|
+
enabled: boolean;
|
|
765
|
+
}
|
|
738
766
|
export interface SetLayersPayload {
|
|
739
767
|
flightId: number;
|
|
740
768
|
layers: Layer[];
|
|
@@ -1094,6 +1122,15 @@ export type ClientMessage =
|
|
|
1094
1122
|
| {
|
|
1095
1123
|
type: "set-throttle-main-screen";
|
|
1096
1124
|
content: SetThrottleMainScreenPayload;
|
|
1125
|
+
}
|
|
1126
|
+
/**
|
|
1127
|
+
* Start or stop `FrameStamp` messages on this peer's control channel.
|
|
1128
|
+
* Off until asked for, so clients that predate stamps never receive
|
|
1129
|
+
* them. Send only to a sidecar whose `Hello` has `frameStamps: true`.
|
|
1130
|
+
*/
|
|
1131
|
+
| {
|
|
1132
|
+
type: "set-frame-stamps";
|
|
1133
|
+
content: SetFrameStampsPayload;
|
|
1097
1134
|
};
|
|
1098
1135
|
/** Messages sent FROM the sidecar TO the client. */
|
|
1099
1136
|
export type ServerMessage =
|
|
@@ -1179,7 +1216,8 @@ export type ServerMessage =
|
|
|
1179
1216
|
}
|
|
1180
1217
|
/**
|
|
1181
1218
|
* Capture UT of one frame about to go out on a video track, keyed by
|
|
1182
|
-
* its RTP timestamp. One per frame per track
|
|
1219
|
+
* its RTP timestamp. One per frame per track, only to a peer that
|
|
1220
|
+
* enabled them with `SetFrameStamps`.
|
|
1183
1221
|
*/
|
|
1184
1222
|
| {
|
|
1185
1223
|
type: "frame-stamp";
|
|
@@ -172,4 +172,15 @@ export var ErrorCode;
|
|
|
172
172
|
ErrorCode["CameraDestroyed"] = "camera-destroyed";
|
|
173
173
|
/** A command authority in game holds the command cameras' aim lock. */
|
|
174
174
|
ErrorCode["CommandLocked"] = "command-locked";
|
|
175
|
+
/**
|
|
176
|
+
* A command aim names a craft that is not in the camera's latest
|
|
177
|
+
* `commandCentre.targets`, for example one merged away in a dock.
|
|
178
|
+
*/
|
|
179
|
+
ErrorCode["CommandTargetUnknown"] = "command-target-unknown";
|
|
180
|
+
/**
|
|
181
|
+
* `POST /offer` refused: the offer's video carries no H.264 with
|
|
182
|
+
* packetization-mode=1, the only video Kerbcast sends. A browser
|
|
183
|
+
* without H.264 support (some Firefox builds lack OpenH264) offers none.
|
|
184
|
+
*/
|
|
185
|
+
ErrorCode["CodecUnsupported"] = "codec-unsupported";
|
|
175
186
|
})(ErrorCode || (ErrorCode = {}));
|
package/dist/client.d.ts
CHANGED
|
@@ -92,6 +92,20 @@ export interface KerbcastCameraHandle {
|
|
|
92
92
|
* without noise so only the text overlay renders.
|
|
93
93
|
*/
|
|
94
94
|
setShowStatic(enabled: boolean): void;
|
|
95
|
+
/**
|
|
96
|
+
* Run a transform on this camera's encoded frames before they are decoded,
|
|
97
|
+
* and so before Kerbcast's static and frame lock see them. Kerbcast calls
|
|
98
|
+
* `factory` for a fresh instance each time the camera lands on a receiver
|
|
99
|
+
* (connect, slot rebind, reconnect) and removes it from a receiver the
|
|
100
|
+
* camera leaves; frames the old instance still holds are discarded. The
|
|
101
|
+
* setting persists across reconnects. `null` detaches.
|
|
102
|
+
*
|
|
103
|
+
* Needs {@link KerbcastClientConfig.encodedTransforms}; throws without it,
|
|
104
|
+
* or when the browser has no install path. Failures while installing
|
|
105
|
+
* (the factory throws, or returns the wrong kind for the path) surface as
|
|
106
|
+
* client `error` events.
|
|
107
|
+
*/
|
|
108
|
+
setEncodedTransform(factory: EncodedTransformFactory | null): void;
|
|
95
109
|
on<K extends keyof KerbcastCameraEvents>(event: K, handler: (data: KerbcastCameraEvents[K]) => void): () => void;
|
|
96
110
|
}
|
|
97
111
|
/** Event payloads emitted by a {@link KerbcastCameraHandle}. */
|
|
@@ -103,6 +117,26 @@ export interface KerbcastCameraEvents {
|
|
|
103
117
|
/** Frames stopped arriving on a live source (`true`) / resumed (`false`). */
|
|
104
118
|
stall: boolean;
|
|
105
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* How a peer installs encoded transforms. `"script"` sets an
|
|
122
|
+
* `RTCRtpScriptTransform` as the receiver's `transform`, used wherever the
|
|
123
|
+
* browser has it; `"streams"` runs a main-thread `TransformStream` over the
|
|
124
|
+
* receiver's `createEncodedStreams()`, used on Chrome builds without it.
|
|
125
|
+
*/
|
|
126
|
+
export type EncodedTransformPath = "script" | "streams";
|
|
127
|
+
/** A transform over encoded video frames: an `RTCRtpScriptTransform` on the `"script"` path, a `TransformStream` on `"streams"`. */
|
|
128
|
+
export type EncodedTransform = RTCRtpScriptTransform | TransformStream<RTCEncodedVideoFrame, RTCEncodedVideoFrame>;
|
|
129
|
+
/** Passed to an {@link EncodedTransformFactory}. */
|
|
130
|
+
export interface EncodedTransformContext {
|
|
131
|
+
flightId: number;
|
|
132
|
+
/** Which kind of {@link EncodedTransform} to return. */
|
|
133
|
+
path: EncodedTransformPath;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Builds a transform instance for one receiver. An instance is single-use,
|
|
137
|
+
* so Kerbcast asks for a new one whenever the camera moves receiver.
|
|
138
|
+
*/
|
|
139
|
+
export type EncodedTransformFactory = (ctx: EncodedTransformContext) => EncodedTransform;
|
|
106
140
|
/** Configuration for {@link KerbcastClient} construction. */
|
|
107
141
|
export interface KerbcastClientConfig {
|
|
108
142
|
/** Sidecar host (matches the sidecar's `--http-bind`). */
|
|
@@ -130,6 +164,18 @@ export interface KerbcastClientConfig {
|
|
|
130
164
|
* Default false.
|
|
131
165
|
*/
|
|
132
166
|
frameLock?: boolean;
|
|
167
|
+
/**
|
|
168
|
+
* Enable {@link KerbcastCameraHandle.setEncodedTransform}. Every receiver
|
|
169
|
+
* then carries a passthrough transform from creation, because Chrome only
|
|
170
|
+
* honours a receiver transform that was in place before negotiation and
|
|
171
|
+
* stops a receiver's frames when its transform is cleared. This routes
|
|
172
|
+
* every camera's frames through a worker (or, on Chrome builds without
|
|
173
|
+
* `RTCRtpScriptTransform`, a main-thread `createEncodedStreams` pipe), so
|
|
174
|
+
* it is off by default. The worker is a `blob:` URL, so a page with a
|
|
175
|
+
* Content Security Policy must allow `worker-src blob:`. Set it before
|
|
176
|
+
* connecting; a peer keeps the path it was created with.
|
|
177
|
+
*/
|
|
178
|
+
encodedTransforms?: boolean;
|
|
133
179
|
/**
|
|
134
180
|
* ICE gathering timeout in milliseconds. Passed to the default
|
|
135
181
|
* {@link BrowserKerbcastTransport}; ignored when a custom transport is
|
|
@@ -256,6 +302,27 @@ export declare class CommandLockedError extends Error {
|
|
|
256
302
|
readonly code = ErrorCode.CommandLocked;
|
|
257
303
|
constructor(owner: string);
|
|
258
304
|
}
|
|
305
|
+
/**
|
|
306
|
+
* {@link KerbcastClient.setCommandAim} refused because the aim's craft (a
|
|
307
|
+
* `vessel` aim's craft, or an `orbit` or `positionAt` aim's subject) is not in
|
|
308
|
+
* the camera's `commandCentre.targets`, for example one merged away in a dock.
|
|
309
|
+
*/
|
|
310
|
+
export declare class CommandTargetUnknownError extends Error {
|
|
311
|
+
readonly flightId: number;
|
|
312
|
+
readonly persistentId: number;
|
|
313
|
+
readonly code = ErrorCode.CommandTargetUnknown;
|
|
314
|
+
constructor(flightId: number, persistentId: number);
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* The sidecar refused `POST /offer` with a reason, for example
|
|
318
|
+
* `ErrorCode.CodecUnsupported` when the browser offers no H.264 video.
|
|
319
|
+
*/
|
|
320
|
+
export declare class OfferRefusedError extends Error {
|
|
321
|
+
readonly status: number;
|
|
322
|
+
readonly reason: string;
|
|
323
|
+
readonly code?: ErrorCode | undefined;
|
|
324
|
+
constructor(status: number, reason: string, code?: ErrorCode | undefined);
|
|
325
|
+
}
|
|
259
326
|
/** How long {@link KerbcastClient.createCommandCamera} waits for the camera by default. */
|
|
260
327
|
export declare const COMMAND_CAMERA_CREATE_TIMEOUT_MS = 35000;
|
|
261
328
|
/**
|
|
@@ -324,7 +391,17 @@ export interface KerbcastClientEvents {
|
|
|
324
391
|
* implementation to exercise the state machine without a real peer.
|
|
325
392
|
*/
|
|
326
393
|
export interface KerbcastTransport {
|
|
327
|
-
createPeer(iceServers: RTCIceServer[]): KerbcastPeer;
|
|
394
|
+
createPeer(iceServers: RTCIceServer[], opts?: KerbcastPeerOptions): KerbcastPeer;
|
|
395
|
+
/**
|
|
396
|
+
* The encoded-transform path a peer created with `opts` would use, or null
|
|
397
|
+
* when it has none. Optional; a transport without it offers no path.
|
|
398
|
+
*/
|
|
399
|
+
encodedTransformPath?(opts: KerbcastPeerOptions): EncodedTransformPath | null;
|
|
400
|
+
}
|
|
401
|
+
/** Peer creation options passed to {@link KerbcastTransport.createPeer}. */
|
|
402
|
+
export interface KerbcastPeerOptions {
|
|
403
|
+
/** Mirrors {@link KerbcastClientConfig.encodedTransforms}. */
|
|
404
|
+
encodedTransforms?: boolean;
|
|
328
405
|
}
|
|
329
406
|
export interface KerbcastPeer {
|
|
330
407
|
addRecvOnlyTransceiver(): void;
|
|
@@ -343,6 +420,12 @@ export interface KerbcastPeer {
|
|
|
343
420
|
* changes. Equivalent to `RTCPeerConnection.getStats(null)`.
|
|
344
421
|
*/
|
|
345
422
|
getStats?(): Promise<RTCStatsReport>;
|
|
423
|
+
/**
|
|
424
|
+
* Install `transform` on the receiver of slot `mid`, replacing any
|
|
425
|
+
* previous one; `null` restores passthrough. Throws when the receiver is
|
|
426
|
+
* unknown or the transform's kind does not match the peer's path.
|
|
427
|
+
*/
|
|
428
|
+
setReceiverTransform?(mid: string, transform: EncodedTransform | null): void;
|
|
346
429
|
}
|
|
347
430
|
export interface KerbcastDataChannel {
|
|
348
431
|
send(payload: string): void;
|
|
@@ -365,7 +448,8 @@ export interface BrowserKerbcastTransportOptions {
|
|
|
365
448
|
export declare class BrowserKerbcastTransport implements KerbcastTransport {
|
|
366
449
|
private readonly opts;
|
|
367
450
|
constructor(opts?: BrowserKerbcastTransportOptions);
|
|
368
|
-
|
|
451
|
+
encodedTransformPath(opts: KerbcastPeerOptions): EncodedTransformPath | null;
|
|
452
|
+
createPeer(iceServers: RTCIceServer[], opts?: KerbcastPeerOptions): KerbcastPeer;
|
|
369
453
|
}
|
|
370
454
|
declare class TypedEmitter<E> {
|
|
371
455
|
private readonly listeners;
|
|
@@ -424,6 +508,12 @@ export declare class KerbcastClient extends TypedEmitter<KerbcastClientEvents> {
|
|
|
424
508
|
* matches by mid instead).
|
|
425
509
|
*/
|
|
426
510
|
private readonly flightByTrackId;
|
|
511
|
+
/** Legacy mode: transceiver mid -> the camera routed to it by index. */
|
|
512
|
+
private readonly legacyFlightByMid;
|
|
513
|
+
/** The encoded-transform path the current peer was created with. */
|
|
514
|
+
private peerTransformPath;
|
|
515
|
+
/** Receivers holding a camera's encoded transform, by mid, with the factory that built it. */
|
|
516
|
+
private readonly transformInstalls;
|
|
427
517
|
/** Sidecar version reported on `Hello`; null before handshake. */
|
|
428
518
|
private _sidecarVersion;
|
|
429
519
|
private _encoderBackend;
|
|
@@ -634,6 +724,11 @@ export declare class KerbcastClient extends TypedEmitter<KerbcastClientEvents> {
|
|
|
634
724
|
* (`commandTrack.authority`): it holds the lock and only it can aim. A
|
|
635
725
|
* refusal that races the lock being taken arrives as an `error` event with
|
|
636
726
|
* code `ErrorCode.CommandLocked` instead.
|
|
727
|
+
*
|
|
728
|
+
* Rejects with a {@link CommandTargetUnknownError} when the aim's craft is
|
|
729
|
+
* not in the camera's `commandCentre.targets` (a craft merged away in a
|
|
730
|
+
* dock, say). A refusal that races the list changing arrives as an `error`
|
|
731
|
+
* event with code `ErrorCode.CommandTargetUnknown`.
|
|
637
732
|
*/
|
|
638
733
|
setCommandAim(flightId: number, aim: CommandAim | null): Promise<void>;
|
|
639
734
|
/**
|
|
@@ -696,6 +791,20 @@ export declare class KerbcastClient extends TypedEmitter<KerbcastClientEvents> {
|
|
|
696
791
|
* (modern browsers include it; some implementations omit it).
|
|
697
792
|
*/
|
|
698
793
|
inboundVideoStats(): Promise<Map<number, InboundVideoStats>>;
|
|
794
|
+
/** The encoded-transform path this client's next peer will use, or null when it has none. */
|
|
795
|
+
get encodedTransformPath(): EncodedTransformPath | null;
|
|
796
|
+
private peerOptions;
|
|
797
|
+
/** Internal: throws unless {@link KerbcastCameraHandle.setEncodedTransform} can work here. */
|
|
798
|
+
_assertEncodedTransforms(): void;
|
|
799
|
+
/**
|
|
800
|
+
* Internal: bring each receiver's installed transform in line with the
|
|
801
|
+
* camera now bound to it. A receiver whose camera or factory changed loses
|
|
802
|
+
* its instance; a bound camera with a factory gets a fresh one.
|
|
803
|
+
*/
|
|
804
|
+
_syncEncodedTransforms(): void;
|
|
805
|
+
private clearEncodedTransforms;
|
|
806
|
+
private setReceiverTransform;
|
|
807
|
+
private emitTransformError;
|
|
699
808
|
private tearDownStreams;
|
|
700
809
|
}
|
|
701
810
|
export {};
|