Additional fixes for corrupt FEC recovery handling

This commit is contained in:
Cameron Gutman 2018-09-05 12:04:39 -07:00
parent 9c1d7ffb70
commit 884b8d0a95
3 changed files with 22 additions and 8 deletions

View File

@ -72,11 +72,11 @@ static int queuePacket(PRTP_FEC_QUEUE queue, PRTPFEC_QUEUE_ENTRY newEntry, int h
} }
#define PACKET_RECOVERY_FAILURE() \ #define PACKET_RECOVERY_FAILURE() \
free(packets[i]); \
ret = -1; \ ret = -1; \
Limelog("FEC recovery returned corrupt packet %d" \ Limelog("FEC recovery returned corrupt packet %d" \
" (frame %d)", rtpPacket->sequenceNumber, \ " (frame %d)", rtpPacket->sequenceNumber, \
queue->currentFrameNumber); \ queue->currentFrameNumber); \
free(packets[i]); \
continue continue
// Returns 0 if the frame is completely constructed // Returns 0 if the frame is completely constructed

View File

@ -162,6 +162,10 @@ static int addGen5Options(PSDP_OPTION* head) {
err |= addAttributeString(head, "x-nv-vqos[0].fec.repairPercent", "5"); err |= addAttributeString(head, "x-nv-vqos[0].fec.repairPercent", "5");
} }
// Recovery mode can cause the FEC percentage to change mid-frame, which
// breaks many assumptions in RTP FEC queue.
err |= addAttributeString(head, "x-nv-general.enableRecoveryMode", "0");
return err; return err;
} }

View File

@ -471,9 +471,23 @@ void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length, unsigned long l
streamPacketIndex = videoPacket->streamPacketIndex; streamPacketIndex = videoPacket->streamPacketIndex;
// The packets and frames must be in sequence from the FEC queue // Drop packets from a previously corrupt frame
LC_ASSERT(!isBefore24(streamPacketIndex, U24(lastPacketInStream + 1))); if (isBefore32(frameIndex, nextFrameNumber)) {
LC_ASSERT(!isBefore32(frameIndex, nextFrameNumber)); return;
}
// The FEC queue can sometimes recover corrupt frames (see comments in RtpFecQueue).
// It almost always detects them before they get to us, but in case it doesn't
// the streamPacketIndex not matching correctly should find nearly all of the rest.
if (isBefore24(streamPacketIndex, U24(lastPacketInStream + 1)) ||
(!firstPacket && streamPacketIndex != U24(lastPacketInStream + 1))) {
Limelog("Depacketizer detected corrupt frame: %d", frameIndex);
decodingFrame = 0;
nextFrameNumber = frameIndex + 1;
waitingForNextSuccessfulFrame = 1;
dropFrameState();
return;
}
// Notify the listener of the latest frame we've seen from the PC // Notify the listener of the latest frame we've seen from the PC
connectionSawFrame(frameIndex); connectionSawFrame(frameIndex);
@ -502,10 +516,6 @@ void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length, unsigned long l
firstPacketReceiveTime = receiveTimeMs; firstPacketReceiveTime = receiveTimeMs;
} }
// This must be the first packet in a frame or be contiguous with the last
// packet received.
LC_ASSERT(firstPacket || streamPacketIndex == U24(lastPacketInStream + 1));
lastPacketInStream = streamPacketIndex; lastPacketInStream = streamPacketIndex;
// If this is the first packet, skip the frame header (if one exists) // If this is the first packet, skip the frame header (if one exists)