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

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

如果你需要这些资料,可以戳这里获取

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

17 65 62 a1 f1 44 dc df 4b 4a 38 aa 96 b7 dd 24 .eb??D??KJ8???$
前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中的F、NRI,Type是28;FU Header的S、E、R分别按照分片起始位置设置,Type是NAL Header中的Type。

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

3、RTP荷载PS流

针对H264 做如下PS 封装:每个IDR NALU 前一般都会包含SPS、PPS 等NALU,因此将SPS、PPS、IDR 的NALU 封装为一个PS 包,包括ps 头,然后加上PS system header,PS system map,PES header+h264 raw data。所以一个IDR NALU PS 包由外到内顺序是:PSheader| PS system header | PS system Map | PES header | h264 raw data。对于其它非关键帧的PS 包,就简单多了,直接加上PS头和PES 头就可以了。顺序为:PS header | PES header | h264raw data。以上是对只有视频video 的情况,如果要把音频Audio也打包进PS 封装,也可以。当有音频数据时,将数据加上PES header 放到视频PES 后就可以了。顺序如下:PS 包=PS头|PES(video)|PES(audio),再用RTP 封装发送就可以了。

GB28181 对RTP 传输的数据负载类型有规定(参考GB28181 附录B),负载类型中96-127

RFC2250 建议96 表示PS 封装,建议97 为MPEG-4,建议98 为H264

即我们接收到的RTP 包首先需要判断负载类型,若负载类型为96,则采用PS 解复用,将音视频分开解码。若负载类型为98,直接按照H264 的解码类型解码。

注:此方法不一定准确,取决于打包格式是否标准

PS 包中的流类型(stream type)的取值如下:

1)        MPEG-4 视频流: 0x10;

2)        H.264 视频流: 0x1B;

3)        SVAC 视频流: 0x80;

4)        G.711 音频流: 0x90;

5)        G.722.1 音频流: 0x92;

6)        G.723.1 音频流: 0x93;

7)        G.729 音频流: 0x99;

  1. SVAC音频流: 0x9B。

3.1、PS包头

图7

1)        Pack start code:包起始码字段,值为0x000001BA的位串,用来标志一个包的开始。

2)        System clock reference base,system clock reference extenstion:系统时钟参考字段。

3)        Pack stuffing length :包填充长度字段,3 位整数,规定该字段后填充字节的个数

