From 829707057e53950650b8a704f8bd77f3da6b3c24 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sun, 10 Nov 2024 09:11:57 +0100 Subject: [PATCH] Split computeVideoSize() into limit() and round8() Expose two methods on Size directly: - limit() to downscale a size; - round8() to round both dimensions to multiples of 8. This will allow to remove ScreenInfo completely. --- .../com/genymobile/scrcpy/device/Size.java | 51 +++++++++++++++++++ .../scrcpy/video/NewDisplayCapture.java | 2 +- .../genymobile/scrcpy/video/ScreenInfo.java | 30 +---------- 3 files changed, 53 insertions(+), 30 deletions(-) diff --git a/server/src/main/java/com/genymobile/scrcpy/device/Size.java b/server/src/main/java/com/genymobile/scrcpy/device/Size.java index 558deb00..3baa1bdd 100644 --- a/server/src/main/java/com/genymobile/scrcpy/device/Size.java +++ b/server/src/main/java/com/genymobile/scrcpy/device/Size.java @@ -29,6 +29,57 @@ public final class Size { return new Size(height, width); } + public Size limit(int maxSize) { + assert maxSize >= 0 : "Max size may not be negative"; + assert maxSize % 8 == 0 : "Max size must be a multiple of 8"; + + if (maxSize == 0) { + // No limit + return this; + } + + boolean portrait = height > width; + int major = portrait ? height : width; + if (major <= maxSize) { + return this; + } + + int minor = portrait ? width : height; + + int newMajor = maxSize; + int newMinor = maxSize * minor / major; + + int w = portrait ? newMinor : newMajor; + int h = portrait ? newMajor : newMinor; + return new Size(w, h); + } + + /** + * Round both dimensions of this size to be a multiple of 8 (as required by many encoders). + * + * @return The current size rounded. + */ + public Size round8() { + if ((width & 7) == 0 && (height & 7) == 0) { + // Already a multiple of 8 + return this; + } + + boolean portrait = height > width; + int major = portrait ? height : width; + int minor = portrait ? width : height; + + major &= ~7; // round down to not exceed the initial size + minor = (minor + 4) & ~7; // round to the nearest to minimize aspect ratio distortion + if (minor > major) { + minor = major; + } + + int w = portrait ? minor : major; + int h = portrait ? major : minor; + return new Size(w, h); + } + public Rect toRect() { return new Rect(0, 0, width, height); } diff --git a/server/src/main/java/com/genymobile/scrcpy/video/NewDisplayCapture.java b/server/src/main/java/com/genymobile/scrcpy/video/NewDisplayCapture.java index 9b1c9933..b9cecbe4 100644 --- a/server/src/main/java/com/genymobile/scrcpy/video/NewDisplayCapture.java +++ b/server/src/main/java/com/genymobile/scrcpy/video/NewDisplayCapture.java @@ -71,7 +71,7 @@ public class NewDisplayCapture extends SurfaceCapture { @Override public void prepare() { if (!newDisplay.hasExplicitSize()) { - size = ScreenInfo.computeVideoSize(mainDisplaySize.getWidth(), mainDisplaySize.getHeight(), maxSize); + size = mainDisplaySize.limit(maxSize).round8(); } if (!newDisplay.hasExplicitDpi()) { dpi = scaleDpi(mainDisplaySize, mainDisplayDpi, size); diff --git a/server/src/main/java/com/genymobile/scrcpy/video/ScreenInfo.java b/server/src/main/java/com/genymobile/scrcpy/video/ScreenInfo.java index cc82a654..010ab59a 100644 --- a/server/src/main/java/com/genymobile/scrcpy/video/ScreenInfo.java +++ b/server/src/main/java/com/genymobile/scrcpy/video/ScreenInfo.java @@ -1,6 +1,5 @@ package com.genymobile.scrcpy.video; -import com.genymobile.scrcpy.BuildConfig; import com.genymobile.scrcpy.device.Device; import com.genymobile.scrcpy.device.Size; import com.genymobile.scrcpy.util.Ln; @@ -82,7 +81,7 @@ public final class ScreenInfo { } } - Size videoSize = computeVideoSize(contentRect.width(), contentRect.height(), maxSize); + Size videoSize = new Size(contentRect.width(), contentRect.height()).limit(maxSize).round8(); return new ScreenInfo(contentRect, videoSize, rotation, lockedVideoOrientation); } @@ -90,33 +89,6 @@ public final class ScreenInfo { return rect.width() + ":" + rect.height() + ":" + rect.left + ":" + rect.top; } - public static Size computeVideoSize(int w, int h, int maxSize) { - // Compute the video size and the padding of the content inside this video. - // Principle: - // - scale down the great side of the screen to maxSize (if necessary); - // - scale down the other side so that the aspect ratio is preserved; - // - round this value to the nearest multiple of 8 (H.264 only accepts multiples of 8) - w &= ~7; // in case it's not a multiple of 8 - h &= ~7; - if (maxSize > 0) { - if (BuildConfig.DEBUG && maxSize % 8 != 0) { - throw new AssertionError("Max size must be a multiple of 8"); - } - boolean portrait = h > w; - int major = portrait ? h : w; - int minor = portrait ? w : h; - if (major > maxSize) { - int minorExact = minor * maxSize / major; - // +4 to round the value to the nearest multiple of 8 - minor = (minorExact + 4) & ~7; - major = maxSize; - } - w = portrait ? minor : major; - h = portrait ? major : minor; - } - return new Size(w, h); - } - private static Rect flipRect(Rect crop) { return new Rect(crop.top, crop.left, crop.bottom, crop.right); }