mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-20 11:33:06 +00:00
Fix sequencing errors that lead to drops in audio or video for potentially long periods under the right conditions
This commit is contained in:
parent
33ffbe151f
commit
cc92f3829e
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user