RTCP 协议的 NACK 报文

article/2025/10/6 16:29:30

接收方定时把所有未收到的包序号通过反馈报文通知到发送方进行重传。

相对 ARQ带来的改进:减少的反馈包的频率和带宽占用,同时也能比较及时地通知发送方进行丢包重传。

NACK 报文的定义在 [rfc4585] 文档中定义。

RTCP 的反馈报文包头定义如下,FMT 和 PT 决定了该报文的类型,FCI 则是该类型报文的具体负载:

version (V): 2 bits 该字段标识RTP版本。当前版本是2

padding (P): 1 bit 如果设置,则填充位指示数据包包含末尾的其他填充八位位组不属于控制信息,但包含在长度字段中。

Feedback message type (FMT): 5 bits 此字段标识FB消息的类型,并且为相对于类型(传输层,有效负载特定的或应用层的反馈)。每个值 三种反馈类型在各自的部分中定义下面。

Payload type (PT): 8 bits 这是RTCP数据包类型,将数据包标识为RTCP FB消息. IANA定义了两个值:

Length: 16 bits 此数据包的长度(以32位字为单位)减去1,包括标头和任何填充。这符合定义RTCP发送方和接收方报告中使用的长度字段。

SSRC of packet sender: 32 bits 此消息的发起者的同步源标识符包。

SSRC of media source: 32 bits 媒体源的同步源标识符。

协议规定的 NACK 反馈报文的 PT= 205,FMT=1,FCI 的格式如下(可以附带多个 FCI,通过 header 的 length 字段来标示其长度):

这里的设计比较巧妙,它可以一次性携带多个连续的数据包的丢包情况:

Packet ID (PID): 16 bits PID字段用于指定丢失的数据包。PID字段表示丢失数据包的RTP序列号。

bitmask of following lost packets (BLP): 16 bits BLP允许报告紧跟在PID指示的RTP数据包之后16个RTP数据包中任何一个的丢失情况。如果接收方将位掩码的位i设置为1, 表示编号为(PID + i)的RTP数据包丢失。 否则,将位i设置为0。

 

NACK数据抓包

下面为RTCP数据包,红色方框内就为NACK数据。

使用wireshark解析如下:

 

通过丢失的RTP数据包序列号计算 PID 和 BLP

static void check_for_seq_number_gap_immediate(RtpSession *session, rtp_header_t *rtp) {uint16_t pid;uint16_t i;/*don't check anything before first packet delivered*/if (session->flags & RTP_SESSION_FIRST_PACKET_DELIVERED&& RTP_SEQ_IS_STRICTLY_GREATER_THAN(rtp->seq_number, session->rtp.rcv_last_seq + 1)&& RTP_SEQ_IS_STRICTLY_GREATER_THAN(rtp->seq_number, session->rtp.snd_last_nack + 1)) {uint16_t first_missed_seq = session->rtp.rcv_last_seq + 1;uint16_t diff;if (first_missed_seq <= session->rtp.snd_last_nack) {first_missed_seq = session->rtp.snd_last_nack + 1;}diff = rtp->seq_number - first_missed_seq;pid = first_missed_seq;for (i = 0; i <= (diff / 16); i++) {uint16_t seq;uint16_t blp = 0;for (seq = pid + 1; (seq < rtp->seq_number) && ((seq - pid) < 16); seq++) {blp |= (1 << (seq - pid - 1));}if (session->rtp.congdetect != NULL && session->rtp.congdetect->state == CongestionStateDetected) {/** Do not send NACK in IMMEDIATE_NACK mode in congestion, because the retransmission by the other party of the missing packets* will necessarily increase or at least sustain the congestion.* Furthermore, due to the congestion, the retransmitted packets have very few chance to arrive in time.*/ortp_message("Immediate NACK not sent because of congestion.");return;}rtp_session_send_rtcp_fb_generic_nack(session, pid, blp);pid = seq;}}if (RTP_SEQ_IS_STRICTLY_GREATER_THAN(rtp->seq_number, session->rtp.snd_last_nack)) {/* We update the last_nack since we received this packet we don't need a nack for it */session->rtp.snd_last_nack = rtp->seq_number;}
}

 

根据 PID 和 BLP 获取丢失的RTP数据包序列号

static void generic_nack_received(const OrtpEventData *evd, OrtpNackContext *ctx) {if (rtcp_is_RTPFB(evd->packet) && rtcp_RTPFB_get_type(evd->packet) == RTCP_RTPFB_NACK) {RtpTransport *rtpt = NULL;rtcp_fb_generic_nack_fci_t *fci;uint16_t pid, blp, seq;mblk_t *lost_msg;/* get RTP transport from session */rtp_session_get_transports(ctx->session, &rtpt, NULL);fci = rtcp_RTPFB_generic_nack_get_fci(evd->packet);pid = rtcp_fb_generic_nack_fci_get_pid(fci);blp = rtcp_fb_generic_nack_fci_get_blp(fci);bctbx_mutex_lock(&ctx->sent_packets_mutex);lost_msg = find_packet_with_sequence_number(&ctx->sent_packets, pid);if (lost_msg != NULL) {meta_rtp_transport_modifier_inject_packet_to_send(rtpt, ctx->rtp_modifier, lost_msg, 0);ortp_message("OrtpNackContext [%p]: Resending missing packet with seq=%hu", ctx, pid);} else {ortp_warning("OrtpNackContext [%p]: Cannot find missing packet with seq=%hu", ctx, pid);}++pid;for (seq = blp; seq != 0; seq >>= 1, ++pid) {if (seq & 1) {lost_msg = find_packet_with_sequence_number(&ctx->sent_packets, pid);if (lost_msg != NULL) {meta_rtp_transport_modifier_inject_packet_to_send(rtpt, ctx->rtp_modifier, lost_msg, 0);ortp_message("OrtpNackContext [%p]: Resending missing packet with seq=%hu", ctx, pid);} else {ortp_warning("OrtpNackContext [%p]: Cannot find missing packet with seq=%hu", ctx, pid);}}}bctbx_mutex_unlock(&ctx->sent_packets_mutex);}
}

 

 

 


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

相关文章

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)在 ξ处…

费马引理

转载于:https://www.cnblogs.com/fuhang/p/7976329.html

高等数学——微分中值定理

本文始发于个人公众号&#xff1a;TechFlow&#xff0c;原创不易&#xff0c;求个关注 今天和大家回顾一下高数当中的微分中值定理&#xff0c;据说是很多高数公式的基础。由于本人才疏学浅&#xff0c;所以对于这点没有太深的认识。但是提出中值定理的几个数学家倒是如雷贯耳&…

(机器学习、人工智能数学基础:高等数学篇)第三章:微分中值定理:第一节:微分中值定理

文章目录 一&#xff1a;费马引理二&#xff1a;罗尔定理三&#xff1a;拉格朗日中值定理四&#xff1a;柯西中值定理五&#xff1a;泰勒公式&#xff08;1&#xff09;泰勒公式&#xff08;2&#xff09;常见泰勒展开式 一&#xff1a;费马引理 费马引理&#xff1a;如果函数…