H264码流进行RTP包封装

一.H264基本概念

H.264从框架结构上分为视频编码层(VCL)和网络抽象层(NAL)VCL功能是进行视频编解码,包括运动补偿预测,变换编码和熵编码等功能;NAL用于采用适当的格式对VCL视频数据进行封装打包。

VCL数据即被压缩编码后的视频数据序列,在VCL数据封装到NAL单元中之后,才可以用来传输或存储。NAL单元(NALU)是NAL的基本语法结构,它包含一个字节的头信息和一系列来自VCL的称为原始字节序列载荷(RBSP)的字节流。

nalu headerRBSPnalu headerRBSPnalu headerRBSP

H264是一种视频压缩的标准,与H265、SVAC等压缩方式一样,主要目的是对视频流进行压缩,以便减少网络传输对网络带宽的占用,H264压缩后的帧类型分为I帧/P帧/B帧等。

二,NAL单元数据结构

NALU头前通常包含一个 StartCode,StartCode 必须是 0x00000001 或者 0x000001,紧接着就是一个字节的NALU header,NALU header格式如下:

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

2.1NALU header格式下的标志位取值如下:

F(禁止位): 1 个比特.

禁止位在编码中默认值为0,当网络识别此单元中存在比特错误时,可将其设为1,以便接收方丢掉该单元。主要用于适应不同种类的网络环境(比如有线无线相结合的环境)。例如对于从无线到有线的网关,一边是无线的非IP环境,一边是有线网络的无比特错误的环境。假设一个NAL单元到达无线那边时,校验和检测失败,网关可以选择从NAL流中去掉这个NAL单元,也可以把已知被破坏的NAL单元前传给接收端。在这种情况下,智能的解码器将尝试重构这个NAL单元(已知它可能包含比特错误)。而非智能的解码器将简单地抛弃这个NAL单元。

NRI: 2 个比特.
  nal_ref_idc. 取 00 ~ 11, 指示这个 NALU 的重要性, 用于在重构过程中标记一个NAL单元的重要性,值越大,越重要。值为0表示这个NAL单元没有用于预测,因此可被解码器抛弃而不会有错误扩散;值高于0表示此NAL单元要用于无漂移重构,且值越高,对此NAL单元丢失的影响越大。

TYPE: 5 个比特.

TYPE 5位表示的含义不相同, nalu表示的是slice类型,对于rtp payload代表后面的数据的打包方式。type取值如下:

0没有定义
1-23NAL单元 单个 NAL 单元包.
24STAP-A 单一时间的组合包
25STAP-B 单一时间的组合包
26MTAP16 多个时间的组合包
27MTAP24 多个时间的组合包
28FU-A 分片的单元
29FU-B 分片的单元
30-31没有定义

三.NAL单元的类型

以上类型大概可以分为三类,即 H.264可以有三种RTP打包方式

  • 单个 NAL 单元包:一个RTP包包含一个完整的NALU,荷载中只包含一个 NAL 单元。 NAL 头类型域等于原始 NAL 单元类型, 即在范围 1到 23 之间; 
  • 聚合包:对于较小的NALU,一个RTP包可包含多个完整的NALU,本类型用于聚合多个 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;
  • 分片单元: 对于较大的NALU,一个NALU可以分为多个RTP包发送由于单个nal的大小超过了一个rtp传输负载的mtu,所以将其进行分片,用于分片单个 NAL 单元到多个 RTP 包。 现存两个版本 FU-A, FU-B, 用 NAL 单元类型 28,29 标识;

四.RTP包的格式

首先要明确,RTP包的格式是绝不会变的,永远都是RTP头+RTP载荷

         RTP头                                   RTP载荷

RTP头部是固定的,那么只能在RTP载荷中去添加额外信息来说明这个RTP包是表示同一个NALU

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报文有效载荷中的所有特约信源。


===========================================================

五.RTP组合封包模式

5.1单一 NAL 单元模式封包

5.2分片单元(FU-A、FU-B)
5.2.1FU-A封包

第一个字节位FU Indicator,其格式如下

高三位:与NALU第一个字节的高三位相同

F(禁止位): 1 个比特位,

NRI: 2 个比特位,

Type:28,表示该RTP包一个分片,为什么是28?因为H.264的规范中定义的,此外还有许多其他Type,这里不详讲.

======================================================

第二个字节位FU Header,其格式如下

S: 1 bit
当设置成1,开始位指示分片NAL单元的开始。当跟随的FU荷载不是分片NAL单元荷载的开始,开始位设为0, 标记该分片打包的第一个RTP包。
E: 1 bit
当设置成1, 结束位指示分片NAL单元的结束,即, 荷载的最后字节也是分片NAL单元的最后一个字节。当跟随的FU荷载不是分片NAL单元的最后分片,结束位设置为0,比较该分片打包的最后一个RTP包。
R: 1 bit
保留位必须设置为0,接收者必须忽略该位。

Type:5bit

NALU的Type,表示组合方式。

5.2.2FU-B封包

数据流分析:

