Skip to content

Dynacast: keep SVC tracks active while any quality is subscribed#1214

Open
MaxHeimbrock wants to merge 1 commit into
max/fix-dynacast-non-simulcastfrom
max/dynacast-svc-any-enabled
Open

Dynacast: keep SVC tracks active while any quality is subscribed#1214
MaxHeimbrock wants to merge 1 commit into
max/fix-dynacast-non-simulcastfrom
max/dynacast-svc-any-enabled

Conversation

@MaxHeimbrock

Copy link
Copy Markdown
Contributor

Stacked on #1213 (targets that branch; rebase to main once it merges).

What

Ports the SVC special case from client-sdk-js that #1003 didn't bring over: for SVC codecs (VP9/AV1) all spatial layers ride in a single encoded stream and the SFU selects layers server-side. When a SubscribedQualityUpdate has any quality enabled, the whole encoding must stay active, instead of matching qualities per encoding (which can deactivate the track, e.g. if the SFU enables only a quality that doesn't map to the rid-less encoding).

JS reference: setPublishingLayersForSender in livekit-clientif (isSVC) { if (qualities.some(q => q.enabled)) qualities.forEach(q => q.enabled = true); }, with isSVCCodec = vp9 || av1.

Changes

  • LocalVideoTrack::set_publishing_layers takes is_svc and applies the any-enabled rule.
  • handle_subscribed_quality_update derives is_svc from the publication's codec (VP9/AV1), mirroring isSVCCodec in JS.
  • New e2e test test_dynacast_svc (VP9, L3T3_KEY): the single SVC encoding stays active across LOW/HIGH quality requests, deactivates when the last subscriber unsubscribes, and reactivates on resubscribe.
  • SolidColorTrack::publish_with_options test helper for publishing with custom TrackPublishOptions.

Testing

All dynacast e2e tests pass against a local livekit-server --dev:

test test_dynacast ... ok
test test_dynacast_multiple_subscribers_only_publish_requested_tracks ... ok
test test_dynacast_svc ... ok

Observed SFU updates in the new test confirm the flow: vp9:[Low=true, Medium=false, High=false] on a LOW request keeps the encoding ON; [Low=false, Medium=false, High=false] after unsubscribe turns it off.

🤖 Generated with Claude Code

@MaxHeimbrock MaxHeimbrock requested a review from ladvoc as a code owner July 2, 2026 10:03
@MaxHeimbrock MaxHeimbrock force-pushed the max/dynacast-svc-any-enabled branch from b3509d2 to 00d2c3d Compare July 2, 2026 10:04
Port the SVC special case from client-sdk-js: for SVC codecs (VP9/AV1)
all spatial layers ride in a single encoded stream and the SFU selects
layers server-side, so any enabled quality in a SubscribedQualityUpdate
must keep the whole encoding active instead of being matched per-layer.

Adds an e2e test publishing VP9 L3T3_KEY that verifies the encoding
stays active across quality requests, deactivates when the last
subscriber leaves, and reactivates on resubscribe.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@MaxHeimbrock MaxHeimbrock force-pushed the max/dynacast-svc-any-enabled branch from 00d2c3d to 114340b Compare July 2, 2026 10:07
Comment on lines +446 to +449
let sub_options = TestRoomOptions::default();

let mut rooms = test_rooms_with_options([pub_options, sub_options]).await?;
let (pub_room, _pub_events) = rooms.remove(0);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: You can use rooms.pop() here.

Comment thread livekit/src/room/mod.rs

let video_codec = publication.publish_options().video_codec;
// SVC codecs carry all spatial layers in one encoded stream.
let is_svc = matches!(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion(non-blocking): Consider breaking this out into a const helper function.

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.

2 participants