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" />
+