// 数据流
80 e0 00 1e 00 00 d2 f0 00 00 00 00 41 9b 6b 49 €?....??....A?kI      
e1 0f 26 53 02 1a ff06 59 97 1d d2 2e 8c 50 01 ?.&S....Y?.?.?P.
cc 13 ec 52 77 4e e50e 7b fd 16 11 66 27 7c b4 ?.?RwN?.{?..f'|?
f6 e1 29 d5 d6 a4 ef3e 12 d8 fd 6c 97 51 e7 e9 ??)????>.??l?Q??
cfc7 5e c8 a9 51 f6 82 65 d6 48 5a 86 b0 e0 8c ??^??Q??e?HZ????
    
其中,
80               是V_P_X_CC
e0               是M_PT
00 1e          	 是SequenceNum
00 00 d2 f0 	 是Timestamp
00 00 00 00		 是SSRC
    
换成二进制:
0X80 = 1000 0000 
     = 10|0|0|0000
        v|p|x|cc 
    
0Xe0 = 1110 0000  
     = |1|1100000
       |m|pt

六.RTP结构体和总图概要

RTP头的结构体

struct RtpHeader
{
    /* byte 0 */
    uint8_t csrcLen : 4;//CSRC计数器,占4位,指示CSRC 标识符的个数。
    uint8_t extension : 1;//占1位,如果X=1,则在RTP报头后跟有一个扩展报头。
    uint8_t padding : 1;//填充标志,占1位,如果P=1,则在该报文的尾部填充一个或多个额外的八位组,它们不是有效载荷的一部分。
    uint8_t version : 2;//RTP协议的版本号,占2位,当前协议版本号为2。
    /* byte 1 */
    uint8_t payloadType : 7;//有效载荷类型,占7位,用于说明RTP报文中有效载荷的类型,如GSM音频、JPEM图像等。
    uint8_t marker : 1;//标记,占1位,不同的有效载荷有不同的含义,对于视频,标记一帧的结束;对于音频,标记会话的开始。
    /* bytes 2,3 */
    uint16_t seq;//占16位,用于标识发送者所发送的RTP报文的序列号,每发送一个报文,序列号增1。接收者通过序列号来检测报文丢失情况,重新排序报文,恢复数据。
    /* bytes 4-7 */
    uint32_t timestamp;//占32位,时戳反映了该RTP报文的第一个八位组的采样时刻。接收者使用时戳来计算延迟和延迟抖动,并进行同步控制。
    /* bytes 8-11 */
uint32_t ssrc;//占32位,用于标识同步信源。该标识符是随机选择的,参加同一视频会议的两个同步信源不能有相同的SSRC。
客户端发起rstp拉流请求请流,服务端推流随机生产ssrc。
   /*标准的RTP Header 还可能存在 0-15个特约信源(CSRC)标识符  
   每个CSRC标识符占32位,可以有0~15个。每个CSRC标识了包含在该RTP报文有效载荷中的所有特约信源*/
};

RTP的结构体

struct RtpPacket
{
    struct RtpHeader rtpHeader;
    uint8_t payload[0];
};

H264结构和RTP打包总图概要

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【竞技宝】DOTA2:梦幻联赛开战在即 中国区前两名将晋级正赛

北京时间2024年1月12日,近期DOTA2刚刚结束了别墅杯东南亚/中国区的封闭预选赛,而别墅杯的正赛还要等到下个月才会正式开打,而即将在明天开始进行的是梦幻联赛S22的中国区预选赛,除官方直邀的XG战队直接晋级正赛之外,其…

【Leetcode】2085. 统计出现过一次的公共字符串

文章目录 题目思路代码 题目 2085. 统计出现过一次的公共字符串 思路 使用两个哈希表 words1Count 和 words2Count 分别统计两个数组中每个单词的出现次数。然后遍历 words1Count 中的每个单词,如果该单词在 words1 中出现了一次,且在 words2 中也出…

深入理解计算机系统(2):信息的表示和处理

信息存储 大多数计算机使用 8 位的块,或者字节(byte),作为最小的可寻址的内存单位,而不是访问内存中单独的位。机器级程序将内存视为一个非常大的字节数组,称为虚拟内存(virtual memory)。内存的每个字节都由一个唯一的数字来标识…

地表最强,接口调试神器Postman ,写得太好了!

postman是一款支持http协议的接口调试与测试工具,其主要特点就是功能强大,使用简单且易用性好 。 无论是开发人员进行接口调试,还是测试人员做接口测试,postman都是我们的首选工具之一 。 那么接下来就介绍下postman到底有哪些功…

连续多级主管

背景 组织中一般会有个直接主管,或者汇报主管,有的组织可能有多个主管,更有甚者一个人能可能在不同的业务项目中,这样这个人可能存在n个主管,这样在设计流程中就会衍生出很多问题来。一起看一款审批软件的设置&#x…

加入 The Sandbox,在「小王子:友谊与慈善的冒险」中踏上奇幻旅途

这次体验不仅是一次冒险,更是一次充满爱心的愉悦探索。此外,您购买的 NFT 还将用于慈善教育项目:它由安托万德圣埃克苏佩里青少年基金会资助,其中一部分销售收入将用于支持这个慈善机构。这次寓教于乐的旅程交织着对爱、友谊的思考…

