RTP协议解析和H264码流提取

RTSP传输H265码流的一些事情:h265帧解析、rtp封包、sdp生成 RTSP传输H265码流的一些事情:h265帧解析、rtp封包、sdp生成 最近在海思的板子上做一个rtsp服务器的验证demo,大概架构是: 摄像头-->VI-->VPSS-->VENC-->RTSP Server->RTSP Client RTSP Server之前的配置只需要根据SDK里面的demo修改一下就行,这里只说后两个阶段。因为之前只搞过h264码流,对h265(HEVC)不太熟,查了不少资料,记录一下。 1、h265帧解析 参考:The difference 阅读详情

一、 h264基础概念

SODB: 数据比特串-->最原始的编码数据

RBSP: 原始字节序列载荷-->在SODB的后面填加了结尾比特(RBSP trailing bits 一个bit“1”)若干比特“0”,以便字节对齐。

EBSP: 扩展字节序列载荷– >在RBSP基础上填加了仿校验字节(0X03)它的原因是: 在NALU加到Annexb上时,需要填加每组NALU之前的开始码 StartCodePrefix,如果该NALU对应的slice为一帧的开始则用4位字节表示,ox00000001,否则用3位字节表示 ox000001.
为了使NALU主体中不包括与开始码相冲突的,在编码时,每遇到两个字节连续为0,就插入一个字节的0x03。解码时将0x03去掉。 也称为脱壳操作。

H.264的功能分为两层,视频编码层(VCL)和网络提取层(NAL)
VCL数据即被压缩编码后的视频数据序列。把VCL数据要封装到NAL单元中之后,才可以用来传输或存储。NAL单元格式如下图:
这里写图片描述

H.264 的编码视频序列包括一系列的NAL 单元,每个NAL 单元包含一个RBSP,见表1。编码片(包括数据分割片IDR 片)和序列RBSP 结束符被定义为VCL NAL 单元,其余为NAL 单元。典型的RBSP 单元序列如图2 所示。每个单元都按独立的NAL 单元传送。单元的信息头(一个字节)定义了RBSP 单元的类型,NAL 单元的其余部分为RBSP 数据。

这里写图片描述

NAL单元

每个NAL单元是一个一定语法元素的可变长字节字符串,包括包含一个字节的头信息(用来表示数据类型),以及若干整数字节的负荷数据。一个NAL单元可以携带一个编码片、A/B/C型数据分割或一个序列或图像参数集。

NALU 头由一个字节组成, 它的语法如下:
这里写图片描述

  NAL单元按RTP序列号按序传送。其中,T为负荷数据类型,占5bit;R为重要性指示位,占2个bit;最后的F为禁止位,占1bit。具体如下:
  (1)NALU类型位
  可以表示NALU的32种不同类型特征,类型1~12是H.264定义的,类型24~31是用于H.264以外的,RTP负荷规范使用这其中的一些值来定义包聚合和分裂,其他值为H.264保留。
  (2)重要性指示位
  用于在重构过程中标记一个NAL单元的重要性,值越大,越重要。值为0表示这个NAL单元没有用于预测,因此可被解码器抛弃而不会有错误扩散;值高于0表示此NAL单元要用于无漂移重构,且值越高,对此NAL单元丢失的影响越大。
  (3)禁止位
编码中默认值为0,当网络识别此单元中存在比特错误时,可将其设为1,以便接收方丢掉该单元,主要 用于适应不同种类的网络环境(比如有线无线相结合的环境)。

264常见的帧头数据为:

00 00 00 01 67 (SPS)

00 00 00 01 68 (PPS)

00 00 00 01 65 ( IDR 帧)

00 00 00 01 61 (P帧)

等等,那么他们代表的意思是什么呢?

上述的67,68,65,61,还有41等,都是该NALU的识别级别。

F:禁止为,0表示正常,1表示错误,一般都是0

NRI:重要级别,11表示非常重要。

TYPE:表示该NALU的类型是什么,

见下表,由此可知7为序列参数集(SPS),8为图像参数集(PPS),5代表I帧。1代表非I帧。

