博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Qos之丢包重传NACK
阅读量:4171 次
发布时间:2019-05-26

本文共 3598 字,大约阅读时间需要 11 分钟。

 Qos.NACK

一、前言

        RTP/RTCP协议是流媒体通信最基本协议。RTP协议定义流媒体数据在互联网上传输的数据包格式,而RTCP协议则负责可靠传输、流量控制和拥塞控制等服务质量保证。在很多项目中,如WebRTC中,RTP/RTCP模块作为传输模块的一部分,负责对发送端采集到的媒体数据进行进行封包,然后交给上层网络模块发送;在接收端RTP/RTCP模块收到上层模块的数据包后,进行解包操作,最后把负载发送到解码模块。RTP协议是Internet上针对流媒体传输的基础协议,该协议详细说明在互联网上传输音视频的标准数据包格式。

       RTP协议本身只保证实时数据的传输,RTCP协议则负责流媒体的传输质量保证,提供流量控制和拥塞控制等服务。在RTP会话期间,各参与者周期性彼此发送RTCP报文。报文中包含各参与者数据发送和接收等统计信息,参与者可以据此动态控制流媒体传输质量。RFC3550 [1]定义RTP/RTCP协议的基本内容,包括报文格式、传输规则等。    

二、NACKNon-Acknowledge

        说NACK前,先说说ACKACK实际上就是到达通知技术。大家都知道TCP是可靠的连接,他之所以可靠,那是因为接收方在收到数据后会给发送方返回一个已收到数据的消息(ACK),告诉发送方我已经收到了,确保消息的可靠。

        NACK也是一种通知技术,只是触发通知的条件刚好的ACK相反,在未收到消息时,通知发送方我未收到消息,即通知未达。那么问题来了,接受者怎么知道自己未收到消息?音视频数据包都是按时间顺序发送的,一般都带序号(升序排列的时间戳)。例如发送方按顺序发送了时间戳为60,120,180,240320共五个包,接收者已经收到了60包,本来预期下一个接收的包的序号应该是序号120的包,但序号是120的包一直没收到,后面的包却收到了。那么接收者就可以判断,120这个包丢了,这时候接收方需要向发送方发出NACK消息(消息中带有丢包的序号,这里是120),让发送方重新发送丢失的包。

       在WebRTC中,前向纠错(FEC)和丢包重传(NACK)是抵抗网络错误的重要手段。FEC在发送端将数据包添加冗余纠错码,纠错码连同数据包一起发送到接收端;接收端根据纠错码对数据进行检查和纠正。RFC5109[1]定义FEC数据包的格式。NACK则在接收端检测到数据丢包后,发送NACK报文到发送端;发送端根据NACK报文中的序列号,在发送缓冲区找到对应的数据包,重新发送到接收端。NACK需要发送端发送缓冲区的支持,RFC5104[2]定义NACK数据包的格式。

三、NACK协议

NACK报文是类型为205的RTCP 扩展反馈报文,在RFC4585中定义[4]。

 /*
 *| 0                      1                       2                       3                   |           
 *| 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 
0 1 2 3 4 5 6 7          
 *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *|V=2|P|    RC   |   PT=205      |             length                          |
 *
 *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *|                     SSRC of packet sender                                     |
 *+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+==+=+
 *|                     SSRC of media source                                      | 
 *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *|            PID                               |                BLP                       |
 *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *
 */

       其中PT = 205,FMT = 1,Packet identifier(PID)即为丢失RTP数据包的序列号,Bitmao of Lost Packets(BLP)指示从PID开始接下来16个RTP数据包的丢失情况。一个NACK报文可以携带多个RTP序列号,NACK接收端对这些序列号逐个处理。NACK报文构造完成以后,发送到网络层。NACK报文是RTCP报文的一种,因此其发送、接收和分析遵循RTCP报文处理的一般流程。

