From 1531629fcd056972a069fb012e22b2260588f605 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Mon, 10 Nov 2014 23:59:23 -0800 Subject: [PATCH] Also use the slow path for the last packet in each frame because it may be padded --- .../nvstream/av/video/VideoDepacketizer.java | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/moonlight-common/src/com/limelight/nvstream/av/video/VideoDepacketizer.java b/moonlight-common/src/com/limelight/nvstream/av/video/VideoDepacketizer.java index 5fc0c432..9b06d743 100644 --- a/moonlight-common/src/com/limelight/nvstream/av/video/VideoDepacketizer.java +++ b/moonlight-common/src/com/limelight/nvstream/av/video/VideoDepacketizer.java @@ -129,9 +129,11 @@ public class VideoDepacketizer { } } - private void addInputDataSlow(VideoPacket packet, ByteBufferDescriptor location) + private void addInputDataSlow(VideoPacket packet, ByteBufferDescriptor location, + boolean atFrameStart, boolean hasIntraNalPadding) { - boolean isDecodingH264 = false; + // If we're at frame start, we aren't yet decoding. + boolean isDecodingH264 = !atFrameStart; while (location.length != 0) { @@ -156,6 +158,7 @@ public class VideoDepacketizer { reassembleAvcFrame(packet.getFrameIndex()); // Setup state for the new NAL + frameStartTime = System.currentTimeMillis(); avcFrameDataChain = new LinkedList(); avcFrameDataLength = 0; packetSet = new HashSet(); @@ -198,10 +201,17 @@ public class VideoDepacketizer { { // Only stop if we're decoding something or this // isn't padding - if (isDecodingH264 || !NAL.isPadding(cachedSpecialDesc)) + boolean isPadding = NAL.isPadding(cachedSpecialDesc); + if (isDecodingH264 || !isPadding) { break; } + else if (!hasIntraNalPadding && isPadding) + { + // There's nothing more after this + location.length = 0; + break; + } } } @@ -212,6 +222,15 @@ public class VideoDepacketizer { if (isDecodingH264 && avcFrameDataChain != null) { + // HACK: It's possible that the last location in the packet could be zero-padded + // but not with enough zeros to be an invalid AVC sequence. In this case, we're going to + // just guess that 2 zeros in a row at the end are probably padding. + if (!hasIntraNalPadding && location.length == 0 && + location.data[location.offset-2] == 0 && + location.data[location.offset-1] == 0) { + location.offset -= 2; + } + ByteBufferDescriptor data = new ByteBufferDescriptor(location.data, start, location.offset-start); if (packetSet.add(packet)) { @@ -355,13 +374,18 @@ public class VideoDepacketizer { } lastPacketInStream = streamPacketIndex; - if (firstPacket + if ((flags & VideoPacket.FLAG_EOF) != 0) + { + // The last video packet can also have zero padding which we must strip using the slow path. + addInputDataSlow(packet, cachedReassemblyDesc, (flags & VideoPacket.FLAG_SOF) != 0, false); + } + else if (firstPacket && NAL.getSpecialSequenceDescriptor(cachedReassemblyDesc, cachedSpecialDesc) && NAL.isAvcFrameStart(cachedSpecialDesc) && cachedSpecialDesc.data[cachedSpecialDesc.offset+cachedSpecialDesc.length] == 0x67) { - // SPS and PPS prefix is padded between NALs, so we must decode it with the slow path - addInputDataSlow(packet, cachedReassemblyDesc); + // SPS and PPS prefix is padded between NALs, so we must decode it with the slow path. + addInputDataSlow(packet, cachedReassemblyDesc, true, true); } else {