1. 一些约定
byte_aligned() |
返回该当前字节是否到了字节末尾,是则返回true |
more_data_in_byte_stream() |
Annex B规定的 字节流NAL单元 中使用 指示是否还有后续的数据,是则返回true |
more_rbsp_data() |
没有更多RBSP数据,返回false 否则,当搜索到RBSP中最后一个为1的比特(就是rbsp_stop_one_bit,rbsp_trailing_bits()的第一位),如果rbsp_trailing_bits()之前还有更多RBSP数据,则,返回true;否则返回false |
more_rbsp_trailing_data( ) |
是否RBSP有更多数据,是则返回true |
next_bits( n ) |
读取接来下n比特数据,不移动指针 不足n比特返回0 |
read_bits( n ) |
读取接来下n比特数据,并移动指针 n=0时返回0 |
Categories |
Slice DataPartition包括Category=2的语义元素 |
Slice DataPartition包括Category=3的语义元素 |
|
Slice DataPartition包括Category=4的语义元素 |
2. 描述子 (Descriptor)
如果有竖线,左边表示entropy_coding_mode_flag=0时使用,竖线右边则为1时使用
ae(v) |
用cabac编码的语义元素 |
b(8) |
任意形式的8比特,解析过程由read_bits(8)的返回值规定 |
ce(v) |
用cavlc编码的语义元素 |
f(n) |
n位固定模式比特,解析过程由read_bits(n)的返回值规定 |
i(n) |
n比特有符号整数,如果n由v代替,则n通过其他渠道规定 解析过程由read_bits(n)的返回值被译成2的补码形式规定 ???? The parsing process for this descriptor is specified by the return value of the function read_bits( n ) interpreted as a two's complement integer representation with most significant bit written first. (有符号整数的二进制) |
me(v) |
指数哥伦布编码的语义元素(Exp_Golomb) |
se(v) |
有符号整数指数哥伦布编码的语义元素 |
te(v) |
截断指数哥伦布编码的语义元素(Truncated EG) |
u(n) |
无符号n比特整数,如果n由v代替,则n通过其他渠道规定 解析过程由read_bits(n)的返回值用无符号整数的二进制表示规定 |
ue(v) |
无符号整数指数哥伦布编码的语义元素 |
3. 数据分割片:
A:片头和片中每个宏块头数据
B:Intra和SI片宏块的编码残差数据
C:Inter宏块的编码残差数据
IDR片不分割 其他片是否分割视情况而定
4. 几个概念之间的关系
每个NAL单元包含一个RBSP
RBSP的头信息定义了RBSP单元的类型
SPS:seq_parameter_set_id,帧数,POC约束,参考帧数目,解码图像尺寸和帧场编码模式选择标识等
PPS:pic_parameter_set_id,可选的seq_parameter_set_id,熵编码模式选择标识,片组数目,初始量化参数和去方块滤波系数调整标识等
5. NAL单元句法
nal_unit( NumBytesInNALunit ) { |
C |
Descriptor |
forbidden_zero_bit 恒=0,补齐8比特用 |
All |
f(1) |
nal_ref_idc NAL单元优先级(0-3) |
All |
u(2) |
nal_unit_type NAL单元类型 |
All |
u(5) |
NumBytesInRBSP = 0 |
|
|
nalUnitHeaderBytes = 1 |
|
|
if( nal_unit_type = = 14 | | nal_unit_type = = 20 ) { |
|
|
svc_extension_flag |
All |
u(1) |
if( svc_extension_flag ) |
|
|
nal_unit_header_svc_extension( ) /* specified in Annex G */ |
All |
|
else |
|
|
nal_unit_header_mvc_extension( ) /* specified in Annex H */ |
All |
|
nalUnitHeaderBytes += 3 |
|
|
} |
|
|
for( i = nalUnitHeaderBytes; i < NumBytesInNALunit; i++ ) { |
|
|
if( i + 2 < NumBytesInNALunit && next_bits( 24 ) = = 0x000003 ) { |
|
|
rbsp_byte[ NumBytesInRBSP++ ] |
All |
b(8) |
rbsp_byte[ NumBytesInRBSP++ ] |
All |
b(8) |
i += 2 |
|
|
emulation_prevention_three_byte /* equal to 0x03 */ |
All |
f(8) |
} else |
|
|
rbsp_byte[ NumBytesInRBSP++ ] |
All |
b(8) |
} |
|
|
} |
|
|
1) 每个NAL单元可以有 起始码前缀 和 额外填充单元(填充若干个字节0在起始码前缀前实现每个NAL单元长度对齐-------介质存储)
2) 起始码0x000001,填充0x000000
防止竞争
0x000000 |
0x00000300 |
0x000001 |
0x00000301 |
0x000002 |
0x00000302 |
0x000003 |
0x00000303 |
注意:在RBSP最后,如果没有cabac_zero_word,最后一个字节肯定不是0x00,但是如果最后由一个或者多个cabac_zero_word,则,需要在末尾填上一个0x03.
因为码流里除了起始,其他地方绝不能出现0x000001和0x000000
所以就连cabac_zero_word出现0x0000,0x0000,中间也要被0x03隔断!
3) 每次读一个NAL单元,检测到下个NAL单元起始码,就可以计算出NumBytesInNALunit
4) nal_ref_idc:优先级
非0:包含序列参数集、序列参数集extension,subset序列参数集, 图像参数集, 参考图像slice, 参考图像的slice data partition, 参考图像slice的NAL单元前缀
为0:非参考图像的slice或者slice data partition
-1) 序列参数集、序列参数集extension,subset序列参数集, 图像参数集的nal_ref_idc不应为0,如果nal_ref_idc=0且nal_unit_type=1~4,那所有的nal_unit_type=1~4的nal_ref_idc=0
-2) nal_unit_type=5时,nal_ref_idc不能为0
-3) nal_unit_type=6,9,10,11,12时,nal_ref_idc为0
5) nal_unit_type:
nal_unit_type |
Content of NAL unit and RBSP syntax structure |
C |
Annex A NAL unit type class |
Annex G/H NAL unit type class |
0 |
未定义 |
|
non-VCL |
non-VCL |
1 |
不分区,非IDR图像的slice |
2, 3, 4 |
VCL |
VCL |
2 |
slice分区A |
2 |
VCL |
未使用 |
3 |
slice分区 B |
3 |
VCL |
未使用 |
4 |
slice分区C |
4 |
VCL |
未使用 |
5 |
IDR图像slice |
2, 3 |
VCL |
VCL |
6 |
补充增强单元信息(SEI) |