@desklink/host 0.2.0 → 0.3.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/NOTICE +23 -0
- package/README.md +78 -48
- package/bin/desklink-host.mjs +1 -1
- package/dist/bridge.d.ts +1 -0
- package/dist/bridge.d.ts.map +1 -1
- package/dist/bridge.js +12 -4
- package/dist/bridge.js.map +1 -1
- package/dist/engineProcess.d.ts.map +1 -1
- package/dist/engineProcess.js +1 -0
- package/dist/engineProcess.js.map +1 -1
- package/dist/protocol.d.ts +26 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js.map +1 -1
- package/dist/resolveEngine.d.ts +1 -1
- package/dist/resolveEngine.d.ts.map +1 -1
- package/dist/resolveEngine.js +22 -9
- package/dist/resolveEngine.js.map +1 -1
- package/docs/BOUNDARY.md +15 -7
- package/docs/PROTOCOL.md +150 -23
- package/engine/Cargo.lock +46 -1
- package/engine/Cargo.toml +12 -2
- package/engine/build.rs +28 -2
- package/engine/native/nvenc_shim.c +453 -0
- package/engine/native/vaapi_shim.c +727 -0
- package/engine/native/vpx_shim.c +54 -4
- package/engine/native/vt_shim.c +448 -0
- package/engine/src/capture.rs +75 -55
- package/engine/src/capture_mac.rs +24 -14
- package/engine/src/convert.rs +286 -61
- package/engine/src/encoder.rs +122 -13
- package/engine/src/h264.rs +188 -0
- package/engine/src/h264_nvenc.rs +308 -0
- package/engine/src/h264_openh264.rs +735 -0
- package/engine/src/h264_vaapi.rs +263 -0
- package/engine/src/h264_vt.rs +368 -0
- package/engine/src/mac.rs +6 -3
- package/engine/src/main.rs +22 -4
- package/engine/src/peer.rs +466 -28
- package/engine/src/protocol.rs +15 -2
- package/engine/src/session.rs +790 -93
- package/engine/src/x11.rs +210 -9
- package/engine/src/x11_mac.rs +12 -0
- package/engine/vendor/libva/COPYING +19 -0
- package/engine/vendor/libva/va/va.h +5450 -0
- package/engine/vendor/libva/va/va_dec_av1.h +695 -0
- package/engine/vendor/libva/va/va_dec_hevc.h +616 -0
- package/engine/vendor/libva/va/va_dec_jpeg.h +157 -0
- package/engine/vendor/libva/va/va_dec_vp8.h +249 -0
- package/engine/vendor/libva/va/va_dec_vp9.h +312 -0
- package/engine/vendor/libva/va/va_dec_vvc.h +688 -0
- package/engine/vendor/libva/va/va_drm.h +61 -0
- package/engine/vendor/libva/va/va_enc_av1.h +1010 -0
- package/engine/vendor/libva/va/va_enc_h264.h +659 -0
- package/engine/vendor/libva/va/va_enc_hevc.h +958 -0
- package/engine/vendor/libva/va/va_enc_jpeg.h +162 -0
- package/engine/vendor/libva/va/va_enc_mpeg2.h +308 -0
- package/engine/vendor/libva/va/va_enc_vp8.h +350 -0
- package/engine/vendor/libva/va/va_enc_vp9.h +639 -0
- package/engine/vendor/libva/va/va_fei.h +170 -0
- package/engine/vendor/libva/va/va_fei_h264.h +505 -0
- package/engine/vendor/libva/va/va_fei_hevc.h +254 -0
- package/engine/vendor/libva/va/va_prot.h +525 -0
- package/engine/vendor/libva/va/va_version.h +87 -0
- package/engine/vendor/libva/va/va_vpp.h +1590 -0
- package/engine/vendor/nv-codec-headers/LICENSE +24 -0
- package/engine/vendor/nv-codec-headers/README +7 -0
- package/engine/vendor/nv-codec-headers/include/ffnvcodec/nvEncodeAPI.h +3825 -0
- package/examples/reference-client.html +1 -1
- package/package.json +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveEngine.js","sourceRoot":"","sources":["../src/resolveEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAsBzC,mDAAmD;AACnD,MAAM,kBAAkB,GAAG,CAAC,eAAe,EAAE,cAAc,CAAC,CAAC;AAE7D,MAAM,UAAU,kBAAkB,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,EAAE,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc;IAC7F,OAAO,QAAQ,KAAK,QAAQ,IAAI,IAAI,KAAK,GAAG,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC7B,OAAO,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACvB,WAAmB,OAAO,CAAC,QAAQ,EACnC,OAAe,OAAO,CAAC,IAAI,EAC3B,QAA6B,QAAQ,EAAE;IAEvC,IAAI,QAAQ,KAAK,OAAO;QAAE,OAAO,SAAS,IAAI,IAAI,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;IACrF,OAAO,GAAG,QAAQ,IAAI,IAAI,EAAE,CAAC;AACjC,CAAC;AAED,yEAAyE;AACzE,SAAS,QAAQ;IACb,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,SAAS,CAAC;IACnD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,EAA+D,CAAC;IAC1G,OAAO,MAAM,EAAE,MAAM,EAAE,mBAAmB,KAAK,SAAS,CAAC;AAC7D,CAAC;AAED,SAAS,cAAc;IACnB,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,kBAAkB,WAAW,EAAE,EAAE,CAAC;IAC/C,IAAI,CAAC;QACD,mEAAmE;QACnE,2DAA2D;QAC3D,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,IAAI,eAAe,CAA0D,CAAC;QAC1G,MAAM,QAAQ,GAAG,QAAQ,CAAC,UAAU,IAAI,QAAQ,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,CAAC;QACxE,IAAI,OAAO,QAAQ,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC9C,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,IAAI,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;QACzE,OAAO,IAAI,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACjC,OAAO;QACH,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,eAAe,CAAC;QAC1D,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,eAAe,CAAC;QACxD,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,eAAe,CAAC;KACrC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"resolveEngine.js","sourceRoot":"","sources":["../src/resolveEngine.ts"],"names":[],"mappings":"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"}
|
package/docs/BOUNDARY.md
CHANGED
|
@@ -20,8 +20,9 @@ apply authenticated input to the same desktop".
|
|
|
20
20
|
- In: `session.open`, SDP/ICE, scoped WebRTC control-channel input, explicit
|
|
21
21
|
clipboard read/write, close — and `session.feed`, which supplies the access
|
|
22
22
|
units of a consumer-encoded `encoded` source. See `docs/PROTOCOL.md`.
|
|
23
|
-
- Out: one video track — VP9
|
|
24
|
-
H.264 it only packetizes for a
|
|
23
|
+
- Out: one video track — VP9 or H.264 (the receiver's answer picks) the engine
|
|
24
|
+
encodes from a captured desktop, or H.264 it only packetizes for a
|
|
25
|
+
consumer-fed `encoded` source, whose control
|
|
25
26
|
messages are forwarded to the consumer instead of applied — and session
|
|
26
27
|
notifications. Metrics are a request, not an event; the wire contract is in
|
|
27
28
|
`docs/PROTOCOL.md`.
|
|
@@ -31,6 +32,9 @@ apply authenticated input to the same desktop".
|
|
|
31
32
|
- Never: decides identity, installs rules, grants capabilities, carries audio,
|
|
32
33
|
arbitrates two controllers, remembers a session across a restart.
|
|
33
34
|
|
|
35
|
+
For prebuilt platform support and macOS installation, see the
|
|
36
|
+
[host installation guide](../README.md#install-and-run).
|
|
37
|
+
|
|
34
38
|
The public surface carries no consumer concepts. A machine id, a chat, a pane or
|
|
35
39
|
an account never appears in the protocol or in the engine's state.
|
|
36
40
|
|
|
@@ -47,8 +51,10 @@ local gestures into that session's input".
|
|
|
47
51
|
- `session.showKeyboard()/hideKeyboard()`,
|
|
48
52
|
`session.copyRemoteToLocal()/pasteLocalToRemote()` are the control primitives
|
|
49
53
|
the app mounts wherever it wants.
|
|
50
|
-
- Native side owns the video decoder factory selection (
|
|
51
|
-
than the underlying wrapper's software default
|
|
54
|
+
- Native side owns the video decoder factory selection (on Android, hardware
|
|
55
|
+
VP9 rather than the underlying wrapper's software default; on iOS, whose
|
|
56
|
+
WebRTC decodes VP9 only in software, the receiver asks for H.264, which it
|
|
57
|
+
decodes in hardware), the renderer and the IME/text
|
|
52
58
|
connection. For input enablement and release on background/unmount, see the
|
|
53
59
|
[client contract](../../desktop-client/README.md#what-the-package-guarantees).
|
|
54
60
|
- The app supplies `authorize()` (a short-lived, engine-scoped capability plus
|
|
@@ -73,10 +79,9 @@ local gestures into that session's input".
|
|
|
73
79
|
|
|
74
80
|
## Reused, not rebuilt `[decided]`
|
|
75
81
|
|
|
76
|
-
| Need |
|
|
82
|
+
| Need | Integration owner or consumer reference |
|
|
77
83
|
|---|---|
|
|
78
|
-
|
|
|
79
|
-
| Relay stream channel (host joins as machine, client as client) | `packages/contract` `wsTickets` / preview channel pattern |
|
|
84
|
+
| Authenticated request channel, identity, pairing, relay and reachable addresses | The consuming app's kits; see the [BYOKit integration guidance](../../../README.md#why-desklink-exists) |
|
|
80
85
|
| A reference for a "live surface inside a conversation" | `apps/mobile/sources/desktop` |
|
|
81
86
|
| Flow-test style for the packages | `apps/mobile/sources/catalog/application/sessionSync.integration.spec.ts` |
|
|
82
87
|
|
|
@@ -88,6 +93,9 @@ local gestures into that session's input".
|
|
|
88
93
|
| Portal ScreenCast + PipeWire fd | `ashpd` (zbus) | MIT |
|
|
89
94
|
| PipeWire stream client | `pipewire` | MIT |
|
|
90
95
|
| VP9 encode | libvpx | BSD-3-Clause |
|
|
96
|
+
| H.264 encode (macOS) | VideoToolbox (system framework) | Apple SDK |
|
|
97
|
+
| H.264 encode (Linux GPU) | NVENC, VA-API — loaded at runtime from the driver | NVIDIA driver / libva MIT |
|
|
98
|
+
| H.264 encode (Linux, no GPU encoder) | Cisco's prebuilt openh264, downloaded at runtime, never built or shipped | BSD-2-Clause (Cisco's binary licence) |
|
|
91
99
|
| Virtual mouse/keyboard | inputtino (uinput/libevdev) | MIT |
|
|
92
100
|
| Clipboard read/write | `wl-clipboard-rs` | MIT |
|
|
93
101
|
| Keyboard layout mapping | `xkbcommon` | MIT |
|
package/docs/PROTOCOL.md
CHANGED
|
@@ -66,7 +66,7 @@ Request parameters use the engine's own snake_case names (`session_id`,
|
|
|
66
66
|
Result:
|
|
67
67
|
|
|
68
68
|
```jsonc
|
|
69
|
-
{"protocol":3,"engine":"desklink-host/0.
|
|
69
|
+
{"protocol":3,"engine":"desklink-host/0.3.0","platform":"linux", /* the rest of Capabilities */ }
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
The consumer must send `hello` first, and a version the engine does not speak is
|
|
@@ -76,8 +76,12 @@ arrives, every other request is refused the same way; `capabilities` and
|
|
|
76
76
|
|
|
77
77
|
## macOS
|
|
78
78
|
|
|
79
|
+
For engine installation and the macOS resolution opt-out, see the
|
|
80
|
+
[host installation guide](../README.md#macos).
|
|
81
|
+
|
|
79
82
|
macOS speaks protocol 3 and shares the session lifecycle below. It captures the
|
|
80
|
-
selected display with ScreenCaptureKit, encodes VP9
|
|
83
|
+
selected display with ScreenCaptureKit, encodes VP9 (and H.264 through
|
|
84
|
+
VideoToolbox, for a receiver that asks for it), and uses the same WebRTC
|
|
81
85
|
offer, ICE, control-channel, lease, and metrics flow as Linux. Capture currently
|
|
82
86
|
uses one bounded ScreenCaptureKit stream (three-frame queue); the backend may
|
|
83
87
|
supply fewer frames. Audio is not captured.
|
|
@@ -108,7 +112,7 @@ session may require fresh consent. The macOS engine requires a VP9-enabled build
|
|
|
108
112
|
```jsonc
|
|
109
113
|
{
|
|
110
114
|
"protocol": 3,
|
|
111
|
-
"engine": "desklink-host/0.
|
|
115
|
+
"engine": "desklink-host/0.3.0",
|
|
112
116
|
"platform": "linux",
|
|
113
117
|
"session": {"kind": "wayland"},
|
|
114
118
|
"x11": {"available": true, "size": [2560, 1440]},
|
|
@@ -119,7 +123,8 @@ session may require fresh consent. The macOS engine requires a VP9-enabled build
|
|
|
119
123
|
"cursor": "embedded",
|
|
120
124
|
"audio": false
|
|
121
125
|
},
|
|
122
|
-
"encode": {"codecs": ["vp9"], "hardware": false
|
|
126
|
+
"encode": {"codecs": ["vp9", "h264"], "hardware": false,
|
|
127
|
+
"h264": {"encoder": "vaapi", "hardware": true}},
|
|
123
128
|
"input": {
|
|
124
129
|
"mechanism": "inputtino/uinput",
|
|
125
130
|
"pointer": true, "wheel": true, "keyboard": true,
|
|
@@ -133,6 +138,28 @@ session may require fresh consent. The macOS engine requires a VP9-enabled build
|
|
|
133
138
|
}
|
|
134
139
|
```
|
|
135
140
|
|
|
141
|
+
`encode` describes what the engine codes from a captured desktop. VP9 (libvpx,
|
|
142
|
+
software; `hardware` describes it) is always there and is the default. `h264`
|
|
143
|
+
appears in `codecs` when an H.264 encoder starts on this machine right now, and
|
|
144
|
+
`encode.h264.encoder` names it: `videotoolbox` on macOS; on Linux `nvenc` or
|
|
145
|
+
`vaapi` when the GPU has an H.264 encoder, else `openh264`, Cisco's prebuilt
|
|
146
|
+
library. `encoder` is `null` when there is none. The answer to the offer picks
|
|
147
|
+
between them (see *Codecs* below).
|
|
148
|
+
|
|
149
|
+
openh264 is never part of this package: the engine loads only Cisco's own
|
|
150
|
+
binary, checked against its published SHA-256, from
|
|
151
|
+
`$XDG_CACHE_HOME/desklink/openh264/` (else `~/.cache/desklink/openh264/`). When a
|
|
152
|
+
Linux machine has no hardware H.264 encoder and the library is not there yet,
|
|
153
|
+
the first captured `session.open` downloads it from Cisco
|
|
154
|
+
(`ciscobinary.openh264.org`) before making its offer; that session is offered
|
|
155
|
+
VP9 alone if the download fails. `capabilities` itself never downloads.
|
|
156
|
+
`DESKLINK_OPENH264=off` in the engine's environment disables openh264 (no
|
|
157
|
+
download, no load); `DESKLINK_OPENH264=<path>` loads that file instead, still
|
|
158
|
+
only if its hash is Cisco's. `DESKLINK_H264_ENCODER=<name>` restricts the engine
|
|
159
|
+
to one H.264 encoder (`off` for none), for measuring one backend. Cisco's
|
|
160
|
+
licence asks that this be stated: OpenH264 Video Codec provided by Cisco
|
|
161
|
+
Systems, Inc.
|
|
162
|
+
|
|
136
163
|
`encoded` lists the codecs this build will carry when the consumer supplies the
|
|
137
164
|
video itself (see *Encoded sources*): a consumer reads it rather than inferring
|
|
138
165
|
support from the engine's version string.
|
|
@@ -168,12 +195,13 @@ trigger a capture request.
|
|
|
168
195
|
"permissions": ["view","control","clipboard"],
|
|
169
196
|
"max_width": 3840, "max_height": 2160, // encode box (default); never upscales
|
|
170
197
|
"bitrate_kbps": 0, // 0 (default): sized to the encoded surface
|
|
171
|
-
"max_fps":
|
|
198
|
+
"max_fps": 60,
|
|
172
199
|
"ice_servers": [{"urls":["stun:..."],"username":null,"credential":null}],
|
|
173
200
|
"restore_token": null, // from a previous session.restoreToken
|
|
174
201
|
"ttl_seconds": 3600, // session lease; default 3600
|
|
175
202
|
"loopback_tcp": false, // also offer ICE over TCP on 127.0.0.1; default false
|
|
176
|
-
"agent_indicator": false
|
|
203
|
+
"agent_indicator": false, // local input feedback; default false (phone control)
|
|
204
|
+
"local_frames": true // keep frames for session.frame; default true
|
|
177
205
|
}}
|
|
178
206
|
```
|
|
179
207
|
|
|
@@ -201,7 +229,7 @@ clipboard action and never infers them from a source, a peer or an SDP.
|
|
|
201
229
|
`control` without a working input backend is refused at `session.open` with
|
|
202
230
|
`error.code = "input-unavailable"` — the consumer must ask for `view` explicitly instead.
|
|
203
231
|
|
|
204
|
-
`max_fps` defaults to
|
|
232
|
+
`max_fps` defaults to 60 and is bounded to 1–60. It caps the encoded frame
|
|
205
233
|
rate and X11 capture loop; portal capture offers it as the preferred PipeWire
|
|
206
234
|
frame rate, and macOS sets its ScreenCaptureKit stream minimum frame interval.
|
|
207
235
|
A source may still supply fewer frames.
|
|
@@ -211,11 +239,19 @@ sets it for control sessions, never for view-only or human phone control. It
|
|
|
211
239
|
adds an eased pointer halo, click ripple, and typing pulse. On Wayland it uses
|
|
212
240
|
a click-through layer-shell surface with an edge glow; its bounded area is
|
|
213
241
|
masked before capture/diff (pixels behind the effect can remain briefly stale).
|
|
214
|
-
On bare X11 it replaces the pointer sprite instead, which
|
|
242
|
+
On bare X11 it replaces the pointer sprite instead, which the X11 grab excludes:
|
|
215
243
|
there is no edge glow on that path. macOS uses a nonactivating, click-through
|
|
216
244
|
window excluded by the ScreenCaptureKit content filter. Closing the session
|
|
217
245
|
fades and removes the indicator.
|
|
218
246
|
|
|
247
|
+
`local_frames` keeps the latest pre-encode frame and its tile hashes for
|
|
248
|
+
`session.frame` and `session.frame.changed` (see "Latest frame over the local
|
|
249
|
+
protocol"). A consumer that only streams sets it to `false`: each captured
|
|
250
|
+
frame is then converted once, for the encoder, no frame is kept, no
|
|
251
|
+
`session.frame.changed` is emitted, and `session.frame` is refused with
|
|
252
|
+
`error.code = "operation"`. The WebSocket bridge sets it to `false` unless its
|
|
253
|
+
host listens to engine events, because neither travels past the socket.
|
|
254
|
+
|
|
219
255
|
`session.open` is where the capture request happens, which is where the user's
|
|
220
256
|
consent appears. It is not implicit and it is not retried silently.
|
|
221
257
|
|
|
@@ -243,6 +279,36 @@ the SDP and candidates to the client and brings back the answer.
|
|
|
243
279
|
|
|
244
280
|
A candidate that arrives before the remote description is buffered, not dropped.
|
|
245
281
|
|
|
282
|
+
#### Codecs
|
|
283
|
+
|
|
284
|
+
For a captured desktop the offer's video section lists VP9 (payload type 98)
|
|
285
|
+
and, when `capabilities.encode.codecs` has `h264` and the encoded surface is
|
|
286
|
+
within H.264 level 5.2 (at most 36864 16x16 macroblocks, e.g. 4096x2304 — a
|
|
287
|
+
5K surface is offered VP9 alone), H.264 after it (payload type
|
|
288
|
+
102, `packetization-mode=1`, Constrained Baseline, `profile-level-id=42e034`
|
|
289
|
+
with `level-asymmetry-allowed=1`). The engine codes whichever of the two the
|
|
290
|
+
answer lists first. A receiver that applies the offer as it comes answers in
|
|
291
|
+
the offer's order and gets VP9, as before; a receiver that wants H.264 puts it
|
|
292
|
+
first — with `setCodecPreferences` before `createAnswer`, or by moving its
|
|
293
|
+
payload type to the front of the offer's `m=video` line before applying it.
|
|
294
|
+
The iOS receiver in `@desklink/client` does the latter, because iOS decodes
|
|
295
|
+
H.264 in hardware and VP9 in software; the web and Android receivers keep VP9.
|
|
296
|
+
The choice is made by the first answer and kept for the session, ICE restarts
|
|
297
|
+
included; the encoder starts after that answer, so the first frame sent is
|
|
298
|
+
already in the chosen codec. H.264 is coded at the full encoded size throughout
|
|
299
|
+
(no half-size motion), with an IDR carrying its SPS and PPS only for the first
|
|
300
|
+
frame and on a receiver's request. An `encoded` source offers H.264 alone, as
|
|
301
|
+
described under *Encoded sources*.
|
|
302
|
+
|
|
303
|
+
The offer negotiates the `playout-delay` RTP header extension
|
|
304
|
+
(`http://www.webrtc.org/experiments/rtp-hdrext/playout-delay`), and every video
|
|
305
|
+
packet asks for a playout delay of 0: a receiver that honours it shows each
|
|
306
|
+
frame when it is decoded instead of buffering frames to smooth playback. A
|
|
307
|
+
receiver may decline the extension in its answer; its packets then carry no
|
|
308
|
+
playout delay and it buffers as usual. The iOS receiver in
|
|
309
|
+
`@desklink/react-native` declines it, because `RTCView` draws a frame only when
|
|
310
|
+
its timestamp is new and zero-delay frames all carry the same one.
|
|
311
|
+
|
|
246
312
|
A client whose ICE connection goes `disconnected` may restart ICE on the same
|
|
247
313
|
peer connection instead of opening a new session: it sends
|
|
248
314
|
`session.restart_ice` with the session's id and generation, and the engine
|
|
@@ -278,8 +344,9 @@ always does.
|
|
|
278
344
|
|
|
279
345
|
`disconnected` is ICE losing the path: the picture is frozen but the session
|
|
280
346
|
is alive, and a client should show reconnecting and may restart ICE (above)
|
|
281
|
-
rather than open a new session. `failed` is terminal: the engine revokes
|
|
282
|
-
closes
|
|
347
|
+
rather than open a new session. `failed` is terminal: the engine revokes the
|
|
348
|
+
session with code `transport` and closes it, and only a new `session.open`
|
|
349
|
+
recovers it.
|
|
283
350
|
|
|
284
351
|
While its control channel is open the engine also sends a heartbeat twice a
|
|
285
352
|
second, `{"kind":"ping"}`. It lets a client notice a stalled path within
|
|
@@ -310,10 +377,26 @@ picker; restoration is silent only where the backend supports it. Cancellation
|
|
|
310
377
|
is an error, not a reason to retry or bypass consent.
|
|
311
378
|
|
|
312
379
|
```jsonc
|
|
313
|
-
{"event":"session.revoked","params":{"sessionId":"…","reason":"…"
|
|
380
|
+
{"event":"session.revoked","params":{"sessionId":"…","reason":"…",
|
|
381
|
+
"code":"transport"}} // transport|lease|error
|
|
314
382
|
```
|
|
315
383
|
|
|
316
384
|
The session ended on the engine's side; there is nothing further to drain.
|
|
385
|
+
`reason` is prose for people; `code` is what a client acts on:
|
|
386
|
+
|
|
387
|
+
| `code` | Meaning | A client should |
|
|
388
|
+
|---|---|---|
|
|
389
|
+
| `transport` | The path to the client's peer was lost (ICE `failed`, or the track refused a frame) | open a new session with fresh authority; the desktop is still available |
|
|
390
|
+
| `lease` | The session's `ttl_seconds` ran out | end; the grant is spent |
|
|
391
|
+
| `error` | The engine could not keep serving it, such as an encoder refusing a frame | end and report |
|
|
392
|
+
|
|
393
|
+
A session the consumer closes or replaces (`session.close`, a new
|
|
394
|
+
`session.open`, the consumer leaving) sends no `session.revoked`: the consumer
|
|
395
|
+
asked for it, and signaling sees `session.state` with `capture` `ended`. Only
|
|
396
|
+
its control channel is told, with code `closed` (below).
|
|
397
|
+
|
|
398
|
+
A code a client does not know is terminal. Engines before this field sent no
|
|
399
|
+
`code`; treat its absence as terminal too.
|
|
317
400
|
|
|
318
401
|
Metrics are a request, not a notification:
|
|
319
402
|
|
|
@@ -323,17 +406,56 @@ Metrics are a request, not a notification:
|
|
|
323
406
|
|
|
324
407
|
```jsonc
|
|
325
408
|
{"id":7,"result":{"captured_frames":812,"dropped_frames":3,"encoded_frames":809,
|
|
326
|
-
"encoded_bytes":12345678,"key_frames":1,"refined_frames":37,
|
|
409
|
+
"encoded_bytes":12345678,"key_frames":1,"refined_frames":37,"halved_frames":0,"motion_frames":770,
|
|
327
410
|
"encode_micros":7390000,"target_kbps":16430,"input_applied":44,"input_rejected":0,
|
|
328
|
-
"fed_frames":0,"input_forwarded":0
|
|
411
|
+
"fed_frames":0,"input_forwarded":0,"codec":"vp9","encoder":"libvpx",
|
|
412
|
+
"capture_micros":14100000,"convert_micros":3200000,
|
|
413
|
+
"queue_micros":410000,"send_micros":180000}}
|
|
329
414
|
```
|
|
330
415
|
|
|
331
416
|
`dropped_frames` counts frames superseded by a newer one before they were coded;
|
|
332
|
-
the newest frame is always coded.
|
|
417
|
+
the newest frame is always coded. That includes frames that arrived while a
|
|
418
|
+
large one (a key frame, a refinement) was still crossing the link: the stream
|
|
419
|
+
runs at most about 60 ms of its rate target ahead of it, so frames never queue
|
|
420
|
+
behind a burst. `refined_frames` counts refinement passes: a
|
|
333
421
|
desktop that stops changing is coded once more at a fine quantizer, so it reads
|
|
334
|
-
sharp.
|
|
335
|
-
|
|
336
|
-
|
|
422
|
+
sharp. `halved_frames` counts motion frames coded at half width and height: when
|
|
423
|
+
full-size frames that change much of the picture take longer to code than a
|
|
424
|
+
frame interval while a newer frame is already waiting, several frames in a row,
|
|
425
|
+
motion is coded at half size until the desktop stops or its changes shrink to
|
|
426
|
+
small ones that code in time; the refinement pass is always full size. Key
|
|
427
|
+
frames are sent only for the first frame, when the receiver asks (RTCP PLI or
|
|
428
|
+
FIR), and when the coded size changes that way, so a receiver never has to scale
|
|
429
|
+
references across a size change. `target_kbps` is the current rate target after
|
|
430
|
+
any back-off: for a standing queue on the path, measured from the receiver's
|
|
431
|
+
transport-wide congestion feedback (RTP `transport-cc`), and for the loss
|
|
432
|
+
its receiver reports carry. `codec` is what frames go out in
|
|
433
|
+
(`vp9` or `h264`) and `encoder` what codes them (`libvpx`, `videotoolbox`,
|
|
434
|
+
`nvenc`, `vaapi` or `openh264`); both are empty for an encoded source.
|
|
435
|
+
|
|
436
|
+
Per-stage timings (the L0 lab harness reads these, and every later lane cites
|
|
437
|
+
them). Each is a cumulative microsecond counter; divide by the frame count
|
|
438
|
+
named beside it for the per-frame mean:
|
|
439
|
+
|
|
440
|
+
- `capture_micros` / `captured_frames`: grabbing a frame and converting it on
|
|
441
|
+
the capture thread (on X11: an MIT-SHM grab, falling back to socket
|
|
442
|
+
`GetImage` where the server lacks MIT-SHM, plus the downscale to I420), over
|
|
443
|
+
forwarded (changed) frames only — unchanged polls are excluded.
|
|
444
|
+
- `convert_micros` / `captured_frames`: tile hashing and damage computation on
|
|
445
|
+
the capture thread, after the grab; the hash branch runs only with
|
|
446
|
+
`local_frames` on.
|
|
447
|
+
- `queue_micros` / `motion_frames`: how long a freshly captured frame waited
|
|
448
|
+
between the capture handoff and the start of its encode. Refinement,
|
|
449
|
+
keepalive and receiver-requested re-encodes re-code a picture that was
|
|
450
|
+
already sent; they queue nothing and stay out of this mean.
|
|
451
|
+
- `send_micros` / `encoded_frames`: packetizing a frame and handing it to the
|
|
452
|
+
transport.
|
|
453
|
+
- `encode_micros` / `encoded_frames`: the encoder alone.
|
|
454
|
+
|
|
455
|
+
`capture + convert` per captured frame plus `queue` per motion-coded frame and
|
|
456
|
+
`encode + send` per encoded frame reconciles against engine-side wall time per
|
|
457
|
+
frame within measurement noise; a stage that will not reconcile is a stage
|
|
458
|
+
whose accounting is wrong.
|
|
337
459
|
|
|
338
460
|
## Input and clipboard: the session's control channel
|
|
339
461
|
|
|
@@ -373,7 +495,7 @@ The engine answers on the same channel, and sends two things unprompted:
|
|
|
373
495
|
{"kind":"ack","seq":44}
|
|
374
496
|
{"kind":"rejected","seq":44,"code":"coordinates","message":"(9000,4) is outside the 1280x720 surface"}
|
|
375
497
|
{"kind":"clipboard","request":"…","text":"…","truncated":false} // an empty "text" with "error" when the read failed
|
|
376
|
-
{"kind":"revoked","reason":"…"}
|
|
498
|
+
{"kind":"revoked","reason":"…","code":"closed"} // closed, or a session.revoked code
|
|
377
499
|
```
|
|
378
500
|
|
|
379
501
|
Refusal codes: `permission`, `session`, `input-replay`, `coordinates`,
|
|
@@ -494,9 +616,12 @@ is the consumer's to carry.
|
|
|
494
616
|
|
|
495
617
|
`session.frame` and `session.wait_frame` are refused with `error.code =
|
|
496
618
|
"operation"` — there is no lossless frame to read — and `captured_frames`,
|
|
497
|
-
`refined_frames`
|
|
498
|
-
|
|
499
|
-
|
|
619
|
+
`refined_frames`, `halved_frames`, `motion_frames`, `target_kbps`, `capture_micros`,
|
|
620
|
+
`convert_micros`, `queue_micros` and `send_micros` stay at zero while
|
|
621
|
+
`fed_frames` counts what the consumer handed over and `encoded_frames`,
|
|
622
|
+
`encoded_bytes`, `key_frames` and `encode_micros` describe what was packetized
|
|
623
|
+
and sent — on this path `encode_micros` covers packetizing and sending too,
|
|
624
|
+
because packetization is the only stage the engine itself runs.
|
|
500
625
|
|
|
501
626
|
## Latest frame over the local protocol
|
|
502
627
|
|
|
@@ -516,7 +641,8 @@ of stillness. When both are supplied, both conditions must hold.
|
|
|
516
641
|
Each changed capture emits a local `session.frame.changed` event with `sessionId`,
|
|
517
642
|
`seq` and `damage`, allowing a co-located consumer to track animation across
|
|
518
643
|
observations. Neither the event nor this file-writing method is forwarded by
|
|
519
|
-
the remote WebSocket bridge.
|
|
644
|
+
the remote WebSocket bridge. A session opened with `local_frames: false` keeps
|
|
645
|
+
no frame: both are refused with `error.code = "operation"` (see `session.open`).
|
|
520
646
|
|
|
521
647
|
```json
|
|
522
648
|
{"id":20,"method":"session.frame","params":{"session_id":"…","since":7,"path":"/run/user/1000/frame.raw"}}
|
|
@@ -616,7 +742,8 @@ anything to show.
|
|
|
616
742
|
|
|
617
743
|
- It does not decide *who* the user is. It trusts the consumer's local
|
|
618
744
|
permission decision and enforces the resulting scope; there is no second
|
|
619
|
-
account, token or pairing ceremony.
|
|
745
|
+
account, token or pairing ceremony. For consumer integration, see the
|
|
746
|
+
[BYOKit guidance](../../../README.md#why-desklink-exists).
|
|
620
747
|
- It does not open ports, register a service, install udev rules, join groups or
|
|
621
748
|
raise capabilities. Kernel input access is a separate, explicit, guided step
|
|
622
749
|
(`desklink-host setup-input` reports what is missing; it does not change it).
|
package/engine/Cargo.lock
CHANGED
|
@@ -307,6 +307,16 @@ version = "1.12.1"
|
|
|
307
307
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
308
308
|
checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
|
|
309
309
|
|
|
310
|
+
[[package]]
|
|
311
|
+
name = "bzip2-rs"
|
|
312
|
+
version = "0.1.2"
|
|
313
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
314
|
+
checksum = "beeb59e7e4c811ab37cc73680c798c7a5da77fc9989c62b09138e31ee740f735"
|
|
315
|
+
dependencies = [
|
|
316
|
+
"crc32fast",
|
|
317
|
+
"tinyvec",
|
|
318
|
+
]
|
|
319
|
+
|
|
310
320
|
[[package]]
|
|
311
321
|
name = "cc"
|
|
312
322
|
version = "1.4.7"
|
|
@@ -449,6 +459,15 @@ dependencies = [
|
|
|
449
459
|
"rustc_version",
|
|
450
460
|
]
|
|
451
461
|
|
|
462
|
+
[[package]]
|
|
463
|
+
name = "crc32fast"
|
|
464
|
+
version = "1.5.2"
|
|
465
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
466
|
+
checksum = "01a7799fd6b852db0e61728dde9a204c423b44d689dbd432522543614b490e78"
|
|
467
|
+
dependencies = [
|
|
468
|
+
"cfg-if",
|
|
469
|
+
]
|
|
470
|
+
|
|
452
471
|
[[package]]
|
|
453
472
|
name = "crossbeam-utils"
|
|
454
473
|
version = "0.8.23"
|
|
@@ -517,7 +536,7 @@ checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
|
|
|
517
536
|
|
|
518
537
|
[[package]]
|
|
519
538
|
name = "desklink-host"
|
|
520
|
-
version = "0.
|
|
539
|
+
version = "0.3.0"
|
|
521
540
|
dependencies = [
|
|
522
541
|
"anyhow",
|
|
523
542
|
"ashpd",
|
|
@@ -525,6 +544,7 @@ dependencies = [
|
|
|
525
544
|
"base64 0.22.1",
|
|
526
545
|
"block2",
|
|
527
546
|
"bytes",
|
|
547
|
+
"bzip2-rs",
|
|
528
548
|
"cc",
|
|
529
549
|
"futures-util",
|
|
530
550
|
"libc",
|
|
@@ -534,12 +554,16 @@ dependencies = [
|
|
|
534
554
|
"objc2-core-media",
|
|
535
555
|
"objc2-foundation",
|
|
536
556
|
"objc2-screen-capture-kit",
|
|
557
|
+
"openh264-sys2",
|
|
537
558
|
"pipewire",
|
|
538
559
|
"rand 0.8.8",
|
|
539
560
|
"rtc",
|
|
540
561
|
"serde",
|
|
541
562
|
"serde_json",
|
|
563
|
+
"sha2",
|
|
542
564
|
"tokio",
|
|
565
|
+
"wayland-client",
|
|
566
|
+
"wayland-protocols",
|
|
543
567
|
"webrtc",
|
|
544
568
|
"wl-clipboard-rs",
|
|
545
569
|
"x11rb",
|
|
@@ -1430,6 +1454,16 @@ version = "1.21.4"
|
|
|
1430
1454
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1431
1455
|
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|
1432
1456
|
|
|
1457
|
+
[[package]]
|
|
1458
|
+
name = "openh264-sys2"
|
|
1459
|
+
version = "0.9.8"
|
|
1460
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1461
|
+
checksum = "6ada29a4cadc13d4d326737af87c13e224210d7d99fe47594e9f3f9b0102fd70"
|
|
1462
|
+
dependencies = [
|
|
1463
|
+
"libloading",
|
|
1464
|
+
"sha2",
|
|
1465
|
+
]
|
|
1466
|
+
|
|
1433
1467
|
[[package]]
|
|
1434
1468
|
name = "ordered-stream"
|
|
1435
1469
|
version = "0.2.0"
|
|
@@ -2239,6 +2273,17 @@ dependencies = [
|
|
|
2239
2273
|
"digest",
|
|
2240
2274
|
]
|
|
2241
2275
|
|
|
2276
|
+
[[package]]
|
|
2277
|
+
name = "sha2"
|
|
2278
|
+
version = "0.10.9"
|
|
2279
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2280
|
+
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
|
2281
|
+
dependencies = [
|
|
2282
|
+
"cfg-if",
|
|
2283
|
+
"cpufeatures 0.2.17",
|
|
2284
|
+
"digest",
|
|
2285
|
+
]
|
|
2286
|
+
|
|
2242
2287
|
[[package]]
|
|
2243
2288
|
name = "shlex"
|
|
2244
2289
|
version = "1.3.0"
|
package/engine/Cargo.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "desklink-host"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.0"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
rust-version = "1.97.1"
|
|
6
6
|
license = "Apache-2.0"
|
|
@@ -30,8 +30,18 @@ rand = "0.8"
|
|
|
30
30
|
ashpd = { version = "0.11", default-features = false, features = ["tokio"] }
|
|
31
31
|
pipewire = { version = "0.10", features = ["v0_3_44"] }
|
|
32
32
|
xkbcommon = "0.8"
|
|
33
|
-
x11rb = { version = "0.14", default-features = false, features = ["allow-unsafe-code", "xtest"] }
|
|
33
|
+
x11rb = { version = "0.14", default-features = false, features = ["allow-unsafe-code", "xtest", "shm", "damage"] }
|
|
34
34
|
wl-clipboard-rs = "0.9"
|
|
35
|
+
# H.264 fallback: Cisco's prebuilt openh264, loaded at runtime (never built
|
|
36
|
+
# from source), fetched once as bzip2 and checked against a pinned sha256.
|
|
37
|
+
openh264-sys2 = { version = "0.9.8", default-features = false, features = ["libloading"] }
|
|
38
|
+
sha2 = "0.10"
|
|
39
|
+
bzip2-rs = "0.1.2"
|
|
40
|
+
|
|
41
|
+
[target.'cfg(target_os = "linux")'.dev-dependencies]
|
|
42
|
+
# The Wayland stamp example only; already in the tree through wl-clipboard-rs.
|
|
43
|
+
wayland-client = "0.31"
|
|
44
|
+
wayland-protocols = { version = "0.32", features = ["client"] }
|
|
35
45
|
|
|
36
46
|
[target.'cfg(target_os = "macos")'.dependencies]
|
|
37
47
|
anyhow = "1"
|
package/engine/build.rs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
//! Native dependencies of the engine.
|
|
2
2
|
//!
|
|
3
3
|
//! The Linux build uses two permissive C libraries, both built or linked from
|
|
4
|
-
//! this machine's own sources — no prebuilt binary is fetched, and
|
|
5
|
-
//! installed:
|
|
4
|
+
//! this machine's own sources — no prebuilt binary is fetched at build time, and
|
|
5
|
+
//! nothing is installed:
|
|
6
6
|
//!
|
|
7
7
|
//! * libvpx (BSD-3-Clause) — VP9 encode, through `native/vpx_shim.c` so the
|
|
8
8
|
//! versioned encoder config struct is laid out by a C compiler.
|
|
@@ -10,6 +10,12 @@
|
|
|
10
10
|
//! over `uinput`/`libevdev`, built by its own CMake project into a static
|
|
11
11
|
//! library and called through its documented C API.
|
|
12
12
|
//!
|
|
13
|
+
//! H.264 encoding adds no link-time dependency: NVENC and VA-API are loaded with
|
|
14
|
+
//! `dlopen` from the machine's driver at run time, compiled against vendored
|
|
15
|
+
//! MIT headers (`vendor/nv-codec-headers`, `vendor/libva`); openh264 is Cisco's
|
|
16
|
+
//! prebuilt library, fetched by the engine at run time (see `src/h264.rs`). The
|
|
17
|
+
//! macOS build links the VideoToolbox system framework.
|
|
18
|
+
//!
|
|
13
19
|
//! macOS builds only the libvpx shim; ScreenCaptureKit, Quartz input and
|
|
14
20
|
//! AppKit clipboard use native frameworks. Linux runtime input access is still
|
|
15
21
|
//! checked through `/dev/uinput`.
|
|
@@ -25,6 +31,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
25
31
|
println!("cargo:rustc-check-cfg=cfg(desklink_vpx)");
|
|
26
32
|
println!("cargo:rustc-check-cfg=cfg(desklink_macos_cli)");
|
|
27
33
|
println!("cargo:rerun-if-changed=native/vpx_shim.c");
|
|
34
|
+
println!("cargo:rerun-if-changed=native/nvenc_shim.c");
|
|
35
|
+
println!("cargo:rerun-if-changed=native/vaapi_shim.c");
|
|
36
|
+
println!("cargo:rerun-if-changed=native/vt_shim.c");
|
|
28
37
|
println!("cargo:rerun-if-changed=native/inputtino_shim.cpp");
|
|
29
38
|
println!("cargo:rerun-if-changed=native/mac_stream.mm");
|
|
30
39
|
println!("cargo:rerun-if-changed=native/agent_overlay_mac.m");
|
|
@@ -69,6 +78,18 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
69
78
|
}
|
|
70
79
|
|
|
71
80
|
if target_os == "linux" {
|
|
81
|
+
// H.264 through NVENC and VA-API: the driver libraries are dlopen'd at
|
|
82
|
+
// run time, so building needs only their vendored MIT headers, and a
|
|
83
|
+
// machine without them still runs the engine.
|
|
84
|
+
cc::Build::new()
|
|
85
|
+
.file("native/nvenc_shim.c")
|
|
86
|
+
.include("vendor/nv-codec-headers/include")
|
|
87
|
+
.compile("dlnvenc");
|
|
88
|
+
cc::Build::new()
|
|
89
|
+
.file("native/vaapi_shim.c")
|
|
90
|
+
.include("vendor/libva")
|
|
91
|
+
.compile("dlvaapi");
|
|
92
|
+
println!("cargo:rustc-link-lib=dl");
|
|
72
93
|
cc::Build::new()
|
|
73
94
|
.file("native/agent_overlay_x11.c")
|
|
74
95
|
.file("native/agent_overlay_wayland.c")
|
|
@@ -114,6 +135,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
114
135
|
);
|
|
115
136
|
println!("cargo:rustc-link-lib=static=vpx");
|
|
116
137
|
println!("cargo:rustc-cfg=desklink_vpx");
|
|
138
|
+
// H.264 for receivers that decode it in hardware; VideoToolbox is a
|
|
139
|
+
// system framework, so linking it adds no dependency.
|
|
140
|
+
cc::Build::new().file("native/vt_shim.c").compile("dlvt");
|
|
141
|
+
println!("cargo:rustc-link-lib=framework=VideoToolbox");
|
|
142
|
+
println!("cargo:rustc-link-lib=framework=CoreFoundation");
|
|
117
143
|
}
|
|
118
144
|
println!("cargo:rustc-link-lib=framework=CoreGraphics");
|
|
119
145
|
println!("cargo:rustc-link-lib=framework=ApplicationServices");
|