博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
h264 NALU的获取与分析
阅读量:4160 次
发布时间:2019-05-26

本文共 3108 字,大约阅读时间需要 10 分钟。

转载地址 :

一、如何从H264数据流中获取NALU

0x00000001或0x000001是一个nalu的起始标志,遇到下一个此标志时为该nalu的结尾。起始标志的后面第一个字节(type)里包含有nalu的类型,type & 0x1F即为该nalu的类型(nal_unit_type),具体类型分析详见下节。
二、H264帧分类
1、PPS与SPS
nal_unit_type=7时,nalu为SPS;nal_unit_type=8时,nalu为PPS。
SPS(Sequence Parameter Set)序列参数集,PPS(Picture Parameter Set)图像参数集。SPS和PPS串,包含了初始化H.264解码器所需要的信息参数,包括编码所用的profile,level,图像的宽和高,deblock滤波器等。如果对获取的nalu去掉开始码之后进行base64编码,得到的信息就可以用于sdp(SPS和PPS需要用逗号分隔开来)。下图为一个完整的sdp,sprop-parameter-sets为SPS和PPS的base64码,逗号前的为SPS,逗号后的为PPS:

2、I帧

nal_unit_type=5是,nalu为I帧。
I帧全名叫“IDR图像的编码条带”,俗称关键帧,也叫帧内编码帧 ,你可以理解为这一帧画面的完整保留;解码时只需要本帧数据就可以完成(因为包含完整画面)。
I帧特点:
1)它是一个全帧压缩编码帧。它将全帧图像信息进行JPEG压缩编码及传输;
2)解码时仅用I帧的数据就可重构完整图像;
3)I帧描述了图像背景和运动主体的详情;
4)I帧不需要参考其他画面而生成;
5)I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量);
6)I帧是帧组GOP(Group of Pictures)的基础帧(第一帧),在一组中只有一个I帧;
7)I帧不需要考虑运动矢量;
8)I帧所占数据的信息量比较大。
3、nal_unit_type=1时,nalu为“非IDR图像的编码条带”,为P或B帧。
P帧:前向预测编码帧。P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面。(也就是差别帧,P帧没有完整画面数据,只有与前一帧的画面差别的数据)
P帧的预测与重构:P帧是以I帧为参考帧,在I帧中找出P帧“某点”的预测值和运动矢量,取预测差值和运动矢量一起传送。在接收端根据运动矢量从I帧中找出P帧“某点”的预测值并与差值相加以得到P帧“某点”样值,从而可得到完整的P帧。
P帧特点:
1)P帧是I帧后面相隔1~2帧的编码帧;
2)P帧采用运动补偿的方法传送它与前面的I或P帧的差值及运动矢量(预测误差);
3)解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像;
4)P帧属于前向预测的帧间编码。它只参考前面最靠近它的I帧或P帧;
5)P帧可以是其后面P帧的参考帧,也可以是其前后的B帧的参考帧;
6)由于P帧是参考帧,它可能造成解码错误的扩散;
7)由于是差值传送,P帧的压缩比较高。
B帧:双向预测内插编码帧。B帧是双向差别帧,也就是B帧记录的是本帧与前后帧的差别(具体比较复杂,有4种情况,但我这样说简单些),换言之,要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但是解码时CPU会比较累。
B帧的预测与重构
B帧以前面的I或P帧和后面的P帧为参考帧,“找出”B帧“某点”的预测值和两个运动矢量,并取预测差值和运动矢量传送。接收端根据运动矢量在两个参考帧中“找出(算出)”预测值并与差值求和,得到B帧“某点”样值,从而可得到完整的B帧。
B帧特点
1)B帧是由前面的I或P帧和后面的P帧来进行预测的;
2)B帧传送的是它与前面的I或P帧和后面的P帧之间的预测误差及运动矢量;
3)B帧是双向预测编码帧;
4)B帧压缩比最高,因为它只反映了参考帧间运动主体的变化情况,预测比较准确;
5)B帧不是参考帧,不会造成解码错误的扩散。
注:I、B、P各帧是根据压缩算法的需要,是人为定义的,它们都是实实在在的物理帧。一般来说,I帧的压缩率是7(跟JPG差不多),P帧是20,B帧可以达到50。可见使用B帧能节省大量空间,节省出来的空间可以用来保存多一些I帧,这样在相同码率下,可以提供更好的画质。
三、h264 NALU分析示例
下图为用UE打开的一个h264文件:

