WebRTC中丢包重传NACK实现分析https://www.jianshu.com/p/a7f6ec0c9273

2023-10-25 05:38

本文主要是介绍WebRTC中丢包重传NACK实现分析https://www.jianshu.com/p/a7f6ec0c9273,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

转自: https://www.jianshu.com/p/a7f6ec0c9273

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

本文在研究WebRTC源代码的基础上,以Video数据包的发送和接收为例,深入分析ANCK丢包重传机制的实现。主要内容包括:SDP协商NACK,接收端丢包判定,NACK报文构造、发送、接收和解析,RTP数据包重传。下面分别详细论述之。</br>

1 SDP协商NACK

</br>
NACK作为RTP层反馈参数,和Video Codec联系在一起。WebRTC在初始化阶段,创建PeerConnectionFactory对象,在该对象中创建MediaEngine,其中的VideoEngine为WebRtcVideoEngine2。该对象在构造时,会收集本端支持的所有Video Codec,NACK作为Codec的属性被一起收集。在接下来的SDP协商过程中,NACK属性被协商到Offer/Answer中,如图1所示。</br>

图1 SDP协商NACK及作用于Video JitterBuffer

PeerConnection在CreateOffer时,收集本端的会话控制信息、音视频Codec信息和网络信息等内容。视频Codec信息从WebRtcVideoEngine2中获取。最后本端Offer形成SDP报文,经过PeerConnection对象发送到网络。</br>

接收端在收到Offer之后,首先调用SetRemoteDescription,根据本地配置信息向下创建VideoReceiveStream对象,本地NACK配置信息会最终到达VCMJitterBuffer。接着PeerConnection调用CreateAnswer,生成Answer;根据Offer中的Codec信息和本端支持的Codec信息,最终选定双方都支持的Codec集合。最后用生成的Answer作为参数调用SetLocalDescription,根据Answer中的Video Codec信息向下重新创建VideoReceiveStream对象。NACK信息向下传递最终到达VCMJitterBuffer,在这里设置NACK相关参数。这些参数在接收RTP数据包过程中发挥作用,比如判断丢包、是否发送NACK报文等。Answer发回发送端时,发送端调用SetRemoteDescription执行同样的设置流程。</br>

2 接收端丢包判定

</br>
Video接收端丢包判定在Worker线程中进行。RTP数据包到达接收端后,经过RTP模块到达VCM模块的JitterBuffer对象,最终调用VCMJitterBuffer的InsertPacket函数对数据包进行缓存和重排。</br>

VCMJitterBuffer把丢失RTP数据包的序列号存储在集合missing_seq_nums中。对于本次从RTP模块到来的数据包,标记其序列号为seq1,而上次到达数据包的序列号为seq2。如果seq1 > seq2,则表示seq1顺序到达,标记(seqnum2, seqnum1)区间内的数据包为丢失状态,将其存储到missing_seq_nums集合中。注意这里的丢失状态是暂时的,如果下个数据包到达时有seq1 < seq2,则表示数据包乱序到达,则把missing_seq_nums中小于seq1的序列号都删除掉。</br>

在更新missing_seq_nums集合时,如果集合中存储的序列号超过预设的容量,则通过调用RecycleFramesUntilKeyFrame()不断丢包来减少集合中的序列号,直到集合中的序列号总数低于预设容量值。</br>

3 NACK报文发送和接收

</br>
接收端的NACK报文构造和发送工作在ModuleProcessThread线程中周期性完成。过程如图2所示。</br>

图2 NACK报文构造和发送

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

NACK报文是类型为205的RTCP 扩展反馈报文,在RFC4585中定义[4]。具体格式如图3所示:</br>

图3 NACK报文格式

其中PT = 205,FMT = 1,Packet identifier(PID)即为丢失RTP数据包的序列号,Bitmao of Lost Packets(BLP)指示从PID开始接下来16个RTP数据包的丢失情况。一个NACK报文可以携带多个RTP序列号,NACK接收端对这些序列号逐个处理。</br>

NACK报文构造完成以后,发送到网络层。NACK报文是RTCP报文的一种,因此其发送、接收和分析遵循RTCP报文处理的一般流程。这部分内容可参考文档[3]。</br>

4 RTP数据包重传

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

图4 发送端数据包重传

RTCPReceiver在解析RTCP之后,得到RTCP报文的描述结构,然后通过回调进行报文语义处理。NACK报文会被发送到RTPSender进行处理。RTPSender根据NACK报文中包含的序列号,到RTPPacketHistory缓存中查找对应的RTP数据包。如果找到,则把数据包发送到网络。</br>

