Also add bitstream restrictions to Qualcomm devices to hopefully address the GS3 issue

This commit is contained in:
Cameron Gutman 2014-08-06 17:22:41 -07:00
parent ac5c264090
commit b2ad259a7c

View File

@ -48,6 +48,7 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
static { static {
spsFixupBitsreamFixupDecoderPrefixes = new LinkedList<String>(); spsFixupBitsreamFixupDecoderPrefixes = new LinkedList<String>();
spsFixupBitsreamFixupDecoderPrefixes.add("omx.nvidia"); spsFixupBitsreamFixupDecoderPrefixes.add("omx.nvidia");
spsFixupBitsreamFixupDecoderPrefixes.add("omx.qcom");
spsFixupNumRefFixupDecoderPrefixes = new LinkedList<String>(); spsFixupNumRefFixupDecoderPrefixes = new LinkedList<String>();
spsFixupNumRefFixupDecoderPrefixes.add("omx.TI"); spsFixupNumRefFixupDecoderPrefixes.add("omx.TI");
@ -179,7 +180,7 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
if (du != null) { if (du != null) {
if (!submitDecodeUnit(du)) { if (!submitDecodeUnit(du)) {
// Thread was interrupted // Thread was interrupted
depacketizer.freeDecodeUnit(du); depacketizer.freeDecodeUnit(du);
return; return;
} }
else { else {
@ -266,101 +267,101 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
inputIndex = videoDecoder.dequeueInputBuffer(100000); inputIndex = videoDecoder.dequeueInputBuffer(100000);
} while (inputIndex < 0); } while (inputIndex < 0);
ByteBuffer buf = videoDecoderInputBuffers[inputIndex]; ByteBuffer buf = videoDecoderInputBuffers[inputIndex];
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
long delta = currentTime-decodeUnit.getReceiveTimestamp(); long delta = currentTime-decodeUnit.getReceiveTimestamp();
if (delta >= 0 && delta < 300) { if (delta >= 0 && delta < 300) {
totalTimeMs += currentTime-decodeUnit.getReceiveTimestamp(); totalTimeMs += currentTime-decodeUnit.getReceiveTimestamp();
totalFrames++; totalFrames++;
} }
// Clear old input data // Clear old input data
buf.clear(); buf.clear();
int codecFlags = 0; int codecFlags = 0;
int decodeUnitFlags = decodeUnit.getFlags(); int decodeUnitFlags = decodeUnit.getFlags();
if ((decodeUnitFlags & DecodeUnit.DU_FLAG_CODEC_CONFIG) != 0) { if ((decodeUnitFlags & DecodeUnit.DU_FLAG_CODEC_CONFIG) != 0) {
codecFlags |= MediaCodec.BUFFER_FLAG_CODEC_CONFIG; codecFlags |= MediaCodec.BUFFER_FLAG_CODEC_CONFIG;
} }
if ((decodeUnitFlags & DecodeUnit.DU_FLAG_SYNC_FRAME) != 0) { if ((decodeUnitFlags & DecodeUnit.DU_FLAG_SYNC_FRAME) != 0) {
codecFlags |= MediaCodec.BUFFER_FLAG_SYNC_FRAME; codecFlags |= MediaCodec.BUFFER_FLAG_SYNC_FRAME;
} }
if ((decodeUnitFlags & DecodeUnit.DU_FLAG_CODEC_CONFIG) != 0 && if ((decodeUnitFlags & DecodeUnit.DU_FLAG_CODEC_CONFIG) != 0 &&
(needsSpsBitstreamFixup || needsSpsNumRefFixup)) { (needsSpsBitstreamFixup || needsSpsNumRefFixup)) {
ByteBufferDescriptor header = decodeUnit.getBufferList().get(0); ByteBufferDescriptor header = decodeUnit.getBufferList().get(0);
if (header.data[header.offset+4] == 0x67) { if (header.data[header.offset+4] == 0x67) {
byte last = header.data[header.length+header.offset-1]; byte last = header.data[header.length+header.offset-1];
// TI OMAP4 requires a reference frame count of 1 to decode successfully // TI OMAP4 requires a reference frame count of 1 to decode successfully
if (needsSpsNumRefFixup) { if (needsSpsNumRefFixup) {
LimeLog.info("Fixing up num ref frames"); LimeLog.info("Fixing up num ref frames");
this.replace(header, 80, 9, new byte[] {0x40}, 3); this.replace(header, 80, 9, new byte[] {0x40}, 3);
} }
// 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.
// We manually modify the SPS here to speed-up decoding if the decoder was flagged as needing it. // We manually modify the SPS here to speed-up decoding if the decoder was flagged as needing it.
int spsLength; int spsLength;
if (needsSpsBitstreamFixup) { if (needsSpsBitstreamFixup) {
if (!needsSpsNumRefFixup) { if (!needsSpsNumRefFixup) {
switch (header.length) { switch (header.length) {
case 26: case 26:
LimeLog.info("Adding bitstream restrictions to SPS (26)"); LimeLog.info("Adding bitstream restrictions to SPS (26)");
buf.put(header.data, header.offset, 24); buf.put(header.data, header.offset, 24);
buf.put((byte) 0x11); buf.put((byte) 0x11);
buf.put((byte) 0xe3); buf.put((byte) 0xe3);
buf.put((byte) 0x06); buf.put((byte) 0x06);
buf.put((byte) 0x50); buf.put((byte) 0x50);
spsLength = header.length + 2; spsLength = header.length + 2;
break; break;
case 27: case 27:
LimeLog.info("Adding bitstream restrictions to SPS (27)"); LimeLog.info("Adding bitstream restrictions to SPS (27)");
buf.put(header.data, header.offset, 25); buf.put(header.data, header.offset, 25);
buf.put((byte) 0x04); buf.put((byte) 0x04);
buf.put((byte) 0x78); buf.put((byte) 0x78);
buf.put((byte) 0xc1); buf.put((byte) 0xc1);
buf.put((byte) 0x94); buf.put((byte) 0x94);
spsLength = header.length + 2; spsLength = header.length + 2;
break; break;
default: default:
LimeLog.warning("Unknown SPS of length "+header.length); LimeLog.warning("Unknown SPS of length "+header.length);
buf.put(header.data, header.offset, header.length);
spsLength = header.length;
break;
}
}
else {
// Set bitstream restrictions to only buffer single frame
// (starts 9 bits before stop bit and 6 bits earlier because of the shortening above)
this.replace(header, header.length*8+Integer.numberOfLeadingZeros(last & - last)%8-9-6, 2, BITSTREAM_RESTRICTIONS, 3*8);
buf.put(header.data, header.offset, header.length); buf.put(header.data, header.offset, header.length);
spsLength = header.length; spsLength = header.length;
break;
} }
} }
else { else {
// Set bitstream restrictions to only buffer single frame
// (starts 9 bits before stop bit and 6 bits earlier because of the shortening above)
this.replace(header, header.length*8+Integer.numberOfLeadingZeros(last & - last)%8-9-6, 2, BITSTREAM_RESTRICTIONS, 3*8);
buf.put(header.data, header.offset, header.length); buf.put(header.data, header.offset, header.length);
spsLength = header.length; spsLength = header.length;
} }
videoDecoder.queueInputBuffer(inputIndex,
0, spsLength,
currentTime * 1000, codecFlags);
return true;
} }
} else {
buf.put(header.data, header.offset, header.length);
spsLength = header.length;
}
// Copy data from our buffer list into the input buffer videoDecoder.queueInputBuffer(inputIndex,
for (ByteBufferDescriptor desc : decodeUnit.getBufferList()) 0, spsLength,
{ currentTime * 1000, codecFlags);
buf.put(desc.data, desc.offset, desc.length); return true;
} }
}
videoDecoder.queueInputBuffer(inputIndex, // Copy data from our buffer list into the input buffer
0, decodeUnit.getDataLength(), for (ByteBufferDescriptor desc : decodeUnit.getBufferList())
currentTime * 1000, codecFlags); {
buf.put(desc.data, desc.offset, desc.length);
}
videoDecoder.queueInputBuffer(inputIndex,
0, decodeUnit.getDataLength(),
currentTime * 1000, codecFlags);
return true; return true;
} }