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 ScreenShareCodecProfileEntry,
type ScreenShareCodecRanking, type ScreenShareCodecRanking,
} from '@app/features/voice/utils/ScreenShareCodecSelection'; } 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 {getProbedVideoDecoderExclusionsSync} from '@app/features/voice/utils/VideoDecoderCapabilities';
import type {TrackPublishDefaults, TrackPublishOptions} from 'livekit-client'; import type {TrackPublishDefaults, TrackPublishOptions} from 'livekit-client';
import {BackupCodecPolicy, supportsVideoCodec, type VideoCodec, type VideoEncoding} from 'livekit-client'; import {BackupCodecPolicy, supportsVideoCodec, type VideoCodec, type VideoEncoding} from 'livekit-client';
@@ -410,6 +410,7 @@ export function buildScreenShareCodecProfile(): ScreenShareCodecProfile {
h265: entry('h265'), h265: entry('h265'),
av1: entry('av1'), 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']; export const CODEC_PREFERENCE: ReadonlyArray<VideoCodec> = ['av1', 'h265', 'h264', 'vp9', 'vp8'];
const SOFTWARE_H264_CODEC_PREFERENCE: ReadonlyArray<VideoCodec> = ['av1', 'h265', 'vp9', 'h264', '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 GECKO_CODEC_PREFERENCE: ReadonlyArray<VideoCodec> = ['vp8', 'h264'];
const COMPATIBILITY_CODECS: ReadonlySet<VideoCodec> = new Set(['h264', 'vp9', 'vp8']); const COMPATIBILITY_CODECS: ReadonlySet<VideoCodec> = new Set(['h264', 'vp9', 'vp8']);
export const LAST_RESORT_VIDEO_CODEC: VideoCodec = 'vp8'; export const LAST_RESORT_VIDEO_CODEC: VideoCodec = 'vp8';
@@ -79,6 +80,7 @@ export interface ScreenShareCodecProfile {
browser: ScreenShareCodecBrowser; browser: ScreenShareCodecBrowser;
desktop: boolean; desktop: boolean;
codecs: Record<VideoCodec, ScreenShareCodecProfileEntry>; codecs: Record<VideoCodec, ScreenShareCodecProfileEntry>;
h264SoftwareClamped?: boolean;
} }
export interface ScreenShareCodecRankingInput { export interface ScreenShareCodecRankingInput {
@@ -94,7 +96,9 @@ export interface ScreenShareCodecRanking {
export function rankScreenShareCodecs(input: ScreenShareCodecRankingInput): ScreenShareCodecRanking { export function rankScreenShareCodecs(input: ScreenShareCodecRankingInput): ScreenShareCodecRanking {
const {codecs} = input.profile; 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 hardwareAvailable = CODEC_PREFERENCE.some((codec) => isHardware(codec));
const pin = input.pin !== 'auto' && codecs[input.pin].allowed && codecs[input.pin].supported ? input.pin : null; const pin = input.pin !== 'auto' && codecs[input.pin].allowed && codecs[input.pin].supported ? input.pin : null;
const baselineOnly = const baselineOnly =
@@ -108,6 +112,8 @@ export function rankScreenShareCodecs(input: ScreenShareCodecRankingInput): Scre
const preference = const preference =
input.profile.browser === 'firefox' input.profile.browser === 'firefox'
? GECKO_CODEC_PREFERENCE ? GECKO_CODEC_PREFERENCE
: h264Clamped
? CLAMPED_H264_CODEC_PREFERENCE
: isHardware('h264') : isHardware('h264')
? CODEC_PREFERENCE ? CODEC_PREFERENCE
: SOFTWARE_H264_CODEC_PREFERENCE; : SOFTWARE_H264_CODEC_PREFERENCE;
@@ -330,11 +330,14 @@ export function resolveScreenShareDegradationPreference(
return 'maintain-framerate'; return 'maintain-framerate';
} }
function shouldClampToSoftwareH264(codec: VideoCodec | undefined): boolean { export function isH264SoftwareClamped(): boolean {
if (codec !== 'h264') return false;
return getH264HardwareProfilesSync()?.profiles.size === 0; return getH264HardwareProfilesSync()?.profiles.size === 0;
} }
function shouldClampToSoftwareH264(codec: VideoCodec | undefined): boolean {
return codec === 'h264' && isH264SoftwareClamped();
}
function clampToSoftwareH264Budget(quality: { function clampToSoftwareH264Budget(quality: {
mode: StreamingMode; mode: StreamingMode;
resolution: ScreenshareResolution; resolution: ScreenshareResolution;