RTP协议基本分析(RTSP、WebRTC使用)

目录

  • 1、介绍
  • 2、RTP
  • 3、格式
  • 4、RTP打包H264
    • 4.1、H264打包方式之Single NAL Unit
    • 4.2、H264打包方式之FU-A
      • 4.2.1、FU indication
      • 4.2.2、FU header
      • 4.2.3、第一个IDR帧的NALU第一个切片
      • 4.2.4、第一个IDR帧的NALU第二个切片
      • 4.2.5、第一个IDR帧的NALU最后一个切片
  • 5、RTP打包AAC
    • 5.1、AU-headers-length
    • 5.2、AU-header
    • 5.3、AU
    • 5.4、RTSP/SDP中AAC相关配置
    • 5.5、AU-Header数据段的格式

1、介绍

实时流传输协议(RTSP:Real Time Streaming Protocol)是一种网络传输协议,旨在发送低延迟流。
该协议由RealNetworks,Netscape和哥伦比亚大学的专家在1996年开发。它定义了应如何打包流中的数
据以进行传输。
在这里插入图片描述

2、RTP

RTP协议原理,负责对流媒体数据进行封包并实现媒体流的实时传输,即它按照RTP数据包格式来封装流媒体数据,并利用与它绑定的协议进行数据包的传输。

RTP可以基于UDP和TCP两种方式传输,两种方式大致是一样的,下面主要都是基于UDP的分析:

RTP在端口号1025到65535之间选择一个未使用的偶数UDP端口号,而在同一次会话中的RTCP则使用下一个基数UDP端口号。

3、格式

RTP报文由两部分组成:报头和有效载荷。RTP报头格式如下图所示,其中:V:RTP协议的版本号,占2位,当前协议版本号为2。P:填充标志,占1位,如果P=1,则在该报文的尾部填充一个或多个额外的八位组,它们不是有效载荷
的一部分。X:扩展标志,占1位,如果X=1,则在RTP报头后跟有一个扩展报头。
CC:CSRC计数器,占4位,指示CSRC 标识符的个数。M: 标记,占1位,不同的有效载荷有不同的含义,对于视频,标记一帧的结束;对于音频,标记帧的开
始。PT: 有效载荷类型,占7位,用于说明RTP报文中有效载荷的类型,如GSM音频、JPEM图像等。
序列号:占16位,用于标识发送者所发送的RTP报文的序列号,每发送一个报文,序列号增1。接收者
通过序列号来检测报文丢失情况,重新排序报文,恢复数据。时戳(Timestamp):占32位,时戳反映了该RTP报文的第一个八位组的采样时刻。接收者使用时戳来
计算延迟和延迟抖动,并进行同步控制。同步信源(SSRC)标识符:占32位,用于标识同步信源。该标识符是随机选择的,参加同一视频会议的
两个同步信源不能有相同的SSRC。特约信源(CSRC)标识符:每个CSRC标识符占32位,可以有015个。每个CSRC标识了包含在该RTP
报文有效载荷中的所有特约信源。

在这里插入图片描述

1 typedef struct _rtp_header_t
2 {
3 uint32_t v:2; /* protocol version */
4 uint32_t p:1; /* padding flag */
5 uint32_t x:1; /* header extension flag */
6 uint32_t cc:4; /* CSRC count */
7 uint32_t m:1; /* marker bit */
8 uint32_t pt:7; /* payload type */
9 uint32_t seq:16; /* sequence number */
10 uint32_t timestamp; /* timestamp */
11 uint32_t ssrc; /* synchronization source */
12 } rtp_header_t;

同步信源:是指产生媒体流的信源,例如麦克风、摄像机、RTP混合器等。它通过RTP报头中的一个32位数
字SSRC标识符来标识,而不依赖于网络地址,接收者将根据SSRC标识符来区分不同的信源,进行RTP报
文的分组。

特约信源:是指当混合器接收到一个或多个同步信源的RTP报文后,经过混合处理产生一个新的组合RTP报
文,并把混合器作为组合RTP报文的SSRC,而将原来所有的SSRC都作为CSRC传送给接收者,使接收者
知道组成组合报文的各个SSRC。
在这里插入图片描述
例如:
有三个信号源各发出一路rtp流,RTP1携带的SSRC是SSRC1,RTP2携带的SSRC是SSRC2,
RTP3携带SSRC3,这三路RTP流到达混合器时,混合器会将这三路流混合成一路流发出去,它会把这三
路流的SSRC记录下来,形成一个列表,叫CSRC表,在发送的混合RTP流中,SSRC域填充的字段是混合
器本身的SSRC4,而CSRC字段则会根据该包的负载的源来填入。

