H.264格式
H.264是把原始的yuv文件编码成码流的文件。
H.264是由一系列startcode加NALU构成的
startcode | NALU | startcode | NALU | …… | startcode | NALU | startcode | NALU |
---|---|---|---|---|---|---|---|---|
RBSP = SODB + RBSP trailing bits
NALU = NAL header(1 byte) + RBSP
H.264 = Start Code Prefix(3 bytes) + NALU + Start Code Prefix(3 bytes) + NALU +…
startcode
起始码分两种:
0x00000001(4Byte)表示NALU对应的Slice为一帧的开始
0x000001(3Byte)
NALU
NAL header(1 byte) + RBSP = NALU
NAL headerbit0-bit4表示nal type(type见下表),bit5-bit6表示nal参考级别,bit7必须为0
nal_unit:
{
forbidden_zero_bit (1 bit)
nal_ref_idc (2 bits)
nal_unit_type (5 bits)
RBSP(Raw Byte Sequence Payloads)
}
如果一个包含一个条带或条带数据分割的NAL 单元的nal_ref_idc 等于0 时,该条带或条带数据分割是一个非参考图像的一部分。
对于序列参数集或序列参数集扩展或图像参数集的NAL单元,nal_ref_idc不应等于0。当一个特定的图像的一个条带或条带数据分割NAL单元的nal_ref_idc等于0,该图像的所有条带或条带数据划分NAL单元都应该等于0。
IDR NAL单元的nal_ref_idc不应等于0,即nal_unit_type等于5的NAL单元。
所有nal_unit_type等于6、9、10、11或12的NAL单元其nal_ref_idc都应等于0。
当解码器性能不足需要丢帧时,nal_ref_idc可以作为判断能否丢帧的依据。如果nal_ref_idc为0,则可以丢弃。当该帧nal_unit_type等于6,9,10,11或12时,nal_ref_idc为0。部分非IDR帧的nal_ref_idc也为0,也可以丢弃。丢弃的同时也能保证不会花屏。
RBSP尾部
标准中描述了很多种的RBSP结构并且通过语法表现出来,RBSP语法主要规定了该结构由什么成员组成,各个成员如何组合,成员会占用几个bit。不过虽然RBSP结构有很多种,但是他们也有一个共同点:都有一个RBSP尾部。
RBSP尾部的语法如下:
rbsp_trailing_bits( ) { C Descriptor
rbsp_stop_one_bit /* equal to 1 */ All f(1)
while( !byte_aligned( ) )
rbsp_alignment_zero_bit /* equal to 0 */ All f(1)
}
语法元素
- rbsp_stop_one_bit 1位的1
- rbsp_alignment_zero_bit 字节补零,目的是为了进行字节对齐
有一种特殊情况:如果采用的熵编码方式为CABAC,而且当前是实际图像内容相关的RBSP(名称包含slice的RBSP结构),那么会在RBSP尾部的后面添加1个或多个0x0000。语法表示如下:
rbsp_slice_trailing_bits( ) { C Descriptor
rbsp_trailing_bits( ) All
if( entropy_coding_mode_flag )
while( more_rbsp_trailing_data( ) )
cabac_zero_word /* equal to 0x0000 */ All f(16)
}
语法元素
- cabac_zero_word 0x0000
RBSP中除了rbsp_trailing_bits以及rbsp_slice_trailing_bits,其余部分被统称为SODB(String Of Data Bits)。
NALU结构
H.264码流分层次结构
一些定义
可变长度
可变长度,以非0xFF结束
int _read_ff_coded_number(bs_t* b)
{
int n1 = 0;
int n2;
do
{
n2 = bs_read_u8(b);
n1 += n2;
} while (n2 == 0xff);
return n1;
}
GOP
GOP 是画面组,一个 GOP 是一组连续的画面。
GOP 一般有两个数字,如 M = 3,N = 12,M 制定 I 帧与 P 帧之间的距离,N 指定两个 I 帧之间的距离。那么现在的 GOP 结构是
I BBP BBP BBP BB I
增大图片组能有效的减少编码后的视频体积,但是也会降低视频质量,至于怎么取舍,得看需求了。
工具
streameye
H.264 Visa
解码参考代码
https://github.com/jiayayao/h264_analysis/blob/master/NALParse.cpp
参考
https://www.cnblogs.com/TaigaCon/p/5215448.html
https://blog.csdn.net/shaqoneal/article/details/52080975