定义: NACK报文是类型为205的RTCP 扩展反馈报文
NACK作用: 丢包重传.接收方定时把所有未收到的包序号通过反馈报文通知到发送方进行重传。
(每个rtp包都有编号,没收到的seq就是丢失,还是应用层做序号?)
nack使用rtcp的rtpfb报文发送。rtpfb可以发送两种报文,nack和transport-cc.
发送时机:不是每个丢包都发送nack报文而是可以多个丢包用一个报文表示。记得最多16个丢包
FMT=1, PT=RTPFB
a=rtcp-fb:96 nack
PT=RTPFB
-
FMT=1 Generic NACK
-
FMT=15 接收端构造TransportCC报文 transport wide cc
NACK
FMT是1,WebRTC对应的代码是nack.cc。
NACK的FCI个数如下,其中PID(Packet ID)是第一个丢失的序号,BLP(bitmask of following lost packets)是继第一个序号之后的16个包的丢失情况,当丢失之后,此二进制位就会被mark为1。例如PID等于666,如果668和692也丢失了,那么BLP等于100010。当后续丢失的包序号大于第一个丢失的包序号16以上就需要重新使用一个新的FCI反馈包表示。NACK包可以存在多个FCI。
例如PID等于666,如果668和692也丢失了,那么BLP等于100010。当后续丢失的包序号大于第一个丢失的包序号16以上就需要重新使用一个新的FCI反馈包表示。NACK包可以存在多个FCI
FCI:变长 Feedback Control Information。
WebRTC中丢包重传NACK实现分析 - 简书
1、RTPFB
问题 5:接收端多久发送一次 nack 请求 ?
假设接收端发现数据包发生序列号跳跃后立即发送 NACK 请求,由于 UDP 数据包可能会乱序到达,因此这种方案会导致过多的无效重传请求。
更加合理的方案是:每间隔指定的时间(比如:WebRTC 使用的是 10ms)发送一次 NACK 请求,一次性带上这段时间所有的丢包序号。
WEBRTC浅析(五)视频Nack包的发送判断逻辑以及数据流_muwesky的专栏-CSDN博客
webrtc QOS方法一(NACK实现)_CrystalShaw的博客-CSDN博客_nack pli
webrtc QOS方法一.2(接收端NACK流程实现)_CrystalShaw的博客-CSDN博客,
Rtx原理:重发的包封装到RTX包里发送,RTX包与原RTP有不同的SSRC,不同的rtpseq,但是timestamp与丢失包的时间戳相同。
Rtx优势:rtp重传包在带宽估计时不计入运算,使用rtx比较方便,不使用rtx统计丢包率有时会出现负值
参考rfc4588,使用额外的 ssrc 传输,在sdp中标识
a=rtpmap:97rtx/90000
a=ssrc-group:FID2736695910239189782
notes:RTX可以发送重传包或者fec包。webrtc发送重传包. nack和rtx是一对
Nack 协议头
Nack: webrtc 10ms发送一次?
Nack重传分成两种类型的包,不仅仅是重传rtp 报文
PID(Packet identifier),即为丢失的 RTP 数据包的序列号
BLP(Bitmao of Lost Packets),通过掩码的方式指出了接下来 16 个数据包的丢失情况
Packet identifier(PID)即为丢失RTP数据包的序列号,Bitmap of Lost Packets(BLP)指示从PID开始接下来16个RTP数据包的丢失情况。一个NACK报文可以携带多个RTP序列号,NACK接收端对这些序列号逐个处理。如下示例:
Packet identifier(PID)为176。
Bitmap of Lost Packets(BLP):0x6ae1。解析的时候需要按照小模式解析,
0x6ae1对应二进制:110101011100001倒过来看1000 0111 0101 0110。
按照1bit是丢包,0bit是没有丢包解析,丢失报文序列号分别是:
188 190 191与wireshark解析一致。
case RTCP_RTPFB: {//RTPFB(Generic RTP Feedback)
/* RTPFB, Transport layer FB message (rfc4585) */
gint fmt = rtcp->rc;
janus_rtcp_fb *rtcpfb = (janus_rtcp_fb *)rtcp;
//~ JANUS_LOG(LOG_HUGE, " -- SSRC: %u\n", ntohl(rtcpfb->ssrc));
/*PT=RTPFB;FMT=1 Generic NACK;*/
if(fmt == 1) {//nack
JANUS_LOG2(LOG_HUGE, janus_session_id," #%d NACK -- RTPFB (205)\n", pno);
if(fixssrc && newssrcr) {
rtcpfb->media = htonl(newssrcr);
}
int nacks = ntohs(rtcp->length)-2; /* Skip SSRCs */
if(nacks > 0) {
JANUS_LOG2(LOG_DBG, janus_session_id, " Got %d nacks\n", nacks);
janus_rtcp_nack *nack = NULL;
uint16_t pid = 0;
uint16_t blp = 0;
int i=0, j=0;
char bitmask[20];
for(i=0; i< nacks; i++) {
nack = (janus_rtcp_nack *)rtcpfb->fci + i;
pid = ntohs(nack->pid);
blp = ntohs(nack->blp);
memset(bitmask, 0, 20);
//blp 根据bitrate判断丢包的number
for(j=0; j<16; j++) {//16个RTP数据包
bitmask[j] = (blp & ( 1 << j )) >> j ? '1' : '0';
}
bitmask[16] = '\n';
JANUS_LOG2(LOG_DBG, janus_session_id, "[%d] %"SCNu16" / %s\n", i, pid, bitmask);
}
}
}
网上还有个例子:668和672也丢失了,那么BLP等于100010
kDefaultSendNackDelayMs=20ms 20ms
PT=RTPFB
FMT=1 Generic NACK
FMT=15 接收端构造TransportCC报文 transport wide cc
谈谈网络通信中的 ACK、NACK 和 REX_Jhuster的专栏的技术博客_51CTO博客
webrtc QOS方法一(NACK实现)_CrystalShaw的博客-CSDN博客_nack pli
其中RTPFB(transport layer feedback messages,传输层反馈),可以表示两种类型RTX作用:接收nack之后,发送方发送重传包
实现:
nack逻辑:收到nack,查找queue中有没有,有则retransmit
没收到对方的数据包,missing queue--nack queuue--- timeout general nack发送
janus_rtcp_nacks;
janus_rtcp_get_nacks,