H264原始码流格式分析
1.H264码流结构组成
H.264裸码流(Raw Bitstream)数据主要由一系列的NALU(网络抽象层单元)组成。每个NALU包含一个NAL头和一个RBSP(原始字节序列载荷)。
1.1 H.264码流层次
H.264码流的结构可以分为两个层次:VCL(视频编码层)和NAL(网络抽象层)。下图为H.264码流中的层次图:
VCL层:负责对视频的原始数据进行压缩。VCL数据编码器直接输出的原始数据比特串(SODB),表示图像被压缩后的编码比特流。
- SODB:生成压缩原始的图像编码数据比特串。
- 编码图像:宏块进行的帧内编码/帧间编码/熵编码等处理。
NAL层:负责将VCL数据封装成NAL单元(NALU),并在网络上传输或存储到磁盘上。每个NAL单元之前需要添加StartCodePrefix,形成H.264码流。NAL层还处理拆包和组包的工作,以适应网络传输的最大传输单元(通常为1500字节)。
1.2 NALU网络层组成
一个NALU由两个主要部分组成:
-
头部(Header):
NALU的头部包含了关于该单元的一些元数据信息,例如NAL单元类型(如序列参数集、图像参数集、帧数据单元等),NALU的优先级、参考帧标识、重要性指示等。头部的信息有助于解码器正确解析和处理每个NAL单元。
-
载荷(Payload):
NALU的载荷部分包含了实际的编码数据。这些数据可以是帧的视频数据、补充增强信息或其他特定于编码标准的数据。在视频解码过程中,解码器通过解析头部信息来识别NALU的类型,并且根据类型和载荷数据进行相应的解码和处理。
在H.264/AVC中,定义了多种NALU的类型,以适应不同的应用场景。常见的类型包括:
帧内预测(I)片:仅使用当前帧的信息进行编码。
预测(P)片:使用前一帧的信息进行编码。
双向预测(B)片:使用前一帧和后一帧的信息进行编码。
1.3 序列参数集SPS
序列参数集(Sequence Parameter Set,SPS)包含了描述视频序列全局参数的信息,这些参数对于解码器正确解码视频流至关重要。以下是SPS的一些主要内容和结构:
- profile_idc:标识H.264码流的profile,例如Baseline、Main、High等。
- level_idc:标识码流的Level,定义了最大分辨率、最大帧率等参数。
- seq_parameter_set_id:序列参数集的ID,用于标识不同的SPS。
- log2_max_frame_num_minus4:用于计算frame_num的最大值,frame_num标识图像的解码顺序。
- pic_order_cnt_type:指明图像播放顺序的编码方法。
- log2_max_pic_order_cnt_lsb_minus4:用于计算POC(Picture Order Count)的最大值。
- max_num_ref_frames:指定参考帧队列的最大长度。
- gaps_in_frame_num_value_allowed_flag:指示是否允许frame_num不连续。
- pic_width_in_mbs_minus1:图像宽度,以宏块为单位。
- pic_height_in_map_units_minus1:图像高度,以宏块为单位。
SPS中的信息对于解码器初始化和正确解码视频流至关重要。如果SPS数据丢失或损坏,解码器可能无法正确解码视频。
1.4 图像参数集PPS
图像参数集(Picture Parameter Set,PPS)包含了与单个图像编码相关的参数,这些参数用于控制图像的编码方式。以下是PPS的一些主要内容和结构:
- pic_parameter_set_id:当前PPS的唯一ID,取值范围为0-255。
- seq_parameter_set_id:指明该PPS对应的SPS(序列参数集)ID。
- entropy_coding_mode_flag:表示使用的熵编码类型,0为CAVLC,1为CABAC。
- num_slice_groups_minus1:表示slice group的数量,通常为0。
- num_ref_idx_l0_default_active_minus1和num_ref_idx_l1_default_active_minus1:表示P/B slice的前向和后向参考帧的最大个数减1。
- weighted_pred_flag:表示P slice的预测权重方式,0为默认预测权重,1为显式方式。
- weighted_bipred_flag:表示B slice的预测权重方式,0为默认预测权重,1为显式方式,2为隐式方式。
- pic_init_qp_minus26:用于计算Y分量的初始QP值。
- chroma_qp_index_offset:表示Cb分量QP相对于slice QP的偏移量。
- deblocking_filter_control_present_flag:表示是否存在去块效应滤波器的控制语法元素。
- constrained_intra_pred_flag:表示帧内预测方式是否存在限制条件。
- transform_8x8_mode_flag:表示是否使用8x8大小的DCT变换方式。
- pic_scaling_matrix_present_flag:表示量化参数矩阵是否存在。
- second_chroma_qp_index_offset:表示Cr分量QP相对于slice QP的偏移量。
PPS中的信息对于解码器正确解码视频流至关重要。PPS通常紧跟在SPS之后,并且可以有多个,因为不同的slice group可能有不同的参数设置。
2.常用的两种NALU格式
2.1 AnnexB
AnnexB是一种常见的NALU(网络抽象层单元)封装格式,主要用于H.264和H.265视频编码标准。AnnexB格式的基本结构如下:
[开始代码] [NALU单元] [开始代码] [NALU单元] ...
每个NALU单元由一个开始代码和随后的原始字节数据组成,通过分隔符0x00 00 00 01或者0x00 00 01区分不同的NALU单元。如果在RBSP(原始字节流载荷)中出现了0x000000、0x000001、0x000002或0x000003这样的序列,就需要插入一个0x03字节来避免这些序列被误识别。例如,将0x000001变成0x00000301,这样在解码时可以去除0x03字节,恢复原始数据。这种方法确保了数据的完整性和正确解码。例如:
-
原始数据:
0x000001
插入“模拟预防”字节后:0x00000301
解码时去除0x03字节,恢复为:0x000001
-
原始数据:
0x000000
插入“模拟预防”字节后:0x00000300
解码时去除0x03字节,恢复为:0x000000
-
原始数据:
0x000002
插入“模拟预防”字节后:0x00000302
解码时去除0x03字节,恢复为:0x000002
-
原始数据:
0x000003
插入“模拟预防”字节后:0x00000303
解码时去除0x03字节,恢复为:0x000003
如果插入的数据本身包含了“模拟预防”字节(例如0x00000301),编码器会将其转义为0x0000030301。
2.2 AVCC
AVCC(AVC Configuration)格式是一种用于存储和传输H.264视频流的格式,通常用于MP4、MKV等容器中。与Annex B格式不同,AVCC格式不使用起始码(start code)来分隔NALU(网络抽象层单元),而是使用NALU长度前缀。
AVCC格式结构:
- 头部信息(extradata):
- 包含SPS(序列参数集)和PPS(图像参数集)等参数信息。
- 头部信息的格式如下:
- 第1字节:版本号(通常为0x01)
- 第2字节:AVC Profile(与第一个SPS的第2字节相同)
- 第3字节:AVC Compatibility(与第一个SPS的第3字节相同)
- 第4字节:AVC Level(与第一个SPS的第4字节相同)
- 第5字节:保留位(前6位全1),后2位表示NALU长度字段的字节数减1(通常为3,即4字节)
- 第6字节:保留位(前3位全1),后5位表示SPS的个数(通常为1)
- 后续字节:SPS数据(包括16位SPS长度和SPS NALU数据)
- PPS数据(包括16位PPS长度和PPS NALU数据)
- NALU数据:
- 每个NALU前面都有一个长度前缀(通常为4字节),表示该NALU的长度。
- NALU数据不包含起始码。
假设有一个NALU数据为0x65 88 84 21
,其长度为4字节。在AVCC格式中,这个NALU会被存储为:
0x00 00 00 04 65 88 84 21
其中,0x00 00 00 04
表示NALU的长度为4字节,后面的65 88 84 21
是实际的NALU数据。
在解析AVCC格式时,需要先读取头部信息(extradata),然后根据NALU长度前缀来提取每个NALU的数据。
2.3 AnnexB和AVCC的优缺点
Annex B和AVCC是H.264视频编码中常见的两种NALU(网络抽象层单元)封装格式。它们各有优缺点,适用于不同的应用场景。以下是它们的优劣之处:
Annex B | |
---|---|
优点 | 简单直接:使用起始码(start code)0x000001 或0x00000001 来分隔NALU,便于解析和同步。广泛支持:许多硬件解码器和流媒体协议(如RTSP、RTP)默认支持Annex B格式。 实时流媒体:适合实时流媒体传输,因为起始码可以快速定位NALU的边界。 |
缺点 | 额外开销:起始码会增加一些额外的字节,导致数据冗余。 不适合文件存储:在文件存储中,起始码的存在可能会增加文件大小,不如AVCC格式高效。 |
AVCC | |
---|---|
优点 | 高效存储:使用NALU长度前缀(通常为4字节)来标识NALU的长度,减少了数据冗余,适合文件存储。 灵活性高:适用于多种容器格式(如MP4、MKV),便于在不同平台和设备之间传输和存储。 标准化:AVCC格式在许多多媒体框架和库(如FFmpeg、GStreamer)中得到广泛支持。 |
缺点 | 解析复杂:需要解析NALU长度前缀,增加了解码器的复杂性。 实时性较差:不如Annex B格式适合实时流媒体传输,因为需要额外的步骤来解析NALU长度。 |
选择建议
- 实时流媒体传输:推荐使用Annex B格式,因其简单直接,便于实时解析和同步。
- 文件存储和传输:推荐使用AVCC格式,因其高效存储和灵活性,适合在不同平台和设备之间传输和存储。
3.码流中的重要参数
3.1 量化参数(QP值)
QP(Quantization Parameter,量化参数)是H.264视频编码中用于控制视频压缩的质量和比特率。QP值直接影响视频的量化步长(Qstep),从而影响视频的压缩程度和图像质量。QP值的作用:
- 控制压缩质量:QP值越小,量化越精细,保留的图像细节越多,视频质量越高,但比特率也越高。相反,QP值越大,量化越粗糙,丢失的细节越多,视频质量下降,但比特率降低。
- 调节比特率:通过调整QP值,可以在视频质量和比特率之间找到一个平衡点,以满足不同的应用需求。
QP值的范围,在H.264标准中,QP值的取值范围为0到51:
- QP = 0:量化最精细,视频质量最高,比特率最大。
- QP = 51:量化最粗糙,视频质量最低,比特率最小。
假设你有一个视频片段,使用不同的QP值进行编码:
- QP = 20:视频质量较高,细节保留较多,但比特率较高。
- QP = 40:视频质量较低,细节丢失较多,但比特率较低。
QP值与量化步长(Qstep)之间存在一个对数关系。具体来说,QP每增加6,Qstep大约增加一倍。这个关系使得编码器可以在不同的QP值下灵活调整视频的压缩程度。
- 低QP值:适用于需要高质量视频的场景,如高清电影、专业视频制作。
- 高QP值:适用于对比特率要求较高的场景,如实时视频传输、低带宽环境。
3.2 码率
码率(Bitrate)是指单位时间内传输的数据量,通常以kbps(千比特每秒)或Mbps(兆比特每秒)为单位。码率在视频和音频编码中起着至关重要的作用,直接影响到文件的质量和大小。
- 视频质量:码率越高,视频质量越好,因为更多的数据可以用来表示图像细节。反之,码率越低,视频质量越差。
- 文件大小:码率越高,文件大小越大。对于同一段视频,较高的码率会导致更大的文件。
- 传输效率:在流媒体传输中,码率决定了视频流的带宽需求。较高的码率需要更高的网络带宽。
码率的基本计算公式为:
码率 (kbps)=\frac{文件大小 (KB)×8}{时间 (秒)}
码率控制模式:
- 恒定码率(CBR):码率在整个视频中保持恒定,适用于带宽稳定的环境。
- 可变码率(VBR):码率根据视频内容的复杂度动态调整,通常在保证质量的同时节省带宽。
- 平均码率(ABR):在指定的文件大小内,动态调整码率以平衡质量和文件大小。
假设一个视频文件大小为500MB,时长为10分钟(600秒),其码率计算如下:
码率 (kbps)=\frac{500×1024×8}{600}≈6826.67 kbps
如何选择合适的码率?
- 高质量需求:如高清电影、专业视频制作,建议使用较高的码率。
- 实时传输:如视频会议、直播,建议使用适中的码率以平衡质量和带宽需求。
- 低带宽环境:如移动网络,建议使用较低的码率以减少缓冲和卡顿。
相关文章:

