常用名词及概念
-
H.264
由VCEG
(Video Coding Experts Group)和MPEG
(Moving Picture Experts Group)共同推进并且目前广泛使用的一种通用视频编码技术;相比于H.265
,压缩率较低,但是对于硬件设备的要求也低一些;另外,h.265商用是非免费的;H.264
中两个重要的概念是NAL
(Network Abstract Layer)和VCL
(Video Coding Layer);VCL
负责表示有效视频数据的内容,NAL
负责格式化数据及头信息,使之可以在不同的信道和存储媒介传播;一个H.264
文件由多个NALU
组成,每个NALU
又可以分为VCL
或non-VCL
。视频数据由编码器处理后然后打包为多个NALU
;针对不同的系统,打包
NALU
的方式有两种:包传输系统(Packet-Transport System)和字节流格式(Byte-Stream Format);对于类似于RTP
的包传输系统,传输系统协议会把编码数据切割成不同的块;系统能够简单地区分NALU
边界并且不需要额外的start code
。
然而,很多传输系统并没有这样的协议去分割NALU
,为了让解码端能够正确区分出NALU
边界,通常会在NALU
的起始位置添加一个3或4字节的start code
;这种类型称为字节流格式 -
NALU
:Network Abstract Layer Unit,网络抽象层;NAL是H.264/AVC
视频编码标准的一部分;NAL-unit是视讯编码层(Video Coding Layer, VCL)的运算单元;H.264
比特流是由多个NAL-unit
组成的;NALU Header
:是NALU
的第一个字节,包含了当前NALU
的基本信息,由3部分构成——forbidden_zero_bit
(1bit)、 nal_ref_idc(2bits)、nal_unit_type(5bits);forbidden_zero_bit
用于检测传输过程中是否发生错误;0
表示正常,1
表示出现错误;nal_ref_idc
表示该NALU
是否是一个参考field/frame/picture
,非零表示是一个参考field/frame/picture
;并且非零值越大,表示该NALU
越重要;nal_unit_type
用于定义当前NALU
的类型,长度5bits;上边提到的VCL
和non-VCL
的NALU
可以更具nal_unit_type
进行区分——nal_unit_type
等于1-5的为VCL
,其他的均为non-VCL
;
常见的几个nal_unit_type
:5-IDR(首个I帧)、6-SEI(辅助增强信息)、7-SPS(Sequence Parameter Set)、8-PPS(Picture Parameter Set)、9-Access unit delimiter、10-End of Sequence、 11-End of Stream、12-Filler datanal_unit_type
与nal_ref_idc
的关系:
nal_unit_type | nal_ref_idc |
---|---|
1-4 | 如果其中一个NALU 是0,type为1-4的NALU 都为0 |
5 Coded Slice of IDR | 非零 |
7 Sequence Parameter Set | 非零 |
8 Picture parameter set | 非零 |
13 Sequence parameter set extension | 非零 |
15 Subset Sequence parameter set | 非零 |
6,9,10,11,12 | 0 |
-
start code
:为了区分不同的NALU
的边界,通常每个NALU
都是以0x000001
或0x00000001
作为前缀的;如果当前NALU
是一帧的起始,则使用0x00000001
,否则使用0x000001
;Start Code + NALU + ... + Start Code + NALU = h.264 Byte Stream
-
SODB
:String of Data Bits. 原始数据比特流
定义
:一个包含多个字节的序列,表示在一个RBSP
中位于RBSP Stop bit
之前的多个字节;在SODB
中越靠左的比特越有意义; -
RBSP
:Raw Byte Sequence Payload,原始数据字节流负载;
定义
:包含多个字节的封装在NALU
中的一个语法结构;一个RBSP
要么为空,要么为由以下格式组成:一个SODB
后面接一个RBSP Stop bit
,然后接一个或多个均等于0的比特;RGSP
总是字节对齐的(8-bits),通过RBSP Stop bit
后添加0的方式;SODB + RBSP Stopbit + 0 bit(s) = RBSP
RBSP Stop bit
:位于RGSP
中的SODB
之后的值为1且长度为1比特,用于标识SODB
的结束;由于它是当前RBSP
的最后一个非零比特位,可以方便定位RGSP
中的SODB
; -
EBSP
: Encapsulated Byte Sequence Payload,封装字节流负载;上面提到了作为NALU
分隔符的Start Code
,然而在RBSP
中可能存在0x00000X
的数据格式(X = 1, 2, 3)的数据流与起始码数据结构非常相似;因此为了简化解码过程,在编码的时候遇到0x00000X
会在其后插入emulation_prevention_three_byte (0x03)
,使之转换为0x0000030X
;在解码过程中会忽略emulation_prevention_three_byte (0x03),保证解码正确;RBSP partA + 0x03 + RBSP partB+ 0x03 + ... + RBSP + 0x03 = EBSP NALU Header + EBSP = NALU
PPS
:Picture Parameter Set,序列参数集,nal_unit_type
等于8;多个NALU
组成一个视频帧,该视频帧相关的元数据(metadata)保存在PPS
中;PPS
通常独立保存在一个NAL unit中;包含的语法元素及含义
语法元素 | 含义 |
---|---|
pic_parameter_set_id | 当前PPS的id,可用于slice引用PPS,取值0-255 |
seq_parameter_set_id | 当前PPS所引用的激活的SPS的id,通过该方式可以PPS中获取到对应SPS的参数,取值0-31 |
entropy_coding_mode_flag | 熵编码模式标识;部分语法元素在不同的编码配置中选择不同的熵编码方式,比如一个宏块的语法元素描述符为"ue(v)|ae(v)",则在baseline profile等设置下使用指数哥伦布编码,在main profile等设置下使用CABAC编码;该标识为0,选择左侧算法,通常为指数哥伦布编码 或CAVLC ;该值为1时,选择右边算法,通常为CABAC |
num_slice_groups_minus1 | 标识一帧中slice group的个数;该值为0,标识该帧中的所有slice属于统一一个slice group; |
weighted_pred_flag | 是否在P/SP slice中开启加权预测的标识位 |
```js
在封装格式中,`SPS`、`PPS`、`SEI`等信息也会保存在视频文件的文件头中
```
SPS
:Sequence Parameter Set,序列参数集,nal_unit_type
等于7;多个PPS
组成一个视频学历,该序列相关的原始数据保存在SPS
中;一般SPS的第一个字节和第3个字节分别为profile_idc
和level_idc
,
语法元素 | 含义 |
---|---|
profile_idc | 标识当前H.264流的profile,profile用于控制食品的压缩特性(越大压缩特性越高),有3中可选值:baseline profile(66)、main profile(77)、extended profile(88) ,high profile(>=100),通常一个字节表示 |
level_idc | 标识当前麻溜的Level。level定义了特定条件下的最大视频分辨率、最大视频帧率等参数,通常一个字节表示;level越大, 一定条件下分辨率、码率、帧率等越高 |
seq_parameter_set_id | 当前SPS的id |
log2_max_frame_num_minus4 | MaxFrameNum的对数值 |
max_num_ref_frames | 参考帧最大数值 |
pic_width_in_mbs_minus1 | 单位为宏块个数,可用于计算图像的宽度值;frame_width = (pic_width_in_mbs_minus1 + 1) * 16(16是基于macroblock的大小为1616); |
frame_cropping_flag | 是否对输出图像进行裁剪的标识位 |
SEI
:Supplymental Enhancement Information,辅助增强信息,包含了增强视频的 一些辅助信息;比如直播答题中增加一些与视频信息同步的文本信息,或者字幕信息控制等用户自定义信息均可以放在SEI中;生成SEI中的方式包括编码时生成SEI及容器封装时写入SEI信息等;宏块
:是运动预测的基本单位,通常一张完整的帧可以分为多个宏块,宏块是选择特定预测类型的基准,整个图像可以使用不同的预测类型;
Demo
通常,在一个H.164的字节流中,第一个NALU为SPS,第二个NALU为PPS,第三个NALU为IDR
如下,是一个H.264
的字节流,可以得到印证;可以看到0x67对应的是SPS的NALU Header,0x64
为profile_idc
,对应为十进制的100,表示high profile;0x33
为level_idc
,对应的十进制为51,表示level=5.1,所以该码流的profile
和level
可以记为High@L5.1
;使用mediaInfo直接查看对应信息可以验证;
具体的profile
和Level
值的映射表可以参考wikipedia。