diff --git a/app/src/main/java/com/limelight/Game.java b/app/src/main/java/com/limelight/Game.java index 1f054ca0..512f0f73 100644 --- a/app/src/main/java/com/limelight/Game.java +++ b/app/src/main/java/com/limelight/Game.java @@ -219,9 +219,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, // Initialize the MediaCodec helper before creating the decoder MediaCodecHelper.initializeWithContext(this); - decoderRenderer = new MediaCodecDecoderRenderer(prefConfig.videoFormat, - prefConfig.bitrate, - prefConfig.batterySaver, + decoderRenderer = new MediaCodecDecoderRenderer(prefConfig, new CrashListener() { @Override public void notifyCrash(Exception e) { 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 61850b10..dd74a9d3 100644 --- a/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java +++ b/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java @@ -12,7 +12,6 @@ import com.limelight.nvstream.av.video.VideoDecoderRenderer; import com.limelight.nvstream.jni.MoonBridge; import com.limelight.preferences.PreferenceConfiguration; -import android.content.SharedPreferences; import android.media.MediaCodec; import android.media.MediaCodecInfo; import android.media.MediaFormat; @@ -67,7 +66,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer { private int framesLost; private int lastFrameNumber; private int refreshRate; - private int bitrate; + private PreferenceConfiguration prefs; private int numSpsIn; private int numPpsIn; @@ -113,16 +112,16 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer { this.renderTarget = renderTarget; } - public MediaCodecDecoderRenderer(int videoFormat, int bitrate, boolean batterySaver, + public MediaCodecDecoderRenderer(PreferenceConfiguration prefs, CrashListener crashListener, int consecutiveCrashCount) { //dumpDecoders(); - this.bitrate = bitrate; + this.prefs = prefs; this.crashListener = crashListener; this.consecutiveCrashCount = consecutiveCrashCount; // Disable spinner threads in battery saver mode - if (batterySaver) { + if (prefs.batterySaver) { spinnerThreads = new Thread[0]; } else { @@ -137,7 +136,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer { LimeLog.warning("No AVC decoder found"); } - hevcDecoder = findHevcDecoder(videoFormat); + hevcDecoder = findHevcDecoder(prefs.videoFormat); if (hevcDecoder != null) { LimeLog.info("Selected HEVC decoder: "+hevcDecoder.getName()); } @@ -367,7 +366,14 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer { } // Render the last buffer - videoDecoder.releaseOutputBuffer(lastIndex, true); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && prefs.disableFrameDrop) { + // Use a PTS that will cause this frame to never be dropped if frame dropping + // is disabled + videoDecoder.releaseOutputBuffer(lastIndex, 0); + } + else { + videoDecoder.releaseOutputBuffer(lastIndex, true); + } // Add delta time to the totals (excluding probable outliers) long delta = MediaCodecHelper.getMonotonicMillis() - (presentationTimeUs / 1000); @@ -926,7 +932,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer { str += "Consecutive crashes: "+renderer.consecutiveCrashCount+"\n"; str += "Initial video dimensions: "+renderer.initialWidth+"x"+renderer.initialHeight+"\n"; str += "FPS target: "+renderer.refreshRate+"\n"; - str += "Bitrate: "+renderer.bitrate+" Mbps \n"; + str += "Bitrate: "+renderer.prefs.bitrate+" Mbps \n"; str += "In stats: "+renderer.numVpsIn+", "+renderer.numSpsIn+", "+renderer.numPpsIn+"\n"; str += "Total frames: "+renderer.totalFrames+"\n"; str += "Frame losses: "+renderer.framesLost+" in "+frameLossEvents+" loss events\n"; diff --git a/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java b/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java index 5c7b151e..ded3c95f 100644 --- a/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java +++ b/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java @@ -23,6 +23,7 @@ public class PreferenceConfiguration { private static final String VIDEO_FORMAT_PREF_STRING = "video_format"; private static final String ONSCREEN_CONTROLLER_PREF_STRING = "checkbox_show_onscreen_controls"; private static final String BATTERY_SAVER_PREF_STRING = "checkbox_battery_saver"; + private static final String DISABLE_FRAME_DROP_PREF_STRING = "checkbox_disable_frame_drop"; private static final int BITRATE_DEFAULT_720_30 = 5; private static final int BITRATE_DEFAULT_720_60 = 10; @@ -46,6 +47,7 @@ public class PreferenceConfiguration { private static final String DEFAULT_VIDEO_FORMAT = "auto"; private static final boolean ONSCREEN_CONTROLLER_DEFAULT = false; private static final boolean DEFAULT_BATTERY_SAVER = false; + private static final boolean DEFAULT_DISABLE_FRAME_DROP = false; public static final int FORCE_H265_ON = -1; public static final int AUTOSELECT_H265 = 0; @@ -60,6 +62,7 @@ public class PreferenceConfiguration { public boolean listMode, smallIconMode, multiController, enable51Surround, usbDriver; public boolean onscreenController; public boolean batterySaver; + public boolean disableFrameDrop; public static int getDefaultBitrate(String resFpsString) { if (resFpsString.equals("720p30")) { @@ -201,6 +204,7 @@ public class PreferenceConfiguration { config.usbDriver = prefs.getBoolean(USB_DRIVER_PREF_SRING, DEFAULT_USB_DRIVER); config.onscreenController = prefs.getBoolean(ONSCREEN_CONTROLLER_PREF_STRING, ONSCREEN_CONTROLLER_DEFAULT); config.batterySaver = prefs.getBoolean(BATTERY_SAVER_PREF_STRING, DEFAULT_BATTERY_SAVER); + config.disableFrameDrop = prefs.getBoolean(DISABLE_FRAME_DROP_PREF_STRING, DEFAULT_DISABLE_FRAME_DROP); return config; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8572c05c..d77dfebd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -142,7 +142,9 @@ Play audio from the computer and this device Advanced Settings + Never drop frames + May reduce micro-stuttering on some devices, but can increase latency Change H.265 settings - H.265 lowers video bandwidth requirements but requires a very recent device. + H.265 lowers video bandwidth requirements but requires a very recent device diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index a5b3d51c..aa23510a 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -97,5 +97,10 @@ android:entryValues="@array/video_format_values" android:summary="@string/summary_video_format" android:defaultValue="auto" /> +