H264码流进行RTP包封装

news2024/11/15 21:24:57

一.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打包总图概要

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

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

相关文章

CAN201计网历年大题收集

网络性能计算 e.g1.1 算RTT 传输时间 when you enter the URL in your browser, it initiates an HTTP request. This request is encapsulated in TCP, which is then further encapsulated in IP for routing. The data is transmitted over the physical medium using link …

中国信通院联合发布《数字孪生城市白皮书(2023年)》

2017年“数字孪生城市”概念被首次提出,2021年我国“十四五”规划纲要明确“探索建设数字孪生城市”,2023年《数字中国建设整体布局规划》再次提出“全面提升数字中国建设的整体性、系统性、协同性”以及“探索建设数字孪生城市”等要求。数字孪生城市建…

ES高级查询

ES中提供了一种强大的检索数据方式,这种检索方式称为Query DSL,这种方式的丰富查询语法让ES检索变得更强大,更简洁。 1.常见查询 1.1查询所有[match_all] match_all关键字:返回索引中的全部文档。 GET /products/_search { &…

基于springboot+vue药店管理系统

摘要 药店管理系统的设计和应用在当前社会背景下具有巨大的实际意义和社会价值。随着医药行业的不断发展和社会健康水平的提高,药店作为医疗服务的一部分,其管理方式也需要不断创新与优化。该系统的研究不仅关系到单一药店的运营效率,更涉及到…

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

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

【设计模式-04】Factory工厂模式

简要描述 简单工厂静态工厂工厂方法 FactoryMethod 产品维度扩展 抽象工厂 产品一族进行扩展Spring IOC 一、工厂的定义 任何可以产生对象的方法或类,都可以称之为工厂单例也是一种工厂不可咬文嚼字,死扣概念为什么有了new之后,还要有工厂&am…

一阶低通滤波器

一阶低通滤波器 X为输入,Y为滤波后得到的输出值;本次的输出结果主要取决于上次的滤波输出值,其中a是和滤波效果有关的一个参数,称为滤波系数;它决定新采样值在本次滤波结果中所占的权重; 滤波系数a越小&a…

12GoF之代理模式

解决问题的思维:AOP 解决问题技术:代理技术 代理技术太麻烦,因此使用框架 Spring AOP框架(底层是代理技术:jdk动态daili,cglib) 代理模式是GoF23种设计模式之一。属于结构型设计模式。 代理…

【BetterBench】2024年都有哪些数学建模竞赛和大数据竞赛?

2024年每个月有哪些竞赛? 2024年32个数学建模和数据挖掘竞赛重磅来袭!!! 2024年数学建模和数学挖掘竞赛时间目录汇总 一月 (1)2024年第二届“华数杯”国际大学生数学建模竞赛 报名时间:即日起…

List列表操作中的坑

使用 Arrays.asList 把数据转换为 List 的三个坑 在如下代码中,我们初始化三个数字的 int[]数组,然后使用 Arrays.asList 把数组转换为 List: int[] arr {1, 2, 3}; List list Arrays.asList(arr); log.info("list:{} size:{} class…

Angular - 笔记

文章目录 语法属性绑定引用模板变量组件绑定父组件传子组件 input子组件传父组件 outputEventEmitter ViewChildViewChildren获取子组件对象列表 管道常用模块 函数localStorage实现数据持久化简介使用 参考文档 语法 属性绑定 Angular 的双向绑定语法是方括号和圆括号的组合 …

代码随想录算法训练DAY23|二叉树9

算法训练DAY23|二叉树9 669. 修剪二叉搜索树 力扣题目链接 给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>L) 。你可能需要改变树的根节点,所以结果应当返回修剪好的二叉搜索…

如何使用 Python、Node.js 和 Go 创建基于 YOLOv8 的对象检测 Web 服务

1. 介绍 这是有关 YOLOv8 系列文章的第二篇。在上一篇文章中我们介绍了YOLOv8以及如何使用它,然后展示了如何使用 Python 和基于 PyTorch 的官方 YOLOv8 库创建一个 Web 服务来检测图像上的对象。 在本文中,将展示如何在不需要PyTorch和官方API的情况下…

【Python进阶必备】一文掌握re库:实战正则表达式

目录 re库初识 re库基础使用方法 compile()函数 基本用法 正则表达式常用规则字符 match与search方法 match search match/search findall与finditer方法 使用findall()返回所有匹配项 使用findall()提取多个组的匹配 使用finditer()逐个返回Match对象 使用findi…

STM32---基本定时器(含源码)小白可入

写在前面:定时器是STM32中一个十分重要的外设,并且在STM32中具有多个定时器。定时器的包括基本定时器、通用定时器以及高级控制定时器,这些定时器相关独立,不共享任何资源。当然,其难易程度也是逐渐增加的,…

U盘启动安装win11遇到缺少计算机所需的介质驱动程序问题

一、使用U盘制作启动盘遇到问题 下载了windows原版镜像,验证了md5,确保文件没有损坏。使用ultroiso制作u盘启动盘,开始安装后出现下图的报错: 在网上搜索解决方案,主要有以下几种: 安装的时候&#xff0c…

2024年【电工(初级)】最新解析及电工(初级)模拟考试

题库来源:安全生产模拟考试一点通公众号小程序 电工(初级)最新解析根据新电工(初级)考试大纲要求,安全生产模拟考试一点通将电工(初级)模拟考试试题进行汇编,组成一套电…

直接写一区! ZOA-PCNN-AT-SVM斑马优化并行卷积-支持向量机融合注意力机制的故障识别程序,特征可视化,实验多!图多!

适用平台:Matlab2023版本及以上 本原创程序提出的ZOA-PCNN-AT-SVM故障识别模型还没有人写!在此基础上进一步对参考模型进行多重改进,程序注释清晰,干货满满,下面对文章和程序做简要介绍! ①识别模型部分参…

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

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

C++力扣题目106,105--中序和后序,前序和中序遍历构造二叉树

106.从中序与后序遍历序列构造二叉树 力扣题目链接(opens new window) 根据一棵树的中序遍历与后序遍历构造二叉树。 注意: 你可以假设树中没有重复的元素。 例如,给出 中序遍历 inorder [9,3,15,20,7]后序遍历 postorder [9,15,7,20,3] 返回如下的二叉树&am…