H264--4--H264编码[7]
-----------------------------------
编码器输出格式
----------------------------------
总的来说H264的码流的打包方式有两种,一种为annex-b byte stream format的格式,这个是绝大部分编码器的默认输出格式,就是每个帧的开头的3~4个字节是H264的start_code,0x00000001或者0x000001。
另一种是原始的NAL打包格式,就是开始的若干字节(1,2,4字节)是NAL的长度,而不是start_code,此时必须借助某个全局的数据来获得编码器的profile,level,PPS,SPS等信息才可以解码。
@之前还疑惑过PPS 和SPS是哪里来的,答案是编码器给出的。
------------------------------
编码数据流分析
------------------------------
首先明确一下,NAL数据流的组成:开始码+NAL头(forbidden_bit+nal_ref+nal_type)+RBSP
下面对一段H264编码数据流进行分析。
00 00 00 01 67 42 00 1E 99 A0 B1 31 00 00 00 01
H264的数据流分为两种,一种是NAL UNIT stream(RTP),一种是 bits stream,
两者可以互相转换。我们分析的这个是 bit stream,根据AnnexB
00 00 00 01 67 42 00 1E 99 A0 B1 31 是 一个NAL,在两个00 00 00 01之间
0110 0111 0100 0010 0000 0000 0001 1110 1001 1001 1010 0000 1011 0001 0011 0001
forbidden_zero_bit(1)= 0//网络传输正确
nal_ref_idc(2)= 11//参考值为3
nal_unit_type(5) = 0 0111:seq_parameter_set_rbsp( )//7,序列参数集
说明这个NALU的RBSP里装的是SPS数据 ,所以 processSPS
profile_idc(8):42:0100 0010
constraint_set0_flag(1):0
constraint_set1_flag(1):0
constraint_set2_flag(1):0
constraint_set3_flag(1):0
reserved_zero_4bits(4):0
level_idc(8):1E
seq_parameter_set_id(UE(V)):
ue(v): unsigned integer Exp-Golomb-coded syntax element with the left bit first. The parsing process for this descriptor is specified in subclause9.1
uvlC: 1001:根据Table9.1 , value= 0,只占1bit.
根据profile_idc忽略掉一部分。
log2_max_frame_num_minus4(ue(v): 001 1001,len = 5,value= 5
pic_order_cnt_type(ue(v)):01 1010,len = 3,value = 2
根据pic_order_cnt_type忽略几个参数
num_ref_frames(ue):010,len = 3,value = 1
0000 1011 0001 0011 0001
gaps_in_frame_num_value_allowed_flag(1) = 0
pic_width_in_mbs_minus1(ue):000 1011 ,len = 7,value = 10;
pic_height_in_map_units_minus1(ue):0001 001,len = 7,value = 8
frame_mbs_only_flag(1) = 1
忽略1
direct_8x8_inference_flag(1):0
忽略
vui_parameters_present_flag(1):0
忽略
NALU结束
68 CE 38 80 00 00 00 01
0110 1000
forbidden_zero_bit(1)= 0
nal_ref_idc(2)= 11
nal_unit_type(5) =01000:pic_parameter_set_rbsp( ),7.3.2.2//8图像参数集
1100
pic_parameter_set_id (ue)=0
seq_parameter_set_id(ue)=0
entropy_coding_mode_flag(1) :0, 重要的flag,0表示编码Exp-Golomb coded and CAVLC,1表示CABAC
pic_order_present_flag(1):0
1110
num_slice_groups_minus1(ue):0
忽略
num_ref_idx_l0_active_minus1(ue):0
num_ref_idx_l1_active_minus1(ue):0
weighted_pred_flag(1);0
0011 1000 1000 0000
weighted_bipred_idc(2):00
pic_init_qp_minus26 /* relative to 26 */(se):0
pic_init_qs_minus26 /* relative to 26 */(se):0
chroma_qp_index_offset(se):0
deblocking_filter_control_present_flag(1);0
constrained_intra_pred_flag(1):0
redundant_pic_cnt_present_flag(1):0
忽略
NALU结束
65 88 80 21 71 27 1B 88…….3888*16 byte
65:0110 0101
forbidden_zero_bit(1)= 0
nal_ref_idc(2)= 11
nal_unit_type(5) =0 0101:slice_layer_without_partitioning_rbsp( )//IDR帧
Slice
Slice_Header:
first_mb_in_slice(ue):0
slice_type(ue):000 1000 = 7
pic_parameter_set_id(ue) = 0
80 21:000 0000 0010 0001
frame_num(u(v): frame_num is used as an identifier for pictures and shall be represented by log2_max_frame_num_minus4 + 4 bits,9 bits = 0
忽略
if( nal_unit_type = = 5 ) //IDR frame
idr_pic_id(u(e)):0
忽略N多
ref_pic_list_reordering( ) 见7。3。3。1忽略,Islice,SI slice,B slice
nal_ref_idc =11 所以dec_ref_pic_marking( )
nal_unit_type = 5,所以
no_output_of_prior_pics_flag(1):0
long_term_reference_flag(1):0
忽略
。。71 27
001 0111 0001 0010 0111
slice_qp_delta(se(v):001 01,4:-2
忽略
slice_data( ):7.3.4
对I-Slice:忽略N多
进入if( moreDataFlag ) { if( MbaffFrameFlag && ( CurrMbAddr % 2 = = 0 | | ( CurrMbAddr % 2 = = 1 && prevMbSkipped ) ) )mb_field_decoding_flag
macroblock_layer( )}
mb_field_decoding_flag忽略
macroblock_layer( )
mb_type(ue(v):0
mb_pred( mb_type )
prev_intra4x4_pred_mode_flag[ luma4x4BlkIdx ](1bit,对babac是ae(v)):1
1 27:0001 0010 0111
prev_intra4x4_pred_mode_flag[ 1 ] : 0001,0,001
0010 0111
prev_intra4x4_pred_mode_flag[ 2 ] : 0010,0,010
prev_intra4x4_pred_mode_flag[ 3] : 0111,0,111
……16个
1b 88 00 3e cf.
intra_chroma_pred_mode(ue(v)) :最后的一个1bit:0
接下来是macroblock_layer的coded_block_pattern和run level,既系数
c0 06 ad a0 18
1100 0000 0000 0110 1010 0000 0001 1000
coded_block_pattern(me(v):0,根据T= 47,0x2f
mb_qp_delta(se(v):):0 len =1
residual( )见7.3.5.3
residual_block( LumaLevel[ i8x8 * 4 + i4x4 ], 16 )
coeff_token(ce(v): 00 0000 0000 0110 1
nc = 0(left block and top block 相关的):
len: { // 0702
{ 1, 6, 8, 9,10,11,13,13,13,14,14,15,15,16,16,16,16},
{ 0, 2, 6, 8, 9,10,11,13,13,14,14,15,15,15,16,16,16},
{ 0, 0, 3, 7, 8, 9,10,11,13,13,14,14,15,15,16,16,16},
{ 0, 0, 0, 5, 6, 7, 8, 9,10,11,13,14,14,15,15,16,16},
},
{
{ 2, 6, 6, 7, 8, 8, 9,11,11,12,12,12,13,13,13,14,14},
{ 0, 2, 5, 6, 6, 7, 8, 9,11,11,12,12,13,13,14,14,14},
{ 0, 0, 3, 6, 6, 7, 8, 9,11,11,12,12,13,13,13,14,14},
{ 0, 0, 0, 4, 4, 5, 6, 6, 7, 9,11,11,12,13,13,13,14},
},
{
{ 4, 6, 6, 6, 7, 7, 7, 7, 8, 8, 9, 9, 9,10,10,10,10},
{ 0, 4, 5, 5, 5, 5, 6, 6, 7, 8, 8, 9, 9, 9,10,10,10},
{ 0, 0, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,10,10,10},
{ 0, 0, 0, 4, 4, 4, 4, 4, 5, 6, 7, 8, 8, 9,10,10,10},
},
code:
{ 1, 5, 7, 7, 7, 7,15,11, 8,15,11,15,11,15,11, 7,4},
{ 0, 1, 4, 6, 6, 6, 6,14,10,14,10,14,10, 1,14,10,6},
{ 0, 0, 1, 5, 5, 5, 5, 5,13, 9,13, 9,13, 9,13, 9,5},
{ 0, 0, 0, 3, 3, 4, 4, 4, 4, 4,12,12, 8,12, 8,12,8},
},
{
{ 3,11, 7, 7, 7, 4, 7,15,11,15,11, 8,15,11, 7, 9,7},
{ 0, 2, 7,10, 6, 6, 6, 6,14,10,14,10,14,10,11, 8,6},
{ 0, 0, 3, 9, 5, 5, 5, 5,13, 9,13, 9,13, 9, 6,10,5},
{ 0, 0, 0, 5, 4, 6, 8, 4, 4, 4,12, 8,12,12, 8, 1,4},
},
{
{15,15,11, 8,15,11, 9, 8,15,11,15,11, 8,13, 9, 5,1},
{ 0,14,15,12,10, 8,14,10,14,14,10,14,10, 7,12, 8,4},
{ 0, 0,13,14,11, 9,13, 9,13,10,13, 9,13, 9,11, 7,3},
{ 0, 0, 0,12,11,10, 9, 8,13,12,12,12, 8,12,10, 6,2},
},
根据表查的:
code = 13,len = 15,i= 12,j=2
所以numcoeff = 12,numtrailingones = 2
010 0000 0001 1000: totalzeros:根据numcoeff
int lentab[TOTRUN_NUM][16] =
{
{ 1,3,3,4,4,5,5,6,6,7,7,8,8,9,9,9},
{ 3,3,3,3,3,4,4,4,4,5,5,6,6,6,6},
{ 4,3,3,3,4,4,3,3,4,5,5,6,5,6},
{ 5,3,4,4,3,3,3,4,3,4,5,5,5},
{ 4,4,4,3,3,3,3,3,4,5,4,5},
{ 6,5,3,3,3,3,3,3,4,3,6},
{ 6,5,3,3,3,2,3,4,3,6},
{ 6,4,5,3,2,2,3,3,6},
{ 6,6,4,2,2,3,2,5},
{ 5,5,3,2,2,2,4},
{ 4,4,3,3,1,3},
{ 4,4,2,1,3}, numcoeff开始
{ 3,3,1,2},
{ 2,2,1},
{ 1,1},
};
int codtab[TOTRUN_NUM][16] =
{
{1,3,2,3,2,3,2,3,2,3,2,3,2,3,2,1},
{7,6,5,4,3,5,4,3,2,3,2,3,2,1,0},
{5,7,6,5,4,3,4,3,2,3,2,1,1,0},
{3,7,5,4,6,5,4,3,3,2,2,1,0},
{5,4,3,7,6,5,4,3,2,1,1,0},
{1,1,7,6,5,4,3,2,1,1,0},
{1,1,5,4,3,3,2,1,1,0},
{1,1,1,3,3,2,2,1,0},
{1,0,1,3,2,1,1,1,},
{1,0,1,3,2,1,1,},
{0,1,1,2,1,3},
{0,1,1,1,1}, numcoeff开始
{0,1,1,1},
{0,1,1},
{0,1},
};
Code = 1,len = 2,i=2,j = 0, totzeros = 2
Read run: 0 0000 0001 1000根据totzeros = 2
int lentab[TOTRUN_NUM][16] =
{
{1,1},
{1,2,2},
{2,2,2,2},
{2,2,2,3,3},
{2,2,3,3,3,3},
{2,3,3,3,3,3,3},
{3,3,3,3,3,3,3,4,5,6,7,8,9,10,11},
};
int codtab[TOTRUN_NUM][16] =
{
{1,0},
{1,1,0},
{3,2,1,0},
{3,2,1,1,0},
{3,2,3,2,1,0},
{3,0,1,3,2,5,4},
{7,6,5,4,3,2,1,1,1,1,1,1,1,1,1},
Code = 1,len =1,I = 0,j = 0
0.1.1 Slice data syntax
slice_data( ) { |
C |
Descriptor |
if( entropy_coding_mode_flag ) |
||
while( !byte_aligned( ) ) |
||
cabac_alignment_one_bit |
2 |
f(1) |
CurrMbAddr = first_mb_in_slice * ( 1 + MbaffFrameFlag ) |
||
moreDataFlag = 1 |
||
prevMbSkipped = 0 |
||
do { |
||
if( slice_type != I && slice_type != SI ) |
||
if( !entropy_coding_mode_flag ) { |
||
mb_skip_run |
2 |
ue(v) |
prevMbSkipped = ( mb_skip_run > 0 ) |
||
for( i=0; i<mb_skip_run; i++ ) |
||
CurrMbAddr = NextMbAddress( CurrMbAddr ) |
||
moreDataFlag = more_rbsp_data( ) |
||
} else { |
||
mb_skip_flag |
2 |
ae(v) |
moreDataFlag = !mb_skip_flag |
||
} |
||
if( moreDataFlag ) { |
||
if( MbaffFrameFlag && ( CurrMbAddr % 2 = = 0 | | ( CurrMbAddr % 2 = = 1 && prevMbSkipped ) ) ) |
||
mb_field_decoding_flag |
2 |
u(1) | ae(v) |
macroblock_layer( ) |
2 | 3 | 4 |
|
} |
||
if( !entropy_coding_mode_flag ) |
||
moreDataFlag = more_rbsp_data( ) |
||
else { |
||
if( slice_type != I && slice_type != SI ) |
||
prevMbSkipped = mb_skip_flag |
||
if( MbaffFrameFlag && CurrMbAddr % 2 = = 0 ) |
||
moreDataFlag = 1 |
||
else { |
||
end_of_slice_flag |
2 |
ae(v) |
moreDataFlag = !end_of_slice_flag |
||
} |
||
} |
||
CurrMbAddr = NextMbAddress( CurrMbAddr ) |
||
} while( moreDataFlag ) |
||
} |
se(v) : CABAC正式介绍。根据Table 9 5 – coeff_token mapping to TotalCoeff( coeff_token ) and TrailingOnes( coeff_token )。
chroma_format_idc 无
Table 9‑1 – Bit strings with “prefix” and “suffix” bits and assignment to codeNum ranges (informative)
Bit string form |
Range of codeNum |
1 |
0 |
0 1 x0 |
1-2 |
0 0 1 x1 x0 |
3-6 |
0 0 0 1 x2 x1 x0 |
7-14 |
0 0 0 0 1 x3 x2 x1 x0 |
15-30 |
0 0 0 0 0 1 x4 x3 x2 x1 x0 |
31-62 |
… |
… |
0.1.1.1 Slice layer without partitioning RBSP syntax
slice_layer_without_partitioning_rbsp( ) { |
C |
Descriptor |
slice_header( ) |
2 |
|
slice_data( ) /* all categories of slice_data( ) syntax */ |
2 | 3 | 4 |
|
rbsp_slice_trailing_bits( ) |
2 |
|
} |
0.1.1.2 Sequence parameter set RBSP syntax
seq_parameter_set_rbsp( ) { |
C |
Descriptor |
profile_idc |
0 |
u(8) |
constraint_set0_flag |
0 |
u(1) |
constraint_set1_flag |
0 |
u(1) |
constraint_set2_flag |
0 |
u(1) |
constraint_set3_flag |
0 |
u(1) |
reserved_zero_4bits /* equal to 0 */ |
0 |
u(4) |
level_idc |
0 |
u(8) |
seq_parameter_set_id |
0 |
ue(v) |
if( profile_idc = = 100 | | profile_idc = = 110 | | |
||
chroma_format_idc |
0 |
ue(v) |
if( chroma_format_idc = = 3 ) |
||
residual_colour_transform_flag |
0 |
u(1) |
bit_depth_luma_minus8 |
0 |
ue(v) |
bit_depth_chroma_minus8 |
0 |
ue(v) |
qpprime_y_zero_transform_bypass_flag |
0 |
u(1) |
seq_scaling_matrix_present_flag |
0 |
u(1) |
if( seq_scaling_matrix_present_flag ) |
||
for( i = 0; i < 8; i++ ) { |
||
seq_scaling_list_present_flag[ i] |
0 |
u(1) |
if( seq_scaling_list_present_flag[ i ] ) |
||
if( i < 6 ) |
||
scaling_list( ScalingList4x4[ i ], 16, |
0 |
|
else |
||
scaling_list( ScalingList8x8[ i – 6 ], 64, |
0 |
|
} |
||
} |
||
log2_max_frame_num_minus4 |
0 |
ue(v) |
pic_order_cnt_type |
0 |
ue(v) |
if( pic_order_cnt_type = = 0 ) |
||
log2_max_pic_order_cnt_lsb_minus4 |
0 |
ue(v) |
else if( pic_order_cnt_type = = 1 ) { |
||
delta_pic_order_always_zero_flag |
0 |
u(1) |
offset_for_non_ref_pic |
0 |
se(v) |
offset_for_top_to_bottom_field |
0 |
se(v) |
num_ref_frames_in_pic_order_cnt_cycle |
0 |
ue(v) |
for( i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++ ) |
||
offset_for_ref_frame[ i ] |
0 |
se(v) |
} |
||
num_ref_frames |
0 |
ue(v) |
gaps_in_frame_num_value_allowed_flag |
0 |
u(1) |
pic_width_in_mbs_minus1 |
0 |
ue(v) |
pic_height_in_map_units_minus1 |
0 |
ue(v) |
frame_mbs_only_flag |
0 |
u(1) |
if( !frame_mbs_only_flag ) |
||
mb_adaptive_frame_field_flag |
0 |
u(1) |
direct_8x8_inference_flag |
0 |
u(1) |
frame_cropping_flag |
0 |
u(1) |
if( frame_cropping_flag ) { |
||
frame_crop_left_offset |
0 |
ue(v) |
frame_crop_right_offset |
0 |
ue(v) |
frame_crop_top_offset |
0 |
ue(v) |
frame_crop_bottom_offset |
0 |
ue(v) |
} |
||
vui_parameters_present_flag |
0 |
u(1) |
if( vui_parameters_present_flag ) |
||
vui_parameters( ) |
0 |
|
rbsp_trailing_bits( ) |
0 |
|
} |
Table 7‑1 – NAL unit type codes
nal_unit_type |
Content of NAL unit and RBSP syntax structure |
C |
0 |
Unspecified |
|
1 |
Coded slice of a non-IDR picture |
2, 3, 4 |
2 |
Coded slice data partition A |
2 |
3 |
Coded slice data partition B |
3 |
4 |
Coded slice data partition C |
4 |
5 |
Coded slice of an IDR picture |
2, 3 |
6 |
Supplemental enhancement information (SEI) |
5 |
7 |
Sequence parameter set |
0 |
8 |
Picture parameter set |
1 |
9 |
Access unit delimiter |
6 |
10 |
End of sequence |
7 |
11 |
End of stream |
8 |
12 |
Filler data |
9 |
13 |
Sequence parameter set extension |
10 |
14..18 |
Reserved |
|
19 |
Coded slice of an auxiliary coded picture without partitioning |
2, 3, 4 |
20..23 |
Reserved |
|
24..31 |
Unspecified |
byte_stream_nal_unit( NumBytesInNALunit ) { |
C |
Descriptor |
while( next_bits( 24 ) != 0x000001 && |
||
leading_zero_8bits /* equal to 0x00 */ |
f(8) |
|
if( next_bits( 24 ) != 0x000001 ) |
||
zero_byte /* equal to 0x00 */ |
f(8) |
|
start_code_prefix_one_3bytes /* equal to 0x000001 */ |
f(24) |
|
nal_unit( NumBytesInNALunit) |
||
while( more_data_in_byte_stream( ) && |
||
trailing_zero_8bits /* equal to 0x00 */ |
f(8) |
|
} |
0.1.1.3 Picture parameter set RBSP syntax
pic_parameter_set_rbsp( ) { |
C |
Descriptor |
pic_parameter_set_id |
1 |
ue(v) |
seq_parameter_set_id |
1 |
ue(v) |
entropy_coding_mode_flag |
1 |
u(1) |
pic_order_present_flag |
1 |
u(1) |
num_slice_groups_minus1 |
1 |
ue(v) |
if( num_slice_groups_minus1 > 0 ) { |
||
slice_group_map_type |
1 |
ue(v) |
if( slice_group_map_type = = 0 ) |
||
for( iGroup = 0; iGroup <= num_slice_groups_minus1; iGroup++ ) |
||
run_length_minus1[ iGroup ] |
1 |
ue(v) |
else if( slice_group_map_type = = 2 ) |
||
for( iGroup = 0; iGroup < num_slice_groups_minus1; iGroup++ ) { |
||
top_left[ iGroup ] |
1 |
ue(v) |
bottom_right[ iGroup ] |
1 |
ue(v) |
} |
||
else if( slice_group_map_type = = 3 | | |
||
slice_group_change_direction_flag |
1 |
u(1) |
slice_group_change_rate_minus1 |
1 |
ue(v) |
} else if( slice_group_map_type = = 6 ) { |
||
pic_size_in_map_units_minus1 |
1 |
ue(v) |
for( i = 0; i <= pic_size_in_map_units_minus1; i++ ) |
||
slice_group_id[ i ] |
1 |
u(v) |
} |
||
} |
||
num_ref_idx_l0_active_minus1 |
1 |
ue(v) |
num_ref_idx_l1_active_minus1 |
1 |
ue(v) |
weighted_pred_flag |
1 |
u(1) |
weighted_bipred_idc |
1 |
u(2) |
pic_init_qp_minus26 /* relative to 26 */ |
1 |
se(v) |
pic_init_qs_minus26 /* relative to 26 */ |
1 |
se(v) |
chroma_qp_index_offset |
1 |
se(v) |
deblocking_filter_control_present_flag |
1 |
u(1) |
constrained_intra_pred_flag |
1 |
u(1) |
redundant_pic_cnt_present_flag |
1 |
u(1) |
if( more_rbsp_data( ) ) { |
||
transform_8x8_mode_flag |
1 |
u(1) |
pic_scaling_matrix_present_flag |
1 |
u(1) |
if( pic_scaling_matrix_present_flag ) |
||
for( i = 0; i < 6 + 2* transform_8x8_mode_flag; i++ ) { |
||
pic_scaling_list_present_flag[ i] |
1 |
u(1) |
if( pic_scaling_list_present_flag[ i ] ) |
||
if( i < 6 ) |
||
scaling_list( ScalingList4x4[ i ], 16, |
1 |
|
else |
||
scaling_list( ScalingList8x8[ i – 6 ], 64, |
1 |
|
} |
||
second_chroma_qp_index_offset |
1 |
se(v) |
} |
||
rbsp_trailing_bits( ) |
1 |
|
} |
0.1.2 Slice header syntax
slice_header( ) { |
C |
Descriptor |
first_mb_in_slice |
2 |
ue(v) |
slice_type |
2 |
ue(v) |
pic_parameter_set_id |
2 |
ue(v) |
frame_num |
2 |
u(v) |
if( !frame_mbs_only_flag ) { |
||
field_pic_flag |
2 |
u(1) |
if( field_pic_flag ) |
||
bottom_field_flag |
2 |
u(1) |
} |
||
if( nal_unit_type = = 5 ) |
||
idr_pic_id |
2 |
ue(v) |
if( pic_order_cnt_type = = 0 ) { |
||
pic_order_cnt_lsb |
2 |
u(v) |
if( pic_order_present_flag && !field_pic_flag ) |
||
delta_pic_order_cnt_bottom |
2 |
se(v) |
} |
||
if( pic_order_cnt_type = = 1 && !delta_pic_order_always_zero_flag ) { |
||
delta_pic_order_cnt[ 0 ] |
2 |
se(v) |
if( pic_order_present_flag && !field_pic_flag ) |
||
delta_pic_order_cnt[ 1 ] |
2 |
se(v) |
} |
||
if( redundant_pic_cnt_present_flag ) |
||
redundant_pic_cnt |
2 |
ue(v) |
if( slice_type = = B ) |
||
direct_spatial_mv_pred_flag |
2 |
u(1) |
if( slice_type = = P | | slice_type = = SP | | slice_type = = B ) { |
||
num_ref_idx_active_override_flag |
2 |
u(1) |
if( num_ref_idx_active_override_flag ) { |
||
num_ref_idx_l0_active_minus1 |
2 |
ue(v) |
if( slice_type = = B ) |
||
num_ref_idx_l1_active_minus1 |
2 |
ue(v) |
} |
||
} |
||
ref_pic_list_reordering( ) |
2 |
|
if( ( weighted_pred_flag && ( slice_type = = P | | slice_type = = SP ) ) | | |
||
pred_weight_table( ) |
2 |
|
if( nal_ref_idc != 0 ) |
||
dec_ref_pic_marking( ) |
2 |
|
if( entropy_coding_mode_flag && slice_type != I && slice_type != SI ) |
||
cabac_init_idc |
2 |
ue(v) |
slice_qp_delta |
2 |
se(v) |
if( slice_type = = SP | | slice_type = = SI ) { |
||
if( slice_type = = SP ) |
||
sp_for_switch_flag |
2 |
u(1) |
slice_qs_delta |
2 |
se(v) |
} |
||
if( deblocking_filter_control_present_flag ) { |
||
disable_deblocking_filter_idc |
2 |
ue(v) |
if( disable_deblocking_filter_idc != 1 ) { |
||
slice_alpha_c0_offset_div2 |
2 |
se(v) |
slice_beta_offset_div2 |
2 |
se(v) |
} |
||
} |
||
if( num_slice_groups_minus1 > 0 && |
||
slice_group_change_cycle |
2 |
u(v) |
} |
0.1.3 Slice data syntax
slice_data( ) { |
C |
Descriptor |
if( entropy_coding_mode_flag ) |
||
while( !byte_aligned( ) ) |
||
cabac_alignment_one_bit |
2 |
f(1) |
CurrMbAddr = first_mb_in_slice * ( 1 + MbaffFrameFlag ) |
||
moreDataFlag = 1 |
||
prevMbSkipped = 0 |
||
do { |
||
if( slice_type != I && slice_type != SI ) |
||
if( !entropy_coding_mode_flag ) { |
||
mb_skip_run |
2 |
ue(v) |
prevMbSkipped = ( mb_skip_run > 0 ) |
||
for( i=0; i<mb_skip_run; i++ ) |
||
CurrMbAddr = NextMbAddress( CurrMbAddr ) |
||
moreDataFlag = more_rbsp_data( ) |
||
} else { |
||
mb_skip_flag |
2 |
ae(v) |
moreDataFlag = !mb_skip_flag |
||
} |
||
if( moreDataFlag ) { |
||
if( MbaffFrameFlag && ( CurrMbAddr % 2 = = 0 | | ( CurrMbAddr % 2 = = 1 && prevMbSkipped ) ) ) |
||
mb_field_decoding_flag |
2 |
u(1) | ae(v) |
macroblock_layer( ) |
2 | 3 | 4 |
|
} |
||
if( !entropy_coding_mode_flag ) |
||
moreDataFlag = more_rbsp_data( ) |
||
else { |
||
if( slice_type != I && slice_type != SI ) |
||
prevMbSkipped = mb_skip_flag |
||
if( MbaffFrameFlag && CurrMbAddr % 2 = = 0 ) |
||
moreDataFlag = 1 |
||
else { |
||
end_of_slice_flag |
2 |
ae(v) |
moreDataFlag = !end_of_slice_flag |
||
} |
||
} |
||
CurrMbAddr = NextMbAddress( CurrMbAddr ) |
||
} while( moreDataFlag ) |
||
} |
The variable MbaffFrameFlag is derived as follows.
MbaffFrameFlag = ( mb_adaptive_frame_field_flag && !field_pic_flag ) (7-22)
0.1.4 Macroblock layer syntax
macroblock_layer( ) { |
C |
Descriptor |
mb_type |
2 |
ue(v) | ae(v) |
if( mb_type = = I_PCM ) { |
||
while( !byte_aligned( ) ) |
||
pcm_alignment_zero_bit |
2 |
f(1) |
for( i = 0; i < 256; i++ ) |
||
pcm_sample_luma[ i ] |
2 |
u(v) |
for( i = 0; i < 2 * MbWidthC * MbHeightC; i++ ) |
||
pcm_sample_chroma[ i ] |
2 |
u(v) |
} else { |
||
noSubMbPartSizeLessThan8x8Flag = 1 |
||
if( mb_type != I_NxN && MbPartPredMode( mb_type, 0 ) != Intra_16x16 && NumMbPart( mb_type ) = = 4 ) { |
||
sub_mb_pred( mb_type ) |
2 |
|
for( mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++ ) |
||
if( sub_mb_type[ mbPartIdx ] != B_Direct_8x8 ) { |
||
if( NumSubMbPart( sub_mb_type[ mbPartIdx ] ) > 1 ) |
||
noSubMbPartSizeLessThan8x8Flag = 0 |
||
} else if( !direct_8x8_inference_flag ) |
||
noSubMbPartSizeLessThan8x8Flag = 0 |
||
} else { |
||
if( transform_8x8_mode_flag && mb_type = = I_NxN ) |
||
transform_size_8x8_flag |
2 |
u(1) | ae(v) |
mb_pred( mb_type ) |
2 |
|
} |
||
if( MbPartPredMode( mb_type, 0 ) != Intra_16x16 ) { |
||
coded_block_pattern |
2 |
me(v) | ae(v) |
if( CodedBlockPatternLuma > 0 && transform_8x8_mode_flag && mb_type != I_NxN && noSubMbPartSizeLessThan8x8Flag && ( mb_type != B_Direct_16x16 | | direct_8x8_inference_flag ) ) |
||
transform_size_8x8_flag |
2 |
u(1) | ae(v) |
} |
||
if( CodedBlockPatternLuma > 0 | | CodedBlockPatternChroma > 0 | | |
||
mb_qp_delta |
2 |
se(v) | ae(v) |
residual( ) |
3 | 4 |
|
} |
||
} |
||
} |
0.1.4.1 Macroblock prediction syntax
mb_pred( mb_type ) { |
C |
Descriptor |
if( MbPartPredMode( mb_type, 0 ) = = Intra_4x4 | | |
||
if( MbPartPredMode( mb_type, 0 ) = = Intra_4x4 ) |
||
for( luma4x4BlkIdx=0; luma4x4BlkIdx<16; luma4x4BlkIdx++ ) { |
||
prev_intra4x4_pred_mode_flag[ luma4x4BlkIdx ] |
2 |
u(1) | ae(v) |
if( !prev_intra4x4_pred_mode_flag[ luma4x4BlkIdx ] ) |
||
rem_intra4x4_pred_mode[ luma4x4BlkIdx ] |
2 |
u(3) | ae(v) |
} |
||
if( MbPartPredMode( mb_type, 0 ) = = Intra_8x8 ) |
||
for( luma8x8BlkIdx=0; luma8x8BlkIdx<4; luma8x8BlkIdx++ ) { |
||
prev_intra8x8_pred_mode_flag[ luma8x8BlkIdx ] |
2 |
u(1) | ae(v) |
if( !prev_intra8x8_pred_mode_flag[ luma8x8BlkIdx ] ) |
||
rem_intra8x8_pred_mode[ luma8x8BlkIdx ] |
2 |
u(3) | ae(v) |
} |
||
if( chroma_format_idc != 0 ) |
||
intra_chroma_pred_mode |
2 |
ue(v) | ae(v) |
} else if( MbPartPredMode( mb_type, 0 ) != Direct ) { |
||
for( mbPartIdx = 0; mbPartIdx < NumMbPart( mb_type ); mbPartIdx++) |
||
if( ( num_ref_idx_l0_active_minus1 > 0 | | |
||
ref_idx_l0[ mbPartIdx ] |
2 |
te(v) | ae(v) |
for( mbPartIdx = 0; mbPartIdx < NumMbPart( mb_type ); mbPartIdx++) |
||
if( ( num_ref_idx_l1_active_minus1 > 0 | | |
||
ref_idx_l1[ mbPartIdx ] |
2 |
te(v) | ae(v) |
for( mbPartIdx = 0; mbPartIdx < NumMbPart( mb_type ); mbPartIdx++) |
||
if( MbPartPredMode ( mb_type, mbPartIdx ) != Pred_L1 ) |
||
for( compIdx = 0; compIdx < 2; compIdx++ ) |
||
mvd_l0[ mbPartIdx ][ 0 ][ compIdx ] |
2 |
se(v) | ae(v) |
for( mbPartIdx = 0; mbPartIdx < NumMbPart( mb_type ); mbPartIdx++) |
||
if( MbPartPredMode( mb_type, mbPartIdx ) != Pred_L0 ) |
||
for( compIdx = 0; compIdx < 2; compIdx++ ) |
||
mvd_l1[ mbPartIdx ][ 0 ][ compIdx ] |
2 |
se(v) | ae(v) |
} |
||
} |
0.1.4.2 Residual data syntax
residual( ) { |
C |
Descriptor |
if( !entropy_coding_mode_flag ) |
||
residual_block = residual_block_cavlc |
||
else |
||
residual_block = residual_block_cabac |
||
if( MbPartPredMode( mb_type, 0 ) = = Intra_16x16 ) |
||
residual_block( Intra16x16DCLevel, 16 ) |
3 |
|
for( i8x8 = 0; i8x8 < 4; i8x8++ ) /* each luma 8x8 block */ |
||
if( !transform_size_8x8_flag | | !entropy_coding_mode_flag ) |
||
for( i4x4 = 0; i4x4 < 4; i4x4++ ) { /* each 4x4 sub-block of block */ |
||
if( CodedBlockPatternLuma & ( 1 << i8x8 ) ) |
||
if( MbPartPredMode( mb_type, 0 ) = = Intra_16x16 ) |
||
residual_block( Intra16x16ACLevel[ i8x8 * 4 + i4x4 ], 15 ) |
3 |
|
else |
||
residual_block( LumaLevel[ i8x8 * 4 + i4x4 ], 16 ) |
3 | 4 |
|
else if( MbPartPredMode( mb_type, 0 ) = = Intra_16x16 ) |
||
for( i = 0; i < 15; i++ ) |
||
Intra16x16ACLevel[ i8x8 * 4 + i4x4 ][ i ] = 0 |
||
else |
||
for( i = 0; i < 16; i++ ) |
||
LumaLevel[ i8x8 * 4 + i4x4 ][ i ] = 0 |
||
if( !entropy_coding_mode_flag && transform_size_8x8_flag ) |
||
for( i = 0; i < 16; i++ ) |
||
LumaLevel8x8[ i8x8 ][ 4 * i + i4x4 ] = |
||
} |
||
else if( CodedBlockPatternLuma & ( 1 << i8x8 ) ) |
||
residual_block( LumaLevel8x8[ i8x8 ], 64 ) |
3 | 4 |
|
else |
||
for( i = 0; i < 64; i++ ) |
||
LumaLevel8x8[ i8x8 ][ i ] = 0 |
||
if( chroma_format_idc != 0 ) { |
||
NumC8x8 = 4 / ( SubWidthC * SubHeightC ) |
||
for( iCbCr = 0; iCbCr < 2; iCbCr++ ) |
||
if( CodedBlockPatternChroma & 3 ) /* chroma DC residual present */ |
||
residual_block( ChromaDCLevel[ iCbCr ], 4 * NumC8x8 ) |
3 | 4 |
|
else |
||
for( i = 0; i < 4 * NumC8x8; i++ ) |
||
ChromaDCLevel[ iCbCr ][ i ] = 0 |
||
for( iCbCr = 0; iCbCr < 2; iCbCr++ ) |
||
for( i8x8 = 0; i8x8 < NumC8x8; i8x8++ ) |
||
for( i4x4 = 0; i4x4 < 4; i4x4++ ) |
||
if( CodedBlockPatternChroma & 2 ) |
||
residual_block( ChromaACLevel[ iCbCr ][ i8x8*4+i4x4 ], 15) |
3 | 4 |
|
else |
||
for( i = 0; i < 15; i++ ) |
||
ChromaACLevel[ iCbCr ][ i8x8*4+i4x4 ][ i ] = 0 |
||
} |
residual_block_cavlc( coeffLevel, maxNumCoeff ) { |
C |
Descriptor |
for( i = 0; i < maxNumCoeff; i++ ) |
||
coeffLevel[ i ] = 0 |
||
coeff_token |
3 | 4 |
ce(v) |
if( TotalCoeff( coeff_token ) > 0 ) { |
||
if( TotalCoeff( coeff_token ) > 10 && TrailingOnes( coeff_token ) < 3 ) |
||
suffixLength = 1 |
||
else |
||
suffixLength = 0 |
||
for( i = 0; i < TotalCoeff( coeff_token ); i++ ) |
||
if( i < TrailingOnes( coeff_token ) ) { |
||
trailing_ones_sign_flag |
3 | 4 |
u(1) |
level[ i ] = 1 – 2 * trailing_ones_sign_flag |
||
} else { |
||
level_prefix |
3 | 4 |
ce(v) |
levelCode = ( Min( 15, level_prefix ) << suffixLength ) |
||
if( suffixLength > 0 | | level_prefix >= 14 ) { |
||
level_suffix |
3 | 4 |
u(v) |
levelCode += level_suffix |
||
} |
||
if( level_prefix > = 15 && suffixLength = = 0 ) |
||
levelCode += 15 |
||
if( level_prefix > = 16 ) |
||
levelCode += ( 1 << ( level_prefix – 3 ) ) – 4096 |
||
if( i = = TrailingOnes( coeff_token ) && |
||
levelCode += 2 |
||
if( levelCode % 2 = = 0 ) |
||
level[ i ] = ( levelCode + 2 ) >> 1 |
||
else |
||
level[ i ] = ( –levelCode – 1 ) >> 1 |
||
if( suffixLength = = 0 ) |
||
suffixLength = 1 |
||
if( Abs( level[ i ] ) > ( 3 << ( suffixLength – 1 ) ) && |
||
suffixLength++ |
||
} |
||
if( TotalCoeff( coeff_token ) < maxNumCoeff ) { |
||
total_zeros |
3 | 4 |
ce(v) |
zerosLeft = total_zeros |
||
} else |
||
zerosLeft = 0 |
||
for( i = 0; i < TotalCoeff( coeff_token ) – 1; i++ ) { |
||
if( zerosLeft > 0 ) { |
||
run_before |
3 | 4 |
ce(v) |
run[ i ] = run_before |
||
} else |
||
run[ i ] = 0 |
||
zerosLeft = zerosLeft – run[ i ] |
||
} |
||
run[ TotalCoeff( coeff_token ) – 1 ] = zerosLeft |
||
coeffNum = ‑1 |
||
for( i = TotalCoeff( coeff_token ) – 1; i >= 0; i-- ) { |
||
coeffNum += run[ i ] + 1 |
||
coeffLevel[ coeffNum ] = level[ i ] |
||
} |
||
} |
||
} |
H264--4--H264编码[7]相关推荐
- 1小时学会:最简单的iOS直播推流(八)h264/aac 软编码
最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有,愿意懂直播技术的同学快来看!! 源 ...
- 1小时学会:最简单的iOS直播推流(七)h264/aac 硬编码
最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有,愿意懂直播技术的同学快来看!! 源 ...
- ffmpeg使用h264、h265编码转换
1.编译x264 git clone https://code.videolan.org/videolan/x264.git cd x264 ./configure --enable-shared - ...
- iOS H264,H265视频编码(Video encode)
本例需求:使用H264, H265实现视频数据的编码并录制开始200帧存为文件. 原理:比如做直播功能,需要将客户端的视频数据传给服务器,如果分辨率过大如2K,4K则传输压力太大,所以需要对视频数据进 ...
- MPEG-4与H264区别,编码及应用
H264 编解码协议详解 https://blog.csdn.net/qq_19923217/article/details/83348095 H264视频--x264编解码原理详解 https:// ...
- H264和MPEG4编码哪一种画质更好,文件大小有区别吗?
H.264就是MPEG4,MPEG4只是H.264的封装格式而已,H.264可以封装为MPEG4或者MP4或者AVI,画质只是从画面分辨率来判断的,和文件无关系. 1. MPEG4是一整套视频压缩规范 ...
- H264和h265编码
未压缩的码流:一秒钟码流大小:640x480x1.5x15x8=55296000 (是55MB)其中 1.5是yuv占用1.5倍,rgb是3倍,8是一个字节是八位bit H264的建议码流是500kp ...
- 移植mp4v2开源库,h264+g711a/g711u编码mp4
1.mp4v2移植 step1.下载:https://launchpad.net/ubuntu/+source/mp4v2 step2.编译 简单配置参数: ./configure --host=ar ...
- H264压缩比和编码码率
在格式为YUV420的情况下,分辨率为1280x1024,帧率为60,每秒传输1280x1024x60X1.5x8 = 943,718,400 bit = 943.7184 Mbps,因此至少需要94 ...
- ffmpeg 将h264格式文件编码为MP4文件
1.在编码过程中涉及到一些时间戳相关概念主要: PTS:度量解码后的视频帧什么时候被显示出来: DTS:读入内存中的bit流在什么时候开始送入解码器中进行解码: duration:表示当前帧的持续时间 ...
最新文章
- 迷你世界电锯机器人_迷你世界:三分钟制作超简单飞翔石像机器人报道!
- Webpack 学习记录-02
- mxnet METRIC自定义评估验证函数
- 开源DDos 机器学习思路求解的一些源码——TODO 待分析
- HIVE元数据表/数据字典
- scrum与第一次teamwork
- 使用事务操作SQLite数据批量插入,提高数据批量写入速度,源码讲解
- python三维数据图_matplotlib中三维数据的热图
- word文档保存发生错误_文档还是没有发生
- mysql安装排错-解决1
- 02-橄榄球 VS 软件
- 机器学习笔记(十一):优化梯度公式 | 凌云时刻
- [Devcpp]为Devc自定义编译器及Devcpp路径读取的Bug
- CAN FD协议描述
- java 权重 分配_一种按权重分配的Java算法
- 电脑桌面数字时钟c语言,DesktopDigitalClock(桌面数字时钟)
- iso硬盘安装 凤凰os_在Linux中安装凤凰系统(Phoenix OS)的方法
- 游戏《我的世界》马怎么繁殖?如何驯化?
- 震惊,java8 Nashorn和laytpl居然能擦出这样火花!
- 对比学习的应用(SimCSE,CLEAR,DeCLUTR,DiffCSE)
热门文章
- filter过滤器_不了解布隆过滤器?一文给你整的明明白白
- php ajax 长轮询 表单,Thinkphp结合AJAX长轮询实现PC与APP推送详解
- android 三星 oom,android - 终结者抛出未捕获的异常:谷歌API错误或三星内核错误? - 堆栈内存溢出...
- win7计算机无法远程访问,win7无法被远程桌面连接的几种解决方法
- 编写一个程序,要求输入一个ASCII码值(如66),然后输入相应的字符`
- android打开sqlite数据库,Android:打开和关闭SQLite数据库
- MySQL The JSON Data Type(JSON格式数据)
- 编程语言对比 内存操作
- vue.js v-bind
- Python numpy基础知识