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

相关文章

慢sql提前分析预警和动态sql替换-Mybatis-SQL

《慢sql提前分析预警和动态sql替换-Mybatis-SQL》为防止慢SQL问题而开发的MyBatis组件,该组件能够在开发、测试阶段自动分析SQL语句,并在出现慢SQL问题时通过Ducc配置实现动... 目录背景解决思路开源方案调研设计方案详细设计使用方法1、引入依赖jar包2、配置组件XML3、核心配

Java NoClassDefFoundError运行时错误分析解决

《JavaNoClassDefFoundError运行时错误分析解决》在Java开发中,NoClassDefFoundError是一种常见的运行时错误,它通常表明Java虚拟机在尝试加载一个类时未能... 目录前言一、问题分析二、报错原因三、解决思路检查类路径配置检查依赖库检查类文件调试类加载器问题四、常见

使用Python实现IP地址和端口状态检测与监控

《使用Python实现IP地址和端口状态检测与监控》在网络运维和服务器管理中,IP地址和端口的可用性监控是保障业务连续性的基础需求,本文将带你用Python从零打造一个高可用IP监控系统,感兴趣的小伙... 目录概述:为什么需要IP监控系统使用步骤说明1. 环境准备2. 系统部署3. 核心功能配置系统效果展

Python实现微信自动锁定工具

《Python实现微信自动锁定工具》在数字化办公时代,微信已成为职场沟通的重要工具,但临时离开时忘记锁屏可能导致敏感信息泄露,下面我们就来看看如何使用Python打造一个微信自动锁定工具吧... 目录引言:当微信隐私遇到自动化守护效果展示核心功能全景图技术亮点深度解析1. 无操作检测引擎2. 微信路径智能获

Python中pywin32 常用窗口操作的实现

《Python中pywin32常用窗口操作的实现》本文主要介绍了Python中pywin32常用窗口操作的实现,pywin32主要的作用是供Python开发者快速调用WindowsAPI的一个... 目录获取窗口句柄获取最前端窗口句柄获取指定坐标处的窗口根据窗口的完整标题匹配获取句柄根据窗口的类别匹配获取句

在 Spring Boot 中实现异常处理最佳实践

《在SpringBoot中实现异常处理最佳实践》本文介绍如何在SpringBoot中实现异常处理,涵盖核心概念、实现方法、与先前查询的集成、性能分析、常见问题和最佳实践,感兴趣的朋友一起看看吧... 目录一、Spring Boot 异常处理的背景与核心概念1.1 为什么需要异常处理?1.2 Spring B

Python中的Walrus运算符分析示例详解

《Python中的Walrus运算符分析示例详解》Python中的Walrus运算符(:=)是Python3.8引入的一个新特性,允许在表达式中同时赋值和返回值,它的核心作用是减少重复计算,提升代码简... 目录1. 在循环中避免重复计算2. 在条件判断中同时赋值变量3. 在列表推导式或字典推导式中简化逻辑

Python位移操作和位运算的实现示例

《Python位移操作和位运算的实现示例》本文主要介绍了Python位移操作和位运算的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 位移操作1.1 左移操作 (<<)1.2 右移操作 (>>)注意事项:2. 位运算2.1

如何在 Spring Boot 中实现 FreeMarker 模板

《如何在SpringBoot中实现FreeMarker模板》FreeMarker是一种功能强大、轻量级的模板引擎,用于在Java应用中生成动态文本输出(如HTML、XML、邮件内容等),本文... 目录什么是 FreeMarker 模板?在 Spring Boot 中实现 FreeMarker 模板1. 环

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义