简述WebRTC中的丢包重传Nack的实现

article/2025/10/6 15:43:06

一 简述

接收端发现序列号不连续,发送RTCP FB Nack包,发送端从历史队列中查找该包,再发送RTP包,但WebRTC用的RTX重发该包,ssrc和原视频流不同,pt也不同

a=rtpmap:96 H264/90000
a=rtcp-fb:96 goog-remb
a=rtcp-fb:96 transport-cc
a=rtcp-fb:96 ccm fir
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=fmtp:96 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=96 //表示97是96重传
a=ssrc-group:FID 1753454336 165688474

这是WebRTC中的SDP,原视频流PT是96,重传RTX PT是97, ssrc-group是原视频流ssrc和RTX ssrc。

 

 sender ssrc是发送RTCP NACK包这端发送视频rtp包的ssrc,media ssrc是随机生成的。

if (receiver_only_ || main_ssrc_ != nack.media_ssrc())  // Not to us.

return;

RTCP FB Nack包如上图所示:pt=205,fmt=1,PID是丢包的起始序列号-2字节,BLP表示起始序列号后面16位丢包情况,1是丢包,0是没丢包。读blp的值要反一下。BLP占2字节。这种结构体可以有多个。

二 实现

发送RTCP FB NACK报文

NackModule2发送RTCP FB NACK报文有两种实现方式:一种是基于序列号,另一种基于时间,周期是20ms。两种都有用到。

AddPacketsToNack(uint16_t seq_num_start,uint16_t seq_num_end),参1 !=参2,说明丢包了。// Do not send nack for packets that are already recovered by FEC or RTXif (recovered_list_.find(seq_num) != recovered_list_.end())continue;丢包了,就放到nack_list_[seq_num] = nack_info;中。
std::vector<uint16_t> NackModule2::GetNackBatch(NackFilterOptions options) {
...
//send_nack_delay_ms_可设置,默认为0
bool delay_timed_out =now.ms() - it->second.created_at_time >= send_nack_delay_ms_;//resend_delay是rtt,基于时间的,要判断rttbool nack_on_rtt_passed =now.ms() - it->second.sent_at_time >= resend_delay.ms();bool nack_on_seq_num_passed =it->second.sent_at_time == -1 &&AheadOrAt(newest_seq_num_, it->second.send_at_seq_num);//sent_at_time == -1, 重发一次后,值变了,基于序列号的不会重发到第二次if (delay_timed_out && ((consider_seq_num && nack_on_seq_num_passed) ||(consider_timestamp && nack_on_rtt_passed))) {nack_batch.emplace_back(it->second.seq_num);	++it->second.retries;	it->second.sent_at_time = now.ms();
...
}

nack_sender_->SendNack(nack_batch, /*buffering_allowed=*/true);

基于时间的:在构造函数中,起了一个定时任务, nack_sender_->SendNack(nack_batch, /*buffering_allowed=*/false);

一些参数:

const int kMaxNackPackets = 1000;//nack_list_队列的最大长度
const int kDefaultRttMs = 100; //rtt的默认值
const int kMaxNackRetries = 10; //最大重传次数10次
const int kMaxPacketAge = 10000;

丢包太多,会直接请求FIR、关键帧了。

2 发送端用RTX重发RTP包

根据序列号,从packet_history_找到该包。重发。

packet_history_默认大小是600个,可设置的,存储600个RTP包。

static const int kMinSendSidePacketHistorySize = 600;

细节1:发送端重发丢失的包,会判断RTT,时间比RTT小,不发送