由此可知,61和41其实都是P帧(type值为1),只是重要级别不一样(它们的NRI一个是11BIN,一个是10BIN)

NALU类型是我们判断帧类型的利器,从官方文档中得出如下图:

这里写图片描述

H264(NAL简介与I帧判断)

这里写图片描述

我们还是接着看最上面图的码流对应的数据来层层分析,以00 00 00 01分割之后的下一个字节就是NALU类型,将其转为二进制数据后,

解读顺序为从左往右算,如下:

(1)第1位禁止位,值为1表示语法出错

(2)第2~3位为参考级别

(3)第4~8为是nal单元类型

例如上面00000001后有67,68以及65

其中0x67的二进制码为:

0110 0111

4-8为00111,转为十进制7,参考第二幅图:7对应序列参数集SPS

其中0x68的二进制码为:

0110 1000
4-8为01000,转为十进制8,参考第二幅图:8对应图像参数集PPS

其中0x65的二进制码为:

011 00101

4-8位为00101,转为十进制5,参考第二幅图:5对应IDR图像中的片(I帧)

所以判断是否为I帧的算法为:

(NALU类型 & 0001 1111) = 5 即 (NALU类型 & 31) = 5
比如0x65 & 31 = 5

二、RTP Header解析

 

1)        V:RTP协议的版本号,占2位,当前协议版本号为2

2)        P:填充标志,占1位,如果P=1,则在该报文的尾部填充一个或多个额外的八位组,它们不是有效载荷的一部分。

3)        X:扩展标志,占1位,如果X=1,则在RTP报头后跟有一个扩展报头

4)        CC:CSRC计数器,占4位,指示CSRC 标识符的个数

5)        M: 标记,占1位,不同的有效载荷有不同的含义,对于视频,标记一帧的结束;对于音频,标记会话的开始。

6)        PT: 有效荷载类型,占7位,用于说明RTP报文中有效载荷的类型,如GSM音频、JPEM图像等,在流媒体中大部分是用来区分音频流和视频流的,这样便于客户端进行解析。

7)        序列号:占16位,用于标识发送者所发送的RTP报文的序列号,每发送一个报文,序列号增1。这个字段当下层的承载协议用UDP的时候,网络状况不好的时候可以用来检查丢包。同时出现网络抖动的情况可以用来对数据进行重新排序,序列号的初始值是随机的,同时音频包和视频包的sequence是分别记数的。

8)        时戳(Timestamp):占32位,必须使用90 kHz 时钟频率。时戳反映了该RTP报文的第一个八位组的采样时刻。接收者使用时戳来计算延迟和延迟抖动,并进行同步控制。

9)        同步信源(SSRC)标识符:占32位,用于标识同步信源。该标识符是随机选择的,参加同一视频会议的两个同步信源不能有相同的SSRC。

10)    特约信源(CSRC)标识符:每个CSRC标识符占32位,可以有0~15个。每个CSRC标识了包含在该RTP报文有效载荷中的所有特约信源。

注:基本的RTP说明并不定义任何头扩展本身,如果遇到X=1,需要特殊处理

 

使用Wireshark抓一段码流进行分析

 

其中,

80                    是V_P_X_CC

60                    是M_PT

00 01              是SequenceNum

00 00  00 00  是Timestamp
39 6e d3 46  是SSRC

把前两字节换成二进制如下

1000 0000 0110 0000

按顺序解释如下:

10               是V;

0                 是P;

0                 是X;

0000          是CC;

0                 是M;

110 0000   是PT;

三、RTP荷载H264码流

 +---------------+
  |0|1|2|3|4|5|6|7|
  +-+-+-+-+-+-+-+-+
  |F|NRI|  Type   |
  +---------------+

荷载格式定义三个不同的基本荷载结构,接收者可以通过RTP荷载的第一个字节后5位(如上图参考RFC3984)识别荷载结构。

1)   单个NAL单元包:荷载中只包含一个NAL单元。NAL头类型域等于原始 NAL单元类型,即在范围1到23之间