该段数据中共有4个nalu,红色标注部分为4个nalu的起始位置,开头均为0x00000001四个字节,根据起始的第五个字节分析,段1:0x06 & 0x1f = 6,nalu为辅助增强信息 (SEI);段2:0x67 & 0x1f = 7,nalu为SPS;段3:0x68 & 0x1f = 8,nalu为PPS;段4:0x65 & 0x1f = 5,nalu为I帧。

四、附录
nal_unit_type类型列表:
nal_unit_type    NAL 单元和 RBSP 语法结构的内容    备注
0    未指定     
1    一个非IDR图像的编码条带 
slice_layer_without_partitioning_rbsp( )     
2    编码条带数据分割块A 
slice_data_partition_a_layer_rbsp( )     
3    编码条带数据分割块B 
slice_data_partition_b_layer_rbsp( )     
4    编码条带数据分割块C 
slice_data_partition_c_layer_rbsp( )     
5    IDR图像的编码条带 
slice_layer_without_partitioning_rbsp( )    I帧
6    辅助增强信息 (SEI) 
sei_rbsp( )     
7    序列参数集 
seq_parameter_set_rbsp( )    SPS
8    图像参数集 
pic_parameter_set_rbsp( )    PPS
9    访问单元分隔符 
access_unit_delimiter_rbsp( )     
10    序列结尾 
end_of_seq_rbsp( )     
11    流结尾 
end_of_stream_rbsp( )     
12    填充数据 
filler_data_rbsp( )     
13    序列参数集扩展 
seq_parameter_set_extension_rbsp( )     
14...18    保留     
19    未分割的辅助编码图像的编码条带 
slice_layer_without_partitioning_rbsp( )     
20...23    保留     
24...31    未指定     
下面是h264标准中定义的nalu类型宏:
#define NALU_TYPE_SLICE 1
#define NALU_TYPE_DPA 2
#define NALU_TYPE_DPB 3
#define NALU_TYPE_DPC 4
#define NALU_TYPE_IDR 5
#define NALU_TYPE_SEI 6
#define NALU_TYPE_SPS 7
#define NALU_TYPE_PPS 8
#define NALU_TYPE_AUD 9
#define NALU_TYPE_EOSEQ 10
#define NALU_TYPE_EOSTREAM 11
#define NALU_TYPE_FILL 12
--------------------- 
 

你可能感兴趣的文章
卸载oracle
查看>>
hive 自定义函数jar发布的方法
查看>>
Java 设计模式之原型模式
查看>>
对DMA传输机制的学习
查看>>
QT中this指针
查看>>
设计模式_02_依赖倒置原则
查看>>
设计模式_03_单一职责原则
查看>>
设计模式_04_接口隔离原则
查看>>
设计模式_05_迪米特原则
查看>>
设计模式_06_ 里氏替换原则
查看>>
设计模式_07_聚合复用原则
查看>>
设计模式_08_简单工厂模式
查看>>
设计模式_09_工厂方法模式
查看>>
设计模式_10_抽象工厂模式
查看>>
文件解压缩工具类(适用zip,tar,tar.gz)
查看>>
文件压缩工具类(zip)
查看>>
Java读取Excel文件(支持xls,xlsx,多sheet)
查看>>
《我的前半生》读懂职场三件事
查看>>
curl命令小记
查看>>
c语言List头文件和应用
查看>>