Fix spurious exit of fast recovery mode when the stream starts

This commit is contained in:
Cameron Gutman 2021-06-12 18:33:20 -05:00
parent 9999156f26
commit b2d4b2c61f
2 changed files with 12 additions and 7 deletions

View File

@ -17,7 +17,10 @@
void RtpaInitializeQueue(PRTP_AUDIO_QUEUE queue) { void RtpaInitializeQueue(PRTP_AUDIO_QUEUE queue) {
memset(queue, 0, sizeof(*queue)); memset(queue, 0, sizeof(*queue));
queue->nextRtpSequenceNumber = UINT16_MAX;
// We will start in the synchronizing state, where we wait for the first
// full FEC block before reporting losses, out of order packets, etc.
queue->synchronizing = true;
reed_solomon_init(); reed_solomon_init();
@ -39,10 +42,8 @@ static void validateFecBlockState(PRTP_AUDIO_QUEUE queue) {
#ifdef LC_DEBUG #ifdef LC_DEBUG
PRTPA_FEC_BLOCK lastBlock = queue->blockHead; PRTPA_FEC_BLOCK lastBlock = queue->blockHead;
// The next sequence number must not be less than the oldest BSN unless we're in the // The next sequence number must not be less than the oldest BSN unless we're still synchronizing with the source
// starting state (prior to us setting nextRtpSequenceNumber and oldestRtpBaseSequenceNumber). LC_ASSERT(!isBefore16(queue->nextRtpSequenceNumber, queue->oldestRtpBaseSequenceNumber) || queue->synchronizing);
LC_ASSERT(!isBefore16(queue->nextRtpSequenceNumber, queue->oldestRtpBaseSequenceNumber) ||
(queue->nextRtpSequenceNumber == UINT16_MAX && queue->oldestRtpBaseSequenceNumber == 0));
if (lastBlock == NULL) { if (lastBlock == NULL) {
return; return;
@ -132,6 +133,9 @@ static void freeFecBlockHead(PRTP_AUDIO_QUEUE queue) {
queue->oldestRtpBaseSequenceNumber = blockHead->fecHeader.baseSequenceNumber + RTPA_DATA_SHARDS; queue->oldestRtpBaseSequenceNumber = blockHead->fecHeader.baseSequenceNumber + RTPA_DATA_SHARDS;
// Once we complete an FEC block (successfully or not), we're synchronized with the source
queue->synchronizing = false;
validateFecBlockState(queue); validateFecBlockState(queue);
if (queue->freeBlockCount >= RTPA_CACHED_FEC_BLOCK_LIMIT) { if (queue->freeBlockCount >= RTPA_CACHED_FEC_BLOCK_LIMIT) {
@ -186,7 +190,7 @@ static PRTPA_FEC_BLOCK getFecBlockForRtpPacket(PRTP_AUDIO_QUEUE queue, PRTP_PACK
// Remember if we've received out-of-sequence packets lately. We can use // Remember if we've received out-of-sequence packets lately. We can use
// this knowledge to more quickly give up on FEC blocks. // this knowledge to more quickly give up on FEC blocks.
if (isBefore16(packet->sequenceNumber, queue->oldestRtpBaseSequenceNumber)) { if (!queue->synchronizing && isBefore16(packet->sequenceNumber, queue->oldestRtpBaseSequenceNumber)) {
queue->lastOosSequenceNumber = packet->sequenceNumber; queue->lastOosSequenceNumber = packet->sequenceNumber;
if (!queue->receivedOosData) { if (!queue->receivedOosData) {
Limelog("Leaving fast audio recovery mode after OOS audio data (%u < %u)\n", Limelog("Leaving fast audio recovery mode after OOS audio data (%u < %u)\n",
@ -244,7 +248,7 @@ static PRTPA_FEC_BLOCK getFecBlockForRtpPacket(PRTP_AUDIO_QUEUE queue, PRTP_PACK
// when the connection begins. Start on the next FEC block boundary, so we can // when the connection begins. Start on the next FEC block boundary, so we can
// be sure we aren't starting in the middle (which will lead to a spurious audio // be sure we aren't starting in the middle (which will lead to a spurious audio
// data block recovery warning on connection start if we miss more than 2 packets). // data block recovery warning on connection start if we miss more than 2 packets).
if (queue->nextRtpSequenceNumber == UINT16_MAX && queue->oldestRtpBaseSequenceNumber == 0) { if (queue->synchronizing && queue->oldestRtpBaseSequenceNumber == 0) {
queue->nextRtpSequenceNumber = queue->oldestRtpBaseSequenceNumber = fecBlockBaseSeqNum + RTPA_DATA_SHARDS; queue->nextRtpSequenceNumber = queue->oldestRtpBaseSequenceNumber = fecBlockBaseSeqNum + RTPA_DATA_SHARDS;
return NULL; return NULL;
} }

View File

@ -61,6 +61,7 @@ typedef struct _RTP_AUDIO_QUEUE {
uint16_t lastOosSequenceNumber; uint16_t lastOosSequenceNumber;
bool receivedOosData; bool receivedOosData;
bool synchronizing;
} RTP_AUDIO_QUEUE, *PRTP_AUDIO_QUEUE; } RTP_AUDIO_QUEUE, *PRTP_AUDIO_QUEUE;
#define RTPQ_RET_PACKET_CONSUMED 0x1 #define RTPQ_RET_PACKET_CONSUMED 0x1