2)   聚合包:本类型用于聚合多个NAL单元到单个RTP荷载中。本包有四种版本,单时间聚合包类型A (STAP-A),单时间聚合包类型B (STAP-B),多时间聚合包类型(MTAP)16位位移(MTAP16), 多时间聚合包类型(MTAP)24位位移(MTAP24)。赋予STAP-A, STAP-B, MTAP16, MTAP24的NAL单元类型号分别是 24,25, 26, 27

3)   分片单元:用于分片单个NAL单元到多个RTP包。现存两个版本FU-A,FU-B,用NAL单元类型 28,29标识

常用的打包时的分包规则是:如果小于MTU采用单个NAL单元包,如果大于MTU就采用FUs分片方式。因为常用的打包方式就是单个NAL包和FU-A方式,所以我们只解析这两种。

3.1 单个NAL单元包

 0                   1                   2                   3
   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |F|NRI|  type   |                                               |
  +-+-+-+-+-+-+-+-+                                               |
  |                                                               |
  |               Bytes 2..n of a Single NAL unit                 |
  |                                                               |
  |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |                               :...OPTIONAL RTP padding        |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

定义在此的NAL单元包必须只包含一个。这意味聚合包和分片单元不可以用在单个NAL 单元包中。并且RTP序号必须符合NAL单元的解码顺序。NAL单元的第一字节和RTP荷载头第一个字节重合。(如上图参考RFC3984)打包H264码流时,只需在帧前面加上12字节的RTP头即可。

3.2 分片单元(FU-A)

  0                   1                   2                   3
   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  | FU indicator  |   FU header  |                               |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
  |                                                               |
  |                         FU payload                            |
  |                                                               |
  |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |                               :...OPTIONAL RTP padding        |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                                 图 1

分片只定义于单个NAL单元不用于任何聚合包。NAL单元的一个分片由整数个连续NAL单元字节组成。每个NAL单元字节必须正好是该NAL单元一个分片的一部分。相同NAL单元的分片必须使用递增的RTP序号连续顺序发送(第一和最后分片之间没有其他的RTP包)。相似,NAL单元必须按照RTP顺序号的顺序装配。

   当一个NAL单元被分片运送在分片单元(FUs)中时,被引用为分片NAL单元。STAPs,MTAPs不可以被分片。 FUs不可以嵌套。 即, 一个FU 不可以包含另一个FU。运送FU的RTP时戳被设置成分片NAL单元的NALU时刻。

图 1表示FU-A的RTP荷载格式。FU-A由1字节的分片单元指示(如图2),1字节的分片单元头(如图3),和分片单元荷载组成。

  +---------------+
  |0|1|2|3|4|5|6|7|
  +-+-+-+-+-+-+-+-+
  |F|NRI|  Type   |
  +---------------+
        图 2

FU指示字节的类型域Type=28表示FU-A。。NRI域的值必须根据分片NAL单元的NRI域的值设置。

 +---------------+
  |0|1|2|3|4|5|6|7|
  +-+-+-+-+-+-+-+-+
  |S|E|R|  Type   |
  +---------------+
         图 3

S: 1 bit 当设置成1,开始位指示分片NAL单元的开始。当跟随的FU荷载不是分片NAL单元荷载的开始,开始位设为0。

E: 1 bit 当设置成1, 结束位指示分片NAL单元的结束,即, 荷载的最后字节也是分片NAL单元的最后一个字节。当跟随的 FU荷载不是分片NAL单元的最后分片,结束位设置为0。

R: 1 bit 保留位必须设置为0,接收者必须忽略该位

打包时,原始的NAL头的前三位为FU indicator的前三位,原始的NAL头的后五位为FU header的后五位。

 

使用Wireshark抓一段码流进行分析

前12字节是RTP Header
7c是FU indicator
85是FU Header
FU indicator(0x7C)和FU Header(0x85)换成二进制如下
0111 1100 1000 0101

按顺序解析如下:

0                            是F

11                          是NRI

11100                    是FU Type,这里是28,即FU-A

1                            是S,Start,说明是分片的第一包

0                            是E,End,如果是分片的最后一包,设置为1,这里不是

0                            是R,Remain,保留位,总是0

00101                   是NAl Type,这里是5,说明是关键帧(不知道为什么是关键帧请自行谷歌)