至此,一个完整的NACK报文回路完成,丢失的RTP数据包会重新发送到接收端。</br>

5 总结

</br>
本文深入分析了WebRTC内部关于丢包重传(NACK)的实现细节,对NACK的SDP协商、丢包判定和重传进行深入研究,为继续学习掌握WebRTC的QoS机制奠定基础。</br>
< /br>

参考文献

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



作者:weizhenwei
链接:https://www.jianshu.com/p/a7f6ec0c9273
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

这篇关于WebRTC中丢包重传NACK实现分析https://www.jianshu.com/p/a7f6ec0c9273的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/280361

相关文章

基于C++的UDP网络通信系统设计与实现详解

《基于C++的UDP网络通信系统设计与实现详解》在网络编程领域,UDP作为一种无连接的传输层协议,以其高效、低延迟的特性在实时性要求高的应用场景中占据重要地位,下面我们就来看看如何从零开始构建一个完整... 目录前言一、UDP服务器UdpServer.hpp1.1 基本框架设计1.2 初始化函数Init详解

Java中Map的五种遍历方式实现与对比

《Java中Map的五种遍历方式实现与对比》其实Map遍历藏着多种玩法,有的优雅简洁,有的性能拉满,今天咱们盘一盘这些进阶偏基础的遍历方式,告别重复又臃肿的代码,感兴趣的小伙伴可以了解下... 目录一、先搞懂:Map遍历的核心目标二、几种遍历方式的对比1. 传统EntrySet遍历(最通用)2. Lambd

springboot+redis实现订单过期(超时取消)功能的方法详解

《springboot+redis实现订单过期(超时取消)功能的方法详解》在SpringBoot中使用Redis实现订单过期(超时取消)功能,有多种成熟方案,本文为大家整理了几个详细方法,文中的示例代... 目录一、Redis键过期回调方案(推荐)1. 配置Redis监听器2. 监听键过期事件3. Redi

SpringBoot全局异常拦截与自定义错误页面实现过程解读

《SpringBoot全局异常拦截与自定义错误页面实现过程解读》本文介绍了SpringBoot中全局异常拦截与自定义错误页面的实现方法,包括异常的分类、SpringBoot默认异常处理机制、全局异常拦... 目录一、引言二、Spring Boot异常处理基础2.1 异常的分类2.2 Spring Boot默

基于SpringBoot实现分布式锁的三种方法

《基于SpringBoot实现分布式锁的三种方法》这篇文章主要为大家详细介绍了基于SpringBoot实现分布式锁的三种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、基于Redis原生命令实现分布式锁1. 基础版Redis分布式锁2. 可重入锁实现二、使用Redisso

SpringBoo WebFlux+MongoDB实现非阻塞API过程

《SpringBooWebFlux+MongoDB实现非阻塞API过程》本文介绍了如何使用SpringBootWebFlux和MongoDB实现非阻塞API,通过响应式编程提高系统的吞吐量和响应性能... 目录一、引言二、响应式编程基础2.1 响应式编程概念2.2 响应式编程的优势2.3 响应式编程相关技术

C#实现将XML数据自动化地写入Excel文件

《C#实现将XML数据自动化地写入Excel文件》在现代企业级应用中,数据处理与报表生成是核心环节,本文将深入探讨如何利用C#和一款优秀的库,将XML数据自动化地写入Excel文件,有需要的小伙伴可以... 目录理解XML数据结构与Excel的对应关系引入高效工具:使用Spire.XLS for .NETC

Nginx更新SSL证书的实现步骤

《Nginx更新SSL证书的实现步骤》本文主要介绍了Nginx更新SSL证书的实现步骤,包括下载新证书、备份旧证书、配置新证书、验证配置及遇到问题时的解决方法,感兴趣的了解一下... 目录1 下载最新的SSL证书文件2 备份旧的SSL证书文件3 配置新证书4 验证配置5 遇到的http://www.cppc

Nginx之https证书配置实现

《Nginx之https证书配置实现》本文主要介绍了Nginx之https证书配置的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起... 目录背景介绍为什么不能部署在 IIS 或 NAT 设备上?具体实现证书获取nginx配置扩展结果验证

SpringBoot整合 Quartz实现定时推送实战指南

《SpringBoot整合Quartz实现定时推送实战指南》文章介绍了SpringBoot中使用Quartz动态定时任务和任务持久化实现多条不确定结束时间并提前N分钟推送的方案,本文结合实例代码给大... 目录前言一、Quartz 是什么?1、核心定位:解决什么问题?2、Quartz 核心组件二、使用步骤1