H264原始码流格式分析
1.H264码流结构组成 H.264裸码流(Raw Bitstream)数据主要由一系列的NALU(网络抽象层单元)组成。每个NALU包含一个NAL头和一个RBSP(原始字节序列载荷)。 1.1 H.264码流层次 H.264码流的结构可以分为两个层…...

JAVA 接口、抽象类的关系和用处 详细解析
接口 - Java教程 - 廖雪峰的官方网站 一个 抽象类 如果实现了一个接口,可以只选择实现接口中的 部分方法(所有的方法都要有,可以一部分已经写具体,另一部分继续保留抽象),原因在于: 抽象类本身…...

反向代理模块b
1 概念 1.1 反向代理概念 反向代理是指以代理服务器来接收客户端的请求,然后将请求转发给内部网络上的服务器,将从服务器上得到的结果返回给客户端,此时代理服务器对外表现为一个反向代理服务器。 对于客户端来说,反向代理就相当于…...

Nuitka打包python脚本
Python脚本打包 Python是解释执行语言,需要解释器才能运行代码,这就导致在开发机上编写的代码在别的电脑上无法直接运行,除非目标机器上也安装了Python解释器,有时候还需要额外安装Python第三方包,相当麻烦。 事实上P…...

pytorch线性回归模型预测房价例子
import torch import torch.nn as nn import torch.optim as optim import numpy as np# 1. 创建线性回归模型类 class LinearRegressionModel(nn.Module):def __init__(self):super(LinearRegressionModel, self).__init__()self.linear nn.Linear(1, 1) # 1个输入特征&…...