RTPSender::ReSendPacket(...)中,会从packet_history_队列中查找,if (!VerifyRtt(*packet, clock_->TimeInMilliseconds())) {// Packet already resent within too short a time window, ignore.return nullptr;}

PacingController::EnqueuePacket中,会判断优先级,音频、重传、视频。

细节2:RTX和原RTP包不同的地方:payload多了2字节的OSN即原始序列号,具体见 RTPSender::BuildRtxPacket。

3 接收到原视频包或RTX包

根据ssrc判断出是那种。在RtxReceiveStream::OnRtpPacket中,处理RTX包,然后给RtpVideoStreamReceiver2::OnRtpPacket。

三 自问自答

1 RTCP FB NACK包发送原则?发现丢包立即发送?定时发送?

答:不仅仅判断丢包,基于时间的还判断了RTT,RTT是一直在更新的。

代码见:NackModule2::GetNackBatch。不同版本有差别。

2 重发RTP包即RTX包,原则?判断了rtt时间。

发RTCP Nack包,最多重试10次?

基于序列号的,不会重发10次的。sent_at_time == -1 ,还有什么情况能赋值为-1 ?

基于时间存在重试10次的情况。

3 基于时间周期是20ms,期望RTT在20毫秒之内!!!这个值可以优化。

4 基于序列号和时间有冲突吗?没有,++retries。

怎么优化nack,调整那些参数?


http://chatgpt.dhexx.cn/article/btQML9ex.shtml

相关文章

WEBRTC浅析(五)视频Nack包的发送判断逻辑以及数据流

这篇文章是对webrtc 中Nack包发送机制的梳理&#xff0c;主要包括三个部分&#xff1a; 第一部分&#xff0c;介绍RTCP包中&#xff0c;Nack包的规范。 第二部分&#xff0c;介绍在WEBRTC中&#xff0c;Nack发送机制的数据流程图。 第三部分&#xff0c;介绍在WEBRTC中&#xf…

RabbitMQ的ack和nack机制

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、ACK机制二、主动ACK三、手动ACK四、Nack机制五、MQ unack的影响总结 前言 本文主要讨论RabbitMQ消费者的ack和nack机制&#xff0c;并且关注ack和nack使用…

RTCP 协议的 NACK 报文

接收方定时把所有未收到的包序号通过反馈报文通知到发送方进行重传。 相对 ARQ带来的改进&#xff1a;减少的反馈包的频率和带宽占用&#xff0c;同时也能比较及时地通知发送方进行丢包重传。 NACK 报文的定义在 [rfc4585] 文档中定义。 RTCP 的反馈报文包头定义如下&#x…

webrtc nack实现原理

1.nack 简介 webrtc 中nack是最基本的QOS策略&#xff0c;与ack机制不同的地方是nack是接收端检测到丢包时&#xff0c;告知发送端具体丢包的序号&#xff0c;接收端收到nack后从缓存中找到对应的包并发送出去。 2. nack实现 nack rtcp报文格式如上图所示&#xff0c;pt205。P…

webrtc QOS方法一(NACK实现)

一&#xff1a;概述 NACK则在接收端检测到数据丢包后&#xff0c;发送NACK报文到发送端&#xff1b;发送端根据NACK报文中的序列号&#xff0c;在发送缓冲区找到对应的数据包&#xff0c;重新发送到接收端。NACK需要发送端发送缓冲区的支持&#xff0c;RFC5104[2]定义NACK数据包…

认识网络通信中的 ACK、NACK 和 REX

ACK、NACK、 REX在面试或者网络通信的时候&#xff0c;我们可能经常听到和遇到。今天就来详细介绍一下ACK、NACK、 REX。 认识ACK、NACK、 REX ACK&#xff1a;Acknowledgement&#xff0c;它是一种正向反馈&#xff0c;接收方收到数据后回复消息告知发送方。NACK&#xff1a…

WebRTC之NACK、RTX 在什么时机判断丢包发送NACK请求和RTX丢包重传

WebRTC之NACK、RTX 在什么时机判断丢包发送NACK请求和RTX丢包重传 WebRTC之NACK、RTX 在什么时机判断丢包发送NACK请求和RTX丢包重传 WebRTC之NACK、RTX 在什么时机判断丢包发送NACK请求和RTX丢包重传前言一、NACK与RTX的作用1、NACK/RTX的工作机制的流程图2、NACK/RTX涉及到的…

WebRTC 的音频弱网对抗之 NACK

本文梳理 WebRTC 的音频弱网对抗中的 NACK 机制的实现。音频的 NACK 机制在 WebRTC 中默认是关闭的&#xff0c;本文会介绍开启 NACK 机制的方法。 在网络数据传输中&#xff0c;NACK (NAK&#xff0c;negative acknowledgment&#xff0c;not acknowledged) 是数据接收端主动…

流媒体弱网优化之路(NACK)——纯NACK方案的优化探索

流媒体弱网优化之路(NACK)——纯NACK方案的优化探索 —— 我正在的github给大家开发一个用于做实验的项目 —— github.com/qw225967/Bifrost目标&#xff1a;可以让大家熟悉各类Qos能力、带宽估计能力&#xff0c;提供每个环节关键参数调节接口并实现一个json全配置&#xff…

WebRTC源码分析 nack详解

1、Nack过程 1.1 nack是什么 丢包重传(NACK)是抵抗网络错误的重要手段。NACK在接收端检测到数据丢包后&#xff0c;发送NACK报文到发送端&#xff1b;发送端根据NACK报文中的序列号&#xff0c;在发送缓冲区找到对应的数据包&#xff0c;重新发送到接收端。NACK需要发送端&am…

谈谈网络通信中的 ACK、NACK 和 REX

目录 名词解释 问题 1&#xff1a; 接收方如何判断数据包是否丢失&#xff1f; 问题 2&#xff1a;发送方如何确认数据包已经丢失&#xff1f; 问题 3&#xff1a;重传超时的计算规则&#xff1f; 问题 4&#xff1a;发送方的数据包要缓存多久&#xff1f; 问题 5&#x…

费马定理_高数_1元微积分

定理 设 f(x) 在 x0 点处满足&#xff1a;1、可导 2、取得极值&#xff0c;则有 f ’ (x0)0 证明 不妨假设 f(x) 在点 x0 处取得极大值&#xff0c;则存在 x0 的邻域 U( x0 )&#xff0c;对任意的 x属于U( x0 )&#xff0c;都有 根据导数定义与极限的保号性有 又 f(x) 在点…

老猿Python博客文章目录索引

本目录提供老猿Python所有相关博文的一级目录汇总&#xff0c;带星号的为付费专栏&#xff1a; 一、专栏列表 本部分为老猿所有专栏的列表&#xff0c;每个专栏都有该专栏置顶的博文目录&#xff1a; Python基础教程目录PyQt入门学习* 使用PyQt开发图形界面Python应用PyQtmo…

(组合数+快速幂+lucas+费马小引理)acwing 887. 求组合数 III

887. 求组合数 III 题目链接https://www.acwing.com/problem/content/889/ 题目&#xff1a; 思路&#xff1a; #include<iostream> #include<cstdio> using namespace std; typedef long long LL; int n; int qmi(LL a,int k,int p){int res1;while(k){if(k&…

(组合数 +快速幂+逆元+费马小引理)acwing 886. 求组合数 II

886. 求组合数 II 题目链接https://www.acwing.com/problem/content/888/ 题目&#xff1a; 思路&#xff1a; #include<iostream> #include<cstdio> using namespace std; typedef long long LL; const int mod1e97;//mod为质数 int a,b,n; int fact[100010],…

Leetcode-数学费马平方和定理-633. 平方数之和

题目633. 平方数之和&#xff1a; 题解&#xff1a; 1&#xff0c;暴力枚举sqrt class Solution { public:bool judgeSquareSum(int c) {if(c < 2 ){return true;}for(long a 0; a*a < c; a){double b sqrt(c - a * a);if((int)b b){return true;}}return false;} …

费马定理、罗尔中值定理、零点存在定理、拉格朗日中值定理、

介值定理 介值定理如果AB,则开区间&#xff08;a,b&#xff09;内可能取不到端点值A,B 即介值定理如果C不等于端点值&#xff0c;那么 ξ ξ ξ可以是属于开区间&#xff0c;如果C等于端点值&#xff0c;那么 ξ ξ ξ必须属于闭区间。 零点存在定理 假设函数f(x)在闭区间[a,…

费马引理的证明

设 f(x)在 ξ处最大&#xff0c;故不论Δx是正或负&#xff0c;总有 设 &#xff0c; 则 。 故由极限的保号性有 &#xff08;1&#xff09; 而当 时&#xff0c; &#xff0c; 故 &#xff08;2&#xff09; 由(1)&#xff0c;(2)两式及 存在知&#xff0c;必有 设 f(x)在 ξ处…