打包时,FUindicator的F、NRI是NAL Header中的NRI,Type是28;FU Header的S、E、R分别按照分片起始位置设置,Type是NAL Header中的Type。

解包时,取FU indicator的前三位和FU Header的后五位,即0110 0101(0x65)为NAL类型(即I帧)。

Refrences:

http://blog.youkuaiyun.com/machh/article/details/52165292

H264码流结构分析 1、码流总体结构: h264的功能分为两层,视频编码层(VCL)和网络提取层(NAL)。H.264 的编码视频序列包括一系列的NAL 单元,每个NAL 单元包含一个RBSP。一个原始的H.264 NALU 单元常由 [StartCode] [NALU Header] [NALU Payload] 三部分组成,其中 Start Code 用于标示这是一个NALU 单元的开始,必须是"00 00 0 阅读详情

相关推荐

H264码流格式解析及RTP打包规则整理

1、H264的结构图 2、H264的编码分层 H.264原始码流(裸流)是由一个接一个NALU组成,它的功能分为两层,VCL(视频编码层)和 NAL(网络提取层). (1)NAL层 (视频数据网络抽象层) 因为H264最终还是要在网络上进行传输,在传输的时候,网络包的最大传输单元是1500字节,一个H264的帧往往是大于1500字节的,所以需要将一个帧拆成多个包进行传输。这些拆包、组包等工作都在NAL层去处理。VCL数据要在网络上传输或者存储到磁...

luoyaxing0812的专栏 4108

Rtsp之H265解析

以前做过Rtsp接收H264的视频流,最近在研究H265视频流,发现在码流解析上面,还是有一点区别。 参考文献 https://tools.ietf.org/html/draft-ietf-payload-rtp-h265-14 分两种情况: 1.不需要rtp分包的,直接保存rtp数据即可。 2、需要rtp分包的,直接上码流: 情况1:不需要分包  前面两个字节 00 01 =...

5782

RTP 协议解包为 H264 裸流

RTP 协议解包为 H264裸流 一. 为什么使用 RTP 协议? TCP 传输流媒体数据由于其可靠性,会造成很大的网络延时和卡顿。 UDP 传输由于其不可靠性,会导致丢帧,如果是关键帧,则会花屏一个序列的时长。 RTP 使用了 RTP 和 RTCP 两个子协议来完成。 RTP 使用 UDP 完成流媒体数据传输,保证其时效性。 RTCP 也是使用 UDP,但只传输控制信息,占带宽很小,此时上层...

pang_gua的博客 5176

RTP协议全解析(H264码流和PS流)

1RTP Header解析 2、RTP荷载H264码流 2.1、单个NAL单元包 2.2、分片单元(FU-A) 3、RTP荷载PS流 3.1、PS包头 3.2、系统标题 3.3、节目映射流 3.4、PES分组头部

对牛乱弹琴 27万+

RTP协议详解

1.什么是RTP 数据传输协议RTP,用于实时传输数据。RTP全名是Real-time Transport Protocol(实时传输协议)。它是IETF提出的一个标准,对应的RFC文档为RFC3550。RFC3550不仅定义了RTP,而且定义了配套的相关协议RTCP(Real-time Transport Control Protocol,即实时传输控制协议)。RTP用来为IP网上的语音、图像、传真等多种需要实时传输的多媒体数据提供端到端的实时传输服务。RTP为Internet上端到端的实时传输提..

流媒体巅峰之路 2万+

【流媒体】基于RTP协议的H264码流发送器和接收器

RTP(Real-time Transport Protocol,实时传输协议)是一种网络协议,用于在IP网络上传输实时数据,如音频、视频等。它的主要目的是提供一种可靠的、面向数据包的传输机制,以支持实时多媒体应用。无连接RTP协议本身不保证数据的可靠传输,它只是负责将数据包从发送端发送到接收端,而不关心数据包是否按顺序到达或者是丢失面向数据包RTP协议适用于传输数据包,而不是连续的数据流。这意味着它可以处理任意大小的数据包,而不需要预先建立连接时间戳。

weixin_42877471的博客 1563