如当前的RTP包的负载是来自SSRC1的,那么在当前RTP包的CSRC字段填入SSRC1。
这样接收者就可以根据CSRC来区分不同的信源。

4、RTP打包H264

RTP的特点不仅仅支持承载在UDP上,这样利于低延迟音视频数据的传输,另外一个特点是它允许
通过其它协议接收端和发送端协商音视频数据的封装和编解码格式,这样固定头的playload type字
段就比较灵活。

H.264标准协议定义了两种不同的类型:一种是VCL即Video Coding Layer , 一 种 是 NAL 即
Network Abstraction Layer。其中前者就是编码器吐出来的原始编码数据,没有考虑传输和存储
问题。后面这种就是为了展现H.264的网络亲和性,对VCL输出的slice片数据进行了封装为
NALUs(NAL Units),然后再封装为RTP包进行传输。

NALU的基本格式是:NALU Header + NALU Data,其中NALU的头由一个字节组成如下所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
一、
1-11就是NALU的单个包类型,但是一个NALU的大小是不一样的,如果是非视频数据的
SPS PPS才十几个字节,对于IDR帧,则有可能几十KB。
这样把NALU打包到RTP方式就很多,分为:
一个RTP包承载一个NALU;
多个NALU合并到一个RTP;
一个大的NALU切分成多个RTP。

二、
同时由于时间戳的问题,就有了24-29几种类型。
但是对于发送端组RTP包的一方来说,尽可能找简单的打包方式。对于接受端则需要适配各种发送
端的打包方式,因为无法决定输入源的打包方式。
(打包的时候不要搞太复杂的模式)

  1. 我们对于NALU的长度<=1400(rtp payload size)的则采用的是单一NALU打包到单一的RTP
    包中;
  2. 我们对于NALU的长度>1400的则采用了FU-A的方式进行了打包,这种就是把一个大的NALU进
    行了切分,最后接收方则进行了合并,把多个RTP包合并成一个完整的NALU即可;
  3. 为什么NALU的长度大于1400字节就要进行FU-A切片,是因为底层MTU大小值一般为1500,从
    传输效率讲,使用1400作为切分条件。
    RTP最大数据包(包含RTP头部) = MTU - UDP首部 - IP 报文首部

4.1、H264打包方式之Single NAL Unit

一个RTP包打包一个单独的NALU方式,其实最好理解,就是在RTP固定头后直接填充NLAU
单元数据即可,即:
RTP Header + NALU Header + NALU Data; (不包括startcode)
文件中的SPS:
在这里插入图片描述
RTP包中的SPS:
在这里插入图片描述

4.2、H264打包方式之FU-A

需要了解两个数据包头即FU indicator和Fu header。

4.2.1、FU indication

在这里插入图片描述
这里面的的F和NRI就是NALU头的前面三个bit位,后面的
TYPE就是NALU的FU-A类型28,这样在RTP固定头后面第一字节的后面5bit提取出来就确认了该
RTP包承载的不是一个完整的NALU,是其一部分。

那么问题来了,一个NALU切分成多个RTP包传输,那么到底从哪里开始哪里结束呢?
可能有人说RTP包固定头不是有mark标记么,注意区分那个是以帧图像的结束标记,这里要确定是NALU结束
的标记,其次NALU的类型呢?那么就需要RTP固定12字节后面的Fu Header来进行区分。

4.2.2、FU header

在这里插入图片描述

字段解释:
S: 1 bit 当设置成1,开始位指示分片NAL单元的开始。当跟随的FU荷载不是分片NAL单元荷载的开
始,开始位设为0。E: 1 bit 当设置成1, 结束位指示分片NAL单元的结束,即, 荷载的最后字节也是分片NAL单元的最后
一个字节,当跟随的FU荷载不是分片NAL单元的最后分片,结束位设置为0。
也就是说一个NALU切片时,第一个切片的SE是10,然后中间的切片是00,最后一个切片时11。R: 1 bit
保留位必须设置为0,接收者必须忽略该位。Type: 5 bits
此处的Type就是NALU头中的Type,1-23的那个值,表示 NAL单元荷载类型定义。

