Fix crash on MediaTek PAL Android TVs

This commit is contained in:
Cameron Gutman 2018-02-10 16:42:45 -08:00
parent ef3b28295b
commit 617c8582b4
3 changed files with 42 additions and 8 deletions

View File

@ -329,13 +329,21 @@ public class Game extends Activity implements SurfaceHolder.Callback,
// Hopefully, we can get rid of this once someone comes up with a better way // Hopefully, we can get rid of this once someone comes up with a better way
// to track the state of the pipeline and time frames. // to track the state of the pipeline and time frames.
int roundedRefreshRate = Math.round(displayRefreshRate); int roundedRefreshRate = Math.round(displayRefreshRate);
if (roundedRefreshRate <= 49) {
// Let's avoid clearly bogus refresh rates
roundedRefreshRate = 60;
}
if (!prefConfig.disableFrameDrop && prefConfig.fps >= roundedRefreshRate) { if (!prefConfig.disableFrameDrop && prefConfig.fps >= roundedRefreshRate) {
prefConfig.fps = roundedRefreshRate - 1; if (roundedRefreshRate <= 49) {
LimeLog.info("Adjusting FPS target for screen to "+prefConfig.fps); // Let's avoid clearly bogus refresh rates and fall back to legacy rendering
decoderRenderer.enableLegacyFrameDropRendering();
LimeLog.info("Bogus refresh rate: "+roundedRefreshRate);
}
// HACK: Avoid crashing on some MTK devices
else if (roundedRefreshRate == 50 && decoderRenderer.is49FpsBlacklisted()) {
// Use the old rendering strategy on these broken devices
decoderRenderer.enableLegacyFrameDropRendering();
}
else {
prefConfig.fps = roundedRefreshRate - 1;
LimeLog.info("Adjusting FPS target for screen to "+prefConfig.fps);
}
} }
StreamConfiguration config = new StreamConfiguration.Builder() StreamConfiguration config = new StreamConfiguration.Builder()

View File

@ -56,6 +56,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
private int consecutiveCrashCount; private int consecutiveCrashCount;
private String glRenderer; private String glRenderer;
private boolean foreground = true; private boolean foreground = true;
private boolean legacyFrameDropRendering = false;
private boolean needsBaselineSpsHack; private boolean needsBaselineSpsHack;
private SeqParameterSet savedSps; private SeqParameterSet savedSps;
@ -191,6 +192,15 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
return avcDecoder != null; return avcDecoder != null;
} }
public boolean is49FpsBlacklisted() {
return avcDecoder != null && MediaCodecHelper.decoderBlacklistedFor49Fps(avcDecoder.getName());
}
public void enableLegacyFrameDropRendering() {
LimeLog.info("Legacy frame drop rendering enabled");
legacyFrameDropRendering = true;
}
public boolean isHevcMain10Hdr10Supported() { public boolean isHevcMain10Hdr10Supported() {
if (hevcDecoder == null) { if (hevcDecoder == null) {
return false; return false;
@ -410,7 +420,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
} }
// Render the last buffer // Render the last buffer
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !legacyFrameDropRendering) {
// Use a PTS that will cause this frame to never be dropped if frame dropping // Use a PTS that will cause this frame to never be dropped if frame dropping
// is disabled // is disabled
videoDecoder.releaseOutputBuffer(lastIndex, 0); videoDecoder.releaseOutputBuffer(lastIndex, 0);

View File

@ -36,6 +36,7 @@ public class MediaCodecHelper {
private static final List<String> whitelistedHevcDecoders; private static final List<String> whitelistedHevcDecoders;
private static final List<String> refFrameInvalidationAvcPrefixes; private static final List<String> refFrameInvalidationAvcPrefixes;
private static final List<String> refFrameInvalidationHevcPrefixes; private static final List<String> refFrameInvalidationHevcPrefixes;
private static final List<String> blacklisted49FpsDecoderPrefixes;
private static boolean isLowEndSnapdragon = false; private static boolean isLowEndSnapdragon = false;
private static boolean initialized = false; private static boolean initialized = false;
@ -153,6 +154,17 @@ public class MediaCodecHelper {
// Qualcomm is currently the only decoders in this group. // Qualcomm is currently the only decoders in this group.
} }
static {
blacklisted49FpsDecoderPrefixes = new LinkedList<>();
// We see a bunch of crashes on MediaTek Android TVs running
// at 49 FPS (PAL 50 Hz - 1). Blacklist this frame rate for
// these devices and hope they fix it in Oreo.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
blacklisted49FpsDecoderPrefixes.add("omx.mtk");
}
}
private static String getAdrenoVersionString(String glRenderer) { private static String getAdrenoVersionString(String glRenderer) {
glRenderer = glRenderer.toLowerCase().trim(); glRenderer = glRenderer.toLowerCase().trim();
@ -271,7 +283,7 @@ public class MediaCodecHelper {
public static long getMonotonicMillis() { public static long getMonotonicMillis() {
return System.nanoTime() / 1000000L; return System.nanoTime() / 1000000L;
} }
public static boolean decoderSupportsAdaptivePlayback(MediaCodecInfo decoderInfo) { public static boolean decoderSupportsAdaptivePlayback(MediaCodecInfo decoderInfo) {
// 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) {
@ -312,6 +324,10 @@ public class MediaCodecHelper {
return isDecoderInList(baselineProfileHackPrefixes, decoderName); return isDecoderInList(baselineProfileHackPrefixes, decoderName);
} }
public static boolean decoderBlacklistedFor49Fps(String decoderName) {
return isDecoderInList(blacklisted49FpsDecoderPrefixes, decoderName);
}
public static boolean decoderSupportsRefFrameInvalidationAvc(String decoderName, int videoHeight) { public static boolean decoderSupportsRefFrameInvalidationAvc(String decoderName, int videoHeight) {
// Reference frame invalidation is broken on low-end Snapdragon SoCs at 1080p. // Reference frame invalidation is broken on low-end Snapdragon SoCs at 1080p.
if (videoHeight > 720 && isLowEndSnapdragon) { if (videoHeight > 720 && isLowEndSnapdragon) {