VLC,FFMPEG, RTP,28181 学习 网址做了个汇总

  https://blog.youkuaiyun.com/zhouyongku/article/details/41546789  海康RTSP客户端连接深入分析  http://www.avahi.org/doxygen/html/client-publish-service_8c-example.html  HTTP服务实现 https://blog.youkuaiyun.com/altermanzhu/ar...

DANFBAORE的博客 2276

网络摄像机(IPC)开发(7):RTP协议解析(H264码流)

一、RTP(实时传输协议) RTP全名是Real-time Transport Protocol(实时传输协议),它是IETF提出的一个标准,对应的RFC文档为RFC3550(RFC1889为其过期版本),RFC3550不仅定义了RTP,而且定义了配套的相关协议RTSP,RTP用来为IP网上的语音、图像、传真等多种需要实时传输的多媒体数据提供端到端的实时传输服务,RTP为Internet上...

ProYuan的博客 3969

详解RTSP协议和H264码流进行RTP封装,并分析实现传输h264的RSTP服务器

本篇为实现一个基于UDP的RTP传输H264的RTSP服务器,并能够进行rtsp拉流播放,并会介绍RTSP协议,RTP协议,RTCP协议,H264码流以及如何将H264码流进行RTP封装。

m0_63174159的博客 4905

H264码流RTP封装方式详解

在流媒体传输领域,经常使用的传输协议是RTP/RTCP,本文将对RTP对H264进行封装的过程进行详解

技术控的笔记 21万+

从零开始:用这些公开数据集搞定电力AI项目(含鸟巢、绝缘子、负荷预测等33个实战资源)

本文系统梳理了电力AI领域33个精选公开数据集,涵盖目标检测、负荷预测等关键场景,如鸟巢检测、绝缘子缺陷识别等。通过实战案例解析数据预处理、模型选型及性能优化策略,帮助工程师快速构建端到端解决方案,解决电力AI项目中的数据获取与处理难题。

weixin_42522552的博客 220

使用RTP包荷载H264码流数据

在音视频通话中我们通常使用 RTP 协议包荷载音视频码流数据,例如用户摄像头采集图像后进行编码成帧,再将帧数据拆分到 RTP 协议包后发送到流媒体服务器,本文将介绍如何使用 JRTPLIB 发送 H264 码流数据。

椛茶的博客 5290

基于单片机红外线遥控Proteus仿真电路发射接收

*单片机设计介绍,基于单片机红外线遥控Proteus仿真电路发射接收。

2201_75940997的博客 3943

FFmpeg发送RTP封包的H264

7).序列号(SN):占16位,用于标识发送者所发送的RTP报文的序列号,每发送一个报文,序列号增1。接收端可以据此检测丢包和重建包序列,当下层的承载协议用UDP的时候,网络状况不好的时候可以用来检查丢包,同时出现网络抖动的情况可以用来对数据进行重新排序,序列号的初始值是随机的,同时音频包和视频包的sequence是分别记数的。2).填充位(P):填充标志,占1位,如果P=1,则该RTP包的尾部就包含附加的填充字节,在该报文的尾部填充一个或多个额外的八位组,它们不是有效载荷的一部分。

ihungry的专栏 2715

STM32 RTC_WaitForSynchro()死循环问题分析与LSI时钟优化实践

本文深入分析了STM32使用LSI时钟源时,调用RTC_WaitForSynchro()函数陷入死循环的根本原因。问题核心在于RTC时钟域未正确使能,导致硬件同步标志RSF无法置位。文章提供了通过显式调用RCC_RTCCLKCmd(ENABLE)函数启用RTC时钟总开关的解决方案,并分享了编写健壮RTC/BKP初始化代码、增加超时机制等最佳实践,确保系统稳定运行。

weixin_29185493的博客 512

Cadence17.2 > Allegro > 检查PCB Layout信号线组等长

Cadence17.2 > Allegro > 检查PCB Layout等长和配线

DL_62532的专栏 1万+
上一篇: 海康摄像机、NVR、流媒体服务器、回放取流RTSP地址规则说明
下一篇: 双目立体视觉匹配算法-----SAD匹配算法、BM算法、SGBM算法、GC算法
zero_china
博客等级 码龄16年 10粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值