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() \
free(packets[i]); \
ret = -1; \
Limelog("FEC recovery returned corrupt packet %d" \
" (frame %d)", rtpPacket->sequenceNumber, \
queue->currentFrameNumber); \
free(packets[i]); \
continue
// 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");
}
// 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;
}

View File

@ -471,9 +471,23 @@ void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length, unsigned long l
streamPacketIndex = videoPacket->streamPacketIndex;
// The packets and frames must be in sequence from the FEC queue
LC_ASSERT(!isBefore24(streamPacketIndex, U24(lastPacketInStream + 1)));
LC_ASSERT(!isBefore32(frameIndex, nextFrameNumber));
// Drop packets from a previously corrupt frame
if (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
connectionSawFrame(frameIndex);
@ -502,10 +516,6 @@ void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length, unsigned long l
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;
// If this is the first packet, skip the frame header (if one exists)