fix(voice): avoid capped software h264 for auto screen shares (#3139)

This commit is contained in:
Hampus
2026-10-02 22:52:03 +02:00
committed by GitHub
parent b52a0b5d5f
commit 98fa41dcf0
3 changed files with 17 additions and 7 deletions
@@ -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(),
};
}
@@ -5,6 +5,7 @@ import type {VideoCodec} from 'livekit-client';
export const CODEC_PREFERENCE: ReadonlyArray<VideoCodec> = ['av1', 'h265', 'h264', 'vp9', 'vp8'];
const SOFTWARE_H264_CODEC_PREFERENCE: ReadonlyArray<VideoCodec> = ['av1', 'h265', 'vp9', 'h264', 'vp8'];
const CLAMPED_H264_CODEC_PREFERENCE: ReadonlyArray<VideoCodec> = ['av1', 'h265', 'vp9', 'vp8', 'h264'];
const GECKO_CODEC_PREFERENCE: ReadonlyArray<VideoCodec> = ['vp8', 'h264'];
const COMPATIBILITY_CODECS: ReadonlySet<VideoCodec> = 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<VideoCodec, ScreenShareCodecProfileEntry>;
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'
@@ -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;