4.2.3、第一个IDR帧的NALU第一个切片

在这里插入图片描述

FU indication:
十六机制:0x7C
二进制:0111 1100
FU header:
十六进制:0x85
二进制:1000 0101
这里的SE是10,则说明该RTP包承载的NALU的第一个切片。

4.2.4、第一个IDR帧的NALU第二个切片

在这里插入图片描述

FU indication:
十六机制:0x7C
二进制:0111 1100
FU header:
十六进制:0x05
二进制:0000 0101
这里的SE是00,则说明该RTP包承载的NALU的中间切片。

4.2.5、第一个IDR帧的NALU最后一个切片

在这里插入图片描述

FU indication:
十六机制:0x7C
二进制:0111 1100
FU header:
十六进制:0x45
二进制:0100 0101
这里的SE是01,则说明该RTP包承载的NALU的最后一个切片。

5、RTP打包AAC

过程:

  1. 需要将aac的前7个(或9个)字节的ADTS去掉,即是跳过adts header。
  2. 添加RTP Header。
  3. 添加AU_HEADER_LENGTH。
  4. 添加AU_HEADER。
  5. 添加AU(去掉ADTS的aac数据)数据。

如:

注意:一个RTP包中可以有一个AU-headers-length 和 n个AU-header和 n个AU(AU每包实际音频数据流)

5.1、AU-headers-length

头两个字节表示au-header的长度,单位是bit。 一个AU-header长度是两个字节(16bit)因为可以有多
个au-header所以AU-headers-length的值是 16的倍数,一般音频都是单个音频数据流的发送,所以
AU-headers-length的值是16
//AU_HEADER_LENGTH
bytes[12] = 0x00; //高位
bytes[13] = 0x10; //低位 只有一个AU_HEADER
因为单位是bit, 除以8就是auHeader的字节长度;又因为单个auheader字节长度2字节,所以再除以2就
是auheader的个数。
(注意:AU-header长度并不是固定为2字节,具体要看SDP)

5.2、AU-header

au-header的高13个bits就是一个au 的字节长度:
//AU_HEADER
bytes[14] = (byte)((len & 0x1fe0) >> 5); //高位
bytes[15] = (byte)((len & 0x1f) << 3); //低位
(注意:AU-header长度并不是固定为2字节,具体要看SDP)

5.3、AU

音频实际数据(去掉ADTS的aac数据)

5.4、RTSP/SDP中AAC相关配置

1 v=0
2 o=- 16128587303007558182 16128587303007558182 IN IP4 WINDOWS-75ID
U9Q
3 s=Unnamed
4 i=N/A
5 c=IN IP4 0.0.0.0
6 t=0 0
7 a=tool:vlc 3.0.5
8 a=recvonly
9 a=type:broadcast
10 a=charset:UTF-8
11 a=control:rtsp://192.168.2.195:8554/
12 m=audio 0 RTP/AVP 96
13 b=AS:128
14 b=RR:0
15 a=rtpmap:96 mpeg4-generic/22050
16 a=fmtp:96 streamtype=5; profile-level-id=15; mode=AAC-hbr; config
=138856e500; sizeLength=13; indexLength=3; indexDeltaLength=3; Pr
ofile=1;
17 a=control:rtsp://192.168.2.195:8554/trackID=4
18 m=video 0 RTP/AVP 96
19 b=AS:800
20 b=RR:0
21 a=rtpmap:96 H264/90000
22 a=fmtp:96 packetization-mode=1;profile-level-id=42c01e;sprop-para
meter-sets=Z0LAHtoCQKeX/8CgAJ/EAAADAZAAAF2qPFi6gA==,aM43IA==;
23 a=control:rtsp://192.168.2.195:8554/trackID=5

streamtype对于AAC, 固定为5。
profile-level-id固定为1。
config, SizeLength, IndexLength, IndexDeltaLength作用:
config是16进制的, 前两个字节 1388 , 表示采样率为22050, 1个channel。
前两个字节的为ios-14996-3中定义的AudioSpecificConfig, 前13个bits的格式为:
在这里插入图片描述
samplingFrequencyIndex的取值:
在这里插入图片描述
1388 转换成2进制为 0001 0011 1000 1000
audioObjectType为 00010 , 即 2
samplingFrequencyIndex为 0111 , 即 7 , 对应的采样频率为 22050
channelConfiguration为 0001 , 表示channel数量为1。

