Skip to content

Commit 66eeeed

Browse files
committed
fix: improve android display streaming
1 parent 3b59dd3 commit 66eeeed

26 files changed

Lines changed: 807 additions & 2025 deletions

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ Normal service restarts preserve that token so paired clients stay connected.
8989
Use `simdeck service reset` only when you want to rotate the service token and
9090
restart the LaunchAgent.
9191
The service uses port 4310 unless you pass `-p` or `--port`.
92+
SimDeck-owned Android emulator boots use host GPU rendering by default; use
93+
`simdeck service restart --android-gpu auto` or
94+
`--android-gpu swiftshader_indirect` only as a machine-specific fallback.
9295
Use `simdeck service kill` when you want to stop every SimDeck service process,
9396
including services started from another checkout or installed binary.
9497

@@ -130,7 +133,6 @@ simdeck pasteboard get
130133
simdeck screenshot --output screen.png
131134
simdeck screenshot --with-bezel --output screen-bezel.png
132135
simdeck record --seconds 5 --output screen-recording.mp4
133-
simdeck stream --frames 120 > stream.h264
134136
simdeck describe
135137
simdeck describe --format agent --max-depth 4
136138
simdeck describe --format agent --max-depth 4 --interactive

docs/api/health.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Example:
2121
"serverKind": "launchAgent",
2222
"timestamp": 1714094761.234,
2323
"videoCodec": "auto",
24+
"androidGpu": "host",
2425
"lowLatency": false,
2526
"realtimeStream": true,
2627
"localStreamFps": 60,
@@ -46,6 +47,7 @@ Important fields:
4647
| `httpPort` | Port serving UI and API |
4748
| `serverKind` | `launchAgent` or `standalone` |
4849
| `videoCodec` | Requested codec mode: `auto`, `hardware`, or `software` |
50+
| `androidGpu` | Android emulator renderer mode for SimDeck-owned boots |
4951
| `streamQuality` | Active stream profile and limits |
5052
| `webRtc` | ICE settings the browser should use |
5153

@@ -90,7 +92,7 @@ Content-Type: application/json
9092
"clientId": "browser-ABC",
9193
"kind": "viewport",
9294
"udid": "9D7E5BB7-...",
93-
"codec": "h264",
95+
"codec": "video/H264/103",
9496
"decodedFps": 59.7,
9597
"droppedFps": 0.0,
9698
"latestRenderMs": 6.2

docs/api/rest.md

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -165,15 +165,14 @@ Performance query parameters:
165165

166166
## Live video
167167

168-
| Method | Path | Purpose |
169-
| ------ | ------------------------------------- | -------------------------------------- |
170-
| `POST` | `/api/simulators/{udid}/webrtc/offer` | WebRTC offer/answer stream setup |
171-
| `GET` | `/api/simulators/{udid}/h264` | H.264 WebSocket fallback |
172-
| `GET` | `/api/simulators/{udid}/input` | Input WebSocket for fallback transport |
173-
| `GET` | `/api/simulators/{udid}/control` | Alias for input control WebSocket |
174-
| `POST` | `/api/simulators/{udid}/refresh` | Request a fresh frame or keyframe |
175-
176-
For normal clients, copy the browser behavior instead of hand-coding a raw decoder. The UI supports WebRTC first and H.264 WebSocket fallback. Android emulator IDs use the same endpoints; their H.264 frames are produced from the emulator `-share-vid` display surface, not screenshot polling.
168+
| Method | Path | Purpose |
169+
| ------ | ------------------------------------- | ------------------------------------- |
170+
| `POST` | `/api/simulators/{udid}/webrtc/offer` | WebRTC offer/answer stream setup |
171+
| `GET` | `/api/simulators/{udid}/input` | Input WebSocket fallback for controls |
172+
| `GET` | `/api/simulators/{udid}/control` | Alias for input control WebSocket |
173+
| `POST` | `/api/simulators/{udid}/refresh` | Request a fresh frame or keyframe |
174+
175+
For normal clients, copy the browser behavior instead of hand-coding a raw decoder. The UI uses the WebRTC offer endpoint for live video. Android emulator IDs use the same WebRTC endpoint; their H.264 frames are produced from the emulator `-share-vid` display surface, not screenshot polling.
177176

