NACK在mediasoup中如何实现丢包重传?
在 mediasoup 中NACKNegative Acknowledgement否定确认对丢包恢复至关重要核心原因在于它是当前 mediasoup 实现中唯一有效的主动丢包重传机制。由于 mediasoup 尚未实现前向纠错FEC当网络发生丢包时接收端无法通过冗余数据自行恢复必须依赖 NACK 机制请求发送端重传丢失的数据包这是保障音视频流媒体传输质量的关键防线。其重要性具体体现在以下两个层面1. 架构层面的核心地位mediasoup 的 NACK 机制实现了与 WebRTC 标准的对接构成了其丢包恢复能力的基石。发送端RtpStreamSend使用RtpRetransmissionBuffer缓存已发送的 RTP 包接收端RtpStreamRecv通过NackGenerator检测丢包并生成 NACK 请求触发发送端从缓存中取出对应包进行重传通过 RTX 或原始 SSRC。整个处理流程清晰是保障数据可靠性的核心链路。2. 机制设计的必要性NACK 的触发与执行机制确保了恢复的及时性和有效性。发送端缓存管理发送端缓存受最大数量2500个包和最大延迟视频2000ms音频1000ms限制确保有足够的数据可供重传同时避免无限缓存。接收端丢包检测与请求NackGenerator通过比对 RTP 序列号来识别丢包并将丢失的包信息加入nackList。触发重传请求的条件包括序列号触发当收到序列号大于某个丢失包预设的sendAtSeq时会触发对该丢失包的首次重传请求。定时器触发如果一个丢失包的重传请求发出后超过一个 RTTRound-Trip Time时间仍未收到该包则会再次发起请求。请求本身也有延迟默认10ms和最大重试次数限制以避免无效的网络泛洪。以下代码片段展示了NackGenerator中获取一批待重传包序列号的核心逻辑体现了上述触发机制std::vectoruint16_t NackGenerator::GetNackBatch(NackFilter filter) { const uint64_t nowMs DepLibUV::GetTimeMs(); std::vectoruint16_t nackBatch; auto it this-nackList.begin(); while (it ! this-nackList.end()) { NackInfo nackInfo it-second; const uint16_t seq nackInfo.seq; // 条件1: 检查是否满足最小发送延迟如10ms if (this-sendNackDelayMs 0 nowMs - nackInfo.createdAtMs this-sendNackDelayMs) { it; continue; } // 条件2: 序列号触发首次发送 if (filter NackFilter::SEQ nackInfo.sentAtMs 0 (nackInfo.sendAtSeq this-lastSeq || SeqManageruint16_t::IsSeqHigherThan(this-lastSeq, nackInfo.sendAtSeq))) { nackBatch.emplace_back(seq); nackInfo.retries; nackInfo.sentAtMs nowMs; // 达到最大重试次数则移除 if (nackInfo.retries MaxNackRetries) { it this-nackList.erase(it); } else { it; } continue; } // 条件3: 定时器触发非首次发送距离上次请求超过一个RTT if (filter NackFilter::TIME (nackInfo.sentAtMs 0 || nowMs - nackInfo.sentAtMs (this-rtt 0u ? this-rtt : DefaultRtt))) { nackBatch.emplace_back(seq); nackInfo.retries; nackInfo.sentAtMs nowMs; if (nackInfo.retries MaxNackRetries) { it this-nackList.erase(it); } else { it; } continue; } it; } return nackBatch; }3. 与 WebRTC 实现的对比与 WebRTC 的实现相比mediasoup 的 NACK 机制进行了一定简化这更凸显了其在当前架构下的不可或缺性特性mediasoup 实现WebRTC 实现对 mediasoup 的影响触发序列号计算直接将丢失包序列号设为触发点 (sendAtSeq seq)。基于乱序直方图统计计算一个概率值如50%对应的偏移量作为触发点。策略更为激进倾向于立即请求重传在无FEC的情况下有助于更快开始恢复流程。恢复包列表作用recoveredList仅存储 RTX 重传包且逻辑上其必要性存疑。recovered_list_用于存储通过 FEC 或 RTX 恢复的包这些包会影响乱序统计。由于无FEC此列表功能弱化侧面说明丢包恢复几乎完全依赖 NACKRTX。发送端缓存清理基于最大数量(2500)和固定最大延迟视频2000ms/音频1000ms。基于数量、动态时长max(1000ms, 3*RTT)及更严格的“终极”限制。mediasoup 策略更简单直接在缺乏其他恢复手段时确保合理时间窗口内的包可被重传。综上所述NACK 是 mediasoup 应对网络丢包的核心且主要的恢复机制。其简洁有效的设计在缺乏 FEC 等辅助手段的情况下承担了保障实时音视频数据传输可靠性的全部重担因此对于 mediasoup 的丢包恢复能力至关重要。参考来源深入浅出mediasoup—NACK