Only use SPS hack on Tegra devices

This commit is contained in:
Cameron Gutman
2014-01-10 01:05:15 -06:00
parent 81ae7bd638
commit 46fbee1a3b
@@ -21,8 +21,10 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
private MediaCodec videoDecoder; private MediaCodec videoDecoder;
private Thread rendererThread; private Thread rendererThread;
private int redrawRate; private int redrawRate;
private boolean needsSpsFixup;
public static final List<String> blacklistedDecoderPrefixes; public static final List<String> blacklistedDecoderPrefixes;
public static final List<String> spsFixupDecoderPrefixes;
static { static {
blacklistedDecoderPrefixes = new LinkedList<String>(); blacklistedDecoderPrefixes = new LinkedList<String>();
@@ -31,6 +33,24 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
blacklistedDecoderPrefixes.add("AVCDecoder"); blacklistedDecoderPrefixes.add("AVCDecoder");
} }
static {
spsFixupDecoderPrefixes = new LinkedList<String>();
spsFixupDecoderPrefixes.add("omx.nvidia");
}
private static boolean decoderNeedsSpsFixup(String decoderName) {
for (String badPrefix : spsFixupDecoderPrefixes) {
if (decoderName.length() >= badPrefix.length()) {
String prefix = decoderName.substring(0, badPrefix.length());
if (prefix.equalsIgnoreCase(badPrefix)) {
return true;
}
}
}
return false;
}
public static MediaCodecInfo findSafeDecoder() { public static MediaCodecInfo findSafeDecoder() {
for (int i = 0; i < MediaCodecList.getCodecCount(); i++) { for (int i = 0; i < MediaCodecList.getCodecCount(); i++) {
@@ -76,9 +96,14 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
MediaCodecInfo safeDecoder = findSafeDecoder(); MediaCodecInfo safeDecoder = findSafeDecoder();
if (safeDecoder != null) { if (safeDecoder != null) {
videoDecoder = MediaCodec.createByCodecName(safeDecoder.getName()); videoDecoder = MediaCodec.createByCodecName(safeDecoder.getName());
needsSpsFixup = decoderNeedsSpsFixup(safeDecoder.getName());
if (needsSpsFixup) {
System.out.println("Decoder "+safeDecoder.getName()+" needs SPS fixup");
}
} }
else { else {
videoDecoder = MediaCodec.createDecoderByType("video/avc"); videoDecoder = MediaCodec.createDecoderByType("video/avc");
needsSpsFixup = false;
} }
MediaFormat videoFormat = MediaFormat.createVideoFormat("video/avc", width, height); MediaFormat videoFormat = MediaFormat.createVideoFormat("video/avc", width, height);
@@ -173,6 +198,48 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
// Clear old input data // Clear old input data
buf.clear(); buf.clear();
// 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.
// We manually modify the SPS here to speed-up decoding if the decoder was flagged as needing it.
if (needsSpsFixup) {
ByteBufferDescriptor header = decodeUnit.getBufferList().get(0);
// Check for SPS NALU type
if (header.data[header.offset+4] == 0x67) {
int spsLength;
switch (header.length) {
case 26:
System.out.println("Modifying SPS (26)");
buf.put(header.data, header.offset, 24);
buf.put((byte) 0x11);
buf.put((byte) 0xe3);
buf.put((byte) 0x06);
buf.put((byte) 0x50);
spsLength = header.length + 2;
break;
case 27:
System.out.println("Modifying SPS (27)");
buf.put(header.data, header.offset, 25);
buf.put((byte) 0x04);
buf.put((byte) 0x78);
buf.put((byte) 0xc1);
buf.put((byte) 0x94);
spsLength = header.length + 2;
break;
default:
System.out.println("Unknown SPS of length "+header.length);
buf.put(header.data, header.offset, header.length);
spsLength = header.length;
break;
}
videoDecoder.queueInputBuffer(inputIndex,
0, spsLength,
0, decodeUnit.getFlags());
return true;
}
}
// Copy data from our buffer list into the input buffer // Copy data from our buffer list into the input buffer
for (ByteBufferDescriptor desc : decodeUnit.getBufferList()) for (ByteBufferDescriptor desc : decodeUnit.getBufferList())
{ {
@@ -180,8 +247,8 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
} }
videoDecoder.queueInputBuffer(inputIndex, videoDecoder.queueInputBuffer(inputIndex,
0, decodeUnit.getDataLength(), 0, decodeUnit.getDataLength(),
0, decodeUnit.getFlags()); 0, decodeUnit.getFlags());
} }
return true; return true;