从WebRtc学习RTP协议

文章目录

  • TCP为何不适用于实时音视频
  • UDP->RTP
  • RTP协议结构
  • Jittbuffer
  • RTP扩展头
  • RTP填充数据
  • 参考

TCP为何不适用于实时音视频

可靠性是以牺牲实时性为代价的。按照TCP原理,当出现极端网络情况时,理论上每个包的时延可达到秒级以上,而且这种时延是不断叠加的。这对于音视频实时通信来说是不可接受的。
TCP为了实现数据传输的可靠性,采用的是“发送→确认→丢包→重传”这样一套机制。而且为了增加网络的吞吐量,还采用了延迟确认和Nagle算法(将多个小包组成一个大包发送,组合包的大小不超过网络最大传输单元)

为了增加网络的吞吐量,接收端不必每收到一个包就确认一次,而是对一段时间内收到的所有数据集体确认一次即可。为了实现该功能,TCP通常会在接收端启动一个定时器。定时器的时间间隔一般设置为200ms,即每隔200ms确认一次接收到的数据。这就是延迟确认机制。‘
除此之外,TCP在发送端也启动了一个定时器,不过该定时器的功能不是发送确认消息,而是用来判别是否有丢包的情况。发送端定时器的时长为一个RTO(RTO(Retransmission Timeout),重传超时时长。其值约等于RTT的平均值,每次超时后以指数级增长。RTT表示一个数据包从发送端到接收端,然后再回到发送端所用的时长)如果在定时器超时后仍然没有收到包的确认消息,则认为包丢失了,需要发送端重发丢失的包。这就是TCP的丢包重传机制。
在这里插入图片描述

假如接收端发送的确认消息丢失了,按TCP的协议规则,通信双方会怎么做呢?首先,发送端只有等到定时器超时后,才能发现该包丢失了。确认丢包后,发送端会将前面所有未确认的包重发一遍。如果在收到数据后,接收端发送的确认消息又丢失了,那么发送端还要等到定时器超时后才能知道包丢失了。因此,在遇到这种极端网络的情况下,TCP传输的时延要累加很多,这种时延是不可控的。

UDP->RTP

UDP没有这套逻辑,所以实时性最高。WebRTC通过NACK、FEC、Jitter Bufer以及NetEQ技术既可以解决丢包和抖动问题,又不会产生影响服务质量的时延。
UDP传输一些有前后逻辑关系的数据时有缺陷,所以在UDP之上的应用层上使用RTP传输音视频数据

RTP协议结构

保持有序:Sequence Number
我们希望在使用RTP传输音视频数据时,一旦有数据丢失,可以快速定位是哪个数据包丢失了。
如果给每个发送的数据包都打上一个编号,并且编号是连续的,那么,接收端就可以很容易地判断出哪些包丢失了。在RTP头中,有一个专门记录该编号的字段,称作Sequence Number。在发送端,每产生一个RTP包,其Sequence Number字段中的值就被自动加1,以保证每个包的编号唯一且连续。当接收端收到RTP包时,会对Sequence Number字段进行检查,如果发现Sequence Number不连续了,就说明有包丢失或乱序了。
区分不同类型数据:PayloadType
我们在做网络应用开发时,通常会使用同一个端口传输不同类型的数据,如音视频数据。但接收端是如何区分出不同类型的数据的?RTP在其协议头中设置了PT(PayloadType)字段.比如VP8的PT一般为96,而Opus的PT一般为111
区分不同源数据包:SSRC
同一个端口不仅可以同时传输不同类型的数据包,还可以传输同一类型但不同源的数据包。
流媒体服务就可以将多个不同源(参与人)的视频通过同一个端口发送给客户端。那么客户端(接收端)又是如何将不同源的数据区分出来的呢?这就要说到RTP中另一个字段SSRC了。
RTP要求所有不同的源的数据流之间可以通过SSRC字段进行区分,且每个源的SSRC必须唯一。
每个SSRC所代表的数据流的Sequence Number都是单独计数的,如下图:
在这里插入图片描述

完整的协议格式如下:
在这里插入图片描述