80 60 53 1f 00 94 89 00 00 0000 00 00 00 01 ba €`S…??..?

7e ff 3e fb 44 01 00 5f 6b f8 00 00 01 e0 14 53 ~.>?D…_k?..?.S

80 80 05 2f bf cf bed1 1c 42 56 7b 13 58 0a 1e €€./???.BV{.X…

08 b1 4f 33 69 35 0453 6d 33 a8 04 15 58 d9 21 .?O3i5.Sm3?..X?!

9741 b9 f1 75 3d 94 2b 1f bc 0b b2 b4 97 bf 93 ?A??u=?+.?.???

前12位是RTP Header,这里不再赘述;

000001ba是包头起始码;

接下来的9位包括了SCR,SCRE,MUXRate,具体看图7

最后一位是保留位(0xf8),定义了是否有扩展,二进制如下

1111 1000

前5位跳过,后3位指示了扩展长度,这里是0.

3.2、系统标题

图8

Systemheader当且仅当pack是第一个数据包时才存在,即PS包头之后就是系统标题。取值0x000001BB的位串,指出系统标题的开始,暂时不需要处理,读取Header Length直接跳过即可。

3.3、节目映射流

system Map也是当且仅当pack是第一个数据包时才存在,即系统标题之后就是节目流映射。取值0x000001BC的位串,指出节目流映射的开始,暂时不需要处理,读取Header Length直接跳过即可。前5字节的结构同系统标题,见图8。

取一段码流分析系统标题和节目映射流

00 00 01 ba 45 a9 d4 5c 34 0100 5f 6b f8 00 00  …?E??\4…_k?..

01 bb 00 0c 80 cc f5 04 e1 7f e0 e0 e8 c0 c0 20  .?..€??.?.???

00 00 01 bc 00 1e e1 ff00 00 00 18 1b e0 00 0c …?..?..?..

2a 0a 7f ff 00 00 0708 1f fe a0 5a 90 c0 00 00  *…??Z??..

00 00 00 00 00 00 01 e0 7f e0 80 80 0521 6a 75  …?.?€€.!ju

前14个字节是PS包头(注意,没有扩展);

接下来的00 00 01 bb是系统标题起始码;

接下来的00 0c说明了系统标题的长度(不包括起始码和长度字节本身);

接下来的12个字节是系统标题的具体内容,这里不做解析;

继续看到00 00 01 bc,这是节目映射流起始码;

紧接着的00 1e同样代表长度;

跳过e1 ff,基本没用;

接着2个字节代表program_stream_info长度,这里是00 00,即便有值,一般也可以直接跳过;

接下来是00 18,代表基本流长度,说明了后面还有24个字节;

接下来的1b,意思是H264编码格式;

下一个字节e0,意思是视频流;

接下里00 0c,同样代表接下的长度12个字节;

跳过这12个字节,看到90,这是G.711音频格式;

下一个字节是c0,代表音频流;

接下来的00 00同样代表长度,这里是0;

接下来4个字节是CRC,循环冗余校验。

到这里节目映射流解析完毕。(好累)。

原创不易,转载请附上链接,谢谢RTP协议全解析(H264码流和PS流)_对牛乱弹琴-CSDN博客_ps流

好戏还在后头呢。

3.4、PES分组头部

图9

别被这么长的图吓到,其实原理相同,但是,你必须处理其中的每一位。

1)        Packet start code prefix:值为0x000001的位串,它和后面的stream id 构成了标识分组开始的分组起始码,用来标志一个包的开始。

2)        Stream id:在节目流中,它规定了基本流的号码和类型。0x(C0DF)指音频,0x(E0EF)为视频

3)        PES packet length:16 位字段,指出了PES 分组中跟在该字段后的字节数目。值为0 表示PES 分组长度要么没有规定要么没有限制。这种情况只允许出现在有效负载包含来源于传输流分组中某个视频基本流的字节的PES 分组中。

4)        PTS_DTS:2 位字段。当值为’10’时,PTS 字段应出现在PES 分组标题中;当值为’11’时,PTS 字段和DTS 字段都应出现在PES 分组标题中;当值为’00’时,PTS 字段和DTS 字段都不出现在PES分组标题中。值’01’是不允许的。

5)        ESCR:1位。置’1’时表示ESCR 基础和扩展字段出现在PES 分组标题中;值为’0’表示没有ESCR 字段。

6)        ESrate:1 位。置’1’时表示ES rate 字段出现在PES 分组标题中;值为’0’表示没有ES rate 字段。

7)        DSMtrick mode:1 位。置’1’时表示有8 位特技方式字段;值为’0’表示没有该字段。

8)        Additionalinfo:1 位。附加版权信息标志字段。置’1’时表示有附加拷贝信息字段;值为’0’表示没有该字段。

9)        CRC:1 位。置’1’时表示CRC 字段出现在PES 分组标题中;值为’0’表示没有该字段。

10)    Extensionflag:1 位标志。置’1’时表示PES 分组标题中有扩展字段;值为’0’表示没有该字段。

PES header data length: 8 位。PES 标题数据长度字段。指出包含在PES 分组标题中的可选字段和任何填充字节所占用的总字节数。该字段之前的字节指出了有无可选字段。

老规矩,上码流:

00 00 01 e0 21 33 80 80 05 2b 5f df 5c 95 71 84 …?!3€€.+_??q?

aa e4 e9 e9 ec 40 cc17 e0 68 7b 23 f6 89 df 90 ???@?.?h{#???

a9d4 be 74 b9 67 ad 34 6d f0 92 0d 5a 48 dd 13 ???t?g?4m??.ZH?.

00 00 01是起始码;

e0是视频流;

21 33 是帧长度;

接下来的两个80 80见下面的二进制解析;

下一个字节05指出了可选字段的长度,前一字节指出了有无可选字段;

接下来的5字节是PTS;

第7、8字节的二进制如下:

1000 0000 1000 0000

按顺序解析:

第7个字节:

10                         是标志位,必须是10;

00                         是加扰控制字段,‘00’表示没有加密,剩下的01,10,11由用户自定义;

0                           是优先级,1为高,0为低;

0                           是数据对齐指示字段;

0                           是版权字段;

0                           是原始或拷贝字段。置’1’时表示相关PES分组有效负载的内容是原始的;'0’表示内容是一份拷贝;

第8个字节:

10                         是PTS_DTS字段,这里是10,表示有PTS,没有DTS;

0                           是ESCR标志字段,这里为0,表示没有该段;

0                           是ES速率标志字段,,这里为0,表示没有该段;

0                           是DSM特技方式标志字段,,这里为0,表示没有该段;

0                           是附加版权信息标志字段,,这里为0,表示没有该段;

0                           是PESCRC标志字段,,这里为0,表示没有该段;

0                           是PES扩展标志字段,,这里为0,表示没有该段;

本段码流只有PTS,贴一下解析函数

unsigned long parse_time_stamp (const unsigned char *p)
{
    unsigned long b;
    //共33位,溢出后从0开始
    unsigned long val;

    //第1个字节的第5、6、7位
    b = *p++;
    val = (b & 0x0e) << 29;

    //第2个字节的8位和第3个字节的前7位
    b = (*(p++)) << 8;
    b += *(p++);
    val += ((b & 0xfffe) << 14);

    //第4个字节的8位和第5个字节的前7位
    b = (*(p++)) << 8;
    b += *(p++);
    val += ((b & 0xfffe) >> 1);

    return val;
}

其他字段可参考协议解析

ps:

遇到00 00 01 bd的,这个是海康私有流的标识,可以丢弃。丢弃之后就看不到原视频里移动侦测时闪烁的红框。

ps:

另外,有的hk摄像头回调然后解读出来的原始h.264码流,有的一包里只有分界符数据(nal_unit_type=9)或补充增强信息单元(nal_unit_type=6),如果直接送入解码器,有可能会出现问题,这里的处理方式要么丢弃这两个部分,要么和之后的数据合起来,再送入解码器里,如有遇到的朋友可以交流一下:)

写在后面:

第一次发原创,在这里感谢  @cmengwei  的无私帮助,提供了很多帮助,非常感谢。

文档我都放在了我的资源里面,有1个下载积分,大家不要吝啬,绝对值得!

《RTP Payload Format for H.264 Video》

rfc3984(For264).txt_PS流-互联网文档类资源-CSDN下载.txt_PS流-互联网文档类资源-CSDN下载")

《MPEG2-2(13818中文版)》

MPEG2-2(13818中文版)_mpeg2-C++文档类资源-CSDN下载_mpeg2-C++文档类资源-CSDN下载")

RTP荷载H264的代码参考:

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

如果你需要这些资料,可以戳这里获取

G2-2(13818中文版)_mpeg2-C++文档类资源-CSDN下载](https://bbs.csdn.net/topics/618679757)_mpeg2-C++文档类资源-CSDN下载")

RTP荷载H264的代码参考:

[外链图片转存中…(img-hh9Gg5RZ-1715903385154)]
[外链图片转存中…(img-JOzVSmA6-1715903385154)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

如果你需要这些资料,可以戳这里获取

  • 25
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值