Table of Contents
5.11.3 clear_block_decoded_flags函数
5.11.7 intra_frame_mode_info语法
5.11.14 seg_feature_active_idx函数
5.11.18 inter_frame_mode_info语法
5.11.22 intra_block_mode_info语法
5.11.23 inter_block_mode_info语法
5.11.24 filter_intra_mode_info语法
5.11.28 read_interintra_mode语法
5.11.38 get_plane_residual_size函数
5.11.50 get_palette_color_context函数
5.11.52 is_inside_filter_region函数
5.11 Tile组OBU语法
5.11.1 tile_group_obu语法
tile_group_obu( sz )
{
NumTiles = TileCols * TileRows
startBitPos = get_position( )
tile_start_and_end_present_flag = 0
if ( NumTiles > 1 )
tile_start_and_end_present_flag // Type f(1)
if ( NumTiles == 1 || !tile_start_and_end_present_flag )
{
tg_start = 0
tg_end = NumTiles - 1
}
else
{
tileBits = TileColsLog2 + TileRowsLog2
tg_start // Type f(tileBits)
tg_end // Type f(tileBits)
}
byte_alignment( )
endBitPos = get_position( )
headerBytes = (endBitPos - startBitPos) / 8
sz -= headerBytes
for ( TileNum = tg_start; TileNum <= tg_end; TileNum++ )
{
tileRow = TileNum / TileCols
tileCol = TileNum % TileCols
lastTile = TileNum == tg_end
if ( lastTile )
{
tileSize = sz
}
else
{
tile_size_minus_1 // Type le(TileSizeBytes)
tileSize = tile_size_minus_1 + 1
sz -= tileSize + TileSizeBytes
}
MiRowStart = MiRowStarts[ tileRow ]
MiRowEnd = MiRowStarts[ tileRow + 1 ]
MiColStart = MiColStarts[ tileCol ]
MiColEnd = MiColStarts[ tileCol + 1 ]
CurrentQIndex = base_q_idx
init_symbol( tileSize )
decode_tile( )
exit_symbol( )
}
if ( tg_end == NumTiles - 1 )
{
if ( !disable_frame_end_update_cdf )
{
frame_end_update_cdf( )
}
decode_frame_wrapup( )
SeenFrameHeader = 0
}
}
5.11.2 decode_tile语法
decode_tile( )
{
clear_above_context( )
for ( i = 0; i < FRAME_LF_COUNT; i++ )
DeltaLF[ i ] = 0
for ( plane = 0; plane < NumPlanes; plane++ )
{
for ( pass = 0; pass < 2; pass++ )
{
RefSgrXqd[ plane ][ pass ] = Sgrproj_Xqd_Mid[ pass ]
for ( i = 0; i < WIENER_COEFFS; i++ )
{
RefLrWiener[ plane ][ pass ][ i ] = Wiener_Taps_Mid[ i ]
}
}
}
sbSize = use_128x128_superblock ? BLOCK_128X128 : BLOCK_64X64
sbSize4 = Num_4x4_Blocks_Wide[ sbSize ]
for ( r = MiRowStart; r < MiRowEnd; r += sbSize4 )
{
clear_left_context( )
for ( c = MiColStart; c < MiColEnd; c += sbSize4 )
{
ReadDeltas = delta_q_present
clear_cdef( r, c )
clear_block_decoded_flags( r, c, sbSize4 )
read_lr( r, c, sbSize )
decode_partition( r, c, sbSize )
}
}
}
其中的常量查找表Sgrproj_Xqd_Mid和Wiener_Taps_Mid定义如下,
Wiener_Taps_Mid[3] = { 3, -7, 15 }
Sgrproj_Xqd_Mid[2] = { -32, 31 }
5.11.3 clear_block_decoded_flags函数
clear_block_decoded_flags( r, c, sbSize4 )
{
for ( plane = 0; plane < NumPlanes; plane++ )
{
subX = (plane > 0) ? subsampling_x : 0
subY = (plane > 0) ? subsampling_y : 0
sbWidth4 = ( MiColEnd - c ) >> subX
sbHeight4 = ( MiRowEnd - r ) >> subY
for ( y = -1; y <= ( sbSize4 >> subY ); y++ )
for ( x = -1; x <= ( sbSize4 >> subX ); x++ )
{
if ( y < 0 && x < sbWidth4 )
BlockDecoded[ plane ][ y ][ x ] = 1
else if ( x < 0 && y < sbHeight4 )
BlockDecoded[ plane ][ y ][ x ] = 1
else
BlockDecoded[ plane ][ y ][ x ] = 0
}
BlockDecoded[ plane ][ sbSize4 >> subY ][ -1 ] = 0
}
}
5.11.4 decode_partition语法
decode_partition( r, c, bSize )
{
if ( r >= MiRows || c >= MiCols )
return 0
AvailU = is_inside( r - 1, c )
AvailL = is_inside( r, c - 1 )
num4x4 = Num_4x4_Blocks_Wide[ bSize ]
halfBlock4x4 = num4x4 >> 1
quarterBlock4x4 = halfBlock4x4 >> 1
hasRows = ( r + halfBlock4x4 ) < MiRows
hasCols = ( c + halfBlock4x4 ) < MiCols
if ( bSize < BLOCK_8X8 )
{
partition = PARTITION_NONE
}
else if ( hasRows && hasCols )
{
partition // Type S()
}
else if ( hasCols )
{
split_or_horz // Type S()
partition = split_or_horz ? PARTITION_SPLIT : PARTITION_HORZ
}
else if ( hasRows )
{
split_or_vert // Type S()
partition = split_or_vert ? PARTITION_SPLIT : PARTITION_VERT
}
else
{
partition = PARTITION_SPLIT
}
subSize = Partition_Subsize[ partition ][ bSize ]
splitSize = Partition_Subsize[ PARTITION_SPLIT ][ bSize ]
if ( partition == PARTITION_NONE )
{
decode_block( r, c, subSize )
}
else if ( partition == PARTITION_HORZ )
{
decode_block( r, c, subSize )
if ( hasRows )
decode_block( r + halfBlock4x4, c, subSize )
}
else if ( partition == PARTITION_VERT )
{
decode_block( r, c, subSize )
if ( hasCols )
decode_block( r, c + halfBlock4x4, subSize )
}
else if ( partition == PARTITION_SPLIT )
{
decode_partition( r, c, subSize )
decode_partition( r, c + halfBlock4x4, subSize )
decode_partition( r + halfBlock4x4, c, subSize )
decode_partition( r + halfBlock4x4, c + halfBlock4x4, subSize )
}
else if ( partition == PARTITION_HORZ_A )
{
decode_block( r, c, splitSize )
decode_block( r, c + halfBlock4x4, splitSize )
decode_block( r + halfBlock4x4, c, subSize )
}
else if ( partition == PARTITION_HORZ_B )
{
decode_block( r, c, subSize )
decode_block( r + halfBlock4x4, c, splitSize )
decode_block( r + halfBlock4x4, c + halfBlock4x4, splitSize )
}
else if ( partition == PARTITION_VERT_A )
{
decode_block( r, c, splitSize )
decode_block( r + halfBlock4x4, c, splitSize )
decode_block( r, c + halfBlock4x4, subSize )
}
else if ( partition == PARTITION_VERT_B )
{
decode_block( r, c, subSize )
decode_block( r, c + halfBlock4x4, splitSize )
decode_block( r + halfBlock4x4, c + halfBlock4x4, splitSize )
}
else if ( partition == PARTITION_HORZ_4 )
{
decode_block( r + quarterBlock4x4 * 0, c, subSize )
decode_block( r + quarterBlock4x4 * 1, c, subSize )
decode_block( r + quarterBlock4x4 * 2, c, subSize )
if ( r + quarterBlock4x4 * 3 < MiRows )
decode_block( r + quarterBlock4x4 * 3, c, subSize )
}
else
{
decode_block( r, c + quarterBlock4x4 * 0, subSize )
decode_block( r, c + quarterBlock4x4 * 1, subSize )
decode_block( r, c + quarterBlock4x4 * 2, subSize )
if ( c + quarterBlock4x4 * 3 < MiCols )
decode_block( r, c + quarterBlock4x4 * 3, subSize )
}
}
5.11.5 decode_block语法
decode_block( r, c, subSize )
{
MiRow = r
MiCol = c
MiSize = subSize
bw4 = Num_4x4_Blocks_Wide[ subSize ]
bh4 = Num_4x4_Blocks_High[ subSize ]
if ( bh4 == 1 && subsampling_y && (MiRow & 1) == 0 )
HasChroma = 0
else if ( bw4 == 1 && subsampling_x && (MiCol & 1) == 0 )
HasChroma = 0
else
HasChroma = NumPlanes > 1
AvailU = is_inside( r - 1, c )
AvailL = is_inside( r, c - 1 )
AvailUChroma = AvailU
AvailLChroma = AvailL
if ( HasChroma )
{
if ( subsampling_y && bh4 == 1 )
AvailUChroma = is_inside( r - 2, c )
if ( subsampling_x && bw4 == 1 )
AvailLChroma = is_inside( r, c - 2 )
}
else
{
AvailUChroma = 0
AvailLChroma = 0
}
mode_info( )
palette_tokens( )
read_block_tx_size( )
if ( skip )
reset_block_context( bw4, bh4 )
isCompound = RefFrame[ 1 ] > INTRA_FRAME
for ( y = 0; y < bh4; y++ )
{
for ( x = 0; x < bw4; x++ )
{
YModes [ r + y ][ c + x ] = YMode
if ( RefFrame[ 0 ] == INTRA_FRAME && HasChroma )
UVModes [ r + y ][ c + x ] = UVMode
for ( refList = 0; refList < 2; refList++ )
RefFrames[ r + y ][ c + x ][ refList ] = RefFrame[ refList ]
if ( is_inter )
{
if ( !use_intrabc )
{
CompGroupIdxs[ r + y ][ c + x ] = comp_group_idx
CompoundIdxs[ r + y ][ c + x ] = compound_idx
}
for ( dir = 0; dir < 2; dir++ )
{
InterpFilters[ r + y ][ c + x ][ dir ] = interp_filter[ dir ]
}
for ( refList = 0; refList < 1 + isCompound; refList++ )
{
Mvs[ r + y ][ c + x ][ refList ] = Mv[ refList ]
}
}
}
}
compute_prediction( )
residual( )
for ( y = 0; y < bh4; y++ )
{
for ( x = 0; x < bw4; x++ )
{
IsInters[ r + y ][ c + x ] = is_inter
SkipModes[ r + y ][ c + x ] = skip_mode
Skips[ r + y ][ c + x ] = skip
TxSizes[ r + y ][ c + x ] = TxSize
MiSizes[ r + y ][ c + x ] = MiSize
SegmentIds[ r + y ][ c + x ] = segment_id
PaletteSizes[ 0 ][ r + y ][ c + x ] = PaletteSizeY
PaletteSizes[ 1 ][ r + y ][ c + x ] = PaletteSizeUV
for ( i = 0; i < PaletteSizeY; i++ )
PaletteColors[ 0 ][ r + y ][ c + x ][ i ] = palette_colors_y[ i ]
for ( i = 0; i < PaletteSizeUV; i++ )
PaletteColors[ 1 ][ r + y ][ c + x ][ i ] = palette_colors_u[ i ]
for ( i = 0; i < FRAME_LF_COUNT; i++ )
DeltaLFs[ r + y ][ c + x ][ i ] = DeltaLF[ i ]
}
}
}
其中的reset_block_context()定义如下,
reset_block_context( bw4, bh4 )
{
for ( plane = 0; plane < 1 + 2 * HasChroma; plane++ )
{
subX = (plane > 0) ? subsampling_x : 0
subY = (plane > 0) ? subsampling_y : 0
for ( i = MiCol >> subX; i < ( ( MiCol + bw4 ) >> subX ); i++)
{
AboveLevelContext[ plane ][ i ] = 0
AboveDcContext[ plane ][ i ] = 0
}
for ( i = MiRow >> subY; i < ( ( MiRow + bh4 ) >> subY ); i++)
{
LeftLevelContext[ plane ][ i ] = 0
LeftDcContext[ plane ][ i ] = 0
}
}
}
5.11.6 mode_info语法
mode_info( )
{
if ( FrameIsIntra )
intra_frame_mode_info( )
else
inter_frame_mode_info( )
}
5.11.7 intra_frame_mode_info语法
intra_frame_mode_info( )
{
skip = 0
if ( SegIdPreSkip )
intra_segment_id( )
skip_mode = 0
read_skip( )
if ( !SegIdPreSkip )
intra_segment_id( )
read_cdef( )
read_delta_qindex( )
read_delta_lf( )
ReadDeltas = 0
RefFrame[ 0 ] = INTRA_FRAME
RefFrame[ 1 ] = NONE
if ( allow_intrabc )
{
use_intrabc // Type S()
}
else
{
use_intrabc = 0
}
if ( use_intrabc )
{
is_inter = 1
YMode = DC_PRED
UVMode = DC_PRED
motion_mode = SIMPLE
compound_type = COMPOUND_AVERAGE
PaletteSizeY = 0
PaletteSizeUV = 0
interp_filter[ 0 ] = BILINEAR
interp_filter[ 1 ] = BILINEAR
find_mv_stack( 0 )
assign_mv( 0 )
}
else
{
is_inter = 0
intra_frame_y_mode // Type S()
YMode = intra_frame_y_mode
intra_angle_info_y( )
if ( HasChroma )
{
uv_mode // Type S()
UVMode = uv_mode
if ( UVMode == UV_CFL_PRED )
{
read_cfl_alphas( )
}
intra_angle_info_uv( )
}
PaletteSizeY = 0
PaletteSizeUV = 0
if ( MiSize >= BLOCK_8X8
&& Block_Width[ MiSize ] <= 64
&& Block_Height[ MiSize ] <= 64
&& allow_screen_content_tools )
{
palette_mode_info( )
}
filter_intra_mode_info( )
}
}
5.11.8 intra_segment_id语法
intra_segment_id( )
{
if ( segmentation_enabled )
read_segment_id( )
else
segment_id = 0
Lossless = LosslessArray[ segment_id ]
}
5.11.9 read_segment_id语法
read_segment_id( )
{
if ( AvailU && AvailL )
prevUL = SegmentIds[ MiRow - 1 ][ MiCol - 1 ]
else
prevUL = -1
if ( AvailU )
prevU = SegmentIds[ MiRow - 1 ][ MiCol ]
else
prevU = -1
if ( AvailL )
prevL = SegmentIds[ MiRow ][ MiCol - 1 ]
else
prevL = -1
if ( prevU == -1 )
pred = (prevL == -1) ? 0 : prevL
else if ( prevL == -1 )
pred = prevU
else
pred = (prevUL == prevU) ? prevU : prevL
if ( skip )
{
segment_id = pred
}
else
{
segment_id // Type S()
segment_id = neg_deinterleave( segment_id, pred, LastActiveSegId + 1 )
}
}
其中的neg_deinterleave()定义如下,
neg_deinterleave(diff, ref, max)
{
if ( !ref )
return diff
if ( ref >= (max - 1) )
return max - diff - 1
if ( 2 * ref < max )
{
if ( diff <= 2 * ref )
{
if ( diff & 1 )
return ref + ((diff + 1) >> 1)
else
return ref - (diff >> 1)
}
return diff
}
else
{
if ( diff <= 2 * (max - ref - 1) )
{
if ( diff & 1 )
return ref + ((diff + 1) >> 1)
else
return ref - (diff >> 1)
}
return max - (diff + 1)
}
}
5.11.10 read_skip_mode语法
read_skip_mode()
{
if ( seg_feature_active( SEG_LVL_SKIP )
|| seg_feature_active( SEG_LVL_REF_FRAME )
|| seg_feature_active( SEG_LVL_GLOBALMV )
|| !skip_mode_present
|| Block_Width[ MiSize ] < 8
|| Block_Height[ MiSize ] < 8 )
{
skip_mode = 0
}
else
{
skip_mode // Type S()
}
}
5.11.11 read_skip语法
read_skip()
{
if ( SegIdPreSkip && seg_feature_active( SEG_LVL_SKIP ) )
{
skip = 1
}
else
{
skip // Type S()
}
}
5.11.12 read_delta_qindex语法
read_delta_qindex( )
{
sbSize = use_128x128_superblock ? BLOCK_128X128 : BLOCK_64X64
if ( MiSize == sbSize && skip )
return
if ( ReadDeltas )
{
delta_q_abs // Type S()
if ( delta_q_abs == DELTA_Q_SMALL )
{
delta_q_rem_bits // Type L(3)
delta_q_rem_bits++
delta_q_abs_bits // Type L(delta_q_rem_bits)
delta_q_abs = delta_q_abs_bits + (1 << delta_q_rem_bits) + 1
}
if ( delta_q_abs )
{
delta_q_sign_bit // Type L(1)
reducedDeltaQIndex = delta_q_sign_bit ? -delta_q_abs : delta_q_abs
CurrentQIndex = Clip3(1, 255, CurrentQIndex + (reducedDeltaQIndex << delta_q_res))
}
}
}
5.11.13 read_delta_lf语法
read_delta_lf( )
{
sbSize = use_128x128_superblock ? BLOCK_128X128 : BLOCK_64X64
if ( MiSize == sbSize && skip )
return
if ( ReadDeltas && delta_lf_present )
{
frameLfCount = 1
if ( delta_lf_multi )
{
frameLfCount = ( NumPlanes > 1 ) ? FRAME_LF_COUNT : ( FRAME_LF_COUNT - 2 )
}
for ( i = 0; i < frameLfCount; i++ )
{
delta_lf_abs // Type S()
if ( delta_lf_abs == DELTA_LF_SMALL )
{
delta_lf_rem_bits // Type L(3)
n = delta_lf_rem_bits + 1
delta_lf_abs_bits // Type L(n)
deltaLfAbs = delta_lf_abs_bits + ( 1 << n ) + 1
}
else
{
deltaLfAbs = delta_lf_abs
}
if ( deltaLfAbs )
{
delta_lf_sign_bit // Type L(1)
reducedDeltaLfLevel = delta_lf_sign_bit ? -deltaLfAbs : deltaLfAbs
DeltaLF[ i ] = Clip3( -MAX_LOOP_FILTER, MAX_LOOP_FILTER, DeltaLF[ i ] + (reducedDeltaLfLevel << delta_lf_res) )
}
}
}
}
5.11.14 seg_feature_active_idx函数
seg_feature_active_idx( idx, feature )
{
return segmentation_enabled && FeatureEnabled[ idx ][ feature ]
}
seg_feature_active( feature )
{
return seg_feature_active_idx( segment_id, feature )
}
5.11.15 read_tx_size语法
read_tx_size( allowSelect )
{
if ( Lossless )
{
TxSize = TX_4X4
return
}
maxRectTxSize = Max_Tx_Size_Rect[ MiSize ]
maxTxDepth = Max_Tx_Depth[ MiSize ]
TxSize = maxRectTxSize
if ( MiSize > BLOCK_4X4 && allowSelect && TxMode == TX_MODE_SELECT )
{
tx_depth // Type S()
for ( i = 0; i < tx_depth; i++ )
TxSize = Split_Tx_Size[ TxSize ]
}
}
其中Max_Tx_Depth定义了每个块尺寸的最大变换深度,
Max_Tx_Depth[ BLOCK_SIZES ] =
{
0, 1, 1, 1,
2, 2, 2, 3,
3, 3, 4, 4,
4, 4, 4, 4,
2, 2, 3, 3,
4, 4
}
注意:Max_Tx_Depth包含必须拆分变换以达到4x4变换大小的次数。它可能大于MAX_TX_DEPTH。但是,因为tx_depth只能编码0到2范围内的值,所以无法进行变换深度大于MAX_TX_DEPTH的编码。
5.11.16 read_block_tx_size语法
read_block_tx_size( )
{
bw4 = Num_4x4_Blocks_Wide[ MiSize ]
bh4 = Num_4x4_Blocks_High[ MiSize ]
if ( TxMode ==