Add a workaround for the Nexus 9 dropping frames with the new renderer

This commit is contained in:
Cameron Gutman 2015-03-16 21:26:02 -04:00
parent 42c65f4f16
commit 7ce29e3a09
2 changed files with 34 additions and 5 deletions

View File

@ -27,10 +27,11 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
private ByteBuffer[] videoDecoderInputBuffers; private ByteBuffer[] videoDecoderInputBuffers;
private MediaCodec videoDecoder; private MediaCodec videoDecoder;
private Thread rendererThread; private Thread rendererThread;
private boolean needsSpsBitstreamFixup, isExynos4; private final boolean needsSpsBitstreamFixup, isExynos4;
private VideoDepacketizer depacketizer; private VideoDepacketizer depacketizer;
private boolean adaptivePlayback; private final boolean adaptivePlayback;
private int initialWidth, initialHeight; private int initialWidth, initialHeight;
private final int dequeueOutputBufferTimeout;
private boolean needsBaselineSpsHack; private boolean needsBaselineSpsHack;
private SeqParameterSet savedSps; private SeqParameterSet savedSps;
@ -55,12 +56,17 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
} }
if (decoder == null) { if (decoder == null) {
// This case is handled later in setup() // This case is handled later in setup()
needsSpsBitstreamFixup = false;
isExynos4 = false;
adaptivePlayback = false;
dequeueOutputBufferTimeout = 0;
return; return;
} }
decoderName = decoder.getName(); decoderName = decoder.getName();
// Set decoder-specific attributes // Set decoder-specific attributes
dequeueOutputBufferTimeout = MediaCodecHelper.getOptimalOutputBufferDequeueTimeout(decoderName, decoder);
adaptivePlayback = MediaCodecHelper.decoderSupportsAdaptivePlayback(decoderName, decoder); adaptivePlayback = MediaCodecHelper.decoderSupportsAdaptivePlayback(decoderName, decoder);
needsSpsBitstreamFixup = MediaCodecHelper.decoderNeedsSpsBitstreamRestrictions(decoderName, decoder); needsSpsBitstreamFixup = MediaCodecHelper.decoderNeedsSpsBitstreamRestrictions(decoderName, decoder);
needsBaselineSpsHack = MediaCodecHelper.decoderNeedsBaselineSpsHack(decoderName, decoder); needsBaselineSpsHack = MediaCodecHelper.decoderNeedsBaselineSpsHack(decoderName, decoder);
@ -145,7 +151,7 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
while (!isInterrupted()) { while (!isInterrupted()) {
try { try {
// Try to output a frame // Try to output a frame
int outIndex = videoDecoder.dequeueOutputBuffer(info, 50000); int outIndex = videoDecoder.dequeueOutputBuffer(info, dequeueOutputBufferTimeout);
if (outIndex >= 0) { if (outIndex >= 0) {
long presentationTimeUs = info.presentationTimeUs; long presentationTimeUs = info.presentationTimeUs;
int lastIndex = outIndex; int lastIndex = outIndex;
@ -189,7 +195,7 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer {
} }
}; };
rendererThread.setName("Video - Renderer (MediaCodec)"); rendererThread.setName("Video - Renderer (MediaCodec)");
rendererThread.setPriority(Thread.MAX_PRIORITY); rendererThread.setPriority(Thread.NORM_PRIORITY + 2);
rendererThread.start(); rendererThread.start();
} }

View File

@ -26,7 +26,16 @@ public class MediaCodecHelper {
private static final List<String> spsFixupBitstreamFixupDecoderPrefixes; private static final List<String> spsFixupBitstreamFixupDecoderPrefixes;
private static final List<String> whitelistedAdaptiveResolutionPrefixes; private static final List<String> whitelistedAdaptiveResolutionPrefixes;
private static final List<String> baselineProfileHackPrefixes; private static final List<String> baselineProfileHackPrefixes;
private static final List<String> 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<String>();
fastOutputPollPrefixes.add("omx.nvidia");
}
static { static {
preferredDecoders = new LinkedList<String>(); preferredDecoders = new LinkedList<String>();
} }
@ -97,6 +106,20 @@ public class MediaCodecHelper {
return false; 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) { public static boolean decoderNeedsSpsBitstreamRestrictions(String decoderName, MediaCodecInfo decoderInfo) {
return isDecoderInList(spsFixupBitstreamFixupDecoderPrefixes, decoderName); return isDecoderInList(spsFixupBitstreamFixupDecoderPrefixes, decoderName);