mirror of
https://github.com/moonlight-stream/moonlight-common-c.git
synced 2026-06-22 00:31:09 +00:00
Suppress speculative RFI for 5 minutes after OOS data is detected
This commit is contained in:
+36
-18
@@ -9,6 +9,13 @@
|
|||||||
#define FEC_VERBOSE
|
#define FEC_VERBOSE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Don't try speculative RFI for 5 minutes after seeing
|
||||||
|
// an out of order packet or incorrect prediction
|
||||||
|
#define SPECULATIVE_RFI_COOLDOWN_PERIOD_MS 300000
|
||||||
|
|
||||||
|
// RTP packets use a 90 KHz presentation timestamp clock
|
||||||
|
#define PTS_DIVISOR 90
|
||||||
|
|
||||||
void RtpvInitializeQueue(PRTP_VIDEO_QUEUE queue) {
|
void RtpvInitializeQueue(PRTP_VIDEO_QUEUE queue) {
|
||||||
reed_solomon_init();
|
reed_solomon_init();
|
||||||
memset(queue, 0, sizeof(*queue));
|
memset(queue, 0, sizeof(*queue));
|
||||||
@@ -85,6 +92,7 @@ static void removeEntryFromList(PRTPV_QUEUE_LIST list, PRTPV_QUEUE_ENTRY entry)
|
|||||||
// newEntry is contained within the packet buffer so we free the whole entry by freeing entry->packet
|
// newEntry is contained within the packet buffer so we free the whole entry by freeing entry->packet
|
||||||
static bool queuePacket(PRTP_VIDEO_QUEUE queue, PRTPV_QUEUE_ENTRY newEntry, PRTP_PACKET packet, int length, bool isParity, bool isFecRecovery) {
|
static bool queuePacket(PRTP_VIDEO_QUEUE queue, PRTPV_QUEUE_ENTRY newEntry, PRTP_PACKET packet, int length, bool isParity, bool isFecRecovery) {
|
||||||
PRTPV_QUEUE_ENTRY entry;
|
PRTPV_QUEUE_ENTRY entry;
|
||||||
|
bool outOfSequence = false;
|
||||||
|
|
||||||
LC_ASSERT(!(isFecRecovery && isParity));
|
LC_ASSERT(!(isFecRecovery && isParity));
|
||||||
LC_ASSERT(!isBefore16(packet->sequenceNumber, queue->nextContiguousSequenceNumber));
|
LC_ASSERT(!isBefore16(packet->sequenceNumber, queue->nextContiguousSequenceNumber));
|
||||||
@@ -102,35 +110,39 @@ static bool queuePacket(PRTP_VIDEO_QUEUE queue, PRTPV_QUEUE_ENTRY newEntry, PRTP
|
|||||||
if (packet->sequenceNumber == entry->packet->sequenceNumber) {
|
if (packet->sequenceNumber == entry->packet->sequenceNumber) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!isFecRecovery && isBefore16(packet->sequenceNumber, entry->packet->sequenceNumber)) {
|
else if (isBefore16(packet->sequenceNumber, entry->packet->sequenceNumber)) {
|
||||||
// This packet was received after a higher sequence number packet, so note that we
|
outOfSequence = true;
|
||||||
// received an out of order packet to disable our speculative RFI recovery logic.
|
|
||||||
queue->lastOosSequenceNumber = packet->sequenceNumber;
|
|
||||||
if (!queue->receivedOosData) {
|
|
||||||
Limelog("Leaving speculative RFI mode after OOS video data (%u < %u)\n",
|
|
||||||
packet->sequenceNumber, entry->packet->sequenceNumber);
|
|
||||||
queue->receivedOosData = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entry = entry->next;
|
entry = entry->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is just a fancy way of determining if 32767 packets have passed since our last OOS data
|
|
||||||
if (queue->receivedOosData && isBefore16(queue->bufferHighestSequenceNumber, queue->lastOosSequenceNumber)) {
|
|
||||||
Limelog("Entering speculative RFI mode after sequenced video data\n");
|
|
||||||
queue->receivedOosData = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
newEntry->packet = packet;
|
newEntry->packet = packet;
|
||||||
newEntry->length = length;
|
newEntry->length = length;
|
||||||
newEntry->isParity = isParity;
|
newEntry->isParity = isParity;
|
||||||
newEntry->prev = NULL;
|
newEntry->prev = NULL;
|
||||||
newEntry->next = NULL;
|
newEntry->next = NULL;
|
||||||
|
newEntry->presentationTimeMs = packet->timestamp / PTS_DIVISOR;
|
||||||
|
|
||||||
// 90 KHz video clock
|
// FEC recovery packets are synthesized by us, so don't use them to determine OOS data
|
||||||
newEntry->presentationTimeMs = packet->timestamp / 90;
|
if (!isFecRecovery) {
|
||||||
|
if (outOfSequence) {
|
||||||
|
// This packet was received after a higher sequence number packet, so note that we
|
||||||
|
// received an out of order packet to disable our speculative RFI recovery logic.
|
||||||
|
queue->lastOosFramePresentationTimestamp = newEntry->presentationTimeMs;
|
||||||
|
if (!queue->receivedOosData) {
|
||||||
|
Limelog("Leaving speculative RFI mode after OOS video data at frame %u\n",
|
||||||
|
queue->currentFrameNumber);
|
||||||
|
queue->receivedOosData = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (queue->receivedOosData && newEntry->presentationTimeMs > queue->lastOosFramePresentationTimestamp + SPECULATIVE_RFI_COOLDOWN_PERIOD_MS) {
|
||||||
|
Limelog("Entering speculative RFI mode after sequenced video data at frame %u\n",
|
||||||
|
queue->currentFrameNumber);
|
||||||
|
queue->receivedOosData = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
insertEntryIntoList(&queue->pendingFecBlockList, newEntry);
|
insertEntryIntoList(&queue->pendingFecBlockList, newEntry);
|
||||||
|
|
||||||
@@ -183,8 +195,14 @@ static int reconstructFrame(PRTP_VIDEO_QUEUE queue) {
|
|||||||
|
|
||||||
// If we make it here and reported a lost frame, we lied to the host. This can happen if we happen to get
|
// If we make it here and reported a lost frame, we lied to the host. This can happen if we happen to get
|
||||||
// unlucky and this particular frame happens to be the one with OOS data, but it should almost never happen.
|
// unlucky and this particular frame happens to be the one with OOS data, but it should almost never happen.
|
||||||
LC_ASSERT(!queue->reportedLostFrame);
|
|
||||||
LC_ASSERT(queue->receivedParityPackets >= queue->missingDataPackets);
|
LC_ASSERT(queue->receivedParityPackets >= queue->missingDataPackets);
|
||||||
|
LC_ASSERT(!queue->reportedLostFrame);
|
||||||
|
if (queue->reportedLostFrame) {
|
||||||
|
// If it turns out that we lied to the host, stop further speculative RFI requests for a while.
|
||||||
|
queue->receivedOosData = true;
|
||||||
|
queue->lastOosFramePresentationTimestamp = queue->pendingFecBlockList.head->presentationTimeMs;
|
||||||
|
Limelog("Leaving speculative RFI mode due to incorrect loss prediction of frame %u\n", queue->currentFrameNumber);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef FEC_VALIDATION_MODE
|
#ifdef FEC_VALIDATION_MODE
|
||||||
// If FEC is disabled or unsupported for this frame, we must bail early here.
|
// If FEC is disabled or unsupported for this frame, we must bail early here.
|
||||||
|
|||||||
+1
-1
@@ -43,7 +43,7 @@ typedef struct _RTP_VIDEO_QUEUE {
|
|||||||
uint8_t multiFecCurrentBlockNumber;
|
uint8_t multiFecCurrentBlockNumber;
|
||||||
uint8_t multiFecLastBlockNumber;
|
uint8_t multiFecLastBlockNumber;
|
||||||
|
|
||||||
uint16_t lastOosSequenceNumber;
|
uint32_t lastOosFramePresentationTimestamp;
|
||||||
bool receivedOosData;
|
bool receivedOosData;
|
||||||
} RTP_VIDEO_QUEUE, *PRTP_VIDEO_QUEUE;
|
} RTP_VIDEO_QUEUE, *PRTP_VIDEO_QUEUE;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user