moonlight-common-c/src/RtpVideoQueue.h
Cameron Gutman 1be56269a3 Fix handling of duplicate packets when OOS data was also received
It's possible for a sequence of packets seqnums like 2, 0, 1, 2 to end up hitting the fast path
again after filling in gap of OOS packets. The fast path assumes duplicate packets are caught
by the next contiguous sequence number check, but this is only true if that value is kept updated.

Since the slow path doesn't update the next contiguous sequence number, it's no longer safe to
use the fast path for the remaining packets in the frame because duplicate packets would be
mishandled.

Queuing duplicate packets violates all sorts of queue assumptions and can cause us to return
corrupt data to the decoder or attempt an FEC recovery without enough shards.
2023-09-23 12:08:16 -04:00

57 lines
1.6 KiB
C

#pragma once
#include "Video.h"
typedef struct _RTPV_QUEUE_ENTRY {
struct _RTPV_QUEUE_ENTRY* next;
struct _RTPV_QUEUE_ENTRY* prev;
PRTP_PACKET packet;
uint64_t receiveTimeMs;
uint32_t presentationTimeMs;
int length;
bool isParity;
} RTPV_QUEUE_ENTRY, *PRTPV_QUEUE_ENTRY;
typedef struct _RTPV_QUEUE_LIST {
PRTPV_QUEUE_ENTRY head;
PRTPV_QUEUE_ENTRY tail;
uint32_t count;
} RTPV_QUEUE_LIST, *PRTPV_QUEUE_LIST;
typedef struct _RTP_VIDEO_QUEUE {
RTPV_QUEUE_LIST pendingFecBlockList;
RTPV_QUEUE_LIST completedFecBlockList;
uint64_t bufferFirstRecvTimeMs;
uint32_t bufferLowestSequenceNumber;
uint32_t bufferHighestSequenceNumber;
uint32_t bufferFirstParitySequenceNumber;
uint32_t bufferDataPackets;
uint32_t bufferParityPackets;
uint32_t receivedDataPackets;
uint32_t receivedParityPackets;
uint32_t receivedHighestSequenceNumber;
uint32_t fecPercentage;
uint32_t nextContiguousSequenceNumber;
uint32_t missingPackets; // # of holes behind receivedHighestSequenceNumber
bool useFastQueuePath;
bool reportedLostFrame;
uint32_t currentFrameNumber;
bool multiFecCapable;
uint8_t multiFecCurrentBlockNumber;
uint8_t multiFecLastBlockNumber;
uint32_t lastOosFramePresentationTimestamp;
bool receivedOosData;
} RTP_VIDEO_QUEUE, *PRTP_VIDEO_QUEUE;
#define RTPF_RET_QUEUED 0
#define RTPF_RET_REJECTED 1
void RtpvInitializeQueue(PRTP_VIDEO_QUEUE queue);
void RtpvCleanupQueue(PRTP_VIDEO_QUEUE queue);
int RtpvAddPacket(PRTP_VIDEO_QUEUE queue, PRTP_PACKET packet, int length, PRTPV_QUEUE_ENTRY packetEntry);
void RtpvSubmitQueuedPackets(PRTP_VIDEO_QUEUE queue);