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. 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. 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, Exynos 4 - 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. 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 - 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 - 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 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 5. Some decoders will hang if max_dec_frame_buffering is not present
- Affected decoders: MediaTek decoder in Fire HD 7 (2014) - 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.os.Build;
import android.view.SurfaceHolder; import android.view.SurfaceHolder;
@SuppressWarnings("unused")
public class MediaCodecDecoderRenderer implements VideoDecoderRenderer { public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
private ByteBuffer[] videoDecoderInputBuffers; private ByteBuffer[] videoDecoderInputBuffers;
private MediaCodec videoDecoder; private MediaCodec videoDecoder;
private Thread rendererThread; private Thread rendererThread;
private boolean needsSpsBitstreamFixup; private boolean needsSpsBitstreamFixup, isExynos4;
private VideoDepacketizer depacketizer; private VideoDepacketizer depacketizer;
private boolean adaptivePlayback; private boolean adaptivePlayback;
private int initialWidth, initialHeight; private int initialWidth, initialHeight;
@@ -65,6 +66,10 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
if (needsSpsBitstreamFixup) { if (needsSpsBitstreamFixup) {
LimeLog.info("Decoder "+decoderName+" needs SPS bitstream restrictions fixup"); 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) @TargetApi(Build.VERSION_CODES.LOLLIPOP)
@@ -406,7 +411,7 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
LimeLog.info("Patching num_ref_frames in SPS"); LimeLog.info("Patching num_ref_frames in SPS");
sps.num_ref_frames = 1; 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 // 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. // or max_dec_frame_buffering which increases decoding latency on Tegra.
LimeLog.info("Adding bitstream restrictions"); LimeLog.info("Adding bitstream restrictions");
@@ -512,6 +517,15 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
str += "Buffer codec flags: "+currentCodecFlags+"\n"; 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"; str += "Full decoder dump:\n";
try { try {
str += MediaCodecHelper.dumpDecoders(); str += MediaCodecHelper.dumpDecoders();

View File

@@ -1,7 +1,11 @@
package com.limelight.binding.video; package com.limelight.binding.video;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Locale;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.annotation.TargetApi; import android.annotation.TargetApi;
@@ -233,4 +237,63 @@ public class MediaCodecHelper {
return null; 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;
}
} }