I have a quick question regarding the NackGenerator logic: NackGenerator::ReceivePacket
if (isRecovered)
{
this->recoveredList.insert(seq);
// Remove old ones so we don't accumulate recovered packets.
auto it = this->recoveredList.lower_bound(seq - MaxPacketAge);
if (it != this->recoveredList.begin())
{
this->recoveredList.erase(this->recoveredList.begin(), it);
}
// Do not let a packet pass if it's newer than last seen seq and came via
// RTX.
return false;
}
My understanding is that mediasoup does not implement FEC decoding and typically disables it during SDP negotiation. In a pure NACK/RTX environment, it seems logically impossible for a “recovered” packet (one with [isRecovered = true]) to have a sequence number greater than lastSeq.
A “recovered” packet with [seq > lastSeq] seems plausible in WebRTC if it’s reconstructed by FEC. But since mediasoup doesn’t do this, is the if (isRecovered) block within the [seq > lastSeq] logic path in [NackGenerator::ReceivePacket] actually reachable?
From this perspective, is the recoveredList truly necessary, or is it primarily a defensive measure for scenarios (like FEC) that are not currently implemented in mediasoup’s core?
I may be missing something, so any clarification would be greatly appreciated.
This might be an obvious question to everyone, but it has genuinely puzzled me for quite some time. It’s possible that my thinking is off or that I’ve misunderstood something. To further clarify my question, I’d like to share my understanding, which may not be entirely accurate, and I’d greatly appreciate any corrections or insights from the community.
In WebRTC’s NACK implementation, another factor for the recovery queue is the need to handle out-of-order packet sequences. WebRTC uses a histogram to calculate the out-of-order status of packet sequences and determines the sequence number threshold for triggering NACK retransmissions based on this. To calculate the out-of-order situation more accurately, recovered packets must not interfere with the original packet sequence, which is why they need to be uniformly placed in the recovery queue.
Yes, it’s optional — but it’s there for efficiency and NACK deduplication. If you’re building something minimal or testing, it’s safe to skip.
recoveredList is just an optimization step — helps avoid unnecessary NACKs and keeps retransmissions efficient. Not essential for basic functionality, but improves stream delivery under packet loss.
Which is the exact block in NackGenerator.cpp that is not reachable? Note that isRecovered is set to true if the packet is a RTX. In theory the decoded seq number in that packet (the seq of the retransmitted packet) should not be newer than last seen seq number, but nothing prevents the client from sending a RTX packet with an encoded seq higher than the last seq sent over the normal RTP stream.