178177
Minimal WebRTC request:
179178

docs/cli/commands.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -207,12 +207,6 @@ simdeck logs --seconds 30 --limit 200
207207
simdeck chrome-profile
208208
```
209209

210-
Diagnostic iOS H.264 stream:
211-
212-
```sh
213-
simdeck stream --frames 120 > stream.h264
214-
```
215-
216210
## Studio and providers
217211

218212
For hosted Studio workflows:

docs/cli/flags.md

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,19 @@ When `service restart` is run without `--port`, it preserves the installed
2626
LaunchAgent port or the current singleton service port before falling back to
2727
`4310`.
2828

29-
| Flag | Default | Notes |
30-
| ---------------------------- | -------------- | --------------------------------------------------------------------------------- |
31-
| `--port <port>` / `-p` | `4310` | HTTP port; `service restart` preserves the existing service port when omitted |
32-
| `--bind <ip>` | `127.0.0.1` | Use `0.0.0.0` or `::` for LAN access |
33-
| `--advertise-host <host>` | detected | Host printed for remote browsers |
34-
| `--client-root <path>` | bundled client | Static client directory |
35-
| `--video-codec <mode>` | `auto` | `auto`, `hardware`, or `software` |
36-
| `--stream-quality <profile>` | `full` | `full`, `balanced`, `economy`, `low`, `tiny`, `ci-software`, and related profiles |
37-
| `--local-stream-fps <fps>` | `60` | Local stream frame target |
38-
| `--low-latency` | off | Conservative software H.264 profile |
39-
| `--open` | off | Open the browser after starting the service |
40-
| `--autostart` / `-a` | off | Register the service as a macOS LaunchAgent |
29+
| Flag | Default | Notes |
30+
| ---------------------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------- |
31+
| `--port <port>` / `-p` | `4310` | HTTP port; `service restart` preserves the existing service port when omitted |
32+
| `--bind <ip>` | `127.0.0.1` | Use `0.0.0.0` or `::` for LAN access |
33+
| `--advertise-host <host>` | detected | Host printed for remote browsers |
34+
| `--client-root <path>` | bundled client | Static client directory |
35+
| `--video-codec <mode>` | `auto` | `auto`, `hardware`, or `software` |
36+
| `--android-gpu <mode>` | `host` | Android emulator renderer: `host`, `auto`, `software`, `lavapipe`, `swiftshader`, `swangle`, or `swiftshader_indirect` |
37+
| `--stream-quality <profile>` | `full` | `full`, `balanced`, `smooth`, `economy`, `low`, `tiny`, `ci-software`, and related profiles |
38+
| `--local-stream-fps <fps>` | `60` | Local stream frame target |
39+
| `--low-latency` | off | Conservative software H.264 profile |
40+
| `--open` | off | Open the browser after starting the service |
41+
| `--autostart` / `-a` | off | Register the service as a macOS LaunchAgent |
4142

4243
## `describe`
4344

docs/extensions/browser-client.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ Force a stream transport while debugging:
3838

3939
```text
4040
http://127.0.0.1:4310?stream=webrtc
41-
http://127.0.0.1:4310?stream=h264
4241
```
4342

4443
Use the default URL for normal operation.

docs/guide/architecture.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ This is why a long-lived service feels faster than repeatedly calling lower-leve
2626

2727
## Video flow
2828

29-
The browser opens a live stream for the selected device. SimDeck sends fresh frames, drops stale ones when a client falls behind, and lets the browser request refreshes. iOS frames come from the native display bridge and are encoded on the Mac; Android frames come from the emulator `-share-vid` shared display surface and are encoded on the Mac. The UI can use WebRTC or H.264-over-WebSocket fallback depending on browser support and network behavior.
29+
The browser opens a live WebRTC stream for the selected device. SimDeck sends fresh frames, drops stale ones when a client falls behind, and lets the browser request refreshes. iOS frames come from the native display bridge and are encoded on the Mac; Android frames come from the emulator `-share-vid` shared display surface and are encoded on the Mac.
3030

3131
Tune this from the user-facing controls or with:
3232

docs/guide/service.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,16 @@ LaunchAgent port or the current singleton service port before falling back to
6363
These options are accepted by `simdeck`, `service start`, `service restart`,
6464
`service on`, and `service reset`:
6565

66-
| Flag | Default | Use it when |
67-
| ---------------------------- | ----------- | ------------------------------------------ |
68-
| `--port <port>` / `-p` | `4310` | You want a specific service port |
69-
| `--bind <ip>` | `127.0.0.1` | You need LAN access with `0.0.0.0` or `::` |
70-
| `--advertise-host <host>` | detected | Remote browsers need a specific host or IP |
71-
| `--video-codec <mode>` | `auto` | You need to force encoder behavior |
72-
| `--stream-quality <profile>` | `full` | You want lower CPU or bandwidth use |
73-
| `--local-stream-fps <fps>` | `60` | You want a different local stream target |
74-
| `--client-root <path>` | bundled UI | You are serving a custom static client |
66+
| Flag | Default | Use it when |
67+
| ---------------------------- | ----------- | ------------------------------------------------- |
68+
| `--port <port>` / `-p` | `4310` | You want a specific service port |
69+
| `--bind <ip>` | `127.0.0.1` | You need LAN access with `0.0.0.0` or `::` |
70+
| `--advertise-host <host>` | detected | Remote browsers need a specific host or IP |
71+
| `--video-codec <mode>` | `auto` | You need to force encoder behavior |
72+
| `--android-gpu <mode>` | `host` | You need to change Android emulator GPU rendering |
73+
| `--stream-quality <profile>` | `full` | You want lower CPU or bandwidth use |
74+
| `--local-stream-fps <fps>` | `60` | You want a different local stream target |
75+
| `--client-root <path>` | bundled UI | You are serving a custom static client |
7576

7677
## Restart CoreSimulator
7778

docs/guide/troubleshooting.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,14 +137,14 @@ curl http://127.0.0.1:4310/api/metrics
137137

138138
If `frames_dropped_server` keeps climbing, the client or network cannot keep up. Move closer to the host, reduce quality, or switch to software encoding.
139139

140-
For Android emulator streams, SimDeck uses the emulator `-share-vid` shared display surface. If Android video never starts, confirm `adb devices` shows the emulator as `device`, that it has fully booted, and that externally launched emulators were started with `-share-vid`. SimDeck-owned Android boots add the flag automatically.
140+
For Android emulator streams, SimDeck uses the emulator `-share-vid` shared display surface. If Android video never starts, confirm `adb devices` shows the emulator as `device`, that it has fully booted, and that externally launched emulators were started with `-share-vid`. SimDeck-owned Android boots add the flag automatically and default to `--android-gpu host`; try `simdeck service restart --android-gpu auto` or `--android-gpu swiftshader_indirect` only when host rendering is unstable.
141141

142142
### Browser cannot establish WebRTC
143143

144-
Force the H.264 WebSocket fallback while testing:
144+
Use `?stream=webrtc` while testing to make transport selection explicit:
145145

146146
```text
147-
http://127.0.0.1:4310?stream=h264
147+
http://127.0.0.1:4310?stream=webrtc
148148
```
149149

150150
For routed remote sessions, configure TURN as described in [Video and streaming](/guide/video#remote-browsers).

docs/guide/video.md

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
# Video and streaming
22

3-
SimDeck streams live device video to the browser. Local sessions default to high quality. Remote or constrained sessions can trade detail for lower CPU and latency.
3+
SimDeck streams live device video to the browser. Local sessions default to full-resolution 60 fps. Remote or constrained sessions can trade detail for lower CPU and latency.
44

55
iOS simulator H.264 uses VideoToolbox for hardware encoding and x264 for software encoding.
66
Android emulator H.264 uses the emulator `-share-vid` display surface. SimDeck reads BGRA frames from the `videmulator<console-port>` shared memory region and encodes them on the Mac, so normal Android live video stays on the native shared display path.
77

88
## When encoding runs
99

1010
SimDeck starts encoding when a browser stream needs H.264 frames. For iOS, the
11-
server requests an initial keyframe to answer the WebRTC or H.264 WebSocket
12-
viewer, then keeps a shared refresh pump active while frame subscribers exist.
11+
server requests an initial keyframe to answer the WebRTC viewer, then keeps a
12+
shared refresh pump active while frame subscribers exist.
1313
For Android, SimDeck starts emulators with `-share-vid`, maps the shared display
1414
region, and feeds changed BGRA frames into the native host H.264 encoder.
15+
SimDeck-owned Android boots also default to `-gpu host`, matching the native
16+
emulator app's accelerated renderer while staying in headless shared-video mode.
1517

1618
The browser reports whether the page and stream canvas are foreground. When all
1719
known viewers are hidden or the last frame subscriber disconnects, the native
@@ -38,7 +40,8 @@ Common profiles:
3840

3941
| Profile | Use it for |
4042
| ------------- | --------------------------------------- |
41-
| `full` | Local browser on a fast Mac |
43+
| `full` | Default local full-resolution 60 fps |
44+
| `smooth` | Full-size 60 fps with lower bitrate |
4245
| `balanced` | Good local quality with less bandwidth |
4346
| `economy` | Remote browser or busy machine |
4447
| `low` | Slower Wi-Fi or shared hosts |
@@ -47,6 +50,18 @@ Common profiles:
4750

4851
The browser also has stream controls for transport, resolution, FPS, and refresh.
4952

53+
## Pick an Android GPU mode
54+
55+
SimDeck-owned Android emulator boots use host GPU acceleration by default:
56+
57+
```sh
58+
simdeck service restart --android-gpu host
59+
```
60+
61+
Use `auto` to let the Android emulator choose the renderer. Use
62+
`swiftshader_indirect`, `swiftshader`, `software`, `lavapipe`, or `swangle` only
63+
when host rendering is unstable on a specific machine.
64+
5065
## Pick a codec
5166

5267
```sh
@@ -61,11 +76,11 @@ simdeck service restart --video-codec software
6176
| `hardware` | Dedicated local machines where VideoToolbox hardware H.264 is reliable. |
6277
| `software` | x264 software H.264 for CI, screen recording conflicts, or hardware encoder stalls. |
6378

