一、概述
二、函数走读
发送端实现NACK的三个重点流程:
1、发送RTP报文,实时存储报文到packet_history_队列
ProcessThreadImpl::Process
->PacedSender::Process
->PacingController::ProcessPackets
->PacketRouter::SendPacket
->ModuleRtpRtcpImpl2::TrySendPacket
->RtpSenderEgress::SendPacket
每次pacer发送报文的时候,都会把媒体报文储存在packet_history_队列。
RtpPacketHistory::PutRtpPacket以SequenceNumber为索引,把rtp保存在packet_history_队列
SetStorePacketsStatus配置队列长度。
视频在CreateRtpStreamSenders->SetStorePacketsStatus配置。
音频在RegisterSenderCongestionControlObjects->SetStorePacketsStatus配置。
2、处理接收到的RTCP NACK报文
函数调用关系如下:
RTCPReceiver::HandleNack:压栈packet_information->nack_sequence_numbers丢包队列。
ModuleRtpRtcpImpl::OnReceivedNack
将RTT延时时间及nack_sequence_numbers队列更新到RTPSender::OnReceivedNack
3、重发NACK反馈的RTP报文
RTPSender::OnReceivedNack
重发报文这里有三点需要注意:
1)GetPacketAndMarkAsPending会判断上次重传报文时间和当前时间差是否大于RTT,若小于则不重传。
RtpPacketHistory::VerifyRtt
2)NACK重新发送媒体数据有两种方式:单独RTX通道发送、与媒体数据混在一起发送
两种形式对单纯的NACK抗性影响不太大,但是与媒体数据混在一起发送模式,接收端无法区分是NACK重传报文,还是正常媒体数据,会导致接收端反馈的丢包率低于实际值,影响gcc探测码率,及发送端FEC冗余度配置。所以建议还是以RTX通道单独发送。
RTX通道单独发送重传报文,需要配置参数有如下三个:
3)RTPSender::ReSendPacket在将重传数据加入pacer队列,会设置报文优先级,为了保证实时性,NACK重传报文需要按照高优先级重传。
优先级配置在set_packet_type,发送报文时,会根据kRetransmission获取发送优先级。
PacingController::EnqueuePacket
GetPriorityForType