From d2773be32eb19db4ed9fc5e7bab7ceab18721cc1 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Mon, 14 Apr 2014 13:24:52 -0400 Subject: [PATCH] Separate the different SPS fixups by decoder. Go back to the old way of doing bitstream restrictions because the new way seems to be broken. TI OMAP4's Ducati decoder works now :) --- .../video/MediaCodecDecoderRenderer.java | 87 ++++++++++++++----- 1 file changed, 65 insertions(+), 22 deletions(-) diff --git a/src/com/limelight/binding/video/MediaCodecDecoderRenderer.java b/src/com/limelight/binding/video/MediaCodecDecoderRenderer.java index 1d8034cd..d9150527 100644 --- a/src/com/limelight/binding/video/MediaCodecDecoderRenderer.java +++ b/src/com/limelight/binding/video/MediaCodecDecoderRenderer.java @@ -24,24 +24,27 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer { private MediaCodec videoDecoder; private Thread rendererThread; private int redrawRate; - private boolean needsSpsFixup; + private boolean needsSpsBitstreamFixup; + private boolean needsSpsNumRefFixup; private boolean fastInputQueueing; public static final List blacklistedDecoderPrefixes; - public static final List spsFixupDecoderPrefixes; + public static final List spsFixupBitsreamFixupDecoderPrefixes; + public static final List spsFixupNumRefFixupDecoderPrefixes; public static final List fastInputQueueingPrefixes; static { blacklistedDecoderPrefixes = new LinkedList(); - // TI's decoder technically supports high profile but doesn't work for some reason - blacklistedDecoderPrefixes.add("omx.TI"); + // Nothing here right now :) } - private final static byte[] BITSTREAM_RESTRICTIONS = new byte[] {(byte) 0xF1, (byte) 0x83, 0x2A, 0x00}; static { - spsFixupDecoderPrefixes = new LinkedList(); - spsFixupDecoderPrefixes.add("omx.nvidia"); + spsFixupBitsreamFixupDecoderPrefixes = new LinkedList(); + spsFixupBitsreamFixupDecoderPrefixes.add("omx.nvidia"); + + spsFixupNumRefFixupDecoderPrefixes = new LinkedList(); + spsFixupNumRefFixupDecoderPrefixes.add("omx.TI"); } static { @@ -129,9 +132,13 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer { MediaCodecInfo safeDecoder = findSafeDecoder(); if (safeDecoder != null) { videoDecoder = MediaCodec.createByCodecName(safeDecoder.getName()); - needsSpsFixup = isDecoderInList(spsFixupDecoderPrefixes, safeDecoder.getName()); - if (needsSpsFixup) { - LimeLog.info("Decoder "+safeDecoder.getName()+" needs SPS fixup"); + needsSpsBitstreamFixup = isDecoderInList(spsFixupBitsreamFixupDecoderPrefixes, safeDecoder.getName()); + needsSpsNumRefFixup = isDecoderInList(spsFixupNumRefFixupDecoderPrefixes, safeDecoder.getName()); + if (needsSpsBitstreamFixup) { + LimeLog.info("Decoder "+safeDecoder.getName()+" needs SPS bitstream restrictions fixup"); + } + if (needsSpsNumRefFixup) { + LimeLog.info("Decoder "+safeDecoder.getName()+" needs SPS ref num fixup"); } fastInputQueueing = isDecoderInList(fastInputQueueingPrefixes, safeDecoder.getName()); if (fastInputQueueing) { @@ -140,7 +147,8 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer { } else { videoDecoder = MediaCodec.createDecoderByType("video/avc"); - needsSpsFixup = false; + needsSpsBitstreamFixup = false; + needsSpsNumRefFixup = false; fastInputQueueing = false; } @@ -257,20 +265,55 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer { // Clear old input data 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) { + if (needsSpsBitstreamFixup || needsSpsNumRefFixup) { ByteBufferDescriptor header = decodeUnit.getBufferList().get(0); if (header.data[header.offset+4] == 0x67) { - LimeLog.info("Fixing up SPS"); - - //Set number of reference frames back to 1 as it's the minimum for bitstream restrictions - this.replace(header, 80, 9, new byte[] {0x40}, 3); + // TI OMAP4 requires a reference frame count of 1 to decode successfully + if (needsSpsNumRefFixup) { + LimeLog.info("Fixing up num ref frames"); + this.replace(header, 80, 9, new byte[] {0x40}, 3); + } - //Set bitstream restrictions to only buffer single frame - byte last = header.data[header.length+header.offset-1]; - this.replace(header, header.length*8+Integer.numberOfLeadingZeros(last & - last)%8-9, 2, BITSTREAM_RESTRICTIONS, 3*8); + // 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. + int spsLength; + if (needsSpsBitstreamFixup) { + switch (header.length) { + case 26: + LimeLog.info("Adding bitstream restrictions to 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: + LimeLog.info("Adding bitstream restrictions to 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: + LimeLog.warning("Unknown SPS of length "+header.length); + buf.put(header.data, header.offset, header.length); + spsLength = header.length; + break; + } + } + else { + buf.put(header.data, header.offset, header.length); + spsLength = header.length; + } + + videoDecoder.queueInputBuffer(inputIndex, + 0, spsLength, + 0, mcFlags); + return true; } }