Attempt to detect Exynos 4 to apply the bitstream fixup code

This commit is contained in:
Cameron Gutman
2014-10-21 19:20:54 -04:00
parent 7b1f6ee483
commit 6f05b2af8a
3 changed files with 82 additions and 5 deletions

View File

@@ -1,7 +1,7 @@
This file serves to document some of the decoder errata when using MediaCodec hardware decoders on certain devices.
1. num_ref_frames is set to 16 by NVENC which causes decoders to allocate 16+ buffers. This can cause an error on some devices.
- Affected decoders: TI OMAP4, Exynos 4
1. num_ref_frames is set to 16 by NVENC which causes decoders to allocate 16+ buffers. This can cause an error or lag on some devices.
- Affected decoders: TI OMAP4, Allwinner A20
2. Some decoders have a huge per-frame latency with the unmodified SPS sent from NVENC. Setting max_dec_frame_buffering fixes this latency issue.
- Affected decoders: NVIDIA Tegra 3 and 4
@@ -10,7 +10,7 @@ This file serves to document some of the decoder errata when using MediaCodec ha
- Affected decoders: TI OMAP4
4. Some decoders require num_ref_frames=1 and max_dec_frame_buffering=1 to avoid crashing on SPS or first I-frame
- Affected decoders: Qualcomm in GS3 on 4.3+
- Affected decoders: Qualcomm in GS3 on 4.3+, Exynos 4 at 1080p only
5. Some decoders will hang if max_dec_frame_buffering is not present
- Affected decoders: MediaTek decoder in Fire HD 7 (2014)

View File

@@ -22,12 +22,13 @@ import android.media.MediaCodec.CodecException;
import android.os.Build;
import android.view.SurfaceHolder;
@SuppressWarnings("unused")
public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
private ByteBuffer[] videoDecoderInputBuffers;
private MediaCodec videoDecoder;
private Thread rendererThread;
private boolean needsSpsBitstreamFixup;
private boolean needsSpsBitstreamFixup, isExynos4;
private VideoDepacketizer depacketizer;
private boolean adaptivePlayback;
private int initialWidth, initialHeight;
@@ -65,6 +66,10 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
if (needsSpsBitstreamFixup) {
LimeLog.info("Decoder "+decoderName+" needs SPS bitstream restrictions fixup");
}
isExynos4 = MediaCodecHelper.isExynos4Device();
if (isExynos4) {
LimeLog.info("Decoder "+decoderName+" is on Exynos 4");
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@@ -406,7 +411,7 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
LimeLog.info("Patching num_ref_frames in SPS");
sps.num_ref_frames = 1;
if (needsSpsBitstreamFixup) {
if (needsSpsBitstreamFixup || isExynos4) {
// The SPS that comes in the current H264 bytestream doesn't set bitstream_restriction_flag
// or max_dec_frame_buffering which increases decoding latency on Tegra.
LimeLog.info("Adding bitstream restrictions");
@@ -512,6 +517,15 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
str += "Buffer codec flags: "+currentCodecFlags+"\n";
}
str += "Is Exynos 4: "+renderer.isExynos4+"\n";
str += "/proc/cpuinfo:\n";
try {
str += MediaCodecHelper.readCpuinfo();
} catch (Exception e) {
str += e.getMessage();
}
str += "Full decoder dump:\n";
try {
str += MediaCodecHelper.dumpDecoders();

View File

@@ -1,7 +1,11 @@
package com.limelight.binding.video;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
@@ -233,4 +237,63 @@ public class MediaCodecHelper {
return null;
}
public static String readCpuinfo() throws Exception {
StringBuilder cpuInfo = new StringBuilder();
BufferedReader br = new BufferedReader(new FileReader(new File("/proc/cpuinfo")));
try {
for (;;) {
int ch = br.read();
if (ch == -1)
break;
cpuInfo.append((char)ch);
}
return cpuInfo.toString();
} finally {
br.close();
}
}
private static boolean stringContainsIgnoreCase(String string, String substring) {
return string.toLowerCase(Locale.ENGLISH).contains(substring.toLowerCase(Locale.ENGLISH));
}
public static boolean isExynos4Device() {
try {
// Try reading CPU info too look for
String cpuInfo = readCpuinfo();
// SMDK4xxx is Exynos 4
if (stringContainsIgnoreCase(cpuInfo, "SMDK4")) {
LimeLog.info("Found SMDK4 in /proc/cpuinfo");
return true;
}
// If we see "Exynos 4" also we'll count it
if (stringContainsIgnoreCase(cpuInfo, "Exynos 4")) {
LimeLog.info("Found Exynos 4 in /proc/cpuinfo");
return true;
}
} catch (Exception e) {
e.printStackTrace();
}
try {
File systemDir = new File("/sys/devices/system");
File[] files = systemDir.listFiles();
if (files != null) {
for (File f : files) {
if (stringContainsIgnoreCase(f.getName(), "exynos4")) {
LimeLog.info("Found exynos4 in /sys/devices/system");
return true;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}