丢包重传(NACK)是抵抗网络错误的重要手段。NACK在接收端检测到数据丢包后,发送NACK报文到发送端;发送端根据NACK报文中的序列号,在发送缓冲区找到对应的数据包,重新发送到接收端。NACK需要发送端,发送缓冲区的支持。
发送端发送rtp,到达接收端时,发现丢包,接收端发送nack请求,发送端会从历史队列中取出数据重发。
在rfc4585协议中定义可重传未到达数据的类型有二种:
1)RTPFB:rtp报文丢失重传(nack)。
2)PSFB:指定净荷重传,指定净荷重传里面又分如下三种(关键帧请求):
1、PLI (Picture Loss Indication) 视频帧丢失重传。
2、SLI (Slice Loss Indication) slice丢失重转。
3、RPSI (Reference Picture Selection Indication)参考帧丢失重传。
在创建视频连接的SDP协议里面,会协商以上述哪种类型进行NACK重转。以webrtc为例,会协商两种NACK,一个rtp报文丢包重传的nack(nack后面不带参数,默认RTPFB)、PLI 视频帧丢失重传的nack。
rtcp包格式
nack rtcp报文格式如上图所示,pt=205。Packet identifier(PID) 为丢包起始参考值,Bitmap of Lost Packets(BLP)为16位的bitmap,对应为1的为表示丢包数据,具体如下抓包分析:
Packet identifier(PID)为176。Bitmap of Lost Packets(BLP):0x6ae1。解析的时候需要按照小模式解析,0x6ae1对应二进制:110101011100001倒过来看1000 0111 0101 0110。按照1bit是丢包,0bit是没有丢包解析,丢失报文序列号分别是:176 177 182 183 184 186 188 190 191与wireshark解析一致,当然pid和blp可以有多个。
以视频为例
H264EncoderImpl::Encode VideoStreamEncoder::OnEncodedImage VideoSendStreamImpl::OnEncodedImage RtpVideoSender::OnEncodedImage RTPSenderVideo::SendEncodedImage RTPSenderVideo::SendVideo RTPSenderVideo::LogAndSendToNetwork RTPSender::EnqueuePackets pacer // RtpSenderEgress::SendPacket //放入队列 RtpPacketHistory::PutRtpPacket
modules/rtp_rtcp/source/rtp_rtcp_impl2.h
struct RtpSenderContext { explicit RtpSenderContext(const RtpRtcpInterface::Configuration& config); // Storage of packets, for retransmissions and padding, if applicable. RtpPacketHistory packet_history; SequenceChecker sequencing_checker; // Handles sequence number assignment and padding timestamp generation. PacketSequencer sequencer RTC_GUARDED_BY(sequencing_checker); // Handles final time timestamping/stats/etc and handover to Transport. RtpSenderEgress packet_sender; // If no paced sender configured, this class will be used to pass packets // from `packet_generator_` to `packet_sender_`. RtpSenderEgress::NonPacedPacketSender non_paced_sender; // Handles creation of RTP packets to be sent. RTPSender packet_generator; };