From 0a1e8815b6801627826cffb146e6102decef652b Mon Sep 17 00:00:00 2001 From: CloudWebRTC Date: Sat, 2 Sep 2023 10:55:50 +0800 Subject: [PATCH] Add max bitrate calculation for AV1 and VP9. (#348) --- lib/src/participant/local.dart | 1 + lib/src/types/video_encoding.dart | 9 +++++++++ lib/src/utils.dart | 23 +++++++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/lib/src/participant/local.dart b/lib/src/participant/local.dart index 42d61172..727e8f91 100644 --- a/lib/src/participant/local.dart +++ b/lib/src/participant/local.dart @@ -172,6 +172,7 @@ class LocalParticipant extends Participant { isScreenShare: track.source == TrackSource.screenShareVideo, dimensions: dimensions, options: publishOptions, + codec: publishOptions.videoCodec, ); logger.fine('Using encodings: ${encodings?.map((e) => e.toMap())}'); diff --git a/lib/src/types/video_encoding.dart b/lib/src/types/video_encoding.dart index 64e27d9b..7e8f74a2 100644 --- a/lib/src/types/video_encoding.dart +++ b/lib/src/types/video_encoding.dart @@ -26,6 +26,15 @@ class VideoEncoding implements Comparable { required this.maxBitrate, }); + VideoEncoding copyWith({ + int? maxFramerate, + int? maxBitrate, + }) => + VideoEncoding( + maxFramerate: maxFramerate ?? this.maxFramerate, + maxBitrate: maxBitrate ?? this.maxBitrate, + ); + @override String toString() => '${runtimeType}(maxFramerate: ${maxFramerate}, maxBitrate: ${maxBitrate})'; diff --git a/lib/src/utils.dart b/lib/src/utils.dart index 924068c5..dc6f6459 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -271,6 +271,7 @@ class Utils { required bool isScreenShare, required VideoDimensions dimensions, required List presets, + String? codec, }) { assert(presets.isNotEmpty, 'presets should not be empty'); VideoEncoding result = presets.first.encoding; @@ -283,6 +284,26 @@ class Utils { if (preset.dimensions.width >= size) break; } + // presets are based on the assumption of vp8 as a codec + // for other codecs we adjust the maxBitrate if no specific videoEncoding has been provided + // users should override these with ones that are optimized for their use case + // NOTE: SVC codec bitrates are inclusive of all scalability layers. while + // bitrate for non-SVC codecs does not include other simulcast layers. + if (codec != null) { + switch (codec) { + case 'av1': + result = + result.copyWith(maxBitrate: (result.maxBitrate * 0.7) as int); + break; + case 'vp9': + result = + result.copyWith(maxBitrate: (result.maxBitrate * 0.85) as int); + break; + default: + break; + } + } + return result; } @@ -371,6 +392,7 @@ class Utils { required bool isScreenShare, VideoDimensions? dimensions, VideoPublishOptions? options, + String? codec, }) { options ??= const VideoPublishOptions(); @@ -397,6 +419,7 @@ class Utils { isScreenShare: isScreenShare, dimensions: dimensions, presets: presets, + codec: codec, ); logger.fine('using video encoding', videoEncoding);