sizeLength=13; indexLength=3; indexDeltaLength=3涉及到音频的AU Header。

5.5、AU-Header数据段的格式

在这里插入图片描述
在这里插入图片描述

其它的值都是可选的, 如果sdp中没有出现相关的参数(或者为0), 则表示它们不出现。
以最简单的情况举例, 假设aac数据长度为200字节, 只有一个au-header。
200 的二进制为 0000011001000。 (补足为13 bits)
AU-headers-length 值为16, 因为只有一个au-header, au-header中
只有AU-size和AU-Index, 共占用16bits。

整个au-header数据段的内容为

0000 0000 0000 1000 0000011001000 000

如果一个rtp中只有一个aac包, 不需要加AU-Header, 那么sdp中的aac参数可以简化为

a=fmtp:96 streamtype=5; profile-level-id=1; mode=AAC-hbr; config=1
38856e500;

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

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

相关文章

对照片进行边缘化处理,并将边缘化处理后的结果保存

对照片进行边缘化处理&#xff0c;并将边缘化处理后的结果保存 import cv2 from matplotlib import pyplot as plt img cv2.imread(E:\Python-workspace\OpenCV\OpenCV/water1.png,1)#第一个参数为选择照片的路径&#xff0c;注意照片路径最后一个为正斜杠其他都为反斜杠&…

小皇帝,篮球,热火

失败&#xff0c;又一次&#xff0c;完全预料之中. 热火的防守早已是千疮百孔&#xff0c;热火的攻击也是乱无头绪. 现在的热火&#xff0c;需要詹姆斯无球的跑动&#xff0c;需要韦德的助攻。 转载于:https://www.cnblogs.com/JeffChen/archive/2010/11/12/2600335.html

fastjson转换时有大括号或者冒号或者有中括号_[Python Basic] 字符串处理以及类型转换 1...

String Manipulation & Typecasting (1)1. 文本复制以及连接1.1 Multiply sign使用 multiply sigh/乘号* 来复制文本片段。乘号复制文本举例&#xff1a; print("Hi" * 3) # output: HiHiHi print("*" * 10)# output:**********1.2 连接1.2.1 使用 plu…

Java IdentityHashMap size()方法与示例

IdentityHashMap类的size()方法 (IdentityHashMap Class size() method) size() method is available in java.util package. size()方法在java.util包中可用。 size() method is used to return the size (i.e. How many key-value pair exists) of this IdentityHashMap. siz…

读《深入分析Java Web技术内幕》

这里这本书的预读章节&#xff0c;看完预读部分&#xff0c;解答了一些疑惑&#xff0c;也相信这是一本夯实Java Web架构体系的好书。 HTTP协议解析 开发一般使用firefox的firebug调试&#xff0c;这的确是一个利器&#xff0c;HTTP的请求头响应头一目了然。 浏览器缓存机制 当…

windows mobile多国语言实现[转]

介绍一种多国语言的实现办法&#xff0c;这也是微软推荐的方式&#xff0c;打开windows mobile下的windows目录可以看到有很多以MUI为后缀名的文件&#xff0c;例如shellres.dll.0804.mui、shell.dll.0804.mui。。。。。。我们可以用eXeScope.exe或者resources hacker这样的文件…

RTSP协议基本分析

目录一、介绍二、RTSP与HTTP三、RTSP推流基本过程1、OPTION 查询服务器端可用方法1.1、Client 请求1.2、Server 回复2、ANNOUNCE 发送媒体描述信息2.1、Client 请求2.2、Server 回复3、SETUP建立RTSP会话3.1、Client 请求&#xff08;视频流&#xff09;3.2、Server 回复&#…

找取照片上的25个特征点,并保存结果

找取照片上的25个特征点&#xff0c;并保存结果 import numpy as np import cv2 from matplotlib import pyplot as plt img cv2.imread(E:\Python-workspace\OpenCV\OpenCV/water1.png,1)#第一个参数为选择照片的路径&#xff0c;注意照片路径最后一个为正斜杠其他都为反斜杠…

nutsdb与mysql_分享下 nutsdb 单机 1 亿、10 亿数据实测

大家好&#xff0c; 想给大家分享下我最近为 nutsdb 做的数据测试。测试项目起因事情起因是这个 issue &#xff0c;简单说就是内存高了&#xff0c;不够用了。可能很多人不知道 NutsDB。简单介绍下&#xff0c;NutsDB 是我几个月以前开源的一个 Go 语言编写的内嵌型 KV 数据库…

