Skip to content

Commit a6446b3

Browse files
committed
Add explicit video codec modes
1 parent 8225d16 commit a6446b3

17 files changed

Lines changed: 144 additions & 82 deletions

File tree

.github/workflows/simdeck-provider.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ jobs:
222222
--bind 127.0.0.1 \
223223
--access-token "$PROVIDER_TOKEN" \
224224
--client-root "$PWD/client/dist" \
225-
--video-codec h264-software \
225+
--video-codec software \
226226
--stream-quality "${SIMDECK_STREAM_QUALITY:-ci-software}" \
227227
>> simdeck.log 2>&1 &
228228
simdeck_pid="$!"

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,9 @@ simdeck studio expose "iPhone 17 Pro"
7777

7878
The command starts or reuses the local daemon, creates an ephemeral Studio
7979
session, prints a unique `https://simdeck.djdev.me/simulator/...` URL, and keeps
80-
the outbound bridge alive until you press Ctrl-C. It uses hardware H.264 by
81-
default with realtime stream settings for remote viewing. Pass `--software-h264`
82-
when hardware encode is unavailable; Studio then defaults to the `ci-software`
80+
the outbound bridge alive until you press Ctrl-C. It uses `auto` mode by default,
81+
letting VideoToolbox choose the encoder. Pass `--video-codec software` when you
82+
need to force software encoding; Studio then defaults to the `ci-software`
8383
stream quality profile (`960` longest edge at `24` fps). Use
8484
`--stream-quality quality|balanced|smooth|economy|ci-software` to override it.
8585

@@ -110,7 +110,7 @@ Use software H.264's low-latency profile on slower runners where freshness is
110110
more important than full-resolution smoothness:
111111

112112
```sh
113-
simdeck daemon start --video-codec h264-software --low-latency
113+
simdeck daemon start --video-codec software --low-latency
114114
```
115115

116116
Restart the CoreSimulator service layer when `simctl` reports a stale service

cli/XCWH264Encoder.m

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,24 @@
3838
static const NSUInteger XCWRealtimeHardwareHealthyFrameWindow = 6;
3939

4040
typedef NS_ENUM(NSUInteger, XCWVideoEncoderMode) {
41+
XCWVideoEncoderModeAuto,
4142
XCWVideoEncoderModeH264Hardware,
4243
XCWVideoEncoderModeH264Software,
4344
};
4445

