diff --git a/app/src/main/java/com/limelight/Game.java b/app/src/main/java/com/limelight/Game.java
index efeae15a..1498efaa 100644
--- a/app/src/main/java/com/limelight/Game.java
+++ b/app/src/main/java/com/limelight/Game.java
@@ -389,6 +389,28 @@ public class Game extends Activity implements SurfaceHolder.Callback,
float displayRefreshRate = prepareDisplayForRendering();
LimeLog.info("Display refresh rate: "+displayRefreshRate);
+ // If the user requested frame pacing using a capped FPS, we will need to change our
+ // desired FPS setting here in accordance with the active display refresh rate.
+ int roundedRefreshRate = Math.round(displayRefreshRate);
+ int chosenFrameRate = prefConfig.fps;
+ if (prefConfig.framePacing == PreferenceConfiguration.FRAME_PACING_CAP_FPS) {
+ if (prefConfig.fps >= roundedRefreshRate) {
+ if (prefConfig.unlockFps) {
+ // Use frame drops when rendering above the screen frame rate
+ prefConfig.framePacing = PreferenceConfiguration.FRAME_PACING_BALANCED;
+ LimeLog.info("Using drop mode for FPS > Hz");
+ } else if (roundedRefreshRate <= 49) {
+ // Let's avoid clearly bogus refresh rates and fall back to legacy rendering
+ prefConfig.framePacing = PreferenceConfiguration.FRAME_PACING_BALANCED;
+ LimeLog.info("Bogus refresh rate: " + roundedRefreshRate);
+ }
+ else {
+ chosenFrameRate = roundedRefreshRate - 1;
+ LimeLog.info("Adjusting FPS target for screen to " + chosenFrameRate);
+ }
+ }
+ }
+
boolean vpnActive = NetHelper.isActiveNetworkVpn(this);
if (vpnActive) {
LimeLog.info("Detected active network is a VPN");
@@ -397,7 +419,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
StreamConfiguration config = new StreamConfiguration.Builder()
.setResolution(prefConfig.width, prefConfig.height)
.setLaunchRefreshRate(prefConfig.fps)
- .setRefreshRate(prefConfig.fps)
+ .setRefreshRate(chosenFrameRate)
.setApp(new NvApp(appName != null ? appName : "app", appId, appSupportsHdr))
.setBitrate(prefConfig.bitrate)
.setEnableSops(prefConfig.enableSops)
diff --git a/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java b/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java
index 108b8ce9..6fe54098 100644
--- a/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java
+++ b/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java
@@ -468,8 +468,9 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
presentationTimeUs = info.presentationTimeUs;
}
- if (prefs.framePacing == PreferenceConfiguration.FRAME_PACING_MAX_SMOOTHNESS) {
- // In max smoothness mode, we want to never drop frames
+ if (prefs.framePacing == PreferenceConfiguration.FRAME_PACING_MAX_SMOOTHNESS ||
+ prefs.framePacing == PreferenceConfiguration.FRAME_PACING_CAP_FPS) {
+ // In max smoothness or cap FPS mode, we want to never drop frames
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// Use a PTS that will cause this frame to never be dropped
videoDecoder.releaseOutputBuffer(lastIndex, 0);
diff --git a/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java b/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java
index 34fa435d..b928f29b 100644
--- a/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java
+++ b/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java
@@ -80,7 +80,8 @@ public class PreferenceConfiguration {
public static final int FRAME_PACING_MIN_LATENCY = 0;
public static final int FRAME_PACING_BALANCED = 1;
- public static final int FRAME_PACING_MAX_SMOOTHNESS = 2;
+ public static final int FRAME_PACING_CAP_FPS = 2;
+ public static final int FRAME_PACING_MAX_SMOOTHNESS = 3;
public static final String RES_360P = "640x360";
public static final String RES_480P = "854x480";
@@ -288,6 +289,9 @@ public class PreferenceConfiguration {
else if (str.equals("balanced")) {
return FRAME_PACING_BALANCED;
}
+ else if (str.equals("cap-fps")) {
+ return FRAME_PACING_CAP_FPS;
+ }
else if (str.equals("smoothness")) {
return FRAME_PACING_MAX_SMOOTHNESS;
}
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
index 2ddf3a10..cd334e44 100644
--- a/app/src/main/res/values/arrays.xml
+++ b/app/src/main/res/values/arrays.xml
@@ -98,11 +98,13 @@
- @string/pacing_latency
- @string/pacing_balanced
+ - @string/pacing_balanced_alt
- @string/pacing_smoothness
- latency
- balanced
+ - cap-fps
- smoothness
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f4f6f8b1..cc49d25f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -252,5 +252,6 @@
Specify how to balance video latency and smoothness
Prefer lowest latency
Balanced
+ Balanced with FPS cap (may perform better on certain devices)
Prefer smoothest video (may significantly increase latency)