java 方法 示例_带有示例的Java EnumSetSupplementOf()方法

java 方法 示例EnumSet类complementOf()方法 (EnumSet Class complementOf() method) complementOf() method is available in java.util package. clipartOf()方法在java.util包中可用。 complementOf() method is used to contain all the elements of this EnumSet that are…

在需要时开启Perl新特性

从5.10开始&#xff0c;新特性必须开启才能使用。Perl默认不启用新特性保持向后兼容。 如果想启用新特性&#xff0c;可以使用新的-E开关。打开所有的新特性。 % perl5.10.1 -E say.pl #开启5.10.1 版本的所有新特性 在源代码中使用 use 指令之后指定perl版本号就可以了。 use …

P2P技术详解(一):NAT详解——详细原理、P2P简介

目录1. IPv4协议和NAT的由来2. NAT的工作模型和特点2.1、NAT的概念模型2.2、一对一的NAT2.3、一对多的NAT2.4、按照NAT端口映射方式分类2.4.1全锥形NAT2.4.2限制锥形NAT2.4.3端口限制锥形NAT2.4.4对称型NAT3. NAT的限制与解决方案3.1、IP端到端服务模型3.2、NAT的弊端3.3、NAT穿…

决定孩子命运的八大关键问题

你可以不是天才&#xff0c;但你可以是天才的父母&#xff01;树立做父母正确的家庭教育观念&#xff0c;为孩子建造一个良好的人生平台&#xff0c;让孩子有很好的人格修养&#xff0c;懂得做人&#xff0c;懂得成功的真正含义。简单方便&#xff0c;容易操作&#xff0c;适合…

java calendar_Java Calendar internalGet()方法与示例

java calendar日历类internalGet()方法 (Calendar Class internalGet() method) internalGet() method is available in java.util package. internalGet()方法在java.util包中可用。 internalGet() method is used to get the value of the given field(fi) of this Calendar …

显示照片的二维直方图

显示照片的二维直方图 import cv2 from matplotlib import pyplot as plt img cv2.imread(E:\Python-workspace\OpenCV\OpenCV/water1.png,1)#第一个参数为选择照片的路径&#xff0c;注意照片路径最后一个为正斜杠其他都为反斜杠&#xff1b;第二个参数&#xff0c;其中1表示…

周五怎么表示 mysql_完美起航-MySQL找每个月最后一个星期五--函数定义与使用

数据库作业有一道题是这样子的&#xff1a;有一张名叫emp的表记录员工信息&#xff0c;其中有如下字段 HIREDATE 表示员工被雇用的日期&#xff1a;然后问题是这样的&#xff1a;q7.Show details of employee hiredates and the date of their first payday.(Paydays occur on…

要想能安心,必须先死心。

其实&#xff0c;不论是感情&#xff0c;还是学习、工作还是生活&#xff0c;不都是如此&#xff1f;曾经年少怀抱一个名校梦&#xff0c;如果高考不成功&#xff0c;那么你一定会选择考研让自己死一次心&#xff1b;小时候特别喜欢 某个职业&#xff0c;长大了你抛弃所有机会追…

silverlight学习总结【完】

以下内容是个人理解&#xff0c;不保证正确性。且假设使用C#&#xff0c;并且有一定的相关知识和XML基础。 silverlight是什么&#xff0c;能做什么 silverlight用XAML来做前端界面&#xff0c;用.NET或者JS作为程序脚本支持&#xff0c;在浏览器内外运行的应用。可以认为和FLA…

P2P技术详解(二):P2P中的NAT穿越(打洞)方案详解

目录1、内容概述2、反向链接技术&#xff1a;一种特殊的P2P场景&#xff08;通信双方中只有一方位于NAT设备之后&#xff09;3、基于UDP协议的P2P打洞技术详解3.1、原理概述3.2、典型P2P情景1&#xff1a; 两客户端位于同一NAT设备后面&#xff08;即相同内网中&#xff09;3.3…

Java Byte类的compareTo()方法和示例

简短的类compareTo()方法 (Short class compareTo() method) compareTo() method is available in java.lang package. compareTo()方法在java.lang包中可用。 compareTo() method is used to check equality or inequality for this Byte object against the given Byte objec…