From 8fb6e053378792f52784b87bfdb6f12ac3c315da Mon Sep 17 00:00:00 2001 From: Oliver Lazoroski Date: Wed, 6 Nov 2024 14:51:29 +0100 Subject: [PATCH] fix: max simulcast layers preference --- packages/client/src/rtc/Publisher.ts | 11 ++++++----- packages/client/src/rtc/videoLayers.ts | 8 ++++++-- packages/client/src/types.ts | 4 ++++ .../react/react-dogfood/components/MeetingUI.tsx | 8 +++++++- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/packages/client/src/rtc/Publisher.ts b/packages/client/src/rtc/Publisher.ts index a55de6411e..8cf7e67afa 100644 --- a/packages/client/src/rtc/Publisher.ts +++ b/packages/client/src/rtc/Publisher.ts @@ -390,11 +390,12 @@ export class Publisher { let changed = false; for (const encoder of params.encodings) { - const layer = usesSvcCodec - ? // for SVC, we only have one layer (q) and often rid is omitted - enabledLayers[0] - : // for non-SVC, we need to find the layer by rid (simulcast) - enabledLayers.find((l) => l.name === encoder.rid); + const layer = + usesSvcCodec || enabledLayers.length === 1 + ? // for SVC, we only have one layer (q) and often rid is omitted + enabledLayers[0] + : // for non-SVC, we need to find the layer by rid (simulcast) + enabledLayers.find((l) => l.name === encoder.rid); // flip 'active' flag only when necessary const shouldActivate = !!layer?.active; diff --git a/packages/client/src/rtc/videoLayers.ts b/packages/client/src/rtc/videoLayers.ts index 5fede153b1..2f0a4318bc 100644 --- a/packages/client/src/rtc/videoLayers.ts +++ b/packages/client/src/rtc/videoLayers.ts @@ -65,7 +65,11 @@ export const findOptimalVideoLayers = ( const optimalVideoLayers: OptimalVideoLayer[] = []; const settings = videoTrack.getSettings(); const { width = 0, height = 0 } = settings; - const { scalabilityMode, bitrateDownscaleFactor = 2 } = publishOptions || {}; + const { + scalabilityMode, + bitrateDownscaleFactor = 2, + maxSimulcastLayers = 3, + } = publishOptions || {}; const maxBitrate = getComputedMaxBitrate( targetResolution, width, @@ -76,7 +80,7 @@ export const findOptimalVideoLayers = ( let downscaleFactor = 1; let bitrateFactor = 1; const svcCodec = isSvcCodec(codecInUse); - for (const rid of ['f', 'h', 'q']) { + for (const rid of ['f', 'h', 'q'].slice(0, Math.min(3, maxSimulcastLayers))) { const layer: OptimalVideoLayer = { active: true, rid, diff --git a/packages/client/src/types.ts b/packages/client/src/types.ts index e32c82694e..3cb8a59858 100644 --- a/packages/client/src/types.ts +++ b/packages/client/src/types.ts @@ -181,6 +181,10 @@ export type PublishOptions = { * in simulcast mode (non-SVC). */ bitrateDownscaleFactor?: number; + /** + * The maximum number of simulcast layers to use when publishing the video stream. + */ + maxSimulcastLayers?: number; /** * Screen share settings. */ diff --git a/sample-apps/react/react-dogfood/components/MeetingUI.tsx b/sample-apps/react/react-dogfood/components/MeetingUI.tsx index 5479dae277..3758f2dafd 100644 --- a/sample-apps/react/react-dogfood/components/MeetingUI.tsx +++ b/sample-apps/react/react-dogfood/components/MeetingUI.tsx @@ -56,6 +56,9 @@ export const MeetingUI = ({ chatClient, mode }: MeetingUIProps) => { const scalabilityMode = router.query['scalability_mode'] as | string | undefined; + const maxSimulcastLayers = router.query['max_simulcast_layers'] as + | string + | undefined; const onJoin = useCallback( async ({ fastJoin = false } = {}) => { @@ -67,13 +70,16 @@ export const MeetingUI = ({ chatClient, mode }: MeetingUIProps) => { : undefined; call.updatePublishOptions({ - preferredCodec: 'vp9', + preferredCodec: 'h264', forceCodec: videoCodecOverride, scalabilityMode, preferredBitrate, bitrateDownscaleFactor: bitrateFactorOverride ? parseInt(bitrateFactorOverride, 10) : 2, // default to 2 + maxSimulcastLayers: maxSimulcastLayers + ? parseInt(maxSimulcastLayers, 10) + : 3, // default to 3 }); await call.join({ create: true });