Table of Contents
5.9.10 read_interpolation_filter语法
5.9.26 decode_signed_subexp_with_ref语法
5.9.27 decode_unsigned_subexp_with_ref语法
5.9 帧数据头OBU语法
5.9.1 frame_header_obu语法
frame_header_obu( )
{
if ( SeenFrameHeader == 1 )
{
frame_header_copy()
}
else
{
SeenFrameHeader = 1
uncompressed_header( )
if ( show_existing_frame )
{
decode_frame_wrapup( )
SeenFrameHeader = 0
}
else
{
TileNum = 0
SeenFrameHeader = 1
}
}
}
5.9.2 uncompressed_header语法
uncompressed_header( )
{
if ( frame_id_numbers_present_flag )
{
idLen = (additional_frame_id_length_minus_1 + delta_frame_id_length_minus_2 + 3)
}
allFrames = (1 << NUM_REF_FRAMES) - 1
if ( reduced_still_picture_header )
{
show_existing_frame = 0
frame_type = KEY_FRAME
FrameIsIntra = 1
show_frame = 1
showable_frame = 0
}
else
{
show_existing_frame // Type f(1)
if ( show_existing_frame == 1 )
{
frame_to_show_map_idx // Type f(3)
if ( decoder_model_info_present_flag && !equal_picture_interval )
{
temporal_point_info( )
}
refresh_frame_flags = 0
if ( frame_id_numbers_present_flag )
{
display_frame_id // Type f(idLen)
}
frame_type = RefFrameType[ frame_to_show_map_idx ]
if ( frame_type == KEY_FRAME )
{
refresh_frame_flags = allFrames
}
if ( film_grain_params_present )
{
load_grain_params( frame_to_show_map_idx )
}
return
}
frame_type // Type f(2)
FrameIsIntra = (frame_type == INTRA_ONLY_FRAME || frame_type == KEY_FRAME)
show_frame // Type f(1)
if ( show_frame && decoder_model_info_present_flag && !equal_picture_interval )
{
temporal_point_info( )
}
if ( show_frame )
{
showable_frame = frame_type != KEY_FRAME
}
else
{
showable_frame // Type f(1)
}
if ( frame_type == SWITCH_FRAME || ( frame_type == KEY_FRAME && show_frame ) )
error_resilient_mode = 1
else
error_resilient_mode // Type f(1)
}
if ( frame_type == KEY_FRAME && show_frame )
{
for ( i = 0; i < NUM_REF_FRAMES; i++ )
{
RefValid[ i ] = 0
RefOrderHint[ i ] = 0
}
for ( i = 0; i < REFS_PER_FRAME; i++ )
{
OrderHints[ LAST_FRAME + i ] = 0
}
}
disable_cdf_update // Type f(1)
if ( seq_force_screen_content_tools == SELECT_SCREEN_CONTENT_TOOLS )
{
allow_screen_content_tools // Type f(1)
}
else
{
allow_screen_content_tools = seq_force_screen_content_tools
}
if ( allow_screen_content_tools )
{
if ( seq_force_integer_mv == SELECT_INTEGER_MV )
{
force_integer_mv // Type f(1)
}
else
{
force_integer_mv = seq_force_integer_mv
}
}
else
{
force_integer_mv = 0
}
if ( FrameIsIntra )
{
force_integer_mv = 1
}
if ( frame_id_numbers_present_flag )
{
PrevFrameID = current_frame_id
current_frame_id // Type f(idLen)
mark_ref_frames( idLen )
}
else
{
current_frame_id = 0
}
if ( frame_type == SWITCH_FRAME )
frame_size_override_flag = 1
else if ( reduced_still_picture_header )
frame_size_override_flag = 0
else
frame_size_override_flag // Type f(1)
order_hint // Type f(OrderHintBits)
OrderHint = order_hint
if ( FrameIsIntra || error_resilient_mode )
{
primary_ref_frame = PRIMARY_REF_NONE
}
else
{
primary_ref_frame // Type f(3)
}
if ( decoder_model_info_present_flag )
{
buffer_removal_time_present_flag // Type f(1)
if ( buffer_removal_time_present_flag )
{
for ( opNum = 0; opNum <= operating_points_cnt_minus_1; opNum++ )
{
if ( decoder_model_present_for_this_op[ opNum ] )
{
opPtIdc = operating_point_idc[ opNum ]
inTemporalLayer = ( opPtIdc >> temporal_id ) & 1
inSpatialLayer = ( opPtIdc >> ( spatial_id + 8 ) ) & 1
if ( opPtIdc == 0 || ( inTemporalLayer && inSpatialLayer ) )
{
n = buffer_removal_time_length_minus_1 + 1
buffer_removal_time[ opNum ] // Type f(n)
}
}
}
}
}
allow_high_precision_mv = 0
use_ref_frame_mvs = 0
allow_intrabc = 0
if ( frame_type == SWITCH_FRAME || ( frame_type == KEY_FRAME && show_frame ) )
{
refresh_frame_flags = allFrames
}
else
{
refresh_frame_flags // Type f(8)
}
if ( !FrameIsIntra || refresh_frame_flags != allFrames )
{
if ( error_resilient_mode && enable_order_hint )
{
for ( i = 0; i < NUM_REF_FRAMES; i++)
{
ref_order_hint[ i ] // Type f(OrderHintBits)
if ( ref_order_hint[ i ] != RefOrderHint[ i ] )
{
RefValid[ i ] = 0
}
}
}
}
if ( FrameIsIntra )
{
frame_size( )
render_size( )
if ( allow_screen_content_tools && UpscaledWidth == FrameWidth )
{
allow_intrabc // Type f(1)
}
}
else
{
if ( !enable_order_hint )
{
frame_refs_short_signaling = 0
}
else
{
frame_refs_short_signaling // Type f(1)
if ( frame_refs_short_signaling )
{
last_frame_idx // Type f(3)
gold_frame_idx // Type f(3)
set_frame_refs()
}
}
for ( i = 0; i < REFS_PER_FRAME; i++ )
{
if ( !frame_refs_short_signaling )
ref_frame_idx[ i ] // Type f(3)
if ( frame_id_numbers_present_flag )
{
n = delta_frame_id_length_minus_2 + 2
delta_frame_id_minus_1 // Type f(n)
DeltaFrameId = delta_frame_id_minus_1 + 1
expectedFrameId[ i ] = ((current_frame_id + (1 << idLen) - DeltaFrameId ) % (1 << idLen))
}
}
if ( frame_size_override_flag && !error_resilient_mode )
{
frame_size_with_refs( )
}
else
{
frame_size( )
render_size( )
}
if ( force_integer_mv )
{
allow_high_precision_mv = 0
}
else
{
allow_high_precision_mv // Type f(1)
}
read_interpolation_filter( )
is_motion_mode_switchable // Type f(1)
if ( error_resilient_mode || !enable_ref_frame_mvs )
{
use_ref_frame_mvs = 0
}
else
{
use_ref_frame_mvs // Type f(1)
}
for ( i = 0; i < REFS_PER_FRAME; i++ )
{
refFrame = LAST_FRAME + i
hint = RefOrderHint[ ref_frame_idx[ i ] ]
OrderHints[ refFrame ] = hint
if ( !enable_order_hint )
{
RefFrameSignBias[ refFrame ] = 0
}
else
{
RefFrameSignBias[ refFrame ] = get_relative_dist( hint, OrderHint) > 0
}
}
}
if ( reduced_still_picture_header || disable_cdf_update )
disable_frame_end_update_cdf = 1
else
disable_frame_end_update_cdf // Type f(1)
if ( primary_ref_frame == PRIMARY_REF_NONE )
{
init_non_coeff_cdfs( )
setup_past_independence( )
}
else
{
load_cdfs( ref_frame_idx[ primary_ref_frame ] )
load_previous( )
}
if ( use_ref_frame_mvs == 1 )
motion_field_estimation( )
tile_info( )
quantization_params( )
segmentation_params( )
delta_q_params( )
delta_lf_params( )
if ( primary_ref_frame == PRIMARY_REF_NONE )
{
init_coeff_cdfs( )
}
else
{
load_previous_segment_ids( )
}
CodedLossless = 1
for ( segmentId = 0; segmentId < MAX_SEGMENTS; segmentId++ )
{
qindex = get_qindex( 1, segmentId )
LosslessArray[ segmentId ] = qindex == 0 && DeltaQYDc == 0 &&
DeltaQUAc == 0 && DeltaQUDc == 0 &&
DeltaQVAc == 0 && DeltaQVDc == 0
if ( !LosslessArray[ segmentId ] )
CodedLossless = 0
if ( using_qmatrix )
{
if ( LosslessArray[ segmentId ] )
{
SegQMLevel[ 0 ][ segmentId ] = 15
SegQMLevel[ 1 ][ segmentId ] = 15
SegQMLevel[ 2 ][ segmentId ] = 15
}
else
{
SegQMLevel[ 0 ][ segmentId ] = qm_y
SegQMLevel[ 1 ][ segmentId ] = qm_u
SegQMLevel[ 2 ][ segmentId ] = qm_v
}
}
}
AllLossless = CodedLossless && ( FrameWidth == UpscaledWidth )
loop_filter_params( )
cdef_params( )
lr_params( )
read_tx_mode( )
frame_reference_mode( )
skip_mode_params( )
if ( FrameIsIntra || error_resilient_mode || !enable_warped_motion )
allow_warped_motion = 0
else
allow_warped_motion // Type f(1)
reduced_tx_set // Type f(1)
global_motion_params( )
film_grain_params( )
}
5.9.3 get_relative_dist函数
get_relative_dist( a, b )
{
if ( !enable_order_hint )
return 0
diff = a - b
m = 1 << (OrderHintBits - 1)
diff = (diff & (m - 1)) - (diff & m)
return diff
}
5.9.4 mark_ref_frames函数
mark_ref_frames( idLen )
{
diffLen = delta_frame_id_length_minus_2 + 2
for ( i = 0; i < NUM_REF_FRAMES; i++ )
{
if ( current_frame_id > ( 1 << diffLen ) )
{
if ( RefFrameId[ i ] > current_frame_id || RefFrameId[ i ] < ( current_frame_id - ( 1 << diffLen ) ) )
RefValid[ i ] = 0
}
else
{
if ( RefFrameId[ i ] > current_frame_id && RefFrameId[ i ] < ( ( 1 << idLen ) + current_frame_id - ( 1 << diffLen ) ) )
RefValid[ i ] = 0
}
}
}
5.9.6 render_size语法
render_size( )
{
render_and_frame_size_different // Type f(1)
if ( render_and_frame_size_different == 1 )
{
render_width_minus_1 // Type f(16)
render_height_minus_1 // Type f(16)
RenderWidth = render_width_minus_1 + 1
RenderHeight = render_height_minus_1 + 1
}
else
{
RenderWidth = UpscaledWidth
RenderHeight = FrameHeight
}
}
5.9.7 frame_size_with_refs语法
frame_size_with_refs( )
{
for ( i = 0; i < REFS_PER_FRAME; i++ )
{
found_ref // Type f(1)
if ( found_ref == 1 )
{
UpscaledWidth = RefUpscaledWidth[ ref_frame_idx[ i ] ]
FrameWidth = UpscaledWidth
FrameHeight = RefFrameHeight[ ref_frame_idx[ i ] ]
RenderWidth = RefRenderWidth[ ref_frame_idx[ i ] ]
RenderHeight = RefRenderHeight[ ref_frame_idx[ i ] ]
break
}
}
if ( found_ref == 0 )
{
frame_size( )
render_size( )
}
else
{
superres_params( )
compute_image_size( )
}
}
5.9.8 superres_params语法
superres_params()
{
if ( enable_superres )
use_superres // Type f(1)
else
use_superres = 0
if ( use_superres )
{
coded_denom f(SUPERRES_DENOM_BITS)
SuperresDenom = coded_denom + SUPERRES_DENOM_MIN
}
else
{
SuperresDenom = SUPERRES_NUM
}
UpscaledWidth = FrameWidth
FrameWidth = (UpscaledWidth * SUPERRES_NUM + (SuperresDenom / 2)) / SuperresDenom
}
5.9.9 compute_image_size函数
compute_image_size( )
{
MiCols = 2 * ( ( FrameWidth + 7 ) >> 3 )
MiRows = 2 * ( ( FrameHeight + 7 ) >> 3 )
}
5.9.10 read_interpolation_filter语法
read_interpolation_filter( )
{
is_filter_switchable // Type f(1)
if ( is_filter_switchable == 1 )
{
interpolation_filter = SWITCHABLE
}
else
{
interpolation_filter // Type f(2)
}
}
5.9.11 loop_filter_params语法
loop_filter_params( )
{
if ( CodedLossless || allow_intrabc )
{
loop_filter_level[ 0 ] = 0
loop_filter_level[ 1 ] = 0
loop_filter_ref_deltas[ INTRA_FRAME ] = 1
loop_filter_ref_deltas[ LAST_FRAME ] = 0
loop_filter_ref_deltas[ LAST2_FRAME ] = 0
loop_filter_ref_deltas[ LAST3_FRAME ] = 0
loop_filter_ref_deltas[ BWDREF_FRAME ] = 0
loop_filter_ref_deltas[ GOLDEN_FRAME ] = -1
loop_filter_ref_deltas[ ALTREF_FRAME ] = -1
loop_filter_ref_deltas[ ALTREF2_FRAME ] = -1
for ( i = 0; i < 2; i++ )
{
loop_filter_mode_deltas[ i ] = 0
}
return
}
loop_filter_level[ 0 ] // Type f(6)
loop_filter_level[ 1 ] // Type f(6)
if ( NumPlanes > 1 )
{
if ( loop_filter_level[ 0 ] || loop_filter_level[ 1 ] )
{
loop_filter_level[ 2 ] // Type f(6)
loop_filter_level[ 3 ] // Type f(6)
}
}
loop_filter_sharpness // Type f(3)
loop_filter_delta_enabled // Type f(1)
if ( loop_filter_delta_enabled == 1 )
{
loop_filter_delta_update // Type f(1)
if ( loop_filter_delta_update == 1 )
{
for ( i = 0; i < TOTAL_REFS_PER_FRAME; i++ )
{
update_ref_delta // Type f(1)
if ( update_ref_delta == 1 )
loop_filter_ref_deltas[ i ] // Type su(1+6)
}
for ( i = 0; i < 2; i++ )
{
update_mode_delta // Type f(1)
if ( update_mode_delta == 1 )
loop_filter_mode_deltas[ i ] // Type su(1+6)
}
}
}
}
5.9.12 quantization_params语法
quantization_params( )
{
base_q_idx // Type f(8)
DeltaQYDc = read_delta_q( )
if ( NumPlanes > 1 )
{
if ( separate_uv_delta_q )
diff_uv_delta // Type f(1)
else
diff_uv_delta = 0
DeltaQUDc = read_delta_q( )
DeltaQUAc = read_delta_q( )
if ( diff_uv_delta )
{
DeltaQVDc = read_delta_q( )
DeltaQVAc = read_delta_q( )
}
else
{
DeltaQVDc = DeltaQUDc
DeltaQVAc = DeltaQUAc
}
}
else
{
DeltaQUDc = 0
DeltaQUAc = 0
DeltaQVDc = 0
DeltaQVAc = 0
}
using_qmatrix // Type f(1)
if ( using_qmatrix )
{
qm_y // Type f(4)
qm_u // Type f(4)
if ( !separate_uv_delta_q )
qm_v = qm_u
else
qm_v // Type f(4)
}
}
5.9.13 read_delta_q语法
read_delta_q( )
{
delta_coded // Type f(1)
if ( delta_coded )
{
delta_q // Type su(1+6)
}
else
{
delta_q = 0
}
return delta_q
}
5.9.14 segmentation_params语法
segmentation_params( )
{
segmentation_enabled // Type f(1)
if ( segmentation_enabled == 1 )
{
if ( primary_ref_frame == PRIMARY_REF_NONE )
{
segmentation_update_map = 1
segmentation_temporal_update = 0
segmentation_update_data = 1
}
else
{
segmentation_update_map // Type f(1)
if ( segmentation_update_map == 1 )
segmentation_temporal_update // Type f(1)
segmentation_update_data // Type f(1)
}
if ( segmentation_update_data == 1 )
{
for ( i = 0; i < MAX_SEGMENTS; i++ )
{
for ( j = 0; j < SEG_LVL_MAX; j++ )
{
feature_value = 0
feature_enabled // Type f(1)
FeatureEnabled[ i ][ j ] = feature_enabled
clippedValue = 0
if ( feature_enabled == 1 )
{
bitsToRead = Segmentation_Feature_Bits[ j ]
limit = Segmentation_Feature_Max[ j ]
if ( Segmentation_Feature_Signed[ j ] == 1 )
{
feature_value su(1+bitsToRead)
clippedValue = Clip3( -limit, limit, feature_value)
}
else
{
feature_value // Type f(bitsToRead)
clippedValue = Clip3( 0, limit, feature_value)
}
}
FeatureData[ i ][ j ] = clippedValue
}
}
}
}
else
{
for ( i = 0; i < MAX_SEGMENTS; i++ )
{
for ( j = 0; j < SEG_LVL_MAX; j++ )
{
FeatureEnabled[ i ][ j ] = 0
FeatureData[ i ][ j ] = 0
}
}
}
SegIdPreSkip = 0
LastActiveSegId = 0
for ( i = 0; i < MAX_SEGMENTS; i++ )
{
for ( j = 0; j < SEG_LVL_MAX; j++ )
{
if ( FeatureEnabled[ i ][ j ] )
{
LastActiveSegId = i
if ( j >= SEG_LVL_REF_FRAME )
{
SegIdPreSkip = 1
}
}
}
}
}
该语法中所使用的常量查找表定义如下,
Segmentation_Feature_Bits[ SEG_LVL_MAX ] = { 8, 6, 6, 6, 6, 3, 0, 0 }
Segmentation_Feature_Signed[ SEG_LVL_MAX ] = { 1, 1, 1, 1, 1, 0, 0, 0 }
Segmentation_Feature_Max[ SEG_LVL_MAX ] = { 255, MAX_LOOP_FILTER, MAX_LOOP_FILTER, MAX_LOOP_FILTER, MAX_LOOP_FILTER, 7, 0, 0 }
5.9.15 tile_info语法
tile_info ( )
{
sbCols = use_128x128_superblock ? ( ( MiCols + 31 ) >> 5 ) : ( ( MiCols + 15 ) >> 4 )
sbRows = use_128x128_superblock ? ( ( MiRows + 31 ) >> 5 ) : ( ( MiRows + 15 ) >> 4 )
sbShift = use_128x128_superblock ? 5 : 4
sbSize = sbShift + 2
maxTileWidthSb = MAX_TILE_WIDTH >> sbSize
maxTileAreaSb = MAX_TILE_AREA >> ( 2 * sbSize )
minLog2TileCols = tile_log2(maxTileWidthSb, sbCols)
maxLog2TileCols = tile_log2(1, Min(sbCols, MAX_TILE_COLS))
maxLog2TileRows = tile_log2(1, Min(sbRows, MAX_TILE_ROWS))
minLog2Tiles = Max(minLog2TileCols,
tile_log2(maxTileAreaSb, sbRows * sbCols))
uniform_tile_spacing_flag // Type f(1)
if ( uniform_tile_spacing_flag )
{
TileColsLog2 = minLog2TileCols
while ( TileColsLog2 < maxLog2TileCols )
{
increment_tile_cols_log2 // Type f(1)
if ( increment_tile_cols_log2 == 1 )
TileColsLog2++
else
break
}
tileWidthSb = (sbCols + (1 << TileColsLog2) - 1) >> TileColsLog2
i = 0
for ( startSb = 0; startSb < sbCols; startSb += tileWidthSb )
{
MiColStarts[ i ] = startSb << sbShift
i += 1
}
MiColStarts[i] = MiCols
TileCols = i
minLog2TileRows = Max( minLog2Tiles - TileColsLog2, 0)
TileRowsLog2 = minLog2TileRows
while ( TileRowsLog2 < maxLog2TileRows )
{
increment_tile_rows_log2 // Type f(1)
if ( increment_tile_rows_log2 == 1 )
TileRowsLog2++
else
break
}
tileHeightSb = (sbRows + (1 << TileRowsLog2) - 1) >> TileRowsLog2
i = 0
for ( startSb = 0; startSb < sbRows; startSb += tileHeightSb )
{
MiRowStarts[ i ] = startSb << sbShift
i += 1
}
MiRowStarts[i] = MiRows
TileRows = i
}
else
{
widestTileSb = 0
startSb = 0
for ( i = 0; startSb < sbCols; i++ )
{
MiColStarts[ i ] = startSb << sbShift
maxWidth = Min(sbCols - startSb, maxTileWidthSb)
width_in_sbs_minus_1 // Type ns(maxWidth)
sizeSb = width_in_sbs_minus_1 + 1
widestTileSb = Max( sizeSb, widestTileSb )
startSb += sizeSb
}
MiColStarts[i] = MiCols
TileCols = i
TileColsLog2 = tile_log2(1, TileCols)
if ( minLog2Tiles > 0 )
maxTileAreaSb = (sbRows * sbCols) >> (minLog2Tiles + 1)
else
maxTileAreaSb = sbRows * sbCols
maxTileHeightSb = Max( maxTileAreaSb / widestTileSb, 1 )
startSb = 0
for ( i = 0; startSb < sbRows; i++ )
{
MiRowStarts[ i ] = startSb << sbShift
maxHeight = Min(sbRows - startSb, maxTileHeightSb)
height_in_sbs_minus_1 // Type ns(maxHeight)
sizeSb = height_in_sbs_minus_1 + 1
startSb += sizeSb
}
MiRowStarts[ i ] = MiRows
TileRows = i
TileRowsLog2 = tile_log2(1, TileRows)
}
if ( TileColsLog2 > 0 || TileRowsLog2 > 0 )
{
context_update_tile_id // Type f(TileRowsLog2 + TileColsLog2)
tile_size_bytes_minus_1 // Type f(2)
TileSizeBytes = tile_size_bytes_minus_1 + 1
}
else
{
context_update_tile_id = 0
}
}
5.9.16 tile_log2函数
tile_log2的返回值为k的最小值,能够符合blkSize << k大于等于目标值。
tile_log2( blkSize, target )
{
for ( k = 0; (blkSize << k) < target; k++ )
{
}
return k
}
5.9.17 delta_q_params语法
delta_q_params( )
{
delta_q_res = 0
delta_q_present = 0
if ( base_q_idx > 0 )
{
delta_q_present // Type f(1)
}
if ( delta_q_present )
{
delta_q_res // Type f(2)
}
}
5.9.18 delta_lf_params语法
delta_lf_params( )
{
delta_lf_present = 0
delta_lf_res = 0
delta_lf_multi = 0
if ( delta_q_present )
{
if ( !allow_intrabc )
delta_lf_present // Type f(1)
if ( delta_lf_present )
{
delta_lf_res // Type f(2)
delta_lf_multi // Type f(1)
}
}
}
5.9.19 cdef_params语法
cdef_params( )
{
if ( CodedLossless || allow_intrabc || !enable_cdef)
{
cdef_bits = 0
cdef_y_pri_strength[0] = 0
cdef_y_sec_strength[0] = 0
cdef_uv_pri_strength[0] = 0
cdef_uv_sec_strength[0] = 0
CdefDamping = 3
return
}
cdef_damping_minus_3 // Type f(2)
CdefDamping = cdef_damping_minus_3 + 3
cdef_bits // Type f(2)
for ( i = 0; i < (1 << cdef_bits); i++ )
{
cdef_y_pri_strength[i] // Type f(4)
cdef_y_sec_strength[i] // Type f(2)
if ( cdef_y_sec_strength[i] == 3 )
cdef_y_sec_strength[i] += 1
if ( NumPlanes > 1 )
{
cdef_uv_pri_strength[i] // Type f(4)
cdef_uv_sec_strength[i] // Type f(2)
if ( cdef_uv_sec_strength[i] == 3 )
cdef_uv_sec_strength[i] += 1
}
}
}
5.9.20 lr_params语法
lr_params( )
{
if ( AllLossless || allow_intrabc || !enable_restoration )
{
FrameRestorationType[0] = RESTORE_NONE
FrameRestorationType[1] = RESTORE_NONE
FrameRestorationType[2] = RESTORE_NONE
UsesLr = 0
return
}
UsesLr = 0
usesChromaLr = 0
for ( i = 0; i < NumPlanes; i++ )
{
lr_type // Type f(2)
FrameRestorationType[i] = Remap_Lr_Type[lr_type]
if ( FrameRestorationType[i] != RESTORE_NONE )
{
UsesLr = 1
if ( i > 0 )
{
usesChromaLr = 1
}
}
}
if ( UsesLr )
{
if ( use_128x128_superblock )
{
lr_unit_shift // Type f(1)
lr_unit_shift++
}
else
{
lr_unit_shift // Type f(1)
if ( lr_unit_shift )
{
lr_unit_extra_shift // Type f(1)
lr_unit_shift += lr_unit_extra_shift
}
}
LoopRestorationSize[ 0 ] = RESTORATION_TILESIZE_MAX >> (2 - lr_unit_shift)
if ( subsampling_x && subsampling_y && usesChromaLr )
{
lr_uv_shift // Type f(1)
}
else
{
lr_uv_shift = 0
}
LoopRestorationSize[ 1 ] = LoopRestorationSize[ 0 ] >> lr_uv_shift
LoopRestorationSize[ 2 ] = LoopRestorationSize[ 0 ] >> lr_uv_shift
}
}
其中的常量查找表定义如下,
Remap_Lr_Type[4] = { RESTORE_NONE, RESTORE_SWITCHABLE, RESTORE_WIENER, RESTORE_SGRPROJ }
5.9.21 read_tx_mode语法
read_tx_mode( )
{
if ( CodedLossless == 1 )
{
TxMode = ONLY_4X4
}
else
{
tx_mode_select // Type f(1)
if ( tx_mode_select )
{
TxMode = TX_MODE_SELECT
}
else
{
TxMode = TX_MODE_LARGEST
}
}
}
5.9.22 skip_mode_params语法
skip_mode_params( )
{
if ( FrameIsIntra || !reference_select || !enable_order_hint )
{
skipModeAllowed = 0
}
else
{
forwardIdx = -1
backwardIdx = -1
for ( i = 0; i < REFS_PER_FRAME; i++ )
{
refHint = RefOrderHint[ ref_frame_idx[ i ] ]
if ( get_relative_dist( refHint, OrderHint ) < 0 )
{
if ( forwardIdx < 0 || get_relative_dist( refHint, forwardHint) > 0 )
{
forwardIdx = i
forwardHint = refHint
}
}
else if ( get_relative_dist( refHint, OrderHint) > 0 )
{
if ( backwardIdx < 0 || get_relative_dist( refHint, backwardHint) < 0 )
{
backwardIdx = i
backwardHint = refHint
}
}
}
if ( forwardIdx < 0 )
{
skipModeAllowed = 0
}
else if ( backwardIdx >= 0 )
{
skipModeAllowed = 1
SkipModeFrame[ 0 ] = LAST_FRAME + Min(forwardIdx, backwardIdx)
SkipModeFrame[ 1 ] = LAST_FRAME + Max(forwardIdx, backwardIdx)
}
else
{
secondForwardIdx = -1
for ( i = 0; i < REFS_PER_FRAME; i++ )
{
refHint = RefOrderHint[ ref_frame_idx[ i ] ]
if ( get_relative_dist( refHint, forwardHint ) < 0 )
{
if ( secondForwardIdx < 0 || get_relative_dist( refHint, secondForwardHint ) > 0 )
{
secondForwardIdx = i
secondForwardHint = refHint
}
}
}
if ( secondForwardIdx < 0 )
{
skipModeAllowed = 0
}
else
{
skipModeAllowed = 1
SkipModeFrame[ 0 ] = LAST_FRAME + Min(forwardIdx, secondForwardIdx)
SkipModeFrame[ 1 ] = LAST_FRAME + Max(forwardIdx, secondForwardIdx)
}
}
}
if ( skipModeAllowed )
{
skip_mode_present // Type f(1)
}
else
{
skip_mode_present = 0
}
}
5.9.23 frame_reference_mode语法
frame_reference_mode( )
{
if ( FrameIsIntra )
{
reference_select = 0
}
else
{
reference_select // Type f(1)
}
}
5.9.24 global_motion_params语法
global_motion_params( )
{
for ( ref = LAST_FRAME; ref <= ALTREF_FRAME; ref++ )
{
GmType[ ref ] = IDENTITY
for ( i = 0; i < 6; i++ )
{
gm_params[ ref ][ i ] = ( ( i % 3 == 2 ) ? 1 << WARPEDMODEL_PREC_BITS : 0 )
}
}
if ( FrameIsIntra )
return
for ( ref = LAST_FRAME; ref <= ALTREF_FRAME; ref++ )
{
is_global // Type f(1)
if ( is_global )
{
is_rot_zoom // Type f(1)
if ( is_rot_zoom )
{
type = ROTZOOM
}
else
{
is_translation // Type f(1)
type = is_translation ? TRANSLATION : AFFINE
}
}
else
{
type = IDENTITY
}
GmType[ref] = type
if ( type >= ROTZOOM )
{
read_global_param(type,ref,2)
read_global_param(type,ref,3)
if ( type == AFFINE )
{
read_global_param(type,ref,4)
read_global_param(type,ref,5)
}
else
{
gm_params[ref][4] = -gm_params[ref][3]
gm_params[ref][5] = gm_params[ref][2]
}
}
if ( type >= TRANSLATION )
{
read_global_param(type,ref,0)
read_global_param(type,ref,1)
}
}
}
5.9.25 read_global_param语法
read_global_param( type, ref, idx )
{
absBits = GM_ABS_ALPHA_BITS
precBits = GM_ALPHA_PREC_BITS
if ( idx < 2 )
{
if ( type == TRANSLATION )
{
absBits = GM_ABS_TRANS_ONLY_BITS - !allow_high_precision_mv
precBits = GM_TRANS_ONLY_PREC_BITS - !allow_high_precision_mv
}
else
{
absBits = GM_ABS_TRANS_BITS
precBits = GM_TRANS_PREC_BITS
}
}
precDiff = WARPEDMODEL_PREC_BITS – precBits
round = (idx % 3) == 2 ? (1 << WARPEDMODEL_PREC_BITS) : 0
sub = (idx % 3) == 2 ? (1 << precBits) : 0
mx = (1 << absBits)
r = (PrevGmParams[ref][idx] >> precDiff) - sub
gm_params[ref][idx] = (decode_signed_subexp_with_ref( -mx, mx + 1, r )<< precDiff) + round
}
注意:当force_integer_mv等于1时,转换组件仍会读取一些小数位。但是,这些小数位将在Setup Global MV处理过程中被舍弃。
5.9.26 decode_signed_subexp_with_ref语法
decode_signed_subexp_with_ref( low, high, r )
{
x = decode_unsigned_subexp_with_ref(high - low, r - low)
return x + low
}
注意:decode_signed_subexp_with_ref的返回值范围为low~(high-1)。
5.9.27 decode_unsigned_subexp_with_ref语法
decode_unsigned_subexp_with_ref( mx, r )
{
v = decode_subexp( mx )
if ( (r << 1) <= mx )
{
return inverse_recenter(r, v)
}
else
{
return mx - 1 - inverse_recenter(mx - 1 - r, v)
}
}
注意:decode_unsigned_subexp_with_ref的返回值范围为0~(mx-1)。
5.9.28 decode_subexp语法
decode_subexp( numSyms )
{
i = 0
mk = 0
k = 3
while ( 1 )
{
b2 = i ? k + i - 1 : k
a = 1 << b2
if ( numSyms <= mk + 3 * a )
{
subexp_final_bits ns(numSyms - mk)
return subexp_final_bits + mk
}
else
{
subexp_more_bits // Type f(1)
if ( subexp_more_bits )
{
i++
mk += a
}
else
{
subexp_bits // Type f(b2)
return subexp_bits + mk
}
}
}
}
5.9.29 inverse_recenter函数
inverse_recenter( r, v )
{
if ( v > 2 * r )
return v
else if ( v & 1 )
return r - ((v + 1) >> 1)
else
return r + (v >> 1)
}
5.9.30 film_grain_params语法
film_grain_params( )
{
if ( !film_grain_params_present || (!show_frame && !showable_frame) )
{
reset_grain_params()
return
}
apply_grain // Type f(1)
if ( !apply_grain )
{
reset_grain_params()
return
}
grain_seed // Type f(16)
if ( frame_type == INTER_FRAME )
update_grain // Type f(1)
else
update_grain = 1
if ( !update_grain )
{
film_grain_params_ref_idx // Type f(3)
tempGrainSeed = grain_seed
load_grain_params( film_grain_params_ref_idx )
grain_seed = tempGrainSeed
return
}
num_y_points // Type f(4)
for ( i = 0; i < num_y_points; i++ )
{
point_y_value[ i ] // Type f(8)
point_y_scaling[ i ] // Type f(8)
}
if ( mono_chrome )
{
chroma_scaling_from_luma = 0
}
else
{
chroma_scaling_from_luma // Type f(1)
}
if ( mono_chrome || chroma_scaling_from_luma || ( subsampling_x == 1 && subsampling_y == 1 && num_y_points == 0 ))
{
num_cb_points = 0
num_cr_points = 0
}
else
{
num_cb_points // Type f(4)
for ( i = 0; i < num_cb_points; i++ )
{
point_cb_value[ i ] // Type f(8)
point_cb_scaling[ i ] // Type f(8)
}
num_cr_points // Type f(4)
for ( i = 0; i < num_cr_points; i++ )
{
point_cr_value[ i ] // Type f(8)
point_cr_scaling[ i ] // Type f(8)
}
}
grain_scaling_minus_8 // Type f(2)
ar_coeff_lag // Type f(2)
numPosLuma = 2 * ar_coeff_lag * ( ar_coeff_lag + 1 )
if ( num_y_points )
{
numPosChroma = numPosLuma + 1
for ( i = 0; i < numPosLuma; i++ )
ar_coeffs_y_plus_128[ i ] // Type f(8)
}
else
{
numPosChroma = numPosLuma
}
if ( chroma_scaling_from_luma || num_cb_points )
{
for ( i = 0; i < numPosChroma; i++ )
ar_coeffs_cb_plus_128[ i ] // Type f(8)
}
if ( chroma_scaling_from_luma || num_cr_points )
{
for ( i = 0; i < numPosChroma; i++ )
ar_coeffs_cr_plus_128[ i ] // Type f(8)
}
ar_coeff_shift_minus_6 // Type f(2)
grain_scale_shift // Type f(2)
if ( num_cb_points )
{
cb_mult // Type f(8)
cb_luma_mult // Type f(8)
cb_offset // Type f(9)
}
if ( num_cr_points )
{
cr_mult // Type f(8)
cr_luma_mult // Type f(8)
cr_offset // Type f(9)
}
overlap_flag // Type f(1)
clip_to_restricted_range // Type f(1)
}
5.9.31 temporal_point_info语法
temporal_point_info( )
{
n = frame_presentation_time_length_minus_1 + 1
frame_presentation_time // Type f(n)
}
5.10 帧OBU语法
frame_obu( sz )
{
startBitPos = get_position( )
frame_header_obu( )
byte_alignment( )
endBitPos = get_position( )
headerBytes = (endBitPos - startBitPos) / 8
sz -= headerBytes
tile_group_obu( sz )
}