From 31eec97cdc232c3abf24f58bbf014a1beb0cfcf5 Mon Sep 17 00:00:00 2001 From: cloudwebrtc Date: Mon, 15 Jul 2024 18:23:12 +0800 Subject: [PATCH] feat: expose DegradationPreference for publish options. --- lib/src/extensions.dart | 12 ++++++++++++ lib/src/options.dart | 34 +++++++++++++++++++++++----------- lib/src/participant/local.dart | 21 +++++++++++++++++++++ lib/src/track/local/video.dart | 10 ++++++++++ 4 files changed, 66 insertions(+), 11 deletions(-) diff --git a/lib/src/extensions.dart b/lib/src/extensions.dart index c456144c1..f98b17d7b 100644 --- a/lib/src/extensions.dart +++ b/lib/src/extensions.dart @@ -21,6 +21,7 @@ import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; import 'e2ee/options.dart'; import 'events.dart'; import 'managers/event.dart'; +import 'options.dart'; import 'proto/livekit_models.pb.dart' as lk_models; import 'proto/livekit_rtc.pb.dart' as lk_rtc; import 'types/other.dart'; @@ -261,3 +262,14 @@ extension ParticipantTypeExt on lk_models.ParticipantInfo_Kind { lk_models.ParticipantInfo_Kind.AGENT: ParticipantKind.AGENT, }[this]!; } + +extension DegradationPreferenceExt on DegradationPreference { + rtc.RTCDegradationPreference toRTCType() => { + DegradationPreference.disabled: rtc.RTCDegradationPreference.DISABLED, + DegradationPreference.maintainFramerate: + rtc.RTCDegradationPreference.MAINTAIN_FRAMERATE, + DegradationPreference.maintainResolution: + rtc.RTCDegradationPreference.MAINTAIN_RESOLUTION, + DegradationPreference.balanced: rtc.RTCDegradationPreference.BALANCED, + }[this]!; +} diff --git a/lib/src/options.dart b/lib/src/options.dart index d9bab4bff..ed80b5da6 100644 --- a/lib/src/options.dart +++ b/lib/src/options.dart @@ -162,6 +162,13 @@ class RoomOptions { } } +enum DegradationPreference { + disabled, + maintainFramerate, + maintainResolution, + balanced, +} + class BackupVideoCodec { const BackupVideoCodec({ this.enabled = true, @@ -227,6 +234,8 @@ class VideoPublishOptions extends PublishOptions { /// Defaults to true. final bool simulcast; + final DegradationPreference? degradationPreference; + final List videoSimulcastLayers; final List screenShareSimulcastLayers; @@ -235,17 +244,17 @@ class VideoPublishOptions extends PublishOptions { final BackupVideoCodec backupVideoCodec; - const VideoPublishOptions({ - super.name, - super.stream, - this.videoCodec = defaultVideoCodec, - this.videoEncoding, - this.simulcast = true, - this.videoSimulcastLayers = const [], - this.screenShareSimulcastLayers = const [], - this.backupVideoCodec = defualtBackupVideoCodec, - this.scalabilityMode, - }); + const VideoPublishOptions( + {super.name, + super.stream, + this.videoCodec = defaultVideoCodec, + this.videoEncoding, + this.simulcast = true, + this.videoSimulcastLayers = const [], + this.screenShareSimulcastLayers = const [], + this.backupVideoCodec = defualtBackupVideoCodec, + this.scalabilityMode, + this.degradationPreference}); VideoPublishOptions copyWith({ VideoEncoding? videoEncoding, @@ -254,6 +263,7 @@ class VideoPublishOptions extends PublishOptions { List? screenShareSimulcastLayers, String? videoCodec, BackupVideoCodec? backupVideoCodec, + DegradationPreference? degradationPreference, String? scalabilityMode, String? name, String? stream, @@ -266,6 +276,8 @@ class VideoPublishOptions extends PublishOptions { screenShareSimulcastLayers ?? this.screenShareSimulcastLayers, videoCodec: videoCodec ?? this.videoCodec, backupVideoCodec: backupVideoCodec ?? this.backupVideoCodec, + degradationPreference: + degradationPreference ?? this.degradationPreference, scalabilityMode: scalabilityMode ?? this.scalabilityMode, name: name ?? this.name, stream: stream ?? this.stream, diff --git a/lib/src/participant/local.dart b/lib/src/participant/local.dart index be48dbc08..83af59610 100644 --- a/lib/src/participant/local.dart +++ b/lib/src/participant/local.dart @@ -305,6 +305,15 @@ class LocalParticipant extends Participant { await sender.setParameters(parameters); } + if ([TrackSource.camera, TrackSource.screenShareVideo] + .contains(track.source)) { + var degradationPreference = publishOptions.degradationPreference ?? + getDefaultDegradationPreference( + track, + ); + track.setDegradationPreference(degradationPreference); + } + if (kIsWeb && lkBrowser() == BrowserType.firefox && track.kind == TrackType.AUDIO) { @@ -397,6 +406,18 @@ class LocalParticipant extends Participant { await pub.dispose(); } + DegradationPreference getDefaultDegradationPreference(LocalVideoTrack track) { + // a few of reasons we have different default paths: + // 1. without this, Chrome seems to aggressively resize the SVC video stating `quality-limitation: bandwidth` even when BW isn't an issue + // 2. since we are overriding contentHint to motion (to workaround L1T3 publishing), it overrides the default degradationPreference to `balanced` + VideoDimensions dimensions = track.currentOptions.params.dimensions; + if (track.source == TrackSource.screenShareVideo || + dimensions.height >= 1080) { + return DegradationPreference.maintainResolution; + } + return DegradationPreference.balanced; + } + /// Convenience method to unpublish all tracks. Future unpublishAllTracks( {bool notify = true, bool? stopOnUnpublish}) async { diff --git a/lib/src/track/local/video.dart b/lib/src/track/local/video.dart index 731ac0441..0600f9a23 100644 --- a/lib/src/track/local/video.dart +++ b/lib/src/track/local/video.dart @@ -16,6 +16,7 @@ import 'package:flutter/foundation.dart'; import 'package:collection/collection.dart'; import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; +import 'package:livekit_client/src/extensions.dart'; import '../../events.dart'; import '../../exceptions.dart'; @@ -490,4 +491,13 @@ extension LocalVideoTrackExt on LocalVideoTrack { simulcastCodecs[codec] = simulcastCodecInfo; return simulcastCodecInfo; } + + void setDegradationPreference(DegradationPreference preference) { + final params = sender?.parameters; + if (params == null) { + return; + } + params.degradationPreference = preference.toRTCType(); + sender?.setParameters(params); + } }