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 795efc06..bfa12cae 100644 --- a/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java +++ b/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java @@ -27,10 +27,11 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer { private ByteBuffer[] videoDecoderInputBuffers; private MediaCodec videoDecoder; private Thread rendererThread; - private boolean needsSpsBitstreamFixup, isExynos4; + private final boolean needsSpsBitstreamFixup, isExynos4; private VideoDepacketizer depacketizer; - private boolean adaptivePlayback; + private final boolean adaptivePlayback; private int initialWidth, initialHeight; + private final int dequeueOutputBufferTimeout; private boolean needsBaselineSpsHack; private SeqParameterSet savedSps; @@ -55,12 +56,17 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer { } if (decoder == null) { // This case is handled later in setup() + needsSpsBitstreamFixup = false; + isExynos4 = false; + adaptivePlayback = false; + dequeueOutputBufferTimeout = 0; return; } decoderName = decoder.getName(); // Set decoder-specific attributes + dequeueOutputBufferTimeout = MediaCodecHelper.getOptimalOutputBufferDequeueTimeout(decoderName, decoder); adaptivePlayback = MediaCodecHelper.decoderSupportsAdaptivePlayback(decoderName, decoder); needsSpsBitstreamFixup = MediaCodecHelper.decoderNeedsSpsBitstreamRestrictions(decoderName, decoder); needsBaselineSpsHack = MediaCodecHelper.decoderNeedsBaselineSpsHack(decoderName, decoder); @@ -145,7 +151,7 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer { while (!isInterrupted()) { try { // Try to output a frame - int outIndex = videoDecoder.dequeueOutputBuffer(info, 50000); + int outIndex = videoDecoder.dequeueOutputBuffer(info, dequeueOutputBufferTimeout); if (outIndex >= 0) { long presentationTimeUs = info.presentationTimeUs; int lastIndex = outIndex; @@ -189,7 +195,7 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer { } }; rendererThread.setName("Video - Renderer (MediaCodec)"); - rendererThread.setPriority(Thread.MAX_PRIORITY); + rendererThread.setPriority(Thread.NORM_PRIORITY + 2); rendererThread.start(); } diff --git a/app/src/main/java/com/limelight/binding/video/MediaCodecHelper.java b/app/src/main/java/com/limelight/binding/video/MediaCodecHelper.java index d3befe7d..a760bb50 100644 --- a/app/src/main/java/com/limelight/binding/video/MediaCodecHelper.java +++ b/app/src/main/java/com/limelight/binding/video/MediaCodecHelper.java @@ -26,7 +26,16 @@ public class MediaCodecHelper { private static final List spsFixupBitstreamFixupDecoderPrefixes; private static final List whitelistedAdaptiveResolutionPrefixes; private static final List baselineProfileHackPrefixes; - + private static final List fastOutputPollPrefixes; + + private static final int FAST_OUTPUT_POLL_US = 3; // 3 us + private static final int NORMAL_OUTPUT_POLL_US = 50000; // 50 ms + + static { + fastOutputPollPrefixes = new LinkedList(); + fastOutputPollPrefixes.add("omx.nvidia"); + } + static { preferredDecoders = new LinkedList(); } @@ -97,6 +106,20 @@ public class MediaCodecHelper { return false; } + + public static int getOptimalOutputBufferDequeueTimeout(String decoderName, MediaCodecInfo decoderInfo) { + // This concept of "fast output polling" is a workaround for certain devices that are powerful enough + // that the governor overzealously reduces the clockspeed of the CPU enough that it causes frames to be + // lost. This (at least) affects the Denver Tegra K1 running Android 5.0. To simplify things, I've simply + // set all Tegra devices to use fast polling. + if (isDecoderInList(fastOutputPollPrefixes, decoderName)) { + LimeLog.info("Decoder "+decoderName+" requires fast output polling"); + return FAST_OUTPUT_POLL_US; + } + else { + return NORMAL_OUTPUT_POLL_US; + } + } public static boolean decoderNeedsSpsBitstreamRestrictions(String decoderName, MediaCodecInfo decoderInfo) { return isDecoderInList(spsFixupBitstreamFixupDecoderPrefixes, decoderName);