4546
static XCWVideoEncoderMode XCWVideoEncoderModeFromEnvironment(void) {
4647
const char *rawValue = getenv("SIMDECK_VIDEO_CODEC");
4748
NSString *value = rawValue != NULL ? [[[NSString alloc] initWithUTF8String:rawValue] lowercaseString] : @"";
48-
if ([value isEqualToString:@"h264"] || [value isEqualToString:@"h264-hardware"] || [value isEqualToString:@"avc"]) {
49+
if (value.length == 0 || [value isEqualToString:@"auto"]) {
50+
return XCWVideoEncoderModeAuto;
51+
}
52+
if ([value isEqualToString:@"hardware"]) {
4953
return XCWVideoEncoderModeH264Hardware;
5054
}
51-
if ([value isEqualToString:@"h264-software"] || [value isEqualToString:@"software-h264"]) {
55+
if ([value isEqualToString:@"software"]) {
5256
return XCWVideoEncoderModeH264Software;
5357
}
54-
return XCWVideoEncoderModeH264Software;
58+
return XCWVideoEncoderModeAuto;
5559
}
5660

5761
static BOOL XCWLowLatencyModeFromEnvironment(void) {
@@ -149,6 +153,7 @@ static int32_t XCWRealtimeMinimumAverageBitRate(void) {
149153

150154
static CMVideoCodecType XCWVideoCodecTypeForMode(XCWVideoEncoderMode mode) {
151155
switch (mode) {
156+
case XCWVideoEncoderModeAuto:
152157
case XCWVideoEncoderModeH264Hardware:
153158
case XCWVideoEncoderModeH264Software:
154159
default:
@@ -158,16 +163,19 @@ static CMVideoCodecType XCWVideoCodecTypeForMode(XCWVideoEncoderMode mode) {
158163

159164
static NSString *XCWVideoEncoderModeName(XCWVideoEncoderMode mode) {
160165
switch (mode) {
166+
case XCWVideoEncoderModeAuto:
167+
return @"auto";
161168
case XCWVideoEncoderModeH264Hardware:
162-
return @"h264";
169+
return @"hardware";
163170
case XCWVideoEncoderModeH264Software:
164171
default:
165-
return @"h264-software";
172+
return @"software";
166173
}
167174
}
168175

169176
static NSString *XCWVideoEncoderIDForMode(XCWVideoEncoderMode mode) {
170177
switch (mode) {
178+
case XCWVideoEncoderModeAuto:
171179
case XCWVideoEncoderModeH264Hardware:
172180
return nil;
173181
case XCWVideoEncoderModeH264Software:
@@ -648,7 +656,7 @@ - (int32_t)expectedFrameRateLocked {
648656
}
649657

650658
- (BOOL)shouldPaceRealtimeHardwareFrameAtTimeUs:(uint64_t)nowUs {
651-
if (_encoderMode != XCWVideoEncoderModeH264Hardware || !_realtimeStreamMode || _needsKeyFrame) {
659+
if ((_encoderMode != XCWVideoEncoderModeAuto && _encoderMode != XCWVideoEncoderModeH264Hardware) || !_realtimeStreamMode || _needsKeyFrame) {
652660
return NO;
653661
}
654662
if (_realtimeHardwareFrameIntervalUs == 0) {
@@ -723,7 +731,7 @@ - (void)adaptSoftwarePacingForLatencyUs:(uint64_t)latencyUs {
723731
}
724732

725733
- (void)adaptRealtimeHardwarePacingForLatencyUs:(uint64_t)latencyUs {
726-
if (_encoderMode != XCWVideoEncoderModeH264Hardware || !_realtimeStreamMode || latencyUs == 0) {
734+
if ((_encoderMode != XCWVideoEncoderModeAuto && _encoderMode != XCWVideoEncoderModeH264Hardware) || !_realtimeStreamMode || latencyUs == 0) {
727735
return;
728736
}
729737
if (_realtimeHardwareFrameIntervalUs == 0) {
@@ -843,7 +851,7 @@ - (BOOL)encodePixelBufferLocked:(CVPixelBufferRef)pixelBuffer {
843851
_submittedFrameCount += 1;
844852
if (_encoderMode == XCWVideoEncoderModeH264Software) {
845853
_lastSoftwareSubmissionUs = nowUs;
846-
} else if (_encoderMode == XCWVideoEncoderModeH264Hardware && _realtimeStreamMode) {
854+
} else if ((_encoderMode == XCWVideoEncoderModeAuto || _encoderMode == XCWVideoEncoderModeH264Hardware) && _realtimeStreamMode) {
847855
_lastRealtimeHardwareSubmissionUs = nowUs;
848856
}
849857
_maxInFlightFrameCount = MAX(_maxInFlightFrameCount, _inFlightFrameCount);
@@ -872,7 +880,7 @@ - (BOOL)ensureCompressionSessionWithWidth:(int32_t)width height:(int32_t)height
872880
}
873881
if (_encoderMode == XCWVideoEncoderModeH264Software) {
874882
encoderSpecification[(__bridge NSString *)kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder] = @NO;
875-
} else {
883+
} else if (_encoderMode == XCWVideoEncoderModeH264Hardware) {
876884
encoderSpecification[(__bridge NSString *)kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder] = @YES;
877885
}
878886

docs/api/health.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Returns the static bootstrap information the browser client needs, plus a freshn
1111
"ok": true,
1212
"httpPort": 4310,
1313
"timestamp": 1714094761.234,
14-
"videoCodec": "h264",
14+
"videoCodec": "auto",
1515
"lowLatency": false,
1616
"webRtc": {
1717
"iceServers": [{ "urls": ["stun:stun.l.google.com:19302"] }],
@@ -20,17 +20,17 @@ Returns the static bootstrap information the browser client needs, plus a freshn
2020
}
2121
```
2222

23-
| Field | Notes |
24-
| --------------------------- | ----------------------------------------------------------------------------------------- |
25-
| `ok` | Always `true` if the route is reachable. Network failures are signalled by HTTP errors. |
26-
| `httpPort` | HTTP port for the REST API, browser UI, and WebRTC offer endpoint. |
27-
| `timestamp` | Server-side `time.now()` as a fractional Unix epoch in seconds. |
28-
| `videoCodec` | Active encoder. One of `h264` or `h264-software`. See [Video Pipeline](/guide/video). |
29-
| `lowLatency` | `true` when software H.264 low-latency mode was enabled at daemon startup. |
30-
| `realtimeStream` | `true` when the WebRTC stream is configured to favor freshness and realtime pacing. |
31-
| `streamQuality` | Active realtime quality profile and encoder limits such as `maxEdge`, `fps`, and bitrate. |
32-
| `webRtc.iceServers` | ICE servers the browser should use when creating the WebRTC peer connection. |
33-
| `webRtc.iceTransportPolicy` | Browser ICE transport policy. One of `all` or `relay`. |
23+
| Field | Notes |
24+
| --------------------------- | ----------------------------------------------------------------------------------------------------- |
25+
| `ok` | Always `true` if the route is reachable. Network failures are signalled by HTTP errors. |
26+
| `httpPort` | HTTP port for the REST API, browser UI, and WebRTC offer endpoint. |
27+
| `timestamp` | Server-side `time.now()` as a fractional Unix epoch in seconds. |
28+
| `videoCodec` | Requested encoder mode. One of `auto`, `hardware`, or `software`. See [Video Pipeline](/guide/video). |
29+
| `lowLatency` | `true` when software H.264 low-latency mode was enabled at daemon startup. |
30+
| `realtimeStream` | `true` when the WebRTC stream is configured to favor freshness and realtime pacing. |
31+
| `streamQuality` | Active realtime quality profile and encoder limits such as `maxEdge`, `fps`, and bitrate. |
32+
| `webRtc.iceServers` | ICE servers the browser should use when creating the WebRTC peer connection. |
33+
| `webRtc.iceTransportPolicy` | Browser ICE transport policy. One of `all` or `relay`. |
3434

3535
The default access token is regenerated every time the server restarts. A client should refetch `/api/health` after any disconnection.
3636

docs/api/rest.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Returns server health and the active video encoder mode.
2222
"ok": true,
2323
"httpPort": 4310,
2424
"timestamp": 1714094761.234,
25-
"videoCodec": "h264",
25+
"videoCodec": "auto",
2626
"lowLatency": false,
2727
"webRtc": {
2828
"iceServers": [{ "urls": ["stun:stun.l.google.com:19302"] }],
@@ -146,8 +146,8 @@ and the server responds with an SDP answer for a receive-only H.264 video track:
146146
}
147147
```
148148

149-
The endpoint requires the active simulator stream codec to be `h264` or
150-
`h264-software`. The bundled browser client always uses this endpoint.
149+
The endpoint requires the active simulator stream to produce H.264-compatible
150+
samples. The bundled browser client always uses this endpoint.
151151

152152
### `POST /api/simulators/{udid}/open-url`
153153

docs/cli/commands.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Start or reuse the project daemon and serve the browser UI.
3131

3232
```sh
3333
simdeck ui [--port 4310] [--bind 127.0.0.1] [--advertise-host <host>]
34-
[--client-root <path>] [--video-codec h264|h264-software]
34+
[--client-root <path>] [--video-codec auto|hardware|software]
3535
[--low-latency] [--stream-quality <profile>] [--open]
3636
```
3737

@@ -44,7 +44,7 @@ Start or reuse the project daemon without opening the browser:
4444
```sh
4545
simdeck daemon start [--port 4310] [--bind 127.0.0.1]
4646
[--advertise-host <host>] [--client-root <path>]
47-
[--video-codec h264|h264-software] [--low-latency]
47+
[--video-codec auto|hardware|software] [--low-latency]
4848
[--stream-quality <profile>]
4949
```
5050

@@ -80,7 +80,7 @@ options as `daemon start`:
8080
```sh
8181
simdeck daemon restart [--port 4310] [--bind 127.0.0.1]
8282
[--advertise-host <host>] [--client-root <path>]
83-
[--video-codec h264|h264-software] [--low-latency]
83+
[--video-codec auto|hardware|software] [--low-latency]
8484
[--stream-quality <profile>]
8585
```
8686

@@ -109,7 +109,7 @@ that starts after login and stays available.
109109
```sh
110110
simdeck service on [--port 4310] [--bind 127.0.0.1]
111111
[--advertise-host <host>] [--client-root <path>]
112-
[--video-codec h264|h264-software] [--low-latency]
112+
[--video-codec auto|hardware|software] [--low-latency]
113113
[--stream-quality <profile>] [--access-token <token>]
114114
simdeck service restart [same options as service on]
115115
simdeck service off

docs/cli/flags.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Targets a specific running SimDeck daemon for commands that support the HTTP fas
3434
| `--bind <ip>` | `127.0.0.1` | Bind address (`0.0.0.0` for [LAN access](/guide/lan-access), `::` for IPv6). |
3535
| `--advertise-host` | matches local host | Hostname or IP printed for LAN browser access. |
3636
| `--client-root` | bundled `client/dist` | Override the static browser client directory. |
37-
| `--video-codec` | `h264` | One of `h264` or `h264-software`. See [Video Pipeline](/guide/video). |
37+
| `--video-codec` | `auto` | One of `auto`, `hardware`, or `software`. See [Video Pipeline](/guide/video). |
3838
| `--low-latency` | `false` | Software H.264 profile for slower runners: caps at 15 fps and favors freshness. |
3939
| `--stream-quality` | auto/default | Optional realtime stream quality profile: `quality`, `balanced`, `smooth`, `economy`, or `ci-software`. |
4040
| `--open` | `false` | `ui` only. Open the browser after the daemon is ready. |

docs/guide/daemon.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ This starts or reuses the project daemon, serves the bundled browser client, and
6060
| `--bind <ip>` | `127.0.0.1` | Bind address. Use `0.0.0.0` for [LAN access](/guide/lan-access). |
6161
| `--advertise-host` | matches local host | Hostname or IP advertised to browser clients. |
6262
| `--client-root` | bundled `client/dist` | Override the static browser client directory. |
63-
| `--video-codec` | `h264` | One of `h264` or `h264-software`. See [Video](/guide/video). |
63+
| `--video-codec` | `auto` | One of `auto`, `hardware`, or `software`. See [Video](/guide/video). |
6464
| `--low-latency` | `false` | Software H.264 profile for slower runners; caps at 15 fps and drops stale frames. |
6565
| `--stream-quality` | auto/default | Optional realtime stream quality profile, including `ci-software` for CI providers. |
6666
| `--open` | `false` | `ui` only. Open the browser after the daemon is ready. |
@@ -122,7 +122,7 @@ default and serves the bundled browser client.
122122
Restart it after changing options:
123123

124124
```sh
125-
simdeck service restart --port 4310 --video-codec h264-software --low-latency
125+
simdeck service restart --port 4310 --video-codec software --low-latency
126126
```
127127

128128
Disable it when you do not want a persistent daemon:

docs/guide/lan-access.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ Whatever you advertise must be resolvable from the remote client.
4848
{
4949
"ok": true,
5050
"httpPort": 4310,
51-
"videoCodec": "h264",
51+
"videoCodec": "auto",
5252
"lowLatency": false,
5353
"webRtc": {
5454
"iceServers": [{ "urls": ["stun:stun.l.google.com:19302"] }],

docs/guide/troubleshooting.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,11 @@ The encoder did not produce a keyframe within 3 seconds. The most common causes:
8282

8383
```sh
8484
simdeck daemon stop
85-
simdeck daemon start --video-codec h264-software
85+
simdeck daemon start --video-codec software
8686
```
8787

8888
On virtualized CI Macs where hardware H.264 is unavailable, use
89-
`--video-codec h264-software --stream-quality ci-software`. That profile
89+
`--video-codec software --stream-quality ci-software`. That profile
9090
targets a 960-pixel longest edge at 24 fps and lowers bitrate/CPU pressure
9191
before backlog turns into visible stream delay.
9292

0 commit comments

Comments
 (0)