From c374283f45e36021b9604ade31655a3657473cae Mon Sep 17 00:00:00 2001 From: davidliu Date: Wed, 16 Feb 2022 01:15:41 +0900 Subject: [PATCH] Ensure even video dimensions (#82) gotcha, I think we may have to do some work iOS later to properly grab the actual capture dimensions rather than rely on the dimensions we request, to properly do the calculations. That said, I think m97 is now handling the odd dimensions properly, so I don't think we'll need this fix anymore. As for adaptOutputFormat, flutter_webrtc is already doing that (though it doesn't seem to prevent the crash on m93). Should native android use this as well? --- lib/src/types.dart | 3 +++ lib/src/utils.dart | 30 +++++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/lib/src/types.dart b/lib/src/types.dart index d6fcf4f..a11fed4 100644 --- a/lib/src/types.dart +++ b/lib/src/types.dart @@ -159,6 +159,9 @@ class VideoDimensions { /// Returns the larger value int max() => math.max(width, height); + /// Returns the smaller value + int min() => math.min(width, height); + VideoDimensions copyWith({ int? width, int? height, diff --git a/lib/src/utils.dart b/lib/src/utils.dart index 8bc4264..7645927 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -231,18 +231,42 @@ class Utils { if (i >= videoRids.length) { return; } - final size = dimensions.max(); - final encodingSize = e.dimensions.max(); final rid = videoRids[i]; result.add(e.encoding.toRTCRtpEncoding( rid: rid, - scaleResolutionDownBy: size / encodingSize, + scaleResolutionDownBy: findEvenScaleDownBy(dimensions, e.dimensions), )); }); return result; } + @internal + static double findEvenScaleDownBy( + VideoDimensions sourceDimensions, + VideoDimensions targetDimensions, + ) { + bool isEven(int v) => v % 2 == 0; + + final sourceSize = sourceDimensions.max(); + final targetSize = targetDimensions.max(); + + for (int i = 0; i <= 30; i++) { + final scaleDownBy = sourceSize.toDouble() / (targetSize + i); + // Internally, WebRTC casts directly to int without rounding. + // https://github.com/webrtc-sdk/webrtc/blob/8c7139f8e6fa19ddf2c91510c177a19746e1ded3/media/engine/webrtc_video_engine.cc#L3676 + final scaledWidth = sourceDimensions.width ~/ scaleDownBy; + final scaledHeight = sourceDimensions.height ~/ scaleDownBy; + + if (isEven(scaledWidth) && isEven(scaledHeight)) { + return scaleDownBy; + } + } + + // couldn't find an even scale, just return original scale and hope it works. + return sourceSize / targetSize; + } + @internal static List? computeVideoEncodings({ required bool isScreenShare,