Skip to content

Clamp lower-layer encoding against the top layer#1001

Merged
pblazej merged 1 commit into
mainfrom
blaze/simulcast-invariants
May 14, 2026
Merged

Clamp lower-layer encoding against the top layer#1001
pblazej merged 1 commit into
mainfrom
blaze/simulcast-invariants

Conversation

@pblazej
Copy link
Copy Markdown
Contributor

@pblazej pblazej commented May 12, 2026

Summary

  • Lower simulcast layers (q, h) are now clamped against the user-configured top encoding: maxFps unconditionally, and maxBitrate when scaleDownBy <= 1.0. A same-resolution lower layer can no longer outspend the top.
  • Extracts computeVideoEncodings and a new pure helper computeSimulcastPresets into Sources/LiveKit/Support/Utils+VideoEncodings.swift so the preset-resolution logic is testable from LiveKitCoreTests (the WebRTC-typed return of computeVideoEncodings is not reachable via @testable import).

Fixes #1000.

Test plan

@pblazej
Copy link
Copy Markdown
Contributor Author

pblazej commented May 12, 2026

Note on the bitrate clamp — stricter than the JS / Android SDKs.

Both peer SDKs only clamp maxFps on lower layers; maxBitrate is left intact:

This PR additionally clamps maxBitrate when scaleDownBy <= 1.0 (i.e. the layer's resolution is not actually being scaled down vs. the top). That's the exact pathology from #1000presetH720_169 used as the h layer with a top encoding at the same 1280×720 resolution but lower bitrate. Layers that genuinely scale down still keep their preset bitrate, matching the JS/Android behavior.

Worth porting upstream into the Rust SDK too (livekit/src/room/options.rs compute_video_encodings has the same bug — no clamping at all).

@pblazej pblazej changed the title fix(simulcast): clamp lower-layer encoding against the top layer Clamp lower-layer encoding against the top layer May 12, 2026
The middle simulcast layer was emitted with the raw preset's maxFps and
maxBitrate, allowing it to exceed the user-configured top layer when a
high-fps/high-bitrate preset (e.g. presetH720_169 at 30 fps / 1.7 Mbps)
was used alongside a more conservative top encoding (e.g. 24 fps / 1.5
Mbps at the same 1280x720 resolution).

Lower layers (q, h) are now clamped against the top encoding: maxFps
unconditionally, and maxBitrate when scaleDownBy <= 1.0 so a
same-resolution layer cannot outspend the top.

Refs #1000
@pblazej pblazej force-pushed the blaze/simulcast-invariants branch from 00f1993 to 9a7752b Compare May 12, 2026 09:45
@pblazej pblazej merged commit 2433b07 into main May 14, 2026
28 checks passed
@pblazej pblazej deleted the blaze/simulcast-invariants branch May 14, 2026 12:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Simulcast middle layer encoding parameters can exceed the user-configured top layer

2 participants