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

news2024/11/17 14:25:18

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位,可以有0~15个。每个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。

★文末名片可以免费领取音视频开发学习资料,内容包括(FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。

见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

例如:

有三个信号源各发出一路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包的一方来说,尽可能找简单的打包方式。对于接受端则需要适配各种发送

端的打包方式,因为无法决定输入源的打包方式。

(打包的时候不要搞太复杂的模式)

我们对于NALU的长度<=1400(rtp payload size)的则采用的是单一NALU打包到单一的RTP

包中;

我们对于NALU的长度>1400的则采用了FU-A的方式进行了打包,这种就是把一个大的NALU进

行了切分,最后接收方则进行了合并,把多个RTP包合并成一个完整的NALU即可;

为什么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;

★文末名片可以免费领取音视频开发学习资料,内容包括(FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。

见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

 

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

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

相关文章

【GD32F427开发板试用】INA226完成电流电压采集

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;จุ๊บ冰语 前言 本次有幸参与并通过了极术社区组织的【GD32F427开发板试用】活动&#xff0c;让我对国产兆易创新的GD32处理器有了更深刻的…

Scala系列之:函数式编程

Scala系列之&#xff1a;函数式编程一、面向对象编程和函数式编程二、函数基本语法三、函数和方法的区别四、函数定义五、函数参数六、函数至简原则七、匿名函数一、面向对象编程和函数式编程 面向对象编程&#xff1a; 解决问题&#xff0c;分解对象&#xff0c;行为&#x…

【最新消息】苹果放出新大招??!!

各位开发者新年快乐&#xff0c;许久没有更新了&#xff0c;近期我收到反馈意思遇到苹果回复的新政策&#xff0c;不知道各位开发者有没有碰到过&#xff0c;我也会在下文提出我的猜测&#xff0c;要是有开发者也遇到了同样的问题&#xff0c;欢迎一起交流哦。 疑似新政策&…

【寒假每日一题】洛谷 P1088 [NOIP2004 普及组] 火星人

题目链接&#xff1a;P1088 [NOIP2004 普及组] 火星人 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目描述 人类终于登上了火星的土地并且见到了神秘的火星人。人类和火星人都无法理解对方的语言&#xff0c;但是我们的科学家发明了一种用数字交流的方法。这种交流方法是…

vue-query 初探

vue-query&#xff0c;类似于vuex/pinia&#xff0c;以缓存为目的&#xff0c;但侧重的是对网络请求的缓存。 这是我预想的使用场景&#xff1a;假设在各个页面都需要发起相同的请求&#xff0c;去获取数据&#xff0c;而这种数据在一定时间内不会发生变化&#xff0c;那么这种…

【JavaWeb】带你走进Maven

文章目录1 什么是Maven?2 Maven 常用命令3 Maven 生命周期4 Maven 坐标详解5 IDEA 导入 Maven 项目1 什么是Maven? 如今我们构建一个项目需要用到很多第三方的类库&#xff0c;如写一个使用Spring的Web项目就需要引入大量的jar包。一个项目Jar包的数量之多往往让我们瞠目结舌…

线程execute()与submit()区别

线程池中有两个提交任务的方法 向线程池提交任务的两种方式大致如下&#xff1a; 方式一&#xff1a;调用execute()方法 方式二&#xff1a;调用submit()方法 一、区别 以上的submit()和execute()两类方法的区别在哪里呢&#xff1f;大致有以下三点&#xff1a; 1.二者所接收…

引入“ 自动化测试 ”都需要满足哪些条件?

&#x1f4cc; 博客主页&#xff1a; 自动化软件测试 &#x1f4cc; 专注于软件测试领域相关技术实践和思考&#xff0c;持续分享自动化软件测试开发干货知识&#xff01; &#x1f4cc; 如果你也想学习软件测试&#xff0c;文末卡片有我的交流群&#xff0c;加入我们&#xff…

由浅入深,聊聊 LeakCanary 的那些事

引言 关于内存泄漏&#xff0c;Android 开发的小伙伴应该都再熟悉不过了&#xff0c;比如最常见的静态类间接持有了某个 Activity 对象&#xff0c;又比如某个组件库的订阅在页面销毁时没有及时清理等等&#xff0c;这些情况下多数时都会造成内存泄漏&#xff0c;从而对我们Ap…

linux内核-内存管理

linux内核内存管理 注意&#xff01;内核空间和用户空间都是处于虚拟空间中 Linux的虚拟地址空间范围为0&#xff5e;4G&#xff0c;Linux内核将这4G字节的空间分为两部分 内核空间&#xff1a; 最高的1G字节&#xff08;从虚拟地址0xC0000000到0xFFFFFFFF&#xff09;&…

RTSP,RTP,RTCP协议

一 RTSP 1 简介 实时流传输协议&#xff0c;是一个应用层协议&#xff08;TCP/IP网络体系中&#xff09;&#xff0c;它是一个多媒体播放控制协议&#xff0c;主要用来使用户在播放流媒体时可以像操作本地的影碟机一样进行控制&#xff0c;即可以对流媒体进行暂停/继续、后退和…

SAP FICO 关于资产的详细解析

SAP资产模块概述 一、概述 资产&#xff08;AA&#xff09;模块是资产会计模块的简称&#xff0c;是财务会计&#xff08;FI&#xff09;模块的一个子模块&#xff0c;主要处理与各类长期资产相关业务的模块。不单指固定资产&#xff0c;也不泛指资产负债表中的资产&#xff0c…

Week4

1.试题 历届真题 时间显示【第十二届】【省赛】【B组】 思路 不难发现,应该从小时往秒处理,这样可以用O(1)的时间复杂度求出,不过有比较麻烦的进位处理。 先看里面可以拼成几个小时,然后得到的小时%24,然后把总时间减去小时的时间,再看有多少分钟,分钟%60,都是此时判断分…

vue多环境配置之 .env配置文件

Vue之.env环境配置文件 .env文件是运行项目时的环境配置文件。但是在实际开发过程中&#xff0c;有本地环境、测试环境、预生产、生产环境等等&#xff0c;不同环境对应的配置会不一样。因此&#xff0c;需要通过不同的.env文件实现差异化配置。 * 文章目录Vue之.env环境配置文…

【JAVA核心知识】46:什么是零拷贝Zero-copy

零拷贝相较于传统的IO流程拥有更高的数据发送效率&#xff0c;无论是RocketMq,Kafka还是Netty等都用到了零拷贝技术&#xff0c;那究竟什么是零拷贝呢&#xff0c;零拷贝又是通过什么方式提升数据发送效率呢&#xff1f; 首先我们要明白&#xff0c;一次数据发送过程就是将磁盘…

Java基础--方法

前言&#xff1a;介绍 Java 中方法的基本语法、分类、执行并分析参数传值。 关键字&#xff1a;方法、形参、实参、返回值、实例方法、静态方法、参数传值 程序引例–为什么要「方法」 public class IntroduceOfMethod {// 入口主方法。public static void main(String[] args…

docker 高级篇

一、DockerFile 1.1、概述 dockerfile 是用来构建docker镜像的文本文件&#xff0c;是由一条条构建镜像所需的指令和参数构成的脚本。 为什么要有dockerfile呢 在基础篇我们讲过&#xff0c;比如我们下载个 ubuntu镜像里面不包含 vim、ifconfig等组件&#xff0c;这个时候 新增…

DES加密算法

DES算法原理 对称密码算法中的分组加密算法&#xff08;对应于流密码&#xff09; 密钥64位&#xff0c;56位参与运算8位校验位&#xff08;校验位为&#xff1a;8、16、24、32、40、48、56、64&#xff09; 加密原理 1. IP置换 将明文数据转化为二进制数&#xff0c;并将它…

Lnix文件权限的修改

首先我们要清楚Linux文件的权限信息 在Linux中输入ls -l 或者 ll查看文件和目录的详细信息 文件详情实例中&#xff0c;a目录的第一个属性用“d”标识这个a是一个目录。 anaconda-ks.cfg第一个属性用“-”标识他是一个文件。 在Linux文件详情的后面属性需要分为三组查看 rwx&am…

三种调用机制: 同步调用、异步调用、回调(同步/异步)

c并发编程-01-并发与并行_发如雪-ty的博客-CSDN博客 c并发编程02-什么是I/O_发如雪-ty的博客-CSDN博客 c并发编程03-I/O多路复用_发如雪-ty的博客-CSDN博客 c并发编程04-同步与异步_发如雪-ty的博客-CSDN博客_c同步和异步 c并发编程05-什么是回调函数_发如雪-ty的博客-CSDN…