V(Version)字段,占2位,表示RTP的版本号,现在使用的都是第2个版本,所以该域固定为2。
P(Padding)字段,占1位,表示RTP包是否有填充值。为1时表示有填充,填充以字节为单位。一般数据加密时需要固定大小的数据块,此时需要将该位置1。
X(eXtension)字段,占1位,表示是否有扩展头。如果有扩展头,扩展头会放在CSRC之后。扩展头主要用于携带一些附加信息。
CC(CSRCCount)字段,占4位,记录了CSRS标识符的个数。每个CSRC占4字节,如果CC=2,则表示有两个CSRC,共占8字节。
M(Marker)字段,其含义是由配置文件决定的,一般情况下用于标识边界。比如一帧H264被分成多个包发送,那么最后一个包的M位就会被置位,表示这一帧数据结束了。
timestamp字段,占4字节,用于记录该包产生的时间,主要用于组包和音视频同步。
CSRC字段,指该RTP包中的数据是由哪些源贡献的。比如混音数据是由三个音频混成的,那么这三个音频源都会被记录在CSRS列表中。

Jittbuffer

介绍一下使用RTP消除包抖动的一个简要过程:
对于WebRTC而言,其在接收RTP包时,会为之创建一个接收队列来消除包抖动。一开始,队列中只收到了100、101、102和104号包。由于103号包还没到,所以无法将100∼104号包组成一帧数据。103号包没有到有两种可能的原因:一种原因是103号包丢失了;另一种原因是网络抖动导致包乱序了。判断缓冲队列有没有满。如果缓冲队列满了,就说明包真的丢失了。对于103号包来说,由于现在缓冲队列还不满,因此该包处于待定状态。同理,当107号包到达时,105号包和106号包也处于待定状态。
在这里插入图片描述

很快103号包来了,通过对其RTP头中Sequence Number字段的计算,它会被插到队列中对应的空缺位置,此时100∼104号包连成了一串。又由于104号包上有M标记,因此可以将这几个RTP包组成一个完整的帧。接下来,100∼104号包将从缓冲队列中弹出,交由组帧模块处理,空出的位置可以继续接收新包。WebRTC也是通过类似的方法从网络上将一个个RTP包接收下来。
WebRTC中解决RTP包抖动的缓冲队列就是我们通常所说的JitterBufer。

RTP扩展头

当X被置位1,说明有扩展头
在这里插入图片描述

RTP扩展头由三部分组成,分别为profile、length以及headerex tension。
在RFC5285中定义了两种profile,分别是**{0xBE,0xDE}{0x10,0x0X}**(分别代表存放在headerextension中的两种不同的数据格式,即one-byte-header和two-byte-header)

接收端解析RTP扩展头时,通过profile来区分header extension中的内容该如何解析。
length字段表示扩展头所携带的header extension的个数。如果length为4,表示有4个headerextension;
header extension字段是扩展头信息,以4字节为单位,其具体含义由profile决定。

one-byte-header格式:
存放在扩展头header extension字段中的数据,由一个字节的Header和N字节的Body组成,而Header又由4位的ID和4位的len组成。注意,length的值为跟在Header后面的数据(以字节为单位)长度减1
在这里插入图片描述