练习题 - DRF 3.x Caching 缓存使用示例和配置方法
在构建现代化的 Web 应用程序时,性能优化是一个非常重要的环节。尤其是在使用 Django Rest Framework (DRF) 开发 API 服务时,合理地利用缓存技术可以显著提高应用的响应速度和减轻数据库的负担。DRF 提供了多种缓存机制,包括基于内存、文件系统、数据库以及第三方缓存服务(…...

如何解压7z文件?8种方法(Win/Mac/手机/网页端)
7z 文件是一种高效的压缩文件格式,由 7 - Zip 软件开发者所采用。它运用独特的压缩算法,能显著缩小文件体积,便于存储与传输各类数据,像软件安装包、大型资料集等。但要使用其中内容,就必须解压,因为处于压…...

python学opencv|读取图像(五十)使用addWeighted()函数实现图像加权叠加效果
【1】引言 前序学习进程中,学习了图像互相叠加的不同操作方法,包括add()函数直接叠加BGR值和使用bitwise()函数对BGR值进行按位计算叠加等,相关文章链接包括且不限于: python学opencv|读取图像(四十二)使…...

window中80端口被占用问题
1,查看报错信息 可以看到在启动项目的时候,8081端口被占用了,导致项目无法启动。 2,查看被占用端口的pid #语法 netstat -aon|findstr :被占用端口#示例 netstat -aon|findstr :8080 3,杀死进程 #语法 taikkill /pid…...

06-机器学习-数据预处理
数据清洗 数据清洗是数据预处理的核心步骤,旨在修正或移除数据集中的错误、不完整、重复或不一致的部分,为后续分析和建模提供可靠基础。以下是数据清洗的详细流程、方法和实战示例: 一、数据清洗的核心任务 问题类型表现示例影响缺失值数值…...

电梯系统的UML文档12
5.2.1 DoorControl 的状态图 图 19: DoorControl 的状态图 5.2.2 DriveControl 的状态图 图 20: DriveControl 的状态图 5.2.3 LanternControl 的状态图 图 21: LanternControl 的状态图 5.2.4 HallButtonControl 的状态图 图 22: HallButtonControl 的状态图 5.2.5 CarB…...

萌新学 Python 之运算符
Python 中运算符包括:算术运算符、比较运算符、逻辑运算符、赋值运算符、位运算符、海象运算符 算术运算符:加 减 - 乘 * 除 / 取整 // 求余 % 求幂 ** 注意:取整时,一正一负整除,向下取整 比如 5 // …...

嵌入式知识点总结 Linux驱动 (五)-linux内核
针对于嵌入式软件杂乱的知识点总结起来,提供给读者学习复习对下述内容的强化。 目录 1.内核镜像格式有几种?分别有什么区别? 2.内核中申请内存有哪几个函数?有什么区别? 3.什么是内核空间,用户空间&…...

zabbix7 配置字体 解决中文乱码问题(随手记)
目录 问题网传的方法(无效)正确的修改方式步骤 问题 zabbix 最新数据 中,图标的中文显示不出。 网传的方法(无效) 网传有一个方法:上传字体文件到/usr/share/zabbix/assets/fonts;修改/usr/…...

预测不规则离散运动的下一个结构
有一个点在19*19的平面上运动,运动轨迹为 一共移动了90步,顺序为 y x y x y x 0 17 16 30 10 8 60 15 15 1 3 6 31 10 7 61 14 15 2 12 17 32 9 9 62 16 15 3 4 12 33 10 9 63 18 15 4 3 18 34 15 12 6…...

CTFSHOW-WEB入门-命令执行29-32
题目:web 29 题目:解题思路:分析代码: error_reporting(0); if(isset($_GET[c])){//get一个c的参数$c $_GET[c];//赋值给Cif(!preg_match("/flag/i", $c)){eval($c);//if C变量里面没有flag,那么就执行C…...

SQL Server 建立每日自动log备份的维护计划
SQLServer数据库可以使用维护计划完成数据库的自动备份,下面以在SQL Server 2012为例说明具体配置方法。 1.启动SQL Server Management Studio,在【对象资源管理器】窗格中选择数据库实例,然后依次选择【管理】→【维护计划】选项࿰…...

doris:HLL
HLL是用作模糊去重,在数据量大的情况性能优于 Count Distinct。HLL的导入需要结合hll_hash等函数来使用。更多文档参考HLL。 使用示例 第 1 步:准备数据 创建如下的 csv 文件:test_hll.csv 1001|koga 1002|nijg 1003|lojn 1004|lofn …...

双层Git管理项目,github托管显示正常
双层Git管理项目,github托管显示正常 背景 在写React项目时,使用Next.js,该项目默认由git托管。但是我有在项目代码外层记笔记的习惯,我就在外层使用了git托管。 目录如下 code 层内也有.git 文件,对其托管。 我没太在意&…...

准备知识——旋转机械的频率和振动基础
旋转频率,也称为转速或旋转速率(符号ν,小写希腊字母nu,也作n),是物体绕轴旋转的频率。其国际单位制单位是秒的倒数(s −1 );其他常见测量单位包括赫兹(Hz)、每秒周期数(cps) 和每分钟转数(rpm)…...

知识库管理驱动企业知识流动与工作协同创新模式
内容概要 知识库管理在现代企业中扮演着至关重要的角色,其价值不仅体现在知识的积累,还在于通过优质的信息流动促进协作与创新。有效的知识库能够将分散的信息整合为有序、易于访问的资源,为员工提供实时支持,进而提升整体工作效…...

CMake常用命令指南(CMakeList.txt)
CMakeList从入门到精通的文章有很多不再赘述( 此处附带一篇优秀的博文链接:一个简单例子,完全入门CMake语法与CMakeList编写 )。 本文主要列举 CMake 中常用命令的详细说明、优缺点分析以及推荐做法,以更好地理解和灵…...

【回溯+剪枝】找出所有子集的异或总和再求和 全排列Ⅱ
文章目录 1863. 找出所有子集的异或总和再求和解题思路:子集问题解法(回溯 剪枝)47. 全排列 II解题思路:排序 回溯 剪枝 1863. 找出所有子集的异或总和再求和 1863. 找出所有子集的异或总和再求和 一个数组的 异或总和 定义为…...

中国技术突破对国际格局的多维影响与回应
链接地址: https://download.csdn.net/download/wanggang130532/90323798https://download.csdn.net/download/wanggang130532/90323798...

【漫话机器学习系列】068.网格搜索(GridSearch)
网格搜索(Grid Search) 网格搜索(Grid Search)是一种用于优化机器学习模型超参数的技术。它通过系统地遍历给定的参数组合,找出使模型性能达到最优的参数配置。 网格搜索的核心思想 定义参数网格 创建一个包含超参数值…...

元宇宙下的Facebook:虚拟现实与社交的结合
随着科技的不断进步,虚拟现实(VR)技术逐渐从科幻走入现实,成为人们探索未来社交方式的重要工具。在这一浪潮中,Facebook(现为Meta)作为全球领先的社交平台,正在积极布局虚拟现实和元…...

记忆力训练day08
写作头脑风暴训练 1 集体的头脑风暴: 2 一个人的头脑风暴 没事,你说老师我还没有摸到门道,你去做,做的时候你就会知道什么叫做头脑风暴。记住,不要用脑子就在感觉里面,你究竟想给人呈现一种什么样的文章&am…...

崇州市街子古镇正月初一繁华剪影
今天是蛇年正月初一,下午笔者步出家门,逛到了崇州市街子古镇井水街,想看看景象如何。结果看到的是车水马龙、人流如织,繁花似锦,热闹非凡,原来今天开始预订此地摆下的长街宴。心里高兴,便用手机…...

websocket webworker教程及应用
WebSocket 和 Web Workers 是两种不同的 Web 技术,分别用于实现实时通信和后台线程处理。以下是它们的简要教程: WebSocket 教程 1. 什么是 WebSocket? WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。它允许服务器主动向客户端推…...

【后端】Flask
长期更新,建议关注收藏点赞! 实例1 Jinja2 是 Flask 和 Django 使用的 模板引擎,它允许你在 HTML 中嵌入 Python 代码,以动态生成页面内容。Jinja2 语法类似于 Django 模板,并支持变量、条件判断、循环、过滤器等。 fr…...