Use KEY_LOW_LATENCY to request low-latency decoding on Android R

This commit is contained in:
Cameron Gutman 2020-02-19 23:40:06 -08:00
parent c91d1097f6
commit 112d9c41eb
2 changed files with 35 additions and 4 deletions

View File

@ -45,6 +45,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
private Thread rendererThread; private Thread rendererThread;
private boolean needsSpsBitstreamFixup, isExynos4; private boolean needsSpsBitstreamFixup, isExynos4;
private boolean adaptivePlayback, directSubmit; private boolean adaptivePlayback, directSubmit;
private boolean lowLatency;
private boolean constrainedHighProfile; private boolean constrainedHighProfile;
private boolean refFrameInvalidationAvc, refFrameInvalidationHevc; private boolean refFrameInvalidationAvc, refFrameInvalidationHevc;
private boolean refFrameInvalidationActive; private boolean refFrameInvalidationActive;
@ -161,7 +162,6 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
// shared between AVC and HEVC decoders on the same device. // shared between AVC and HEVC decoders on the same device.
if (avcDecoder != null) { if (avcDecoder != null) {
directSubmit = MediaCodecHelper.decoderCanDirectSubmit(avcDecoder.getName()); directSubmit = MediaCodecHelper.decoderCanDirectSubmit(avcDecoder.getName());
adaptivePlayback = MediaCodecHelper.decoderSupportsAdaptivePlayback(avcDecoder);
refFrameInvalidationAvc = MediaCodecHelper.decoderSupportsRefFrameInvalidationAvc(avcDecoder.getName(), prefs.height); refFrameInvalidationAvc = MediaCodecHelper.decoderSupportsRefFrameInvalidationAvc(avcDecoder.getName(), prefs.height);
refFrameInvalidationHevc = MediaCodecHelper.decoderSupportsRefFrameInvalidationHevc(avcDecoder.getName()); refFrameInvalidationHevc = MediaCodecHelper.decoderSupportsRefFrameInvalidationHevc(avcDecoder.getName());
@ -264,6 +264,9 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
} }
refFrameInvalidationActive = refFrameInvalidationAvc; refFrameInvalidationActive = refFrameInvalidationAvc;
lowLatency = MediaCodecHelper.decoderSupportsLowLatency(avcDecoder, mimeType);
adaptivePlayback = MediaCodecHelper.decoderSupportsAdaptivePlayback(avcDecoder, mimeType);
} }
else if ((videoFormat & MoonBridge.VIDEO_FORMAT_MASK_H265) != 0) { else if ((videoFormat & MoonBridge.VIDEO_FORMAT_MASK_H265) != 0) {
mimeType = "video/hevc"; mimeType = "video/hevc";
@ -275,6 +278,9 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
} }
refFrameInvalidationActive = refFrameInvalidationHevc; refFrameInvalidationActive = refFrameInvalidationHevc;
lowLatency = MediaCodecHelper.decoderSupportsLowLatency(hevcDecoder, mimeType);
adaptivePlayback = MediaCodecHelper.decoderSupportsAdaptivePlayback(hevcDecoder, mimeType);
} }
else { else {
// Unknown format // Unknown format
@ -300,7 +306,10 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
videoFormat.setInteger(MediaFormat.KEY_MAX_HEIGHT, height); videoFormat.setInteger(MediaFormat.KEY_MAX_HEIGHT, height);
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (lowLatency) {
videoFormat.setInteger(MediaCodecHelper.KEY_LOW_LATENCY, 1);
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Operate at maximum rate to lower latency as much as possible on // Operate at maximum rate to lower latency as much as possible on
// some Qualcomm platforms. We could also set KEY_PRIORITY to 0 (realtime) // some Qualcomm platforms. We could also set KEY_PRIORITY to 0 (realtime)
// but that will actually result in the decoder crashing if it can't satisfy // but that will actually result in the decoder crashing if it can't satisfy
@ -1031,6 +1040,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
str += "Consecutive crashes: "+renderer.consecutiveCrashCount+"\n"; str += "Consecutive crashes: "+renderer.consecutiveCrashCount+"\n";
str += "RFI active: "+renderer.refFrameInvalidationActive+"\n"; str += "RFI active: "+renderer.refFrameInvalidationActive+"\n";
str += "Using modern SPS patching: "+(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)+"\n"; str += "Using modern SPS patching: "+(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)+"\n";
str += "Low latency mode: "+renderer.lowLatency+"\n";
str += "Video dimensions: "+renderer.initialWidth+"x"+renderer.initialHeight+"\n"; str += "Video dimensions: "+renderer.initialWidth+"x"+renderer.initialHeight+"\n";
str += "FPS target: "+renderer.refreshRate+"\n"; str += "FPS target: "+renderer.refreshRate+"\n";
str += "Bitrate: "+renderer.prefs.bitrate+" Kbps \n"; str += "Bitrate: "+renderer.prefs.bitrate+" Kbps \n";

View File

@ -39,6 +39,10 @@ public class MediaCodecHelper {
private static final List<String> blacklisted49FpsDecoderPrefixes; private static final List<String> blacklisted49FpsDecoderPrefixes;
private static final List<String> blacklisted59FpsDecoderPrefixes; private static final List<String> blacklisted59FpsDecoderPrefixes;
// FIXME: Remove when Android R SDK is finalized
public static final String FEATURE_LowLatency = "low-latency";
public static final String KEY_LOW_LATENCY = "low-latency";
private static boolean isLowEndSnapdragon = false; private static boolean isLowEndSnapdragon = false;
private static boolean initialized = false; private static boolean initialized = false;
@ -330,7 +334,23 @@ public class MediaCodecHelper {
return System.nanoTime() / 1000000L; return System.nanoTime() / 1000000L;
} }
public static boolean decoderSupportsAdaptivePlayback(MediaCodecInfo decoderInfo) { public static boolean decoderSupportsLowLatency(MediaCodecInfo decoderInfo, String mimeType) {
try {
if (decoderInfo.getCapabilitiesForType(mimeType).
isFeatureSupported(FEATURE_LowLatency))
{
LimeLog.info("Low latency decoding mode supported (FEATURE_LowLatency)");
return true;
}
} catch (Exception e) {
// Tolerate buggy codecs
e.printStackTrace();
}
return false;
}
public static boolean decoderSupportsAdaptivePlayback(MediaCodecInfo decoderInfo, String mimeType) {
// Possibly enable adaptive playback on KitKat and above // Possibly enable adaptive playback on KitKat and above
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (isDecoderInList(blacklistedAdaptivePlaybackPrefixes, decoderInfo.getName())) { if (isDecoderInList(blacklistedAdaptivePlaybackPrefixes, decoderInfo.getName())) {
@ -339,7 +359,7 @@ public class MediaCodecHelper {
} }
try { try {
if (decoderInfo.getCapabilitiesForType("video/avc"). if (decoderInfo.getCapabilitiesForType(mimeType).
isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback)) isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback))
{ {
// This will make getCapabilities() return that adaptive playback is supported // This will make getCapabilities() return that adaptive playback is supported
@ -348,6 +368,7 @@ public class MediaCodecHelper {
} }
} catch (Exception e) { } catch (Exception e) {
// Tolerate buggy codecs // Tolerate buggy codecs
e.printStackTrace();
} }
} }