第一个one-byte-header的length值为0,其数据长度为(0+1)=1字节;第二个one-byte-header(的length值为1,其数据占(1+1)=2字节;第三个one-byte-header的length值为3,其数据占(3+1)=4字节。此外,由于扩展头要保持4字节对齐,所以最后两个字节是填充字节,设置为0。
在这里插入图片描述

two-byte-header格式:
Header部分由两个字节组成,第一个字节表示ID,第二个字节表示长度,two-byte-header中length存放的是实际长度。
在这里插入图片描述

通过上面的介绍我们知道RTP扩展头有三个要点。一是RTP标准头中的X位,该位置1时,RTP中才会有扩展头。二是扩展头中的profile字段指明了扩展头中数据的格式。如果profile为0xBEDE,则说明使用的扩展头格式为one-byte-header;如果profile为0x100X(X表示任意值),则说明使用的扩展头格式为two-byte-header。三是one-byte-header与two-byte-header的区别。如果ID和len放在一个字节中,说明它是one-byte-header格式;如果ID和len放在两个字节中,说明它是two-byte-header格式。

RTP填充数据

RTP头中的P位用于标识RTP包中是否有填充数据。如果P位为1,说明RTP包中含有填充数据。
当RTP包中包含有填充数据时,其数据包的最后一个字节记录着包中填充字节的个数,即图中的Padding Size部分。
在这里插入图片描述

如果Padding Size为5,说明RTP包中共有5个填充字节,其中包括它自己。在解析RTP Payload部分之前,应将填充部分去掉。去掉填充字节的算法也非常简单,首先读取RTP包的最后一个字节,取出填充字节数,然后从最后一个字节算起,将其前面的Padding Size个字节丢掉即可。

参考

李超《WebRTC音视频实时互动技术:原理、实战与源码分析》
https://weread.qq.com/web/reader/377320f07260a55337761c1kc81322c012c81e728d9d180

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/376680.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决ListView异步加载数据之后不能点击的问题

在ListView的onScroll事件中执行异步加载数据,然后使用notifyDataSetChange()函数更新适配器,之后发现listView不能点击了,这问题苦恼了我半天。最后在一篇博文中发现调用listView的requestFocusFromTouch()函数终于解决了这问题。 Java代码…

从WebRtc学习RTCP协议

文章目录RTCP支持的消息类型RTCP协议头WebRTC的反馈报文RTPFB支持的报文类型:PSFB支持的报文类型:参考RTCP是RTP的控制协议.那么RTCP能对RTP做哪些控制呢?其中最为大家熟知的就是 丢包控制。发送端发送数据后,接收端如果发现有RTP…

无锁队列设计思路以及简要代码

文章目录非并发的一写一读环形队列多读多写环形队列非并发的一写一读环形队列 读指针: 1、先判断是否有数据 2、读取数据 3、操作指针 写指针: 1、先判断空间是否足够 2、写入数据 3、操作指针 所以代码也十分简单: bool putqueue(void* pDa…

CPU Cache对于并发编程的影响

文章目录引子CPU Cache对于并发的影响读写顺序对性能的影响字节对齐对Cache的影响小结引子 下面给出两个极其相似的代码&#xff0c;运行出的时间却是有很大差别&#xff1a; 代码一 #include <stdio.h> #include <pthread.h> #include <stdint.h> #includ…

软工之初识

我们之前已经在完全不懂软件工程的情况下&#xff0c;已经做完了两个小系统&#xff0c;虽然能够运行&#xff0c;但其中有很多的问题&#xff0c;学习软工就是让我们在工程学原理的指导之下去开发和设计软件。 软件工程同大多数书讲的都是一样的&#xff0c;首先对软件工程有一…

perf +火焰图使用

以mysqld进程为例&#xff1a; [rootVM-90-225-centos ~]# ps -ef | grep mysqld root 9808 9621 0 19:30 pts/7 00:00:00 grep --colorauto mysqld root 16104 1 0 17:30 pts/0 00:00:00 /bin/sh /usr/local/mysql/bin/mysqld_safe --datadir/usr/loc…

在一个字符串中找到第一个只出现一次的字符

题目&#xff1a;在一个字符串中找到第一个只出现一次的字符&#xff0c;如输入abaccdeff&#xff0c;则输出b&#xff1b;具体实现如下&#xff1a;#include <iostream> #include <string> using namespace std; void FindChar(const string &strBuf) {int nA…

零拷贝机制在文件传输中的使用手法

文章目录文件传输&#xff08;读取与发送&#xff09;中的拷贝与上下文切换零拷贝技术sendfilesendfile SG-DMAmmap writespliceDirect I/O经典应用文件传输&#xff08;读取与发送&#xff09;中的拷贝与上下文切换 如果服务端要提供文件传输的功能&#xff0c;最简单的方式…

POJ 3233 Matrix Power Series 矩阵快速幂 + 二分

题意&#xff1a;求矩阵的次方和 解题思路&#xff1a;最容易想到方法就是两次二分因为 我们可以把一段 A^1 A^2 .......A^K 变成 A^1 ..A^(K/2) ( A^1 ..A^(K/2))*(A^(k/2)) 当k 为奇数的时候 或者 A^1 ..A^(K/2) ( A^1 ..A^(K/2))*(A^(k/2)) A^K 当K 为偶数的时候…

时间序列进行分析的一些手法以及代码实现(移动平均、指数平滑、SARIMA模型、时间序列的(非)线性模型)

文章目录1、移动平均moving average方法weighted average方法2、指数平滑单指数平滑 exponential_smoothing双指数平滑三指数平滑 Triple exponential smoothing3、平稳性以及时间序列建模SARIMA模型4、时间序列的&#xff08;非&#xff09;线性模型时间序列的滞后值使用线性回…

三大平衡树(Treap + Splay + SBT)总结+模板

Treap树 核心是 利用随机数的二叉排序树的各种操作复杂度平均为O(lgn) Treap模板&#xff1a; #include <cstdio> #include <cstring> #include <ctime> #include <iostream> #include <algorithm> #include <cstdlib> #include <cmath…

mysqld进程 ut_delay 占用率过高

采用性能分析工具perf top -p mysqld进程 在测试mysql数据库时&#xff0c;用perf top如果看到热点函数是ut_delay或者_raw_spin_lock的话&#xff0c;说明锁争用比较严重。 ut_delay这是innodb的一个自旋琐。也就是说&#xff0c;在这里由于锁等待&#xff0c;innodb不停地在…

滑动窗口在重构数据集的作用

step1&#xff1a;使用滑动窗口重构数据集 给定时间序列数据集的数字序列&#xff0c;我们可以将数据重构为看起来像监督学习问题。 我们可以通过使用以前的时间步作为输入变量并使用下一个时间步作为输出变量来做到这一点。 通过观察重构后的数据集与原本的时间序列&…

sliverlight - Unhandled Error in Silverlight Application错误

使用firebug控制台输出错误&#xff1a; Unhandled Error in Silverlight Application 查询“GetFlow_Process”的 Load 操作失败。远程服务器返回了错误: NotFound。 位于 System.ServiceModel.DomainServices.Client.OperationBase.Complete(Exception error) 位于 System.S…

前向验证对于模型的更新作用

首先&#xff0c;让我们看一个小的单变量时间序列数据&#xff0c;我们将用作上下文来理解这三种回测方法&#xff1a;太阳黑子数据集。该数据集描述了刚刚超过 230 年&#xff08;1749-1983 年&#xff09;观察到的太阳黑子数量的每月计数。 数据集显示了季节之间差异很大的…

PHP-面向对象(八)

1、多态的介绍与优势 多态性是继抽象和继承后&#xff0c;面向对象语言的第三个特征。从字面上理解&#xff0c;多态的意思是“多种形态”&#xff0c;简单来说&#xff0c;多态是具有表现多种形态的能力的特征&#xff0c;在OO中是指“语言具有根据对象的类型以不同方式处理。…

双指数平滑中参数对于预测模型的影响

先看看α 在β一致的情况下&#xff0c;α越小&#xff0c;模型越滞后。 再看看β 在α一致的情况下&#xff0c;β越大&#xff0c;模型对于趋势的预测更敏锐。

分页查询

分页查询算是比较常用的一个查询了在DAO层主要是查两个数据第一个总条数第二个要查询起始记录数到查询的条数当第一次点击查询时候(非下一页时Page类里面预设的就是 index就是0 pageSize是预设值当点击下一页的时候 index 和 pageSize带的就是页面上面给的值了分页的页面一般的…

me23n去价格

SELECT knumv kposn AS ebelp kschl kbetr kpein kwert INTO CORRESPONDING FIELDS OF TABLE gt_konv FROM konv FOR ALL ENTRIES IN gt_ekpo WHERE knumv gt_ekpo-knumv AND kinak EQ AND kschl IN (PB00,PBXX,P101).转载于:…

使用Bootstrap-table创建表单,并且与flask后台进行数据交互

文章目录引用css和js使用htmljavascriptflaskmysql参考引用css和js Bootstrap-table为这些文件提供了 CDN 的支持&#xff0c;所以不需要下载.js .css文件就可以直接用了&#xff0c;十分方便 <!-- Latest compiled and minified CSS --> <link rel"stylesheet…