注意version, padding, blockcount, packettype, length , ssrc为公共头部分,即所有消息都具有,此头信息,而ssrcsource, pid, blp为NACK消息特有部分。

  class NackStructor {                                                           

    public:

      uint32_tversion :2;      //协议版本号(2bit)

      uint32_t padding :1;                                                                   

      uint32_t fmt :5;          //(5bit)在不同消息中叫法不同,也叫blockcount或RC,此处指格式

                                       //format,在NACK消息中此值为1,之所以同时具有fmt和packettype

                                      //是因为某些消息存在多级类型,比如当前的NACK消息属于Feedback

                                      //类型。因此fmt=1(Feedback).

      uint32_t packettype :8;  //包类型(8bit),NACK消息类型值为205,Feedback子类型                                          

      uint32_t length :16;      //(16bit)消息长度                                            

      uint32_t ssrc;            //构造发送当前消息包的端的SSRC,若本端是此NACK包的发送者,此

                                       //SSRC值就是本端的SSRC值(源标识符)

      uint32_t ssrcsource;      //NACK消息部分,也是SSRC值,在此可称为媒体源标识符,用来指明

                                      //此消息要反鐀谁的情况。比如我是接收端,我知道发送端的音频流

                                     //(SSRC:1234)给我发来的数据包有丢包,我要反鐀对方音频流的

                                       //情况,那这个地方就应该填写1234(对方音频流SSRC)。

      uint32_t pid:16;          //packet id(sequence number)详见下面PID-BLP图                                          

      uint32_t blp:16;         

 };

 //在一个消息的一个公用头后面的NACK块部分可以有多个,每个NACK块可以反鐀1个流(SSRC)的情况。当然

 1个NACK块中的blp部分也可以有多个。

四、WebRTC中实现NACK

(1)接收端的NACK报文构造和发送工作在ModuleProcessThread线程中周期性完成。

                     

                    ModuleProcessThread线程周期性调用VideoReceiver::process函数,该函数通过VCMReceiver调用VCMJitterBuffer::GetNackList,从missing_seq_nums集合中得到过去一段时间内丢失RTP数据包的序列号。然后调用RtpStreamReceiver::ResendPackets函数。调用流程最终会到达RTCPSender::SendRTCP,发送类型为NACK的RTCP报文。

(2)接收端在接收和解析NACK报文后,通过回调机制处理各种类型的RTCP报文,对于NACK报文,会调用RTPSender重新发送RTP数据包,如图所示:

 

        RTCPReceiver在解析RTCP之后,得到RTCP报文的描述结构,然后通过回调进行报文语义处理。NACK报文会被发送到RTPSender进行处理。RTPSender根据NACK报文中包含的序列号,到RTPPacketHistory缓存中查找对应的RTP数据包。如果找到,则把数据包发送到网络。至此,一个完整的NACK报文回路完成,丢失的RTP数据包会重新发送到接收端。

     

参考文献

[1] RFC5109 - RTP Payload Format for Generic Forward Error Correction.
[2] RFC5104 - RFC 5104 - Codec Control Messages in the RTP Audio-Visual Profile with Feedback (AVPF)
[3] WebRTC中RTP/RTCP协议实现分析 - http://www.jianshu.com/p/c84be6f3ddf3
[4] RFC4585 - Extended RTP Profile for Real-time Transport Control Protocol (RTCP)-Based Feedback (RTP/AVPF)         

 

转载地址:http://mdqxi.baihongyu.com/

你可能感兴趣的文章
poj 1287 Networking (最小生成树Kruskal算法)
查看>>
w3c 学习html DOM
查看>>
Socket连接、TCP、UDP、HTTP连接详解
查看>>
linux权限设置
查看>>
python 10 days
查看>>
解决tomcat启东时一闪而过的问题
查看>>
C# 参考之上下文关键字get、set、value、partial、where和yield
查看>>
c网购物车流程图
查看>>
油豆腐
查看>>
MySql排序,去重,表复制,数据导入导出
查看>>
[react native] Error loading page
查看>>
Win10更新补丁失败后出现无法更新正在撤销 解决办法
查看>>
Kindle一周使用感受
查看>>
遍历 JSON JavaScript 对象树中的所有节点
查看>>
5.常见的数据处理技巧——《数据挖掘与数据化运营实战》
查看>>
缓动动画封装
查看>>
HDU 1568
查看>>
内网和外网的设置
查看>>
oracle 存储过程使用动态sql
查看>>
Delphi 如何调出字体对话框
查看>>