64-
The codec setting controls iOS simulator host encoding. Android emulator streams
65-
use a dedicated host encoder for shared display frames; set
66-
`SIMDECK_ANDROID_VIDEO_CODEC=hardware` or `software` before starting the service
67-
when you need to override Android's encoder choice. Stream quality controls the
68-
encoded Android frame size.
79+
The codec setting controls simulator host encoding. Android emulator streams use
80+
the same service codec by default for shared display frames; set
81+
`SIMDECK_ANDROID_VIDEO_CODEC=auto`, `hardware`, or `software` before starting the
82+
service only when you need an Android-specific encoder override. Stream quality
83+
controls the encoded Android frame size.
6984

7085
When multiple simulator streams run at the same time, `auto` keeps one active
7186
stream on the hardware encoder path and routes additional active auto streams to
@@ -78,15 +93,14 @@ For very constrained software sessions:
7893
simdeck service restart --video-codec software --low-latency
7994
```
8095

81-
## WebRTC and fallback
96+
## WebRTC
8297

83-
The browser tries WebRTC first. If WebRTC cannot render a frame, the UI can fall back to H.264 over WebSocket when the browser supports WebCodecs.
98+
The browser uses WebRTC for live video. SimDeck no longer exposes a separate H.264 WebSocket video transport.
8499

85100
Force a mode while debugging:
86101

87102
```text
88103
http://127.0.0.1:4310?stream=webrtc
89-
http://127.0.0.1:4310?stream=h264
90104
```
91105

92106
## Remote browsers

0 commit comments

Comments
 (0)