MySQL比较运算符详解

MySQL比较运算符详解 一、常用的比较运算符二、比较运算符的使用方法2.1 等于运算符&#xff08;&#xff09;2.2 不等于运算符&#xff08;<>或!&#xff09;2.3 大于运算符&#xff08;>&#xff09;2.4 小于运算符&#xff08;<&#xff09;2.5 大于等于运算符&…

开源云真机平台-Sonic实际使用过程踩坑及解决方法(持续更新)

开源云真机平台-Sonic实际使用过程踩坑及解决方法(持续更新) 1、执行Python 自定义脚本时requests文件报错 Script stderrTraceback (most recent call last): File "D:TestToolssonic-agent-2.6 2-windows x86 64 onic-ent-v2.6.2-windows X86 64tes-utDut2b713b90-493-…

【MFC实践】基于MFC向导C++制作计算器(附文件)

一、写在前面1.1 什么是MFC向导&#xff1f;1.2 使用MFC向导制作计算器1.3安装visual studio 2022和MFC插件 二、设计计算器界面1.1 新创建MFC项目1.2 设计计算器界面1.3 添加相关变量1.4 算法的一些问题及解决方式1.5 计算功能的实现1.6 其它功能的实现1.6.1 DEL功能1.6.2 C置…

Linux——firewalld防火墙(二)

一、firewalld高级配置 1、IP地址伪装 地址伪装&#xff08;masquerade):通过地址伪装&#xff0c;NAT设备将经过设备的包转发到指定接收方&#xff0c;同时将通过的数据包的源地址更改为其自己的接口地址。当返回的数据包到达时&#xff0c;会将目的地址修改为原始主机的地址…

(26)Linux 进程通信之共享内存(共享储存空间)

共享内存是System V版本的最后一个进程间通信方式。共享内存&#xff0c;顾名思义就是允许两个不相关的进程访问同一个逻辑内存&#xff0c;共享内存是两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常为同一段物理内存。进程可以将同一…

6.4、SDN在云数据中心的应用案例分析

云数据中心中的虚拟子网包含网关和IP网段,IP分配给各个服务器,服务器间能够互相通信或通过网关访问外部网络。 在SDN云数据中心内,用户可以随时订购任意网段的虚拟子网,而且这些子网是可以在不同用户之间复用的,也就是说,不同用户可以使用相同的私有网段。 SDN云数据中心…

Matlab 字符识别OCR实验

Matlab 字符识别实验 图像来源于屏幕截图&#xff0c;要求黑底白字。数据来源是任意二进制文件&#xff0c;内容以16进制打印输出&#xff0c;0-9a-f’字符被16个可打印字符替代&#xff0c;这些替代字符经过挑选&#xff0c;使其相对容易被识别。 第一步进行线分割和字符分割…

从“唯分论”到“过程评价” 助力教育高质量发展

近日,为推动教育评价改革工作高质量发展,山东省委办公厅、省政府办公厅印发《关于进一步推进教育评价改革工作的若干措施》,从学校评价改革、学生评价改革等6方面共提出25条举措,对教育评价改革进行了全面部署。 教育评价改革是教育改革的“牛鼻子”,为教育发展提供了明确的方…

CSS 中的伪装大师:伪类和伪元素的奇妙世界

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

开源大数据集群部署(四)Freeipa部署(kerberos+ldap)

作者&#xff1a;櫰木 1、 FreeIPA介绍 Kerberos协议只是一种协议标准的框架&#xff0c;而MIT Kerberos则是实现了该协议的认证服务&#xff0c;是Kerberos的物理载体。将它与Hadoop服务进行集成便能够很好地解决安全性不足的问题。 除了需要安装MIT Kerberos之外&#xff0…

调查问卷设计指南:提升数据收集与分析效果的实用技巧

想要做好一份调查问卷要明确哪几点&#xff1f; 一、问卷三要素 1、问卷主题 我们使用调查问卷法进行调查的时候&#xff0c;首先要明确主题是什么&#xff0c;是关于人员满意度调查、人员喜好类型调查还是其他主题。明确主题后我们才可以进行接下来的动作。 2、调查人群 明确问…

互联网 HR 眼中的好简历是什么样子的?

HR浏览一份简历也就25秒左右&#xff0c;如果你连「好简历」都没有&#xff0c;怎么能找到好工作呢&#xff1f; 如果你不懂得如何在简历上展示自己&#xff0c;或者觉得怎么改简历都不出彩&#xff0c;那请你一定仔细读完。 互联网运营个人简历范文> 男 22 本科 AI简历…

数据类型、数据类型转换(Java)

一、数据类型的分类 1. byte&#xff1a;1字节&#xff0c;-128~127 2. short&#xff1a;2字节&#xff0c;-32768~32767 3. int&#xff1a;4字节 默认整型 4. long&#xff1a;8字节 注意&#xff1a;随便写一个整型字面量会默认是整型的&#xff0c;所以我们在写一个…

Docker 安装部署

1、Docker 安装 ① 卸载docker&#xff0c;清空之前的docker文件 yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-selinux \docker-engine-selinux \docker-engine \docker-ce…