From 98fa41dcf08320c860c636d687ec5ff173c0d917 Mon Sep 17 00:00:00 2001 From: Hampus Date: Fri, 2 Oct 2026 22:52:03 +0200 Subject: [PATCH] fix(voice): avoid capped software h264 for auto screen shares (#3139) --- .../voice/utils/CodecCapabilityDetector.ts | 3 ++- .../voice/utils/ScreenShareCodecSelection.ts | 14 ++++++++++---- .../src/features/voice/utils/ScreenShareOptions.ts | 7 +++++-- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/fluxer_app/src/features/voice/utils/CodecCapabilityDetector.ts b/fluxer_app/src/features/voice/utils/CodecCapabilityDetector.ts index 99aa131a6..50f6f1abd 100644 --- a/fluxer_app/src/features/voice/utils/CodecCapabilityDetector.ts +++ b/fluxer_app/src/features/voice/utils/CodecCapabilityDetector.ts @@ -24,7 +24,7 @@ import { type ScreenShareCodecProfileEntry, type ScreenShareCodecRanking, } from '@app/features/voice/utils/ScreenShareCodecSelection'; -import {normaliseStreamingModeForContext} from '@app/features/voice/utils/ScreenShareOptions'; +import {isH264SoftwareClamped, normaliseStreamingModeForContext} from '@app/features/voice/utils/ScreenShareOptions'; import {getProbedVideoDecoderExclusionsSync} from '@app/features/voice/utils/VideoDecoderCapabilities'; import type {TrackPublishDefaults, TrackPublishOptions} from 'livekit-client'; import {BackupCodecPolicy, supportsVideoCodec, type VideoCodec, type VideoEncoding} from 'livekit-client'; @@ -410,6 +410,7 @@ export function buildScreenShareCodecProfile(): ScreenShareCodecProfile { h265: entry('h265'), av1: entry('av1'), }, + h264SoftwareClamped: isH264SoftwareClamped(), }; } diff --git a/fluxer_app/src/features/voice/utils/ScreenShareCodecSelection.ts b/fluxer_app/src/features/voice/utils/ScreenShareCodecSelection.ts index 198eabde5..b9c431e21 100644 --- a/fluxer_app/src/features/voice/utils/ScreenShareCodecSelection.ts +++ b/fluxer_app/src/features/voice/utils/ScreenShareCodecSelection.ts @@ -5,6 +5,7 @@ import type {VideoCodec} from 'livekit-client'; export const CODEC_PREFERENCE: ReadonlyArray = ['av1', 'h265', 'h264', 'vp9', 'vp8']; const SOFTWARE_H264_CODEC_PREFERENCE: ReadonlyArray = ['av1', 'h265', 'vp9', 'h264', 'vp8']; +const CLAMPED_H264_CODEC_PREFERENCE: ReadonlyArray = ['av1', 'h265', 'vp9', 'vp8', 'h264']; const GECKO_CODEC_PREFERENCE: ReadonlyArray = ['vp8', 'h264']; const COMPATIBILITY_CODECS: ReadonlySet = new Set(['h264', 'vp9', 'vp8']); export const LAST_RESORT_VIDEO_CODEC: VideoCodec = 'vp8'; @@ -79,6 +80,7 @@ export interface ScreenShareCodecProfile { browser: ScreenShareCodecBrowser; desktop: boolean; codecs: Record; + h264SoftwareClamped?: boolean; } export interface ScreenShareCodecRankingInput { @@ -94,7 +96,9 @@ export interface ScreenShareCodecRanking { export function rankScreenShareCodecs(input: ScreenShareCodecRankingInput): ScreenShareCodecRanking { const {codecs} = input.profile; - const isHardware = (codec: VideoCodec): boolean => codecs[codec].supported && codecs[codec].hardware; + const h264Clamped = input.profile.h264SoftwareClamped === true; + const isHardware = (codec: VideoCodec): boolean => + codecs[codec].supported && codecs[codec].hardware && !(codec === 'h264' && h264Clamped); const hardwareAvailable = CODEC_PREFERENCE.some((codec) => isHardware(codec)); const pin = input.pin !== 'auto' && codecs[input.pin].allowed && codecs[input.pin].supported ? input.pin : null; const baselineOnly = @@ -108,9 +112,11 @@ export function rankScreenShareCodecs(input: ScreenShareCodecRankingInput): Scre const preference = input.profile.browser === 'firefox' ? GECKO_CODEC_PREFERENCE - : isHardware('h264') - ? CODEC_PREFERENCE - : SOFTWARE_H264_CODEC_PREFERENCE; + : h264Clamped + ? CLAMPED_H264_CODEC_PREFERENCE + : isHardware('h264') + ? CODEC_PREFERENCE + : SOFTWARE_H264_CODEC_PREFERENCE; const survivors = preference.filter(survives); const ranked = input.encoderModeSetting === 'software' diff --git a/fluxer_app/src/features/voice/utils/ScreenShareOptions.ts b/fluxer_app/src/features/voice/utils/ScreenShareOptions.ts index 36682260d..8da8e2f78 100644 --- a/fluxer_app/src/features/voice/utils/ScreenShareOptions.ts +++ b/fluxer_app/src/features/voice/utils/ScreenShareOptions.ts @@ -330,11 +330,14 @@ export function resolveScreenShareDegradationPreference( return 'maintain-framerate'; } -function shouldClampToSoftwareH264(codec: VideoCodec | undefined): boolean { - if (codec !== 'h264') return false; +export function isH264SoftwareClamped(): boolean { return getH264HardwareProfilesSync()?.profiles.size === 0; } +function shouldClampToSoftwareH264(codec: VideoCodec | undefined): boolean { + return codec === 'h264' && isH264SoftwareClamped(); +} + function clampToSoftwareH264Budget(quality: { mode: StreamingMode; resolution: ScreenshareResolution;