diff --git a/moonlight-common/src/com/limelight/nvstream/av/RtpReorderQueue.java b/moonlight-common/src/com/limelight/nvstream/av/RtpReorderQueue.java index aad5cc96..d7711931 100644 --- a/moonlight-common/src/com/limelight/nvstream/av/RtpReorderQueue.java +++ b/moonlight-common/src/com/limelight/nvstream/av/RtpReorderQueue.java @@ -45,7 +45,7 @@ public class RtpReorderQueue { if (nextRtpSequenceNumber != Short.MAX_VALUE) { // Don't queue packets we're already ahead of - if (seq < nextRtpSequenceNumber) { + if (SequenceHelper.isBeforeSigned(seq, nextRtpSequenceNumber, false)) { return false; } @@ -88,11 +88,15 @@ public class RtpReorderQueue { } private RtpQueueEntry getEntryByLowestSeq() { - short nextSeq = Short.MAX_VALUE; - RtpQueueEntry lowestSeqEntry = null; + if (queue.isEmpty()) { + return null; + } + + RtpQueueEntry lowestSeqEntry = queue.getFirst(); + short nextSeq = lowestSeqEntry.sequenceNumber; for (RtpQueueEntry entry : queue) { - if (entry.sequenceNumber < nextSeq) { + if (SequenceHelper.isBeforeSigned(entry.sequenceNumber, nextSeq, true)) { lowestSeqEntry = entry; nextSeq = entry.sequenceNumber; } @@ -140,7 +144,7 @@ public class RtpReorderQueue { public RtpQueueStatus addPacket(RtpPacketFields packet) { if (nextRtpSequenceNumber != Short.MAX_VALUE && - packet.getRtpSequenceNumber() < nextRtpSequenceNumber) { + SequenceHelper.isBeforeSigned(packet.getRtpSequenceNumber(), nextRtpSequenceNumber, false)) { // Reject packets behind our current sequence number return RtpQueueStatus.REJECTED; } diff --git a/moonlight-common/src/com/limelight/nvstream/av/SequenceHelper.java b/moonlight-common/src/com/limelight/nvstream/av/SequenceHelper.java new file mode 100644 index 00000000..10f38199 --- /dev/null +++ b/moonlight-common/src/com/limelight/nvstream/av/SequenceHelper.java @@ -0,0 +1,20 @@ +package com.limelight.nvstream.av; + +public class SequenceHelper { + public static boolean isBeforeSigned(int numA, int numB, boolean ambiguousCase) { + // This should be the common case for most callers + if (numA == numB) { + return false; + } + + // If numA and numB have the same signs, + // we can just do a regular comparison. + if ((numA < 0 && numB < 0) || (numA >= 0 && numB >= 0)) { + return numA < numB; + } + else { + // The sign switch is ambiguous + return ambiguousCase; + } + } +} diff --git a/moonlight-common/src/com/limelight/nvstream/av/audio/AudioDepacketizer.java b/moonlight-common/src/com/limelight/nvstream/av/audio/AudioDepacketizer.java index 0cb3c5bb..2bebf6b6 100644 --- a/moonlight-common/src/com/limelight/nvstream/av/audio/AudioDepacketizer.java +++ b/moonlight-common/src/com/limelight/nvstream/av/audio/AudioDepacketizer.java @@ -4,6 +4,7 @@ import com.limelight.LimeLog; import com.limelight.nvstream.av.ByteBufferDescriptor; import com.limelight.nvstream.av.PopulatedBufferList; import com.limelight.nvstream.av.RtpPacket; +import com.limelight.nvstream.av.SequenceHelper; public class AudioDepacketizer { @@ -88,7 +89,7 @@ public class AudioDepacketizer { // Only tell the decoder if we got packets ahead of what we expected // If the packet is behind the current sequence number, drop it - if (seq > (short)(lastSequenceNumber + 1)) { + if (!SequenceHelper.isBeforeSigned(seq, (short)(lastSequenceNumber + 1), false)) { decodeData(null, 0, 0); } else { 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 730b4fd9..80e12c61 100644 --- a/moonlight-common/src/com/limelight/nvstream/av/video/VideoDepacketizer.java +++ b/moonlight-common/src/com/limelight/nvstream/av/video/VideoDepacketizer.java @@ -7,6 +7,7 @@ import com.limelight.nvstream.av.ByteBufferDescriptor; import com.limelight.nvstream.av.DecodeUnit; import com.limelight.nvstream.av.ConnectionStatusListener; import com.limelight.nvstream.av.PopulatedBufferList; +import com.limelight.nvstream.av.SequenceHelper; public class VideoDepacketizer { @@ -232,12 +233,12 @@ public class VideoDepacketizer { // Drop duplicates or re-ordered packets int streamPacketIndex = packet.getStreamPacketIndex(); - if (streamPacketIndex < (int)(lastPacketInStream + 1)) { + if (SequenceHelper.isBeforeSigned((short)streamPacketIndex, (short)(lastPacketInStream + 1), false)) { return; } // Drop packets from a previously completed frame - if (frameIndex < nextFrameNumber) { + if (SequenceHelper.isBeforeSigned(frameIndex, nextFrameNumber, false)) { return; } @@ -279,7 +280,7 @@ public class VideoDepacketizer { // miss one in between else if (firstPacket) { // Make sure this is the next consecutive frame - if (nextFrameNumber < frameIndex) { + if (SequenceHelper.isBeforeSigned(nextFrameNumber, frameIndex, true)) { LimeLog.warning("Network dropped an entire frame"); nextFrameNumber = frameIndex; @@ -287,7 +288,7 @@ public class VideoDepacketizer { waitingForNextSuccessfulFrame = true; dropAvcFrameState(); } - else if (nextFrameNumber > frameIndex){ + else if (nextFrameNumber != frameIndex) { // Duplicate packet or FEC dup decodingFrame = false; return;