mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2026-02-16 18:40:46 +00:00
Replace frame pacing hack with Choreographer-based rendering
This mimics the frame pacing logic now present in the iOS client.
This commit is contained in:
@@ -389,58 +389,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
float displayRefreshRate = prepareDisplayForRendering();
|
||||
LimeLog.info("Display refresh rate: "+displayRefreshRate);
|
||||
|
||||
// HACK: Despite many efforts to ensure low latency consistent frame
|
||||
// delivery, the best non-lossy mechanism is to buffer 1 extra frame
|
||||
// in the output pipeline. Android does some buffering on its end
|
||||
// in SurfaceFlinger and it's difficult (impossible?) to inspect
|
||||
// the precise state of the buffer queue to the screen after we
|
||||
// release a frame for rendering.
|
||||
//
|
||||
// Since buffering a frame adds latency and we are primarily a
|
||||
// latency-optimized client, rather than one designed for picture-perfect
|
||||
// accuracy, we will synthetically induce a negative pressure on the display
|
||||
// output pipeline by driving the decoder input pipeline under the speed
|
||||
// that the display can refresh. This ensures a constant negative pressure
|
||||
// to keep latency down but does induce a periodic frame loss. However, this
|
||||
// periodic frame loss is *way* less than what we'd already get in Marshmallow's
|
||||
// display pipeline where frames are dropped outside of our control if they land
|
||||
// on the same V-sync.
|
||||
//
|
||||
// Hopefully, we can get rid of this once someone comes up with a better way
|
||||
// to track the state of the pipeline and time frames.
|
||||
int roundedRefreshRate = Math.round(displayRefreshRate);
|
||||
int chosenFrameRate = prefConfig.fps;
|
||||
if (!prefConfig.disableFrameDrop || prefConfig.unlockFps) {
|
||||
if (Build.DEVICE.equals("coral") || Build.DEVICE.equals("flame")) {
|
||||
// HACK: Pixel 4 (XL) ignores the preferred display mode and lowers refresh rate,
|
||||
// causing frame pacing issues. See https://issuetracker.google.com/issues/143401475
|
||||
// To work around this, use frame drop mode if we want to stream at >= 60 FPS.
|
||||
if (prefConfig.fps >= 60) {
|
||||
LimeLog.info("Using Pixel 4 rendering hack");
|
||||
decoderRenderer.enableLegacyFrameDropRendering();
|
||||
}
|
||||
}
|
||||
else if (prefConfig.fps >= roundedRefreshRate) {
|
||||
if (prefConfig.unlockFps) {
|
||||
// Use frame drops when rendering above the screen frame rate
|
||||
decoderRenderer.enableLegacyFrameDropRendering();
|
||||
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
|
||||
decoderRenderer.enableLegacyFrameDropRendering();
|
||||
LimeLog.info("Bogus refresh rate: " + roundedRefreshRate);
|
||||
}
|
||||
// HACK: Avoid crashing on some MTK devices
|
||||
else if (decoderRenderer.isBlacklistedForFrameRate(roundedRefreshRate - 1)) {
|
||||
// Use the old rendering strategy on these broken devices
|
||||
decoderRenderer.enableLegacyFrameDropRendering();
|
||||
} 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");
|
||||
@@ -449,7 +397,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
StreamConfiguration config = new StreamConfiguration.Builder()
|
||||
.setResolution(prefConfig.width, prefConfig.height)
|
||||
.setLaunchRefreshRate(prefConfig.fps)
|
||||
.setRefreshRate(chosenFrameRate)
|
||||
.setRefreshRate(prefConfig.fps)
|
||||
.setApp(new NvApp(appName != null ? appName : "app", appId, appSupportsHdr))
|
||||
.setBitrate(prefConfig.bitrate)
|
||||
.setEnableSops(prefConfig.enableSops)
|
||||
|
||||
Reference in New Issue
Block a user