▼ AV2 Syntax Browser

AV2 Syntax Browser

AOM Working Group Draft, 5 January 2026

Version: v13-public@7181740

⚠️ This is not the official specification. See AV2 Specification
Section 5: Syntax Structures

5.1. General

This section presents the syntax structures in a tabular form. The meaning of each of the syntax elements is presented in § 6 Syntax structures semantics.

5.2. OBU syntax

5.2.1. General OBU syntax

open_bitstream_unit( sz ) { Descriptor
obu_header()
obuPayloadSize = sz - 1 - obu_header_extension_flag
startPosition = get_position( )
if ( obu_type != OBU_SEQUENCE_HEADER &&
obu_type != OBU_TEMPORAL_DELIMITER &&
OperatingPointIdc != 0 )
{
inTLayer = (OperatingPointIdc >> obu_tlayer_id ) & 1
inMLayer = (OperatingPointIdc >> (obu_mlayer_id + MAX_NUM_TLAYERS) ) & 1
if ( !inTLayer || ! inMLayer ) {
drop_obu( obuPayloadSize )
return
}
}
if ( obu_type == OBU_SEQUENCE_HEADER ) {
sequence_header_obu( )
} else if ( obu_type == OBU_TEMPORAL_DELIMITER ) {
temporal_delimiter_obu( )
} else if ( obu_type == OBU_MSDO ) {
multi_stream_decoder_operation_obu()
} else if ( obu_type == OBU_MULTI_FRAME_HEADER ) {
multi_frame_header_obu( )
} else if ( is_sef() || is_tip_frame() || obu_type == OBU_BRIDGE_FRAME ) {
frame_header( 1 )
} else if ( obu_type == OBU_METADATA_SHORT ) {
metadata_short_obu( )
} else if ( obu_type == OBU_METADATA_GROUP ) {
metadata_group_obu( )
} else if ( is_tile_group() ) {
tile_group_obu( obuPayloadSize )
} else if ( obu_type == OBU_LAYER_CONFIGURATION_RECORD ) {
layer_config_record_obu( )
} else if ( obu_type == OBU_ATLAS_SEGMENT ) {
atlas_segment_info_obu( )
} else if ( obu_type == OBU_OPERATING_POINT_SET ) {
operating_point_set_obu( )
} else if ( obu_type == OBU_BUFFER_REMOVAL_TIMING ) {
buffer_removal_timing_obu( )
} else if ( obu_type == OBU_QUANTIZATION_MATRIX ) {
quantizer_matrix_obu( )
} else if ( obu_type == OBU_FILM_GRAIN ) {
film_grain_obu( )
} else if ( obu_type == OBU_CONTENT_INTERPRETATION ) {
content_interpretation_obu( )
} else if ( obu_type == OBU_PADDING ) {
padding_obu( )
} else {
reserved_obu( )
}
usedArith = is_tile_group()
currentPosition = get_position( )
parsedPayloadBits = currentPosition - startPosition
remainingPayloadBits = obuPayloadSize * 8 - parsedPayloadBits
if ( obuPayloadSize > 0 && !usedArith ) {
if ( is_extensible_obu() ) {
// OBUs with extensible payloads
obu_extension_flag f(1)
if ( obu_extension_flag ) {
obu_extension_data( remainingPayloadBits - 1 )
} else {
trailing_bits( remainingPayloadBits - 1 )
}
} else {
trailing_bits( remainingPayloadBits )
}
}
}

where some helper functions used to identify collections of OBU types are specified as:

is_tip_frame() {    return obu_type == OBU_LEADING_TIP || obu_type == OBU_REGULAR_TIP}
is_sef() {    return obu_type == OBU_LEADING_SEF || obu_type == OBU_REGULAR_SEF}
is_tile_group() {    return obu_type == OBU_LEADING_TILE_GROUP ||            obu_type == OBU_REGULAR_TILE_GROUP ||            obu_type == OBU_CLOSED_LOOP_KEY ||            obu_type == OBU_OPEN_LOOP_KEY ||           obu_type == OBU_SWITCH ||           obu_type == OBU_RAS_FRAME}
is_extensible_obu() { Descriptor
return obu_type == OBU_SEQUENCE_HEADER ||
obu_type == OBU_MULTI_FRAME_HEADER ||
obu_type == OBU_LAYER_CONFIGURATION_RECORD ||
obu_type == OBU_CONTENT_INTERPRETATION ||
obu_type == OBU_OPERATING_POINT_SET ||
obu_type == OBU_ATLAS_SEGMENT
}
obu_extension_data( sz ) { Descriptor
for ( i = 0; i < sz; i++ ) {
obu_extension_data_bit f(1)
}
}

5.2.2. OBU header syntax

obu_header() { Descriptor
obu_header_extension_flag f(1)
obu_type f(5)
obu_tlayer_id f(2)
if ( obu_header_extension_flag == 1 ) {
obu_mlayer_id f(3)
obu_xlayer_id f(5)
} else {
obu_mlayer_id = 0
obu_xlayer_id = ( obu_type == OBU_MSDO ) ? GLOBAL_XLAYER_ID : 0
}
}

5.2.3. Trailing bits syntax

trailing_bits( nbBits ) { Descriptor
trailing_one_bit f(1)
nbBits--
while ( nbBits > 0 ) {
trailing_zero_bit f(1)
nbBits--
}
}

5.2.4. Byte alignment syntax

byte_alignment( ) { Descriptor
while ( get_position( ) & 7 ) {
zero_bit f(1)
}
}

5.3. Reserved OBU syntax

reserved_obu( ) { Descriptor
}

Note: Reserved OBUs do not have a defined syntax. The obu_type reserved values are reserved for future use. Decoders should ignore the entire OBU if they do not understand the obu_type. The last byte of the valid content of the payload data for this OBU type is considered to be the last byte that is not equal to zero. This rule is to prevent the dropping of valid bytes by systems that interpret trailing zero bytes as a continuation of the trailing bits in an OBU. This implies that when any payload data is present for this OBU type, at least one byte of the payload data (including the trailing bit) shall not be equal to 0.

5.4. Sequence header OBU syntax

5.4.1. General sequence header OBU syntax

sequence_header_obu( ) { Descriptor
FirstLayer = 1
for ( i = 0; i < MAX_NUM_MLAYERS; i++ ) {
OlkRefresh[ i ] = 0
}
seq_header_id uvlc()
seq_profile_idc f(5)
single_picture_header_flag f(1)
if ( single_picture_header_flag ) {
seq_lcr_id = 0
still_picture = 1
} else {
seq_lcr_id f(3)
still_picture f(1)
}
seq_level_idx f(5)
if ( seq_level_idx > 7 && !single_picture_header_flag ) {
seq_tier f(1)
} else {
seq_tier = 0
}
frame_width_bits_minus_1 f(4)
frame_height_bits_minus_1 f(4)
n = frame_width_bits_minus_1 + 1
max_frame_width_minus_1 f(n)
n = frame_height_bits_minus_1 + 1
max_frame_height_minus_1 f(n)
seq_cropping_window_present_flag f(1)
if ( seq_cropping_window_present_flag ) {
seq_cropping_win_left_offset uvlc()
seq_cropping_win_right_offset uvlc()
seq_cropping_win_top_offset uvlc()
seq_cropping_win_bottom_offset uvlc()
} else {
seq_cropping_win_left_offset = 0
seq_cropping_win_right_offset = 0
seq_cropping_win_top_offset = 0
seq_cropping_win_bottom_offset = 0
}
color_config( )
operatingPoint = 0
OperatingPointIdc = 0
if ( single_picture_header_flag ) {
decoder_model_info_present_flag = 0
max_tlayer_id = 0
max_mlayer_id = 0
seq_max_mlayer_cnt = 1
} else {
max_display_model_info_present_flag f(1)
if ( max_display_model_info_present_flag ) {
max_initial_display_delay_minus_1 f(4)
} else {
max_initial_display_delay_minus_1 = BUFFER_POOL_MAX_SIZE - 1
}
decoder_model_info_present_flag f(1)
if ( decoder_model_info_present_flag ) {
decoder_model_info( )
max_display_model_info_present_flag f(1)
if ( max_display_model_info_present_flag ) {
operating_parameters_info( )
}
}
max_tlayer_id f(2)
max_mlayer_id f(3)
if ( max_mlayer_id > 0 ) {
n = CeilLog2(max_mlayer_id + 1)
seq_max_mlayer_cnt f(n)
}
}
for ( currLayer = 0; currLayer < MAX_NUM_TLAYERS; currLayer++ ) {
for ( refLayer = 0; refLayer < MAX_NUM_TLAYERS; refLayer++ ) {
TLayerDependencyMap[ currLayer ][ refLayer ] =
refLayer <= currLayer && currLayer <= max_tlayer_id
}
}
for ( currLayer = 0; currLayer < MAX_NUM_MLAYERS; currLayer++ ) {
for ( refLayer = 0; refLayer < MAX_NUM_MLAYERS; refLayer++ ) {
MLayerDependencyMap[ currLayer ][ refLayer ] =
refLayer <= currLayer && currLayer <= max_mlayer_id
}
}
if ( max_tlayer_id > 0 ) {
tlayer_dependency_present_flag f(1)
if ( tlayer_dependency_present_flag ) {
for ( currLayer = 1; currLayer <= max_tlayer_id; currLayer++ ) {
for ( refLayer = currLayer; refLayer >= 0; refLayer-- ) {
tlayer_dependency_map f(1)
TLayerDependencyMap[ currLayer ][ refLayer ] =
tlayer_dependency_map
}
}
}
}
if ( max_mlayer_id > 0 ) {
mlayer_dependency_present_flag f(1)
if ( mlayer_dependency_present_flag ) {
for ( currLayer = 1; currLayer <= max_mlayer_id; currLayer++ ) {
for ( refLayer = currLayer; refLayer >= 0; refLayer-- ) {
mlayer_dependency_map f(1)
MLayerDependencyMap[ currLayer ][ refLayer ] =
mlayer_dependency_map
}
}
}
}
sequence_partition_config( )
sequence_segment_config( )
sequence_intra_config( )
sequence_inter_config( )
sequence_scc_config( )
sequence_transform_quant_entropy_config( )
sequence_filter_config( )
seq_tile_info_present_flag f(1)
if ( seq_tile_info_present_flag ) {
allow_tile_info_change f(1)
seqSbSize = get_seq_sb_size()
( SeqSbRowStarts, SeqSbRows, SeqTileRows, SeqTileRowsLog2,
SeqSbColStarts, SeqSbCols, SeqTileCols, SeqTileColsLog2,
SeqUniformTileSpacingFlag, sbShift) = tile_params(
max_frame_width_minus_1 + 1, max_frame_height_minus_1 + 1,
seqSbSize, seqSbSize, 0 )
}
film_grain_params_present f(1)
save_sequence_header( )
}

5.4.2. Sequence partition config syntax

sequence_partition_config( ) { Descriptor
use_256x256_superblock f(1)
if ( !use_256x256_superblock ) {
use_128x128_superblock f(1)
}
if ( Monochrome ) {
enable_sdp = 0
} else {
enable_sdp f(1)
}
if ( enable_sdp && !single_picture_header_flag ) {
enable_extended_sdp f(1)
} else {
enable_extended_sdp = 0
}
enable_ext_partitions f(1)
if ( enable_ext_partitions ) {
enable_uneven_4way_partitions f(1)
} else {
enable_uneven_4way_partitions = 0
}
reduce_pb_aspect_ratio f(1)
if ( reduce_pb_aspect_ratio ) {
max_pb_aspect_ratio_log2_minus1 f(1)
MaxPbAspectRatio = 1 << (max_pb_aspect_ratio_log2_minus1 + 1)
} else {
MaxPbAspectRatio = 8
}
}

5.4.3. Sequence segment config syntax

sequence_segment_config( ) { Descriptor
enable_ext_seg f(1)
MaxSegments = enable_ext_seg ? 16 : 8
seq_seg_info_present_flag f(1)
if ( seq_seg_info_present_flag ) {
seq_allow_seg_info_change f(1)
( SeqFeatureEnabled, SeqFeatureData ) = seg_info( MaxSegments )
}
}

5.4.4. Sequence intra config syntax

sequence_intra_config( ) { Descriptor
enable_dip f(1)
enable_intra_edge_filter f(1)
enable_mrls f(1)
enable_cfl_intra f(1)
if ( Monochrome ) {
cfl_ds_filter_index = 0
} else {
cfl_ds_filter_index f(2)
}
enable_mhccp f(1)
enable_ibp f(1)
}

5.4.5. Sequence inter config syntax

sequence_inter_config( ) { Descriptor
if ( single_picture_header_flag ) {
for ( i = 0; i < MOTION_MODES; i++ ) {
seq_enabled_motion_modes[ i ] = 0
}
enable_six_param_warp_delta = 0
enable_masked_compound = 0
enable_ref_frame_mvs = 0
reduced_ref_frame_mvs_mode = 0
OrderHintBits = 0
enable_opfl_refine = REFINE_NONE
enable_refmvbank f(1)
disable_drl_reorder f(1)
if ( disable_drl_reorder ) {
DrlReorder = DRL_REORDER_DISABLED
} else {
constrain_drl_reorder f(1)
DrlReorder = constrain_drl_reorder ?
DRL_REORDER_CONSTRAINT : DRL_REORDER_ALWAYS
}
seq_max_bvp_drl_bits_minus1 ns(4 - 1)
allow_frame_max_bvp_drl_bits f(1)
enable_bawp f(1)
enable_mv_traj = 0
enable_imp_msk_bld = 0
NumRefFrames = 2
long_term_frame_id_bits = 0
} else {
motionModeEnabled = 0
for ( mode = INTERINTRA; mode < MOTION_MODES; mode++ ) {
seq_enabled_motion_modes[ mode ] f(1)
motionModeEnabled |= seq_enabled_motion_modes[ mode ]
}
if ( motionModeEnabled ) {
seq_frame_motion_modes_present_flag f(1)
} else {
seq_frame_motion_modes_present_flag = 0
}
if ( seq_enabled_motion_modes[ DELTAWARP ] ) {
enable_six_param_warp_delta f(1)
} else {
enable_six_param_warp_delta = 0
}
enable_masked_compound f(1)
enable_ref_frame_mvs f(1)
if ( enable_ref_frame_mvs ) {
reduced_ref_frame_mvs_mode f(1)
} else {
reduced_ref_frame_mvs_mode = 0
}
order_hint_bits_minus_1 f(3)
OrderHintBits = order_hint_bits_minus_1 + 1
enable_refmvbank f(1)
disable_drl_reorder f(1)
if ( disable_drl_reorder ) {
DrlReorder = DRL_REORDER_DISABLED
} else {
constrain_drl_reorder f(1)
DrlReorder = constrain_drl_reorder ? DRL_REORDER_CONSTRAINT :
DRL_REORDER_ALWAYS
}
explicit_ref_frame_map f(1)
use_extra_ref_frames f(1)
if ( use_extra_ref_frames ) {
num_ref_frames_minus_1 f(4)
NumRefFrames = num_ref_frames_minus_1 + 1
} else {
NumRefFrames = 8
}
ActiveNumRefFrames = Min( REFS_PER_FRAME, NumRefFrames )
long_term_frame_id_bits f(3)
seq_max_drl_bits_minus1 ns(6 - 1)
allow_frame_max_drl_bits f(1)
seq_max_bvp_drl_bits_minus1 ns(4 - 1)
allow_frame_max_bvp_drl_bits f(1)
num_same_ref_compound f(2)
enable_tip f(1)
if ( enable_tip ) {
disable_tip_output f(1)
EnableTipOutput = !disable_tip_output
enable_tip_hole_fill f(1)
} else {
enable_tip_hole_fill = 0
EnableTipOutput = 0
}
enable_mv_traj f(1)
enable_bawp f(1)
enable_cwp f(1)
enable_imp_msk_bld f(1)
enable_lf_sub_pu f(1)
if ( EnableTipOutput && enable_lf_sub_pu ) {
enable_tip_explicit_qp f(1)
} else {
enable_tip_explicit_qp = 0
}
enable_opfl_refine f(2)
enable_refinemv f(1)
if ( enable_tip && ( enable_opfl_refine != 0 || enable_refinemv ) ) {
enable_tip_refinemv f(1)
} else {
enable_tip_refinemv = 0
}
enable_bru f(1)
enable_adaptive_mvd f(1)
enable_mvd_sign_derive f(1)
enable_flex_mvres f(1)
if ( single_picture_header_flag ) {
enable_global_motion = 0
} else {
enable_global_motion f(1)
}
enable_short_refresh_frame_flags f(1)
}
}

5.4.6. Sequence screen content config syntax

sequence_scc_config( ) { Descriptor
if ( single_picture_header_flag ) {
seq_force_screen_content_tools = SELECT_SCREEN_CONTENT_TOOLS
seq_force_integer_mv = SELECT_INTEGER_MV
} else {
seq_choose_screen_content_tools f(1)
if ( seq_choose_screen_content_tools ) {
seq_force_screen_content_tools = SELECT_SCREEN_CONTENT_TOOLS
} else {
seq_force_screen_content_tools f(1)
}
if ( seq_force_screen_content_tools > 0 ) {
seq_choose_integer_mv f(1)
if ( seq_choose_integer_mv ) {
seq_force_integer_mv = SELECT_INTEGER_MV
} else {
seq_force_integer_mv f(1)
}
} else {
seq_force_integer_mv = SELECT_INTEGER_MV
}
}
}

5.4.7. Sequence transform quant entropy config syntax

sequence_transform_quant_entropy_config( ) { Descriptor
enable_fsc f(1)
if ( enable_fsc ) {
enable_idtx_intra = 1
} else {
enable_idtx_intra f(1)
}
enable_intra_ist f(1)
enable_inter_ist f(1)
if ( Monochrome ) {
enable_chroma_dctonly = 0
} else {
enable_chroma_dctonly f(1)
}
if ( !single_picture_header_flag ) {
enable_inter_ddt f(1)
}
reduced_tx_part_set f(1)
if ( Monochrome ) {
enable_cctx = 0
} else {
enable_cctx f(1)
}
enable_tcq f(1)
if ( enable_tcq && !single_picture_header_flag ) {
choose_tcq_per_frame f(1)
} else {
choose_tcq_per_frame = 0
}
if ( enable_tcq && !choose_tcq_per_frame ) {
enable_parity_hiding = 0
} else {
enable_parity_hiding f(1)
}
if ( single_picture_header_flag ) {
enable_avg_cdf = 1
avg_cdf_type = 1
} else {
enable_avg_cdf f(1)
if ( enable_avg_cdf ) {
avg_cdf_type f(1)
}
}
if ( Monochrome ) {
separate_uv_delta_q = 0
} else {
separate_uv_delta_q f(1)
}
BaseYDcDeltaQ = 0
BaseUVDcDeltaQ = 0
BaseUVAcDeltaQ = 0
y_dc_delta_q_enabled = 0
uv_dc_delta_q_enabled = 0
uv_ac_delta_q_enabled = 0
equal_ac_dc_q f(1)
if ( !equal_ac_dc_q ) {
base_y_dc_delta_q f(5)
BaseYDcDeltaQ = DELTA_DCQUANT_MIN + base_y_dc_delta_q
y_dc_delta_q_enabled f(1)
}
if ( !Monochrome ) {
if ( !equal_ac_dc_q ) {
base_uv_dc_delta_q f(5)
BaseUVDcDeltaQ = DELTA_DCQUANT_MIN + base_uv_dc_delta_q
uv_dc_delta_q_enabled f(1)
}
base_uv_ac_delta_q f(5)
BaseUVAcDeltaQ = DELTA_DCQUANT_MIN + base_uv_ac_delta_q
uv_ac_delta_q_enabled f(1)
if ( equal_ac_dc_q ) {
BaseUVDcDeltaQ = BaseUVAcDeltaQ
}
}
}

5.4.8. Segment information syntax

seg_info( numSegments ) { Descriptor
for ( i = 0; i < numSegments; i++ ) {
for ( j = 0; j < SEG_LVL_MAX; j++ ) {
feature_enabled f(1)
enabled[ 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 f(bitsToRead)
clippedValue = Clip3( 0, limit, feature_value)
}
}
data[ i ][ j ] = clippedValue
}
}
return (enabled, data)
}

5.4.9. Sequence filter config syntax

sequence_filter_config( ) { Descriptor
disable_loopfilters_across_tiles f(1)
enable_cdef f(1)
enable_gdf f(1)
enable_restoration f(1)
if ( enable_restoration ) {
lr_tools_disable[ 0 ][ RESTORE_PC_WIENER ] f(1)
lr_tools_disable[ 0 ][ RESTORE_WIENER_NONSEP ] f(1)
lr_tools_disable[ 1 ][ RESTORE_PC_WIENER ] = 1
lr_tools_uv_present f(1)
if ( lr_tools_uv_present ) {
lr_tools_disable[ 1 ][ RESTORE_WIENER_NONSEP ] f(1)
} else {
lr_tools_disable[ 1 ][ RESTORE_WIENER_NONSEP ] =
lr_tools_disable[ 0 ][ RESTORE_WIENER_NONSEP ]
}
}
enable_ccso f(1)
if ( single_picture_header_flag ) {
CdefOnSkipTxfm = CDEF_ON_SKIP_TXFM_ADAPTIVE
} else {
cdef_on_skip_txfm_always_on f(1)
if (cdef_on_skip_txfm_always_on) {
CdefOnSkipTxfm = CDEF_ON_SKIP_TXFM_ALWAYS_ON
} else {
cdef_on_skip_txfm_disabled f(1)
CdefOnSkipTxfm = cdef_on_skip_txfm_disabled ?
CDEF_ON_SKIP_TXFM_DISABLED : CDEF_ON_SKIP_TXFM_ADAPTIVE
}
}
df_par_bits_minus2 f(2)
}

5.4.10. User defined QM syntax

user_defined_qm( level, t, plane ) { Descriptor
txSz = Fundamental_Tx_Size[ t ]
w = Tx_Width[ txSz ]
h = Tx_Height[ txSz ]
if ( plane > 0 ) {
qm_copy_from_previous_plane f(1)
if ( qm_copy_from_previous_plane ) {
for ( i = 0; i < h; i++ ) {
for ( j = 0; j < w; j++ ) {
UserQm[ level ][ t ][ plane ][ i ][ j ] =
UserQm[ level ][ t ][ plane - 1 ][ i ][ j ]
}
}
return
}
}
if ( t == 0 ) {
qm_8x8_is_symmetric f(1)
} else if ( t == 2 ) {
qm_4x8_is_transpose_of_8x4 f(1)
if ( qm_4x8_is_transpose_of_8x4 ) {
for ( i = 0; i < h; i++ ) {
for ( j = 0; j < w; j++ ) {
UserQm[ level ][ t ][ plane ][ i ][ j ] =
UserQm[ level ][ 1 ][ plane ][ j ][ i ]
}
}
return
}
}
scan = get_scan( txSz, TX_CLASS_2D )
quant = 32
coefRepeat = 0
for ( c = 0; c < w * h; c++ ) {
pos = scan[ c ]
(row, col) = get_tx_row_col(pos, txSz)
if ( t == 0 && qm_8x8_is_symmetric && col > row ) {
quant = UserQm[ level ][ t ][ plane ][ col ][ row ]
UserQm[ level ][ t ][ plane ][ row ][ col ] = quant
} else if ( coefRepeat ) {
UserQm[ level ][ t ][ plane ][ row ][ col ] = quant
} else {
quant_delta svlc()
quant2 = (quant + quant_delta) & 255
if ( quant2 == 0 ) {
coefRepeat = 1
} else {
quant = quant2
}
UserQm[ level ][ t ][ plane ][ row ][ col ] = quant
}
}
}

where Fundamental_Tx_Size (which gives the order of quantization matrices) is specified as:

Fundamental_Tx_Size[ 3 ] = { TX_8X8, TX_8X4, TX_4X8 }

5.4.11. Color config syntax

color_config( ) { Descriptor
chroma_format_idc uvlc()
if ( chroma_format_idc == CHROMA_FORMAT_420 ) {
SubsamplingX = 1
SubsamplingY = 1
} else if ( chroma_format_idc == CHROMA_FORMAT_444 ) {
SubsamplingX = 0
SubsamplingY = 0
} else if ( chroma_format_idc == CHROMA_FORMAT_422 ) {
SubsamplingX = 1
SubsamplingY = 0
} else if ( chroma_format_idc == CHROMA_FORMAT_400 ) {
SubsamplingX = 1
SubsamplingY = 1
}
bit_depth_idc uvlc()
BitDepth = bit_depth_idc == 0 ? 10 : (bit_depth_idc == 1 ? 8 : 12)
MaxQ = BitDepth == 8 ? MAXQ_8_BITS : (BitDepth == 10 ? MAXQ_10_BITS :
MAXQ_12_BITS)
Monochrome = chroma_format_idc == CHROMA_FORMAT_400
NumPlanes = Monochrome ? 1 : 3
}

5.4.12. Timing info syntax

timing_info( ) { Descriptor
num_units_in_display_tick f(32)
time_scale f(32)
equal_picture_interval f(1)
if ( equal_picture_interval ) {
num_ticks_per_picture_minus_1 uvlc()
}
}

5.4.13. Decoder model info syntax

decoder_model_info( ) { Descriptor
num_units_in_decoding_tick f(32)
}

5.4.14. Operating parameters info syntax

operating_parameters_info( ) { Descriptor
decoder_buffer_delay uvlc()
encoder_buffer_delay uvlc()
low_delay_mode_flag f(1)
}

5.5. Temporal delimiter OBU syntax

temporal_delimiter_obu( ) { Descriptor
SeenFrameHeader = 0
}

Note: The temporal delimiter has an empty payload.

5.6. Multi stream decoder operation OBU syntax

multi_stream_decoder_operation_obu( ) { Descriptor
num_streams_minus2 f(3)
multi_config_idc f(6)
multi_level_idx f(5)
multi_tier f(1)
multi_interop f(4)
multi_even_allocation_flag f(1)
if ( !multi_even_allocation_flag ) {
multi_large_picture_idc f(3)
}
for ( i = 0; i < num_streams_minus2 + 2; i++ ) {
sub_xlayer_id[ i ] f(5)
sub_profile[ i ] f(5)
sub_level[ i ] f(5)
sub_tier[ i ] f(1)
sub_mlayer_count[ i ] f(4)
}
}

5.7. Multi frame header OBU syntax

multi_frame_header_obu( ) { Descriptor
mfh_seq_header_id uvlc()
mfh_id_minus1 uvlc()
mfhId = mfh_id_minus1 + 1
MfhSeqHeaderId[ mfhId ] = mfh_seq_header_id
mfh_frame_size_present_flag[ mfhId ] f(1)
mfh_tile_info_present_flag[ mfhId ] f(1)
if ( mfh_frame_size_present_flag[ mfhId ] ||
mfh_tile_info_present_flag[ mfhId ] ) {
mfh_frame_width_bits_minus_1 f(4)
mfh_frame_height_bits_minus_1 f(4)
n = mfh_frame_width_bits_minus_1 + 1
mfh_frame_width_minus_1[ mfhId ] f(n)
n = mfh_frame_height_bits_minus_1 + 1
mfh_frame_height_minus_1[ mfhId ] f(n)
}
mfh_loop_filter_update[ mfhId ] f(1)
if ( mfh_loop_filter_update[ mfhId ] ) {
for ( i = 0; i < 4; i++ ) {
mfh_apply_loop_filter[ mfhId ][ i ] f(1)
}
}
if ( mfh_tile_info_present_flag[ mfhId ] ) {
mfh_sb_size_idx f(2)
if ( mfh_sb_size_idx == 0 ) {
seqSbSize = BLOCK_64X64
sbSize = BLOCK_64X64
} else if ( mfh_sb_size_idx == 1 ) {
seqSbSize = BLOCK_128X128
sbSize = BLOCK_128X128
} else if ( mfh_sb_size_idx == 2 ) {
seqSbSize = BLOCK_256X256
sbSize = BLOCK_256X256
} else {
seqSbSize = BLOCK_256X256
sbSize = BLOCK_128X128
}
mfh_allow_tile_info_change[ mfhId ] f(1)
( sbRowStarts, MfhSbRows[ mfhId ], MfhTileRows[ mfhId ],
MfhTileRowsLog2[ mfhId ], sbColStarts, MfhSbCols[ mfhId ],
MfhTileCols[ mfhId ], MfhTileColsLog2[ mfhId ],
MfhUniform[ mfhId ], sbShift) =
tile_params( mfh_frame_width_minus_1[ mfhId ] + 1,
mfh_frame_height_minus_1[ mfhId ] + 1,
seqSbSize, sbSize, 0 )
for ( i = 0; i < MfhTileRows[ mfhId ]; i++ ) {
MfhSbRowStarts[ mfhId ][ i ] = sbRowStarts[ i ]
}
for ( i = 0; i < MfhTileCols[ mfhId ]; i++ ) {
MfhSbColStarts[ mfhId ][ i ] = sbColStarts[ i ]
}
}
mfh_seg_info_present_flag[ mfhId ] f(1)
if ( mfh_seg_info_present_flag[ mfhId ] ) {
mfh_ext_seg_flag[ mfhId ] f(1)
mfh_allow_seg_info_change[ mfhId ] f(1)
( MfhFeatureEnabled[mfhId], MfhFeatureData[mfhId] ) =
seg_info( mfh_ext_seg_flag[ mfhId ] ? 16 : 8 )
}
}

5.8. Layer config record OBU syntax

layer_config_record_obu() { Descriptor
if ( obu_xlayer_id == GLOBAL_XLAYER_ID ) {
lcr_global_info( )
} else {
lcr_local_info( obu_xlayer_id )
}
}

5.8.1. LCR global info syntax

lcr_global_info( ) { Descriptor
lcr_global_config_record_id f(3)
lcr_xlayer_map f(31)
LcrMaxNumXLayerCount = 0
for ( i = 0; i < 31; i++ ) {
if ( lcr_xlayer_map & ( 1 << i ) ) {
LcrXLayerID[LcrMaxNumXLayerCount ] = i
LcrMaxNumXLayerCount ++
}
}
lcr_aggregate_profile_tier_level_info_present_flag f(1)
lcr_seq_profile_tier_level_info_present_flag f(1)
lcr_global_payload_present_flag f(1)
lcr_dependent_xlayers_flag f(1)
lcr_global_atlas_id_present_flag f(1)
lcr_global_purpose_id f(7)
if ( lcr_global_atlas_id_present_flag ) {
lcr_global_atlas_id f(3)
} else {
lcr_reserved_zero_3bits f(3)
}
lcr_reserved_zero_7bits f(7)
if ( lcr_aggregate_profile_tier_level_info_present_flag ) {
lcr_aggregate_profile_tier_level_info( )
}
if ( lcr_seq_profile_tier_level_info_present_flag ) {
for ( i = 0; i < LcrMaxNumXLayerCount; i++ ) {
lcr_seq_profile_tier_level_info( LcrXLayerID[ i ] )
}
}
if ( lcr_global_payload_present_flag ) {
for ( i = 0; i < LcrMaxNumXLayerCount; i++) {
lcr_data_size [ i ] leb128()
lcr_global_payload( LcrXLayerID[ i ] )
}
}
}

5.8.2. LCR local info syntax

lcr_local_info( xlayerId ) { Descriptor
lcr_global_id[ xlayerId ] f(3)
lcr_local_id[ xlayerId ] f(3)
lcr_profile_tier_level_info_present_flag[ xlayerId ] f(1)
lcr_local_atlas_id_present_flag[ xlayerId ] f(1)
if ( lcr_profile_tier_level_info_present_flag[ xlayerId ] ) {
lcr_seq_profile_tier_level_info( xlayerId );
}
if ( lcr_local_atlas_id_present_flag[ xlayerId ] ) {
lcr_local_atlas_id[ xlayerId ] f(3)
} else {
lcr_reserved_zero_3bits f(3)
}
lcr_reserved_zero_5bits f(5)
lcr_xlayer_info( 0, xlayerId )
}

5.8.3. LCR aggregate profile tier level information syntax

lcr_aggregate_profile_tier_level_info( ) { Descriptor
lcr_config_idc f(6)
lcr_aggregate_level_idx f(5)
lcr_max_tier_flag f(1)
lcr_max_interop f(4)
}

5.8.4. LCR sequence profile tier level information syntax

lcr_seq_profile_tier_level_info( i ) { Descriptor
lcr_seq_profile_idc[ i ] f(5)
lcr_max_level_idx[ i ] f(5)
lcr_tier_flag[ i ] f(1)
lcr_max_mlayer_count[ i ] f(3)
lsptli_reserved_2bits f(2)
}

5.8.5. LCR global payload syntax

lcr_global_payload( n ) { Descriptor
if ( lcr_dependent_xlayers_flag && n > 0 ) {
lcr_num_dependent_xlayer_map[ n ] f(n)
}
lcr_xlayer_info( 1 , n )
}

5.8.6. LCR xlayer info syntax

lcr_xlayer_info( isGlobal, xId ) { Descriptor
lcr_rep_info_present_flag[ isGlobal ][ xId ] f(1)
lcr_xlayer_purpose_present_flag[ isGlobal ][ xId ] f(1)
lcr_xlayer_color_info_present_flag[ isGlobal ][ xId ] f(1)
lcr_embedded_layer_info_present_flag[ isGlobal ][ xId ] f(1)
if ( lcr_rep_info_present_flag[ isGlobal ][ xId ] ) {
lcr_rep_info( isGlobal, xId )
}
if( lcr_xlayer_purpose_present_flag[ isGlobal ][ xId ] ) {
lcr_xlayer_purpose_id[ isGlobal ][ xId ] f(7)
}
if( lcr_xlayer_color_info_present_flag[ isGlobal ][ xId ] ) {
lcr_xlayer_color_info( isGlobal, xId )
}
byte_alignment()
if ( lcr_embedded_layer_info_present_flag[ isGlobal ][ xId ] ) {
lcr_embedded_layer_info( isGlobal, xId )
} else {
if ( isGlobal && lcr_global_atlas_id_present_flag ) {
lcr_xlayer_atlas_segment_id[ xId ] f(8)
lcr_xlayer_priority_order[ xId ] f(8)
lcr_xlayer_rendering_method[ xId ] f(8)
}
}
}

5.8.7. LCR rep info syntax

lcr_rep_info( isGlobal, xId ) { Descriptor
lcr_max_pic_width[ isGlobal ][ xId ] uvlc()
lcr_max_pic_height[ isGlobal ][ xId ] uvlc()
lcr_format_info_present_flag[ isGlobal ][ xId ] f(1)
lcr_cropping_window_present_flag[ isGlobal ][ xId ] f(1)
if ( lcr_format_info_present_flag[ isGlobal ][ xId ] ) {
lcr_bit_depth_idc[ isGlobal ][ xId ] uvlc()
lcr_chroma_format_idc[ isGlobal ][ xId ] uvlc()
}
if ( lcr_cropping_window_present_flag[ isGlobal ][ xId ] ) {
lcr_cropping_win_left_offset [ isGlobal ][ xId ] uvlc()
lcr_cropping_win_right_offset[ isGlobal ][ xId ] uvlc()
lcr_cropping_win_top_offset [ isGlobal ][ xId ] uvlc()
lcr_cropping_win_bottom_offset[ isGlobal ][ xId ] uvlc()
}
}

5.8.8. LCR embedded layer info syntax

lcr_embedded_layer_info( isGlobal, xId ) { Descriptor
lcr_mlayer_map[ isGlobal ][ xId ] f(8)
for ( j = 0; j < 8; j++ ) {
if ( lcr_mlayer_map[ isGlobal ][ xId ] & (1 << j) ) {
lcr_tlayer_map[ isGlobal ][ xId ][ j ] f(4)
atlasSegmentPresent = isGlobal ?
lcr_global_atlas_id_present_flag :
lcr_local_atlas_id_present_flag[ xId ]
if ( atlasSegmentPresent ) {
lcr_layer_atlas_segment_id[ isGlobal ][ xId ][ j ] f(8)
lcr_priority_order[ isGlobal ][ xId ][ j ] f(8)
lcr_rendering_method[ isGlobal ][ xId ][ j ] f(8)
}
lcr_layer_type[ isGlobal ][ xId ][ j ] f(8)
if ( lcr_layer_type[ isGlobal ][ xId ][ j ] == AUX_LAYER ) {
lcr_auxiliary_type[ isGlobal ][ xId ][ j ] f(8)
}
lcr_view_type[ isGlobal ][ xId ][ j ] f(8)
if ( lcr_view_type[ isGlobal ][ xId ][ j ] == VIEW_EXPLICIT ) {
lcr_view_id[ isGlobal ][ xId ][ j ] f(8)
}
if ( j > 0 ) {
lcr_dependent_layer_map[ isGlobal ][ xId ][ j ] f(j)
}
lcr_crop_info_in_scr_flag[ isGlobal ][ xId ][ j ] f(1)
if ( !lcr_crop_info_in_scr_flag[ isGlobal ][ xId ][ j ] ) {
lcr_crop_max_width[ isGlobal ][ xId ][ j ] uvlc()
lcr_crop_max_height [ isGlobal ][ xId ][ j ] uvlc()
}
byte_alignment( )
}
}
}

5.8.9. LCR xlayer color info syntax

lcr_xlayer_color_info( isGlobal, xId ) { Descriptor
layer_color_description_idc[ isGlobal ][ xId ] rg(2)
if ( layer_color_description_idc[ isGlobal ][ xId ] == 0 ) {
layer_color_primaries[ isGlobal ][ xId ] f(8)
layer_transfer_characteristics[ isGlobal ][ xId ] f(8)
layer_matrix_coefficients[ isGlobal ][ xId ] f(8)
}
layer_full_range_flag[ isGlobal ][ xId ] f(1)
}

5.9. Atlas segment info OBU syntax

atlas_segment_info_obu( ) { Descriptor
atlas_segment_id[ obu_xlayer_id ] f(3)
xAId = atlas_segment_id[ obu_xlayer_id ]
ats_atlas_segment_mode_idc[ obu_xlayer_id ][ xAId ] uvlc()
if ( ats_atlas_segment_mode_idc[ obu_xlayer_id ][ xAId ] ==
ENHANCED_ATLAS ) {
ats_region_info( obu_xlayer_id, xAId )
ats_region_to_segment_mapping( obu_xlayer_id , xAId )
} else if ( ats_atlas_segment_mode_idc[ obu_xlayer_id ][ xAId ] ==
MULTISTREAM_ATLAS ) {
ats_multistream_atlas_info( obu_xlayer_id, xAId, 0 )
} else if ( ats_atlas_segment_mode_idc[ obu_xlayer_id ][ xAId ] ==
BASIC_ATLAS ) {
ats_basic_atlas_info( obu_xlayer_id, xAId )
} else if ( ats_atlas_segment_mode_idc[ obu_xlayer_id ][ xAId ] ==
SINGLE_ATLAS ) {
ats_num_atlas_segments_minus1[ obu_xlayer_id ][ xAId ] = 0
ats_nominal_width_minus1[ obu_xlayer_id ][ xAId ] uvlc()
ats_nominal_height_minus1[ obu_xlayer_id ][ xAId ] uvlc()
} else if ( ats_atlas_segment_mode_idc[ obu_xlayer_id ][ xAId ] ==
MULTISTREAM_ALPHA_ATLAS ) {
ats_multistream_atlas_info( obu_xlayer_id, xAId, 1 )
}
ats_label_segment_info( obu_xlayer_id , xAId )
}

5.9.1. Atlas label segment info syntax

ats_label_segment_info( xlayerId, xAId ) { Descriptor
ats_signaled_atlas_segment_ids_flag[ xlayerId ][ xAId ] f(1)
if ( ats_signaled_atlas_segment_ids_flag[ xlayerId ][ xAId ] ) {
for ( i = 0;i <= ats_num_atlas_segments_minus1[xlayerId][xAId];i++ ) {
ats_atlas_segment_id[ xlayerId ][ xAId ][ i ] f(8)
AtlasSegmentIDToIndex[ xlayerId ][ xAId ]
[ ats_atlas_segment_id[ xlayerId ][ xAId ][ i ] ] = i
AtlasSegmentIndexToID[ xlayerId ][ xAId ][ i ] =
ats_atlas_segment_id[ xlayerId ][ xAId ][ i ]
}
} else {
for ( i = 0;i <= ats_num_atlas_segments_minus1[xlayerId][xAId];i++ ) {
ats_atlas_segment_id[ xlayerId ][ xAId ][ i ] = i
AtlasSegmentIDToIndex[ xlayerId ][ xAId ][ i ] = i
AtlasSegmentIndexToID[ xlayerId ][ xAId ][ i ] = i
}
}
}

5.9.2. Atlas region info syntax

ats_region_info( xlayerId, xAId ) { Descriptor
ats_num_region_columns_minus1[ xlayerId ][ xAId ] uvlc()
ats_num_region_rows_minus1[ xlayerId ][ xAId ] uvlc()
ats_uniform_spacing_flag[ xlayerId ][ xAId ] f(1)
AtlasWidth[ xlayerId ][ xAId ] = 0
AtlasHeight[ xlayerId ][ xAId ] = 0
if ( !ats_uniform_spacing_flag[ xlayerId ][ xAId ] ) {
for ( i = 0; i < ats_num_region_columns_minus1[ xlayerId ][ xAId ] + 1;
i++ ) {
ats_column_width_minus1[ xlayerId ][ xAId ][ i ] uvlc()
AtlasWidth[ xlayerId ][ xAId ] +=
(ats_column_width_minus1[ xlayerId ][ xAId ][ i ] + 1)
}
for ( i = 0;i < ats_num_region_rows_minus1[xlayerId][xAId] + 1; i++ ) {
ats_row_height_minus1[ xlayerId ][ xAId ][ i ] uvlc()
AtlasHeight[ xlayerId ][ xAId ] +=
(ats_row_height_minus1[ xlayerId ][ xAId ][ i ] + 1)
}
} else {
ats_region_width_minus_1[ xlayerId ][ xAId ] uvlc()
ats_region_height_minus_1[ xlayerId ][ xAId ] uvlc()
AtlasWidth[ xlayerId ][ xAId ] =
( ats_region_width_minus_1[ xlayerId ][ xAId ][ i ] + 1 ) *
( ats_num_region_columns_minus1[ xlayerId ][ xAId ] + 1 )
AtlasHeight[ xlayerId ][ xAId ] =
( ats_region_height_minus_1[ xlayerId ][ xAId ][ i ] + 1 ) *
( ats_num_region_rows_minus1[ xlayerId ][ xAId ] + 1 )
}
NumRegionsInAtlas[ xlayerId ][ xAId ] =
( ats_num_region_columns_minus1[ xlayerId ][ xAId ] + 1) *
( ats_num_region_rows_minus1[ xlayerId ][ xAId ] + 1 )
}

5.9.3. Atlas region to segment mapping syntax

ats_region_to_segment_mapping( xlayerId, xAId ) { Descriptor
ats_single_region_per_atlas_segment_flag[ xlayerId ][ xAId ] f(1)
if ( !ats_single_region_per_atlas_segment_flag[ xlayerId ][ xAId ] ) {
maxSegments = MAX_NUM_ATLAS_SEGMENTS
ats_num_atlas_segments_minus1[ xlayerId ][ xAId ] uvlc()
for ( i = 0;i <= ats_num_atlas_segments_minus1[xlayerId][xAId];i++ ) {
ats_top_left_region_column[ xlayerId ][ xAId ][ i ] uvlc()
ats_top_left_region_row[ xlayerId ][ xAId ][ i ] uvlc()
ats_bottom_right_region_column_off[ xlayerId ][ xAId ][ i ] uvlc()
ats_bottom_right_region_row_off[ xlayerId ][ xAId ][ i ] uvlc()
}
} else {
ats_num_atlas_segments_minus1[ xlayerId ][ xAId ] =
NumRegionsInAtlas[ xlayerId ][ xAId ] - 1
}
}

5.9.4. Atlas multistream atlas info syntax

ats_multistream_atlas_info( xlayerId, xAId, hasAlpha ) { Descriptor
ats_atlas_width[ xlayerId ][ xAId ] uvlc()
ats_atlas_height[ xlayerId ][ xAId ] uvlc()
AtlasWidth[ xlayerId ][ xAId ] = ats_atlas_width[ xlayerId ][ xAId ]
AtlasHeight[ xlayerId ][ xAId ] = ats_atlas_height[ xlayerId ][ xAId ]
ats_num_atlas_segments_minus1[ xlayerId ][ xAId ] uvlc()
if ( hasAlpha ) {
ats_alpha_segments_present_flag[ xlayerId ][ xAId ] f(1)
} else {
ats_alpha_segments_present_flag[ xlayerId ][ xAId ] = 0
}
ats_background_info_present_flag[ xlayerId ][ xAId ] f(1)
if ( ats_background_info_present_flag[ xlayerId ][ xAId ] ) {
ats_background_red_value[ xlayerId ][ xAId ] f(8)
ats_background_green_value[ xlayerId ][ xAId ] f(8)
ats_background_blue_value[ xlayerId ][ xAId ] f(8)
}
for ( i = 0; i <= ats_num_atlas_segments_minus1[ xlayerId ][ xAId ]; i++ ) {
ats_input_stream_id[ xlayerId ][ xAId ][ i ] f(5)
ats_segment_top_left_pos_x[ xlayerId ][ xAId ][ i ] uvlc()
ats_segment_top_left_pos_y[ xlayerId ][ xAId ][ i ] uvlc()
ats_segment_width[ xlayerId ][ xAId ][ i ] uvlc()
ats_segment_height[ xlayerId ][ xAId ][ i ] uvlc()
if ( ats_alpha_segments_present_flag[ xlayerId ][ xAId ] &&
i != ats_num_atlas_segments_minus1[ xlayerId ][ xAId ] ) {
ats_alpha_segment_flag[ xlayerId ][ xAId ][ i ] f(1)
} else {
ats_alpha_segment_flag[ xlayerId ][ xAId ][ i ] = 0
}
}
}

5.9.5. Atlas basic atlas info syntax

ats_basic_atlas_info( xlayerId, xAId ) { Descriptor
ats_stream_id_present[ xlayerId ][ xAId ] f(1)
ats_atlas_width[ xlayerId ][ xAId ] uvlc()
ats_atlas_height[ xlayerId ][ xAId ] uvlc()
ats_num_atlas_segments_minus1[ xlayerId ][ xAId ] uvlc()
AtlasWidth[ xlayerId ][ xAId ] = ats_atlas_width[ xlayerId ][ xAId ]
AtlasHeight[ xlayerId ][ xAId ] = ats_atlas_height[ xlayerId ][ xAId ]
for ( i = 0; i <= ats_num_atlas_segments_minus1[ xlayerId ][ xAId ]; i++ ) {
if (ats_stream_id_present[ xlayerId ][ xAId ]) {
ats_input_stream_id[ xlayerId ][ xAId ][ i ] f(5)
}
ats_segment_top_left_pos_x[ xlayerId ][ xAId ][ i ] uvlc()
ats_segment_top_left_pos_y[ xlayerId ][ xAId ][ i ] uvlc()
ats_segment_width[ xlayerId ][ xAId ][ i ] uvlc()
ats_segment_height[ xlayerId ][ xAId ][ i ] uvlc()
}
}

5.10. Operating point set OBU syntax

operating_point_set_obu( ) { Descriptor
ops_reset_flag[ obu_xlayer_id ] f(1)
ops_id[ obu_xlayer_id ] f(4)
opsID = ops_id[ obu_xlayer_id ]
ops_cnt[ obu_xlayer_id ][ opsID ] f(3)
if ( ops_cnt[ obu_xlayer_id ][ opsID ] > 0 ) {
ops_priority[ obu_xlayer_id ][ opsID ] f(4)
ops_intent[ obu_xlayer_id ][ opsID ] f(7)
ops_intent_present_flag[ obu_xlayer_id ][ opsID ] f(1)
ops_ptl_present_flag[ obu_xlayer_id ][ opsID ] f(1)
ops_color_info_present_flag[ obu_xlayer_id ][ opsID ] f(1)
ops_decoder_model_info_present_flag[ obu_xlayer_id ][ opsID ] f(1)
if ( obu_xlayer_id == GLOBAL_XLAYER_ID ) {
ops_mlayer_info_idc[ opsID ] f(2)
ops_reserved_7bits f(7)
} else {
ops_reserved_9bits f(9)
}
for( i = 0; i < ops_cnt[ obu_xlayer_id ][ opsID ]; i++ ) {
operating_point_payload( obu_xlayer_id, opsID, i )
}
}
}

5.11. Operating point payload syntax

operating_point_payload( xId, opsID, i ) { Descriptor
ops_data_size[ xId ][ opsID ][ i ] leb128()
startPos = get_position( )
if ( ops_intent_present_flag[ xId ][ opsID ] ) {
ops_op_intent[ xId ][ opsID ][ i ] f(7)
}
if (ops_ptl_present_flag[ xId ][ opsID ] ) {
if (( xId == GLOBAL_XLAYER_ID )) {
ops_aggregate_profile_tier_level_info( opsID, i )
}
else {
ops_seq_profile_tier_level_info( xId, opsID, i, xId )
}
}
if ( ops_color_info_present_flag[ xId ][ opsID ] ) {
ops_color_info( opsID, i )
}
if ( ops_decoder_model_info_present_flag[ xId ][ opsID ] ) {
ops_decoder_model_info( opsID, i )
}
ops_initial_display_delay_present_flag[ xId ][ opsID ][ i ] f(1)
if ( ops_initial_display_delay_present_flag[ xId ][ opsID ][ i ] ) {
ops_initial_display_delay_minus_1[ xId ][ opsID ][ i ] f(4)
}
if ( xId == GLOBAL_XLAYER_ID ) {
ops_xlayer_map[ opsID ][ i ] f(31)
k = 0
for ( j = 0; j < 31; j++ ) {
if ( ops_xlayer_map[ opsID ][ i ] & (1 << j) ) {
OpsxLayerId[ opsID ][ i ][ k ] = j
k++
if (ops_ptl_present_flag[ xId ][ opsID ] ) {
ops_seq_profile_tier_level_info( xId, opsID, i, j )
}
idc = ops_mlayer_info_idc[ opsID ]
if ( idc == 1 ) {
ops_mlayer_info( xId, opsID, i, j )
} else if ( idc == 2 ) {
ops_mlayer_explicit_info_flag[ opsID ][ i ][ j ] f(1)
if ( ops_mlayer_explicit_info_flag[ opsID ][ i ][ j ] ) {
ops_mlayer_info( xId, opsID, i, j )
}
else {
ops_embedded_ops_id[ opsID ][ i ][ j ] f(4)
ops_embedded_op_index[ opsID ][ i ][ j ] f(3)
}
}
}
}
XCount[ xId ][ opsID ][ i ] = k
} else {
XCount[ xId ][ opsID ][ i ] = 1
OpsxLayerId[ xId ][ opsID ][ i ][ 0 ] = xId
ops_mlayer_info( xId, opsID, i, xId )
}
byte_alignment()
opsBytes = (get_position() - startPos) >> 3
}

5.11.1. Operating point set aggregate profile tier level information syntax

ops_aggregate_profile_tier_level_info( opsID, i ) { Descriptor
ops_config_idc[ opsID ][ i ] f(6)
ops_aggregate_level_idx[ opsID ][ i ] f(5)
ops_max_tier_flag[ opsID ][ i ] f(1)
ops_max_interop[ opsID ][ i ] f(4)
}

5.11.2. Operating point set sequence profile tier level information syntax

ops_seq_profile_tier_level_info( xId, opsID, i, j ) { Descriptor
ops_seq_profile_idc[ xId ][ opsID ][ i ][ j ] f(5)
ops_level_idx[ xId ][ opsID ][ i ][ j ] f(5)
ops_tier_flag[ xId ][ opsID ][ i ][ j ] f(1)
ops_mlayer_count[ xId ][ opsID ][ i ][ j ] f(3)
ops_reserved_2bits f(2)
}

5.11.3. Operating point set decoder model info syntax

ops_decoder_model_info( opsID, i ) { Descriptor
ops_decoder_buffer_delay[ obu_xlayer_id ][ opsID ][ i ] uvlc()
ops_encoder_buffer_delay[ obu_xlayer_id ][ opsID ][ i ] uvlc()
ops_low_delay_mode_flag[ obu_xlayer_id ][ opsID ][ i ] f(1)
}

5.11.4. Operating point set color info syntax

ops_color_info( opsID, i ) { Descriptor
ops_color_description_idc[ obu_xlayer_id ][ opsID ][ i ] rg(2)
if ( ops_color_description_idc[ obu_xlayer_id ][ opsID ][ i ] == 0 ) {
ops_color_primaries[ obu_xlayer_id ][ opsID ][ i ] f(8)
ops_transfer_characteristics[ obu_xlayer_id ][ opsID ][ i ] f(8)
ops_matrix_coefficients[ obu_xlayer_id ][ opsID ][ i ] f(8)
}
ops_full_range_flag[ obu_xlayer_id ][ opsID ][ i ] f(1)
}

5.11.5. Operating point set mlayer info syntax

ops_mlayer_info( obuXLId, opsID, opIndex, xLId ) { Descriptor
ops_mlayer_map[ obuXLId ][ opsID ][ opIndex ][ xLId ] f(8)
OPMLayerCount[ obuXLId ][ opsID ][ opIndex ][ xLId ] = 0
mCount = 0
for ( j = 0; j < 8; j++ ) {
if (ops_mlayer_map[ obuXLId ][ opsID ][ opIndex ][ xLId ] & (1 << j)) {
OpsMlayerID[ obuXLId ][ opsID ][ mCount ][ xLId ]= j
ops_tlayer_map[ obuXLId ][ opsID ][ opIndex ][ xLId ][ j ] f(4)
tCount = 0
for ( k = 0; k < 4; k++ ) {
if ( ops_tlayer_map[ obuXLId ][ opsID ]
[ opIndex ][ xLId ][ j ] & (1 << k) ) {
OpsTlayerID[ obuXLId ][ opsID ][ opIndex ]
[ xLId ][ tCount ] = k
tCount++
}
}
OPTLayerCount[ obuXLId ][ opsID ][ opIndex ][ xLId ][ j ] = tCount
mCount++
}
}
OPMLayerCount[ obuXLId ][ opsID ][ opIndex ][ xLId ] = mCount
}

5.12. Buffer removal timing OBU syntax

buffer_removal_timing_obu() { Descriptor
br_ops_id f(4)
br_ops_cnt f(3)
for ( i = 0; i < br_ops_cnt; i++ ) {
br_decoder_model_present_op_flag f(1)
if ( br_decoder_model_present_op_flag ) {
br_buffer_removal_time[ i ] uvlc()
}
}
}

5.13. Quantizer Matrix OBU syntax

quantizer_matrix_obu( ) { Descriptor
qm_bit_map f(15)
qm_chroma_info_present_flag f(1)
numPlanes = qm_chroma_info_present_flag ? 3 : 1
if ( qm_bit_map == 0 ){
for ( level = 0; level < NUM_CUSTOM_QMS; level++ ) {
QmProtected[ level ] = 1
QmNumPlanes[ level ] = numPlanes
QmDataPresent[ level ] = 0
}
} else {
for ( level = 0; level < 15; level++ ) {
if ( qm_bit_map & (1 << level) ) {
QmSeen[ level ] = 1
QmProtected[ level ] = 1
QmNumPlanes[ level ] = numPlanes
QmMLayerId[ level ] = obu_mlayer_id
QmTLayerId[ level ] = obu_tlayer_id
QmDataPresent[ level ] = 1
qm_is_default_flag f(1)
if ( qm_is_default_flag ) {
QmDataPresent[ level ] = 0
} else {
for ( t = 0; t < 3; t++ ){
for ( plane = 0; plane < numPlanes; plane++ ) {
user_defined_qm( level, t, plane )
}
}
}
}
}
}
}

5.14. Film grain OBU syntax

film_grain_obu( ) { Descriptor
fgm_bit_map f(8)
fgm_chroma_idc uvlc()
if ( fgm_chroma_idc == CHROMA_FORMAT_420 ) {
subX = 1
subY = 1
} else if ( fgm_chroma_idc == CHROMA_FORMAT_444 ) {
subX = 0
subY = 0
} else if ( fgm_chroma_idc == CHROMA_FORMAT_422 ) {
subX = 1
subY = 0
} else if ( fgm_chroma_idc == CHROMA_FORMAT_400 ) {
subX = 1
subY = 1
}
monochrome = fgm_chroma_idc == CHROMA_FORMAT_400
for ( i = 0; i < MAX_FILM_GRAIN; i++ ) {
if ( fgm_bit_map & (1 << i) ) {
FilmGrainPresent[ i ] = 1
film_grain_model( monochrome, subX, subY)
save_grain_model( i )
FgmTLayerId[ i ] = obu_tlayer_id
FgmMLayerId[ i ] = obu_mlayer_id
FgmChromaIdc[ i ] = fgm_chroma_idc
}
}
}

5.15. Content interpretation OBU syntax

content_interpretation_obu() { Descriptor
scan_type_idc f(2)
color_description_present_flag f(1)
chroma_sample_position_present_flag f(1)
aspect_ratio_info_present_flag f(1)
timing_info_present_flag f(1)
reserved_2bit f(2)
color_primaries = CP_UNSPECIFIED
transfer_characteristics = TC_UNSPECIFIED
matrix_coefficients = MC_UNSPECIFIED
if ( color_description_present_flag ) {
color_description_idc rg(2)
if ( color_description_idc == 0 ) {
color_primaries f(8)
transfer_characteristics f(8)
matrix_coefficients f(8)
}
full_range_flag f(1)
}
if ( chroma_sample_position_present_flag ) {
chroma_sample_position_top uvlc()
if ( scan_type_idc != 1 ) {
chroma_sample_position_bottom uvlc()
} else {
chroma_sample_position_bottom = chroma_sample_position_top
}
} else {
chroma_sample_position_top = CSP_UNSPECIFIED;
chroma_sample_position_bottom = CSP_UNSPECIFIED;
}
if ( aspect_ratio_info_present_flag ) {
aspect_ratio_idc f(8)
if ( aspect_ratio_idc == 255 ) {
sar_width uvlc()
sar_height uvlc()
} else {
sar_width = Aspect_Ratio_Width[ aspect_ratio_idc ]
sar_height = Aspect_Ratio_Height[ aspect_ratio_idc ]
}
}
if ( timing_info_present_flag ) {
timing_info()
}
}

where the tables Aspect_Ratio_Width and Aspect_Ratio_Height are specified as:

Aspect_Ratio_Width[ 17 ] = {  0,  1, 12, 10, 16,  40, 24, 20,                              32, 80, 18, 15, 64, 160,  4,  3, 2 }Aspect_Ratio_Height[ 17 ] = {  0,  1, 11, 11, 11, 33, 11, 11,                               11, 33, 11, 11, 33, 99,  3,  2, 1 }

5.16. Padding OBU syntax

padding_obu( ) { Descriptor
for ( i = 0; i < obu_padding_length; i++ ) {
obu_padding_byte f(8)
}
}

Note: obu_padding_length is not coded in the bitstream but can be computed based on the OBU size minus the number of trailing bytes. In practice, though, since this is padding data meant to be skipped, decoders do not need to determine either that length nor the number of trailing bytes. They can ignore the entire OBU. The last byte of the valid content of the payload data for this OBU type is considered to be the last byte that is not equal to zero. This rule is to prevent the dropping of valid bytes by systems that interpret trailing zero bytes as a continuation of the trailing bits in an OBU. This implies that when any payload data is present for this OBU type, at least one byte of the payload data (including the trailing bit) shall not be equal to 0.

Note: A padding OBU with an obuPayloadSize of 0 is legal. This means the OBU has obu_padding_length of 0 and will not contain any trailing bits. A padding OBU with an obuPayloadSize of 1 is legal. This means the OBU has obu_padding_length of 0 and does contain trailing bits. This is allowed so that any OBU can be converted into a padding OBU in-place.

5.17. Metadata OBU syntax

This specification defines two distinct OBU types for carrying metadata:

  • OBU_METADATA_SHORT: using metadata short OBU syntax, and

  • OBU_METADATA_GROUP: using metadata group OBU syntax.

Both OBU types use the same metadata_unit() syntax element to carry the actual metadata payload. The OBU_METADATA_SHORT type provides a compact header structure, while OBU_METADATA_GROUP provides extended capabilities including the ability to carry multiple metadata units within a single OBU with additional signaling for application-specific handling, layer targeting, and priority.

5.17.1. Metadata unit syntax

metadata_unit( ) { Descriptor
if ( metadata_type == METADATA_TYPE_ITUT_T35 ) {
metadata_itut_t35( )
} else if ( metadata_type == METADATA_TYPE_HDR_CLL ) {
metadata_hdr_cll( )
} else if ( metadata_type == METADATA_TYPE_HDR_MDCV ) {
metadata_hdr_mdcv( )
} else if ( metadata_type == METADATA_TYPE_TIMECODE ) {
metadata_timecode( )
} else if ( metadata_type == METADATA_TYPE_BANDING_HINTS ) {
metadata_banding_hints( )
} else if ( metadata_type == METADATA_TYPE_ICC_PROFILE ) {
metadata_icc_profile( )
} else if ( metadata_type == METADATA_TYPE_SCAN_TYPE ) {
metadata_scan_type( )
} else if ( metadata_type == METADATA_TYPE_TEMPORAL_POINT_INFO ) {
metadata_temporal_point_info( )
}
byte_alignment( )
}

Note: The exact syntax of metadata_unit is not defined in this specification when metadata_type is equal to a value reserved for future use or a user private value. Decoders should ignore the metadata_unit() if they do not understand the metadata_type. For OBU_METADATA_SHORT, this means ignoring the entire OBU. For OBU_METADATA_GROUP, decoders should skip only the unrecognized metadata_unit() and continue processing other metadata units within the same OBU.

5.17.2. Short metadata OBU syntax

metadata_short_obu( ) { Descriptor
metadata_is_suffix f(1)
metadata_necessity_idc = 0
metadata_application_id = 0
muh_layer_idc f(3)
muh_cancel_flag f(1)
muh_persistence_idc f(3)
muh_priority = 0
metadata_type leb128()
if ( muh_cancel_flag ) {
return
}
metadata_unit( )
}

5.17.3. Metadata group OBU syntax

metadata_group_obu() { Descriptor
metadata_is_suffix f(1)
metadata_necessity_idc f(2)
metadata_application_id f(5)
metadata_unit_cnt_minus1 leb128()
for ( i = 0; i <= metadata_unit_cnt_minus1; i++ ) {
metadata_type leb128()
muh_header_size f(7)
muh_cancel_flag f(1)
headerRemainingBytes = muh_header_size
if ( !muh_cancel_flag ) {
muh_payload_size leb128()
headerRemainingBytes -= Leb128Bytes
muh_layer_idc f(3)
muh_persistence_idc f(3)
muh_priority f(8)
muh_reserved_zero_2bits f(2)
headerRemainingBytes -= 2
if ( muh_layer_idc == LAYER_VALUES ) {
if ( obu_xlayer_id == GLOBAL_XLAYER_ID ) {
muh_xlayer_map f(32)
headerRemainingBytes -= 4
for ( n = 0; n < 31; n++ ) {
if ( muh_xlayer_map & (0x1 << n) ) {
muh_mlayer_map f(8)
headerRemainingBytes -= 1
}
}
} else {
muh_mlayer_map f(8)
headerRemainingBytes -= 1
}
}
}
for ( j = 0; j < headerRemainingBytes; j++ ) {
muh_header_extension_byte f(8)
}
if ( !muh_cancel_flag ) {
metadata_unit( )
}
}
}

5.17.4. Metadata ITUT T35 syntax

metadata_itut_t35( ) { Descriptor
itu_t_t35_country_code f(8)
if ( itu_t_t35_country_code == 0xFF ) {
itu_t_t35_country_code_extension_byte f(8)
}
itu_t_t35_payload_bytes
}

Note: The exact syntax of itu_t_t35_payload_bytes is not defined in this specification. External specifications can define the syntax. Decoders should ignore the entire OBU if they do not understand it. The last byte of the valid content of the data is considered to be the last byte that is not equal to zero. This rule is to prevent the dropping of valid bytes by systems that interpret trailing zero bytes as a padding continuation of the trailing bits in an OBU. This implies that when any payload data is present for this OBU type, at least one byte of the payload data (including the trailing bit) shall not be equal to 0.

5.17.5. Metadata high dynamic range content light level syntax

metadata_hdr_cll( ) { Descriptor
max_cll f(16)
max_fall f(16)
}

5.17.6. Metadata high dynamic range mastering display color volume syntax

metadata_hdr_mdcv( ) { Descriptor
for ( i = 0; i < 3; i++ ) {
primary_chromaticity_x[ i ] f(16)
primary_chromaticity_y[ i ] f(16)
}
white_point_chromaticity_x f(16)
white_point_chromaticity_y f(16)
luminance_max f(32)
luminance_min f(32)
}

5.17.7. Metadata timecode syntax

metadata_timecode( ) { Descriptor
counting_type f(5)
full_timestamp_flag f(1)
discontinuity_flag f(1)
cnt_dropped_flag f(1)
n_frames f(9)
if ( full_timestamp_flag ) {
seconds_value f(6)
minutes_value f(6)
hours_value f(5)
} else {
seconds_flag f(1)
if ( seconds_flag ) {
seconds_value f(6)
minutes_flag f(1)
if ( minutes_flag ) {
minutes_value f(6)
hours_flag f(1)
if ( hours_flag ) {
hours_value f(5)
}
}
}
}
time_offset_length f(5)
if ( time_offset_length > 0 ) {
time_offset_value f(time_offset_length)
}
}

5.17.8. Metadata banding hints syntax

metadata_banding_hints( ) { Descriptor
coding_banding_present_flag f(1)
source_banding_present_flag f(1)
if ( coding_banding_present_flag ) {
banding_hints_flag f(1)
if ( banding_hints_flag ) {
three_color_components f(1)
numComponents = three_color_components ? 3 : 1
for ( plane = 0; plane < numComponents; plane++ ) {
banding_in_component_present_flag f(1)
if ( banding_in_component_present_flag ) {
max_band_width_minus4 f(6)
max_band_step_minus1 f(4)
}
}
band_units_information_present_flag f(1)
if ( band_units_information_present_flag ) {
num_band_units_rows_minus_1 f(5)
num_band_units_cols_minus_1 f(5)
varying_size_band_units_flag f(1)
if ( varying_size_band_units_flag ) {
band_block_in_luma_samples f(3)
for ( r = 0; r <= num_band_units_rows_minus_1; r++ ) {
vert_size_in_band_blocks_minus1 f(5)
}
for ( c = 0; c <= num_band_units_cols_minus_1; c++ ) {
horz_size_in_band_blocks_minus1 f(5)
}
}
for ( r = 0; r <= num_band_units_rows_minus_1; r++ ) {
for ( c = 0; c <= num_band_units_cols_minus_1; c++ ) {
banding_in_band_unit_present_flag f(1)
}
}
}
}
}
}

5.17.9. Metadata ICC profile syntax

metadata_icc_profile( ) { Descriptor
icc_profile_data_payload_bytes
}

5.17.10. Metadata scan type syntax

metadata_scan_type( ) { Descriptor
mps_pic_struct_type f(5)
mps_source_scan_type_idc f(2)
mps_duplicate_flag f(1)
}

5.17.11. Metadata temporal point info syntax

metadata_temporal_point_info( ) { Descriptor
frame_presentation_time_length_minus_1 f(5)
n = frame_presentation_time_length_minus_1 + 1
frame_presentation_time f(n)
}

5.18. Frame header syntax

5.18.1. General frame header syntax

frame_header( isFirst ) { Descriptor
if ( isFirst ) {
SeenFrameHeader = 1
keyframe = obu_type == OBU_CLOSED_LOOP_KEY ||
obu_type == OBU_OPEN_LOOP_KEY
if ( !keyframe ) {
for ( i = 0; i < NUM_CUSTOM_QMS; i++ ) {
if ( QmSeen[ i ] ) {
QmProtected[ i ] = 0
}
}
}
if ( keyframe && FirstLayer ) {
for ( i = 0; i < NUM_CUSTOM_QMS; i++ ) {
if ( !QmProtected[ i ] ) {
QmDataPresent[ i ] = 0
QmNumPlanes[ i ] = NumPlanes
}
}
}
for ( i = 0; i < NUM_CUSTOM_QMS; i++ ) {
QmSeen[ i ] = 0
}
if ( keyframe && TriggerFlushIfKey ) {
flush_implicit_output_frames()
}
isRegular = ( obu_type == OBU_OPEN_LOOP_KEY ||
obu_type == OBU_REGULAR_TILE_GROUP ||
obu_type == OBU_REGULAR_TIP ||
obu_type == OBU_REGULAR_SEF ||
obu_type == OBU_SWITCH ||
obu_type == OBU_RAS_FRAME ||
obu_type == OBU_BRIDGE_FRAME )
if ( OlkEncountered && isRegular ) {
OlkEncountered = 0
allowedFrames = 0
for ( i = 0; i < MAX_NUM_MLAYERS; i++ ) {
allowedFrames |= OlkRefresh[ i ]
}
for ( i = 0; i < NUM_REF_FRAMES; i++ ) {
if ( ( allowedFrames & (1 << i) ) == 0 )
RefValid[ i ] = 0
}
}
uncompressed_header( )
if ( IsBridge ) {
NumTiles = TileCols * TileRows
tg_start = 0
tg_end = NumTiles - 1
tile_group_payload( 0 )
CountPictureForLevelConstraint = 1
} else if ( show_existing_frame ||
TipFrameMode == TIP_FRAME_AS_OUTPUT ||
bru_inactive ) {
decode_frame_wrapup( )
SeenFrameHeader = 0
CountPictureForLevelConstraint = 0
} else {
TileNum = 0
SeenFrameHeader = 1
CountPictureForLevelConstraint = 1
}
} else {
frame_header_copy()
}
}

5.18.2. Uncompressed header syntax

uncompressed_header( ) { Descriptor
IsBridge = obu_type == OBU_BRIDGE_FRAME
if ( IsBridge ) {
cur_mfh_id = 0
} else {
cur_mfh_id uvlc()
}
if ( cur_mfh_id == 0 ) {
seq_header_id_in_frame_header uvlc()
load_sequence_header( seq_header_id_in_frame_header )
mfh_loop_filter_update[ cur_mfh_id ] = 0
} else {
load_sequence_header( MfhSeqHeaderId[ cur_mfh_id ] )
}
if ( obu_type == OBU_CLOSED_LOOP_KEY || obu_type == OBU_OPEN_LOOP_KEY) {
if ( seq_lcr_id != 0 ) {
activate_layer_configuration_record( seq_lcr_id )
}
}
if ( cur_mfh_id == 0 || !mfh_frame_size_present_flag[ cur_mfh_id ] ) {
mfh_frame_width_minus_1[ cur_mfh_id ] = max_frame_width_minus_1
mfh_frame_height_minus_1[ cur_mfh_id ] = max_frame_height_minus_1
}
mfh_tile_info_present_flag[ 0 ] = seq_tile_info_present_flag
if ( mfh_tile_info_present_flag[ 0 ] ) {
mfh_allow_tile_info_change[ 0 ] = allow_tile_info_change
for ( i = 0; i < SeqTileRows; i++ ) {
MfhSbRowStarts[ 0 ][ i ] = SeqSbRowStarts[ i ]
}
for ( i = 0; i < SeqTileCols; i++ ) {
MfhSbColStarts[ 0 ][ i ] = SeqSbColStarts[ i ]
}
MfhSbRows[ 0 ] = SeqSbRows
MfhTileRows[ 0 ] = SeqTileRows
MfhTileRowsLog2[ 0 ] = SeqTileRowsLog2
MfhSbCols[ 0 ] = SeqSbCols
MfhTileCols[ 0 ] = SeqTileCols
MfhTileColsLog2[ 0 ] = SeqTileColsLog2
MfhUniform[ 0 ] = SeqUniformTileSpacingFlag
}
if ( IsBridge ) {
bridge_frame_ref_idx f(CeilLog2(NumRefFrames))
}
allFrames = (1 << NumRefFrames) - 1
use_bru = 0
bru_inactive = 0
if ( single_picture_header_flag ) {
show_existing_frame = 0
FrameType = KEY_FRAME
FrameIsIntra = 1
immediate_output_frame = 1
implicit_output_frame = 0
} else {
show_existing_frame = is_sef()
if ( show_existing_frame == 1 ) {
frame_to_show_map_idx f(CeilLog2(NumRefFrames))
derive_sef_order_hint f(1)
if (derive_sef_order_hint == 0) {
sef_order_hint f(OrderHintBits)
OrderHintLsbs = sef_order_hint
OrderHint = get_disp_order_hint()
}
refresh_frame_flags = 0
FrameType = RefFrameType[ frame_to_show_map_idx ]
immediate_output_frame = 1
film_grain_config()
if ( derive_sef_order_hint ) {
save_grain_params( frame_to_show_map_idx )
}
TipFrameMode = TIP_FRAME_DISABLED
return
}
if ( IsBridge ) {
FrameType = INTER_FRAME
} else if ( obu_type == OBU_SWITCH || obu_type == OBU_RAS_FRAME ) {
FrameType = SWITCH_FRAME
} else if ( is_tip_frame() ) {
FrameType = INTER_FRAME
} else if ( obu_type == OBU_CLOSED_LOOP_KEY ||
obu_type == OBU_OPEN_LOOP_KEY ) {
FrameType = KEY_FRAME
} else {
frame_is_inter f(1)
FrameType = frame_is_inter ? INTER_FRAME : INTRA_ONLY_FRAME
}
long_term_id = -1
if ( FrameType == KEY_FRAME ) {
long_term_id f(long_term_frame_id_bits)
}
if ( obu_type == OBU_RAS_FRAME ) {
num_key_ref_frames f(3)
for ( i = 0; i < num_key_ref_frames; i++ ) {
ref_long_term_id[ i ] f(long_term_frame_id_bits)
}
}
if ( FrameType == SWITCH_FRAME && restricted_prediction_switch ) {
for (i = 0; i < NUM_REF_FRAMES; i++) {
RefOrderHint[ i ] = RESTRICTED_OH
}
}
FrameIsIntra = (FrameType == INTRA_ONLY_FRAME ||
FrameType == KEY_FRAME)
if ( IsBridge || obu_type == OBU_OPEN_LOOP_KEY ) {
immediate_output_frame = 0
} else {
immediate_output_frame f(1)
}
if ( IsBridge ) {
implicit_output_frame = 0
} else if ( immediate_output_frame ) {
implicit_output_frame = FrameType != KEY_FRAME
} else {
implicit_output_frame f(1)
}
}
if ( use_256x256_superblock ) {
SbSize = FrameIsIntra ? BLOCK_128X128 : BLOCK_256X256
} else if ( use_128x128_superblock ) {
SbSize = BLOCK_128X128
} else {
SbSize = BLOCK_64X64
}
if ( FrameType == KEY_FRAME && immediate_output_frame ) {
for ( i = 0; i < REFS_PER_FRAME; i++ ) {
OrderHints[ i ] = 0
}
}
disable_cross_frame_cdf_init = 0
if ( IsBridge ) {
primary_ref_frame = PRIMARY_REF_NONE
OrderHintLsbs = RefOrderHintLsbs[ bridge_frame_ref_idx ]
OrderHint = RefOrderHint[ bridge_frame_ref_idx ]
} else {
if ( FrameType == SWITCH_FRAME ) {
frame_size_override_flag = 1
} else if ( single_picture_header_flag ) {
frame_size_override_flag = 0
} else {
frame_size_override_flag f(1)
}
order_hint f(OrderHintBits)
OrderHintLsbs = order_hint
OrderHint = get_disp_order_hint()
if ( FrameIsIntra || FrameType == SWITCH_FRAME ) {
primary_ref_frame = PRIMARY_REF_NONE
} else {
signal_primary_ref_frame f(1)
if ( !is_tip_frame( ) ) {
disable_cross_frame_cdf_init f(1)
}
if ( signal_primary_ref_frame ) {
primary_ref_frame f(3)
} else {
primary_ref_frame = PRIMARY_REF_CHOOSE
}
}
}
FrameMvPrecision = MV_PRECISION_ONE_PEL
MvPrecision = FrameMvPrecision
allow_high_precision_mv = 0
use_ref_frame_mvs = 0
allow_intrabc = 0
allow_global_intrabc = 0
allow_local_intrabc = 0
allow_high_precision_mv = 0
allow_lf_sub_pu = 0
if ( IsBridge ) {
bridge_frame_overwrite_flag f(1)
}
if ( FrameType == KEY_FRAME ) {
if ( obu_type == OBU_CLOSED_LOOP_KEY && max_mlayer_id == 0 ) {
refresh_frame_flags = allFrames
} else if ( enable_short_refresh_frame_flags ) {
frame_to_refresh f(CeilLog2(NumRefFrames))
refresh_frame_flags = 1 << frame_to_refresh
} else {
refresh_frame_flags f(NumRefFrames)
}
if ( obu_type == OBU_CLOSED_LOOP_KEY && FirstLayer ) {
for ( i = 0; i < NumRefFrames; i++ ) {
RefValid[i] = 0
}
}
if ( obu_type == OBU_CLOSED_LOOP_KEY ) {
OlkEncountered = 0
for( i = 0; i < MAX_NUM_MLAYERS; i++ ) {
OlkRefresh[ i ] = 0
}
}
if ( obu_type == OBU_OPEN_LOOP_KEY ) {
OlkEncountered = 1
OlkRefresh[ obu_mlayer_id ] = refresh_frame_flags
}
} else if ( IsBridge && !bridge_frame_overwrite_flag ) {
refresh_frame_flags = 1 << bridge_frame_ref_idx
} else if ( obu_type == OBU_RAS_FRAME ) {
refresh_frame_flags = 0
for ( i = 0; i < NumRefFrames; i++ ) {
if ( !RefValid[i] || !long_term_id_in_use( RefLongTermId[i] ) ) {
refresh_frame_flags |= (1 << i)
}
}
} else if ( FrameType == SWITCH_FRAME ) {
refresh_frame_flags f(NumRefFrames)
} else if ( enable_short_refresh_frame_flags &&
FrameType != SWITCH_FRAME &&
FrameType != KEY_FRAME ) {
has_refresh_frame_flags f(1)
if ( has_refresh_frame_flags ) {
frame_to_refresh f(CeilLog2(NumRefFrames))
refresh_frame_flags = 1 << frame_to_refresh
} else {
refresh_frame_flags = 0
}
} else {
refresh_frame_flags f(NumRefFrames)
}
if ( FrameIsIntra ) {
frame_size( )
screen_content_params( )
intrabc_params( )
NumTotalRefs = 0
TipFrameMode = TIP_FRAME_DISABLED
} else {
if ( FrameType == SWITCH_FRAME ) {
explicitRefFrameMap = 1
} else if ( IsBridge ) {
explicitRefFrameMap = 0
} else if ( explicit_ref_frame_map ) {
frame_explicit_ref_frame_map f(1)
explicitRefFrameMap = frame_explicit_ref_frame_map
} else {
explicitRefFrameMap = 0
}
if ( explicitRefFrameMap ) {
num_total_refs f(3)
NumTotalRefs = num_total_refs
} else {
get_ref_frames( 0 )
}
for ( i = 0; i < NumTotalRefs; i++ ) {
if ( explicitRefFrameMap ) {
ref_frame_idx[ i ] f(CeilLog2(NumRefFrames))
}
}
if ( IsBridge ) {
frame_size_with_bridge( )
} else if ( frame_size_override_flag && FrameType != SWITCH_FRAME ) {
frame_size_with_refs( )
} else {
frame_size( )
}
if ( !explicitRefFrameMap ) {
get_ref_frames( 1 )
}
NumSameRefCompound = Min(num_same_ref_compound, NumTotalRefs)
if ( enable_bru && FrameType == INTER_FRAME && !is_tip_frame( ) &&
!IsBridge ) {
use_bru f(1)
if ( use_bru ) {
bru_ref f(CeilLog2(NumTotalRefs))
bru_inactive f(1)
}
}
if ( explicitRefFrameMap ) {
for ( i = 0; i < NumTotalRefs; i++ ) {
ScoresDistance[ i ] = get_relative_dist( OrderHint,
RefOrderHint[ ref_frame_idx[ i ] ] )
}
}
get_past_future_cur_ref_lists()
if ( FrameType == SWITCH_FRAME || !enable_ref_frame_mvs ||
IsBridge ) {
use_ref_frame_mvs = 0
} else {
use_ref_frame_mvs f(1)
}
if ( use_ref_frame_mvs && NumTotalRefs > 1 && SbSize != BLOCK_64X64 ) {
tmvp_sample_step_minus1 f(1)
ProjStep = tmvp_sample_step_minus1 + 1
} else {
ProjStep = 1
}
for ( i = 0; i < NumTotalRefs; i++ ) {
FrameDistance[ i ] = get_relative_dist( OrderHint,
RefOrderHint[ ref_frame_idx[ i ] ] )
if ( RefOrderHint[ ref_frame_idx[ i ] ] == RESTRICTED_OH ) {
FrameDistance[ i ] = -FrameDistance[ i ]
}
}
for ( i = 0; i < NumTotalRefs; i++ ) {
refFrame = i
hint = RefOrderHint[ ref_frame_idx[ i ] ]
OrderHints[ refFrame ] = hint
}
if ( enable_tip &&
(use_ref_frame_mvs && NumTotalRefs >= 2) &&
!bru_inactive ) {
TipInterpFilter = EIGHTTAP_SHARP
TipGlobalMv[ 0 ] = 0
TipGlobalMv[ 1 ] = 0
if ( EnableTipOutput && is_tip_frame( ) ) {
TipFrameMode = TIP_FRAME_AS_OUTPUT
} else {
tip_frame_mode f(1)
TipFrameMode = tip_frame_mode
}
frame_opfl_refine_type()
if ( TipFrameMode != TIP_FRAME_DISABLED &&
enable_tip_hole_fill ) {
allow_tip_hole_fill f(1)
} else {
allow_tip_hole_fill = 0
}
usesEqualWeight = enable_tip_refinemv &&
NumFutureRefs > 0 && NumPastRefs > 0 &&
( opfl_refine_type != REFINE_NONE || enable_refinemv )
if ( TipFrameMode == TIP_FRAME_DISABLED || usesEqualWeight ) {
tip_global_wtd_index = 0
} else {
tip_global_wtd_index f(3)
}
if ( TipFrameMode == TIP_FRAME_AS_OUTPUT ) {
disable_cdf_update = 1
tip_mv_zero f(1)
if ( !tip_mv_zero ) {
tip_mv_row f(4)
tip_mv_col f(4)
if ( tip_mv_row != 0 ) {
tip_mv_row_sign f(1)
TipGlobalMv[ 0 ] = tip_mv_row_sign ?
-tip_mv_row : tip_mv_row
}
if ( tip_mv_col != 0 ) {
tip_mv_col_sign f(1)
TipGlobalMv[ 1 ] = tip_mv_col_sign ?
-tip_mv_col : tip_mv_col
}
}
tip_sharp f(1)
if ( tip_sharp ) {
TipInterpFilter = EIGHTTAP_SHARP
} else {
tip_regular f(1)
TipInterpFilter = tip_regular ? EIGHTTAP: EIGHTTAP_SMOOTH
}
}
} else {
TipFrameMode = TIP_FRAME_DISABLED
if ( !bru_inactive && !IsBridge ) {
frame_opfl_refine_type()
}
}
if ( TipFrameMode != TIP_FRAME_AS_OUTPUT && !bru_inactive &&
!IsBridge ) {
screen_content_params( )
max_drl_bits_minus_1 = seq_max_drl_bits_minus1
if ( allow_frame_max_drl_bits ) {
change_drl f(1)
if ( change_drl ) {
max_drl_bits_minus_1 ns(6 - 2)
if ( max_drl_bits_minus_1 >= seq_max_drl_bits_minus1 ) {
max_drl_bits_minus_1 += 1
}
}
}
intrabc_params( )
if ( force_integer_mv ) {
FrameMvPrecision = MV_PRECISION_ONE_PEL
UsePerBlockMvPrecision = 0
} else {
use_qtr_precision_mv f(1)
if ( use_qtr_precision_mv ) {
FrameMvPrecision = MV_PRECISION_QUARTER_PEL
} else {
allow_high_precision_mv f(1)
FrameMvPrecision = allow_high_precision_mv ?
MV_PRECISION_EIGHTH_PEL : MV_PRECISION_HALF_PEL
}
UsePerBlockMvPrecision = enable_flex_mvres
}
MvPrecision = FrameMvPrecision
read_interpolation_filter( )
for ( mode = INTERINTRA; mode < MOTION_MODES; mode++ ) {
if ( !seq_frame_motion_modes_present_flag ) {
frame_enabled_motion_modes[ mode ] =
seq_enabled_motion_modes[ mode ]
} else if ( seq_enabled_motion_modes[ mode ] ) {
frame_enabled_motion_modes[ mode ] f(1)
} else {
frame_enabled_motion_modes[ mode ] = 0
}
}
}
}
if ( TipFrameMode == TIP_FRAME_AS_OUTPUT ) {
if ( enable_tip_explicit_qp ) {
quantization_params( )
}
if ( enable_lf_sub_pu ) {
allow_lf_sub_pu f(1)
}
if ( allow_lf_sub_pu ) {
apply_loopfilter_tip f(1)
} else {
apply_loopfilter_tip = 0
}
}
if ( TipFrameMode == TIP_FRAME_AS_OUTPUT || bru_inactive || IsBridge ) {
for ( i = 0 ; i < 3; i++ ) {
frame_filters_on[ i ] = 0
}
if ( bru_inactive || IsBridge ) {
if ( IsBridge ) {
tile_info( )
refIdx = bridge_frame_ref_idx
} else {
refIdx = ref_frame_idx[ bru_ref ]
}
base_q_idx = RefBaseQIdx[ refIdx ]
DeltaQUAc = RefDeltaQUAc[ refIdx ]
DeltaQVAc = RefDeltaQVAc[ refIdx ]
set_primary_ref_frame_and_ctx( 0 )
} else if ( apply_loopfilter_tip ) {
tile_info( )
}
film_grain_config( )
if ( bru_inactive || IsBridge ) {
set_primary_ref_frame_and_ctx( 1 )
}
for (row = 0; row < MiRows; row++) {
for (col = 0; col < MiCols; col++) {
SegmentIds[ row ][ col ] = 0
}
}
for ( ref = 0; ref < REFS_PER_FRAME; ref++ ) {
for ( i = 0; i < 6; i++ ) {
gm_params[ ref ][ i ] = Default_Warp_Params[ i ]
}
}
} else {
disable_cdf_update f(1)
}
if ( bru_inactive || IsBridge ) {
apply_loop_filter[ 0 ] = 0
apply_loop_filter[ 1 ] = 0
cdef_frame_enable = 0
for ( plane = 0; plane < NumPlanes; plane++ ) {
ccso_planes[ plane ] = 0
}
FrameRestorationType[ 0 ] = RESTORE_NONE
FrameRestorationType[ 1 ] = RESTORE_NONE
FrameRestorationType[ 2 ] = RESTORE_NONE
gdf_frame_enable = 0
segmentation_enabled = 0
for ( i = 0; i < MAX_SEGMENTS; i++ ) {
for ( j = 0; j < SEG_LVL_MAX; j++ ) {
FeatureEnabled[ i ][ j ] = 0
FeatureData[ i ][ j ] = 0
}
}
if ( primary_ref_frame == PRIMARY_REF_NONE ||
disable_cross_frame_cdf_init) {
init_coeff_cdfs( )
}
return
}
if ( use_ref_frame_mvs == 1 ) {
HasBothRefs = ClosestFuture != NONE && ClosestPast != NONE
motion_field_estimation( )
if ( TipFrameMode == TIP_FRAME_AS_OUTPUT ) {
if ( !enable_tip_explicit_qp ) {
slot0 = ref_frame_idx[ ClosestPast ]
slot1 = ref_frame_idx[ ClosestFuture ]
base_q_idx = Round2(RefBaseQIdx[slot0] + RefBaseQIdx[slot1], 1)
DeltaQUAc = Round2(RefDeltaQUAc[slot0] + RefDeltaQUAc[slot1], 1)
DeltaQVAc = Round2(RefDeltaQVAc[slot0] + RefDeltaQVAc[slot1], 1)
}
set_primary_ref_frame_and_ctx( 1 )
for (i = 0; i < MAX_SEGMENTS; i++) {
for ( j = 0; j < SEG_LVL_MAX; j++ ) {
FeatureData[ i ][ j ] = 0
FeatureEnabled[ i ][ j ] = 0
}
}
for (row = 0; row < MiRows; row++) {
for (col = 0; col < MiCols; col++) {
PrevSegmentIds[ row ][ col ] = 0
}
}
for ( plane = 0; plane < 3; plane++ ) {
ccso_planes[ plane ] = 0
}
if ( primary_ref_frame == PRIMARY_REF_NONE ||
disable_cross_frame_cdf_init ) {
init_coeff_cdfs( )
}
}
if ( TipFrameMode == TIP_FRAME_DISABLED ) {
fill_tpl_mvs_sample_gap( )
}
}
if ( TipFrameMode != TIP_FRAME_DISABLED ) {
setup_tip_motion_field( )
}
if ( TipFrameMode == TIP_FRAME_AS_OUTPUT ) {
return
}
tile_info( )
quantization_params( )
set_primary_ref_frame_and_ctx( 1 )
segmentation_params( )
setup_qm_params( )
delta_q_params( )
if ( primary_ref_frame == PRIMARY_REF_NONE ||
disable_cross_frame_cdf_init ) {
init_coeff_cdfs( )
}
if ( DerivedPrimaryRefFrame != PRIMARY_REF_NONE ) {
load_previous_segment_ids( )
}
CodedLossless = 1
HasLosslessSegment = 0
for ( segmentId = 0; segmentId < MaxSegments; segmentId++ ) {
qindex = get_qindex( 1, segmentId )
LosslessArray[ segmentId ] = qindex == 0 && delta_q_present == 0 &&
DeltaQYDc + BaseYDcDeltaQ <= 0 &&
DeltaQUDc + BaseUVDcDeltaQ <= 0 &&
DeltaQVDc + BaseUVDcDeltaQ <= 0 &&
DeltaQUAc + BaseUVAcDeltaQ <= 0 &&
DeltaQVAc + BaseUVAcDeltaQ <= 0
if ( LosslessArray[ segmentId ] ) {
HasLosslessSegment = 1
} else {
CodedLossless = 0
}
if ( using_qmatrix ) {
if ( LosslessArray[ segmentId ] ) {
SegQMLevel[ 0 ][ segmentId ] = 15
SegQMLevel[ 1 ][ segmentId ] = 15
SegQMLevel[ 2 ][ segmentId ] = 15
} else {
qmNum = pic_qm_num_minus1 + 1
qmIndexBits = CeilLog2( qmNum )
qm_index f(qmIndexBits)
SegQMLevel[ 0 ][ segmentId ] = qm_y[ qm_index ]
SegQMLevel[ 1 ][ segmentId ] = qm_u[ qm_index ]
SegQMLevel[ 2 ][ segmentId ] = qm_v[ qm_index ]
}
}
}
if ( CodedLossless ) {
allow_tcq = 0
} else if ( choose_tcq_per_frame ) {
allow_tcq f(1)
} else {
allow_tcq = enable_tcq
}
if ( CodedLossless || !enable_parity_hiding || allow_tcq ) {
allow_parity_hiding = 0
} else {
allow_parity_hiding f(1)
}
loop_filter_params( )
gdf_params( )
cdef_params( )
lr_params( )
ccso_params( )
read_tx_mode( )
frame_reference_mode( )
skip_mode_params( )
if (!FrameIsIntra && enable_bawp) {
allow_bawp f(1)
} else {
allow_bawp = 0
}
if ( !FrameIsIntra && frame_enabled_motion_modes[ DELTAWARP ] ) {
allow_warpmv_mode f(1)
} else {
allow_warpmv_mode = 0
}
reduced_tx_set f(2)
global_motion_params( )
film_grain_config( )
}

where the function get_disp_order_hint is defined as:

get_disp_order_hint( ) { Descriptor
if ( obu_type == OBU_CLOSED_LOOP_KEY ||
( !is_sef() && FrameType == SWITCH_FRAME &&
restricted_prediction_switch ) ) {
return OrderHintLsbs
}
maxDisp = get_max_disp_order_hint( 1 )
dispOrderHint = OrderHintLsbs
offset = maxDisp - ((1 << OrderHintBits) >> 1) - OrderHintLsbs
if ( offset >= 0 ) {
dispOrderHint += ((offset >> OrderHintBits) + 1) << OrderHintBits
}
return dispOrderHint
}

where get_max_disp_order_hint (which returns the maximum order hint from certain frames) is defined as:

get_max_disp_order_hint( onlyShowable ) {    maxDisp = 0    for ( i = 0; i < NumRefFrames; i++ ) {        if ( RefValid[i] &&                 TLayerDependencyMap[obu_tlayer_id][RefTLayerId[i]] &&                MLayerDependencyMap[obu_mlayer_id][RefMLayerId[i]] &&                 ( !onlyShowable || RefImplicitOutputFrame[ i ] ) ) {            maxDisp = Max( maxDisp, RefOrderHint[i])        }    }    return maxDisp}

It is a requirement of bitstream conformance that the value returned from get_disp_order_hint is less than (1 << (DISPLAY_ORDER_HINT_BITS - 1).

The function set_primary_ref_frame_and_ctx is defined as:

set_primary_ref_frame_and_ctx( loadCdfs ) { Descriptor
(DerivedPrimaryRefFrame,derivedSecondaryRefFrame) =
choose_primary_secondary_ref_frame()
if ( primary_ref_frame == PRIMARY_REF_CHOOSE ) {
primary_ref_frame = DerivedPrimaryRefFrame
}
if ( DerivedPrimaryRefFrame == PRIMARY_REF_NONE ||
primary_ref_frame == PRIMARY_REF_NONE ) {
primary_ref_frame = PRIMARY_REF_NONE
DerivedPrimaryRefFrame = PRIMARY_REF_NONE
disable_cross_frame_cdf_init = 1
}
if ( !loadCdfs ) {
return
}
if ( primary_ref_frame == PRIMARY_REF_NONE ||
disable_cross_frame_cdf_init ) {
init_non_coeff_cdfs( )
} else {
load_cdfs( ref_frame_idx[ primary_ref_frame ] )
if ( TipFrameMode != TIP_FRAME_AS_OUTPUT ) {
blendFrame = (primary_ref_frame == DerivedPrimaryRefFrame) ?
derivedSecondaryRefFrame : DerivedPrimaryRefFrame
if ( enable_avg_cdf && !avg_cdf_type &&
blendFrame != PRIMARY_REF_NONE &&
!bru_inactive ) {
blend_cdfs( ref_frame_idx[ blendFrame ] )
}
}
}
if ( DerivedPrimaryRefFrame == PRIMARY_REF_NONE ) {
setup_past_independence( )
} else {
load_previous( )
}
}

The functions choose_primary_secondary_ref_frame and is_ref_better are defined as:

choose_primary_secondary_ref_frame() { Descriptor
if ( FrameIsIntra || FrameType == SWITCH_FRAME ) {
return (PRIMARY_REF_NONE, PRIMARY_REF_NONE)
}
primary = PRIMARY_REF_NONE
primaryQpDiff = 512
secondary = PRIMARY_REF_NONE
secondaryQpDiff = 512
primaryD = 0
secondaryD = 0
primaryRatio = 0
secondaryRatio = 0
for ( i = 0; i < NumTotalRefs; i++ ) {
idx = ref_frame_idx[ i ]
if ( RefFrameType[ idx ] == INTER_FRAME && first_slot_with_ref(idx) &&
RefOrderHint[idx] != RESTRICTED_OH ) {
q = RefBaseQIdx[ idx ]
d = RefOrderHint[ idx ]
dRatio = FloorLog2( RefFrameWidth[ idx ] * RefFrameHeight[ idx ] )
qpDiff = Abs(q - base_q_idx)
if ( (qpDiff < primaryQpDiff) ||
(qpDiff == primaryQpDiff &&
is_ref_better(d,primaryD,dRatio,primaryRatio)) ) {
secondary = primary
secondaryQpDiff = primaryQpDiff
secondaryD = primaryD
secondaryRatio = primaryRatio
primary = i
primaryQpDiff = qpDiff
primaryD = d
primaryRatio = dRatio
} else if ((qpDiff < secondaryQpDiff) ||
(qpDiff == secondaryQpDiff &&
is_ref_better(d,secondaryD,dRatio,secondaryRatio))) {
secondary = i
secondaryQpDiff = qpDiff
secondaryD = d
secondaryRatio = dRatio
}
}
}
return (primary,secondary)
}
is_ref_better(refDisp, bestDisp, refRatio, bestRatio) {
d0 = Abs(get_relative_dist(OrderHint,refDisp)) - (refRatio << 1)
d1 = Abs(get_relative_dist(OrderHint,bestDisp)) - (bestRatio << 1)
if (d0 < d1) {
return 1
}
if (d0 == d1 && get_relative_dist(refDisp,bestDisp) > 0) {
return 1
}
return 0
}

The function long_term_id_in_use (which determines if longTermId is present in the ref_long_term_id array) is defined as:

long_term_id_in_use( longTermId ) { Descriptor
for ( j = 0; j < num_key_ref_frames; j++ ) {
if ( longTermId == ref_long_term_id[ j ] ) {
return 1
}
}
return 0
}

5.18.3. Get relative distance function

This function computes the distance between two order hints by sign extending the result of subtracting the values.

get_relative_dist( a, b ) {    if ( a == RESTRICTED_OH && b == RESTRICTED_OH ) {        return 0    } else if ( a == RESTRICTED_OH ) {        return 127    } else if ( b == RESTRICTED_OH ) {        return -127    } else {        return Clip3( -127, 127, a - b )    }}

5.18.4. Frame optical flow refine type syntax

frame_opfl_refine_type( ) { Descriptor
if ( TipFrameMode == TIP_FRAME_AS_OUTPUT ) {
opfl_refine_type = ( !enable_tip_refinemv ||
enable_opfl_refine == REFINE_NONE ) ?
REFINE_NONE : REFINE_ALL
} else if ( enable_opfl_refine == REFINE_AUTO ) {
opfl_refine_type f(1)
if ( opfl_refine_type != REFINE_SWITCHABLE ) {
opfl_refine_all f(1)
opfl_refine_type = opfl_refine_all ? REFINE_ALL : REFINE_NONE
}
} else {
opfl_refine_type = enable_opfl_refine
}
}

5.18.5. Screen content params syntax

screen_content_params( ) { Descriptor
if ( seq_force_screen_content_tools == SELECT_SCREEN_CONTENT_TOOLS ) {
allow_screen_content_tools 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 f(1)
} else {
force_integer_mv = seq_force_integer_mv
}
} else {
force_integer_mv = 0
}
}

5.18.6. Intra block copy params syntax

intrabc_params( ) { Descriptor
allow_intrabc f(1)
if ( allow_intrabc ) {
if ( FrameIsIntra ) {
allow_global_intrabc f(1)
if ( allow_global_intrabc ) {
allow_local_intrabc f(1)
} else {
allow_local_intrabc = 1
}
} else {
allow_global_intrabc = 0
allow_local_intrabc = 1
}
max_bvp_drl_bits_minus_1 = seq_max_bvp_drl_bits_minus1
if ( allow_frame_max_bvp_drl_bits ) {
change_bvp_drl f(1)
if ( change_bvp_drl ) {
max_bvp_drl_bits_minus_1 ns(2)
if ( max_bvp_drl_bits_minus_1 >=
seq_max_bvp_drl_bits_minus1 ) {
max_bvp_drl_bits_minus_1 += 1
}
}
}
}
}

5.18.7. Frame size syntax

frame_size( ) { Descriptor
if ( frame_size_override_flag ) {
n = frame_width_bits_minus_1 + 1
frame_width_minus_1 f(n)
n = frame_height_bits_minus_1 + 1
frame_height_minus_1 f(n)
FrameWidth = frame_width_minus_1 + 1
FrameHeight = frame_height_minus_1 + 1
} else {
FrameWidth = mfh_frame_width_minus_1[ cur_mfh_id ] + 1
FrameHeight = mfh_frame_height_minus_1[ cur_mfh_id ] + 1
}
compute_image_size( )
}

5.18.8. Frame size with bridge syntax

frame_size_with_bridge( ) { Descriptor
n = frame_width_bits_minus_1 + 1
bridge_frame_width_minus_1 f(n)
n = frame_height_bits_minus_1 + 1
bridge_frame_height_minus_1 f(n)
FrameWidth = Min( RefFrameWidth[ bridge_frame_ref_idx ],
bridge_frame_width_minus_1 + 1 )
FrameHeight = Min( RefFrameHeight[ bridge_frame_ref_idx ],
bridge_frame_height_minus_1 + 1 )
compute_image_size( )
}

5.18.9. Frame size with refs syntax

frame_size_with_refs( ) { Descriptor
for ( i = 0; i < NumTotalRefs; i++ ) {
found_ref f(1)
if ( found_ref == 1 ) {
FrameWidth = RefFrameWidth[ ref_frame_idx[ i ] ]
FrameHeight = RefFrameHeight[ ref_frame_idx[ i ] ]
break
}
}
if ( NumTotalRefs == 0 || found_ref == 0 ) {
frame_size( )
} else {
compute_image_size( )
}
}

5.18.10. Compute image size function

compute_image_size( ) { Descriptor
MiCols = 2 * ( ( FrameWidth + 7 ) >> 3 )
MiRows = 2 * ( ( FrameHeight + 7 ) >> 3 )
maxFrameWidth = max_frame_width_minus_1 + 1
maxFrameHeight = max_frame_height_minus_1 + 1
CropLeft = (seq_cropping_win_left_offset * FrameWidth) / maxFrameWidth
cropRight = FrameWidth - ((seq_cropping_win_right_offset * FrameWidth) /
maxFrameWidth)
CropTop = (seq_cropping_win_top_offset * FrameHeight) / maxFrameHeight
cropBottom = FrameHeight - ((seq_cropping_win_bottom_offset * FrameHeight) /
maxFrameHeight)
CropWidth = cropRight - CropLeft
CropHeight = cropBottom - CropTop
}

5.18.11. Interpolation filter syntax

read_interpolation_filter( ) { Descriptor
is_filter_switchable f(1)
if ( is_filter_switchable == 1 ) {
interpolation_filter = SWITCHABLE
} else {
interpolation_filter f(2)
}
}

5.18.12. Loop filter params syntax

loop_filter_params( ) { Descriptor
if ( CodedLossless ) {
apply_loop_filter[ 0 ] = 0
apply_loop_filter[ 1 ] = 0
return
}
if ( enable_lf_sub_pu && FrameType == INTER_FRAME ) {
allow_lf_sub_pu f(1)
} else {
allow_lf_sub_pu = 0
}
if ( mfh_loop_filter_update[ cur_mfh_id ] ) {
apply_loop_filter[ 0 ] = mfh_apply_loop_filter[ cur_mfh_id ][ 0 ]
apply_loop_filter[ 1 ] = mfh_apply_loop_filter[ cur_mfh_id ][ 1 ]
apply_loop_filter[ 2 ] = 0
apply_loop_filter[ 3 ] = 0
if ( NumPlanes > 1 ) {
if ( apply_loop_filter[0] || apply_loop_filter[1] ) {
apply_loop_filter[2] = mfh_apply_loop_filter[cur_mfh_id][2]
apply_loop_filter[3] = mfh_apply_loop_filter[cur_mfh_id][3]
}
}
} else {
apply_loop_filter[ 0 ] f(1)
apply_loop_filter[ 1 ] f(1)
apply_loop_filter[ 2 ] = 0
apply_loop_filter[ 3 ] = 0
if ( NumPlanes > 1 ) {
if ( apply_loop_filter[ 0 ] || apply_loop_filter[ 1 ] ) {
apply_loop_filter[ 2 ] f(1)
apply_loop_filter[ 3 ] f(1)
}
}
}
for ( i = 0; i < 4; i++ ) {
if ( apply_loop_filter[ i ] ) {
lf_delta_q_present f(1)
if ( lf_delta_q_present ) {
dfParBits = df_par_bits_minus2 + 2
lf_delta_q f(dfParBits)
LfDeltaQ[ i ] = lf_delta_q - ( 1 << (dfParBits - 1) )
} else {
LfDeltaQ[ i ] = (i == 1) ? LfDeltaQ[ 0 ] : 0
}
} else {
LfDeltaQ[ i ] = 0
}
}
}

5.18.13. Quantization params syntax

quantization_params( ) { Descriptor
base_q_idx f(BitDepth == 8 ? 8 : 9)
DeltaQYDc = 0
DeltaQUDc = 0
DeltaQUAc = 0
DeltaQVDc = 0
DeltaQVAc = 0
if ( TipFrameMode != TIP_FRAME_AS_OUTPUT && y_dc_delta_q_enabled ) {
DeltaQYDc = read_delta_q( )
}
if ( NumPlanes > 1 && (
uv_ac_delta_q_enabled ||
(TipFrameMode != TIP_FRAME_AS_OUTPUT && uv_dc_delta_q_enabled)
) ) {
if ( separate_uv_delta_q ) {
diff_uv_delta f(1)
} else {
diff_uv_delta = 0
}
if ( TipFrameMode != TIP_FRAME_AS_OUTPUT && uv_dc_delta_q_enabled ) {
DeltaQUDc = read_delta_q( )
}
if ( uv_ac_delta_q_enabled ) {
DeltaQUAc = read_delta_q( )
}
if ( equal_ac_dc_q ) {
DeltaQUDc = DeltaQUAc
}
if ( diff_uv_delta ) {
if ( TipFrameMode != TIP_FRAME_AS_OUTPUT &&
uv_dc_delta_q_enabled ) {
DeltaQVDc = read_delta_q( )
}
if ( uv_ac_delta_q_enabled ) {
DeltaQVAc = read_delta_q( )
}
if ( equal_ac_dc_q ) {
DeltaQVDc = DeltaQVAc
}
} else {
DeltaQVDc = DeltaQUDc
DeltaQVAc = DeltaQUAc
}
}
}

5.18.14. Setup QM params syntax

setup_qm_params( ) { Descriptor
using_qmatrix f(1)
if ( using_qmatrix ) {
if ( segmentation_enabled ) {
pic_qm_num_minus1 f(2)
} else {
pic_qm_num_minus1 = 0
}
qmNum = pic_qm_num_minus1 + 1
for ( i = 0; i < qmNum; i++ ) {
qm_y[ i ] f(4)
if ( NumPlanes > 1 ) {
qm_uv_same_as_y f(1)
if ( qm_uv_same_as_y ) {
qm_u[ i ] = qm_y [ i ]
qm_v[ i ] = qm_y [ i ]
} else {
qm_u[ i ] f(4)
if ( !separate_uv_delta_q ) {
qm_v[ i ] = qm_u[ i ]
} else {
qm_v[ i ] f(4)
}
}
}
}
}
}

5.18.15. Delta quantizer syntax

read_delta_q( ) { Descriptor
delta_coded f(1)
if ( delta_coded ) {
delta_q su(1+6)
} else {
delta_q = 0
}
return delta_q
}

5.18.16. Segmentation params syntax

segmentation_params( ) { Descriptor
segmentation_enabled f(1)
if ( segmentation_enabled == 1 ) {
if ( cur_mfh_id > 0 && mfh_seg_info_present_flag[ cur_mfh_id ] ) {
haveSegParams = mfh_ext_seg_flag[ cur_mfh_id ] == enable_ext_seg
allowChange = haveSegParams && mfh_allow_seg_info_change[cur_mfh_id]
mfhId = cur_mfh_id
} else if ( seq_seg_info_present_flag ) {
haveSegParams = 1
allowChange = seq_allow_seg_info_change
mfhId = 0
} else {
haveSegParams = 0
allowChange = 0
}
if ( allowChange ) {
reuse_seg_info f(1)
} else {
reuse_seg_info = haveSegParams
}
if ( reuse_seg_info ) {
for ( i = 0; i < MAX_SEGMENTS; i++ ) {
for ( j = 0; j < SEG_LVL_MAX; j++ ) {
if ( mfhId == 0 ) {
FeatureData[ i ][ j ] = SeqFeatureData[ i ][ j ]
FeatureEnabled[ i ][ j ] = SeqFeatureEnabled[ i ][ j ]
} else {
FeatureData[ i ][ j ] =
MfhFeatureData[ mfhId ][ i ][ j ]
FeatureEnabled[ i ][ j ] =
MfhFeatureEnabled[ mfhId ][ i ][ j ]
}
}
}
} else {
(FeatureEnabled, FeatureData) = seg_info( MaxSegments )
}
if ( DerivedPrimaryRefFrame == PRIMARY_REF_NONE ) {
segmentation_update_map = 1
segmentation_temporal_update = 0
} else {
segmentation_update_map f(1)
if ( segmentation_update_map == 1 && FrameType != SWITCH_FRAME ) {
segmentation_temporal_update f(1)
} else {
segmentation_temporal_update = 0
}
}
} 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 < MaxSegments; i++ ) {
for ( j = 0; j < SEG_LVL_MAX; j++ ) {
if ( FeatureEnabled[ i ][ j ] ) {
LastActiveSegId = i
if ( j >= SEG_LVL_SKIP ) {
SegIdPreSkip = 1
}
}
}
}
}

The constant lookup tables used in this syntax are defined as:

Segmentation_Feature_Bits[ SEG_LVL_MAX ]   = { 9, 0, 0 }Segmentation_Feature_Signed[ SEG_LVL_MAX ] = { 1, 0, 0 }Segmentation_Feature_Max[ SEG_LVL_MAX ] = { MAXQ_12_BITS, 0, 0 }

5.18.17. Tile info syntax

tile_info ( ) { Descriptor
sb4x4 = Num_4x4_Blocks_Wide[ SbSize ]
sbShift = Mi_Width_Log2[ SbSize ]
sbCols = ( MiCols + sb4x4 - 1 ) >> sbShift
sbRows = ( MiRows + sb4x4 - 1 ) >> sbShift
if ( IsBridge ) {
haveTileParams = 0
} else if ( mfh_tile_info_present_flag[ cur_mfh_id ] ) {
haveTileParams = 1
mfhId = cur_mfh_id
} else {
haveTileParams = mfh_tile_info_present_flag[ 0 ]
mfhId = 0
}
if ( haveTileParams &&
( MfhUniform[ mfhId ] || ( MfhSbCols[ mfhId ] == sbCols &&
MfhSbRows[ mfhId ] == sbRows ) ) ) {
if ( mfh_allow_tile_info_change[ mfhId ] ) {
reuse_tile_info f(1)
} else {
reuse_tile_info = 1
}
} else {
reuse_tile_info = 0
}
seqSbSize = get_seq_sb_size()
if ( reuse_tile_info ) {
( sbRowStarts, TileRows, TileRowsLog2, sbColStarts, TileCols,
TileColsLog2, sbShift2) = reuse_tile_params( MfhUniform[ mfhId ],
MfhSbRowStarts[ mfhId ], MfhTileRows[ mfhId ],
MfhTileRowsLog2[ mfhId ], MfhSbColStarts[ mfhId ],
MfhTileCols[ mfhId ], MfhTileColsLog2[ mfhId ], seqSbSize, SbSize )
} else {
( sbRowStarts, sbRows, TileRows, TileRowsLog2, sbColStarts, sbCols,
TileCols, TileColsLog2, uniformSpacing, sbShift2) = tile_params(
FrameWidth, FrameHeight, seqSbSize, SbSize, IsBridge )
}
for ( i = 0; i < TileCols; i++ ) {
MiColStarts[ i ] = sbColStarts[ i ] << sbShift2
}
for ( i = 0; i < TileRows; i++ ) {
MiRowStarts[ i ] = sbRowStarts[ i ] << sbShift2
}
MiColStarts[ TileCols ] = MiCols
MiRowStarts[ TileRows ] = MiRows
if ( (TileCols > 1 || TileRows > 1) && !IsBridge &&
TipFrameMode != TIP_FRAME_AS_OUTPUT ) {
if ( !enable_avg_cdf || !avg_cdf_type ) {
context_update_tile_id f(TileRowsLog2 + TileColsLog2)
}
tile_size_bytes_minus_1 f(2)
TileSizeBytes = tile_size_bytes_minus_1 + 1
} else {
context_update_tile_id = 0
}
}

5.18.18. Tile params syntax

tile_params( frameWidth, frameHeight, uniformSbSize, sbSize, isBridge ) { Descriptor
miCols = 2 * ( ( frameWidth + 7 ) >> 3 )
miRows = 2 * ( ( frameHeight + 7 ) >> 3 )
sb4x4 = Num_4x4_Blocks_Wide[ sbSize ]
sbShift = Mi_Width_Log2[ sbSize ]
sbCols = ( miCols + sb4x4 - 1 ) >> sbShift
sbRows = ( miRows + sb4x4 - 1 ) >> sbShift
maxTileWidthSb = MAX_TILE_WIDTH >> (sbShift + 2)
maxTileAreaSb = MAX_TILE_AREA >> ( 2 * (sbShift + 2) )
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))
if ( isBridge ) {
uniform_tile_spacing_flag = 1
} else {
uniform_tile_spacing_flag f(1)
}
if ( uniform_tile_spacing_flag ) {
sbShift = Mi_Width_Log2[ uniformSbSize ]
tileColsLog2 = minLog2TileCols
if ( !isBridge ) {
while ( tileColsLog2 < maxLog2TileCols ) {
increment_tile_cols_log2 f(1)
if ( increment_tile_cols_log2 == 1 ) {
tileColsLog2 += 1
} else {
break
}
}
}
(sbColStarts, tileCols) = uniform_spacing( tileColsLog2, miCols,
uniformSbSize )
minLog2TileRows = Max( minLog2Tiles - tileColsLog2, 0)
tileRowsLog2 = minLog2TileRows
if ( !isBridge ) {
while ( tileRowsLog2 < maxLog2TileRows ) {
increment_tile_rows_log2 f(1)
if ( increment_tile_rows_log2 == 1 ) {
tileRowsLog2++
} else {
break
}
}
}
(sbRowStarts, tileRows) = uniform_spacing( tileRowsLog2, miRows,
uniformSbSize )
} else {
widestTileSb = 1
startSb = 0
for ( i = 0; startSb < sbCols; i++ ) {
sbColStarts[ i ] = startSb
maxWidth = Min(sbCols - startSb, maxTileWidthSb)
width_in_sbs_minus_1 ns(maxWidth)
sizeSb = width_in_sbs_minus_1 + 1
widestTileSb = Max( sizeSb, widestTileSb )
startSb += sizeSb
}
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++ ) {
sbRowStarts[ i ] = startSb
maxHeight = Min(sbRows - startSb, maxTileHeightSb)
height_in_sbs_minus_1 ns(maxHeight)
sizeSb = height_in_sbs_minus_1 + 1
startSb = startSb + sizeSb
}
tileRows = i
tileRowsLog2 = tile_log2(1, tileRows)
}
return ( sbRowStarts, sbRows, tileRows, tileRowsLog2, sbColStarts, sbCols,
tileCols, tileColsLog2, uniform_tile_spacing_flag, sbShift)
}

5.18.19. Reuse tile params function

reuse_tile_params( uniformSpacing, sbRowStarts, tileRows, tileRowsLog2, sbColStarts, tileCols, tileColsLog2, seqSbSize, sbSize ) { Descriptor
if ( uniformSpacing ) {
sbShift = Mi_Width_Log2[ seqSbSize ]
(unifSbColStarts, tileCols) = uniform_spacing( tileColsLog2, MiCols,
seqSbSize )
(unifSbRowStarts, tileRows) = uniform_spacing( tileRowsLog2, MiRows,
seqSbSize )
return ( unifSbRowStarts, tileRows, tileRowsLog2, unifSbColStarts,
tileCols, tileColsLog2, sbShift)
} else {
sbShift = Mi_Width_Log2[ sbSize ]
tileColsLog2 = tile_log2(1, tileCols)
tileRowsLog2 = tile_log2(1, tileRows)
return ( sbRowStarts, tileRows, tileRowsLog2, sbColStarts, tileCols,
tileColsLog2, sbShift)
}
}

5.18.20. Uniform spacing function

uniform_spacing( tileLog2, mis, sbSize ) { Descriptor
sb4x4 = Num_4x4_Blocks_Wide[ sbSize ]
sbShift = Mi_Width_Log2[ sbSize ]
sbs = ( mis + sb4x4 - 1 ) >> sbShift
fullSbs = mis >> sbShift
tileSb = fullSbs >> tileLog2
if ( tileSb == 0 ) {
extraSbs = sbs
} else {
extraSbs = fullSbs - (tileSb << tileLog2)
}
startSb = 0
for (i = 0; i < (1 << tileLog2) && startSb < sbs; i++) {
sbStarts[ i ] = startSb
startSb += tileSb
if (i < extraSbs) {
startSb += 1
}
}
return (sbStarts, i)
}

5.18.21. Get sequence superblock size function

get_seq_sb_size() { Descriptor
if ( use_256x256_superblock ) {
return BLOCK_256X256
} else if ( use_128x128_superblock ) {
return BLOCK_128X128
} else {
return BLOCK_64X64
}
}

5.18.22. Tile size calculation function

tile_log2 returns the smallest value for k such that blkSize << k is greater than or equal to target.

tile_log2( blkSize, target ) {    for ( k = 0; (blkSize << k) < target; k++ ) {    }    return k}

5.18.23. Quantizer index delta parameters syntax

delta_q_params( ) { Descriptor
delta_q_res = 0
delta_q_present = 0
if ( base_q_idx > 0 ) {
delta_q_present f(1)
}
if ( delta_q_present ) {
delta_q_res f(2)
}
}

5.18.24. GDF params syntax

gdf_params( ) { Descriptor
if ( CodedLossless || !enable_gdf ) {
gdf_frame_enable = 0
} else {
if ( single_picture_header_flag ) {
gdf_frame_enable = 1
} else {
gdf_frame_enable f(1)
}
if ( !gdf_frame_enable ) {
return
}
gdfBlkSize = Max(Block_Width[ SbSize ],GDF_MIN_SIZE)
if ( SbSize == BLOCK_64X64 ) {
a = 0
for ( i = 0; i < TileCols; i++ ) {
a = a | MiColStarts[ i ]
}
for ( i = 0; i < TileRows; i++ ) {
a = a | MiRowStarts[ i ]
}
if ( a & 16 ) {
gdfBlkSize = 64
}
}
GdfBlkSize = gdfBlkSize
if ( MiCols * MI_SIZE > gdfBlkSize ||
MiRows * MI_SIZE > gdfBlkSize ||
( disable_loopfilters_across_tiles &&
(TileRows > 1 || TileCols > 1) ) ) {
gdf_per_block f(1)
} else {
gdf_per_block = 0
}
gdf_pic_qc_idx f(2)
gdf_pic_scale_idx f(2)
GdfPixScale = 1 + gdf_pic_scale_idx
}
}

5.18.25. CDEF params syntax

cdef_params( ) { Descriptor
if ( CodedLossless ||
!enable_cdef ) {
cdef_frame_enable = 0
return
}
if ( single_picture_header_flag ) {
cdef_frame_enable = 1
} else {
cdef_frame_enable f(1)
}
if ( !cdef_frame_enable ) {
return
}
cdef_damping_minus_3 f(2)
CdefDamping = cdef_damping_minus_3 + 3
cdef_strengths_minus1 f(3)
CdefStrengths = cdef_strengths_minus1 + 1
if ( CdefOnSkipTxfm == CDEF_ON_SKIP_TXFM_ADAPTIVE ) {
cdef_on_skip_txfm_frame_enable f(1)
} else if ( CdefOnSkipTxfm == CDEF_ON_SKIP_TXFM_ALWAYS_ON ) {
cdef_on_skip_txfm_frame_enable = 1
} else {
cdef_on_skip_txfm_frame_enable = 0
}
for ( i = 0; i < CdefStrengths; i++ ) {
cdef_y_pri_zero f(1)
if ( cdef_y_pri_zero ) {
cdef_y_pri_strength[ i ] = 0
} else {
cdef_y_pri_strength[ i ] f(4)
}
cdef_y_sec_strength[ i ] f(2)
if ( cdef_y_sec_strength[ i ] == 3 ) {
cdef_y_sec_strength[ i ] += 1
}
if ( NumPlanes > 1 ) {
cdef_uv_pri_zero f(1)
if ( cdef_uv_pri_zero ) {
cdef_uv_pri_strength[ i ] = 0
} else {
cdef_uv_pri_strength[ i ] f(4)
}
cdef_uv_sec_strength[ i ] f(2)
if ( cdef_uv_sec_strength[ i ] == 3 ) {
cdef_uv_sec_strength[ i ] += 1
}
}
}
}

5.18.26. Loop restoration params syntax

lr_params( ) { Descriptor
if ( CodedLossless || !enable_restoration ) {
FrameRestorationType[ 0 ] = RESTORE_NONE
FrameRestorationType[ 1 ] = RESTORE_NONE
FrameRestorationType[ 2 ] = RESTORE_NONE
UsesLr = 0
for ( i = 0; i < 3; i++ ) {
frame_filters_on[ i ] = 0
}
return
}
usesLumaLr = 0
usesChromaLr = 0
for ( plane = 0; plane < NumPlanes; plane++ ) {
toolsCount = 1
indexToTool[ 0 ] = RESTORE_NONE
for ( i = 1; i < RESTORE_SWITCHABLE_TYPES; i++ ) {
if ( !lr_tools_disable[ plane > 0 ][ i ] ) {
indexToTool[ toolsCount ] = i
toolsCount += 1
}
}
indexToTool[ toolsCount ] = RESTORE_SWITCHABLE
allowSwitchable = (toolsCount > 2)
tool_index ns(toolsCount + allowSwitchable)
FrameRestorationType[ plane ] = indexToTool[ tool_index ]
if ( FrameRestorationType[ plane ] != RESTORE_NONE ) {
if ( plane == 0 ) {
usesLumaLr = 1
} else {
usesChromaLr = 1
}
}
r = FrameRestorationType[ plane ]
if ( plane == 0 ) {
NumFilterClasses = 1
}
frame_filters_on[ plane ] = 0
temporal_pred_flag[ plane ] = 0
if ( r == RESTORE_WIENER_NONSEP || r == RESTORE_SWITCHABLE ) {
frame_filters_on[ plane ] f(1)
if ( frame_filters_on[ plane ] ) {
numRefFrames = (FrameIsIntra || FrameType == SWITCH_FRAME) ?
0 : NumTotalRefs
if ( numRefFrames > 0 ) {
temporal_pred_flag[ plane ] f(1)
}
if ( temporal_pred_flag[ plane ] && numRefFrames > 1 ) {
rst_ref_pic_idx f(CeilLog2(numRefFrames))
} else {
rst_ref_pic_idx = 0
}
if ( temporal_pred_flag[ plane ] ) {
refIdx = ref_frame_idx[ rst_ref_pic_idx ]
refPlane = plane
if ( plane > 0 && !RefFrameFiltersOn[ refIdx ][ plane ] ) {
refPlane = plane == 1 ? 2 : 1
}
if ( plane == 0 ) {
NumFilterClasses = RefNumFilterClasses[ refIdx ]
}
for ( c = 0; c < WIENER_NS_CLASSES; c++ ) {
for ( i = 0; i < WIENER_NS_CHROMA_COEFFS; i++ ) {
FrameLrWienerNs[plane][c][i] =
RefFrameLrWienerNs[refIdx][refPlane][c][i]
}
}
}
}
if ( plane == 0 && frame_filters_on[ 0 ] ) {
if ( temporal_pred_flag[ plane ] ) {
num_filter_classes_idx =
Encode_Num_Filter_Classes[ NumFilterClasses ]
} else {
num_filter_classes_idx f(3)
NumFilterClasses =
Decode_Num_Filter_Classes[ num_filter_classes_idx ]
}
qindex = base_q_idx
index = get_filter_set_index(qindex)
SubclassLookup =
Pc_Wiener_Sub_Classify2[ index ][ num_filter_classes_idx ]
}
}
}
UsesLr = usesLumaLr || usesChromaLr
LoopRestorationSize[ 0 ] = RESTORATION_TILESIZE_MAX >> 3
LoopRestorationSize[ 1 ] = RESTORATION_TILESIZE_MAX >>
( 3 + Max(SubsamplingX, SubsamplingY) )
if ( usesLumaLr ) {
lr_luma_use_half_size f(1)
if ( lr_luma_use_half_size ) {
shift = 1
} else if ( SbSize == BLOCK_256X256 ) {
shift = 0
} else {
lr_luma_use_max_size f(1)
if ( lr_luma_use_max_size ) {
shift = 0
} else if ( SbSize == BLOCK_128X128 ) {
shift = 2
} else {
lr_luma_use_quarter_size f(1)
shift = lr_luma_use_quarter_size ? 2 : 3
}
}
LoopRestorationSize[ 0 ] = RESTORATION_TILESIZE_MAX >> shift
}
if ( usesChromaLr ) {
LoopRestorationSize[ 1 ] = RESTORATION_TILESIZE_MAX >>
Max(SubsamplingX, SubsamplingY)
lr_chroma_use_half_size f(1)
if ( lr_chroma_use_half_size ) {
shift = 1
} else if ( SbSize == BLOCK_256X256 ) {
shift = 0
} else {
lr_chroma_use_max_size f(1)
if ( lr_chroma_use_max_size ) {
shift = 0
} else if ( SbSize == BLOCK_128X128 ) {
shift = 2
} else {
lr_chroma_use_quarter_size f(1)
shift = lr_chroma_use_quarter_size ? 2 : 3
}
}
LoopRestorationSize[ 1 ] = LoopRestorationSize[ 1 ] >> shift
}
LoopRestorationSize[ 2 ] = LoopRestorationSize[ 1 ]
for ( plane = 0; plane < NumPlanes; plane++ ) {
if ( frame_filters_on[ plane ] && !temporal_pred_flag[ plane ] ) {
read_wienerns_filter(plane, 0, 0, 1)
}
}
}

where the function get_filter_set_index is defined as:

get_filter_set_index( base_qindex ) {    if (base_qindex < 130) {        return 0    } else if (base_qindex < 190) {        return 1    } else if (base_qindex < 220) {        return 2    } else {        return 3    }}

and the constant tables Decode_Num_Filter_Classes and Encode_Num_Filter_Classes are defined as:

Encode_Num_Filter_Classes[ 17 ] = {    0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7}Decode_Num_Filter_Classes[ 8 ] = {    1, 2, 3, 4, 6, 8, 12, 16}

5.18.27. CCSO params syntax

ccso_params( ) { Descriptor
for ( plane = 0; plane < NumPlanes; plane++ ) {
ccso_planes[ plane ] = 0
}
if ( CodedLossless || !enable_ccso ) {
return
}
a = 0
for ( i = 0; i < TileCols; i++ ) {
a = a | MiColStarts[ i ]
}
for ( i = 0; i < TileRows; i++ ) {
a = a | MiRowStarts[ i ]
}
if ( (a & 63) == 0 ) {
CcsoLumaSizeLog2 = 8
} else if ( (a & 31) == 0 ) {
CcsoLumaSizeLog2 = 7
} else {
CcsoLumaSizeLog2 = 6
}
if ( single_picture_header_flag ) {
ccso_frame_flag = 1
} else {
ccso_frame_flag f(1)
}
if ( !ccso_frame_flag ) {
return
}
for ( plane = 0; plane < NumPlanes; plane++ ) {
ccso_planes[ plane ] f(1)
if ( ccso_planes[ plane ] ) {
if ( FrameIsIntra || FrameType == SWITCH_FRAME ) {
reuse_ccso[ plane ] = 0
sb_reuse_ccso[ plane ] = 0
} else {
reuse_ccso[ plane ] f(1)
sb_reuse_ccso[ plane ] f(1)
}
if ( reuse_ccso[ plane ] || sb_reuse_ccso[ plane ] ) {
ccso_ref_idx[ plane ] f(CeilLog2(NumTotalRefs))
idx = ref_frame_idx[ ccso_ref_idx[ plane ] ]
tmpCcsoLumaSizeLog2 = CcsoLumaSizeLog2
load_ccso_params(idx, plane)
CcsoLumaSizeLog2 = tmpCcsoLumaSizeLog2
}
}
if ( ccso_planes[ plane ] && !reuse_ccso[ plane ] ) {
ccso_bo_only[ plane ] f(1)
ccso_scale_idx[ plane ] f(2)
if ( ccso_bo_only[ plane ] ) {
ccso_quant_idx[ plane ] = 0
ccso_ext_filter[ plane ] = 0
ccso_edge_clf[ plane ] = 0
} else {
ccso_quant_idx[ plane ] f(2)
ccso_ext_filter[ plane ] f(3)
quantStep = CCSO_Quant_Sz[ ccso_scale_idx[ plane ] ]
[ ccso_quant_idx[ plane ] ]
if ( quantStep == 0 ) {
ccso_edge_clf[ plane ] = 0
} else {
ccso_edge_clf[ plane ] f(1)
}
}
ccso_max_band_log2[ plane ] f(2 + ccso_bo_only[ plane ])
maxEdgeInterval = CCSO_INPUT_INTERVAL - ccso_edge_clf[ plane ]
if ( ccso_bo_only[ plane ] ) {
maxEdgeInterval = 1
}
maxBand = 1 << ccso_max_band_log2[ plane ]
for ( d0 = 0; d0 < maxEdgeInterval; d0++ ) {
for ( d1 = 0; d1 < maxEdgeInterval; d1++ ) {
for ( band = 0; band < maxBand; band++ ) {
ccso_offset_idx tu(7)
offset = Ccso_Offset[ ccso_offset_idx ] *
(ccso_scale_idx[ plane ] + 1)
CcsoFilterOffset[ plane ][ band ][ d0 ][ d1 ] = offset
}
}
}
}
}
}

where Ccso_Offset is defined as:

Ccso_Offset[ 8 ] = {     0, 1, -1, 3, -3, 7, -7, -10}

5.18.28. TX mode syntax

read_tx_mode( ) { Descriptor
if ( CodedLossless == 1 ) {
TxMode = ONLY_4X4
} else {
tx_mode_select f(1)
if ( tx_mode_select ) {
TxMode = TX_MODE_SELECT
} else {
TxMode = TX_MODE_LARGEST
}
}
}

5.18.29. Skip mode params syntax

skip_mode_params( ) { Descriptor
if ( FrameIsIntra || FrameType == SWITCH_FRAME ) {
skipModeAllowed = 0
} else {
skipModeAllowed = 1
SkipModeFrame[ 0 ] = 0
SkipModeFrame[ 1 ] = NumTotalRefs > 1 ? 1 : 0
if ( NumTotalRefs > 1 ) {
curToRef0 = Abs(get_relative_dist(OrderHint,
RefOrderHint[ ref_frame_idx[ 0 ] ]))
curToRef1 = Abs(get_relative_dist(OrderHint,
RefOrderHint[ ref_frame_idx[ 1 ] ]))
if ( OrderHints[ 0 ] == RESTRICTED_OH ) {
curToRef0 = 0
}
if ( OrderHints[ 1 ] == RESTRICTED_OH ) {
curToRef1 = 0
}
if ( Abs(curToRef0 - curToRef1) > 1 ) {
SkipModeFrame[ 1 ] = 0
}
}
}
if ( skipModeAllowed ) {
skip_mode_present f(1)
} else {
skip_mode_present = 0
}
}

5.18.30. Frame reference mode syntax

frame_reference_mode( ) { Descriptor
if ( FrameIsIntra ) {
reference_select = 0
} else {
reference_select f(1)
}
}

5.18.31. Global motion params syntax

global_motion_params( ) { Descriptor
for ( ref = 0; ref < REFS_PER_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 || !enable_global_motion) {
return
}
use_global_motion f(1)
if ( !use_global_motion ) {
return
}
for ( i = 0; i < 6; i++ ) {
baseParams[ i ] = Default_Warp_Params[ i ]
}
baseDistance = 1
if ( FrameType == SWITCH_FRAME ) {
our_ref = NumTotalRefs
} else {
our_ref ns(NumTotalRefs + 1)
}
if ( our_ref != NumTotalRefs ) {
refIdx = ref_frame_idx[ our_ref ]
if ( RefNumTotalRefs[ refIdx ] > 0 ) {
their_ref ns( RefNumTotalRefs[ refIdx ] )
for ( i = 0; i < 6; i++ ) {
baseParams[ i ] = RefGmParams[ refIdx ][ their_ref ][ i ]
}
baseDistance = get_relative_dist(OrderHints[ our_ref ],
SavedOrderHints[ refIdx ][ their_ref ])
}
}
for ( ref = 0; ref < NumTotalRefs; ref++ ) {
dist = get_relative_dist(OrderHint,OrderHints[ ref ])
if ( dist == 0 || OrderHints[ ref ] == RESTRICTED_OH ) {
for ( i = 0; i < 6; i++ ) {
gm_params[ ref ][ i ] = Default_Warp_Params[ i ]
}
GmType[ ref ] = IDENTITY
} else {
for ( i = 0; i < 6; i++ ) {
params = scale_warp_model(baseParams, baseDistance, dist)
PrevGmParams[ ref ][ i ] = params[ i ]
}
is_global f(1)
if ( is_global ) {
is_rot_zoom f(1)
if ( is_rot_zoom ) {
type = ROTZOOM
} else {
type = AFFINE
}
} else {
type = IDENTITY
}
GmType[ ref ] = type
if ( type >= ROTZOOM ) {
read_global_param(ref,2)
read_global_param(ref,3)
if ( type == AFFINE ) {
read_global_param(ref,4)
read_global_param(ref,5)
} else {
gm_params[ ref ][ 4 ] = -gm_params[ ref ][ 3 ]
gm_params[ ref ][ 5 ] = gm_params[ ref ][ 2 ]
}
read_global_param(ref,0)
read_global_param(ref,1)
}
}
}
}

where Param_Shift, Param_Min, Param_Max, and scale_warp_model are defined as:

Param_Shift[ 6 ] = {    GM_TRANS_PREC_DIFF,    GM_TRANS_PREC_DIFF,   GM_ALPHA_PREC_DIFF,    GM_ALPHA_PREC_DIFF,    GM_ALPHA_PREC_DIFF,   GM_ALPHA_PREC_DIFF}Param_Min[ 6 ] = {     GM_TRANS_MIN,    GM_TRANS_MIN,    GM_ALPHA_MIN,    GM_ALPHA_MIN,    GM_ALPHA_MIN,    GM_ALPHA_MIN}Param_Max[ 6 ] = {    GM_TRANS_MAX,    GM_TRANS_MAX,    GM_ALPHA_MAX,    GM_ALPHA_MAX,    GM_ALPHA_MAX,    GM_ALPHA_MAX}
scale_warp_model(baseParams, baseDistance, dist) { Descriptor
if ( baseDistance == 0 ) {
return Default_Warp_Params
}
if ( baseDistance < 0 ) {
baseDistance = -baseDistance
dist = -dist
}
for ( i = 0; i < 6; i++ ) {
center = Default_Warp_Params[ i ]
limit = (1 << 22) - 1
input = Clip3( -limit, limit, baseParams[ i ] - center )
(divShift, divFactor) = resolve_divisor( baseDistance )
scaled = Round2Signed( input * divFactor, divShift )
output = Round2Signed( scaled * dist, Param_Shift[ i ] )
output = Clip3( Param_Min[i], Param_Max[i], output ) << Param_Shift[i]
params[ i ] = center + output
}
return params
}

5.18.32. Global param syntax

read_global_param( ref, idx ) { Descriptor
precBits = GM_ALPHA_PREC_BITS
mx = GM_ALPHA_MAX
if ( idx < 2 ) {
precBits = GM_TRANS_PREC_BITS
mx = GM_TRANS_MAX
}
precDiff = WARPEDMODEL_PREC_BITS - precBits
round = (idx % 3) == 2 ? (1 << WARPEDMODEL_PREC_BITS) : 0
sub = (idx % 3) == 2 ? (1 << precBits) : 0
r = (PrevGmParams[ ref ][ idx ] >> precDiff) - sub
gm_params[ ref ][ idx ] =
(decode_signed_subexp_with_ref( -mx, mx + 1, r, 3 ) << precDiff) + round
}

Note: When force_integer_mv is equal to 1, some fractional bits are still read for the translation components. However, these fractional bits will be discarded during the Setup Global MV process.

5.18.33. Decode signed subexp with ref syntax

decode_signed_subexp_with_ref( low, high, r, k ) { Descriptor
x = decode_unsigned_subexp_with_ref(high - low, r - low, k)
return x + low
}

5.18.34. Decode unsigned subexp with ref syntax

decode_unsigned_subexp_with_ref( mx, r, k ) { Descriptor
v = decode_subexp( mx, k )
if ( (r << 1) <= mx ) {
return inverse_recenter(r, v)
} else {
return mx - 1 - inverse_recenter(mx - 1 - r, v)
}
}

5.18.35. Decode subexp syntax

decode_subexp( numSyms, k ) { Descriptor
i = 0
mk = 0
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 f(1)
if ( subexp_more_bits ) {
i++
mk += a
} else {
subexp_bits f(b2)
return subexp_bits + mk
}
}
}
}

5.18.36. Inverse recenter function

inverse_recenter( r, v ) { Descriptor
if ( v > 2 * r ) {
return v
} else if ( v & 1 ) {
return r - ((v + 1) >> 1)
} else {
return r + (v >> 1)
}
}

5.18.37. Film grain config syntax

film_grain_config( ) { Descriptor
if ( !film_grain_params_present || ( !immediate_output_frame && !implicit_output_frame ) ) {
apply_grain = 0
} else if ( single_picture_header_flag ) {
apply_grain = 1
} else {
apply_grain f(1)
}
if ( apply_grain ) {
fgm_id f(3)
load_grain_model( fgm_id )
grain_seed f(16)
}
}

5.18.38. Film grain model syntax

film_grain_model( monochrome, subX, subY ) { Descriptor
if ( monochrome ) {
chroma_scaling_from_luma = 0
} else {
chroma_scaling_from_luma f(1)
}
num_y_points f(4)
if ( num_y_points > 0) {
point_value_increment_bits_minus1 f(3)
bitsIncr = point_value_increment_bits_minus1 + 1
point_scaling_bits_minus5 f(2)
bitsScal = point_scaling_bits_minus5 + 5
}
for ( i = 0; i < num_y_points; i++ ) {
point_y_value[ i ] f(bitsIncr)
if ( i > 0 ) {
point_y_value[ i ] += point_y_value[ i - 1 ]
}
point_y_scaling[ i ] f(bitsScal)
}
if ( monochrome || chroma_scaling_from_luma ) {
num_cb_points = 0
num_cr_points = 0
} else {
num_cb_points f(4)
if ( num_cb_points > 0 ) {
point_value_increment_bits_minus1 f(3)
bitsIncr = point_value_increment_bits_minus1 + 1
point_scaling_bits_minus5 f(2)
bitsScal = point_scaling_bits_minus5 + 5
}
for ( i = 0; i < num_cb_points; i++ ) {
point_cb_value[ i ] f(bitsIncr)
if ( i > 0 ) {
point_cb_value[ i ] += point_cb_value[ i - 1 ]
}
point_cb_scaling[ i ] f(bitsScal)
}
num_cr_points f(4)
if ( num_cr_points > 0 ) {
point_value_increment_bits_minus1 f(3)
bitsIncr = point_value_increment_bits_minus1 + 1
point_scaling_bits_minus5 f(2)
bitsScal = point_scaling_bits_minus5 + 5
}
for ( i = 0; i < num_cr_points; i++ ) {
point_cr_value[ i ] f(bitsIncr)
if ( i > 0 ) {
point_cr_value[ i ] += point_cr_value[ i - 1 ]
}
point_cr_scaling[ i ] f(bitsScal)
}
}
grain_scaling_minus_8 f(2)
ar_coeff_lag f(2)
numPosLuma = 2 * ar_coeff_lag * ( ar_coeff_lag + 1 )
if ( num_y_points ) {
bits_per_ar_coeff_y_minus5 f(2)
bitsCoef = bits_per_ar_coeff_y_minus5 + 5
numPosChroma = numPosLuma + 1
for ( i = 0; i < numPosLuma; i++ ) {
ar_coeffs_y_plus_128[ i ] f(bitsCoef)
}
} else {
numPosChroma = numPosLuma
}
if ( chroma_scaling_from_luma || num_cb_points ) {
bits_per_ar_coeff_cb_minus5 f(2)
bitsCoef = bits_per_ar_coeff_cb_minus5 + 5
for ( i = 0; i < numPosChroma; i++ ) {
ar_coeffs_cb_plus_128[ i ] f(bitsCoef)
}
}
if ( chroma_scaling_from_luma || num_cr_points ) {
bits_per_ar_coeff_cr_minus5 f(2)
bitsCoef = bits_per_ar_coeff_cr_minus5 + 5
for ( i = 0; i < numPosChroma; i++ ) {
ar_coeffs_cr_plus_128[ i ] f(bitsCoef)
}
}
ar_coeff_shift_minus_6 f(2)
grain_scale_shift f(2)
if ( num_cb_points ) {
cb_mult f(8)
cb_luma_mult f(8)
cb_offset f(9)
}
if ( num_cr_points ) {
cr_mult f(8)
cr_luma_mult f(8)
cr_offset f(9)
}
overlap_flag f(1)
clip_to_restricted_range f(1)
if ( clip_to_restricted_range ) {
mc_identity f(1)
} else {
mc_identity = 0
}
film_grain_block_size f(1)
}

5.19. Tile group OBU syntax

tile_group_obu( sz ) { Descriptor
startBitPos = get_position( )
is_first_tile_group f(1)
if ( obu_type == OBU_SWITCH || obu_type == OBU_RAS_FRAME ) {
restricted_prediction_switch f(1)
} else {
restricted_prediction_switch = 0
}
if ( is_first_tile_group ) {
uncompressed_header_flag = 1
FrameSymbolCount = 0
} else {
uncompressed_header_flag f(1)
}
if ( uncompressed_header_flag ) {
frame_header( is_first_tile_group )
}
if ( bru_inactive ) {
headerBits = get_position( ) - startBitPos
remainingBits = sz * 8 - headerBits
trailing_bits( remainingBits )
return
}
NumTiles = TileCols * TileRows
tile_start_and_end_present_flag = 0
if ( NumTiles > 1 ) {
tile_start_and_end_present_flag f(1)
}
if ( NumTiles == 1 || !tile_start_and_end_present_flag ) {
tg_start = 0
tg_end = NumTiles - 1
} else {
tileBits = TileColsLog2 + TileRowsLog2
tg_start f(tileBits)
tg_end f(tileBits)
}
if ( use_bru ) {
if ( NumTiles > 1 ) {
for ( TileNum = tg_start; TileNum <= tg_end; TileNum++ ) {
tileRow = TileNum / TileCols
tileCol = TileNum % TileCols
bru_tile_active f(1)
BruTileActives[ tileRow ][ tileCol ] = bru_tile_active
}
} else {
BruTileActives[ 0 ][ 0 ] = 1
}
}
byte_alignment( )
endBitPos = get_position( )
headerBytes = (endBitPos - startBitPos) / 8
sz -= headerBytes
tile_group_payload( sz )
}

5.20. Tile group payload syntax

5.20.1. General tile group payload syntax

tile_group_payload( sz ) { Descriptor
for ( TileNum = tg_start; TileNum <= tg_end; TileNum++ ) {
tileRow = TileNum / TileCols
tileCol = TileNum % TileCols
lastTile = TileNum == tg_end
if ( lastTile ) {
tileSize = sz
} else if ( !IsBridge ) {
tile_size_minus_1 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 ]
BruTileActive = use_bru ? BruTileActives[ tileRow ][ tileCol ] : 0
align = Num_4x4_Blocks_High[ SbSize ]
shift = Mi_Height_Log2[ SbSize ]
for( r = MiRowStart; r < ((MiRowEnd + align - 1) >> shift) << shift;
r++) {
for( c = MiColStart; c < ((MiColEnd + align - 1) >> shift) << shift;
c++) {
IBCCoded[ r ][ c ] = 0
}
}
CurrentQIndex = base_q_idx
if ( !IsBridge ) {
init_symbol( tileSize )
}
decode_tile( )
if ( !IsBridge ) {
exit_symbol( )
}
}
if ( tg_end == NumTiles - 1 ) {
if ( !IsBridge ) {
frame_end_update_cdf( )
}
decode_frame_wrapup( )
SeenFrameHeader = 0
}
}

5.20.2. Decode tile syntax

decode_tile( ) { Descriptor
clear_above_context( )
for ( i = 0; i < FRAME_LF_COUNT; i++ ) {
DeltaLF[ i ] = 0
}
for ( plane = 0; plane < WIENER_NS_PLANES; plane++ ) {
for ( c = 0; c < WIENER_NS_CLASSES; c++ ) {
for ( i = 0; i < WIENER_NS_CHROMA_COEFFS; i++ ) {
min = Wiener_Ns_Taps_Min[ plane != 0 ][ i ]
k = Wiener_Ns_Taps_K[ plane != 0 ][ i ]
RefLrWienerNs[ plane ][ c ][ 0 ][ i ] = min + ((1 << k) >> 1)
}
WienerNsPtr[ plane ][ c ] = 0
WienerNsBankSize[ plane ][ c ] = 0
}
}
sbSize4 = Num_4x4_Blocks_Wide[ SbSize ]
for ( r = MiRowStart; r < MiRowEnd; r += sbSize4 ) {
clear_left_context( )
for ( i = 0; i < IBC_NUM_BUFFERS; i++ ) {
IBCBufferValid[ i ] = 0
}
IBCBufferCurRow = r >> (IBC_BUFFER_SIZE_LOG2 - MI_SIZE_LOG2)
IBCBufferCurCol = 0
for ( c = MiColStart; c < MiColEnd; c += sbSize4 ) {
reset_refmv_bank( r, c, sbSize4, r == MiRowStart )
ReadDeltas = delta_q_present
clear_cdef( r, c )
clear_block_decoded_flags( r, c, sbSize4 )
if ( IsBridge ) {
bru_mode = BRU_INACTIVE
} else if ( BruTileActive ) {
bru_mode S()
} else {
bru_mode = use_bru ? BRU_INACTIVE : BRU_ACTIVE
}
BruModes[ r ][ c ] = bru_mode
RegionType = MIXED_REGION
TreeType = SHARED_PART
PlaneStart = 0
PlaneEnd = NumPlanes
decode_partition( r, c, SbSize, BLOCK_INVALID, 0, 1,
enable_extended_sdp && !FrameIsIntra )
}
}
}

where Wiener_Ns_Taps_Min and Wiener_Ns_Taps_K are constant lookup tables specified as:

Wiener_Ns_Taps_Min[ 2 ][ 18 ] = {    {-24, -24, -14 , -14, -16, -16, -8,   -8,  -8,  -8, -8, -8, -8, -8, -8, -8,     -8, -8},    {-24, -24, -14 , -14, -16, -16, -16, -16, -16, -16, -8, -8, -8, -8, -8, -8,     -8, -8}}Wiener_Ns_Taps_K[ 2 ][ 18 ] = {    {6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4},    {6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4}}

5.20.3. Reset reference motion vector bank function

reset_refmv_bank( r, c, sbSize4, topRow ) { Descriptor
WarpBankHits = 0
RefMvBankHits = 0
RefMvRemainHits = 0
RefMvUnitHits = 0
if ( FrameIsIntra || topRow ) {
return
}
rowHits = 0
candRow = r - 1
candCol = c
while ( candCol < MiCols && candCol < c + sbSize4 && rowHits < 4 ) {
candCol2 = (candCol >> 1) << 1
if ( IsInters[ candRow ][ candCol2 ] ) {
rowHits++
update_ref_mv_bank( RefFrames[ candRow ][ candCol2 ],
Mvs[ candRow ][ candCol2 ], CwpIdxs[ candRow ][ candCol2 ],0)
if ( MotionModes[ candRow ][ candCol2 ] >= LOCALWARP ) {
update_warp_param_bank( RefFrames[ candRow ][ candCol2 ],
WarpParamsValid[ candRow ][ candCol2 ],
WarpParams[ candRow ][ candCol2 ],1)
}
}
candSize = MiSizes[ 0 ][ candRow ][ candCol2 ]
candCol += Num_4x4_Blocks_Wide[ candSize ]
}
}

5.20.4. Clear block decoded flags function

clear_block_decoded_flags( r, c, sbSize4 ) { Descriptor
for ( plane = 0; plane < NumPlanes; plane++ ) {
subX = (plane > 0) ? SubsamplingX : 0
subY = (plane > 0) ? SubsamplingY : 0
sbWidth4 = ( MiColEnd - c ) >> subX
sbHeight4 = ( MiRowEnd - r ) >> subY
for ( y = -1; y <= ( sbSize4 >> subY ); y++ ) {
for ( x = -1; x <= ( (2 * 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.20.5. Decode partition syntax

decode_partition( r, c, bSize, parentSize, chromaOffset, hasChroma, extendedSdpAllowed ) { Descriptor
if ( r >= MiRows || c >= MiCols ) {
for ( y = 0; y < Num_4x4_Blocks_High[ bSize ]; y++ ) {
for ( x = 0; x < Num_4x4_Blocks_Wide[ bSize ]; x++ ) {
IBCCoded[ r + y ][ x + c ] = 1
}
}
widthChunks = Max( 1, Block_Width[ bSize ] >> 6 )
heightChunks = Max( 1, Block_Height[ bSize ] >> 6 )
for ( chunkY = 0; chunkY < heightChunks; chunkY++ ) {
for ( chunkX = 0; chunkX < widthChunks; chunkX++ ) {
miRowChunk = r + ( chunkY << 4 )
miColChunk = c + ( chunkX << 4 )
update_ibc_buffers(miRowChunk, miColChunk)
}
}
return
}
if ( enable_sdp && TreeType == SHARED_PART &&
bSize == BLOCK_64X64 && FrameIsIntra ) {
TreeType = LUMA_PART
PlaneStart = 0
PlaneEnd = 1
decode_partition( r, c, BLOCK_64X64, parentSize, 0, 1, 0 )
TreeType = CHROMA_PART
PlaneStart = 1
PlaneEnd = NumPlanes
decode_partition( r, c, BLOCK_64X64, parentSize, 0, 1, 0 )
TreeType = SHARED_PART
PlaneStart = 0
PlaneEnd = NumPlanes
return
}
if ( SbSize == bSize ) {
read_lr(r, c, SbSize)
}
AvailU = is_inside( r - 1, c )
AvailL = is_inside( r, c - 1 )
num4x4wide = Num_4x4_Blocks_Wide[ bSize ]
halfBlock4x4wide = num4x4wide >> 1
num4x4high = Num_4x4_Blocks_High[ bSize ]
halfBlock4x4high = num4x4high >> 1
partition = read_partition(r, c, bSize, chromaOffset, hasChroma)
subSize = Partition_Subsize[ partition ][ bSize ]
usingSdp = 0
if ( bSize != SbSize && extendedSdpAllowed &&
TreeType == SHARED_PART &&
is_bsize_allowed_for_extended_sdp(bSize, partition) &&
bru_mode == BRU_ACTIVE ) {
region_type S()
if ( region_type == INTRA_REGION ) {
TreeType = LUMA_PART
RegionType = INTRA_REGION
PlaneStart = 0
PlaneEnd = 1
usingSdp = 1
}
}
extendedSdpAllowed = extendedSdpAllowed && Block_Width[ subSize ] > 4 &&
Block_Height[ subSize ] > 4
if ( partition == PARTITION_HORZ_3 || partition == PARTITION_VERT_3 ) {
subSize2 = H_Partition_Midsize[ bSize ]
extendedSdpAllowed = extendedSdpAllowed &&
Block_Width[ subSize2 ] > 4 &&
Block_Height[ subSize2 ] > 4
}
if ( SbSize == BLOCK_128X128 ) {
if ( bSize == BLOCK_128X128 ) {
AllowExtraIBCRange = partition == PARTITION_HORZ ||
partition == PARTITION_SPLIT
}
} else {
AllowExtraIBCRange = 0
}
if ( FrameIsIntra ) {
if ( TreeType == LUMA_PART && bSize == BLOCK_64X64 ) {
TopLumaHorz = partition == PARTITION_HORZ ||
partition == PARTITION_HORZ_3
TopLumaVert = partition == PARTITION_VERT ||
partition == PARTITION_VERT_3
TopLumaUnevenHorz = partition == PARTITION_HORZ_4A ||
partition == PARTITION_HORZ_4B
TopLumaUnevenVert = partition == PARTITION_VERT_4A ||
partition == PARTITION_VERT_4B
ChromaFollowsLuma = (partition == PARTITION_NONE) ||
TopLumaHorz || TopLumaVert
LumaPartitions[ r ][ c ] = partition
}
thisHorz = partition == PARTITION_HORZ ||
partition == PARTITION_HORZ_3 ||
partition == PARTITION_HORZ_4A ||
partition == PARTITION_HORZ_4B
thisVert = partition == PARTITION_VERT ||
partition == PARTITION_VERT_3 ||
partition == PARTITION_VERT_4A ||
partition == PARTITION_VERT_4B
if ( TreeType == CHROMA_PART && bSize == BLOCK_64X64 ) {
if ( ChromaFollowsLuma ||
partition == PARTITION_NONE ||
(TopLumaHorz || TopLumaUnevenHorz) && thisHorz ||
(TopLumaVert || TopLumaUnevenVert) && thisVert ) {
CflAllowedInSdp = 1
} else {
CflAllowedInSdp = 0
}
}
if ( TreeType == LUMA_PART && parentSize == BLOCK_64X64 ) {
if ( partition == PARTITION_NONE ||
( TopLumaHorz && thisHorz ) ||
( TopLumaVert && thisVert ) ) {
ChromaFollowsLuma = 0
}
}
}
if ( !chromaOffset && hasChroma ) {
chromaOffset = is_chroma_offset_for_partition( partition, bSize )
ChromaMiRow = r
ChromaMiCol = c
ChromaMiSize = bSize
}
if ( partition == PARTITION_NONE ) {
HasChroma = hasChroma && NumPlanes > 1 && TreeType != LUMA_PART
decode_block( r, c, subSize )
} else if ( partition == PARTITION_HORZ ) {
decode_partition( r, c, subSize, bSize, chromaOffset,
hasChroma && !chromaOffset, extendedSdpAllowed )
decode_partition( r + halfBlock4x4high, c, subSize, bSize, chromaOffset,
hasChroma, extendedSdpAllowed )
} else if ( partition == PARTITION_VERT ) {
decode_partition( r, c, subSize, bSize, chromaOffset,
hasChroma && !chromaOffset, extendedSdpAllowed )
decode_partition( r, c + halfBlock4x4wide, subSize, bSize, chromaOffset,
hasChroma, extendedSdpAllowed )
} else if ( partition == PARTITION_HORZ_3 ) {
decode_partition( r, c, subSize, bSize, chromaOffset,
hasChroma && !chromaOffset, extendedSdpAllowed )
middleChroma = bSize == BLOCK_8X32 && hasChroma && SubsamplingX
if ( middleChroma ) {
ChromaMiRow = r + (halfBlock4x4high >> 1)
ChromaMiCol = c
ChromaMiSize = Partition_Subsize[ PARTITION_HORZ ][ bSize ]
}
decode_partition( r + (halfBlock4x4high >> 1), c,
H_Partition_Midsize[ bSize ], bSize,
chromaOffset || middleChroma,
hasChroma && !chromaOffset && !middleChroma,
extendedSdpAllowed )
decode_partition( r + (halfBlock4x4high >> 1), c + halfBlock4x4wide,
H_Partition_Midsize[ bSize ], bSize,
chromaOffset || middleChroma,
hasChroma && !chromaOffset, extendedSdpAllowed )
decode_partition( r + 3 * (halfBlock4x4high >> 1), c,
subSize, bSize, chromaOffset,
hasChroma, extendedSdpAllowed )
} else if ( partition == PARTITION_HORZ_4A ) {
bSizeBig = Partition_Subsize[ PARTITION_HORZ ][ bSize ]
bsizeMed = Partition_Subsize[ PARTITION_HORZ ][ bSizeBig ]
decode_partition( r, c, subSize, bSize,
chromaOffset, hasChroma && !chromaOffset,
extendedSdpAllowed )
decode_partition( r + (num4x4high >> 3), c, bsizeMed, bSize,
chromaOffset, hasChroma && !chromaOffset,
extendedSdpAllowed )
decode_partition( r + 3 * (num4x4high >> 3), c, bSizeBig, bSize,
chromaOffset, hasChroma && !chromaOffset,
extendedSdpAllowed )
decode_partition( r + 7 * (num4x4high >> 3), c, subSize, bSize,
chromaOffset, hasChroma, extendedSdpAllowed )
} else if ( partition == PARTITION_HORZ_4B ) {
bSizeBig = Partition_Subsize[ PARTITION_HORZ ][ bSize ]
bsizeMed = Partition_Subsize[ PARTITION_HORZ ][ bSizeBig ]
decode_partition( r, c, subSize, bSize,
chromaOffset, hasChroma && !chromaOffset,
extendedSdpAllowed )
decode_partition( r + (num4x4high >> 3), c, bSizeBig, bSize,
chromaOffset, hasChroma && !chromaOffset,
extendedSdpAllowed )
decode_partition( r + 5 * (num4x4high >> 3), c, bsizeMed, bSize,
chromaOffset, hasChroma && !chromaOffset,
extendedSdpAllowed )
decode_partition( r + 7 * (num4x4high >> 3), c, subSize, bSize,
chromaOffset, hasChroma, extendedSdpAllowed )
} else if ( partition == PARTITION_VERT_4A ) {
bSizeBig = Partition_Subsize[ PARTITION_VERT ][ bSize ]
bsizeMed = Partition_Subsize[ PARTITION_VERT ][ bSizeBig ]
decode_partition( r, c, subSize, bSize,
chromaOffset, hasChroma && !chromaOffset,
extendedSdpAllowed )
decode_partition( r, c + (num4x4wide >> 3), bsizeMed, bSize,
chromaOffset, hasChroma && !chromaOffset,
extendedSdpAllowed )
decode_partition( r, c + 3 * (num4x4wide >> 3), bSizeBig, bSize,
chromaOffset, hasChroma && !chromaOffset,
extendedSdpAllowed )
decode_partition( r, c + 7 * (num4x4wide >> 3), subSize, bSize,
chromaOffset, hasChroma, extendedSdpAllowed )
} else if ( partition == PARTITION_VERT_4B ) {
bSizeBig = Partition_Subsize[ PARTITION_VERT ][ bSize ]
bsizeMed = Partition_Subsize[ PARTITION_VERT ][ bSizeBig ]
decode_partition( r, c, subSize, bSize,
chromaOffset, hasChroma && !chromaOffset,
extendedSdpAllowed )
decode_partition( r, c + (num4x4wide >> 3), bSizeBig, bSize,
chromaOffset, hasChroma && !chromaOffset,
extendedSdpAllowed )
decode_partition( r, c + 5 * (num4x4wide >> 3), bsizeMed, bSize,
chromaOffset, hasChroma && !chromaOffset,
extendedSdpAllowed )
decode_partition( r, c + 7 * (num4x4wide >> 3), subSize, bSize,
chromaOffset, hasChroma, extendedSdpAllowed )
} else if ( partition == PARTITION_SPLIT ) {
decode_partition( r, c, subSize, bSize, 0,
hasChroma, extendedSdpAllowed )
decode_partition( r, c + halfBlock4x4wide, subSize, bSize, 0,
hasChroma, extendedSdpAllowed )
decode_partition( r + halfBlock4x4high, c, subSize, bSize, 0,
hasChroma, extendedSdpAllowed )
decode_partition( r + halfBlock4x4high, c + halfBlock4x4wide,
subSize, bSize, 0, hasChroma, extendedSdpAllowed )
} else {
decode_partition( r, c, subSize, bSize, chromaOffset,
hasChroma && !chromaOffset, extendedSdpAllowed )
middleChroma = bSize == BLOCK_32X8 && hasChroma && SubsamplingY
if ( middleChroma ) {
ChromaMiRow = r
ChromaMiCol = c + (halfBlock4x4wide >> 1)
ChromaMiSize = Partition_Subsize[ PARTITION_VERT ][ bSize ]
}
decode_partition( r, c + (halfBlock4x4wide >> 1),
H_Partition_Midsize[ bSize ], bSize,
chromaOffset || middleChroma,
hasChroma && !chromaOffset && !middleChroma,
extendedSdpAllowed )
decode_partition( r + halfBlock4x4high, c + (halfBlock4x4wide >> 1),
H_Partition_Midsize[ bSize ], bSize,
chromaOffset || middleChroma,
hasChroma && !chromaOffset, extendedSdpAllowed )
decode_partition( r, c + 3 * (halfBlock4x4wide >> 1),
subSize, bSize, chromaOffset,
hasChroma, extendedSdpAllowed )
}
if ( FrameIsIntra && TreeType == LUMA_PART && bSize == BLOCK_64X64 ) {
ChromaPartitionKnown[ r ][ c ] = ChromaFollowsLuma
}
if ( usingSdp ) {
TreeType = CHROMA_PART
HasChroma = 1
PlaneStart = 1
PlaneEnd = NumPlanes
ChromaMiRow = r
ChromaMiCol = c
ChromaMiSize = bSize
AvailU = is_inside( r - 1, c )
AvailL = is_inside( r, c - 1 )
decode_block( r, c, bSize )
TreeType = SHARED_PART
PlaneStart = 0
PlaneEnd = NumPlanes
RegionType = MIXED_REGION
}
}

The function is_bsize_allowed_for_extended_sdp is defined as:

is_bsize_allowed_for_extended_sdp(bSize, partition) { Descriptor
bw = Block_Width[ bSize ]
bh = Block_Height[ bSize ]
return bw <= INTER_SDP_MAX_BLOCK_SIZE && bh <= INTER_SDP_MAX_BLOCK_SIZE &&
bw >= 8 && bh >= 8 &&
partition < PARTITION_HORZ_4A && partition != PARTITION_NONE
}

5.20.6. Read partition syntax

Rect_Part_Table[ 2 ][ 2 ][ NUM_UNEVEN_4WAY_PARTS ][ NUM_RECT_PARTS ] = {    {        {            { PARTITION_HORZ, PARTITION_VERT },            { PARTITION_HORZ, PARTITION_VERT },        },        {            { PARTITION_HORZ, PARTITION_VERT },            { PARTITION_HORZ, PARTITION_VERT },        },    },    {        {            { PARTITION_HORZ_3, PARTITION_VERT_3 },            { PARTITION_HORZ_3, PARTITION_VERT_3 },        },        {            { PARTITION_HORZ_4A, PARTITION_VERT_4A },            { PARTITION_HORZ_4B, PARTITION_VERT_4B },        }    }}
read_partition(r, c, bSize, chromaOffset, hasChroma) { Descriptor
(implied,partition) = partition_implied(r, c, bSize)
(numAllowed, allowed) = init_allowed_partitions( r, c, bSize,
chromaOffset, hasChroma )
if ( implied && allowed[ partition ] ) {
return partition
}
if ( numAllowed == 1 ) {
for ( p = 0; p < EXT_PARTITION_TYPES; p++ ) {
if ( allowed[ p ] ) {
return p
}
}
}
if ( bru_mode != BRU_ACTIVE ) {
return PARTITION_NONE
}
if ( allowed[ PARTITION_NONE ] ) {
do_split S()
if ( !do_split ) {
return PARTITION_NONE
}
}
if ( allowed[ PARTITION_SPLIT ] ) {
do_square_split S()
if ( do_square_split ) {
return PARTITION_SPLIT
}
}
rectType = rect_type_implied_by_bsize( bSize )
if ( rectType == RECT_INVALID ) {
allowHorz = ( allowed[ PARTITION_HORZ ] ||
allowed[ PARTITION_HORZ_3 ] ||
allowed[ PARTITION_HORZ_4A ] ||
allowed[ PARTITION_HORZ_4B ] )
allowVert = ( allowed[ PARTITION_VERT ] ||
allowed[ PARTITION_VERT_3 ] ||
allowed[ PARTITION_VERT_4A ] ||
allowed[ PARTITION_VERT_4B ] )
if ( !allowHorz ) {
rectType = RECT_VERT
} else if ( !allowVert ) {
rectType = RECT_HORZ
}
}
if ( rectType == RECT_INVALID ) {
rect_type S()
rectType = rect_type
}
if ( rectType == RECT_HORZ ) {
nonExtAllowed = allowed[ PARTITION_HORZ ]
extAllowed3 = allowed[ PARTITION_HORZ_3 ]
extAllowed4 = allowed[ PARTITION_HORZ_4A ] ||
allowed[ PARTITION_HORZ_4B ]
} else {
nonExtAllowed = allowed[ PARTITION_VERT ]
extAllowed3 = allowed[ PARTITION_VERT_3 ]
extAllowed4 = allowed[ PARTITION_VERT_4A ] ||
allowed[ PARTITION_VERT_4B ]
}
if ( nonExtAllowed && ( extAllowed3 || extAllowed4 ) ) {
do_ext_partition S()
} else {
do_ext_partition = extAllowed3 || extAllowed4
}
do_uneven_4way_partition = 0
uneven_4way_partition_type = 0
if ( do_ext_partition ) {
if ( extAllowed3 && extAllowed4 ) {
do_uneven_4way_partition S()
} else {
do_uneven_4way_partition = extAllowed4
}
if ( do_uneven_4way_partition ) {
uneven_4way_partition_type L(1)
}
}
return Rect_Part_Table[ do_ext_partition ][ do_uneven_4way_partition ]
[ uneven_4way_partition_type ][ rectType ]
}

where init_allowed_partitions, is_partition_allowed, is_chroma_offset_for_partition, is_chroma_offset_for_subsize, check_chroma, block_coded, rect_type_implied_by_bsize, is_ext_partition_allowed, partition_implied_at_bo undary, partition_implied, and is_uneven_4way_partition_allowed are functions defined as:

block_coded(r,c) { Descriptor
return r < MiRows && c < MiCols
}
check_chroma(bSize) { Descriptor
if ( get_plane_residual_size( bSize, 1 ) == BLOCK_INVALID ) {
return 0
}
return ( TreeType == LUMA_PART &&
Block_Width[ bSize ] >= 64 &&
Block_Height[ bSize ] >= 64 )
}
is_chroma_offset_for_subsize( subSize ) { Descriptor
if ( SubsamplingY && Mi_Height_Log2[ subSize ] == 0 ) {
return 1
}
if ( SubsamplingX && Mi_Width_Log2[ subSize ] == 0 ) {
return 1
}
return 0
}
is_chroma_offset_for_partition( p, bSize ) { Descriptor
if ( is_chroma_offset_for_subsize( Partition_Subsize[ p ][ bSize ] ) ) {
return 1
}
if ( p == PARTITION_HORZ_3 ) {
middleChroma = bSize == BLOCK_8X32 && SubsamplingX
if ( !middleChroma ) {
if ( is_chroma_offset_for_subsize( H_Partition_Midsize[bSize] ) ) {
return 1
}
}
}
return 0
}
is_partition_allowed(r,c,p,bSize,chromaOffset,hasChroma,numPlanes) { Descriptor
subSize = Partition_Subsize[ p ][ bSize ]
if ( subSize == BLOCK_INVALID ) {
return 0
}
if ( !FrameIsIntra && RegionType == MIXED_REGION && subSize == BLOCK_4X4 ) {
return 0
}
rectType = rect_type_implied_by_bsize( bSize )
if ( rectType == RECT_VERT &&
(p == PARTITION_HORZ ||
p == PARTITION_HORZ_3 ||
p == PARTITION_HORZ_4A ||
p == PARTITION_HORZ_4B) ) {
return 0
}
if ( rectType == RECT_HORZ &&
(p == PARTITION_VERT ||
p == PARTITION_VERT_3 ||
p == PARTITION_VERT_4A ||
p == PARTITION_VERT_4B) ) {
return 0
}
bw = Block_Width[ subSize ]
bh = Block_Height[ subSize ]
if ( bw > bh * MaxPbAspectRatio || bh > bw * MaxPbAspectRatio ) {
if (p == PARTITION_NONE) {
return 0
}
if ( bw >= bh * 8 || bh >= bw * 8 ) {
return 0
}
}
num4x4wide = Num_4x4_Blocks_Wide[ bSize ]
num4x4high = Num_4x4_Blocks_High[ bSize ]
halfBlock4x4wide = num4x4wide >> 1
halfBlock4x4high = num4x4high >> 1
if ( hasChroma && TreeType != CHROMA_PART ) {
if ( !chromaOffset ) {
chromaOffset = is_chroma_offset_for_partition( p, bSize )
}
}
if ( (hasChroma && !chromaOffset && TreeType != LUMA_PART) ||
check_chroma(bSize) ) {
if ( get_plane_residual_size( subSize, 1 ) == BLOCK_INVALID ) {
return 0
}
}
if ( p == PARTITION_HORZ_3 ) {
if ( !is_ext_partition_allowed( bSize, RECT_HORZ) ) {
return 0
}
} else if ( p == PARTITION_VERT_3 ) {
if ( !is_ext_partition_allowed( bSize, RECT_VERT) ) {
return 0
}
} else if ( p == PARTITION_HORZ_4A || p == PARTITION_HORZ_4B ) {
if ( !is_ext_partition_allowed( bSize, RECT_HORZ) ||
!is_uneven_4way_partition_allowed( bSize, RECT_HORZ ) ) {
return 0
}
} else if ( p == PARTITION_VERT_4A || p == PARTITION_VERT_4B ) {
if ( !is_ext_partition_allowed( bSize, RECT_VERT) ||
!is_uneven_4way_partition_allowed( bSize, RECT_VERT ) ) {
return 0
}
} else if ( p == PARTITION_NONE ) {
hasRows = ( r + halfBlock4x4high ) < MiRows
hasCols = ( c + halfBlock4x4wide ) < MiCols
if ( (TreeType != CHROMA_PART || bSize != BLOCK_8X8) &&
(!hasRows || !hasCols) ) {
return 0
}
}
if ( hasChroma && TreeType != LUMA_PART && numPlanes > 1 ) {
if ( chromaOffset ) {
if ( p == PARTITION_HORZ ) {
return block_coded( r + halfBlock4x4high, c )
} else if ( p == PARTITION_VERT ) {
return block_coded( r, c + halfBlock4x4wide )
} else if ( p == PARTITION_HORZ_3 ) {
return block_coded( r + 3 * (halfBlock4x4high >> 1), c )
} else if ( p == PARTITION_VERT_3 ) {
return block_coded( r, c + 3 * (halfBlock4x4wide >> 1) )
} else if ( p == PARTITION_HORZ_4A || p == PARTITION_HORZ_4B ) {
h4 = Num_4x4_Blocks_High[ subSize ]
return block_coded( r + 7 * h4, c )
} else if ( p == PARTITION_VERT_4A || p == PARTITION_VERT_4B ) {
w4 = Num_4x4_Blocks_Wide[ subSize ]
return block_coded( r, c + 7 * w4 )
}
}
}
return 1
}
init_allowed_partitions(r,c,bSize,chromaOffset,hasChroma) { Descriptor
numAllowed = 0
for ( p = 0; p < EXT_PARTITION_TYPES; p++ ) {
good = is_partition_allowed(r,c,p,bSize,chromaOffset,
hasChroma,NumPlanes)
numAllowed += good
allowed[ p ] = good
}
if ( numAllowed == 0 ) {
allowed[ PARTITION_NONE ] = 1
numAllowed = 1
}
return (numAllowed,allowed)
}
rect_type_implied_by_bsize(bSize) { Descriptor
if ( bSize == BLOCK_4X8 || bSize == BLOCK_64X128 ||
bSize == BLOCK_128X256 || bSize == BLOCK_4X16 ) {
return RECT_HORZ
}
if ( bSize == BLOCK_8X4 || bSize == BLOCK_128X64 ||
bSize == BLOCK_256X128 || bSize == BLOCK_16X4 ) {
return RECT_VERT
}
if ( TreeType == CHROMA_PART ) {
if ( bSize == BLOCK_8X16 || bSize == BLOCK_8X32 ) {
return RECT_HORZ
}
if ( bSize == BLOCK_16X8 || bSize == BLOCK_32X8 ) {
return RECT_VERT
}
}
return RECT_INVALID
}
is_ext_partition_allowed(bSize, rectType) { Descriptor
if ( !enable_ext_partitions ) {
return 0
}
return TreeType != CHROMA_PART ||
(rectType == RECT_HORZ &&
Block_Height[ bSize ] > 16 && Block_Width[ bSize ] > 8) ||
(rectType == RECT_VERT &&
Block_Width[ bSize ] > 16 && Block_Height[ bSize ] > 8)
}
partition_implied_at_boundary(r, c, bSize) { Descriptor
numWide4x4 = Num_4x4_Blocks_Wide[ bSize ]
numHigh4x4 = Num_4x4_Blocks_High[ bSize ]
hasRows = ( r + (numHigh4x4 >> 1) ) < MiRows
hasCols = ( c + (numWide4x4 >> 1) ) < MiCols
if ( hasRows && hasCols ) {
return (0, PARTITION_NONE)
}
impliedPartition = PARTITION_NONE
if ( numWide4x4 == numHigh4x4 ) {
impliedPartition = hasRows ? PARTITION_VERT : PARTITION_HORZ
} else if ( numHigh4x4 > numWide4x4 ) {
if ( !hasRows ) {
impliedPartition = PARTITION_HORZ
} else {
subHasCols = ( c + (numWide4x4 >> 2) ) < MiCols
if ( numWide4x4 >= 4 && !subHasCols ) {
impliedPartition = PARTITION_HORZ
}
}
} else {
if ( !hasCols ) {
impliedPartition = PARTITION_VERT
} else {
subHasRows = ( r + (numHigh4x4 >> 2) ) < MiRows
if ( numHigh4x4 >= 4 && !subHasRows ) {
impliedPartition = PARTITION_VERT
}
}
}
return (impliedPartition != PARTITION_NONE, impliedPartition)
}
partition_implied(r, c, bSize) { Descriptor
if ( bSize == BLOCK_4X4 || bSize >= BLOCK_4X32 ) {
return (1, PARTITION_NONE)
}
if ( TreeType == CHROMA_PART && bSize == BLOCK_8X8 ) {
return (1, PARTITION_NONE)
}
if ( TreeType == CHROMA_PART && bSize == BLOCK_64X64 &&
ChromaPartitionKnown[ r ][ c ] ) {
return (1, LumaPartitions[ r ][ c ])
}
return partition_implied_at_boundary(r, c, bSize)
}
is_uneven_4way_partition_allowed(bSize, rectType) { Descriptor
if ( !enable_uneven_4way_partitions ) {
return 0
}
return TreeType != CHROMA_PART ||
(rectType == RECT_HORZ && Block_Height[ bSize ] == 64) ||
(rectType == RECT_VERT && Block_Width[ bSize ] == 64)
}

5.20.7. Decode block syntax

decode_block( r, c, subSize ) { Descriptor
MiRow = r
MiCol = c
MiSize = subSize
bw4 = Num_4x4_Blocks_Wide[ subSize ]
bh4 = Num_4x4_Blocks_High[ subSize ]
update_ibc_buffers(r, c)
for ( y = 0; y < bh4; y++ ) {
for ( x = 0; x < bw4; x++ ) {
IBCCoded[ r + y ][ x + c ] = 1
}
}
if ( HasChroma ) {
AvailUChroma = is_inside( ChromaMiRow - 1, ChromaMiCol )
AvailLChroma = is_inside( ChromaMiRow, ChromaMiCol - 1 )
} else {
AvailUChroma = 0
AvailLChroma = 0
}
NNum = 0
NNumBuf = 0
add_neighbor( r + bh4 - 1, c - 1 )
add_neighbor( r - 1, c + bw4 - 1 )
add_neighbor( r, c - 1 )
add_neighbor( r - 1, c )
for ( n = 0; n < NNumBuf; n++ ) {
for ( list = 0; list < 2; list++ ) {
NRefFrame[ n ][ list ] =
RefFrames[ NPosBuf[ n ][ 0 ] ][ NPosBuf[ n ][ 1 ] ][ list ]
}
NIntra[ n ] = !IsInters[ NPosBuf[ n ][ 0 ] ][ NPosBuf[ n ][ 1 ] ]
NSingle[ n ] = !is_inter_ref_frame( NRefFrame[ n ][ 1 ] )
}
for ( refList=0;refList<2;refList++ ) {
LocalValid[ refList ] = 0
}
mode_info( )
palette_tokens( )
if ( TreeType != CHROMA_PART ) {
read_block_tx_size( )
}
if ( skip_flag ) {
reset_block_context( bw4, bh4 )
}
isCompound = is_inter_ref_frame(RefFrame[ 1 ])
for ( y = 0; y < bh4; y++ ) {
for ( x = 0; x < bw4; x++ ) {
if ( PlaneStart == 0 ) {
IntraJointModes[ r + y ][ c + x ] = IntraJointMode
YModes [ r + y ][ c + x ] = YMode
AngleDeltaYs[ r + y ][ c + x ] = AngleDeltaY
for ( refList = 0; refList < 2; refList++ ) {
RefFrames[ r + y ][ c + x ][ refList ] = RefFrame[ refList ]
}
MiSizes[ 0 ][ r + y ][ c + x ] = MiSize
w = bw4 * 4
h = bh4 * 4
TipSizes16x16[ r + y ][ c + x ] = enable_tip_refinemv ?
(w == 256 && h == 256) :
(w >= 16 && h >= 16)
LeftMiSizes[ 0 ][ r + y ] = MiSize
AboveMiSizes[ 0 ][ c + x ] = MiSize
MiColStartGrid[ r + y ][ c + x ] = MiColStart
MiRowStartGrid[ r + y ][ c + x ] = MiRowStart
MiColEndGrid[ r + y ][ c + x ] = MiColEnd
MiRowEndGrid[ r + y ][ c + x ] = MiRowEnd
MiColBase[ 0 ][ r + y ][ c + x ] = MiCol
MiRowBase[ 0 ][ r + y ][ c + x ] = MiRow
if ( is_inter ) {
if ( !use_intrabc ) {
CompGroupIdxs[ r + y ][ c + x ] = comp_group_idx
}
InterpFilters[ r + y ][ c + x ] = interp_filter
for ( refList = 0; refList < 1 + isCompound; refList++ ) {
Mvs[r + y][c + x][refList] = BlockMvs[refList]
SubMvs[r + y][c + x][refList] = BlockMvs[refList]
}
}
SubPuColBase[ 0 ][ r + y ][ c + x ] = c
SubPuRowBase[ 0 ][ r + y ][ c + x ] = r
SubPuSize[ 0 ][ r + y ][ c + x ] = Max_Tx_Size_Rect[ MiSize ]
}
}
}
if ( HasChroma ) {
uvSmooth = !is_inter && (UVMode == SMOOTH_PRED ||
UVMode == SMOOTH_V_PRED || UVMode == SMOOTH_H_PRED)
for ( y = 0; y < Num_4x4_Blocks_High[ ChromaMiSize ]; y++ ) {
for ( x = 0; x < Num_4x4_Blocks_Wide[ ChromaMiSize ]; x++ ) {
MiSizes[ 1 ][ ChromaMiRow + y ][ ChromaMiCol + x ] =
ChromaMiSize
LeftMiSizes[ 1 ][ ChromaMiRow + y ] = ChromaMiSize
AboveMiSizes[ 1 ][ ChromaMiCol + x ] = ChromaMiSize
MiColBase[ 1 ][ ChromaMiRow + y ][ ChromaMiCol + x ] =
ChromaMiCol
MiRowBase[ 1 ][ ChromaMiRow + y ][ ChromaMiCol + x ] =
ChromaMiRow
UVSmooth[ ChromaMiRow + y ][ ChromaMiCol + x ] = uvSmooth
UVCfls[ ChromaMiRow + y ][ ChromaMiCol + x ] =
!is_inter && (UVMode == UV_CFL_PRED)
SubPuColBase[ 1 ][ ChromaMiRow + y ][ ChromaMiCol + x ] =
ChromaMiCol
SubPuRowBase[ 1 ][ ChromaMiRow + y ][ ChromaMiCol + x ] =
ChromaMiRow
SubPuSize[ 1 ][ ChromaMiRow + y ][ ChromaMiCol + x ] =
Max_Tx_Size_Rect[ ChromaMiSize ]
RegionTypes[ ChromaMiRow + y ][ ChromaMiCol + x ]
RegionType
ChromaSegmentIds[ ChromaMiRow + y ][ ChromaMiCol + x ] =
segment_id
ChromaQIndex[ ChromaMiRow + y ][ ChromaMiCol + x ] =
CurrentQIndex
}
}
}
compute_prediction( )
residual( )
if ( is_inter && motion_mode >= LOCALWARP ) {
update_warp_param_bank( RefFrame, LocalValid, LocalWarpParams, 0 )
}
if ( enable_refmvbank &&
bru_mode == BRU_ACTIVE &&
RefMvBankHits < MAX_RMB_SB_HITS ) {
if ( is_inter ) {
update_ref_mv_bank( RefFrame, BlockMvs, CwpIdx, 1 )
} else {
update_ref_mv_count( )
}
}
for ( y = 0; y < bh4; y++ ) {
for ( x = 0; x < bw4; x++ ) {
if ( PlaneStart == 0 ) {
for ( refList = 0;refList < 1 + isCompound; refList++ ) {
WarpParamsValid[ r + y ][ c + x ][ refList ] =
LocalValid[ refList ]
for ( i = 0; i < 6; i++ ) {
WarpParams[ r + y ][ c + x ][ refList ][ i ] =
LocalWarpParams[ refList ][ i ]
}
}
IsInters[ r + y ][ c + x ] = is_inter
SkipModes[ r + y ][ c + x ] = skip_mode
Skips[ r + y ][ c + x ] = skip_flag
CwpIdxs[ r + y ][ c + x ] = CwpIdx
FscModes[ r + y ][ c + x ] = fsc_mode
UsesMrls[ r + y ][ c + x ] =
(mrl_index > 0 ? ( mrl_sec_index ? 2 : 1) : 0)
UsesAmvds[ r + y ][ c + x ] = use_amvd
UseDip[ r + y ][ c + x ] = use_dip
UseMostProbablePrecisions[ r + y ][ c + x ] =
use_most_probable_precision
MvPrecisions[ r + y ][ c + x ] =
use_intrabc ? FrameMvPrecision : MvPrecision
MorphPreds[ r + y ][ c + x ] = use_intrabc && morph_pred
SegmentIds[ r + y ][ c + x ] = segment_id
PaletteSizes[ r + y ][ c + x ] = PaletteSizeY
for ( i = 0; i < PaletteSizeY; i++ ) {
PaletteColors[ r + y ][ c + x ][ i ] =
palette_colors_y[ i ]
}
MotionModes[ r + y ][ c + x ] = motion_mode
LumaQIndex[ r + y ][ c + x ] = CurrentQIndex
}
}
}
if ( PlaneStart == 0 ) {
if ( isCompound && opfl_allowed_for_refs( RefFrame ) && use_optflow ) {
motion_field_motion_vector_storage(r, c, subSize, 1)
} else if ( isCompound && compound_type == COMPOUND_AVERAGE &&
use_refinemv ) {
motion_field_motion_vector_storage(r, c, subSize, 2)
} else if ( RefFrame[ 0 ] == TIP_FRAME ) {
if ( store_refined_mvs() ) {
motion_field_motion_vector_storage(r, c, subSize,
LumaUseOptflowRefinement ? 1 : 2 )
} else {
motion_field_motion_vector_storage(r, c, subSize, 0)
}
} else {
motion_field_motion_vector_storage(r, c, subSize, 0)
}
}
}

where reset_block_context( ) is specified as:

reset_block_context( bw4, bh4 ) {    for ( plane = 0; plane < 1 + 2 * HasChroma; plane++ ) {        c = plane > 0 ? ChromaMiCol : MiCol        r = plane > 0 ? ChromaMiRow : MiRow        w4 = plane > 0 ? Num_4x4_Blocks_Wide[ ChromaMiSize ] : bw4        h4 = plane > 0 ? Num_4x4_Blocks_High[ ChromaMiSize ] : bh4        subX = plane > 0 ? SubsamplingX : 0        subY = plane > 0 ? SubsamplingY : 0        for ( i = c >> subX; i < ( ( c + w4 ) >> subX ); i++) {            AboveLevelContext[ plane ][ i ] = 0            AboveDcContext[ plane ][ i ] = 0        }        for ( i = r >> subY; i < ( ( r + h4 ) >> subY ); i++) {            LeftLevelContext[ plane ][ i ] = 0            LeftDcContext[ plane ][ i ] = 0        }    }}

update_warp_param_bank is specified as:

update_warp_param_bank( refFrames, paramsValid , params,                        candFromSbAbove ) {    isCompound = is_inter_ref_frame( refFrames[ 1 ] ) && !candFromSbAbove    for ( refList = 0;refList < 1 + isCompound; refList++ ) {        if ( paramsValid[ refList ] ) {            if ( WarpBankHits >= MAX_WARP_SB_HITS ) {                return            }            WarpBankHits++            ref = refFrames[ refList ]            found = -1            count = WarpBankSize[ ref ]            start = WarpBankStart[ ref ]            for ( i = 0; i < count; i++ ) {                idx = (start + i) % WARP_PARAM_BANK_SIZE                if ( params_equal( WarpBankParams[ ref ][ idx ],                                   params[ refList ] ) ) {                    found = i                    break                }            }            if ( found >= 0 ) {                for ( j = 0; j < 6; j++ ) {                    tmpParams[ j ] = WarpBankParams[ ref ][ idx ][ j ]                }                for ( i = found; i < count - 1; i++ ) {                    idx0 = (start + i) % WARP_PARAM_BANK_SIZE                    idx1 = (start + i + 1) % WARP_PARAM_BANK_SIZE                    for ( j = 0; j < 6; j++ ) {                        WarpBankParams[ ref ][ idx0 ][ j ] =                            WarpBankParams[ ref ][ idx1 ][ j ]                    }                }                tail = (start + count - 1) % WARP_PARAM_BANK_SIZE                for ( j = 0; j < 6; j++ ) {                    WarpBankParams[ ref ][ tail ][ j ] = tmpParams[ j ]                }            } else {                idx = (start + count) % WARP_PARAM_BANK_SIZE                for ( j = 0; j < 6; j++ ) {                    WarpBankParams[ ref ][ idx ][ j ] = params[ refList ][ j ]                }                if ( count < WARP_PARAM_BANK_SIZE ) {                    WarpBankSize[ ref ] = count + 1                } else {                    WarpBankStart[ ref ] = (start + 1) % WARP_PARAM_BANK_SIZE                }            }        }    }}

The function params_equal (which checks if the non-translational parts of two warps are equal) is defined as:

params_equal( paramsA , paramsB ) { Descriptor
for ( i = 2; i < 6; i++ ) {
if ( paramsA[ i ] != paramsB[ i ]) {
return 0
}
}
return 1
}

update_ref_mv_bank (which ensures the current parameters are at the tail of the appropriate bank of motion vectors) is specified as:

update_ref_mv_bank( refFrames, mvs, cwpIdx, fromWithinSb ) { Descriptor
if ( fromWithinSb ) {
update_ref_mv_count( )
if ( RefMvRemainHits == 0 || RefMvUnitHits >= 16 ) {
return
}
RefMvRemainHits--
RefMvUnitHits++
}
RefMvBankHits++
r0 = refFrames[ 0 ]
r1 = refFrames[ 1 ]
isCompound = is_inter_ref_frame(r1)
ref = get_rmb_list_index( refFrames )
for ( i = 0; i < 6; i++ ) {
p[ i ] = 0
}
p[ 0 ] = cwpIdx
p[ 1 ] = isCompound ? r0 + (r1 + 1) * BANK_REFS_PER_FRAME : r0
p[ 2 ] = mvs[ 0 ][ 0 ]
p[ 3 ] = mvs[ 0 ][ 1 ]
if ( isCompound ) {
p[ 4 ] = mvs[ 1 ][ 0 ]
p[ 5 ] = mvs[ 1 ][ 1 ]
}
found = -1
count = RefMvBankSize[ ref ]
start = RefMvBankStart[ ref ]
for ( i = 0; i < count; i++ ) {
idx = (start + i) % REF_MV_BANK_SIZE
if ( rmb_params_equal(RefMvBankParams[ ref ][ idx ],p) ) {
found = i
break
}
}
if ( found >= 0 ) {
for ( i = 0; i < 6; i++ ) {
tmpParams[ i ] = RefMvBankParams[ ref ][ idx ][ i ]
}
for ( i = found; i < count - 1; i++ ) {
idx0 = (start + i) % REF_MV_BANK_SIZE
idx1 = (start + i + 1) % REF_MV_BANK_SIZE
for ( j = 0; j < 6; j++ ) {
RefMvBankParams[ ref ][ idx0 ][ j ] =
RefMvBankParams[ ref ][ idx1 ][ j ]
}
}
tail = (start + count - 1) % REF_MV_BANK_SIZE
for ( j = 0; j < 6; j++ ) {
RefMvBankParams[ ref ][ tail ][ j ] = tmpParams[ j ]
}
return
}
idx = (start + count) % REF_MV_BANK_SIZE
for ( j = 0; j < 6; j++ ) {
RefMvBankParams[ ref ][ idx ][ j ] = p[ j ]
}
if ( count < REF_MV_BANK_SIZE ) {
RefMvBankSize[ ref ] = count + 1
} else {
RefMvBankStart[ ref ] = (start + 1) % REF_MV_BANK_SIZE
}
}

add_neighbor is specified as:

add_neighbor(nRow, nCol) { Descriptor
aboveSbBoundary = (MiRow >> Mi_Width_Log2[ SbSize ]) !=
(nRow >> Mi_Width_Log2[ SbSize ])
if ( NNum < 2 && is_inside(nRow,nCol) && !aboveSbBoundary ) {
NPos[ NNum ][ 0 ] = nRow
NPos[ NNum ][ 1 ] = nCol
NNum += 1
}
if ( NNumBuf < 2 && is_inside(nRow,nCol) ) {
NPosBuf[ NNumBuf ][ 0 ] = nRow
NPosBuf[ NNumBuf ][ 1 ] = nCol
NNumBuf += 1
}
}

Note: NPos will only contain locations that are in the same superblock row as the current block. NposBuf contains locations that may require buffered access to a different superblock row.

update_ref_mv_count is specified as:

update_ref_mv_count() { Descriptor
if ( TreeType != CHROMA_PART ) {
sbSize4 = Num_4x4_Blocks_Wide[ SbSize ]
unitSize4 = sbSize4 >> 3
unitCount = Max( Num_4x4_Blocks_Wide[ MiSize ] / unitSize4 , 1) *
Max( Num_4x4_Blocks_High[ MiSize ] / unitSize4 , 1)
if ( MiRow % sbSize4 == 0 && MiCol % sbSize4 == 0 ) {
RefMvRemainHits = Max( unitCount , 4 )
RefMvUnitHits = 0
} else if ( MiRow % unitSize4 == 0 && MiCol % unitSize4 == 0 ) {
RefMvRemainHits += unitCount
RefMvUnitHits = 0
}
}
}
rmb_params_equal
rmb_params_equal( paramsA, paramsB ) { Descriptor
for ( i = 1; i < 6; i++ ) {
if ( paramsA[ i ] != paramsB[ i ] ) {
return 0
}
}
return 1
}

update_ibc_buffers is specified as:

update_ibc_buffers(miRow, miCol) { Descriptor
bufRow = miRow >> (IBC_BUFFER_SIZE_LOG2 - MI_SIZE_LOG2)
bufCol = miCol >> (IBC_BUFFER_SIZE_LOG2 - MI_SIZE_LOG2)
if ( bufRow != IBCBufferCurRow || bufCol != IBCBufferCurCol ) {
blkIdx = ibc_buffer_index(IBCBufferCurRow, IBCBufferCurCol)
IBCBufferRow[ blkIdx ] = IBCBufferCurRow
IBCBufferCol[ blkIdx ] = IBCBufferCurCol
IBCBufferValid[ blkIdx ] = 1
if ( SbSize == BLOCK_64X64 ) {
bruRow = IBCBufferCurRow << (IBC_BUFFER_SIZE_LOG2 - MI_SIZE_LOG2)
bruCol = IBCBufferCurCol << (IBC_BUFFER_SIZE_LOG2 - MI_SIZE_LOG2)
if ( BruModes[ bruRow ][ bruCol ] == BRU_INACTIVE ) {
for ( i = 0; i < IBC_NUM_BUFFERS; i++ ) {
IBCBufferValid[ i ] = 0
}
}
}
IBCBufferCurRow = bufRow
IBCBufferCurCol = bufCol
}
}

Note: Calls to update_ibc_buffers are only needed for bitstream conformance checks. However, a decoder implementation may wish to use the same logic for updating a local cache of information available for intra block copy.

ibc_buffer_index is specified as:

ibc_buffer_index(row, col) { Descriptor
if ( SbSize == BLOCK_64X64 ) {
return col & 3
} else {
return (col & 1) | ((row & 1) << 1)
}
}

store_refined_mvs is specified as:

store_refined_mvs() { Descriptor
return Tip_Weighting_Factor[ tip_global_wtd_index ] == CWP_EQUAL &&
enable_tip_refinemv && NumFutureRefs > 0 && NumPastRefs > 0
}

5.20.8. Mode info syntax

mode_info( ) { Descriptor
if ( bru_mode != BRU_ACTIVE ) {
bru_mode_info( )
} else if ( FrameIsIntra ) {
intra_frame_mode_info( )
} else {
inter_frame_mode_info( )
}
}

5.20.9. BRU mode info syntax

bru_mode_info( ) { Descriptor
use_intrabc = 0
skip_flag = 1
segment_id = 0
Lossless = LosslessArray[ segment_id ]
skip_mode = 0
is_inter = 1
RefFrame[ 0 ] = IsBridge ? 0 : bru_ref
RefFrame[ 1 ] = NONE
mrl_index = 0
use_dip = 0
fsc_mode = 0
use_dpcm_y = 0
use_dpcm_uv = 0
PaletteSizeY = 0
MvPrecision = MV_PRECISION_ONE_PEL
use_most_probable_precision = 0
IntraJointMode = DC_PRED
use_bawp = 0
use_amvd = 0
CwpIdx = CWP_EQUAL
CurrentQIndex = base_q_idx
use_optflow = 0
use_refinemv = 0
YMode = NEWMV
motion_mode = SIMPLE
BlockMvs[ 0 ][ 0 ] = 0
BlockMvs[ 0 ][ 1 ] = 0
interp_filter = EIGHTTAP_SHARP
read_gdf( )
read_ccso( )
for ( r = MiRow; r < MiRow + Num_4x4_Blocks_High[ MiSize ]; r++ ) {
LeftSegPredContext[ r ] = 0
}
for ( c = MiCol; c < MiCol + Num_4x4_Blocks_Wide[ MiSize ]; c++ ) {
AboveSegPredContext[ c ] = 0
}
}

5.20.10. Intra frame mode info syntax

intra_frame_mode_info( ) { Descriptor
skip_flag = 0
if ( SegIdPreSkip ) {
intra_segment_id( )
}
skip_mode = 0
use_most_probable_precision = 0
MvPrecision = FrameMvPrecision
CwpIdx = CWP_EQUAL
motion_mode = SIMPLE
if ( allow_intrabc && TreeType != CHROMA_PART &&
Block_Width[ MiSize ] <= 64 &&
Block_Height[ MiSize ] <= 64 &&
MiSize != BLOCK_64X64 ) {
use_intrabc S()
} else {
use_intrabc = 0
}
if ( use_intrabc ) {
read_skip( )
} else {
skip_flag = 0
}
if ( !SegIdPreSkip ) {
intra_segment_id( )
}
if ( TreeType != CHROMA_PART ) {
read_gdf( )
read_cdef( )
read_ccso( )
read_delta_qindex( )
}
ReadDeltas = 0
RefFrame[ 0 ] = INTRA_FRAME
RefFrame[ 1 ] = NONE
fsc_mode = 0
if ( use_intrabc ) {
is_inter = 1
mrl_index = 0
read_intrabc_info()
} else {
is_inter = 0
PaletteSizeY = 0
if ( TreeType != CHROMA_PART ) {
read_intra_y_mode()
} else {
YMode = YModes[ MiRow ][ MiCol ]
AngleDeltaY = AngleDeltaYs[ MiRow ][ MiCol ]
PaletteSizeY = PaletteSizes[ MiRow ][ MiCol ]
}
if ( HasChroma ) {
read_intra_uv_mode()
if ( UVMode == UV_CFL_PRED ) {
read_cfl_alphas( )
}
}
if ( MiSize >= BLOCK_8X8 &&
Block_Width[ MiSize ] <= 64 &&
Block_Height[ MiSize ] <= 64 &&
allow_screen_content_tools ) {
palette_mode_info( )
}
if ( TreeType != CHROMA_PART ) {
dip_mode_info( )
}
}
}

5.20.11. Read intra block copy syntax

read_intrabc_info() { Descriptor
IntraJointMode = DC_PRED
mrl_index = 0
use_dip = 0
fsc_mode = 0
AngleDeltaY = 0
use_bawp = 0
use_amvd = 0
warpmv_with_mvd = 0
use_refinemv = 0
DecidedAgainstRefinemv = 0
use_dpcm_y = 0
use_dpcm_uv = 0
CwpIdx = CWP_EQUAL
YMode = DC_PRED
UVMode = DC_PRED
motion_mode = SIMPLE
compound_type = COMPOUND_AVERAGE
PaletteSizeY = 0
interp_filter = BILINEAR
RefFrame[ 0 ] = INTRA_FRAME
RefFrame[ 1 ] = NONE
MvPrecision = force_integer_mv ? MV_PRECISION_ONE_PEL :
MV_PRECISION_QUARTER_PEL
use_most_probable_precision = 0
DeriveWrl = 0
IsAdaptiveMvd = 0
find_mode_ctx( 0 )
find_mv_stack( 0 )
m = max_bvp_drl_bits_minus_1 + 1
intrabc_mode S()
RefMvIdx = 0
for ( idx = 0; idx < m; idx++ ) {
intrabc_drl_mode L(1)
if ( intrabc_drl_mode == 0 ) {
RefMvIdx = idx
break
}
RefMvIdx = idx + 1
}
if ( intrabc_mode == 0 && !force_integer_mv ) {
intrabc_precision S()
MvPrecision = intrabc_precision ? MV_PRECISION_QUARTER_PEL :
MV_PRECISION_ONE_PEL
}
assign_mv( 0 )
if ( FrameIsIntra && allow_screen_content_tools && enable_bawp ) {
morph_pred S()
} else {
morph_pred = 0
}
}

5.20.12. Read intra Y mode syntax

read_intra_y_mode( ) { Descriptor
if ( Lossless ) {
use_dpcm_y S()
} else {
use_dpcm_y = 0
}
if ( use_dpcm_y ) {
dpcm_mode_y S()
AngleDeltaY = 0
mrl_index = 0
if ( dpcm_mode_y ) {
YMode = H_PRED
IntraJointMode = 50
} else {
YMode = V_PRED
IntraJointMode = 22
}
if ( allow_fsc_intra() ) {
fsc_mode S()
}
return
}
y_mode_set S()
if ( y_mode_set == 0 ) {
y_mode_index S()
modeIdx = y_mode_index
if ( y_mode_index == MODE_INDEX_COUNT - 1 ) {
y_mode_offset S()
modeIdx += y_mode_offset
}
} else {
y_second_mode L(4)
modeIdx = FIRST_MODE_COUNT + (y_mode_set - 1) * SECOND_MODE_COUNT +
y_second_mode
}
modeDelta = get_intra_y_mode_set(modeIdx)
IntraJointMode = modeDelta
if ( modeDelta < NON_DIRECTIONAL_MODES_COUNT ) {
YMode = Reordered_Y_Mode[ modeDelta ]
AngleDeltaY = 0
} else {
modeDelta -= NON_DIRECTIONAL_MODES_COUNT
YMode = Reordered_Y_Mode[ modeDelta / TOTAL_ANGLE_DELTA_COUNT +
NON_DIRECTIONAL_MODES_COUNT ]
AngleDeltaY = (modeDelta % TOTAL_ANGLE_DELTA_COUNT) - MAX_ANGLE_DELTA
}
if ( TreeType != CHROMA_PART && allow_fsc_intra() ) {
fsc_mode S()
}
if (enable_mrls && is_directional_mode(YMode)) {
mrl_index S()
if ( mrl_index > 0 ) {
mrl_sec_index S()
}
} else {
mrl_index = 0
}
}

where Reordered_Y_Mode, Default_Mode_List_Y, get_intra_y_mode_set, get_joint_mode, and allow_fsc_intra are defined as:

Reordered_Y_Mode[ INTRA_MODES ] = {    DC_PRED,   SMOOTH_PRED, SMOOTH_V_PRED, SMOOTH_H_PRED, PAETH_PRED,    D45_PRED,  D67_PRED,    V_PRED,        D113_PRED,     D135_PRED,    D157_PRED, H_PRED,      D203_PRED}Default_Mode_List_Y[ DIRECTIONAL_MODES_COUNT ] = {    17, 45, 3, 10, 24, 31, 38, 52,    15, 19, 43, 47, 1, 5, 8, 12, 22, 26, 29, 33, 36, 40, 50, 54,    16, 18, 44, 46, 2, 4, 9, 11, 23, 25, 30, 32, 37, 39, 51, 53,    14, 20, 42, 48, 0, 6, 7, 13, 21, 27, 28, 34, 35, 41, 49, 55}

get_joint_mode( dir ) { Descriptor
if ( dir ) {
mvRow = MiRow - 1
mvCol = MiCol + Num_4x4_Blocks_Wide[ MiSize ] - 1
} else {
mvCol = MiCol - 1
mvRow = MiRow + Num_4x4_Blocks_High[ MiSize ] - 1
}
if ( is_inside( mvRow, mvCol ) ) {
return IntraJointModes[ mvRow ][ mvCol ]
}
return DC_PRED
}
get_intra_y_mode_set( modeIdx ) {
if ( modeIdx < NON_DIRECTIONAL_MODES_COUNT ) {
return modeIdx
}
modeIdx -= NON_DIRECTIONAL_MODES_COUNT
for ( i = 0; i < DIRECTIONAL_MODES_COUNT; i++ ) {
isDirSelected[ i ] = 0
}
if ( MiSize >= BLOCK_8X8 ) {
count = 0
for ( dir = 0; dir < 2; dir++ ) {
mode = get_joint_mode( dir )
if ( mode >= NON_DIRECTIONAL_MODES_COUNT ) {
mode -= NON_DIRECTIONAL_MODES_COUNT
if ( count == 0 || mode != dirModes[ 0 ] ) {
if ( modeIdx == 0 ) {
return mode + NON_DIRECTIONAL_MODES_COUNT
}
modeIdx -= 1
isDirSelected[ mode ] = 1
dirModes[ count ] = mode
count += 1
}
}
}
if ( Block_Width[ MiSize ] * Block_Height[ MiSize ] > 64 ) {
for ( i = 1; i <= 4; i++ ) {
for ( j = 0; j < count; j++ ) {
for ( sgn = -1 ; sgn <= 1 ; sgn += 2 ) {
mode = dirModes[ j ] + i * sgn
if (mode < 0) {
mode += DIRECTIONAL_MODES_COUNT
}
else if (mode >= DIRECTIONAL_MODES_COUNT)
mode -= DIRECTIONAL_MODES_COUNT
if ( !isDirSelected[ mode ] ) {
if ( modeIdx == 0 ) {
return mode + NON_DIRECTIONAL_MODES_COUNT
}
modeIdx -= 1
isDirSelected[ mode ] = 1
}
}
}
}
}
}
for ( i = 0; i < DIRECTIONAL_MODES_COUNT; i++ ) {
mode = Default_Mode_List_Y[ i ]
if ( !isDirSelected[ mode ] ) {
if ( modeIdx == 0 ) {
return mode + NON_DIRECTIONAL_MODES_COUNT
}
modeIdx -= 1
}
}
}
allow_fsc_intra( ) {
w = Block_Width[ MiSize ]
h = Block_Height[ MiSize ]
return enable_idtx_intra && w <= FSC_MAX && h <= FSC_MAX
}

5.20.13. Read intra UV mode syntax

read_intra_uv_mode( ) { Descriptor
if ( Lossless ) {
use_dpcm_uv S()
} else {
use_dpcm_uv = 0
}
if ( use_dpcm_uv ) {
dpcm_mode_uv S()
if ( dpcm_mode_uv ) {
UVMode = H_PRED
} else {
UVMode = V_PRED
}
if ( UVMode == YMode ) {
AngleDeltaUV = AngleDeltaY
} else {
AngleDeltaUV = 0
}
return
}
planeSz = get_plane_residual_size( ChromaMiSize, 1 )
if ( !enable_cfl_intra ) {
cflAllowed = 0
} else if ( TreeType == CHROMA_PART && FrameIsIntra && !CflAllowedInSdp ) {
cflAllowed = 0
} else if ( Lossless ) {
cflAllowed = planeSz == BLOCK_4X4
} else {
cflAllowed = Block_Width[ planeSz ] <= 64 &&
Block_Height[ planeSz ] <= 64
}
if ( cflAllowed || is_mhccp_allowed() ) {
is_cfl S()
if ( is_cfl ) {
AngleDeltaUV = 0
UVMode = UV_CFL_PRED
return
}
}
uv_mode S()
if ( uv_mode == CHROMA_MODE_COUNT - 1 ) {
uv_mode_idx L(3)
uv_mode += uv_mode_idx
}
UVMode = get_intra_uv_mode_set( uv_mode )
if ( UVMode == YMode ) {
AngleDeltaUV = AngleDeltaY
} else {
AngleDeltaUV = 0
}
}

where Default_Mode_List_Uv, get_intra_uv_mode_set, and is_mhccp_allowed are defined as:

Default_Mode_List_Uv[ UV_INTRA_MODES_CFL_NOT_ALLOWED ] = {    DC_PRED, SMOOTH_PRED, SMOOTH_V_PRED, SMOOTH_H_PRED, PAETH_PRED,    V_PRED,   H_PRED,    D45_PRED,  D135_PRED,    D67_PRED, D113_PRED, D157_PRED, D203_PRED}

get_intra_uv_mode_set( modeIdx ) { Descriptor
if ( is_directional_mode( YMode ) ) {
if ( modeIdx == 0 ) {
return YMode
}
modeIdx -= 1
}
for ( i = 0; i < UV_INTRA_MODES_CFL_NOT_ALLOWED; i++ ) {
mode = Default_Mode_List_Uv[ i ]
if ( mode != YMode || !is_directional_mode( YMode ) ) {
if ( modeIdx == 0 ) {
return mode
}
modeIdx -= 1
}
}
}
is_mhccp_allowed( ) {
planeSz = get_plane_residual_size( ChromaMiSize, 1 )
if ( !enable_mhccp ) {
return 0
} else if ( TreeType == CHROMA_PART && FrameIsIntra && !CflAllowedInSdp ) {
return 0
} else if ( Lossless ) {
return planeSz == BLOCK_4X4
} else {
w = Block_Width[ planeSz ]
h = Block_Height[ planeSz ]
return ( w > 4 || h > 4 ) && w <= 32 && h <= 32
}
}

5.20.14. Intra segment ID syntax

intra_segment_id( ) { Descriptor
if ( TreeType == CHROMA_PART ) {
segment_id = SegmentIds[ MiRow ][ MiCol ]
} else if ( segmentation_enabled ) {
read_segment_id( )
} else {
segment_id = 0
}
Lossless = LosslessArray[ segment_id ]
}

5.20.15. Read segment ID syntax

read_segment_id( ) { Descriptor
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_flag && !HasLosslessSegment ) {
segment_id = pred
} else {
if ( enable_ext_seg ) {
seg_id_ext_flag S()
} else {
seg_id_ext_flag = 0
}
segment_id S()
if ( seg_id_ext_flag ) {
segment_id += 8
}
segment_id = neg_deinterleave( segment_id, pred,
LastActiveSegId + 1 )
}
}

where neg_deinterleave is a function defined as:

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.20.16. Skip mode syntax

read_skip_mode() { Descriptor
if ( seg_feature_active( SEG_LVL_SKIP ) ||
seg_feature_active( SEG_LVL_GLOBALMV ) ||
!skip_mode_present ||
!is_comp_ref_allowed( ) ||
RegionType == INTRA_REGION ) {
skip_mode = 0
} else {
skip_mode S()
}
}

where is_comp_ref_allowed is a function that checks the block size as follows:

is_comp_ref_allowed( ) { Descriptor
w = Block_Width[ MiSize ]
h = Block_Height[ MiSize ]
return ( Min( w, h ) >= 8 ) || is_thin_4xn_nx4_block()
}

5.20.17. Skip syntax

read_skip() { Descriptor
if ( SegIdPreSkip && seg_feature_active( SEG_LVL_SKIP ) ) {
skip_flag = 1
} else {
skip_flag S()
}
}

5.20.18. Quantizer index delta syntax

read_delta_qindex( ) { Descriptor
if ( !(MiSize == SbSize && skip_flag) && ReadDeltas ) {
delta_q_abs S()
if ( delta_q_abs == DELTA_Q_SMALL ) {
delta_q_rem_bits L(3)
delta_q_rem_bits++
delta_q_abs_bits L(delta_q_rem_bits)
delta_q_abs = delta_q_abs_bits + (1 << delta_q_rem_bits) +
DELTA_Q_SMALL - 2
}
if ( delta_q_abs ) {
delta_q_sign_bit L(1)
reducedDeltaQIndex = delta_q_sign_bit ? -delta_q_abs : delta_q_abs
CurrentQIndex = Clip3(1, MaxQ,
CurrentQIndex + (reducedDeltaQIndex << delta_q_res))
}
}
if ( delta_q_present ) {
CurrentQIndex = Clip3(1, MaxQ, CurrentQIndex)
}
}

5.20.19. Segmentation feature active function

seg_feature_active_idx( idx, feature ) { Descriptor
return segmentation_enabled && FeatureEnabled[ idx ][ feature ]
}
seg_feature_active( feature ) {
return seg_feature_active_idx( segment_id, feature )
}

5.20.20. TX size syntax

read_tx_size( allowSelect ) { Descriptor
if ( Lossless ) {
if ( MiSize == BLOCK_4X4 ||
( !is_inter && !fsc_mode ) ||
!allowSelect ) {
TxSize = TX_4X4
} else {
lossless_tx_size S()
if ( lossless_tx_size ) {
TxSize = find_tx_size( Min(32, Block_Width[ MiSize ] ),
Min(32, Block_Height[ MiSize ] ) )
} else {
TxSize = TX_4X4
}
}
return 0
}
maxRectTxSize = Max_Tx_Size_Rect[ MiSize ]
TxSize = maxRectTxSize
if ( MiSize > BLOCK_4X4 && allowSelect && TxMode == TX_MODE_SELECT ) {
widthChunks = Block_Width[ MiSize ] >> 6
heightChunks = Block_Height[ MiSize ] >> 6
if ( widthChunks > 1 || heightChunks > 1 ) {
for ( chunkY = 0; chunkY < heightChunks; chunkY++ ) {
for ( chunkX = 0; chunkX < widthChunks; chunkX++ ) {
miRowChunk = MiRow + ( chunkY << 4 )
miColChunk = MiCol + ( chunkX << 4 )
set_tx_size( miRowChunk, miColChunk, 16, 16, 0, 0 )
}
}
} else {
read_tx_partition( MiRow, MiCol, maxRectTxSize )
}
return 1
}
return 0
}

Note: The same transform partition is used for all chunks when read_tx_size is called.

5.20.21. Block TX size syntax

read_block_tx_size( ) { Descriptor
bw4 = Num_4x4_Blocks_Wide[ MiSize ]
bh4 = Num_4x4_Blocks_High[ MiSize ]
if ( TxMode == TX_MODE_SELECT &&
MiSize > BLOCK_4X4 && is_inter &&
!skip_flag && !Lossless ) {
maxTxSz = Max_Tx_Size_Rect[ MiSize ]
txW4 = Tx_Width[ maxTxSz ] / MI_SIZE
txH4 = Tx_Height[ maxTxSz ] / MI_SIZE
for ( row = MiRow; row < MiRow + bh4; row += txH4 ) {
for ( col = MiCol; col < MiCol + bw4; col += txW4 ) {
read_tx_partition( row, col, maxTxSz)
}
}
} else {
if ( read_tx_size( !skip_flag || !is_inter ) == 0 ) {
for ( row = MiRow; row < MiRow + bh4; row++ ) {
for ( col = MiCol; col < MiCol + bw4; col++ ) {
LumaTxSizes[ row ][ col ] = TxSize
LumaTxMiddle[ row ][ col ] = 0
LumaTxScanOrder[ row ][ col ] = 0
}
}
}
}
}

5.20.22. Read TX partition syntax

read_tx_partition( row, col, txSz) { Descriptor
if ( row >= MiRows || col >= MiCols ) {
return
}
horzTxSz = find_tx_size(Tx_Width[ txSz ], Tx_Height[ txSz ] >> 1)
vertTxSz = find_tx_size(Tx_Width[ txSz ] >> 1, Tx_Height[ txSz ])
allowHorz = horzTxSz != TX_INVALID
allowVert = vertTxSz != TX_INVALID
txPartition = TX_PARTITION_NONE
if ( Block_Width[ MiSize ] <= 64 && Block_Height[ MiSize ] <= 64 ) {
tx_do_partition S()
if ( tx_do_partition ) {
if ( allowHorz && allowVert ) {
tx_partition_type S()
txPartition = tx_partition_type + 1
} else if ( Size_To_Tx_Type_Group_Vert_Or_Horz[ MiSize ] > 0 ) {
if ( reduced_tx_part_set ) {
tx_2or3_partition_type = 0
} else {
tx_2or3_partition_type S()
}
if ( allowHorz ) {
txPartition = tx_2or3_partition_type ? TX_PARTITION_HORZ4 :
TX_PARTITION_HORZ
} else {
txPartition = tx_2or3_partition_type ? TX_PARTITION_VERT4 :
TX_PARTITION_VERT
}
} else {
txPartition = allowHorz ? TX_PARTITION_HORZ : TX_PARTITION_VERT
}
}
}
w4 = Tx_Width[ txSz ] / MI_SIZE
h4 = Tx_Height[ txSz ] / MI_SIZE
if ( txPartition == TX_PARTITION_NONE ) {
TxSize = set_tx_size(row, col, h4 , w4, 0, 0)
} else if ( txPartition == TX_PARTITION_HORZ ) {
h4 = h4 >> 1
set_tx_size(row, col, h4, w4, 0, 0)
row += h4
TxSize = set_tx_size(row, col, h4 , w4, 0, 0)
} else if ( txPartition == TX_PARTITION_VERT ) {
w4 = w4 >> 1
set_tx_size(row, col, h4, w4, 0, 0)
col += w4
TxSize = set_tx_size(row, col, h4 , w4, 0, 0)
} else if ( txPartition == TX_PARTITION_HORZ4 ) {
h4 = h4 >> 2
set_tx_size(row, col, h4, w4, 0, 0)
row += h4
set_tx_size(row, col, h4, w4, 0, 0)
row += h4
set_tx_size(row, col, h4, w4, 0, 0)
row += h4
TxSize = set_tx_size(row, col, h4, w4, 0, 0)
} else if ( txPartition == TX_PARTITION_VERT4 ) {
w4 = w4 >> 2
set_tx_size(row, col, h4, w4, 0, 0)
col += w4
set_tx_size(row, col, h4, w4, 0, 0)
col += w4
set_tx_size(row, col, h4, w4, 0, 0)
col += w4
TxSize = set_tx_size(row, col, h4, w4, 0, 0)
} else if ( txPartition == TX_PARTITION_HORZ5 ) {
h4 = h4 >> 2
w4 = w4 >> 1
set_tx_size(row, col, h4, w4, 0, 0)
col += w4
set_tx_size(row, col, h4, w4, 1, 0)
col -= w4
row += h4
h4 = h4 << 1
w4 = w4 << 1
set_tx_size(row, col, h4, w4, 1, 0)
row += h4
h4 = h4 >> 1
w4 = w4 >> 1
set_tx_size(row, col, h4, w4, 1, 0)
col += w4
TxSize = set_tx_size(row, col, h4, w4, 1, 0)
} else if ( txPartition == TX_PARTITION_VERT5 ) {
h4 = h4 >> 1
w4 = w4 >> 2
set_tx_size(row, col, h4, w4, 0, 1)
row += h4
set_tx_size(row, col, h4, w4, 1, 1)
col += w4
row -= h4
h4 = h4 << 1
w4 = w4 << 1
set_tx_size(row, col, h4, w4, 1, 1)
col += w4
h4 = h4 >> 1
w4 = w4 >> 1
set_tx_size(row, col, h4, w4, 1, 1)
row += h4
TxSize = set_tx_size(row, col, h4, w4, 1, 1)
} else { // TX_PARTITION_SPLIT
w4 = w4 >> 1
h4 = h4 >> 1
set_tx_size(row, col + w4, h4, w4, 0, 0)
set_tx_size(row, col, h4, w4, 0, 0)
set_tx_size(row + h4, col, h4, w4, 0, 0)
TxSize = set_tx_size(row + h4, col + w4, h4, w4, 0, 0)
}
}

where the function find_tx_size finds the transform block size for the given dimensions and is defined as:

find_tx_size( w, h ) { Descriptor
for ( txSz = 0; txSz < TX_SIZES_ALL; txSz++ ) {
if ( Tx_Width[ txSz ] == w && Tx_Height[ txSz ] == h ) {
return txSz
}
}
return TX_INVALID
}

and the function set_tx_size saves the transform size as follows:

set_tx_size(row, col, h4, w4, mid, scanOrder) { Descriptor
subTxSz = find_tx_size( w4 << 2, h4 << 2 )
for ( i = 0; i < h4; i++ ) {
for ( j = 0; j < w4; j++ ) {
LumaTxSizes[ row + i ][ col + j ] = subTxSz
LumaTxMiddle[ row + i ][ col + j ] = mid
LumaTxScanOrder[ row + i ][ col + j ] = scanOrder
}
}
return subTxSz
}

5.20.23. Inter frame mode info syntax

inter_frame_mode_info( ) { Descriptor
use_intrabc = 0
skip_flag = 0
inter_segment_id( 1 )
read_skip_mode( )
read_is_inter( )
if ( is_inter ) {
read_skip( )
} else {
skip_flag = 0
}
if ( !SegIdPreSkip ) {
inter_segment_id( 0 )
}
Lossless = LosslessArray[ segment_id ]
if ( TreeType != CHROMA_PART ) {
read_gdf( )
read_cdef( )
read_ccso( )
read_delta_qindex( )
}
ReadDeltas = 0
if ( use_intrabc ) {
read_intrabc_info( )
} else if ( is_inter ) {
inter_block_mode_info( )
} else {
intra_block_mode_info( )
}
}

5.20.24. Inter segment ID syntax

This is called before (preSkip equal to 1) and after (preSkip equal to 0) the skip_flag syntax element has been read.

inter_segment_id( preSkip ) { Descriptor
if ( TreeType == CHROMA_PART ) {
segment_id = SegmentIds[ MiRow ][ MiCol ]
} else if ( segmentation_enabled ) {
predictedSegmentId = get_segment_id( )
if ( segmentation_update_map ) {
if ( preSkip && !SegIdPreSkip ) {
segment_id = 0
return
}
if ( !preSkip ) {
if ( skip_flag ) {
seg_id_predicted = 0
for ( i = 0; i < Num_4x4_Blocks_Wide[ MiSize ]; i++ ) {
AboveSegPredContext[ MiCol + i ] = seg_id_predicted
}
for ( i = 0; i < Num_4x4_Blocks_High[ MiSize ]; i++ ) {
LeftSegPredContext[ MiRow + i ] = seg_id_predicted
}
read_segment_id( )
return
}
}
if ( segmentation_temporal_update == 1 ) {
seg_id_predicted S()
if ( seg_id_predicted ) {
segment_id = predictedSegmentId
} else {
read_segment_id( )
}
for ( i = 0; i < Num_4x4_Blocks_Wide[ MiSize ]; i++ ) {
AboveSegPredContext[ MiCol + i ] = seg_id_predicted
}
for ( i = 0; i < Num_4x4_Blocks_High[ MiSize ]; i++ ) {
LeftSegPredContext[ MiRow + i ] = seg_id_predicted
}
} else {
read_segment_id( )
}
} else {
segment_id = predictedSegmentId
}
} else {
segment_id = 0
}
}

5.20.25. Is inter syntax

read_is_inter( ) { Descriptor
if ( RegionType == INTRA_REGION ) {
is_inter = 0
} else if ( skip_mode ) {
is_inter = 1
} else if ( seg_feature_active ( SEG_LVL_GLOBALMV ) ) {
is_inter = 1
} else if ( TreeType == SHARED_PART && MiSize != ChromaMiSize ) {
is_inter = 1
} else {
is_inter S()
}
if ( !is_inter && allow_intrabc &&
Block_Width[ MiSize ] <= 64 &&
Block_Height[ MiSize ] <= 64 &&
MiSize != BLOCK_64X64 &&
RegionType == MIXED_REGION ) {
use_intrabc S()
if ( use_intrabc ) {
is_inter = 1
}
} else {
use_intrabc = 0
}
}

5.20.26. Get segment ID function

The predicted segment id is the smallest value found in the on-screen region of the segmentation map covered by the current block.

get_segment_id( ) { Descriptor
bw4 = Num_4x4_Blocks_Wide[ MiSize ]
bh4 = Num_4x4_Blocks_High[ MiSize ]
xMis = Min( MiCols - MiCol, bw4 )
yMis = Min( MiRows - MiRow, bh4 )
seg = MAX_SEGMENTS - 1
for ( y = 0; y < yMis; y++ ) {
for ( x = 0; x < xMis; x++ ) {
seg = Min( seg, PrevSegmentIds[ MiRow + y ][ MiCol + x ] )
}
}
return seg
}

5.20.27. Intra block mode info syntax

intra_block_mode_info( ) { Descriptor
RefFrame[ 0 ] = INTRA_FRAME
RefFrame[ 1 ] = NONE
motion_mode = SIMPLE
fsc_mode = 0
use_most_probable_precision = 0
MvPrecision = FrameMvPrecision
CwpIdx = CWP_EQUAL
PaletteSizeY = 0
motion_mode = SIMPLE
if ( TreeType != CHROMA_PART ) {
read_intra_y_mode()
} else {
YMode = YModes[ MiRow ][ MiCol ]
AngleDeltaY = AngleDeltaYs[ MiRow ][ MiCol ]
PaletteSizeY = PaletteSizes[ MiRow ][ MiCol ]
}
if ( HasChroma ) {
read_intra_uv_mode()
if ( UVMode == UV_CFL_PRED ) {
read_cfl_alphas( )
}
}
if ( MiSize >= BLOCK_8X8 &&
Block_Width[ MiSize ] <= 64 &&
Block_Height[ MiSize ] <= 64 &&
allow_screen_content_tools ) {
palette_mode_info( )
}
if ( TreeType != CHROMA_PART ) {
dip_mode_info( )
}
}

5.20.28. Inter block mode info syntax

inter_block_mode_info( ) { Descriptor
mrl_index = 0
use_dip = 0
fsc_mode = 0
use_dpcm_y = 0
use_dpcm_uv = 0
PaletteSizeY = 0
use_most_probable_precision = 0
MvPrecision = FrameMvPrecision
IntraJointMode = DC_PRED
use_bawp = 0
use_amvd = 0
read_ref_frames( )
isCompound = is_inter_ref_frame( RefFrame[ 1 ] )
DeriveWrl = !skip_mode && !isCompound && RefFrame[ 0 ] != TIP_FRAME &&
Block_Width[ MiSize ] >= 8 && Block_Height[ MiSize ] >= 8
find_mode_ctx( isCompound )
if ( skip_mode ) {
YMode = NEAR_NEARMV
use_optflow = 0
} else if ( seg_feature_active( SEG_LVL_SKIP ) ||
seg_feature_active( SEG_LVL_GLOBALMV ) ) {
YMode = GLOBALMV
use_optflow = 0
} else if ( isCompound ) {
if ( RefFrame[ 0 ] == RefFrame[ 1 ] ) {
compound_mode_same_refs S()
if ( compound_mode_same_refs < 2 ) {
YMode = NEAR_NEARMV + compound_mode_same_refs
} else {
YMode = NEAR_NEARMV + compound_mode_same_refs + 1
}
} else {
is_joint S()
if ( is_joint ) {
YMode = JOINT_NEWMV
} else {
compound_mode_non_joint S()
YMode = NEAR_NEARMV + compound_mode_non_joint
}
}
if ( opfl_refine_type == REFINE_SWITCHABLE &&
opfl_allowed_for_refs( RefFrame ) &&
Block_Width[ MiSize ] >= 8 && Block_Height[ MiSize ] >= 8 &&
YMode != GLOBAL_GLOBALMV ) {
use_optflow S()
} else {
use_optflow = 0
}
if ( allow_amvd_mode( YMode ) ) {
use_amvd S()
}
} else {
use_optflow = 0
if ( RefFrame[ 0 ] == TIP_FRAME ) {
tip_pred_mode S()
YMode = Tip_Pred_Index_To_Mode[ tip_pred_mode ]
if ( allow_amvd_mode( YMode ) ) {
use_amvd S()
}
} else {
if ( allow_warpmv_mode &&
Min(Block_Width[ MiSize ], Block_Height[ MiSize ]) >= 8 ) {
is_warp S()
} else {
is_warp = 0
}
if ( is_warp ) {
if ( force_integer_mv ) {
warp_mv = 1
} else {
warp_mv S()
}
YMode = warp_mv ? WARPMV : WARP_NEWMV
} else {
single_mode S()
YMode = NEARMV + single_mode
if ( allow_amvd_mode( YMode ) ) {
use_amvd S()
}
if ( allow_bawp && !is_scaled( RefFrame[ 0 ], 1 ) &&
Min(Block_Width[ MiSize ], Block_Height[ MiSize ]) >= 8 &&
FrameType != SWITCH_FRAME && YMode != GLOBALMV ) {
use_bawp S()
if ( use_bawp ) {
explicit_bawp S()
if ( explicit_bawp ) {
explicit_bawp_scale S()
}
} else {
explicit_bawp = 0
}
if ( use_bawp && HasChroma ) {
use_bawp_chroma S()
}
}
}
}
}
if ( skip_mode ) {
find_mv_stack( isCompound )
} else if ( has_second_drl( YMode ) ) {
r0 = RefFrame[ 0 ]
r1 = RefFrame[ 1 ]
RefFrame[ 0 ] = r0
RefFrame[ 1 ] = NONE
find_mv_stack( 0 )
for ( i = 0; i < MAX_REF_MV_STACK_SIZE; i++ ) {
RefStack0Mvs[ i ] = RefStackMv[ i ][ 0 ]
}
RefFrame[ 0 ] = r1
RefFrame[ 1 ] = NONE
find_mv_stack( 0 )
for ( i = 0; i < MAX_REF_MV_STACK_SIZE; i++ ) {
RefStack1Mvs[ i ] = RefStackMv[ i ][ 0 ]
}
RefFrame[ 0 ] = r0
RefFrame[ 1 ] = r1
} else {
find_mv_stack( isCompound )
}
motion_mode = read_motion_mode( isCompound )
RefWarpIdx = 0
if ( YMode == WARPMV || motion_mode == DELTAWARP ) {
for ( idx = 0; idx < MAX_WARP_REF_CANDIDATES - 1; idx++ ) {
warp_idx S()
if ( warp_idx == 0 ) {
RefWarpIdx = idx
break
}
RefWarpIdx = idx + 1
}
}
if ( YMode == WARPMV && RefWarpIdx < 2 ) {
warpmv_with_mvd S()
} else {
warpmv_with_mvd = 0
}
if ( is_joint_mvd_coding_mode(YMode) ) {
jmvd_scale_mode S()
}
RefMvIdx = 0
if ( has_newmv(YMode) || has_nearmv(YMode) ) {
m = max_drl_bits_minus_1 + 1
if ( has_second_drl( YMode ) ) {
RefMvIdx0 = read_drl_idx( 0, m )
start = ( RefFrame[ 0 ]==RefFrame[ 1 ] && YMode == NEAR_NEARMV ) ?
RefMvIdx0 + 1 : 0
RefMvIdx1 = read_drl_idx( start, m )
} else {
RefMvIdx = read_drl_idx( 0, m )
}
}
IsAdaptiveMvd = enable_adaptive_mvd && use_amvd
if ( IsAdaptiveMvd ) {
MvPrecision = FrameMvPrecision
use_most_probable_precision = 1
} else if ( enable_flex_mvres && UsePerBlockMvPrecision &&
has_newmv( YMode ) ) {
use_most_probable_precision S()
if ( use_most_probable_precision ) {
MvPrecision = FrameMvPrecision
} else {
pb_mv_precision S()
adjustedPrecision = Max( MV_PRECISION_ONE_PEL,
FrameMvPrecision - 2) -
pb_mv_precision
if ( adjustedPrecision <= MV_PRECISION_TWO_PEL ) {
MvPrecision = adjustedPrecision - 1
} else {
MvPrecision = adjustedPrecision
}
}
} else {
MvPrecision = FrameMvPrecision
use_most_probable_precision = 1
}
assign_mv( isCompound )
if ( motion_mode == DELTAWARP ) {
read_warp_delta( )
}
if ( YMode == WARPMV ) {
read_interintra_mode( 1 )
}
read_refinemv( isCompound )
read_compound_type( isCompound )
CwpIdx = CWP_EQUAL
if ( enable_cwp ) {
if ( isCompound && skip_mode ) {
CwpIdx = RefStackCwp[ RefMvIdx ]
} else if ( isCompound && !use_refinemv &&
compound_type == COMPOUND_AVERAGE &&
motion_mode == SIMPLE && !use_optflow ) {
if ( YMode == NEAR_NEARMV || (is_joint_mvd_coding_mode(YMode) &&
jmvd_scale_mode==0) ) {
for ( idx = 0; idx < MAX_CWP_NUM - 1; idx++ ) {
cwp_idx S()
if ( cwp_idx == 0 ) {
break
}
}
CwpIdx = Cwp_Weighting_Factor[ is_same_side() ][ idx ]
}
}
}
if ( isCompound && opfl_refine_type == REFINE_ALL &&
compound_type == COMPOUND_AVERAGE &&
YMode != GLOBAL_GLOBALMV &&
!skip_mode &&
CwpIdx == CWP_EQUAL &&
opfl_allowed_for_refs( RefFrame ) &&
Block_Width[ MiSize ] >= 8 && Block_Height[ MiSize ] >= 8) {
use_optflow = 1
}
if ( skip_mode || use_optflow || use_refinemv || DecidedAgainstRefinemv ||
RefFrame[ 0 ] == TIP_FRAME ) {
interp_filter = EIGHTTAP_SHARP
} else if ( interpolation_filter == SWITCHABLE ) {
if ( needs_interp_filter( ) ) {
interp_filter S()
} else {
interp_filter = EIGHTTAP
}
} else {
interp_filter = interpolation_filter
}
}

The function has_nearmv is defined as:

has_nearmv( mode ) { Descriptor
return (mode == NEARMV || mode == NEAR_NEARMV
|| mode == NEAR_NEWMV || mode == NEW_NEARMV)
}

The function has_newmv is defined as:

has_newmv( mode ) {    return (mode == NEWMV ||            mode == NEW_NEWMV ||            mode == NEAR_NEWMV ||            mode == NEW_NEARMV ||            mode == WARP_NEWMV ||            mode == JOINT_NEWMV            )}

The function needs_interp_filter is defined as:

needs_interp_filter( ) { Descriptor
large = (Min(Block_Width[ MiSize ], Block_Height[ MiSize ]) >= 8)
if ( motion_mode >= LOCALWARP ) {
return 0
} else if ( large && YMode == GLOBALMV ) {
return 0
} else if ( large && YMode == GLOBAL_GLOBALMV ) {
return 0
} else {
return 1
}
}

The function is_inter_ref_frame is defined as:

is_inter_ref_frame(ref) { Descriptor
return ref != INTRA_FRAME && ref != NONE
}

The function is_joint_mvd_coding_mode is defined as:

is_joint_mvd_coding_mode(mode) { Descriptor
return mode == JOINT_NEWMV
}

The function has_second_drl is defined as:

has_second_drl(mode) { Descriptor
return (mode == NEAR_NEARMV || mode == NEAR_NEWMV) && !skip_mode &&
!use_optflow
}

Note: Two reference lists can be used for NEAR_NEWMV, but only one for NEW_NEARMV.

The constant table Cwp_Weighting_Factor is defined as:

Cwp_Weighting_Factor[ 2 ][ MAX_CWP_NUM ] = {    { 8, 12, 4, 10, 6 },    { 8, 12, 4, 20, -4 }}

The function opfl_allowed_for_refs is defined as:

opfl_allowed_for_refs( refFrames ) { Descriptor
if ( FrameType == SWITCH_FRAME ||
is_scaled( refFrames[ 0 ], 1 ) ||
is_scaled( refFrames[ 1 ], 1 ) ) {
return 0
}
d0 = get_relative_dist( OrderHint, OrderHints[ refFrames[ 0 ] ] )
d1 = get_relative_dist( OrderHint, OrderHints[ refFrames[ 1 ] ] )
return (d0 <= 0) ^ (d1 <= 0)
}

The constant table Tip_Pred_Index_To_Mode is defined as:

Tip_Pred_Index_To_Mode[ 2 ] = {    NEARMV,    NEWMV}

The function allow_amvd_mode is defined as:

allow_amvd_mode( mode ) { Descriptor
return enable_adaptive_mvd &&
(mode == NEWMV ||
mode == NEW_NEWMV ||
mode == NEAR_NEWMV ||
mode == NEW_NEARMV ||
mode == JOINT_NEWMV)
}

5.20.29. Read warp delta syntax

read_warp_delta( ) { Descriptor
for ( i = 0; i < 6; i++ ) {
params[ i ] = WarpParamStack[ RefWarpIdx ][ i ]
}
useSixParam = enable_six_param_warp_delta && RefWarpIdx == 1
if ( YMode == WARP_NEWMV && (useSixParam || RefWarpIdx == 0) ) {
warp_delta_precision S()
params[ 0 ] = 0
params[ 1 ] = 0
params[ 2 ] += read_warp_delta_param( 2, warp_delta_precision )
params[ 3 ] += read_warp_delta_param( 3, warp_delta_precision )
if ( useSixParam ) {
params[ 4 ] += read_warp_delta_param(4, warp_delta_precision)
params[ 5 ] += read_warp_delta_param(5, warp_delta_precision)
} else {
params[ 4 ] = -params[ 3 ]
params[ 5 ] = params[ 2 ]
}
}
LocalWarpParams[ 0 ] = reduce_warp_model( params )
LocalValid[ 0 ] = 1
(LocalWarpParams[ 0 ][ 0 ], LocalWarpParams[ 0 ][ 1 ]) =
get_warp_translation( LocalWarpParams[ 0 ], 0 )
}

where the function read_warp_delta_param is specified as:

read_warp_delta_param( idx, highPrec ) { Descriptor
warp_delta_param_low S()
v = warp_delta_param_low
if ( highPrec && v == WARP_DELTA_NUM_SYMBOLS_LOW - 1 ) {
warp_delta_param_high S()
v += warp_delta_param_high
}
if ( v != 0 ) {
warp_delta_param_sign S()
if ( warp_delta_param_sign ) {
v = -v
}
}
return v << ( WARP_DELTA_STEP_BITS + 1 - highPrec )
}

5.20.30. Read drl idx syntax

read_drl_idx(start,m) { Descriptor
for ( idx = start; idx < m; idx++ ) {
drl_mode S()
if ( drl_mode == 0 ) {
return idx
}
}
return m
}

5.20.31. DIP mode info syntax

dip_mode_info( ) { Descriptor
use_dip = 0
if ( enable_dip &&
YMode == DC_PRED && PaletteSizeY == 0 &&
Block_Width[ MiSize ] > 4 && Block_Height[ MiSize ] > 4 &&
Block_Width[ MiSize ] * Block_Height[ MiSize ] >= 128 ) {
use_dip S()
if ( use_dip ) {
dip_transpose L(1)
dip_mode S()
}
}
}

5.20.32. Ref frames syntax

read_ref_frames( ) { Descriptor
if ( skip_mode ) {
(RefFrame[ 0 ], RefFrame[ 1 ]) = skip_mode_frames( )
return
}
bw4 = Num_4x4_Blocks_Wide[ MiSize ]
bh4 = Num_4x4_Blocks_High[ MiSize ]
if ( TipFrameMode != TIP_FRAME_DISABLED &&
!skip_mode && Min( bw4, bh4 ) >= 2 &&
MiSize == ChromaMiSize ) {
tip_mode S()
if ( tip_mode ) {
RefFrame[ 0 ] = TIP_FRAME
RefFrame[ 1 ] = NONE
return
}
}
if ( seg_feature_active( SEG_LVL_SKIP ) ||
seg_feature_active( SEG_LVL_GLOBALMV ) ) {
RefFrame[ 0 ] = SkipSegFrame
RefFrame[ 1 ] = NONE
} else {
if ( reference_select && is_comp_ref_allowed( ) ) {
comp_mode S()
} else {
comp_mode = SINGLE_REFERENCE
}
if ( comp_mode == COMPOUND_REFERENCE ) {
read_compound_ref()
} else {
RefFrame[ 0 ] = read_single_ref()
RefFrame[ 1 ] = NONE
}
}
}

where skip_mode_frames is specified as:

skip_mode_frames() { Descriptor
for ( n = 0; n < NNumBuf; n++ ) {
if ( NRefFrame[ n ][ 0 ] == TIP_FRAME ) {
return ( Min(ClosestPast, ClosestFuture),
Max(ClosestPast, ClosestFuture) )
}
if ( is_inter_ref_frame( NRefFrame[ n ][ 0 ] ) &&
is_inter_ref_frame( NRefFrame[ n ][ 1 ] ) ) {
return (NRefFrame[ n ][ 0 ], NRefFrame[ n ][ 1 ])
}
if ( is_inter_ref_frame( NRefFrame[ n ][ 0 ] ) ) {
break
}
}
return (SkipModeFrame[ 0 ], SkipModeFrame[ 1 ])
}

5.20.33. Read compound ref syntax

read_compound_ref() { Descriptor
RefFrame[ 0 ] = NumTotalRefs - 1
RefFrame[ 1 ] = NumTotalRefs - 1
nFound = 0
for ( ref = 0; ref < NumTotalRefs - 1 && nFound < 2; ref++ ) {
if ( nFound == 0 && ref == 2 ) {
comp_ref = 1
} else if ( nFound == 0 &&
ref + 1 >= NumSameRefCompound &&
ref + 1 == NumTotalRefs - 1 ) {
comp_ref = 1
} else {
comp_ref S()
}
if ( comp_ref ) {
RefFrame[ nFound ] = ref
nFound++
if ( ref < NumSameRefCompound ) {
ref--
}
}
}
}

5.20.34. Read single ref syntax

read_single_ref() { Descriptor
for ( ref = 0; ref < NumTotalRefs - 1; ref++ ) {
single_ref S()
if ( single_ref ) {
return ref
}
}
return NumTotalRefs - 1
}

5.20.35. Assign MV syntax

assign_mv( isCompound ) { Descriptor
mvdRead[ 0 ] = 0
mvdRead[ 1 ] = 0
baseList = 0
firstDist = 0
secondDist = 0
if (is_joint_mvd_coding_mode(YMode)) {
firstDist = Abs(get_relative_dist( OrderHints[ RefFrame[ 0 ] ],
OrderHint ))
secondDist = Abs(get_relative_dist( OrderHints[ RefFrame[ 1 ] ],
OrderHint ))
restrict0 = OrderHints[ RefFrame[ 0 ] ] == RESTRICTED_OH
restrict1 = OrderHints[ RefFrame[ 1 ] ] == RESTRICTED_OH
if ( firstDist < secondDist || ( !restrict0 && restrict1 ) ) {
baseList = 1
(firstDist, secondDist) = (secondDist, firstDist)
}
if (!is_same_side()) {
secondDist = -secondDist
}
}
for ( i = 0; i < 1 + isCompound; i++ ) {
if ( use_intrabc ) {
compMode = intrabc_mode ? NEARMV : NEWMV
} else {
compMode = get_mode( i, baseList )
}
if ( use_intrabc ) {
PredMvs[ 0 ] = RefStackMv[ RefMvIdx ][ 0 ]
} else if ( compMode == GLOBALMV ) {
PredMvs[ i ] = GlobalMvs[ i ]
} else if ( compMode == WARPMV ) {
PredMvs[ 0 ] = get_warp_motion_vector(
WarpParamStack[ RefWarpIdx ],
warpmv_with_mvd ? FrameMvPrecision :
MV_PRECISION_EIGHTH_PEL)
} else if (has_second_drl(YMode)) {
if ( i == 0 ) {
PredMvs[ i ] = RefStack0Mvs[ RefMvIdx0 ]
} else {
PredMvs[ i ] = RefStack1Mvs[ RefMvIdx1 ]
}
} else {
PredMvs[ i ] = RefStackMv[ RefMvIdx ][ i ]
}
if ( compMode == NEWMV || warpmv_with_mvd || compMode == WARP_NEWMV ) {
if ( !warpmv_with_mvd && MvPrecision < MV_PRECISION_HALF_PEL &&
!IsAdaptiveMvd ) {
lower_mv_precision( MvPrecision, PredMvs[ i ] )
}
diffMvs[ i ] = read_mv( )
mvdRead[ i ] = 1
} else {
for ( comp = 0; comp < 2; comp++ ) {
diffMvs[ i ][ comp ] = 0
}
}
}
shift = MV_PRECISION_EIGHTH_PEL - MvPrecision
lastSign = 0
numNonzero = 0
for ( i = 0; i < 1 + isCompound; i++ ) {
if ( mvdRead[ i ] ) {
for ( comp = 0; comp < 2; comp++ ) {
if ( diffMvs[ i ][ comp ] != 0 ) {
lastRef = i
lastComp = comp
lastSign += diffMvs[ i ][ comp ] >> shift
numNonzero++
}
}
}
}
thresh = YMode == NEW_NEWMV ? 4 : 1
allowed = is_mvd_sign_derive_allowed(isCompound) && numNonzero >= thresh
for ( i = 0; i < 1 + isCompound; i++ ) {
if ( mvdRead[ i ] ) {
for ( comp = 0; comp < 2; comp++ ) {
if ( diffMvs[ i ][ comp ] != 0 ) {
if ( allowed && i == lastRef && comp == lastComp ) {
mv_sign = lastSign & 1
} else {
mv_sign L(1)
}
diffMvs[ i ][ comp ] = mv_sign ? -diffMvs[ i ][ comp ] :
diffMvs[ i ][ comp ]
}
}
}
}
if ( is_joint_mvd_coding_mode( YMode ) ) {
projMv = get_mv_projection( diffMvs[ baseList ], secondDist, firstDist)
if ( use_amvd ) {
for ( comp = 0; comp < 2; comp++ ) {
if ( jmvd_scale_mode == 1 ) {
projMv[ comp ] = projMv[ comp ] * 2
} else if ( jmvd_scale_mode == 2 ) {
projMv[ comp ] = projMv[ comp ] / 2
}
}
} else if ( jmvd_scale_mode > 0 ) {
comp = (jmvd_scale_mode - 1) & 1
if ( jmvd_scale_mode <= 2 ) {
projMv[ comp ] = projMv[ comp ] * 2
} else {
projMv[ comp ] = projMv[ comp ] / 2
}
}
for ( comp = 0; comp < 2; comp++ ) {
BlockMvs[ baseList ][ comp ] = mv_clamp_to_integer(
PredMvs[ baseList ][ comp ] + diffMvs[ baseList ][ comp ] )
BlockMvs[ 1 - baseList ][ comp ] = mv_clamp_to_integer(
PredMvs[ 1 - baseList ][ comp ] + projMv[ comp ] )
}
} else {
for ( i = 0; i < 1 + isCompound; i++ ) {
for ( comp = 0; comp < 2; comp++ ) {
BlockMvs[ i ][ comp ] = mv_clamp_to_integer(
PredMvs[ i ][ comp ] + diffMvs[ i ][ comp ] )
}
}
}
}

where the function is_same_side is defined as:

is_same_side() { Descriptor
return ( FrameDistance[ RefFrame[ 0 ] ] < 0 &&
FrameDistance[ RefFrame[ 1 ] ] < 0) ||
( FrameDistance[ RefFrame[ 0 ] ] > 0 &&
FrameDistance[ RefFrame[ 1 ] ] > 0)
}

and the function is_mvd_sign_derive_allowed is defined as:

is_mvd_sign_derive_allowed(isCompound) { Descriptor
if ( use_intrabc ||
!enable_mvd_sign_derive ||
motion_mode != SIMPLE ||
IsAdaptiveMvd || skip_mode ||
allow_screen_content_tools ||
FrameMvPrecision > MV_PRECISION_QUARTER_PEL ||
MvPrecision >= MV_PRECISION_QUARTER_PEL ||
has_nearmv(YMode) ) {
return 0
}
if ( isCompound ) {
return RefMvIdx == 0
} else {
return 1
}
}

and the function lower_mv_precision (which modifies the contents of the input motion vector to the target precision) is defined as:

lower_mv_precision( precision, candMv ) {    bits = MV_PRECISION_EIGHTH_PEL - precision    radix = 1 << bits    for ( i = 0; i < 2; i++ ) {        a = Abs( candMv[ i ] )        aInt = Round2( a - 1, bits )        if ( candMv[ i ] >= 0 ) {            candMv[ i ] = aInt << bits        } else {            candMv[ i ] = (-aInt) << bits        }        if ((aInt << bits) != a) {            candMv[ i ] = Clip3( MV_LOW + radix, MV_UPP - radix, candMv[ i ] )        }    }}

and the function mv_clamp_to_integer (which adjusts a motion vector component to an integer location if it would have overflowed the allowed range) is defined as:

mv_clamp_to_integer( v ) {    if ( v < MV_LOW + 1 ) {        return MV_LOW + 8    } else if ( v > MV_UPP - 1 ) {        return MV_UPP - 8    } else {        return v    }}

5.20.36. Read motion mode syntax

read_motion_mode( isCompound ) { Descriptor
motion_mode_allowed( isCompound )
inter_intra = 0
localAllowed = AllowedMotionModes[ LOCALWARP ] &&
frame_enabled_motion_modes[ LOCALWARP ]
if ( YMode == WARPMV ) {
return DELTAWARP
}
if ( YMode == WARP_NEWMV ) {
extendAllowed = AllowedMotionModes[ EXTENDWARP ] &&
frame_enabled_motion_modes[ EXTENDWARP ]
if ( extendAllowed ) {
use_extend_warp S()
if ( use_extend_warp ) {
return EXTENDWARP
}
}
if ( localAllowed ) {
use_local_warp S()
if ( use_local_warp ) {
return LOCALWARP
}
}
return DELTAWARP
}
if ( AllowedMotionModes[ INTERINTRA ] &&
frame_enabled_motion_modes[ INTERINTRA ] ) {
read_interintra_mode( 0 )
if ( inter_intra ) {
return INTERINTRA
}
}
if ( localAllowed ) {
use_local_warp S()
if ( use_local_warp ) {
return LOCALWARP
}
}
return SIMPLE
}

The function motion_mode_allowed works out the allowed motion modes as follows:

motion_mode_allowed(isCompound) { Descriptor
for ( i = 0; i < MOTION_MODES; i++ ) {
AllowedMotionModes[ i ] = 0
}
if ( YMode == WARPMV ) {
AllowedMotionModes[ DELTAWARP ] = 1
return
}
if ( YMode == WARP_NEWMV ) {
AllowedMotionModes[ LOCALWARP ] = WarpSampleFound[ 0 ]
AllowedMotionModes[ EXTENDWARP ] = WarpSampleFound[ 0 ]
AllowedMotionModes[ DELTAWARP ] = 1
return
}
if ( skip_mode || RefFrame[ 0 ] == INTRA_FRAME || use_bawp ||
RefFrame[ 0 ] == TIP_FRAME ||
seg_feature_active(SEG_LVL_SKIP) ||
seg_feature_active(SEG_LVL_GLOBALMV) ||
( isCompound && is_thin_4xn_nx4_block() ) ) {
return
}
AllowedMotionModes[ INTERINTRA ] = (!isCompound &&
MiSize >= BLOCK_8X8 &&
Block_Width[ MiSize ] <= 64 &&
Block_Height[ MiSize ] <= 64)
if ( RefFrame[ 0 ] == RefFrame[ 1 ] ) {
return
}
if ( !force_integer_mv &&
( YMode == GLOBALMV || YMode == GLOBAL_GLOBALMV ) &&
GmType[ RefFrame[ 0 ] ] > IDENTITY ) {
return
}
if ( Min( Block_Width[ MiSize ], Block_Height[ MiSize ] ) < 8 ) {
return
}
AllowedMotionModes[ LOCALWARP ] = !force_integer_mv && YMode == NEW_NEWMV &&
!use_optflow &&
opfl_refine_type != REFINE_ALL &&
WarpSampleFound[ 0 ] &&
WarpSampleFound[ 1 ]
}

where is_scaled is a function that determines whether a reference frame uses scaling and is specified as:

is_scaled( refFrame, checkRestricted ) { Descriptor
if ( checkRestricted && OrderHints[ refFrame ] == RESTRICTED_OH ) {
return 1
}
refIdx = ref_frame_idx[ refFrame ]
xScale = ( ( RefFrameWidth[ refIdx ] << REF_SCALE_SHIFT ) +
( FrameWidth / 2 ) ) / FrameWidth
yScale = ( ( RefFrameHeight[ refIdx ] << REF_SCALE_SHIFT ) +
( FrameHeight / 2 ) ) / FrameHeight
noScale = 1 << REF_SCALE_SHIFT
return xScale != noScale || yScale != noScale
}

and is_thin_4xn_nx4_block is a function that tests the block size as follows:

is_thin_4xn_nx4_block( ) { Descriptor
w = Block_Width[ MiSize ]
h = Block_Height[ MiSize ]
return (w == 4 && h >= 16) || (h == 4 && w >= 16)
}

5.20.37. Read inter intra syntax

read_interintra_mode( isWarp ) { Descriptor
if ( isWarp ) {
if ( Block_Width[ MiSize ] <= 64 && Block_Height[ MiSize ] <= 64 ) {
warp_inter_intra S()
inter_intra = warp_inter_intra
} else {
inter_intra = 0
}
} else {
inter_intra S()
}
if ( inter_intra ) {
interintra_mode S()
RefFrame[ 1 ] = INTRA_FRAME
AngleDeltaY = 0
AngleDeltaUV = 0
UVMode = DC_PRED
if ( Wedge_Bits[ MiSize ] == 0 ) {
wedge_interintra = 0
} else {
wedge_interintra S()
}
if ( wedge_interintra ) {
read_wedge_mode()
wedge_sign = 0
}
}
}

5.20.38. Read compound type syntax

read_compound_type( isCompound ) { Descriptor
comp_group_idx = 0
if ( skip_mode || use_optflow ||
( YMode == JOINT_NEWMV && use_amvd ) ||
( use_refinemv && is_switchable_refinemv() ) ) {
compound_type = COMPOUND_AVERAGE
return
}
if ( isCompound ) {
n = Wedge_Bits[ MiSize ]
if ( enable_masked_compound && !is_thin_4xn_nx4_block() ) {
comp_group_idx S()
if ( comp_group_idx != 0 && use_refinemv ) {
DecidedAgainstRefinemv = 1
use_refinemv = 0
}
}
if ( comp_group_idx == 0 ) {
compound_type = COMPOUND_AVERAGE
} else {
if ( n == 0 ) {
compound_type = COMPOUND_DIFFWTD
} else {
compound_type S()
}
}
if ( compound_type == COMPOUND_WEDGE ) {
read_wedge_mode()
wedge_sign L(1)
} else if ( compound_type == COMPOUND_DIFFWTD ) {
mask_type L(1)
}
} else {
if ( inter_intra ) {
compound_type = wedge_interintra ? COMPOUND_WEDGE : COMPOUND_INTRA
} else {
compound_type = COMPOUND_AVERAGE
}
}
}

5.20.39. Read refine mv syntax

read_refinemv( isCompound ) { Descriptor
use_refinemv = 0
DecidedAgainstRefinemv = 0
if ( enable_refinemv &&
isCompound &&
(Block_Width[ MiSize ] >= 16 || Block_Height[ MiSize ] >= 16) &&
(Block_Width[ MiSize ] >= 8 && Block_Height[ MiSize ] >= 8) &&
is_refinemv_allowed_mode() &&
is_refinemv_allowed_reference(RefFrame)
) {
if (is_switchable_refinemv()) {
use_refinemv S()
} else {
use_refinemv = 1
}
}
}

where the functions is_refinemv_allowed_mode, is_switchable_refinemv, is_refinemv_allowed_reference are specified as:

is_refinemv_allowed_mode() { Descriptor
if ( skip_mode || YMode == GLOBAL_GLOBALMV || motion_mode != SIMPLE ) {
return 0
}
if ( opfl_refine_type == REFINE_SWITCHABLE &&
has_newmv( YMode ) &&
!use_optflow ) {
return 0
}
return 1
}
is_switchable_refinemv() {
if ( YMode == NEAR_NEARMV ||
(YMode == JOINT_NEWMV && use_optflow &&
opfl_refine_type == REFINE_SWITCHABLE)) {
return 0
}
return 1
}
is_refinemv_allowed_reference( refFrames ) {
if ( FrameType == SWITCH_FRAME ||
is_scaled( refFrames[ 0 ], 1 ) ||
is_scaled( refFrames[ 1 ], 1 ) ) {
return 0
}
d0 = get_relative_dist( OrderHint, OrderHints[ refFrames[ 0 ] ] )
d1 = get_relative_dist( OrderHint, OrderHints[ refFrames[ 1 ] ] )
return d0 != 0 && d0 == -d1
}

5.20.40. Read wedge mode syntax

read_wedge_mode() { Descriptor
wedge_quad S()
wedge_angle S()
wedgeAngle = wedge_quad * 5 + wedge_angle
if ( (wedgeAngle >= H_WEDGE_ANGLES) ||
(wedgeAngle == WEDGE_90) ||
(wedgeAngle == WEDGE_0) ) {
wedge_dist2 S()
wedgeDist = wedge_dist2 + 1
} else {
wedge_dist1 S()
wedgeDist = wedge_dist1
}
WedgeIndex = Wedge_Angle_Dist_2_Index[ wedgeAngle ][ wedgeDist ]
}

where the lookup table Wedge_Angle_Dist_2_Index is specified as:

Wedge_Angle_Dist_2_Index[ WEDGE_ANGLES ][ NUM_WEDGE_DIST ] = {    { -1, 0, 1, 2 },    { 3, 4, 5, 6 },    { 7, 8, 9, 10 },    { 11, 12, 13, 14 },    { 15, 16, 17, 18 },    { -1, 19, 20, 21 },    { 22, 23, 24, 25 },    { 26, 27, 28, 29 },    { 30, 31, 32, 33 },    { 34, 35, 36, 37 },    { -1, 38, 39, 40 },    { -1, 41, 42, 43 },    { -1, 44, 45, 46 },    { -1, 47, 48, 49 },    { -1, 50, 51, 52 },    { -1, 53, 54, 55 },    { -1, 56, 57, 58 },    { -1, 59, 60, 61 },    { -1, 62, 63, 64 },    { -1, 65, 66, 67 }}

5.20.41. Get mode function

get_mode( refList, baseList ) { Descriptor
if ( YMode == JOINT_NEWMV ) {
if ( refList == baseList ) {
compMode = NEWMV
} else {
compMode = NEARMV
}
} else if ( refList == 0 ) {
if ( YMode == NEW_NEWMV || YMode == NEW_NEARMV ) {
compMode = NEWMV
} else if ( YMode < NEAR_NEARMV ) {
compMode = YMode
} else if ( YMode == NEAR_NEARMV || YMode == NEAR_NEWMV ) {
compMode = NEARMV
} else {
compMode = GLOBALMV
}
} else {
if ( YMode == NEW_NEWMV || YMode == NEAR_NEWMV ) {
compMode = NEWMV
} else if ( YMode == NEAR_NEARMV || YMode == NEW_NEARMV ) {
compMode = NEARMV
} else {
compMode = GLOBALMV
}
}
return compMode
}

5.20.42. MV syntax

read_mv( ) { Descriptor
diffMv[ 0 ] = 0
diffMv[ 1 ] = 0
if ( use_intrabc ) {
MvCtx = MV_INTRABC_CONTEXT
} else {
MvCtx = 0
}
if ( IsAdaptiveMvd ) {
mv_joint S()
if ( mv_joint == MV_JOINT_HZVNZ || mv_joint == MV_JOINT_HNZVNZ ) {
diffMv[ 0 ] = read_mv_component( 0 )
}
if ( mv_joint == MV_JOINT_HNZVZ || mv_joint == MV_JOINT_HNZVNZ ) {
diffMv[ 1 ] = read_mv_component( 1 )
}
} else {
shell_set S()
shell_class S()
shellClass = shell_class
if ( shell_set ) {
shellClass += (11 + MvPrecision) >> 1
if ( MvPrecision == MV_PRECISION_EIGHTH_PEL && shell_class == 7 ) {
joint_shell_last_two_classes S()
shellClass += joint_shell_last_two_classes
}
}
shellClassOffset = 0
if ( shellClass < 2 ) {
shell_offset_low_class S()
shellClassOffset = shell_offset_low_class
} else if ( shellClass == 2 ) {
for ( i = 0; i < 3; i++ ) {
if ( i == 0 ) {
shell_offset_class2 S()
shellClassOffset = shell_offset_class2
} else {
shell_offset_class2_high L(1)
shellClassOffset = shell_offset_class2_high + i
}
if ( shellClassOffset == i ) {
break
}
}
} else {
for ( i = 0; i < shellClass; i++ ) {
shell_offset_other_class S()
shellClassOffset |= shell_offset_other_class << i
}
}
shellClassBaseIndex = (shellClass == 0) ? 0 : (1 << shellClass)
shellIndex = shellClassBaseIndex + shellClassOffset
if ( shellIndex > 0 ) {
col = 0
maximumPairIndex = shellIndex >> 1
if ( maximumPairIndex > 0 ) {
maxIdxBits = Min(maximumPairIndex, MAX_COL_TRUNCATED_UNARY_VAL)
for ( i = 0; i < maxIdxBits; i++ ) {
col_mv_greater S()
col = i + col_mv_greater
if ( col_mv_greater == 0 ) {
break
}
}
if ( maximumPairIndex > MAX_COL_TRUNCATED_UNARY_VAL &&
col == MAX_COL_TRUNCATED_UNARY_VAL ) {
col_remainder NS(maximumPairIndex - 1)
col = col_remainder + MAX_COL_TRUNCATED_UNARY_VAL
}
}
skipCodingColBit = (col == maximumPairIndex) &&
((shellIndex & 1) == 0)
if ( skipCodingColBit ) {
diffMv[ 1 ] = maximumPairIndex
} else {
col_mv_index S()
if ( col_mv_index == 0 ) {
diffMv[ 1 ] = col
} else {
diffMv[ 1 ] = shellIndex - col
}
}
diffMv[ 0 ] = shellIndex - diffMv[ 1 ]
shift = MV_PRECISION_EIGHTH_PEL - MvPrecision
diffMv[ 0 ] = diffMv[ 0 ] << shift
diffMv[ 1 ] = diffMv[ 1 ] << shift
}
}
return diffMv
}

5.20.43. MV component syntax

read_mv_component( comp ) { Descriptor
amvd_index S()
return Amvd_Index_To_Mvd[ amvd_index ]
}

where the constant table Amvd_Index_To_Mvd is defined as:

Amvd_Index_To_Mvd[ MAX_AMVD_INDEX ] = {     2, 4, 6, 8, 16, 32, 64, 128 }

5.20.44. Compute prediction syntax

compute_prediction() { Descriptor
sbMask = Num_4x4_Blocks_Wide[ SbSize ] - 1
for ( plane = PlaneStart; plane < 1 + HasChroma * 2; plane++ ) {
planeSz = get_plane_residual_size( plane > 0 ? ChromaMiSize : MiSize,
plane )
num4x4W = Num_4x4_Blocks_Wide[ planeSz ]
num4x4H = Num_4x4_Blocks_High[ planeSz ]
log2W = MI_SIZE_LOG2 + Mi_Width_Log2[ planeSz ]
log2H = MI_SIZE_LOG2 + Mi_Height_Log2[ planeSz ]
subX = (plane > 0) ? SubsamplingX : 0
subY = (plane > 0) ? SubsamplingY : 0
candRow = plane > 0 ? ChromaMiRow : MiRow
candCol = plane > 0 ? ChromaMiCol : MiCol
baseX = (candCol >> subX) * MI_SIZE
baseY = (candRow >> subY) * MI_SIZE
subBlockMiRow = candRow & sbMask
subBlockMiCol = candCol & sbMask
if ( FrameIsIntra ) {
sub8x8Inter = 0
} else {
sub8x8Inter = (plane > 0 && MiSize != ChromaMiSize)
}
isInterIntra = is_inter && RefFrame[ 1 ] == INTRA_FRAME && !sub8x8Inter
if ( isInterIntra ) {
if ( interintra_mode == II_DC_PRED ) {
mode = DC_PRED
}
else if ( interintra_mode == II_V_PRED ) mode = V_PRED
else if ( interintra_mode == II_H_PRED ) mode = H_PRED
else mode = SMOOTH_PRED
predict_intra( plane, baseX, baseY,
plane == 0 ? AvailL : AvailLChroma,
plane == 0 ? AvailU : AvailUChroma,
count_top_right_avail( plane,
( subBlockMiCol >> subX ),
( subBlockMiRow >> subY ),
num4x4W),
count_bottom_left_avail( plane,
( subBlockMiCol >> subX ),
( subBlockMiRow >> subY ),
num4x4H),
mode,
log2W, log2H )
for ( i = 0; i < num4x4H * 4; i++ ) {
for ( j = 0; j < num4x4W * 4; j++ ) {
IntraPred[ i ][ j ] =
CurrFrame[ plane ][ baseY + i ][ baseX + j ]
}
}
}
if ( is_inter ) {
for ( r = 0; r < num4x4H << subY ; r++ ) {
for ( c = 0; c < num4x4W << subX ; c++ ) {
if ( FrameIsIntra ) {
doBlock = r==0 && c==0
predSize = plane > 0 ? ChromaMiSize : MiSize
mvRow = MiRow
mvCol = MiCol
} else {
mvRow = candRow + r
mvCol = candCol + c
doBlock = mvRow < MiRows && mvCol < MiCols &&
MiRowBase[ 0 ][ mvRow ][ mvCol ] == mvRow &&
MiColBase[ 0 ][ mvRow ][ mvCol ] == mvCol
predSize = MiSizes[ 0 ][ mvRow ][ mvCol ]
}
if ( doBlock ) {
predW = Block_Width[ predSize ] >> subX
predH = Block_Height[ predSize ] >> subY
x = (c * 4) >> subX
y = (r * 4) >> subY
predict_inter( plane, baseX + x, baseY + y,
predW, predH,
mvRow, mvCol, 0, sub8x8Inter)
}
}
}
if ( isInterIntra ) {
h = num4x4H * 4
w = num4x4W * 4
if ( compound_type == COMPOUND_WEDGE && plane == 0 ) {
wedge_mask( w, h )
} else if (compound_type == COMPOUND_INTRA) {
intra_mode_variant_mask( w, h )
}
mask_blend( plane, baseX, baseY, w, h )
}
}
}
}

5.20.45. Residual syntax

residual( ) { Descriptor
widthChunks = Max( 1, Block_Width[ MiSize ] >> 6 )
heightChunks = Max( 1, Block_Height[ MiSize ] >> 6 )
miSizeChunk = ( widthChunks > 1 || heightChunks > 1 ) ? BLOCK_64X64 : MiSize
doubleChromaW = SubsamplingX && widthChunks > 1 && !Lossless
doubleChromaH = SubsamplingY && heightChunks > 1 && !Lossless
for ( startChunkY = 0; startChunkY < heightChunks; startChunkY += 2 ) {
for ( startChunkX = 0; startChunkX < widthChunks; startChunkX += 2 ) {
for( chunkY = startChunkY;
chunkY < Min(startChunkY + 2, heightChunks) ; chunkY++ ) {
for ( chunkX = startChunkX;
chunkX < Min(startChunkX + 2, widthChunks); chunkX++ ) {
miRowChunk = MiRow + ( chunkY << 4 )
miColChunk = MiCol + ( chunkX << 4 )
isCfl = !is_inter && UVMode == UV_CFL_PRED
atStart = (!doubleChromaW || (chunkX&1) == 0) &&
(!doubleChromaH || (chunkY&1) == 0)
atEnd = (!doubleChromaW || (chunkX&1) == 1) &&
(!doubleChromaH || (chunkY&1) == 1)
if ( HasChroma && isCfl && (doubleChromaW || doubleChromaH) ) {
doChromaParse = atStart
doChromaRecon = 0
doChromaReconAfter = atEnd
} else {
doChromaParse = HasChroma && atStart
doChromaRecon = doChromaParse
doChromaReconAfter = 0
}
for ( plane = PlaneStart; plane < 1 + doChromaParse * 2; plane++ ) {
if ( plane > 0 && ChromaMiSize != MiSize ) {
planeSz = get_plane_residual_size( ChromaMiSize, plane )
} else {
planeSz = get_plane_residual_size( miSizeChunk, plane )
}
num4x4W = Num_4x4_Blocks_Wide[ planeSz ]
num4x4H = Num_4x4_Blocks_High[ planeSz ]
doRecon = plane == 0 || doChromaRecon
doPred = doRecon
if ( plane > 0 && doubleChromaW ) {
num4x4W = num4x4W << 1
}
if ( plane > 0 && doubleChromaH ) {
num4x4H = num4x4H << 1
}
subX = (plane > 0) ? SubsamplingX : 0
subY = (plane > 0) ? SubsamplingY : 0
if ( miRowChunk < MiRows && miColChunk < MiCols ) {
baseXBlock =
(plane > 0 ? ChromaMiCol >> subX : MiCol) * MI_SIZE
baseYBlock =
(plane > 0 ? ChromaMiRow >> subY : MiRow) * MI_SIZE
txSz = Lossless ? TX_4X4 : get_tx_size( plane, TX_4X4 )
stepX = Tx_Width[ txSz ] >> 2
stepY = Tx_Height[ txSz ] >> 2
allowCorners = 1
if ( plane == 0 &&
LumaTxScanOrder[ miRowChunk ][ miColChunk ] ) {
for ( x4 = 0; x4 < num4x4W; x4 += stepX ) {
col = miColChunk + x4
for ( y4 = 0; y4 < num4x4H; y4 += stepY ) {
row = miRowChunk + y4
if ( row >= MiRows || col >= MiCols ) {
break
}
txSz = LumaTxSizes[ row ][ col ]
allowCorners = !LumaTxMiddle[ row ][ col ]
stepX = Tx_Width[ txSz ] >> 2
stepY = Tx_Height[ txSz ] >> 2
transform_block( plane, baseXBlock, baseYBlock,
txSz,
x4 + ( (chunkX << 4) >> subX ),
y4 + ( (chunkY << 4) >> subY ),
allowCorners, doParse = 1,
doPred = 1, doRecon = 1,
eob = 0 )
}
if ( col >= MiCols ) {
break
}
}
} else {
for ( y4 = 0; y4 < num4x4H; y4 += stepY ) {
for ( x4 = 0; x4 < num4x4W; x4 += stepX ) {
if ( plane == 0 ) {
row = miRowChunk + y4
col = miColChunk + x4
if ( row >= MiRows || col >= MiCols ) {
break
}
txSz = LumaTxSizes[ row ][ col ]
allowCorners = !LumaTxMiddle[ row ][ col ]
stepX = Tx_Width[ txSz ] >> 2
stepY = Tx_Height[ txSz ] >> 2
}
eobs[ plane ] =
transform_block( plane, baseXBlock,
baseYBlock, txSz,
x4 + ( (chunkX << 4) >> subX ),
y4 + ( (chunkY << 4) >> subY ),
allowCorners, doParse = 1,
doPred, doRecon, eob = 0 )
}
if ( plane == 0 && row >= MiRows ) {
break
}
}
}
}
}
if ( doChromaReconAfter ) {
for ( plane = 1; plane < 3; plane++ ) {
miRowChunk = MiRow + ( (chunkY - doubleChromaH) << 4 )
miColChunk = MiCol + ( (chunkX - doubleChromaW) << 4 )
if ( miRowChunk < MiRows && miColChunk < MiCols ) {
subX = SubsamplingX
subY = SubsamplingY
baseXBlock = (ChromaMiCol >> subX) * MI_SIZE
baseYBlock = (ChromaMiRow >> subY) * MI_SIZE
txSz = get_tx_size( plane, TX_4X4 )
transform_block( plane, baseXBlock, baseYBlock, txSz,
( ( (chunkX - doubleChromaW) << 4 ) >> subX ),
( ( (chunkY - doubleChromaH) << 4 ) >> subY ),
allowCorners = 1, doParse = 0, doPred = 1,
doRecon = 1, eobs[ plane ] )
}
}
}
}
}
}
}
}

5.20.46. Transform block syntax

transform_block( plane, baseX, baseY, txSz, x, y, allowCorners, doParse, doPred, doRecon, eob ) { Descriptor
startX = baseX + 4 * x
startY = baseY + 4 * y
subX = (plane > 0) ? SubsamplingX : 0
subY = (plane > 0) ? SubsamplingY : 0
maxX = (MiCols * MI_SIZE) >> subX
maxY = (MiRows * MI_SIZE) >> subY
if ( startX >= maxX || startY >= maxY ) {
return 0
}
row = ( startY << subY ) >> MI_SIZE_LOG2
col = ( startX << subX ) >> MI_SIZE_LOG2
if (plane == 0 || !is_cctx_allowed()) {
if ( doPred ) {
make_intra_prediction(plane,startX,startY,txSz,x,y,allowCorners)
}
if ( !skip_flag ) {
if ( doParse ) {
eob = coeffs( plane, startX, startY, txSz )
}
if ( doParse && eob > 0 ) {
dequant( plane, txSz )
save_dequant(plane, txSz)
}
if ( doRecon && eob > 0 ) {
get_dequant(plane, txSz, CCTX_NONE)
reconstruct( plane, startX, startY, txSz )
}
}
store_tx_info( plane, row, col, txSz, eob, doParse, doPred )
return eob
} else if ( plane == 1 ) {
return 0
} else {
if ( doParse && !skip_flag ) {
for ( p = 1; p <= 2; p++ ) {
eob = coeffs( p, startX, startY, txSz )
CctxEobs[ p ] = eob
if ( eob > 0 ) {
dequant( p, txSz )
}
save_dequant(p, txSz)
}
}
for ( p = 1; p <= 2; p++ ) {
if ( doPred ) {
make_intra_prediction( p, startX, startY, txSz, x, y,
allowCorners)
}
if ( doRecon && !skip_flag ) {
planeEob = CctxEobs[ p ]
if ( planeEob > 0 || cctx_type != CCTX_NONE ) {
get_dequant(p, txSz, cctx_type)
reconstruct( p, startX, startY, txSz )
}
}
store_tx_info( p, row, col, txSz, 0, doParse, doPred )
}
return 0
}
}

The function store_tx_info is defined as:

store_tx_info(plane, row, col, txSz, eob, doParse, doPred) { Descriptor
subX = (plane > 0) ? SubsamplingX : 0
subY = (plane > 0) ? SubsamplingY : 0
sbMask = Num_4x4_Blocks_Wide[ SbSize ] - 1
subBlockMiRow = row & sbMask
subBlockMiCol = col & sbMask
stepX = Tx_Width[ txSz ] >> MI_SIZE_LOG2
stepY = Tx_Height[ txSz ] >> MI_SIZE_LOG2
for ( i = 0; i < stepY; i++ ) {
for ( j = 0; j < stepX; j++ ) {
if ( doParse ) {
if ( plane == 0 ) {
LrTxSkip[ row + i ][ col + j ] = skip_flag || (eob == 0)
}
LoopfilterTxSizes[ plane ]
[ (row >> subY) + i ]
[ (col >> subX) + j ] = txSz
TxColBase[ plane ]
[ (row >> subY) + i ]
[ (col >> subX) + j ] = col
TxRowBase[ plane ]
[ (row >> subY) + i ]
[ (col >> subX) + j ] = row
}
if ( doPred ) {
BlockDecoded[ plane ]
[ ( subBlockMiRow >> subY ) + i ]
[ ( subBlockMiCol >> subX ) + j ] = 1
}
}
}
}

The function make_intra_prediction (which calls intra prediction processes) is defined as:

make_intra_prediction(plane, startX, startY, txSz, x, y, allowCorners) { Descriptor
if ( !is_inter ) {
stepX = Tx_Width[ txSz ] >> MI_SIZE_LOG2
stepY = Tx_Height[ txSz ] >> MI_SIZE_LOG2
subX = (plane > 0) ? SubsamplingX : 0
subY = (plane > 0) ? SubsamplingY : 0
row = ( startY << subY ) >> MI_SIZE_LOG2
col = ( startX << subX ) >> MI_SIZE_LOG2
sbMask = Num_4x4_Blocks_Wide[ SbSize ] - 1
subBlockMiRow = row & sbMask
subBlockMiCol = col & sbMask
if ( plane == 0 && PaletteSizeY ) {
predict_palette( startX, startY, x, y, txSz )
} else {
isCfl = ( plane > 0 && UVMode == UV_CFL_PRED )
if ( plane == 0 ) {
mode = YMode
} else {
mode = ( isCfl ) ? DC_PRED : UVMode
}
log2W = Tx_Width_Log2[ txSz ]
log2H = Tx_Height_Log2[ txSz ]
predict_intra( plane, startX, startY,
( plane == 0 ? AvailL : AvailLChroma ) || x > 0,
( plane == 0 ? AvailU : AvailUChroma ) || y > 0,
allowCorners ? count_top_right_avail( plane,
( subBlockMiCol >> subX ),
( subBlockMiRow >> subY ),
stepX) : 0,
allowCorners ? count_bottom_left_avail( plane,
( subBlockMiCol >> subX ),
( subBlockMiRow >> subY ),
stepY) : 0,
mode,
log2W, log2H )
if ( isCfl ) {
predict_chroma_from_luma( plane, startX, startY, txSz )
}
}
}
}

The functions count_top_right_avail and count_bottom_left_avail (which count how many samples have already been decoded in the corners) are defined as:

count_top_right_avail(plane, x4, y4, w4) { Descriptor
numTopRight = 0
for ( i = 0; i < w4; i++ ) {
if ( BlockDecoded[ plane ][ y4 - 1 ][ x4 + w4 + i ] ) {
numTopRight = i + 1
} else {
break
}
}
return numTopRight
}
count_bottom_left_avail(plane, x4, y4, h4) {
numBottomLeft = 0
for ( i = 0; i < h4; i++ ) {
if ( BlockDecoded[ plane ][ y4 + h4 + i ][ x4 - 1 ] ) {
numBottomLeft = i + 1
} else {
break
}
}
return numBottomLeft
}

5.20.47. Get TX size function

get_tx_size( plane, txSz ) { Descriptor
if ( plane == 0 ) {
return txSz
}
uvTx = Max_Tx_Size_Rect[ get_plane_residual_size( ChromaMiSize, plane ) ]
return uvTx
}

5.20.48. Get plane residual size function

The get_plane_residual_size returns the size of a residual block for the specified plane. (The residual block will always have width and height at least equal to 4.)

get_plane_residual_size( subsize, plane ) { Descriptor
subx = plane > 0 ? SubsamplingX : 0
suby = plane > 0 ? SubsamplingY : 0
return Subsampled_Size[ subsize ][ subx ][ suby ]
}

The Subsampled_Size table is defined as:

Subsampled_Size[ BLOCK_SIZES ][ 2 ][ 2 ] = {  { { BLOCK_4X4,    BLOCK_4X4},      {BLOCK_4X4,     BLOCK_4X4} },  { { BLOCK_4X8,    BLOCK_4X4},      {BLOCK_INVALID, BLOCK_4X4} },  { { BLOCK_8X4,    BLOCK_INVALID},  {BLOCK_4X4,     BLOCK_4X4} },  { { BLOCK_8X8,    BLOCK_8X4},      {BLOCK_4X8,     BLOCK_4X4} },  { {BLOCK_8X16,    BLOCK_8X8},      {BLOCK_4X16,    BLOCK_4X8} },  { {BLOCK_16X8,    BLOCK_16X4},     {BLOCK_8X8,     BLOCK_8X4} },  { {BLOCK_16X16,   BLOCK_16X8},     {BLOCK_8X16,    BLOCK_8X8} },  { {BLOCK_16X32,   BLOCK_16X16},    {BLOCK_8X32,    BLOCK_8X16} },  { {BLOCK_32X16,   BLOCK_32X8},     {BLOCK_16X16,   BLOCK_16X8} },  { {BLOCK_32X32,   BLOCK_32X16},    {BLOCK_16X32,   BLOCK_16X16} },  { {BLOCK_32X64,   BLOCK_32X32},    {BLOCK_16X64,   BLOCK_16X32} },  { {BLOCK_64X32,   BLOCK_64X16},    {BLOCK_32X32,   BLOCK_32X16} },  { {BLOCK_64X64,   BLOCK_64X32},    {BLOCK_32X64,   BLOCK_32X32} },  { {BLOCK_64X128,  BLOCK_64X64},    {BLOCK_INVALID, BLOCK_32X64} },  { {BLOCK_128X64,  BLOCK_INVALID},  {BLOCK_64X64,   BLOCK_64X32} },  { {BLOCK_128X128, BLOCK_128X64},   {BLOCK_64X128,  BLOCK_64X64} },  { {BLOCK_128X256, BLOCK_128X128 }, {BLOCK_INVALID, BLOCK_64X128 } },  { {BLOCK_256X128, BLOCK_INVALID }, {BLOCK_128X128, BLOCK_128X64 } },  { {BLOCK_256X256, BLOCK_256X128 }, {BLOCK_128X256, BLOCK_128X128 } },  { {BLOCK_4X16,    BLOCK_4X8},      {BLOCK_INVALID, BLOCK_4X8} },  { {BLOCK_16X4,    BLOCK_INVALID},  {BLOCK_8X4,     BLOCK_8X4} },  { {BLOCK_8X32,    BLOCK_8X16 },    { BLOCK_4X32,   BLOCK_4X16 } },  { {BLOCK_32X8,    BLOCK_32X4 },    { BLOCK_16X8,   BLOCK_16X4 } },  { {BLOCK_16X64,   BLOCK_16X32 },   { BLOCK_8X64,   BLOCK_8X32 } },  { {BLOCK_64X16,   BLOCK_64X8 },    { BLOCK_32X16,  BLOCK_32X8 } },  { {BLOCK_4X32,    BLOCK_4X16},     { BLOCK_INVALID,BLOCK_4X16 } },  { {BLOCK_32X4,    BLOCK_INVALID }, { BLOCK_16X4,   BLOCK_16X4 } },  { {BLOCK_8X64,    BLOCK_8X32 },    { BLOCK_4X64,   BLOCK_4X32 } },  { {BLOCK_64X8,    BLOCK_64X4 },    { BLOCK_32X8,   BLOCK_32X4 } },  { {BLOCK_4X64,    BLOCK_4X32 },    { BLOCK_INVALID,BLOCK_4X32 } },  { {BLOCK_64X4,    BLOCK_INVALID},  { BLOCK_32X4,   BLOCK_32X4 } },}

5.20.49. Coefficients syntax

coeffs( plane, startX, startY, txSz ) { Descriptor
x4 = startX >> 2
y4 = startY >> 2
w4 = Tx_Width[ txSz ] >> 2
h4 = Tx_Height[ txSz ] >> 2
txSzCtx = ( Tx_Size_Sqr[ txSz ] + Tx_Size_Sqr_Up[ txSz ] + 1 ) >> 1
ptype = plane > 0
segEob = Min( 32, Tx_Width[ txSz ] ) * Min( Tx_Height[ txSz ], 32 )
for ( c = 0; c < segEob; c++ ) {
Quant[ c ] = 0
QuantSign[ c ] = 0
}
for ( i = 0; i < 4 * h4; i++ ) {
for ( j = 0; j < 4 * w4; j++ ) {
Dequant[ i ][ j ] = 0
}
}
for ( i = 0; i < Min(32, 4 * h4); i++ ) {
for ( j = 0; j < Min(32, 4 * w4); j++ ) {
Level[ i ][ j ] = 0
}
}
eob = 0
culLevel = 0
dcCategory = 0
all_zero S()
if ( all_zero ) {
if ( plane == 1 ) {
EobU = 0
cctx_type = 0
}
c = 0
if ( plane == 0 ) {
for ( i = 0; i < w4; i++ ) {
for ( j = 0; j < h4; j++ ) {
TxTypes[ y4 + j ][ x4 + i ] = DCT_DCT
}
}
}
} else {
eobMultisize = Min( Tx_Width_Log2[ txSz ], 5) +
Min( Tx_Height_Log2[ txSz ], 5) - 4
eobCtx = (plane > 0) ? 2 : is_inter
if ( eobMultisize == 0 ) {
eob_pt_16 S()
eobPt = eob_pt_16 + 1
} else if ( eobMultisize == 1 ) {
eob_pt_32 S()
eobPt = eob_pt_32 + 1
} else if ( eobMultisize == 2 ) {
eob_pt_64 S()
eobPt = eob_pt_64 + 1
} else if ( eobMultisize == 3 ) {
eob_pt_128 S()
eobPt = eob_pt_128 + 1
} else if ( eobMultisize == 4 ) {
eob_pt_256 S()
if ( eob_pt_256 == 7 ) {
eob_pt_256_extra L(1)
eobPt = 8 + eob_pt_256_extra
} else {
eobPt = eob_pt_256 + 1
}
} else if ( eobMultisize == 5 ) {
eob_pt_512 S()
if ( eob_pt_512 == 7 ) {
eob_pt_512_extra L(2)
eobPt = 8 + eob_pt_512_extra
} else {
eobPt = eob_pt_512 + 1
}
} else {
eob_pt_1024 S()
if ( eob_pt_1024 == 7 ) {
eob_pt_1024_extra L(2)
eobPt = 8 + eob_pt_1024_extra
} else {
eobPt = eob_pt_1024 + 1
}
}
eob = ( eobPt < 2 ) ? eobPt : ( ( 1 << ( eobPt - 2 ) ) + 1 )
if ( eobPt >= 3 ) {
eob_extra S()
if ( eob_extra ) {
eob += 1 << (eobPt - 3)
}
for ( i = eobPt - 4; i >= 0; i-- ) {
eob_extra_bit L(1)
if ( eob_extra_bit ) {
eob += 1 << i
}
}
}
if ( plane == 0 ) {
transform_type( x4, y4, txSz, eob )
} else if ( plane == 1 ) {
if ( (is_inter || eob != 1) && is_cctx_allowed() ) {
cctx_type S()
} else {
cctx_type = 0
}
}
PlaneTxType = compute_tx_type( plane, txSz, x4, y4 )
txClass = get_tx_class(PlaneTxType)
scan = get_scan( txSz, txClass )
useFsc = enable_fsc && PlaneTxType == IDTX && plane == 0 &&
(fsc_mode || is_inter)
if ( plane == 1 ) {
EobU = eob
}
parityHiding = allow_parity_hiding && !Lossless && plane == 0 &&
PlaneTxType != IDTX
numNz = 0
sumAbs1 = 0
isHidden = 0
useTcq = allow_tcq && plane == 0 && !Lossless &&
txClass == TX_CLASS_2D && !useFsc
tcqState = 0
hrLevelAvg = 0
if ( useFsc ) {
bob = segEob - eob
eob = segEob
for ( c = bob; c < eob; c++ ) {
pos = scan[ c ]
(row, col) = get_tx_row_col(pos, txSz)
if ( c == bob ) {
coeff_base_bob S()
level = coeff_base_bob + 1
} else {
coeff_base_idtx S()
level = coeff_base_idtx
}
if ( level > NUM_BASE_LEVELS ) {
coeff_br_idtx S()
level += coeff_br_idtx
}
Level[ row ][ col ] = level
}
for ( c = 0; c < eob; c += 1 ) {
pos = scan[ c ]
(row, col) = get_tx_row_col(pos, txSz)
level = Level[ row ][ col ]
if ( level != 0 ) {
idtx_sign S()
sign = idtx_sign
} else {
sign = 0
}
(quant,hrLevelAvg) = read_quant(level, pos, 0,
NUM_BASE_LEVELS + COEFF_BASE_RANGE + 1,
hrLevelAvg, 0 )
if ( pos == 0 && quant > 0 ) {
dcCategory = sign ? 1 : 2
}
culLevel = Min(4, culLevel + quant)
if ( sign ) {
quant = -quant
}
Quant[ pos ] = quant
if ( level != 0 ) {
QuantSign[ pos ] = sign ? -1 : 1
}
}
} else {
for ( c = eob - 1; c >= 0; c-- ) {
pos = scan[ c ]
(row, col) = get_tx_row_col(pos, txSz)
isLf = get_lf_limits(row, col, txClass, plane)
if ( c == eob - 1 ) {
coeff_base_eob S()
level = coeff_base_eob + 1
} else {
coeff_base S()
level = coeff_base
}
baseLevels = isLf ? LF_NUM_BASE_LEVELS : NUM_BASE_LEVELS
if ( level > baseLevels && !(isLf && plane > 0) ) {
coeff_br S()
level += coeff_br
}
if ( useTcq ) {
tcqState = Tcq_Next_State[ tcqState ][ llevel&1 ]
}
if ( parityHiding ) {
if ( c > 0 ) {
sumAbs1 ^= Min( level,
NUM_BASE_LEVELS + COEFF_BASE_RANGE + 1) & 1
if ( level != 0 ) {
numNz += 1
isHidden = numNz >= PHTHRESH
}
}
}
Level[ row ][ col ] = level
}
tcqState = 0
for ( c = eob - 1; c >= 0; c -= 1 ) {
pos = scan[ c ]
(row, col) = get_tx_row_col(pos, txSz)
level = Level[ row ][ col ]
if ( level != 0 || (isHidden && c == 0 && sumAbs1 > 0) ) {
if ( row == 0 && col == 0 && plane == 0 ) {
dc_sign S()
sign = dc_sign
} else if ( txClass == TX_CLASS_HORIZ && col == 0 &&
plane == 0 ) {
dc_sign_horz_vert S()
sign = dc_sign_horz_vert
} else if ( txClass == TX_CLASS_VERT && row == 0 &&
plane == 0 ) {
dc_sign_horz_vert S()
sign = dc_sign_horz_vert
} else {
sign_bit L(1)
sign = sign_bit
}
} else {
sign = 0
}
if ( get_lf_limits(row, col, txClass, plane) ) {
maxLevel = ( plane == 0 ) ?
(LF_NUM_BASE_LEVELS + COEFF_BASE_RANGE + 1) :
(LF_NUM_BASE_LEVELS + 1)
} else {
maxLevel = NUM_BASE_LEVELS + COEFF_BASE_RANGE + 1
}
if ( isHidden && c == 0 ) {
maxLevel = NUM_BASE_LEVELS + 1
}
(quant,hrLevelAvg) = read_quant( level, pos, isHidden, maxLevel,
hrLevelAvg, useTcq )
if ( c == 0 && isHidden ) {
quant = 2 * quant + sumAbs1
}
if ( pos == 0 && quant > 0 ) {
dcCategory = sign ? 1 : 2
}
culLevel = Min(4, culLevel + quant)
if ( !Lossless && useTcq ) {
q0 = ((tcqState >> 1) & 1)
tcqState = Tcq_Next_State[ tcqState ][ quant & 1 ]
if ( quant > 0 ) {
quant = quant * 2 - q0
}
}
if ( sign ) {
quant = -quant
}
Quant[ pos ] = quant
}
}
}
for ( i = 0; i < w4; i++ ) {
AboveLevelContext[ plane ][ x4 + i ] = culLevel
AboveDcContext[ plane ][ x4 + i ] = dcCategory
}
for ( i = 0; i < h4; i++ ) {
LeftLevelContext[ plane ][ y4 + i ] = culLevel
LeftDcContext[ plane ][ y4 + i ] = dcCategory
}
return eob
}

where get_tx_row_col (which extracts the row and column for a position in raster order) is defined as:

get_tx_row_col(pos, txSz) { Descriptor
adjTxSz = Adjusted_Tx_Size[ txSz ]
bwl = Tx_Width_Log2[ adjTxSz ]
row = pos >> bwl
col = pos - (row << bwl)
return (row, col)
}

and get_lf_limits (which determines if this is a low frequency coefficient) is defined as:

get_lf_limits(row, col, txClass, plane) { Descriptor
if ( txClass == TX_CLASS_2D ) {
return plane == 0 ? ((row + col) < 4) : ((row + col) < 1)
} else if ( txClass == TX_CLASS_HORIZ ) {
return plane == 0 ? (col < 2) : (col < 1)
} else {
return plane == 0 ? (row < 2) : (row < 1)
}
}

and is_cctx_allowed is defined as:

is_cctx_allowed( ) { Descriptor
is420 = SubsamplingX && SubsamplingY
planeSz = get_plane_residual_size( ChromaMiSize, 1 )
return enable_cctx &&
!Lossless &&
(is420 || Block_Width[planeSz] < 32 || Block_Height[planeSz] < 32)
}

and Tcq_Next_State (which updates the TCQ state based on the current state and parity) is defined as:

Tcq_Next_State[ 8 ][ 2 ] = {    {0, 4},    {4, 0},    {1, 5},    {5, 1},    {6, 2},    {2, 6},    {7, 3},    {3, 7}}

5.20.50. Read quantized coefficient syntax

read_quant(level, pos, isHidden, maxLevel, hrLevelAvg, allowTcq ) { Descriptor
quant = level
if ( quant >= maxLevel - allowTcq ) {
lvlShift = (pos == 0 && isHidden) ? 1 : 0
predLevel = hrLevelAvg >> lvlShift
m = Clip3( 1, 6, FloorLog2( predLevel ) )
k = m + 1
cMax = Min( m + 4, 6 )
for ( q = 0 ; q < cMax; q++ ) {
q_length_bit L(1)
if ( q_length_bit ) {
break
}
}
if ( q == cMax ) {
length = -1
do {
length++
golomb_length_bit L(1)
} while ( !golomb_length_bit )
length += k
xBase = (q << m) + (1 << length) - (1 << k)
} else {
length = m
xBase = q << m
}
coeff_rem L(length)
x = xBase + coeff_rem
hrLevelAvg = ((x << lvlShift) + hrLevelAvg) >> 1
if ( allowTcq ) {
quant += x << 1
} else {
quant = x + maxLevel
}
}
return (quant, hrLevelAvg)
}

5.20.51. Compute transform type function

compute_tx_type( plane, txSz, blockX, blockY ) { Descriptor
if ( Lossless && plane == 0 && fsc_mode ) {
return IDTX
}
if ( Lossless ) {
if ( !is_inter ) {
fscMode = PlaneStart == 0 ? fsc_mode :
FscModes[ ChromaMiRow ][ ChromaMiCol ]
if ( fscMode ) {
return IDTX
} else {
return DCT_DCT
}
}
if ( is_inter && txSz != TX_4X4 ) {
return IDTX
}
if ( plane > 0 ) {
x4 = Max( MiCol, blockX << SubsamplingX )
y4 = Max( MiRow, blockY << SubsamplingY )
if ( is_inter && LumaTxSizes[ y4 ][ x4 ] != TX_4X4 ) {
return IDTX
}
if ( !FrameIsIntra &&
MiRow == ChromaMiRow && MiCol == ChromaMiCol ) {
return TxTypes[ y4 ][ x4 ]
}
return TxTypes[ MiRow ][ MiCol ]
}
}
txSet = get_tx_set( txSz, plane )
if ( plane == 0 ) {
return TxTypes[ blockY ][ blockX ]
}
if ( enable_chroma_dctonly ) {
return DCT_DCT
}
if ( is_inter ) {
x4 = Max( MiCol, blockX << SubsamplingX )
y4 = Max( MiRow, blockY << SubsamplingY )
txType = TxTypes[ y4 ][ x4 ]
if ( !is_tx_type_in_set( txSet, txType ) ) {
return DCT_DCT
}
return txType
}
if ( is_directional_mode( UVMode ) ) {
pAngle = Mode_To_Angle[ UVMode ] + AngleDeltaUV * ANGLE_STEP
(mode, unusedAngle) = wide_angle_mapping( UVMode, Tx_Width[ txSz ],
Tx_Height[ txSz ], pAngle )
txType = Mode_To_Txfm[ mode ]
} else {
txType = Mode_To_Txfm[ UVMode ]
}
if ( !is_tx_type_in_set( txSet, txType ) ) {
return DCT_DCT
}
return txType
}
is_tx_type_in_set( txSet, txType ) {
return is_inter ? Tx_Type_In_Set_Inter[ txSet ][ txType ] :
Tx_Type_In_Set_Intra[ txSet ][ txType ]
}

where the tables Tx_Type_In_Set_Inter and Tx_Type_In_Set_Intra are specified as follows:

Tx_Type_In_Set_Intra[ TX_SET_TYPES_INTRA ][ TX_TYPES ] = {  {    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  },  {     1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0   },  {     1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0  },   {     1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0  },  {     1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1  },  {    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  },  {    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  }}Tx_Type_In_Set_Inter[ TX_SET_TYPES_INTER ][ TX_TYPES ] = {  {    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  },  {     1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0  },  {     1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0  },  {    1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0  },  {    1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1  },  {    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1  },  {    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0  },  {    1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0  },  {    1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0  }}

The function wide_angle_mapping is defined as:

wide_angle_mapping(mode, w, h, pAngle) { Descriptor
if ((h == 2 * w && pAngle < WAIP_WH_RATIO_2_THRES) ||
(h == 4 * w && pAngle < WAIP_WH_RATIO_4_THRES) ||
(h == 8 * w && pAngle < WAIP_WH_RATIO_8_THRES) ||
(h == 16 * w && pAngle < WAIP_WH_RATIO_16_THRES)) {
return (D203_PRED,180 + pAngle)
} else if ((w == 2 * h && pAngle > 270 - WAIP_WH_RATIO_2_THRES) ||
(w == 4 * h && pAngle > 270 - WAIP_WH_RATIO_4_THRES) ||
(w == 8 * h && pAngle > 270 - WAIP_WH_RATIO_8_THRES) ||
(w == 16 * h &&
pAngle > 270 - WAIP_WH_RATIO_16_THRES)) {
return (D45_PRED, pAngle - 180)
}
return (mode,pAngle)
}

5.20.52. Get scan function

get_scan( txSz, txClass ) { Descriptor
w = Min( Tx_Width[ txSz ], 32)
h = Min( Tx_Height[ txSz ], 32)
if ( txClass == TX_CLASS_VERT ) {
c = 0
for ( y = 0; y < h; y++ ) {
for ( x = 0; x < w; x++ ) {
out[ c ] = y * w + x
c += 1
}
}
} else if ( txClass == TX_CLASS_HORIZ ) {
c = 0
for ( x = 0; x < w; x++ ) {
for ( y = 0; y < h; y++ ) {
out[ c ] = y * w + x
c += 1
}
}
} else {
x = 0
y = 0
for ( c = 0; c < w*h; c++ ) {
out[ c ] = y * w + x
x += 1
y -= 1
if ( y < 0 || x >= w ) {
x += 1
s = Min(x,h - 1 - y)
x -= s
y += s
}
}
}
return out
}

5.20.53. Is directional mode function

is_directional_mode( mode ) { Descriptor
if ( ( mode >= V_PRED ) && ( mode <= D67_PRED ) ) {
return 1
}
return 0
}

5.20.54. Read CFL alphas syntax

read_cfl_alphas() { Descriptor
if ( !enable_cfl_intra ) {
cfl_mhccp = 1
} else if ( is_mhccp_allowed() ) {
cfl_mhccp S()
} else {
cfl_mhccp = 0
}
if ( cfl_mhccp ) {
cfl_index = CFL_MULTI
} else {
cfl_index S()
}
if ( cfl_index == CFL_MULTI ) {
cfl_mh_dir S()
}
if ( cfl_index != CFL_EXPLICIT ) {
return
}
cfl_alpha_signs S()
signU = (cfl_alpha_signs + 1 ) / 3
signV = (cfl_alpha_signs + 1 ) % 3
if ( signU != CFL_SIGN_ZERO ) {
cfl_alpha_u S()
CflAlphaU = 1 + cfl_alpha_u
if ( signU == CFL_SIGN_NEG ) {
CflAlphaU = -CflAlphaU
}
} else {
CflAlphaU = 0
}
if ( signV != CFL_SIGN_ZERO ) {
cfl_alpha_v S()
CflAlphaV = 1 + cfl_alpha_v
if ( signV == CFL_SIGN_NEG ) {
CflAlphaV = -CflAlphaV
}
} else {
CflAlphaV = 0
}
}

5.20.55. Palette mode info syntax

palette_mode_info( ) { Descriptor
if ( PlaneStart == 0 && YMode == DC_PRED ) {
has_palette_y S()
if ( has_palette_y ) {
palette_size_y_minus_2 S()
PaletteSizeY = palette_size_y_minus_2 + 2
cacheN = get_palette_cache( )
idx = 0
for ( i = 0; i < cacheN && idx < PaletteSizeY; i++ ) {
use_palette_color_cache_y L(1)
if ( use_palette_color_cache_y ) {
palette_colors_y[ idx ] = PaletteCache[ i ]
idx++
}
}
if ( idx < PaletteSizeY ) {
palette_colors_y[ idx ] L(BitDepth)
idx++
}
if ( idx < PaletteSizeY ) {
minBits = BitDepth - 3
palette_num_extra_bits_y L(2)
paletteBits = minBits + palette_num_extra_bits_y
}
while ( idx < PaletteSizeY ) {
palette_delta_y L(paletteBits)
palette_delta_y++
palette_colors_y[ idx ] =
Clip1( palette_colors_y[ idx - 1 ] +
palette_delta_y )
range = ( 1 << BitDepth ) - palette_colors_y[ idx ] - 1
paletteBits = Min( paletteBits, CeilLog2( range ) )
idx++
}
sort( palette_colors_y, 0, PaletteSizeY - 1 )
}
}
}

The function sort( arr, i1, i2 ) sorts a subarray of the array arr in-place into ascending order. The subarray to be sorted is between indices i1 and i2 inclusive.

Note: The palette colors are generated in ascending order. The palette cache is also in ascending order. This means that the sort function can be replaced in implementations by a merge of two sorted lists.

where the function get_palette_cache, which merges the above and left palettes to form a cache, is specified as follows:

get_palette_cache( ) { Descriptor
r = MiRow
c = MiCol
aboveN = 0
if ( ( r * MI_SIZE ) % 64 ) {
aboveN = PaletteSizes[ r - 1 ][ c ]
}
leftN = 0
if ( AvailL ) {
leftN = PaletteSizes[ r ][ c - 1 ]
}
aboveIdx = 0
leftIdx = 0
n = 0
while ( aboveIdx < aboveN || leftIdx < leftN ) {
if ( aboveIdx < aboveN ) {
val = PaletteColors[ r - 1 ][ c ][ aboveIdx ]
aboveIdx++
PaletteCache[ n ] = val
n++
}
if ( leftIdx < leftN ) {
val = PaletteColors[ r ][ c - 1 ][ leftIdx ]
leftIdx++
PaletteCache[ n ] = val
n++
}
}
return n
}

Note: get_palette_cache interleaves the available palette colors from above and left together.

5.20.56. Transform type syntax

transform_type( x4, y4, txSz, eob ) { Descriptor
set = get_tx_set( txSz, 0 )
if ( fsc_mode ) {
TxType = IDTX
} else if ( !is_inter && eob==1 ) {
TxType = DCT_DCT
} else if ( Lossless && is_inter ) {
if ( txSz == TX_4X4 ) {
lossless_inter_tx_type S()
TxType = lossless_inter_tx_type ? IDTX : DCT_DCT
} else {
TxType = IDTX
}
} else if ( set > 0 &&
!Lossless &&
!( reduced_tx_set == 2 && is_inter == 0 )
) {
if ( set == TX_SET_WIDE_32 || set == TX_SET_HIGH_32 ) {
is_long_side_dct S()
} else {
is_long_side_dct = 1
}
if ( is_inter ) {
inter_tx_type S()
if ( set == TX_SET_WIDE_64 || set == TX_SET_WIDE_32 ) {
TxType = Tx_Type_Inv_Long[ is_long_side_dct ][ 0 ]
[ inter_tx_type ]
} else if ( set == TX_SET_HIGH_64 || set == TX_SET_HIGH_32 ) {
TxType = Tx_Type_Inv_Long[ is_long_side_dct ][ 1 ]
[ inter_tx_type ]
} else if ( set == TX_SET_INTER_1 ) {
inter_tx_type_offset S()
TxType = Tx_Type_Inter_Inv_Set1[ inter_tx_type * 8 +
inter_tx_type_offset ]
} else if ( set == TX_SET_INTER_2 ) {
inter_tx_type_offset S()
TxType = Tx_Type_Inter_Inv_Set2[ inter_tx_type * 8 +
inter_tx_type_offset ]
} else if ( set == TX_SET_DCT_IDTX ) {
TxType = Tx_Type_Inter_Inv_Set3[ inter_tx_type ]
} else {
TxType = Tx_Type_Inter_Inv_Set4[ inter_tx_type ]
}
} else {
intra_tx_type S()
if ( set == TX_SET_WIDE_64 || set == TX_SET_WIDE_32 ) {
TxType = Tx_Type_Inv_Long[ is_long_side_dct ][ 0 ]
[ intra_tx_type ]
} else if ( set == TX_SET_HIGH_64 || set == TX_SET_HIGH_32 ) {
TxType = Tx_Type_Inv_Long[ is_long_side_dct ][ 1 ]
[ intra_tx_type ]
} else {
sizeInfo = Size_Class[ txSz ]
intraDir = YMode
if ( is_directional_mode( intraDir ) ) {
pAngle = Mode_To_Angle[ intraDir ] +
AngleDeltaY * ANGLE_STEP +
Mrl_Index_To_Delta[ MrlIndex ]
(intraDir,unusedAngle) = wide_angle_mapping( intraDir,
Tx_Width[ txSz ],
Tx_Height[ txSz ], pAngle)
}
TxType = Md_Idx_To_Type[ sizeInfo ][ intraDir ][ intra_tx_type ]
}
}
} else {
TxType = DCT_DCT
}
large = Tx_Width[ txSz ] >= 8 && Tx_Height[ txSz ] >= 8
if ( !large ) {
eobLim = IST_4X4_HEIGHT
} else if ( txSz == TX_8X8 || TxType == ADST_ADST ) {
eobLim = IST_8x8_HEIGHT_RED
} else {
eobLim = IST_8X8_HEIGHT
}
if ( (is_inter ?
enable_inter_ist && eob > 3 && TxType == DCT_DCT &&
Tx_Width[ txSz ] >= 16 && Tx_Height[ txSz ] >= 16 :
enable_intra_ist && eob != 1 ) &&
!Lossless &&
(TxType == ADST_ADST || TxType == DCT_DCT) &&
YMode != PAETH_PRED &&
eob <= eobLim ) {
sec_tx_type S()
if ( sec_tx_type != 0 && !is_inter ) {
most_probable_stx_set S()
}
} else {
sec_tx_type = 0
}
for ( i = 0; i < ( Tx_Width[ txSz ] >> 2 ); i++ ) {
for ( j = 0; j < ( Tx_Height[ txSz ] >> 2 ); j++ ) {
TxTypes[ y4 + j ][ x4 + i ] = TxType
}
}
}

where the inversion tables used in the function are specified as follows:

Tx_Type_Inter_Inv_Set1[ 16 ] = {    IDTX, V_DCT, H_DCT, V_ADST, H_ADST, V_FLIPADST, H_FLIPADST,    DCT_DCT, ADST_DCT, DCT_ADST, FLIPADST_DCT, DCT_FLIPADST, ADST_ADST,    FLIPADST_FLIPADST, ADST_FLIPADST, FLIPADST_ADST}Tx_Type_Inter_Inv_Set2[ 12 ] = {    IDTX, V_DCT, H_DCT, DCT_DCT, ADST_DCT, DCT_ADST, FLIPADST_DCT,    DCT_FLIPADST, ADST_ADST, FLIPADST_FLIPADST, ADST_FLIPADST,    FLIPADST_ADST}Tx_Type_Inter_Inv_Set3[ 2 ]  = { IDTX, DCT_DCT }Tx_Type_Inter_Inv_Set4[ 4 ]  = { DCT_DCT, V_DCT, H_DCT, IDTX }Tx_Type_Inv_Long[ 2 ][ 2 ][ 4 ] = {    {        { V_DCT, V_ADST, V_FLIPADST, IDTX },        { H_DCT, H_ADST, H_FLIPADST, IDTX },    },    {        { DCT_DCT, ADST_DCT, FLIPADST_DCT, H_DCT },        { DCT_DCT, DCT_ADST, DCT_FLIPADST, V_DCT },    }}

5.20.57. Get transform set function

get_tx_set( txSz, plane ) { Descriptor
txSzSqr = Tx_Size_Sqr[ txSz ]
txSzSqrUp = Tx_Size_Sqr_Up[ txSz ]
if ( txSzSqrUp > TX_32X32 ) {
if ( txSzSqr >= TX_32X32 ) {
return TX_SET_DCTONLY
}
return (Tx_Width[ txSz ] > Tx_Height[ txSz ]) ? TX_SET_WIDE_64 :
TX_SET_HIGH_64
}
if ( txSzSqrUp == TX_32X32 && txSzSqr != TX_32X32 ) {
return (Tx_Width[ txSz ] > Tx_Height[ txSz ]) ? TX_SET_WIDE_32 :
TX_SET_HIGH_32
}
if (!is_inter && txSzSqrUp == TX_32X32) {
return TX_SET_DCTONLY
}
reducedTxSet = plane == 0 ? reduced_tx_set : enable_chroma_dctonly
if ( txSzSqrUp == TX_32X32 || reducedTxSet == 1 ) {
return is_inter ? TX_SET_DCT_IDTX : TX_SET_INTRA_2
} else if ( reducedTxSet == 2 ) {
return TX_SET_DCT_IDTX
} else if ( reducedTxSet == 3 ) {
return is_inter ? TX_SET_DCT_IDTX_IDDCT : TX_SET_INTRA_2
}
if ( is_inter ) {
return ( txSzSqr == TX_16X16 ) ? TX_SET_INTER_2 : TX_SET_INTER_1
}
return TX_SET_INTRA_1
}

5.20.58. Palette tokens syntax

palette_tokens( ) { Descriptor
blockHeight = Block_Height[ MiSize ]
blockWidth = Block_Width[ MiSize ]
onscreenHeight = Min( blockHeight, (MiRows - MiRow) * MI_SIZE )
onscreenWidth = Min( blockWidth, (MiCols - MiCol) * MI_SIZE )
if ( PlaneStart == 0 && PaletteSizeY ) {
palette_direction = 0
if ( blockWidth < 64 && blockHeight < 64 ) {
palette_direction L(1)
}
prevIdentityRow = PALETTE_ROW_FLAG_CONTEXTS - 1
if ( palette_direction ) {
outerLim = onscreenWidth
innerLim = onscreenHeight
} else {
innerLim = onscreenWidth
outerLim = onscreenHeight
}
for ( i = 0; i < outerLim; i++ ) {
identity_row_y S()
for ( j = 0; j < innerLim; j++ ) {
if ( palette_direction ) {
c = i
r = j
} else {
r = i
c = j
}
if ( identity_row_y == 2 ) {
ColorMapY[ r ][ c ] = palette_direction ?
ColorMapY[ r ][ c - 1 ] : ColorMapY[ r - 1 ][ c ]
} else if ( identity_row_y == 1 && j > 0 ) {
ColorMapY[ r ][ c ] = palette_direction ?
ColorMapY[ r - 1 ][ c ] : ColorMapY[ r ][ c - 1 ]
} else if ( r == 0 && c == 0 ) {
color_index_map_y NS(PaletteSizeY)
ColorMapY[ 0 ][ 0 ] = color_index_map_y
} else {
get_palette_color_context( ColorMapY, r, c, PaletteSizeY )
palette_color_idx_y S()
ColorMapY[ r ][ c ] = ColorOrder[ palette_color_idx_y ]
}
}
prevIdentityRow = identity_row_y
}
for ( i = 0; i < onscreenHeight; i++ ) {
for ( j = onscreenWidth; j < blockWidth; j++ ) {
ColorMapY[ i ][ j ] = ColorMapY[ i ][ onscreenWidth - 1 ]
}
}
for ( i = onscreenHeight; i < blockHeight; i++ ) {
for ( j = 0; j < blockWidth; j++ ) {
ColorMapY[ i ][ j ] = ColorMapY[ onscreenHeight - 1 ][ j ]
}
}
}
}

5.20.59. Palette color context function

get_palette_color_context( colorMap, r, c, n ) { Descriptor
for ( i = 0; i < PALETTE_COLORS; i++ ) {
scores[ i ] = 0
ColorOrder[ i ] = i
}
if ( c > 0 ) {
neighbor = colorMap[ r ][ c - 1 ]
scores[ neighbor ] += 2
}
if ( ( r > 0 ) && ( c > 0 ) ) {
neighbor = colorMap[ r - 1 ][ c - 1 ]
scores[ neighbor ] += 1
}
if ( r > 0 ) {
neighbor = colorMap[ r - 1 ][ c ]
scores[ neighbor ] += 2
}
for ( i = 0; i < PALETTE_NUM_NEIGHBORS; i++ ) {
maxScore = scores[ i ]
maxIdx = i
for ( j = i + 1; j < n; j++ ) {
if ( scores[ j ] > maxScore ) {
maxScore = scores[ j ]
maxIdx = j
} else if ( scores[ j ] > 0 && scores[ j ] == maxScore &&
c > 0 && j == colorMap[ r ][ c - 1 ] ) {
maxScore = scores[ j ]
maxIdx = j
}
}
if ( maxIdx != i ) {
maxScore = scores[ maxIdx ]
maxColorOrder = ColorOrder[ maxIdx ]
for ( k = maxIdx; k > i; k-- ) {
scores[ k ] = scores[ k - 1 ]
ColorOrder[ k ] = ColorOrder[ k - 1 ]
}
scores[ i ] = maxScore
ColorOrder[ i ] = maxColorOrder
}
}
ColorContextHash = 0
for ( i = 0; i < PALETTE_NUM_NEIGHBORS; i++ ) {
ColorContextHash += scores[ i ] * Palette_Color_Hash_Multipliers[ i ]
}
}

Note: The reference software has an alternative implementation that may be better suited for hardware implementations.

5.20.60. Is inside function

is_inside determines whether a candidate position is inside the current tile.

is_inside( candidateR, candidateC ) { Descriptor
return ( candidateC >= MiColStart &&
candidateC < MiColEnd &&
candidateR >= MiRowStart &&
candidateR < MiRowEnd )
}

5.20.61. Is inside frame function

is_inside_frame determines whether a candidate position is inside the current frame.

is_inside_frame( candidateR, candidateC ) { Descriptor
return ( candidateC >= 0 &&
candidateC < MiCols &&
candidateR >= 0 &&
candidateR < MiRows )
}

5.20.62. Is inside filter region function

is_inside_filter_region determines whether a candidate position is inside the region that is being used for CDEF and restoration filtering.

is_inside_filter_region( candidateR, candidateC ) { Descriptor
if ( disable_loopfilters_across_tiles ) {
return is_inside( candidateR, candidateC )
} else {
return is_inside_frame( candidateR, candidateC )
}
}

5.20.63. Clamp MV row function

clamp_mv_row( mvec ) { Descriptor
bh4 = Num_4x4_Blocks_High[ MiSize ]
low = -(MiRow + bh4) * MI_SIZE * 8 - MV_BORDER
high = (MiRows - MiRow) * MI_SIZE * 8 + MV_BORDER
return Clip3( low, high, mvec )
}

5.20.64. Clamp MV col function

clamp_mv_col( mvec ) { Descriptor
bw4 = Num_4x4_Blocks_Wide[ MiSize ]
low = -(MiCol + bw4) * MI_SIZE * 8 - MV_BORDER
high = (MiCols - MiCol) * MI_SIZE * 8 + MV_BORDER
return Clip3( low, high, mvec )
}

5.20.65. Clear CDEF function

clear_cdef( r, c ) { Descriptor
cdef_idx[ r ][ c ] = -1
num4x4 = Num_4x4_Blocks_Wide[ SbSize ]
cdefSize4 = Num_4x4_Blocks_Wide[ BLOCK_64X64 ]
num64x64 = num4x4 / cdefSize4
for ( i = 0; i < num64x64; i++ ) {
for ( j = 0; j < num64x64; j++ ) {
cdef_idx[ r + i * cdefSize4 ][ c + j * cdefSize4 ] = -1
}
}
}

5.20.66. Read CDEF syntax

read_cdef( ) { Descriptor
if ( (skip_flag && !cdef_on_skip_txfm_frame_enable) ||
!cdef_frame_enable ) {
return
}
cdefSize4 = Num_4x4_Blocks_Wide[ BLOCK_64X64 ]
cdefMask4 = ~(cdefSize4 - 1)
r = MiRow & cdefMask4
c = MiCol & cdefMask4
if ( cdef_idx[ r ][ c ] == -1 ) {
if ( CdefStrengths == 1 ) {
cdef_idx[ r ][ c ] = 0
} else {
cdef_index0 S()
if ( cdef_index0 ) {
cdef_idx[ r ][ c ] = 0
} else if ( CdefStrengths == 2 ) {
cdef_idx[ r ][ c ] = 1
} else {
cdef_index_minus1 S()
cdef_idx[ r ][ c ] = cdef_index_minus1 + 1
}
}
w4 = Num_4x4_Blocks_Wide[ MiSize ]
h4 = Num_4x4_Blocks_High[ MiSize ]
for ( i = r; i < r + h4 ; i += cdefSize4 ) {
for ( j = c; j < c + w4 ; j += cdefSize4 ) {
cdef_idx[ i ][ j ] = cdef_idx[ r ][ c ]
}
}
}
}

5.20.67. Read CCSO syntax

read_ccso( ) { Descriptor
if ( !enable_ccso ) {
return
}
shiftRow = CcsoLumaSizeLog2 - MI_SIZE_LOG2
shiftCol = CcsoLumaSizeLog2 - MI_SIZE_LOG2
blkH4 = 1 << shiftRow
blkW4 = 1 << shiftCol
if ( (MiRow & (blkH4 - 1)) || (MiCol & (blkW4 - 1)) ) {
return
}
for ( plane = 0; plane < NumPlanes; plane++ ) {
if ( ccso_planes[ plane ] ) {
if ( !sb_reuse_ccso[ plane ] ) {
ccso_blk S()
CcsoBlks[ plane ][ MiRow >> shiftRow ][ MiCol >> shiftCol ] =
ccso_blk
}
}
}
}

5.20.68. Read GDF syntax

read_gdf( ) { Descriptor
if ( !gdf_frame_enable || !gdf_per_block ) {
return
}
sbSize4 = Num_4x4_Blocks_Wide[ SbSize ]
if ( MiRow % sbSize4 != 0 || MiCol % sbSize4 != 0 ) {
return
}
sbRow = MiRow / sbSize4
sbCol = MiCol / sbSize4
sbPerGdf = GdfBlkSize / Block_Width[ SbSize ]
if ( sbCol % sbPerGdf != 0 ) {
return
}
if ( sbRow % sbPerGdf != 0 ) {
return
}
use_gdf S()
GdfBlks[ sbRow / sbPerGdf ][ sbCol / sbPerGdf ] = use_gdf
}

5.20.69. Read loop restoration syntax

read_lr( row, col, bSize ) { Descriptor
w = Num_4x4_Blocks_Wide[ bSize ]
h = Num_4x4_Blocks_High[ bSize ]
for ( plane = PlaneStart; plane < PlaneEnd; plane++ ) {
if ( FrameRestorationType[ plane ] != RESTORE_NONE ) {
subX = (plane == 0) ? 0 : SubsamplingX
subY = (plane == 0) ? 0 : SubsamplingY
unitSize = LoopRestorationSize[ plane ]
miCols = MiColEnd - MiColStart
miRows = MiRowEnd - MiRowStart
lrRowOffset = (MiRowStart * MI_SIZE >> subY) / unitSize
lrColOffset = (MiColStart * MI_SIZE >> subX) / unitSize
c = col - MiColStart
r = row - MiRowStart
unitRows = count_units_in_frame(unitSize, miRows * MI_SIZE >> subY)
unitCols = count_units_in_frame(unitSize, miCols * MI_SIZE >> subX)
unitRowStart = ( r * ( MI_SIZE >> subY) +
unitSize - 1 ) / unitSize
unitRowEnd = Min( unitRows, ( (r + h) * ( MI_SIZE >> subY) +
unitSize - 1 ) / unitSize)
unitColStart = ( c * (MI_SIZE >> subX) + unitSize - 1 ) / unitSize
unitColEnd = Min( unitCols,
( (c + w) * (MI_SIZE >> subX) + unitSize - 1 ) / unitSize)
for ( unitRow = unitRowStart; unitRow < unitRowEnd; unitRow++ ) {
for (unitCol = unitColStart; unitCol < unitColEnd; unitCol++) {
read_lr_unit(plane, unitRow + lrRowOffset,
unitCol + lrColOffset)
}
}
}
}
}

where count_units_in_frame is a function specified as:

count_units_in_frame(unitSize, frameSize) {    return Max((frameSize + (unitSize >> 1)) / unitSize, 1)}

5.20.70. Read loop restoration unit syntax

read_lr_unit(plane, unitRow, unitCol) { Descriptor
if ( FrameRestorationType[ plane ] == RESTORE_WIENER_NONSEP ) {
use_wiener_ns S()
restorationType = use_wiener_ns ? RESTORE_WIENER_NONSEP : RESTORE_NONE
} else if ( FrameRestorationType[ plane ] == RESTORE_PC_WIENER ) {
use_pc_wiener S()
restorationType = use_pc_wiener ? RESTORE_PC_WIENER : RESTORE_NONE
} else {
restorationType = RESTORE_SWITCHABLE_TYPES - 1
for ( tool = 0; tool < RESTORE_SWITCHABLE_TYPES - 1; tool++ ) {
flex_restoration_type S()
if ( flex_restoration_type ) {
restorationType = tool
break
}
}
}
LrType[ plane ][ unitRow ][ unitCol ] = restorationType
if ( restorationType == RESTORE_WIENER_NONSEP ) {
read_wienerns_filter( plane, unitRow, unitCol, 0 )
}
}

5.20.71. Read Wiener NS syntax

read_wienerns_filter( plane, unitRow, unitCol, readFrameFilters ) { Descriptor
numClasses = 1
if ( frame_filters_on[ plane ] ) {
if ( !readFrameFilters ) {
return
}
(numClasses, numRefFilters, _, _, _) = search_frame_filters( plane, -1 )
nopcw = lr_tools_disable[ 0 ][ RESTORE_PC_WIENER ]
groupCounts[ 0 ] = numClasses
groupCounts[ 1 ] = numRefFilters
groupCounts[ 2 ] = (plane > 0 || nopcw) ?
0 : 64 - numClasses - numRefFilters
for ( i = 0; i < 3; i++ ) {
groupHits[ i ] = 0
}
groupBase[ 0 ] = 0
for ( i = 1; i < 3; i++ ) {
groupBase[ i ] = groupBase[ i - 1 ] + groupCounts[ i - 1 ]
}
for ( c = 0 ; c < numClasses; c++ ) {
groupCounts[ 0 ] = c + 1
if ( c == 0 ) {
predGroup = (groupCounts[ 1 ] > 2) ?
1 : predict_group( groupCounts )
} else {
predGroup = predict_group( groupHits )
}
numZeros = 0
altGroup = 0
for ( i = 0; i < 3; i++ ) {
if ( i != predGroup ) {
if ( groupCounts[ i ] == 0 ) {
numZeros += 1
} else {
altGroup = i
}
}
}
if ( numZeros == 2 ) {
use_alt_group = 0
} else {
use_alt_group f(1)
}
if ( use_alt_group ) {
if ( numZeros == 1 ) {
group = altGroup
} else {
group_bit f(1)
group = predGroup <= group_bit ? group_bit + 1 : group_bit
}
} else {
group = predGroup
}
n = groupCounts[ group ]
ref = groupBase[ group ] + (n >> 1)
if ( n == 1 ) {
matchIndices[ c ] = groupBase[ group ]
} else {
matchIndices[ c ] = decode_signed_subexp_with_ref(
groupBase[ group ],
groupBase[ group ] + n, ref, 4)
}
groupHits[ group ]++
}
}
for ( c = 0 ; c < numClasses ; c++ ) {
if ( readFrameFilters ) {
merged_param f(1)
} else {
merged_param L(1)
}
merged[ c ] = merged_param
if ( readFrameFilters ) {
refBank[ c ] = 0
} else {
for ( k = 0; k < WienerNsBankSize[ plane ][ c ] - 1; k++ ) {
use_bank L(1)
if (use_bank) {
break
}
}
refBank[ c ] = (WienerNsPtr[ plane ][ c ] - k + LR_BANK_SIZE) %
LR_BANK_SIZE
}
}
for ( c = 0 ; c < numClasses ; c++ ) {
if ( frame_filters_on[ plane ] ) {
fill_first_slot_of_bank_with_filter_match( c, plane,
matchIndices[ c ] )
}
nCoeffs = plane > 0 ? WIENER_NS_CHROMA_COEFFS :
WIENER_NS_LUMA_COEFFS
if ( merged[ c ] ) {
if ( WienerNsBankSize[ plane ][ c ] == 0 ) {
WienerNsBankSize[ plane ][ c ] = 1
}
} else {
if ( WienerNsBankSize[ plane ][ c ] < LR_BANK_SIZE ) {
WienerNsPtr[ plane ][ c ] = WienerNsBankSize[ plane ][ c ]
WienerNsBankSize[ plane ][ c ] += 1
} else {
WienerNsPtr[ plane ][ c ] = (WienerNsPtr[ plane ][ c ] + 1) %
LR_BANK_SIZE
}
numSubsets = plane == 0 ? 4 : 3
for ( subset = 0; subset < numSubsets - 1; subset++ ) {
if ( readFrameFilters ) {
wiener_ns_length f(1)
} else {
wiener_ns_length S()
}
if ( wiener_ns_length == 0 ) {
break
}
}
if ( plane > 0 && subset > 0 ) {
if ( readFrameFilters ) {
wiener_ns_uv_sym f(1)
} else {
wiener_ns_uv_sym S()
}
} else {
wiener_ns_uv_sym = 0
}
}
for ( j = 0; j < nCoeffs; j++ ) {
min = Wiener_Ns_Taps_Min[ plane!=0 ][ j ]
k = Wiener_Ns_Taps_K[ plane!=0 ][ j ]
v = RefLrWienerNs[ plane ][ c ][ refBank[ c ] ][ j ]
if ( !merged[ c ] ) {
if ( Wiener_Ns_Taps_Present[ plane!=0 ][ subset ][ j ] ) {
if ( readFrameFilters ) {
v = decode_signed_subexp_with_ref( min, min + (1 << k),
v, k - 3 )
} else {
v = decode_signed_4part( min, k, v )
}
} else {
v = 0
}
}
if ( readFrameFilters ) {
FrameLrWienerNs[ plane ][ c ][ j ] = v
if ( !merged[ c ] && plane > 0 &&
j >= WIENER_NS_SHORT_COEFFS && wiener_ns_uv_sym ) {
FrameLrWienerNs[ plane ][ c ][ j + 1 ] = v
j++
}
} else {
LrWienerNs[ plane ][ unitRow ][ unitCol ][ j ] = v
if ( !merged[ c ] ) {
RefLrWienerNs[ plane ][ c ]
[ WienerNsPtr[ plane ][ c ] ][ j ] = v
}
if ( !merged[ c ] && plane > 0 &&
j >= WIENER_NS_SHORT_COEFFS && wiener_ns_uv_sym ) {
LrWienerNs[ plane ][ unitRow ][ unitCol ][ j + 1 ] = v
RefLrWienerNs[ plane ][ c ]
[ WienerNsPtr[ plane ][ c ] ][ j + 1 ] = v
j++
}
}
}
}
}

where decode_signed_4part is a function defined as follows:

decode_signed_4part(low, k, r) { Descriptor
rOffset = r - low
xOffset = decode_unsigned_4part(k, rOffset)
x = xOffset + low
return x
}
decode_unsigned_4part(k, r) {
mx = 1 << k
v = decode_4part( 6 - k )
if ((r << 1) <= mx) {
offset = inverse_recenter(r, v)
} else {
offset = mx - 1 - inverse_recenter(mx - 1 - r, v)
}
return offset
}
decode_4part(num) {
wiener_ns_base S()
bits = 2 - num + Max(1, wiener_ns_base)
offset = wiener_ns_base == 0 ? 0 : (1 << bits)
wiener_ns_rem L(bits)
return offset + wiener_ns_rem
}

The function fill_first_slot_of_bank_with_filter_match is specified as:

fill_first_slot_of_bank_with_filter_match( c, plane, m ) { Descriptor
WienerNsPtr[ plane ][ c ] = 0
WienerNsBankSize[ plane ][ c ] = 1
(numClasses, numRefFilters, matchIdx, matchCls, matchPlane) =
search_frame_filters( plane, m )
for( j = 0; j < ( (plane > 0) ? WIENER_NS_CHROMA_COEFFS :
WIENER_NS_LUMA_COEFFS ); j++ ) {
if ( m == 0 ) {
v = 0
} else if ( m < numClasses ) {
oldCls = m - 1
v = FrameLrWienerNs[ plane ][ oldCls ][ j ]
} else if ( m < numClasses + numRefFilters ) {
v = RefFrameLrWienerNs[ matchIdx ][ matchPlane ][ matchCls ][ j ]
} else {
v = get_translated_pc_wiener(m - NumFilterClasses - numRefFilters,j)
}
RefLrWienerNs[ plane ][ c ][ 0 ][ j ] = v
}
}

The function search_frame_filters is specified as:

search_frame_filters( plane, target ) { Descriptor
nopcw = lr_tools_disable[ 0 ][ RESTORE_PC_WIENER ]
minPcWiener = (plane > 0 || nopcw) ? 0 : 16
numClasses = (plane == 0) ? NumFilterClasses : 1
maxRefFilters = (nopcw ? 16 : 64) - numClasses - minPcWiener
numRefFilters = 0
numCheckPlanes = plane > 0 ? 2 : 1
matchIdx = 0
matchCls = 0
matchPlane = plane
for ( ref = 0; ref < NumTotalRefs; ref++ ) {
if ( FrameType != SWITCH_FRAME && OrderHints[ref] != RESTRICTED_OH ) {
idx = ref_frame_idx[ ref ]
for ( check = 0; check < numCheckPlanes; check++ ) {
if ( check == 0 ) {
checkPlane = plane
} else {
checkPlane = plane == 1 ? 2 : 1
}
if ( RefFrameFiltersOn[ idx ][ checkPlane ] ) {
numRefClasses = (plane == 0) ?
RefNumFilterClasses[ idx ] : 1
for ( i = 0; i < numRefClasses; i++ ) {
if ( numRefFilters < maxRefFilters ) {
if ( numRefFilters + numClasses == target ) {
matchIdx = idx
matchCls = i
matchPlane = checkPlane
}
numRefFilters += 1
}
}
}
}
}
}
return (numClasses, numRefFilters, matchIdx, matchCls, matchPlane)
}

The function get_translated_pc_wiener (which converts a pixel classified filter into a Wiener filter) is specified as:

get_translated_pc_wiener( m, j ) { Descriptor
if ( j >= 12 ) {
return 0
}
filt = Shuffled_Index[ m ]
coeff = Round2Signed( Pc_Wiener_Filters[ 0 ][ filt ][ j ],
PC_WIENER_PREC_BITS - WIENER_NS_PREC_BITS )
min = Wiener_Ns_Taps_Min[ 0 ][ j ]
max = min + ( 1 << Wiener_Ns_Taps_K[ 0 ][ j ] ) - 1
return Clip3(min, max, coeff)
}

where Shuffled_Index is defined as:

Shuffled_Index[ 64 ] = {    16, 7,  58, 21, 12, 61, 26, 38, 18, 30, 50,    45, 23, 49, 43, 62, 42, 54, 27, 36, 17, 44,    32, 34, 4,  24, 52, 31, 37, 11, 33, 19, 35,    6,  22, 53, 63, 25, 41, 47, 1,  59, 0,  28,    40, 55, 48, 8,  5,  51, 9,  46, 56, 60, 15,    2,  13, 14, 57, 29, 3,  20, 39, 10}

The function predict_group (which finds which group has the highest count) is specified as:

predict_group( counts ) { Descriptor
pred = 0
for ( i = 1; i <= 2; i++ ) {
if ( counts[ i ] > counts[ pred ] ) {
pred = i
}
}
return pred
}

The table Wiener_Ns_Taps_Present (which specifies which filter taps are present) is specified as:

Wiener_Ns_Taps_Present[ 2 ][ 4 ][ WIENER_NS_CHROMA_COEFFS ] = {    {        { 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},        { 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},        { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},        { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}    },    {        { 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},        { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},        { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}     }}
Section 6: Semantics

6.1. General

This section specifies the meaning of the syntax elements read in the syntax structures.

Important variables and function calls are also described.

6.2. OBU semantics

6.2.1. General OBU semantics

An ordered series of OBUs is presented to the decoding process. Each OBU is given to the decoding process as a string of bytes along with a variable sz that identifies the total number of bytes in the OBU.

Methods of framing the OBUs (i.e. of identifying the series of OBUs and their size and payload data) in a delivery or container format may be established in a manner outside the scope of this Specification. One simple method is described in Annex B.

OBU data starts on the first (most significant) bit and ends on the last bit of the given bytes. The payload of an OBU lies between the first bit of the given bytes and the last bit before the first trailing bit. Trailing bits are always present, unless the OBU consists of only the header. Trailing bits achieve byte alignment when the payload of an OBU is not byte aligned. The trailing bits may also be used for additional byte padding, and if used are taken into account in the sz value. In all cases, the pattern used for the trailing bits guarantees that all OBUs (except header-only OBUs) end with the same pattern: one bit set to one, optionally followed by zeros.

Note: As a validity check for malformed encoded data and for operation in environments in which losses and errors can occur, decoders may detect an error if the end of the parsed data is not directly followed by the correct trailing bits pattern or if the parsing of the OBU header and payload leads to the consumption of bits within the trailing bits (except for tile group data which is allowed to read a small distance into the trailing bits as described in § 8.2.4 Exit process for symbol decoder).

drop_obu( obuPayloadSize ) is a function call that indicates when the decoding process should ignore an OBU because it is not contained in the selected operating point. When an OBU is not in the selected operating point the contents have no effect on the decoding process.

When this function is called, the bitstream position indicator should be advanced by obuPayloadSize * 8 bits.

obu_extension_flag specifies if extension data is present.

It is a requirement of bitstream conformance that obu_extension_flag is equal to 0 in bitstreams conforming to this version of this Specification.

obu_extension_data( n ) contains n bits of extension data. The content of this data is not specified in this version of the Specification. Decoders conforming to this version of this Specification shall ignore the contents of obu_extension_data.

6.2.2. OBU header semantics

OBUs are structured with a header and a payload. The header identifies the type of the payload using the obu_type header parameter.

obu_header_extension_flag indicates if the obu_header contains the obu_mlayer_id and obu_xlayer_id syntax elements.

obu_type specifies the type of data structure contained in the OBU payload:

obu_type Name of obu_type Layer-specific
0 Reserved -
1 OBU_SEQUENCE_HEADER N
2 OBU_TEMPORAL_DELIMITER N
3 OBU_MULTI_FRAME_HEADER N
4 OBU_CLOSED_LOOP_KEY Y
5 OBU_OPEN_LOOP_KEY Y
6 OBU_LEADING_TILE_GROUP Y
7 OBU_REGULAR_TILE_GROUP Y
8 OBU_METADATA_SHORT See Table in § 6.16 Metadata OBU semantics
9 OBU_METADATA_GROUP See Table in § 6.16 Metadata OBU semantics
10 OBU_SWITCH Y
11 OBU_LEADING_SEF Y
12 OBU_REGULAR_SEF Y
13 OBU_LEADING_TIP Y
14 OBU_REGULAR_TIP Y
15 OBU_BUFFER_REMOVAL_TIMING Y
16 OBU_LAYER_CONFIGURATION_RECORD Y
17 OBU_ATLAS_SEGMENT Y
18 OBU_OPERATING_POINT_SET Y
19 OBU_BRIDGE_FRAME Y
20 OBU_MSDO Y
21 OBU_RAS_FRAME Y
22 OBU_QUANTIZATION_MATRIX Y
23 OBU_FILM_GRAIN Y
24 OBU_CONTENT_INTERPRETATION Y
25 OBU_PADDING Either
26-31 Reserved -

Reserved units are for future use and shall be ignored by AV2 decoder.

The column “Layer-specific” indicates if the corresponding OBU type is considered to be associated with a specific layer ("Y"), or not ("N").

Metadata OBU types may or may not be layer-specific, depending on the metadata type. The table in § 6.16 Metadata OBU semantics specifies which types of metadata OBUs are layer-specific and which are not.

Padding OBUs may or may not be layer-specific.

obu_tlayer_id specifies the temporal level of the data contained in the OBU.

obu_mlayer_id specifies the embedded level of the data contained in the OBU. In layer-specific OBUs, when obu_mlayer_id is not present it is inferred to be equal to 0.

obu_xlayer_id specifies the extended level of the data contained in the OBU. In layer-specific OBUs, when obu_xlayer_id is not present it is inferred to be equal to 0.

If obu_xlayer_id is equal to GLOBAL_XLAYER_ID, it is a requirement of bitstream conformance that both obu_mlayer_id and obu_tlayer_id are equal to 0.

Tile group OBU data associated with obu_tlayer_id and obu_mlayer_id equal to 0 are referred to as the base layer, whereas tile group OBU data that are associated with obu_mlayer_id greater than 0 or obu_tlayer_id greater than 0 are referred to as enhancement layer(s).

At the end of reading the OBU, it is a requirement of bitstream conformance that obu_tlayer_id is less than or equal to max_tlayer_id.

At the end of reading the OBU, it is a requirement of bitstream conformance that obu_mlayer_id is less than or equal to max_mlayer_id.

Note: These constraints on obu_tlayer_id and obu_mlayer_id apply at the end of reading the OBU because a sequence header OBU can change max_tlayer_id and max_mlayer_id.

6.2.3. Trailing bits semantics

Note: Tile group OBUs and frame OBUs do end with trailing bits, but for these cases, the trailing bits are consumed by the exit_symbol process.

trailing_one_bit shall be equal to 1.

When the syntax element trailing_one_bit is read, it is a requirement that nbBits is greater than zero.

trailing_zero_bit shall be equal to 0 and is inserted into the bitstream to align the bit position to a multiple of 8 bits and add optional zero padding bytes to the OBU.

6.2.4. Byte alignment semantics

zero_bit shall be equal to 0 and is inserted into the bitstream to align the bit position to a multiple of 8 bits.

6.3. Reserved OBU semantics

The reserved OBU allows the extension of this Specification with additional OBU types in a way that allows older decoders to ignore them.

6.4. Sequence header OBU semantics

6.4.1. General sequence header OBU semantics

TriggerFlushIfKey is a variable that specifies if frames from a previous coded video sequence need to be flushed.

Note: These frames are flushed if a sequence header is seen followed by an OBU of type OBU_CLOSED_LOOP_KEY without any other intermediate frames.

FirstLayer is a variable that specifies if a new sequence header needs to be activated.

Note: A sequence header is activated the first time an OBU of type OBU_CLOSED_LOOP_KEY or OBU_OPEN_LOOP_KEY is seen after a sequence header OBU.

seq_header_id specifies an identification number for the sequence header.

It is a requirement of bitstream conformance that seq_header_id is less than MAX_SEQ_NUM.

seq_lcr_id specifies the layer configuration record id that corresponds to this sequence header. If this sequence header is associated with a decoded video sequence in an extended layer with obu_xlayer_id equal to xLayerId and if seq_lcr_id is not equal to 0, the following applies:

  • if an OBU of obu_type equal to OBU_LAYER_CONFIGURATION_RECORD is associated with the extended layer id xLayerId and is either present prior to this sequence header in the same bitstream or is provided through external means, then this OBU is associated with this sequence header,

  • otherwise, if an OBU of obu_type equal to OBU_LAYER_CONFIGURATION_RECORD is associated with an obu_xlayer_id equal to GLOBAL_XLAYER_ID and is either present prior to this sequence header in the same bitstream or is provided through external means, then this OBU is associated with this sequence header,

  • otherwise, no OBU of obu_type equal to OBU_LAYER_CONFIGURATION_RECORD is associated with this sequence header.

still_picture equal to 1 specifies that the coded video sequence contains only one coded frame. still_picture equal to 0 specifies that the coded video sequence contains one or more coded frames.

single_picture_header_flag specifies that the syntax elements not needed by a still picture are omitted.

seq_profile_idc specifies the sequence level coding features that can be used in a coded video sequence associated with a unique obu_xlayer_id.

More information about the allowed values of seq_profile_idc supported in this version of this specification are defined in Annex A.

max_display_model_info_present_flag specifies whether the syntax element max_initial_display_delay_minus_1 is present.

max_initial_display_delay_minus_1 plus 1 specifies the intial display delay for use in the decoder model.

decoder_model_info_present_flag specifies whether decoder model information is present in the coded video sequence.

max_display_model_info_present_flag specifies whether display model information is present in the coded video sequence.

max_tlayer_id specifies the maximum value for obu_tlayer_id for the OBUs represented by this sequence header.

max_mlayer_id specifies the maximum value for obu_mlayer_id for the OBUs represented by this sequence header.

An operating point specifies which spatial and temporal layers should be decoded.

operating_point_idc[ i ] contains a bitmask that indicates which spatial and temporal layers should be decoded for operating point i. Bit k is equal to 1 if temporal layer k should be decoded (for k between 0 and 7). Bit j+8 is equal to 1 if spatial layer j should be decoded (for j between 0 and 3).

However, if operating_point_idc[ i ] is equal to 0 then the coded video sequence has no scalability information and the operating point applies to the entire coded video sequence. This means that all OBUs must be decoded.

It is a requirement of bitstream conformance that operating_point_idc[ i ] is not equal to operating_point_idc[ j ] for j = 0..(i - 1).

Note: This constraint means it is not allowed for two operating points to have the same value of operating_point_idc.

seq_level_idx specifies the level that the coded video sequence conforms to.

seq_tier specifies the tier that the coded video sequence conforms to.

seq_max_mlayer_cnt specifies the maximum number of embedded layers that can be included in the coded video sequence associated with this sequence header. The value of seq_max_mlayer_cnt shall be in the range of 1 to (max_mlayer_id + 1). When seq_max_mlayer_cnt is not present, it is set equal to 1.

choose_operating_point( ) is a function call that indicates that the operating point should be selected.

The implementation of this function depends on the capabilities of the chosen implementation. The order of operating points indicates the preferred order for producing an output: a decoder should select the earliest operating point in the list that meets its decoding capabilities as expressed by the level associated with each operating point.

A decoder must return a value from choose_operating_point between 0 and operating_points_cnt_minus_1, or abandon the decoding process if no level within the decoder’s capabilities can be found.

Note: To help with conformance testing, decoders may allow the operating point to be explicitly signaled by external means.

Note: A decoder may need to change the operating point selection when a new coded video sequence begins.

OperatingPointIdc specifies the value of operating_point_idc for the selected operating point.

It is a requirement of bitstream conformance that the display order hints computation for any frame (i.e. the value returned from get_disp_order_hint) is the same for all the operating points within the bitstream associated with this frame.

It is a requirement of bitstream conformance that if explicit_ref_frame_map is equal to 0 for a frame, the implicit reference mapping process results in the same reference mapping (i.e. they result in exactly the same reference frames to be associated with exactly the same reference indices) for all the operating points within the bitstream associated with the current frame.

Note: This means that the corresponding calls to the get ref frames process specified in § 7.6 Get ref frames process result in exactly the same contents being written to the ref_frame_idx array, and that the corresponding reference frames are the same.

It is a requirement of bitstream conformance that if explicit_ref_frame_map is equal to 1 for a frame, any reference buffer index associated with a particular reference frame, indicated by the explicit reference mapping process, corresponds to the same frame for all operating points within the bitstream associated with the current frame.

Note: These requirements ensure that the references used by a frame are the same for all the operating points that are associated with the current frame. This implies that if film_grain_params_ref_idx is present in the bitstream, the reference frame corresponding to the value of film_grain_params_ref_idx shall be the same for all operating points within the bitstream associated with the current frame, (because it is a requirement of bitstream conformance that film_grain_params_ref_idx is equal to ref_frame_idx[ j ] for some value of j in the range 0 to NumTotalRefs - 1).

frame_width_bits_minus_1 specifies the number of bits minus 1 used for transmitting the frame width syntax elements.

frame_height_bits_minus_1 specifies the number of bits minus 1 used for transmitting the frame height syntax elements.

max_frame_width_minus_1 specifies the maximum frame width minus 1 for the frames represented by this sequence header.

max_frame_height_minus_1 specifies the maximum frame height minus 1 for the frames represented by this sequence header.

seq_cropping_window_present_flag specifies whether the cropping window syntax elements are present in the sequence header.

seq_cropping_win_left_offset is the amount to crop off the left of the frame.

It is a requirement of bitstream conformance that seq_cropping_win_left_offset is less than or equal to max_frame_width_minus_1.

seq_cropping_win_right_offset is the amount to crop off the right of the frame.

It is a requirement of bitstream conformance that seq_cropping_win_right_offset is less than or equal to max_frame_width_minus_1.

seq_cropping_win_top_offset is the amount to crop off the top of the frame.

It is a requirement of bitstream conformance that seq_cropping_win_top_offset is less than or equal to max_frame_height_minus_1.

seq_cropping_win_bottom_offset is the amount to crop off the bottom of the frame.

It is a requirement of bitstream conformance that seq_cropping_win_bottom_offset is less than or equal to max_frame_height_minus_1.

Note: The amounts are expressed in terms of pixels to crop for a frame of maximum size. Smaller frames will have proportionately fewer pixels cropped.

tlayer_dependency_present_flag specified whether tlayer_dependency_map syntax elements are present in the bitstream.

tlayer_dependency_map specifies the temporal layer dependencies.

mlayer_dependency_present_flag specified whether mlayer_dependency_map syntax elements are present in the bitstream.

mlayer_dependency_map specifies the spatial layer dependencies.

seq_tile_info_present_flag specifies whether tile parameters are present in the coded video sequence.

allow_tile_info_change specifies whether if the tile info can be changed in the frame header.

film_grain_params_present specifies whether film grain parameters are present in the coded video sequence.

save_sequence_header is a function call that indicates that all the syntax elements and variables read in sequence_header_obu are stored in an area of memory indexed by seq_header_id.

6.4.2. Sequence partition config semantics

use_256x256_superblock, when equal to 1, indicates that superblocks in inter frames contain 256x256 luma samples. When equal to 0, it indicates that use_128x128_superblock should be read to determine the superblock size.

use_128x128_superblock, when equal to 1, indicates that superblocks contain 128x128 luma samples. When equal to 0, it indicates that superblocks contain 64x64 luma samples. (The number of contained chroma samples depends on SubsamplingX and SubsamplingY.)

enable_sdp specifies whether the chroma partitioning can be sent separately to the luma partitioning.

enable_extended_sdp specifies whether chroma partitioning can be sent separately within an inter frame.

enable_ext_partitions specifies whether an extended range of partitions are allowed in the coded video sequence.

enable_uneven_4way_partitions specifies whether uneven four way partitions are allowed in the coded video sequence.

reduce_pb_aspect_ratio specifies if a reduced aspect ratio of blocks is used in the coded video sequence.

max_pb_aspect_ratio_log2_minus1 plus 1 specifies the base 2 logarithm of the maximum aspect ratio of blocks in the coded video sequence.

6.4.3. Sequence segment config semantics

enable_ext_seg enables extra segment ids. enable_ext_seg equal to 0 specifies there are 8 segments available. enable_ext_seg equal to 1 specifies there are 16 segments available.

seq_seg_info_present_flag specifies whether segment information is specified in this sequence header.

seq_allow_seg_info_change specifies whether the segment information in this sequence header can be changed in the frame header.

6.4.4. Sequence intra config semantics

enable_dip equal to 1 specifies that the use_dip syntax element may be present. enable_dip equal to 0 specifies that the use_dip syntax element will not be present.

enable_intra_edge_filter specifies whether the intra edge filtering process should be enabled.

enable_mrls specifies whether multiple reference line intra prediction is allowed in the coded video sequence.

enable_cfl_intra specifies whether chroma from luma prediction is allowed in the coded video sequence.

cfl_ds_filter_index specifies the type of down-sampling applied to luma samples in CFL prediction process. It is also used to specify the type of down-sampling applied to luma samples in loop restoration filtering process.

Note: A value of 3 can be read for cfl_ds_filter_index, but behaves the same as a value of 0.

enable_mhccp specifies whether MHCCP is allowed in the coded video sequence.

enable_ibp specifies whether IBP is enabled.

6.4.5. Sequence inter config semantics

seq_enabled_motion_modes specifies which motion modes are enabled.

seq_frame_motion_modes_present_flag specifies if frame_enabled_motion_modes are present in the uncompressed header.

enable_six_param_warp_delta equal to 1 specifies that six or four parameters are used for warp delta. enable_six_param_warp_delta equal to 0 specifies that four parameters are used for warp delta.

enable_masked_compound equal to 1 specifies that the mode info for inter blocks may contain the syntax element compound_type. enable_masked_compound equal to 0 specifies that the syntax element compound_type will not be present.

enable_ref_frame_mvs equal to 1 indicates that the use_ref_frame_mvs syntax element may be present. enable_ref_frame_mvs equal to 0 indicates that the use_ref_frame_mvs syntax element will not be present.

reduced_ref_frame_mvs_mode equal to 1 indicates that motion fields from at most one reference frame will be processed.

order_hint_bits_minus_1 is used to compute OrderHintBits.

OrderHintBits specifies the number of bits used for the order_hint syntax element.

enable_refmvbank equal to 1 specifies that banks of recently used motion vectors should be used during motion vector prediction.

disable_drl_reorder and constrain_drl_reorder are used to set the value for DrlReorder:

DrlReorder Name of DrlReorder
0 DRL_REORDER_DISABLED
1 DRL_REORDER_CONSTRAINT
2 DRL_REORDER_ALWAYS

explicit_ref_frame_map equal to 1 specifies that the ref_frame_idx syntax elements will be present in the frame header.

use_extra_ref_frames equal to 1 specifies that the num_ref_frames_minus_1 syntax element is present. Otherwise, num_ref_frames_minus_1 is not present and NumRefFrames is inferred equal to 8.

num_ref_frames_minus_1 plus 1 specifies the number of reference frame slots in the coded video sequence.

long_term_frame_id_bits specifies the number of bits used to specify long term ids.

seq_max_drl_bits_minus1 controls the number of bits read for drl_idx for inter blocks.

allow_frame_max_drl_bits equal to 1 indicates that change_drl is present in the frame header.

seq_max_bvp_drl_bits_minus1 controls the number of bits read for drl_idx for intra BC.

allow_frame_max_bvp_drl_bits equal to 1 indicates that change_bvp_drl is present in the frame header.

num_same_ref_compound specifies the number of references that can be used for same reference compound prediction. This refers to a case when a block uses compound inter prediction, but both references are to the same reference frame.

enable_tip specifies if TIP is allowed in the coded video sequence.

disable_tip_output equal to 1 prevents TipFrameMode from being set to TIP_FRAME_AS_OUTPUT in the coded video sequence.

enable_tip_hole_fill specifies if holes in the interpolated motion field are filled in with estimated motion vectors.

enable_mv_traj specifies if the motion vector trajectory analysis is enabled.

enable_bawp equal to 1 specifies that the allow_bawp syntax element is present in frame headers. Otherwise, allow_bawp is not present and will be inferred to be equal to 0.

enable_cwp specifies whether compound weighted prediction is enabled.

enable_imp_msk_bld specifies whether implicit mask blending is enabled.

enable_lf_sub_pu equal to 1 specifies that the allow_lf_sub_pu syntax element is present in frame headers. enable_lf_sub_pu equal to 0 specifies that the allow_lf_sub_pu syntax element is not present in frame headers (and allow_lf_sub_pu will be inferred to be equal to 0).

enable_tip_explicit_qp equal to 1 specifies that the quantization parameters for TIP are sent explicitly. enable_tip_explicit_qp equal to 0 specifies that the quantization parameters are inferred.

enable_opfl_refine specifies how optical flow is signaled:

enable_opfl_refine Name of enable_opfl_refine
0 REFINE_NONE
1 REFINE_SWITCHABLE
2 REFINE_ALL
3 REFINE_AUTO

Note: REFINE_NONE means optical flow is not used in the coded video sequence. REFINE_SWITCHABLE means the syntax element use_optflow is present to signal the use per block. REFINE_ALL means that optical flow will be used where allowed without being signaled. REFINE_AUTO means that the frame header contains the syntax element opfl_refine_type that allows the method to be varied per frame.

enable_refinemv specifies if motion vector refinement can be used.

enable_tip_refinemv specifies if motion vector refinement and optical flow can be used with TIP prediction.

enable_bru specifies if the use_bru syntax element is present for inter frames in frame headers.

enable_adaptive_mvd specifies if adaptive motion vector differences can be used in the coded video sequence.

enable_mvd_sign_derive specifies if the motion vector sign can be derived instead of being signaled.

enable_flex_mvres specifies if the motion vector precision can be specified per block.

enable_global_motion specifies if global motion is enabled in the coded video sequence.

enable_short_refresh_frame_flags specifies if has_refresh_frame_flags is present in the coded video sequence.

6.4.6. Sequence screen content config semantics

seq_choose_screen_content_tools equal to 0 indicates that the seq_force_screen_content_tools syntax element will be present. seq_choose_screen_content_tools equal to 1 indicates that seq_force_screen_content_tools should be set equal to SELECT_SCREEN_CONTENT_TOOLS.

seq_force_screen_content_tools equal to SELECT_SCREEN_CONTENT_TOOLS indicates that the allow_screen_content_tools syntax element will be present in the frame header. Otherwise, seq_force_screen_content_tools contains the value for allow_screen_content_tools.

seq_choose_integer_mv equal to 0 indicates that the seq_force_integer_mv syntax element will be present. seq_choose_integer_mv equal to 1 indicates that seq_force_integer_mv should be set equal to SELECT_INTEGER_MV.

seq_force_integer_mv equal to SELECT_INTEGER_MV indicates that the force_integer_mv syntax element will be present in the frame header (providing allow_screen_content_tools is equal to 1). Otherwise, seq_force_integer_mv contains the value for force_integer_mv.

6.4.7. Sequence transform_quant_entropy config semantics

enable_fsc specifies whether forward skip coding is enabled.

enable_idtx_intra specifies whether the identity transform is allowed for intra blocks when enable_fsc equal to 0. When enable_fsc is equal to 1, enable_idtx_intra is inferred to be equal to 1.

enable_intra_ist specifies whether the secondary transform is allowed for intra blocks in the coded video sequence.

enable_inter_ist specifies whether the secondary transform is allowed for inter blocks in the coded video sequence.

enable_chroma_dctonly specifies whether the chroma transform is forced to be only DCT.

enable_inter_ddt specifies whether the data dependent transform is allowed for inter blocks in the coded video sequence.

reduced_tx_part_set specifies whether a reduced set of transform partitions is allowed in the coded video sequence.

enable_cctx specifies whether cross component transform is allowed in the coded video sequence.

enable_tcq equal to 1 specifies that TCQ is allowed in the coded video sequence. enable_tcq equal to 0 specifies that TCQ is not allowed in the coded video sequence.

choose_tcq_per_frame equal to 1 specifies that allow_tcq is specified in each frame header. choose_tcq_per_frame equal to 0 specifies that allow_tcq is inferred to be equal to enable_tcq.

enable_parity_hiding specifies whether the allow_parity_hiding syntax elements are present in the coded video sequence.

enable_avg_cdf equal to 1 specifies that the CDFs will be based on an average across CDFs.

avg_cdf_type equal to 1 specifies that the CDFs will be averaged across tiles. avg_cdf_type equal to 0 specifies that the CDFs can be blended between the CDFs saved for different reference frames.

separate_uv_delta_q equal to 1 indicates that the U and V planes may have separate delta quantizer values. separate_uv_delta_q equal to 0 indicates that the U and V planes will share the same delta quantizer value.

equal_ac_dc_q specifies that the DC quantizers match the AC quantizers.

base_y_dc_delta_q specifies a quantizer offset for the DC coefficients in the Y plane.

base_uv_dc_delta_q specifies a quantizer offset for the DC coefficients in the U and V planes.

base_uv_ac_delta_q specifies a quantizer offset for the AC coefficients in the U and V planes.

y_dc_delta_q_enabled specifies that the frame header has a quantizer offset for DC coefficients in the Y plane.

uv_dc_delta_q_enabled specifies that the frame header has a quantizer offset for DC coefficients in the U and V planes.

uv_ac_delta_q_enabled specifies that the frame header has a quantizer offset for AC coefficients in the U and V planes.

6.4.8. Segment information semantics

feature_enabled equal to 0 indicates that the corresponding feature is unused and has value equal to 0. feature_enabled equal to 1 indicates that the feature value is coded.

feature_value specifies the feature data for a segment feature.

6.4.9. Sequence filter config semantics

disable_loopfilters_across_tiles equal to 1 specifies that the loop filter stages do not access samples from a different tile.

enable_cdef equal to 1 specifies that cdef filtering may be enabled. enable_cdef equal to 0 specifies that cdef filtering is disabled.

Note: It is allowed to set enable_cdef equal to 1 even when cdef filtering is not used on any frame in the coded video sequence.

enable_gdf equal to 1 specifies that GDF filtering may be enabled. enable_gdf equal to 0 specifies that GDF filtering is disabled.

enable_restoration equal to 1 specifies that loop restoration filtering may be enabled. enable_restoration equal to 0 specifies that loop restoration filtering is disabled.

Note: It is allowed to set enable_restoration equal to 1 even when loop restoration is not used on any frame in the coded video sequence.

lr_tools_disable[0][i] specifies which loop restoration tools are disabled for luma.

lr_tools_disable[1][i] specifies which loop restoration tools are disabled for chroma.

lr_tools_uv_present specifies if the chroma lr_tools_disable syntax elements are present.

Note: It is allowed to set lr_tools_uv_present equal to 1 even if the stream does not contain chroma.

enable_ccso equal to 1 specifies that CCSO filtering may be enabled. enable_ccso equal to 0 specifies that CCSO filtering is disabled.

cdef_on_skip_txfm_always_on equal to 1 specifies that CDEF will always be on for skipped transform blocks.

cdef_on_skip_txfm_disabled equal to 1 specifies that CDEF will always be off for skipped transform blocks. cdef_on_skip_txfm_disabled equal to 0 specifies that a frame level enable is used to specify how CDEF is applied for skipped transform blocks.

df_par_bits_minus2 plus 2 specifies the number of bits used to read the lf_delta_q syntax element.

6.4.10. User defined QM semantics

qm_copy_from_previous_plane equal to 1 specifies that the quantization matrices are copied from the previous plane.

qm_8x8_is_symmetric equal to 1 specifies that the quantization matrix for TX_8X8 is symmetric (so certain entries can be inferred instead of being present in the bitstream).

qm_4x8_is_transpose_of_8x4 equal to 1 specifies that the quantization matrix for TX_4X8 is equal to the transpose of the matrix for TX_8X4.

quant_delta specifies the adjustment between quantizer values.

It is a requirement of bitstream conformance that quant_delta is greater than or equal to -128, and less than or equal to 127.

It is a requirement of bitstream conformance that no value written into UserQm is equal to 0.

6.4.11. Color config semantics

chroma_format_idc specifies the chroma subsampling format.

chroma_format_idc Name of chroma_format_idc SubsamplingX SubsamplingY Monochrome Description
0 CHROMA_FORMAT_420 1 1 0 YUV 4:2:0
1 CHROMA_FORMAT_400 1 1 1 Monochrome 4:0:0
2 CHROMA_FORMAT_444 0 0 0 YUV 4:4:4
3 CHROMA_FORMAT_422 1 0 0 YUV 4:2:2

It is a requirement of bitstream conformance that chroma_format_idc is less than or equal to 3.

bit_depth_idc is used to determine the bit depth.

It is a requirement of bitstream conformance that bit_depth_idc is less than or equal to 2.

Monochrome equal to 1 indicates that the video does not contain U and V color planes. Monochrome equal to 0 indicates that the video contains Y, U, and V color planes.

SubsamplingX, SubsamplingY specify the chroma subsampling format:

6.4.12. Timing info semantics

num_units_in_display_tick is the number of time units of a clock operating at the frequency time_scale Hz that corresponds to one increment of a clock tick counter. A display clock tick, in seconds, is equal to num_units_in_display_tick divided by time_scale:

DispCT = num_units_in_display_tick ÷ time_scale

Note: The ÷ operator represents standard mathematical division (in contrast to the / operator which represents integer division).

It is a requirement of bitstream conformance that num_units_in_display_tick is greater than 0.

time_scale is the number of time units that pass in one second.

It is a requirement of bitstream conformance that time_scale is greater than 0.

equal_picture_interval equal to 1 indicates that pictures should be displayed according to their output order with the number of ticks between two consecutive pictures (without dropping frames) specified by num_ticks_per_picture_minus_1 + 1. equal_picture_interval equal to 0 indicates that the interval between two consecutive pictures is not specified.

num_ticks_per_picture_minus_1 plus 1 specifies the number of clock ticks corresponding to output time between two consecutive pictures in the output order.

It is a requirement of bitstream conformance that the value of num_ticks_per_picture_minus_1 shall be in the range of 0 to (1 << 32) − 2, inclusive.

Note: The frame rate, when specified explicitly, applies to the top temporal layer of the bitstream. If bitstream is expected to be manipulated, e.g. by intermediate network elements, then the resulting frame rate may not match the specified one. In this case, an encoder is advised to use explicit time codes or some mechanisms that convey picture timing information outside the bitstream.

6.4.13. Decoder model info semantics

num_units_in_decoding_tick is the number of time units of a decoding clock operating at the frequency time_scale Hz that corresponds to one increment of a clock tick counter:

DecCT = num_units_in_decoding_tick ÷ time_scale

Note: The ÷ operator represents standard mathematical division (in contrast to the / operator which represents integer division).

num_units_in_decoding_tick shall be greater than 0. DecCT represents the expected time to decode a single frame or a common divisor of the expected times to decode frames of different sizes and dimensions present in the coded video sequence.

6.4.14. Operating parameters info semantics

decoder_buffer_delay specifies the time interval between the arrival of the first bit in the smoothing buffer and the subsequent removal of the data that belongs to the first coded frame, measured in units of 1/90000 seconds. The length of decoder_buffer_delay is specified by buffer_delay_length_minus_1 + 1, in bits.

encoder_buffer_delay specifies, in combination with decoder_buffer_delay syntax element, the first bit arrival time of frames to be decoded to the smoothing buffer. encoder_buffer_delay is measured in units of 1/90000 seconds.

For a video sequence that includes one or more random access points the sum of decoder_buffer_delay and encoder_buffer_delay shall be kept constant.

low_delay_mode_flag equal to 1 indicates that the smoothing buffer operates in low-delay mode. In low-delay mode late decode times and buffer underflow are both permitted. low_delay_mode_flag equal to 0 indicates that the smoothing buffer operates in strict mode, where buffer underflow is not allowed.

6.5. Temporal delimiter OBU semantics

SeenFrameHeader is a variable used to mark whether the frame header for the current frame has been received. It is initialized to zero.

6.6. Multi stream decoder operation OBU semantics

It is a requirement of bitstream conformance that a multi stream decoder operation OBU has:

  1. obu_tlayer_id equal to 0.

  2. obu_mlayer_id equal to 0.

  3. obu_xlayer_id equal to GLOBAL_XLAYER_ID.

num_streams_minus2 plus 2 specifies the number of independent streams in the bitstream. It is a requirement of bitstream conformance that num_streams_minus_2 is not greater than 2.

multi_config_idc specifies the multi-sequence configuration for the coded multi-stream sequence.

multi_level_idx specifies the level to which the coded multi-stream sequence conforms.

multi_tier specifies the tier to which the coded multi-stream sequence conforms.

multi_interop specifies the interoperability point to which the coded multi-stream sequence conforms.

multi_even_allocation_flag specifies the resource allocation for the multi-stream.

multi_large_picture_idc specifies an index of the sub_xlayer_id array that has a larger resource allocation than the other independent sub-bitstreams.

sub_xlayer_id[ i ] specifies the value of obu_xlayer_id in the obu_extension_header for the i-th independent sub-bitstream in the present bitstream.

sub_profile[ i ] indicates the profile for the i-th independent sub-bitstream in the present bitstream.

sub_level[ i ] indicates the level to which the coded i-th independent sub-bitstream in the present bitstream conforms.

sub_tier[ i ] indicates the tier to which the coded i-th independent sub-bitstream in the present bitstream conforms.

sub_mlayer_count[ i ] indicates the embedded layer count to which the coded i-th independent sub-bitstream in the present bitstream.

6.7. Multi frame header OBU semantics

mfh_seq_header_id specifies a sequence header id.

It is a requirement of bitstream conformance that mfh_seq_header_id is less than MAX_SEQ_NUM.

mfh_id_minus1 plus 1 identifies the multi-frame header for reference by a frame header or a coded frame.

It is a requirement of bitstream conformance that mfh_id_minus1 + 1 is less than MAX_MFH_NUM.

mfh_frame_size_present_flag specifies whether the syntax elements mfh_frame_width_minus_1 and mfh_frame_height_minus_1 are present or not in the multi-frame header.

mfh_tile_info_present_flag specifies whether tile parameters are specified in this multi-frame header.

mfh_frame_width_bits_minus_1 plus one specifies the number of bits used to read mfh_frame_width_minus_1.

mfh_frame_height_bits_minus_1 plus one specifies the number of bits used to read mfh_frame_height_minus_1.

mfh_frame_width_minus_1 plus one specifies the width of the frame that references the multi-frame header in luma samples.

mfh_frame_height_minus_1 plus one specifies the height of the frame that references the multi-frame header in luma samples.

mfh_loop_filter_update specifies whether the syntax elements mfh_apply_loop_filter are present or not in the multi-frame header.

mfh_apply_loop_filter is an array containing flags that specify if the loop filter is applied for a particular plane and direction. Different mfh_apply_loop_filter values from the array are used by a frame header or a coded frame that references the multi-frame header, depending on the image plane being filtered, and the edge direction (vertical or horizontal) being filtered.

mfh_sb_size_idx specifies two superblock sizes for use in reading the tile parameters.

mfh_allow_tile_info_change specifies if the tile info can be changed in the frame header. If mfh_allow_tile_info_change is equal to 0, the tile parameters from the multi frame header are used.

mfh_seg_info_present_flag specifies whether segment information is specified in this multi-frame header.

mfh_ext_seg_flag specifies whether the segment information uses an extended number of segments.

mfh_allow_seg_info_change specifies whether the segment information in this multi-frame header can be changed in the frame header.

6.8. Layer config record OBU semantics

This OBU contains either global information or local layer information depending on the value of obu_xlayer_id.

6.8.1. LCR global info semantics

lcr_global_config_record_id provides an identifier for the global LCR for reference by other syntax elements.

It is a requirement of bitstream conformance that lcr_global_config_record_id is in the range of 1 to 7, inclusive.

lcr_xlayers_map is a bitmap indicating the extended layer sub-bitstreams that are associated with this global LCR and can be present in a CVS that refers to this global LCR. It is a requirement of bitstream conformance that lcr_xlayers_map is in the range of 1 to (1 << 31) - 1, inclusive.

lcr_aggregate_profile_tier_level_info_present_flag specifies whether the lcr_profile_tier_level() syntax structure is present in the current LCR. If lcr_aggregate_profile_tier_level_info_present_flag is equal to 1, then the lcr_aggregate_profile_tier_level_info() syntax structure, which indicates the aggregate profile, tier, level, and interoperability point information of all sub-bitstreams that can be present in the CVS associated with this global LCR, is present in the current LCR. If lcr_aggregate_profile_tier_level_info_present_flag is equal to 0, this information is not present but could be derived by examining the profile, tier, and level indicators, in addition to the maximum number of embedded layers that are indicated for each individual extended layer that is associated with this LCR.

lcr_seq_profile_tier_level_info_present_flag specifies whether the lcr_seq_profile_tier_level_info( i ) syntax structure, for an extended layer with index i that is associated with this LCR, is present in the current LCR. If lcr_seq_profile_tier_level_info_present_flag is equal to 1, then the lcr_seq_profile_tier_level_info( i ) syntax structure, which indicates the sequence profile, tier, level, and maximum number of embedded layers that can be present in the extended layer sub-bitstream with obu_xlayer_id equal to i that is associated with this global LCR, is present in the current LCR. If lcr_seq_profile_tier_level_info_present_flag is equal to 0, this information is not present but could be derived through other means.

lcr_global_payload_present_flag specifies whether the payload, lcr_global_payload( i ) for each individual extended layer i associated with this LCR is present or not in this syntax structure. If lcr_global_payload_present_flag is equal to 1, lcr_global_payload( i ) for each individual extended layer i associated with this LCR is present. Otherwise, if lcr_global_payload_present_flag is equal to 0, lcr_global_payload( i ) for each individual extended layer i associated with this LCR is not present.

lcr_dependent_xlayers_flag specifies whether the syntax element lcr_num_dependent_xlayer_map[ j ] for any extended layer with ID equal to j is present in the global LCR. If lcr_dependent_xlayers_flag is equal to 1, then the lcr_num_dependent_xlayer_map[ j ] syntax element for any extended layer with ID equal to j is present in the current LCR. Otherwise, if lcr_dependent_xlayers_flag is equal to 0, then the lcr_num_dependent_xlayer_map[ j ] syntax element for any extended layer with ID equal to j is not present in the current global LCR.

It is a requirement of bitstream conformance to this version of this specification that the value of lcr_dependent_xlayers_flag is equal to 0. Decoders conforming to this version of this specification shall ignore non-zero values of lcr_dependent_xlayers_flag.

lcr_global_atlas_id_present_flag specifies whether the syntax element lcr_global_atlas_id is present in the global LCR. If lcr_global_atlas_id_present_flag is equal to 1, then the lcr_global_atlas_id syntax element is present in the current global LCR. Otherwise, if lcr_global_atlas_id_present_flag is equal to 0, then the lcr_global_atlas_id syntax element is not present in the current global LCR.

lcr_global_purpose_id specifies the application purpose for the layered bitstream associated with this global LCR by referencing its lcr_global_config_record_id, as follows:

lcr_global_purpose_id Application Purpose
0 Unspecified
1 Stereoscopic Viewports
2 Immersive Multiple Viewports
3 Immersive Multiple Viewports + Alpha
4 Immersive Multiple Viewports + Depth
5 Immersive Multiple Viewports + Alpha + Depth
6 Multiview Playback
7 Subregion Playback
8-127 Reserved

lcr_global_atlas_id, when present, specifies the value of the atlas_segment_id[ 31 ] associated with the current global LCR. When not present in a global LCR, the value of atlas_segment_id[ 31 ] shall be assumed to be equal to 0.

lcr_reserved_zero_3bits, when present, shall be equal to 0 in bitstreams conforming to this version of this Specification. Other values for lcr_reserved_zero_3bits are reserved for future use by AOMedia. Decoders shall ignore the value of lcr_reserved_zero_3bits.

lcr_reserved_zero_7bits, when present, shall be equal to 0 in bitstreams conforming to this version of this Specification. Other values for lcr_reserved_zero_7bits are reserved for future use by AOMedia. Decoders shall ignore the value of lcr_reserved_zero_7bits.

lcr_data_size[ i ], when present, indicates the number of bytes present in an indicated lcr_global_payload() module that is associated with the extended layer sub-bitstream with obu_xlayer_id equal to i.

6.8.2. LCR local info semantics

lcr_global_id[ i ] specifies the value of the lcr_global_config_record_id associated with the local LCR that is indicated in an extended layer with obu_xlayer_id equal to i.

It is a requirement of bitstream conformance that lcr_global_id is not equal to 0.

lcr_local_id[ i ] provides an identifier for the local LCR indicated in an extended layer with ID equal to i for reference by other syntax elements.

It is a requirement of bitstream conformance that lcr_local_id[ i ] is not equal to 0.

lcr_profile_tier_level_info_present_flag[ i ] specifies whether the lcr_seq_profile_tier_level_info( i ) syntax structure, for the extended layer with index i that is associated with this LCR, is present in the current LCR. If lcr_profile_tier_level_info_present_flag[ i ] is equal to 1, then the lcr_seq_profile_tier_level_info( i ) syntax structure, which indicates the sequence profile, tier, level, and maximum number of embedded layers that can be present in the extended layer sub-bitstream with obu_xlayer_id equal to i, is present in this LCR. If lcr_profile_tier_level_info_present_flag[ i ] is equal to 0, this information is not present but could be derived through other means.

lcr_local_atlas_id_present_flag[ i ] specifies whether the syntax element lcr_local_atlas_id[ i ] is present in the local LCR in the extended layer with obu_xlayer_id equal to i. If lcr_local_atlas_id_present_flag[ i ] is equal to 1, then the lcr_local_atlas_id[ i ] syntax element is present. Otherwise (if lcr_local_atlas_id_present_flag[ i ] is equal to 0), then the lcr_local_atlas_id[ i ] syntax element is not present.

lcr_local_atlas_id[ i ], when present, provides an identifier for a local atlas with atlas_segment_id equal to lcr_local_atlas_id[ i ] that is associated with the extended layer with obu_xlayer_id equal to i. If this value is not present this information can be provided by a global atlas, if present, or is considered as unspecified.

lcr_reserved_zero_3bits, when present, shall be equal to 0 in bitstreams conforming to this version of this Specification. Other values for lcr_reserved_zero_3bits are reserved for future use by AOMedia. Decoders shall ignore the value of lcr_reserved_zero_3bits.

lcr_reserved_zero_5bits, when present, shall be equal to 0 in bitstreams conforming to this version of this Specification. Other values for lcr_reserved_zero_5bits are reserved for future use by AOMedia. Decoders shall ignore the value of lcr_reserved_zero_5bits.

6.8.3. LCR aggregate profile tier level payload semantics

lcr_config_idc indicates a profile to which the associated bitstream that has activated this global LCR conforms to according to Annex A. Bitstreams conforming to this version of this specification shall not contain values of lcr_config_idc outside those specified in Annex A. Other values of lcr_config_idc are reserved for future extensions of this specification by AOMedia.

lcr_aggregate_level_idx indicates an aggregate level indicator to which the combination of all sub-bitstreams associated with a bitstream that has activated this LCR conforms to according to Annex A. Bitstreams conforming to this version of this specification shall not contain values of lcr_aggregate_level_idx outside those specified in Annex A.

lcr_max_tier_flag indicates the maximum tier indicator to which all sub-bitstreams associated with a bitstream that has activated this LCR conform to according to Annex A.

lcr_max_interop indicates the maximum interoperability point that the associated bitstream that has activated this LCR conforms to according to Annex A. Bitstreams conforming to this version of this specification shall not contain values of lcr_max_interop outside those specified in Annex A.

6.8.4. LCR sequence profile tier level information semantics

lcr_seq_profile_idc[ i ] specifies the value of the seq_profile_idc associated with the local LCR that is indicated in an extended layer with obu_xlayer_id equal to i. Bitstreams conforming to this version of this specification shall not contain values of lsptli_seq_profile_idc[ i ] outside those specified in Annex A.

lcr_max_level_idx[ i ] specifies the maximum level associated with the local LCR that is indicated in an extended layer with obu_xlayer_id equal to i. Bitstreams conforming to this version of this specification shall not contain values of lcr_max_level_idx[ i ] outside those specified in Annex A.

lcr_tier_flag[ i ] specifies the tier indicator associated with the local LCR that is indicated in an extended layer with obu_xlayer_id equal to i. Bitstreams conforming to this version of this specification shall not contain values of lcr_tier_flag[ i ] outside those specified in Annex A.

lcr_max_mlayer_count[ i ] specifies the maximum number of embedded layers that can be associdated with the local LCR that is indicated in an extended layer with obu_xlayer_id equal to i. Bitstreams conforming to this version of this specification shall not contain values of lcr_max_mlayer_count[ i ] outside those specified in Annex A.

6.8.5. LCR global payload semantics

lcr_xlayer_id[ i ] indicates the corresponding extended layer ID for the indicated extended layer in the global LCR with index i.

It is a requirement of bitstream conformance that the value of lcr_xlayer_id[ i ] is less than or equal to 30.

It is a requirement of bitstream conformance that there shall not be an index value j, with j not equal to i, that will result in lcr_xlayer_id[ i ] equal to lcr_xlayer_id[ j ].

lcr_num_dependent_xlayer_map[ j ], when present, indicates the extended layers on which the extended layer with ID j can depend on in terms of inter-layer prediction. An extended layer with ID j can only depend on layers with an ID smaller than j. When lcr_num_dependent_xlayer_map[ j ] is not present, its value is assumed to be equal to 0.

6.8.6. LCR xlayer info semantics

lcr_rep_info_present_flag[ i ][ j ] indicates the presence of the global, if i is equal to 1, or local, if i is equal to 0, lcr_rep_info( i, j ) syntax in the extended layer information for extended layer id j. If lcr_rep_info_present_flag[ i ][ j ] is equal to 1, the corresponding lcr_rep_info( i, j) syntax is present, otherwise, this syntax is not present.

lcr_xlayer_purpose_present_flag[ i ][ j ] indicates the presence of the lcr_xlayer_purpose_id[ i ][ j ] syntax element in the current LCR. If lcr_xlayer_purpose_present_flag[ i ][ j ] is equal to 1, then lcr_xlayer_purpose_id[ i ][ j ] is present. Otherwise, if lcr_xlayer_purpose_present_flag[ i ][ j ] is equal to 0, then lcr_xlayer_purpose_id[ i ][ j ] is not present.

lcr_xlayer_color_info_present_flag[ i ][ j ] indicates the presence of the global, if i is equal to 1, or local, if i is equal to 0, lcr_xlayer_color_info( i, j) syntax in the extended layer information for extended layer id j. If lcr_xlayer_color_info_present_flag[ i ][ j ] is equal to 1, the corresponding lcr_xlayer_color_info( i, j) syntax is present, otherwise, this syntax is not present.

lcr_embedded_layer_info_present_flag[ i ][ j ] indicates the presence of the global, if i is equal to 1, or local, if i is equal to 0, lcr_embedded_layer_info( i, j) syntax in the extended layer information for extended layer id j. If lcr_embedded_layer_info_present_flag[ i ][ j ] is equal to 1, the corresponding lcr_embedded_layer_info( i, j) syntax is present, otherwise, this syntax is not present.

lcr_xlayer_purpose_id[ i ][ j ], when present, specifies the application purpose for the extended layer with id j, in a global, if i is equal to 1, or a local, if i is equal to 0, LCR with the same semantics as for lcr_global_purpose_id. When the syntax elements lcr_xlayer_purpose_id[ i ][ j ] and lcr_global_purpose_id are not present then lcr_xlayer_purpose_id[ i ][ j ] is set to 0 (Unspecified).

lcr_xlayer_atlas_segment_id[ j ], when present, indicates the corresponding atlas segment ID that the extended layer with index j in the global LCR is associated with. If lcr_xlayer_atlas_segment_id[ j ] is not present, such association can be provided in the embedded layer information, can be specified through external means, or can be unspecified.

lcr_xlayer_priority_order[ j ], when present, indicates the priority order of an extended layer with index j when rendering it on an atlas compared to other extended layers. The lower the value of lcr_xlayer_priority_weight[ j ] the higher the priority rendering order of that layer compared to other layers with a higher value. If this information is missing or two or more layers have the same priority value, then the priority between them is determined based on the extended layer ID of the layers (the lower ID value has a higher rendering priority than a higher ID value). Layers with a higher rendering priority value are rendered first compared to layers with a lower rendering priority value when placed on an atlas.

lcr_xlayer_rendering_method[ j ], when present, indicates the rendering method applied to the extended layer j compared to previously rendered layers according to their priority order value. The interpretation of the value of lcr_xlayer_rendering_method[ j ] for rendering purposes is shown below:

lcr_xlayer_rendering_method Interpretation
0 Overwrite
1 Blend 50%
2 Multiply
3 Darken
4 Lighten
5-255 Reserved

Values corresponding to a reserved interpretation should not be encountered in bitstreams conforming to this version of this Specification and reserved for future use by AOMedia.

6.8.7. LCR rep info semantics

lcr_max_pic_width[ i ][ j ], when present, specifies the maximum picture width for the decoded pictures associated with the extended layer j in either a global, when i is equal to 1, or a local, when i is equal to 0, LCR OBU. The value of lcr_max_pic_width[ i ][ j ] in an activated LCR OBU in an extended layer with index j shall equal max_frame_width_minus_1 + 1.

lcr_max_pic_height[ i ][ j ], when present, specifies the maximum picture height for the decoded pictures associated with the extended layer j in either a global, when i is equal to 1, or a local, when i is equal to 0, LCR OBU. The value of lcr_max_pic_height[ i ][ j ] in an activated LCR OBU in an extended layer with index j shall equal max_frame_height_minus_1 + 1.

lcr_format_info_present_flag[ i ][ j ], when present, specifies the presence of the lcr_bit_depth_idc[ i ][ j] and lcr_chroma_format_idc[ i ][ j ] syntax elements that indicate the bitdepth and chroma format of the decoded pictures associated with the extended layer j in either a global, when i is equal to 1, or a local, when i is equal to 0, LCR OBU. If lcr_format_info_present_flag[ i ][ j ] is 1, then the syntax elements lcr_bit_depth_idc[ i ][ j ] and lcr_chroma_format_idc[ i ][ j ] are present in the LCR OBU. If lcr_format_info_present_flag[ i ][ j ] is 0, then the syntax elements lcr_bit_depth_idc[ i ][ j ] and lcr_chroma_format_idc[ i ][ j ] are not present in the LCR OBU.

lcr_cropping_window_present_flag[ i ][ j ], when present, specifies the presence of a cropping window that should be applied to the decoded pictures associated with the extended layer j in either a global, when i is equal to 1, or a 12 local, when i is equal to 0, LCR OBU, after upscaling such pictures to a width of lcr_max_pic_width[ i ][ j ] and to a height of lcr_max_pic_height[ i ][ j ]. The value of lcr_cropping_window_present_flag[ i ][ j ], when present in an activated LCR OBU in an extended layer with index j shall equal seq_cropping_window_present_flag.

lcr_bit_depth_idc[ i ][ j ], when present, specifies the bit_depth for the decoded pictures associated with the extended layer j in either a global, when i is equal to 1, or a local, when i is equal to 0, LCR OBU. The value of lcr_bit_depth_idc[ i ][ j ] in an activated LCR OBU in an extended layer with index j shall equal bit_depth_idc.

lcr_chroma_format_idc[ i ][ j ], when present, specifies the chroma format idc for the decoded pictures associated with the extended layer j in either a global, when i is equal to 1, or a local, when i is equal to 0, LCR OBU. The value of lcr_chroma_format_idc[ i ][ j ] in an activated LCR OBU in an extended layer with index j shall equal chroma_format_idc.

lcr_cropping_win_left_offset[ i ][ j ], lcr_cropping_win_right_offset[ i ][ j ], lcr_cropping_win_top_offset[ i ][ j ], and lcr_cropping_win_bottom_offset[ i ][ j ], when present, specify the cropping window that should be used to generate the output of the decoding process in combination with the lcr_max_pic_width[ i][ j ] and lcr_max_pic_height[ i][ j ] syntax elements, using the decoded pictures associated with the extended layer j in either a global, when i is equal to 1, or a local, when i is equal to 0, LCR OBU. The values of lcr_cropping_win_left_offset[ i ][ j ], lcr_cropping_win_right_offset[ i ][ j ], lcr_cropping_win_top_offset[ i ][ j ], and lcr_cropping_win_bottom_offset[ i ][ j ] in an activated LCR OBU in an extended layer with index j shall match the values of seq_cropping_win_left_offset, seq_cropping_win_right_offset, seq_cropping_win_top_offset, and seq_cropping_win_bottom_offset.

6.8.8. LCR embedded layer info semantics

lcr_mlayer_map[ isGlobal ][ xId ] specifies a map that indicates which embedded layers are present in the extended layer with ID equal to xId.

lcr_tlayer_map[ isGlobal ][ xId ][ j ] specifies a map that indicates which temporal layers are present in the extended layer with ID equal to xId for the current embedded layer with ID equal to j.

lcr_layer_atlas_segment_id[ isGlobal ][ xId ][ j ] specifies the atlas segment ID with which the current embedded layer with obu_mlayer_id equal to j in the extended layer with obu_xlayer_id equal to xId is associated with.

lcr_priority_order[ isGlobal ][ xId ][ j ], when present, indicates the priority order of an embedded layer with ID j in an extended layer with ID xId when rendering it on an atlas compared to other embedded layers. The lower the value of lcr_priority_order[ isGlobal ][ xId ][ j ] the higher the priority rendering order of that layer compared to other layers with a higher value. If this information is missing or two or more layers have the same priority value, then the priority between them is determined based on the embedded layer ID followed by the extended layer ID of the layers (the lower ID value has a higher rendering priority than a higher ID value). Layers with a higher rendering priority value are rendered first compared to layers with a lower rendering priority value when placed on an atlas.

lcr_rendering_method[ isGlobal ][ xId ][ j ], when present, indicates the rendering method applied to the embedded layer with ID j in the extended layer with ID xId compared to previously rendered layers according to their priority order value. The interpretation of the value of lcr_rendering_method is the same as for lcr_xlayer_rendering_method.

lcr_layer_type[ isGlobal ][ xId ][ j ] indicates the type of the embedded layer with ID j in the extended layer with ID xId as follows:

lcr_layer_type Label Interpretation
0 TEXTURE_LAYER Texture
1 AUX_LAYER Auxiliary
2-255 - Reserved

Reserved values of lcr_layer_type[ isGlobal ][ xId ][ j ] should not be present in bitstreams conforming to this version of this Specification. Such values are reserved for future use by AOMedia.

lcr_auxiliary_type[ isGlobal ][ xId ][ j ] indicates the auxiliary type of the embedded layer with ID j in the extended layer with ID xId as follows:

lcr_auxiliary_type Label Interpretation
0 ALPHA_AUX Alpha auxiliary image
1 DEPTH_AUX Depth auxiliary image
2 SEGMENTATION_AUX Segmentation auxiliary image
3 GAIN_MAP_AUX Gain map auxiliary image
4-255 - Reserved

Reserved values of lcr_auxiliary_type[ isGlobal ][ xId ][ j ] should not be present in bitstreams conforming to this version of this Specification. Such values are reserved for future use by AOMedia.

lcr_view_type[ isGlobal ][ xId ][ j ] indicates the view type of the embedded layer with ID j in the extended layer with ID xId as follows:

lcr_view_type Label Interpretation
0 VIEW_UNSPECIFIED The view type is undefined or not specified
1 VIEW_CENTER Central perspective view
2 VIEW_LEFT View from the left perspective
3 VIEW_RIGHT View from the right perspective
4 VIEW_EXPLICIT Explicit view ID indication
5-255 - Reserved

Reserved values of lcr_view_type[ isGlobal ][ xId ][ j ] should not be present in bitstreams conforming to this version of this Specification. Such values are reserved for future use by AOMedia.

lcr_view_id[ isGlobal ][ xId ][ j ], when present, indicates the view id associated with the embedded layer with ID j in the extended layer with ID xId.

lcr_dependent_layer_map[ isGlobal ][ xId ][ j ], when present, indicates with which embedded layers the current embedded layer with layer ID equal to j, in the extended layer xId, depends from in terms of inter prediction. If lcr_dependent_layer_map[ isGlobal ][ xId ][ j ] is equal to 0, then the current embedded layer can be independently decoded from other embedded layers.

lcr_crop_info_in_scr_flag[ isGlobal ][ xId ][ j ] indicates whether cropping window information is present for the embedded layer with layer Id equal to j, in the extended layer with layer ID equal to xId.

lcr_crop_max_width[ isGlobal ][ xId ][ j ] indicates the width to which the video should be scaled to if the embedded layer with ID equal to j in the extended layer with ID equal to xId is the lowest available layer to be decoded in a selected decoding operating point.

lcr_crop_max_height[ isGlobal ][ xId ][ j ] indicates the height to which the video should be scaled to if the embedded layer with ID equal to j in the extended layer with ID equal to xId is the lowest available layer to be decoded in a selected decoding operating point.

6.8.9. LCR xlayer color info semantics

layer_color_description_idc, layer_color_primaries, layer_matrix_coefficients, layer_transfer_characteristics, layer_full_range_flag specify the color information for this layer with the same interpretation as ops_color_description_idc, ops_color_primaries, ops_matrix_coefficients, ops_transfer_characteristics and ops_full_range_flag.

6.9. Atlas segment info OBU semantics

atlas_segment_id indicated the atlas segment id associated with the current atlas segment information OBU, which can be referred by other syntax structures in this Specification.

ats_atlas_segment_mode_idc specifies the representation description and coding of the atlas segments as follows:

ats_atlas_segment_mode_idc Label Description
0 ENHANCED_ATLAS Enhanced Atlas description
1 BASIC_ATLAS Basic Atlas description
2 SINGLE_ATLAS Single Atlas description
3 MULTISTREAM_ATLAS Multistream Atlas description
4 MULTISTREAM_ALPHA_ATLAS Multistream Alpha Atlas description

It is a requirement of bitstream conformance that ats_atlas_segment_mode_idc is less than or equal to 4.

ats_nominal_width_minus1 plus 1 specifies the nominal width of the atlas.

ats_nominal_height_minus1 plus 1 specifies the nominal height of the atlas.

6.9.1. Atlas label segment info semantics

ats_signaled_atlas_segment_ids_flag indicates whether the atlas segments are assigned explicit IDs or these are set equal to their index. When ats_signaled_atlas_segment_ids_flag is equal to 1, then explicit IDs are assigned to each atlas segment. If ats_signaled_atlas_segment_ids_flag is equal to 0, then the ID of each atlas segment is equal to its index.

ats_atlas_segment_id[ xlayerId ][ xAId ][ i ] indicates the ID associated with the atlas segment with index i.

6.9.2. Atlas region info semantics

ats_num_region_columns_minus1[ xlayerId ][ xAId ] plus 1 specifies the number of column regions to which an atlas with ID equal to xAId needs to be segmented.

It is a requirement of bitstream conformance that ats_num_region_columns_minus1 is less than MAX_ATLAS_COLS.

ats_num_region_rows_minus1[ xlayerId ][ xAId ] plus 1 specifies the number of row regions to which an atlas with ID equal to xAId needs to be segmented.

It is a requirement of bitstream conformance that ats_num_region_rows_minus1 is less than MAX_ATLAS_ROWS.

ats_uniform_spacing_flag[ xlayerId ][ xAId ] specifies whether the regions to which an atlas is segmented are uniformly spaced or not. When ats_uniform_spacing_flag[ xlayerId ][ xAId ] is equal to 0, the atlas regions are not uniformly spaced. If ats_uniform_spacing_flag[ xlayerId ][ xAId ] is equal to 1, the atlas regions are uniformly spaced.

ats_column_width_minus_1[ xlayerId ][ xAId ][ i ] plus 1, when present, indicates the width of the regions in column i in the atlas with ID xAId.

ats_row_height_minus_1[ xlayerId ][ xAId ][ i ] plus 1, when present, indicates the height of the regions in row i in the atlas with ID xAId.

ats_region_width_minus_1[ xlayerId ][ xAId ] plus 1, when present, indicates the width of all regions in the atlas with ID xAId.

ats_region_height_minus_1[ xlayerId ][ xAId ] plus 1, when present, indicates the height of all regions in the atlas with ID xAId.

6.9.3. Atlas region to segment mapping semantics

ats_single_region_per_atlas_segment_flag[ xLayerId ][ xAId ] indicates whether there is one to one mapping of atlas regions with atlas segments.

If ats_single_region_per_atlas_segment_flag[ xLayerId ][ xAId ] is equal to 0, then the mapping of atlas regions with atlas segments is not one to one.

If ats_single_region_per_atlas_segment_flag[ xLayerId ][ xAId ] is equal to 1, then the mapping of atlas regions with atlas segments is one to one.

If ats_single_region_per_atlas_segment_flag[ xLayerId ][ xAId ] is equal to 1, it is a requirement of bitstream conformance that NumRegionsInAtlas[ xLayerId ][ xAId ] is less than or equal to MAX_NUM_ATLAS_SEGMENTS.

ats_num_atlas_segments_minus1[ xLayerId ][ xAId ] plus one, when present, indicates the number of atlas segments.

It is a requirement of bitstream conformance that ats_num_atlas_segments_minus1 is less than MAX_NUM_ATLAS_SEGMENTS.

ats_top_left_region_column[ xLayerId ][ xAId ][ i ] indicates the column of the first region associated with the segment with index i.

ats_top_left_region_row[ xLayerId ][ xAId ][ i ] indicates the row of the first region associated with the segment with index i.

ats_bottom_right_region_column_off[ xLayerId ][ xAId ][ i ] indicates the offset for the column of the last region associated with the segment with index i. The column of the last region is derived as ats_top_left_region_column[ xLayerId ][ xAId ][ i ] + ats_bottom_right_region_column_off[ xLayerId ][ xAId ][ i ].

ats_bottom_right_region_row_off[ xLayerId ][ xAId ][ i ] indicates the offset for the row of the last region associated with the segment with index i. The row of the last region is derived as ats_top_left_region_row[ xLayerId ][ xAId ][ i ] + ats_bottom_right_region_row_off[ xLayerId ][ xAId ][ i ].

6.9.4. Atlas multistream atlas info semantics

ats_input_stream_id, ats_atlas_width, ats_atlas_height, ats_num_atlas_segments_minus1, ats_segment_top_left_pos_x, ats_segment_top_left_pos_y, ats_segment_width, and ats_segment_height have the same semantics as in the Atlas basic atlas info semantics § 6.9.5 Atlas basic atlas info semantics.

ats_alpha_segments_present_flag equal to 1 specifies that the syntax element ats_alpha_segment_flag is present in the bit-stream. ats_alpha_segments_present_flag equal to 0 specifies that the syntax element is not present.

ats_alpha_segment_flag[ xlayerId ][ xAId ][ i ] specifies that the atlas segment with index i is an alpha frame. When not present, ats_alpha_segment_flag[ xAId ][ i ] shall be inferred to be equal to 0.

ats_background_info_present_flag equal to 1 specifies that the syntax elements ats_background_red_value, ats_background_green_value, and ats_background_blue_value are present. ats_background_info_present_flag equal to 0 specifies the syntax elements are not present.

ats_background_red_value specifies the red component of the background color as the 8-bit quantized value (D’R) in Recommendation ITU-R BT.709. When ats_background_red_value is not present, it is inferred to be equal to 16.

ats_background_green_value specifies the green component of the background color as the 8-bit quantized value (D’G) in Recommendation ITU-R BT.709. When ats_background_green_value is not present, it is inferred to be equal to 16.

ats_background_blue_value specifies the blue component of the background color as the 8-bit quantized value (D’B) in Recommendation ITU-R BT.709. When ats_background_blue_value is not present, it is inferred to be equal to 16.

6.9.5. Atlas basic atlas info semantics

ats_stream_id_present[ xlayerId ][ xAId ], when present, indicates ats_input_stream_id is signaled.

ats_atlas_width[ xlayerId ][ xAId ], when present, indicates the width of the atlas with ID xAId.

ats_atlas_height[ xlayerId ][ xAId ], when present, indicates the height of the atlas with ID xAId.

ats_num_atlas_segments_minus1[ xLayerId ][ xAId ] plus one, when present, indicates the number of atlas segments of the atlas with ID xAId.

It is a requirement of bitstream conformance that ats_num_atlas_segments_minus1 is less than MAX_NUM_ATLAS_SEGMENTS.

ats_input_stream_id[ xLayerId ][ xAId ][ i ] specifies the obu_xlayer_id value of the stream corresponding to the i-th composed region.

All values in ats_input_stream_id[ xLayerId ][ xAId ][] shall be unique.

ats_segment_top_left_pos_x[ xLayerId ][ xAId ][ i ], when present, indicates the horizontal coordinate of the top left position of the atlas segment with index i.

ats_segment_top_left_pos_y[ xLayerId ][ xAId ][ i ], when present, indicates the vertical coordinate of the top left position of the atlas segment with index i.

ats_segment_width[ xLayerId ][ xAId ][ i ], when present, indicates the width of the atlas segment with index i.

ats_segment_height[ xLayerId ][ xAId ][ i ], when present, indicates the height of the atlas segment with index i.

6.10. Operating point set OBU semantics

ops_reset_flag[ obu_xlayer_id ] equal to 1 specifies that operating_point_set_obsp( ) of the obu_xlayer_id is reset. ops_reset_flag equal to 0 specifies that operating_point_set_obsp( ) of the obu_xlayer_id is not reset.

ops_id[ obu_xlayer_id ] specifies the OPS id at the obu_xlayer_id.

ops_cnt[ obu_xlayer_id ][ opsID ] specifies the OPS count of the opsID within the obu_xlayer_id.

ops_priority[ obu_xlayer_id ][ opsID ] specifies the priority of the OPS at the opsID within the obu_xlayer_id.

When ops_priority[ obu_xlayer_id ][ opsID ] is not present, ops_priority [ obu_xlayer_id ][ opsID ] shall be inferred to be equal to 0.

ops_intent[ obu_xlayer_id ][ opsID ] specifies the intent of the OPS at the opsID within the obu_xlayer_id as follows:

ops_intent Label
0 OPSI_UNSPECIFIED
1 OPSI_SCALABILITY
2 OPSI_STEREO
3 OPSI_TEXTURE_ALPHA
4 OPSI_TEXTURE_DEPTH
5 OPSI_GAIN_MAP
6 OPSI_MULTIVIEW
7-15 RESERVED

When ops_intent[ obu_xlayer_id ][ opsID ] is not present, ops_intent[ obu_xlayer_id ][ opsID ] shall be inferred to be equal to 0.

ops_intent_present_flag[ obu_xlayer_id ][ opsID ] equal to 1 specifies that ops_op_intent is present in the current OPS. ops_intent_present_flag[ obu_xlayer_id ][ ops_id ] equal to 0 specifies ops_op_intent is not present in the current OPS.

ops_operational_ptl_present_flag[ obu_xlayer_id ][ opsID ] equal to 1 specifies that ops_operational_profile_id, ops_operational_level_id, and ops_operational_tier_id are present for all the operating points within an operating point id specified by opsID. ops_operational_ptl_present_flag[ obu_xlayer_id ][ opsID ] equal to 0 specifies the that ops_operational_profile_id, ops_operational_level_id, and ops_operational_tier_id are not present for all the operating points within an operating point id specified by opsID.

ops_color_info_present_flag[ obu_xlayer_id ][ opsID ] equal to 1 specifies that the ops_color_info( obu_xlayer_id, opsID, i ) syntax is present in the current OPS. ops_color_info_present_flag equal to 0 specifies that the ops_color_info( obu_xlayer_id, opsID, i ) syntax is not present in the current OPS.

ops_decoder_model_info_present_flag equal to 1 specifies that the ops_decoder_model_info syntax is present in the current OPS. ops_decoder_model_info_present_flag equal to 0 specifies that ops_decoder_model_info syntax is not present in the current OPS.

ops_mlayer_info_idc equal to 0 specifies that ops_mlayer_info syntax structure is not present in the current OPS. ops_mlayer_info_idc equal to 1 specifies that the ops_mlayer_info syntax is present in the current OPS for an implicit operating point. ops_mlayer_info_idc equal to 2 specifies that the ops_mlayer_info syntax is present in the current OPS for an explicit operation point.

It is a requirement of bitstream conformance that ops_mlayer_info_idc is not equal to 3.

ops_reserved_2bits must be set to 0. The value is ignored by a decoder.

ops_reserved_3bits must be set to 0. The value is ignored by a decoder.

ops_data_size[ obu_xlayer_id ][ opsID ][ i ] specifies the size of the ops data.

ops_op_intent[ obu_xlayer_id ][ opsID ][ i ] specifies the intent of the i-th operating point with the same semantics as ops_intent.

ops_operational_profile_id[ obu_xlayer_id ][ opsID ][ i ] specifies the profile of the i-th operating point.

ops_operational_level_id[ obu_xlayer_id ][ opsID ][ i ] specifies the level of the i-th operating point.

ops_operational_tier_id[ obu_xlayer_id ][ opsID ][ i ] specifies the tier of the i-th operating point.

It is a requirement of bitstream conformance that the bitstream corresponding to the i-th operating point associated with obu_xlayer_id and opsID shall satisfy all bitstream constraints specified in § 10.4 Levels, by setting seq_profile_idc, seq_tier, and seq_level_idx to ops_operational_profile_id[obu_xlayer_id][opsID][i], ops_operational_tier_id[obu_xlayer_id][opsID][i], and ops_operational_level_id[obu_xlayer_id][opsID][i], respectively.

ops_initial_display_delay_present_flag specifies whether the ops_initial_display_delay_minus_1 syntax element is present.

ops_initial_display_delay_minus_1 plus 1 specifies the number of decoded frames that should be present in the buffer pool before the first presentable frame is displayed. This will ensure that all presentable frames in the sequence can be decoded at or before the time that they are scheduled for display. If not signaled then ops_initial_display_delay_minus_1 is inferred equal to BUFFER_POOL_MAX_SIZE - 1.

ops_xlayer_map[ obu_xlayer_id ][ opsID ][ i ] specifies a bit mask for the i-th operating point.

ops_embedded_ops_id and ops_embedded_op_index provide explicit values for the operating set id and operating point index for use in the ops_mlayer_info syntax.

It is a requirement of bitstream conformance that ops_embedded_op_index is less than 7.

opsBytes is a variable that contains the number of bytes read for the operating point.

It is a requirement of bitstream conformance that the computed value of opsBytes is equal to ops_data_size[ obu_xlayer_id ][ opsID ][ i ].

6.10.1. Operating point set aggregate profile tier level information semantics

ops_config_idc[ opsID ][ i ] indicates a profile identifier at the i-th operating point.

ops_aggregate_level_idx[ opsID ][ i ] specifies an aggregate level indicator at the i-th operating point.

ops_max_tier_flag[ opsID ][ i ] specifies the maximum tier indicator at the i-th operating point.

ops_max_interop[ opsID ][ i ] indicates the maximum interoperability point at the i-th operating point.

6.10.2. Operating point set sequence profile tier level information semantics

ops_seq_profile_idc[ xId ][ opsID ][ i ][ j ] specifies the profile indicator of the i-th operating point at the j-th extended layer id.

ops_level_idx[ xId ][ opsID ][ i ][ j ] specifies the level indicator of the i-th operating point at the j-th extended layer id.

ops_tier_flag[ xId ][ opsID ][ i ][ j ] specifies the tier indicator of the i-th operating point at the j-th extended layer id.

ops_mlayer_count[ xId ][ opsID ][ i ][ j ] specifies the embedded layer count of the i-th operating point at the j-th extended layer id.

ops_reserved_2bits must be set to 0. The value is ignored by a decoder.

6.10.3. Operating point set decoder model info semantics

ops_decoder_buffer_delay specifies the time interval between the arrival of the first bit in the smoothing buffer and the subsequent removal of the data that belongs to the first coded frame for operating point op, measured in units of 1/90000 seconds.

ops_encoder_buffer_delay specifies, in combination with the ops_decoder_buffer_delay syntax element, the first bit arrival time of frames to be decoded to the smoothing buffer. ops_encoder_buffer_delay is measured in units of 1/90000 seconds.

For a video sequence that includes one or more random access points the sum of ops_decoder_buffer_delay and ops_encoder_buffer_delay shall be kept constant.

ops_low_delay_mode_flag equal to 1 indicates that the smoothing buffer operates in low-delay mode for operating point op. In low-delay mode late decode times and buffer underflow are both permitted. ops_low_delay_mode_flag equal to 0 indicates that the smoothing buffer operates in strict mode, where buffer underflow is not allowed.

6.10.4. Operating point set color info semantics

ops_color_description_idc[ obu_xlayer_id ][ opsID ][ i ] indicates the combination of color primaries, transfer characteristics, and matrix coefficients, within the i-th operating point index with an operating point id given by opsID, at the obu_xlayer_id as follows:

Value Interpretation ops_color_primaries ops_transfer_characteristics ops_matrix_coefficients
0 Explicitly signaled Explicit Explicit Explicit
1 BT.709 SDR 1 1 5
2 BT.2100 PQ 9 16 9
3 BT.2100 HLG 9 14 9
4 sRGB 1 13 0
5 sYCC 1 13 5
6-15 Reserved - - -

The value of ops_color_description_idc[ obu_xlayer_id ][ opsID ][ i ] shall be in the range of 0 to 15, inclusive. Values larger than 5 are reserved for future use by AOMedia and should be ignored by decoders conforming to this version of this Specification.

ops_color_primaries[ obu_xlayer_id ][ opsID ][ i ] specifies the color primaries at the i-th operating point index with an operating point id given by opsID at the obu_xlayer_id is an integer that is associated with the ColourPrimaries variable specified in ISO/IEC 23091-4/ITU-T H.273.

ops_color_primaries Name of color primaries Description
1 CP_BT_709 [ITU-R-BT.709]
2 CP_UNSPECIFIED Unspecified
4 CP_BT_470_M BT.470 System M (historical)
5 CP_BT_470_B_G BT.470 System B, G (historical)
6 CP_BT_601 [ITU-R-BT.601]
7 CP_SMPTE_240 SMPTE 240
8 CP_GENERIC_FILM Generic film (color filters using illuminant C)
9 CP_BT_2020 BT.2020, BT.2100
10 CP_XYZ SMPTE 428 (CIE 1921 XYZ)
11 CP_SMPTE_431 SMPTE RP 431-2
12 CP_SMPTE_432 SMPTE EG 432-1
22 CP_EBU_3213 EBU Tech. 3213-E

ops_transfer_characteristics[ obu_xlayer_id ][ opsID ][ i ] specifies the transfer characteristics at the i-th operating point index with an operating point id given by opsID at the obu_xlayer_id is an integer that is associated with the TransferCharacteristics variable specified in ISO/IEC 23091-4/ITU-T H.273.

ops_transfer_characteristics Name of transfer characteristics Description
0 TC_RESERVED_0 For future use
1 TC_BT_709 [ITU-R-BT.709]
2 TC_UNSPECIFIED Unspecified
3 TC_RESERVED_3 For future use
4 TC_BT_470_M BT.470 System M (historical)
5 TC_BT_470_B_G BT.470 System B, G (historical)
6 TC_BT_601 [ITU-R-BT.601]
7 TC_SMPTE_240 SMPTE 240 M
8 TC_LINEAR Linear
9 TC_LOG_100 Logarithmic (100 : 1 range)
10 TC_LOG_100_SQRT10 Logarithmic (100 * Sqrt(10) : 1 range)
11 TC_IEC_61966 IEC 61966-2-4
12 TC_BT_1361 BT.1361
13 TC_SRGB sRGB or sYCC
14 TC_BT_2020_10_BIT BT.2020 10-bit systems [Rec.2020]
15 TC_BT_2020_12_BIT BT.2020 12-bit systems [Rec.2020]
16 TC_SMPTE_2084 SMPTE ST 2084, ITU BT.2100 PQ
17 TC_SMPTE_428 SMPTE ST 428
18 TC_HLG BT.2100 HLG, ARIB STD-B67

ops_matrix_coefficients[ obu_xlayer_id ][ opsID ][ i ] specifies the matrix coefficients at the i-the operating point index with an operating point id given by opsID at the obu_xlayer_id is an integer that is associated with the MatrixCoefficients variable specified in ISO/IEC 23091-4/ITU-T H.273.

ops_matrix_coefficients Name of matrix coefficients Description
0 MC_IDENTITY Identity matrix
1 MC_BT_709 [ITU-R-BT.709]
2 MC_UNSPECIFIED Unspecified
3 MC_RESERVED_3 For future use
4 MC_FCC US FCC 73.628
5 MC_BT_470_B_G BT.470 System B, G (historical)
6 MC_BT_601 [ITU-R-BT.601]
7 MC_SMPTE_240 SMPTE 240 M
8 MC_SMPTE_YCGCO YCgCo
9 MC_BT_2020_NCL BT.2020 non-constant luminance, BT.2100 YCbCr
10 MC_BT_2020_CL BT.2020 constant luminance [Rec.2020]
11 MC_SMPTE_2085 SMPTE ST 2085 YDzDx
12 MC_CHROMAT_NCL Chromaticity-derived non-constant luminance
13 MC_CHROMAT_CL Chromaticity-derived constant luminance
14 MC_ICTCP BT.2100 ICtCp
15 MC_IPT_C2 IPT-C2
16 MC_YCGCO_RE YCgCo-Re
17 MC_YCGCO_RO YCgCo-Ro

ops_full_range_flag[ obu_xlayer_id ][ opsID ][ i ] is a binary value that is associated with the VideoFullRangeFlag variable specified in ISO/IEC 23091-4/ITU-T H.273. ops_full_range_flag specifies the value of the full range flag at the i-th operating point index with an operating point id given by opsID at the obu_xlayer_id. ops_full_color_range_flag equal to 0 shall be referred to as the studio swing representation and ops_full_color_range_flag equal to 1 shall be referred to as the full swing representation for all intents relating to this Specification.

6.10.5. Operating point set mlayer info semantics

ops_mlayer_map[ obuXLId ][ opsID ][ opIndex ][ xLId ] specifies the spatial layer map of the xLId extended layer, within an operating point index specified by opIndex, in an operating point opsID, at the obuXLId.

ops_tlayer_map[ obuXLId ][ opsID ][ opIndex ][ xLId ][ j ] specifies the temporal layer map of the xLId extended layer, within an operating point index specified by opIndex, in an operating point opsID, at the obuXLId.

6.11. Buffer removal timing OBU semantics

br_ops_id specifies the operating point set id.

It is a requirement of bitstream conformance that br_ops_id is equal to ops_id[ obu_xlayer_id ].

br_ops_cnt specifies the operating point count.

It is a requirement of bitstream conformance that br_ops_cnt is equal to ops_cnt[ obu_xlayer_id ][ br_ops_id ].

br_decoder_model_present_op_flag specifies if br_buffer_removal_time is present.

br_buffer_removal_time[ i ] specifies the frame removal time in units of DecCT clock ticks counted from the removal time of the last random access point for operating point i when the current frame is not associated with a random access point and from the previous random access point when the current frame is associated with a random access point.

6.12. Quantizer Matrix OBU semantics

qm_bit_map is a bitmask that specifies which quantizer matrices are present in the OBU.

It is a requirement of bitstream conformance that qm_bit_map is not equal to 0.

When there are multiple quantizer matrices OBUs between coded frames, it is a requirement of bitstream conformance that the same level of quantizer matrix is not specified twice in those OBUs.

qm_chroma_info_present_flag specifies whether the chroma quantizer matrices are present.

qm_is_default_flag specifies that the default quantizer matrix should be used for the current quantizer level.

6.13. Film grain OBU semantics

fgm_bit_map specifies a bitmap of which film grain models are present in the OBU. If bit i of fgm_bit_map is equal to 1 (i.e. if fgm_bit_map & (1 << i) is non-zero), then a film grain model is present for slot i.

When there are multiple film grain OBUs between coded frames, it is a requirement of bitstream conformance that the same slot is not reused in those OBUs.

Note: The film grain slots can be reused, but only after a coded frame has been received.

It is a requirement of bitstream conformance that fgm_bit_map is not equal to 0.

fgm_chroma_idc is used to derive the subsampling format used by the film grain.

It is a requirement of bitstream conformance that fgm_chroma_idc is less than or equal to 3.

save_grain_model(i) is a function call that indicates that all the syntax elements read in film_grain_model should be saved into an area of memory indexed by i.

FilmGrainPresent is an array that records which film grain OBUs have been received. Initialize every entry of FilmGrainPresent to zero at the start of a bitstream.

Note: FilmGrainPresent is only used to specify a conformance constraint and does not affect the decoding process.

6.14. Content interpretation OBU semantics

A content interpetation OBU can be present in any embedded layer. However, when present, all instances of a content interpretation OBU in that embedded layer shall contain the same information. No such constraint exists for content interpetation OBUs in different embedded layers.

scan_type_idc indicates how to interpret the pictures within a CVS in terms of progressive or interlace samples, as follows:

scan_type_idc Interpretation of seq_scan_type_idc
0 Unspecified
1 Progressive frame picture samples
2 Interlace field picture samples
3 Interlace complementary field-pair picture samples

color_description_present_flag specifies if the syntax element color_description_idc and associated syntax is present.

chroma_sample_position_present_flag specifies if syntax elements describing the chroma sample positions are present.

aspect_ratio_info_present_flag specifies if the aspect ratio syntax elements are present.

timing_info_present_flag specifies if timing information is present.

reserved_2bit must be set to 0. The value is ignored by a decoder.

color_description_idc, color_primaries, matrix_coefficients, transfer_characteristics, full_range_flag specify the color information for this layer with the same interpretation as ops_color_description_idc, ops_color_primaries, ops_matrix_coefficients, ops_transfer_characteristics and ops_full_range_flag.

chroma_sample_position_top indicates the chroma sampling grid alignment for top video field or for a frame using the 4:2:0 (in which the two chroma arrays have half the width and half the height of the associated luma array) or 4:2:2 (in which the two chroma arrays have half the width of the associated luma array) color formats. For 4:2:0 formats, these interpretations match those of the Chroma420SampleLocType variable specified in ISO/IEC 23091-4/ITU-T H.273.

The chroma sample positions allowed are:

chroma_sample_position_(top/bottom) Name of chroma sample position Meaning for 4:2:2 (offsets from (0,0) luma sample) Meaning for 4:2:0 (offsets from (0,0) luma sample)
0 CSP_LEFT Horizontal offset 0 Horizontal offset 0, vertical offset 0.5
1 CSP_CENTER Horizontal offset 0.5 Horizontal offset 0.5, vertical offset 0.5
2 CSP_TOPLEFT N/A Horizontal offset 0, vertical offset 0
3 CSP_TOP N/A Horizontal offset 0.5, vertical offset 0
4 CSP_BOTTOMLEFT N/A Horizontal offset 0, vertical offset 1
5 CSP_BOTTOM N/A Horizontal offset 0.5, vertical offset 1
6 CSP_UNSPECIFIED Unknown or determined by the application Unknown or determined by the application

If chroma_sample_position_top is present in the bitstream, it is a requirement of bitstream conformance that the value is less than or equal to 5.

chroma_sample_position_bottom indicates the chroma sampling grid alignment for bottom video field using the 4:2:0 (in which the two chroma arrays have half the width and half the height of the associated luma array) or 4:2:2 (in which the two chroma arrays have half the width of the associated luma array) color formats. For 4:2:0 formats, these interpretations match those of the Chroma420SampleLocType variable specified in ISO/IEC 23091-4/ITU-T H.273.

If chroma_sample_position_bottom is present in the bitstream, it is a requirement of bitstream conformance that the value is less than or equal to 5.

aspect_ratio_idc indicates the value of the sample aspect ratio of the coded luma samples. The sample aspect ratio is a quantity that describes how the width of a sample compares to its height.

When aspect_ratio_idc is equal to 255, then the sample aspect ratio is explicitly indicated using the syntax elements sar_width and sar_height.

If aspect_ratio_idc is not equal to 255, it is a requirement of bitstream conformance that aspect_ratio_idc is less than or equal to 16.

sar_width and sar_height indicate the horizontal and vertical size of the sample aspect ratio (in the same arbitrary units).

When sar_width is equal to 0 or sar_height is equal to 0, the sample aspect ratio is unspecified in this Specification but may be provided through external means.

6.15. Padding OBU semantics

Multiple padding units can be present, each padding with an arbitrary number of bytes.

obu_padding_byte is a padding byte. Padding bytes may have arbitrary values and have no effect on the decoding process.

6.16. Metadata OBU semantics

6.16.1. Metadata unit semantics

Metadata units can be contained in either a metadata OBU or a metadata group OBU.

6.16.2. Metadata short OBU semantics

metadata_is_suffix has the same semantics as in metadata group OBU semantics § 6.16.3 Metadata group OBU semantics.

metadata_necessity_idc has the same semantics as in metadata group OBU semantics § 6.16.3 Metadata group OBU semantics.

metadata_application_id has the same semantics as in metadata group OBU semantics § 6.16.3 Metadata group OBU semantics.

muh_layer_idc has the same semantics as in metadata group OBU semantics § 6.16.3 Metadata group OBU semantics.

It is a requirement of bitstream conformance that muh_layer_idc is less than 3.

muh_cancel_flag has the same semantics as in metadata group OBU semantics § 6.16.3 Metadata group OBU semantics.

muh_persistence_idc has the same semantics as in metadata group OBU semantics § 6.16.3 Metadata group OBU semantics.

metadata_type has the same semantics as in metadata group OBU semantics § 6.16.3 Metadata group OBU semantics.

Note: muh_priority is not specified when this short form is used.

6.16.3. Metadata group OBU semantics

metadata_is_suffix, when equal to 0 (prefix), indicates that the metadata applies to coding units that follow the metadata OBU in decoding order. This is suitable for signaling information that is known prior to encoding or is required before rendering. Otherwise, metadata_is_suffix equal to 1 (suffix) indicates that the metadata applies to coding units associated with a frame or frames (as indicative by its persistence) later in display order than the frame to which the metadata OBU belongs to.

metadata_necessity_idc indicates the essentiality of the metadata OBU and the contained metadata units as follows:

metadata_necessity_idc Name Description
0 UNDEFINED The necessity of the current metadata OBU is undefined.
1 NECESSARY All metadata units within the metadata OBU are considered necessary for the receiving system.
2 ADVISORY All metadata units within the metadata OBU are advisory for the receiving system.
3 MIXED At least one metadata unit is considered necessary, and others may be advisory. The determination is made based on the semantics of each metadata type.

metadata_application_id indicates the application id associated with the current metadata OBU as follows:

metadata_application_id Name Description
0 UNSPECIFIED Application is undetermined.
1 MOBILE_OR_TV Metadata is intended for a mobile device (e.g. smartphone) or a TV.
2 MOBILE Metadata is intended for a mobile device (e.g. smartphone)
3 TV Metadata is intended for a TV.
4 HMD Metadata is intended for a Head Mounted Display.
5 WEARABLE Metadata is intended for a wearable device (e.g. watch).
6-15 Reserved for AOMedia use Reserved for AOMedia use.
16-31 Externally defined Application can be determined through external signaling (e.g. within an mp4 file).

metadata_unit_cnt_minus1 plus 1, specifies the total number of metadata units present in the current metadata_group_obu(). It is a requirement of bitstream conformance that the value of metadata_unit_cnt_minus1 is less than 16383.

metadata_type indicates the type of metadata:

metadata_type Name of metadata_type Layer-specific
0 Reserved for AOMedia use -
1 METADATA_TYPE_HDR_CLL N
2 METADATA_TYPE_HDR_MDCV N
3 METADATA_TYPE_ITUT_T35 payload-specific
4 METADATA_TYPE_TIMECODE N
5 Reserved for AOMedia use N
6 METADATA_TYPE_BANDING_HINTS N
7 METADATA_TYPE_ICC_PROFILE N
8 METADATA_TYPE_SCAN_TYPE N
9 METADATA_TYPE_TEMPORAL_POINT_INFO Y
10 and greater Reserved for AOMedia use -

The semantics of the column “Layer-specific” and its values are defined in § 6.2.2 OBU header semantics.

muh_header_size specifies the number of bytes in the metadata unit header.

Note: muh_header_size includes muh_header_extension_byte syntax elements but excludes muh_cancel_flag.

muh_cancel_flag when set to 1, indicates that any previously signaled metadata information for a metadata with type equal to muh_metadata_type is cancelled for either the current extended layer if obu_xlayer_id is less than 31, or for a set of extended layers if obu_xlayer_id is equal to 31.

muh_layer_idc is used to signal a mode that specifies the layers to which the signaled metadata applies. This value can represent different modes, such as applying the metadata to all layers, applying the metadata to a continuous range of layer values, or applying the metadata to a set of specific layer values. The specific values for the layer_idc are defined as follows:

muh_layer_idc Name Description
0 LAYER_UNSPECIFIED The current signaling does not specify to what layers the metadata applies to. This information can potentially be indicated or determined through external means.
1 LAYER_GLOBAL The metadata applies to all layers if obu_xlayer_id is equal to 31. If obu_xlayer_id is less than 31, layers with matching obu_xlayer_id only.
2 LAYER_CURRENT The metadata applies to the current layer only as indicated by the specific values for obu_xlayer_id and obu_mlayer_id in OBU header.
3 LAYER_VALUES The metadata applies to a set of specific layer values, which are explicitly signaled.
4-7 Reserved Reserved for AOMedia use.

muh_payload_size signals the size of the metadata payload in bytes.

Note: This includes the byte alignment bits if those are needed.

muh_persistence_idc is used to signal the mode in which the signaled metadata persists over time. This value can represent different modes, such as global persistence for the entire video sequence, persistence for a group of frames of a certain duration, or persistence for a single frame only.

The specific values for the muh_persistence_idc are defined as follows:

muh_persistence_idc Name Description
0 GLOBAL_PERSISTENCE Global persistence for the entire video sequence. When this mode is signaled previously signaled global metadata of this type are overwritten. The cancel flag (muh_cancel_flag) does not do anything to it.
1 BASIC_PERSISTENCE Persistence until a new metadata unit of the same type is encountered that applies to the layer or the cancel flag (muh_cancel_flag) is encountered.
2 NO_PERSISTENCE Used only for the current frame.
3 ENHANCED_PERSISTENCE This one is similar to basic but can allow updates of metadata without full replacement.
4-7 Reserved Reserved for AOMedia use.

muh_priority is used to indicate the relative importance or urgency of a particular type of metadata. A lower value indicates a higher priority, while a higher value indicates a lower priority.

Note: This information can be used by decoders to prioritize the processing of different types of metadata, ensuring that critical or time-sensitive metadata is handled before less important metadata. Furthermore, it can also be beneficial on a system level. For example, in lossy channels, more important information can be protected or re-transmitted more frequently, ensuring that critical or time-sensitive metadata is less likely to be lost or corrupted during transmission.

muh_reserved_zero_2bits must be set to zero and be ignored by decoders.

muh_xlayer_map contains a bitmask. The metadata unit is intended for an extended layer x if bit x of muh_xlayer_map is equal to 1.

It is a requirement of bitstream conformance that bit 31 of muh_xlayer_map is equal to 0.

muh_mlayer_map contains a bitmask. The metadata unit is intended for an embedded layer m if bit m of muh_mlayer_map is equal to 1.

It is a requirement of bitstream conformance that bit m of muh_xlayer_map is equal to 0 for m less than obu_mlayer_id.

Note: It is possible that the layers indicated may have been removed because of a selection of an operating point. A decoder will only apply the metadata to the remaining layers according to the selected operating point.

muh_header_extension_byte, if present, contains additional bytes. Decoders conforming to this version of this Specification should ignore the contents.

6.16.4. Metadata ITUT T35 semantics

itu_t_t35_country_code shall be a byte having a value specified as a country code by Annex A of Recommendation ITU-T T.35.

itu_t_t35_country_code_extension_byte shall be a byte having a value specified as a country code by Annex B of Recommendation ITU-T T.35.

itu_t_t35_payload_bytes shall be bytes containing data registered as specified in Recommendation ITU-T T.35.

The ITU-T T.35 terminal provider code and terminal provider oriented code shall be contained in the first one or more bytes of the itu_t_t35_payload_bytes, in the format specified by the Administration that issued the terminal provider code. Any remaining bytes in itu_t_t35_payload_bytes data shall be data having syntax and semantics as specified by the entity identified by the ITU-T T.35 country code and terminal provider code.

6.16.5. Metadata high dynamic range content light level semantics

max_cll specifies the maximum content light level as specified in CEA-861.3, Appendix A.

max_fall specifies the maximum frame-average light level as specified in CEA-861.3, Appendix A.

6.16.6. Metadata high dynamic range mastering display color volume semantics

primary_chromaticity_x[ i ] specifies a 0.16 fixed-point X chromaticity coordinate as defined by CIE 1931, where i = 0,1,2 specifies Red, Green, Blue respectively.

primary_chromaticity_y[ i ] specifies a 0.16 fixed-point Y chromaticity coordinate as defined by CIE 1931, where i = 0,1,2 specifies Red, Green, Blue respectively.

white_point_chromaticity_x specifies a 0.16 fixed-point white X chromaticity coordinate as defined by CIE 1931.

white_point_chromaticity_y specifies a 0.16 fixed-point white Y chromaticity coordinate as defined by CIE 1931.

luminance_max is a 24.8 fixed-point maximum luminance, represented in candelas per square meter.

luminance_min is a 18.14 fixed-point minimum luminance, represented in candelas per square meter.

6.16.7. Metadata timecode semantics

counting_type specifies the method of dropping values of the n_frames syntax element as specified in the table below. counting_type should be the same for all pictures in the coded video sequence.

counting_type Meaning
0 no dropping of n_frames count values and no use of time_offset_value
1 no dropping of n_frames count values
2 dropping of individual zero values of n_frames count
3 dropping of individual values of n_frames count equal to maxFps − 1
4 dropping of the two lowest (value 0 and 1) n_frames counts when seconds_value is equal to 0 and minutes_value is not an integer multiple of 10
5 dropping of unspecified individual n_frames count values
6 dropping of unspecified numbers of unspecified n_frames count values
7..31 reserved

full_timestamp_flag equal to 1 indicates that the the seconds_value, minutes_value, hours_value syntax elements will be present. full_timestamp_flag equal to 0 indicates that there are flags to control the presence of these syntax elements.

When timing_info_present_flag is equal to 1, the contents of the clock timestamp indicate a time of origin, capture, or ideal display. This indicated time is computed as follows:

if ( equal_picture_interval ) {  ticksPerPicture = num_ticks_per_picture_minus_1 + 1} else {  ticksPerPicture = 1}ss = ( ( hours_value * 60 + minutes_value) * 60 + seconds_value )clockTimestamp = ss * time_scale +                  n_frames * ticksPerPicture + time_offset_value

clockTimestamp is in units of clock ticks of a clock with clock frequency equal to time_scale Hz, relative to some unspecified point in time for which clockTimestamp would be equal to 0.

discontinuity_flag equal to 0 indicates that the difference between the current value of clockTimestamp and the value of clockTimestamp computed from the previous set of timestamp syntax elements in output order can be interpreted as the time difference between the times of origin or capture of the associated frames or fields. discontinuity_flag equal to 1 indicates that the difference between the current value of clockTimestamp and the value of clockTimestamp computed from the previous set of clock timestamp syntax elements in output order should not be interpreted as the time difference between the times of origin or capture of the associated frames or fields.

When timing_info_present_flag is equal to 1 and discontinuity_flag is equal to 0, the value of clockTimestamp shall be greater than or equal to the value of clockTimestamp for the previous set of clock timestamp syntax elements in output order.

cnt_dropped_flag specifies the skipping of one or more values of n_frames using the counting method specified by counting_type.

n_frames is used to compute clockTimestamp. When timing_info_present_flag is equal to 1, n_frames shall be less than maxFps, where maxFps is specified by maxFps = ceil( time_scale / ( 2 * num_units_in_display_tick ) ).

seconds_flag equal to 1 specifies that seconds_value and minutes_flag are present when full_timestamp_flag is equal to 0. seconds_flag equal to 0 specifies that seconds_value and minutes_flag are not present.

seconds_value is used to compute clockTimestamp and shall be in the range of 0 to 59. When seconds_value is not present, its value is inferred to be equal to the value of seconds_value for the previous set of clock timestamp syntax elements in decoding order, and it is required that such a previous seconds_value shall have been present.

minutes_flag equal to 1 specifies that minutes_value and hours_flag are present when full_timestamp_flag is equal to 0 and seconds_flag is equal to 1. minutes_flag equal to 0 specifies that minutes_value and hours_flag are not present.

minutes_value specifies the value of mm used to compute clockTimestamp and shall be in the range of 0 to 59, inclusive. When minutes_value is not present, its value is inferred to be equal to the value of minutes_value for the previous set of clock timestamp syntax elements in decoding order, and it is required that such a previous minutes_value shall have been present.

hours_flag equal to 1 specifies that hours_value is present when full_timestamp_flag is equal to 0 and seconds_flag is equal to 1 and minutes_flag is equal to 1.

hours_value is used to compute clockTimestamp and shall be in the range of 0 to 23, inclusive. When hours_value is not present, its value is inferred to be equal to the value of hours_value for the previous set of clock timestamp syntax elements in decoding order, and it is required that such a previous hours_value shall have been present.

time_offset_length greater than 0 specifies the length in bits of the time_offset_value syntax element. time_offset_length equal to 0 specifies that the time_offset_value syntax element is not present. time_offset_length should be the same for all pictures in the coded video sequence.

time_offset_value is used to compute clockTimestamp. The number of bits used to represent time_offset_value is equal to time_offset_length. When time_offset_value is not present, its value is inferred to be equal to 0.

6.16.8. Metadata banding hints semantics

When present, the banding metadata applies to a frame or multiple frames. It indicates hints about the presence of banding and its characteristics.

coding_banding_present_flag coding_banding_present_flag equal to 1 indicates banding due to compression is present in the current frame. coding_banding_present_flag equal to 0 indicates banding due to compression is not present in the current frame.

source_banding_present_flag equal to 1 indicates that source content that may be identified as banding by a debanding algorithm is present in the current frame. source_banding_present_flag equal to 0 indicates that no specific source content that may be identified as banding has been detected in the current frame.

Note: This parameter indicates that banding-like patterns are present in the source that might be detected as banding on the decoded output. The hint aims to reduce false positives and aid in better preserving source information. However, flat source_banding_present_flag equal to 0 does not guarantee the absence of content that an algorithm could mistakenly identify as banding.

banding_hints_flag equal to 1 indicates that additional information hints about the banding characteristic are present in this metadata message. banding_hints_flag equal to 0 indicates that additional information hints about the banding characteristic are not present in this metadata message.

three_color_components equal to 1 indicates that the banding related additional information is signaled for three color components. three_color_components_flag equal to 0 indicates that the banding related additional information is signaled only for the color component 0.

banding_in_component_present_flag equal to 1 indicates banding in the color component plane is present. banding_in_component_present_flag equal to 0 indicates banding in the color component plane is not present.

max_band_width_minus4 plus 4 specifies the typical maximum banding width in color component plane in the current frame in samples of component plane.

max_band_step_minus1 plus 1 specifies the typical maximum difference between two consecutive bands in color component plane in the current frame.

band_units_information_present_flag equal to 1 indicates that additional information hints per band unit are present. band_units_information_present_flag equal to 0 indicates that no additional information on banding presence for band units is present.

num_band_units_rows_minus_1 plus 1 specifies the number of band units rows.

num_band_units_cols_minus_1 plus 1 specifies the number of band units columns.

varying_size_band_units_flag equal to 1 indicates that band units of varying size are used with unit sizes specified by syntax elements vert_size_in_band_blocks_minus1[ r ] and horz_size_in_band_blocks_minus1[ c ]. varying_size_band_units_flag equal to 0 indicates that band units of uniform size are used.

band_block_in_luma_samples specifies the horizontal and vertical size of the band block in samples of component 0 as 16 << band_block_in_luma_samples.

vert_size_in_band_blocks_minus1 plus 1 specifies the size of the r-th band unit row as bandBlockInSamples * (vert_size_in_band_blocks_minus1[ r ] + 1 ) in component 0 samples when varying_size_band_units_flag is equal to 1.

horz_size_in_band_blocks_minus1 plus 1 specifies the size of the c-th band unit column as bandBlockInSamples * (horz_size_in_band_blocks_minus1[ c ] + 1 ) in component 0 samples when varying_size_band_units_flag is equal to 1.

Band units boundaries are aligned across components, taking into account possible component subsampling.

banding_in_band_unit_present_flag equal to 1 indicates banding is present in band unit in row r, column c. banding_in_band_unit_present_flag[ r ][ c ] equals to 0 indicates that banding is not present in band unit in row r, column c.

6.16.9. Metadata ICC profile semantics

icc_profile_data_payload_bytes shall be bytes containing data corresponding to a profile from the International Color Consortium.

The variable ICCmajorVer is set equal to icc_profile_data_payload_bytes[ 8 ] and the variable ICCminorVer is set equal to icc_profile_data_payload_bytes[ 9 ] >> 4.

icc_profile_data_payload_bytes contains data with syntax and semantics specified according to the interpretation of ICCmajorVer and ICCminorVer as follows:

ICCmajorVer ICCminorVer Interpretation
4 2 Major profile 4 and minor profile 2 version as specified in ISO 15076-1
4 3/td> Major profile 4 and minor profile 3 version as specified in ISO 15076-1
4 4 Major profile 4 and minor profile 4 version as specified in ISO 15076-1
5 0 Major profile 5 and minor profile 0 version as specified in ISO 20677

Values of ICCmajorVer and ICCminorVer that are not listed are unspecified or specified by other means.

6.16.10. Metadata scan type semantics

This metadata allows decoded frames to be interpreted as either progressive or interlaced content.

These values have no normative effect on the decoding process which is still frame based.

The prefix mps stands for metadata picture structure.

mps_pic_struct_type indicates whether a picture should be displayed as a frame or as one or more fields and, for the display of frames when fixed_cvs_pic_rate_flag is equal to 1, whether such frame should be repeated or not when output on certain devices.

The interpretation of mps_pic_struct_type is specified as follows:

Value Indicated picture output Elemental Units Restrictions
0 Frame 1 scan_type_idc shall be equal to 1
1 Top field 1 scan_type_idc shall be equal to 2
2 Bottom field 1 scan_type_idc shall be equal to 2
3 Top field, bottom field in that order 2 scan_type_idc shall be equal to 3
4 Bottom field, top field in that order 2 scan_type_idc shall be equal to 3
5 Top field, bottom field, top field repeated, in that order 3 scan_type_idc shall be equal to 3
6 Bottom field, top field, bottom field repeated, in that order 3 scan_type_idc shall be equal to 3
7 Frame doubling 2 scan_type_idc shall be equal to 1 and fixed_cvs_pic_rate_flag shall be equal to 1
8 Frame tripling 3 scan_type_idc shall be equal to 1 and fixed_cvs_pic_rate_flag shall be equal to 1
9 Top field paired with previous bottom field in output order 1 scan_type_idc shall be equal to 2
10 Bottom field paired with previous top field in output order 1 scan_type_idc shall be equal to 2
11 Top field paired with next bottom field in output order 1 scan_type_idc shall be equal to 2
12 Bottom field paired with next top field in output order 1 scan_type_idc shall be equal to 2

Values of mps_pic_struct_type above 12 are reserved for future use by AOMedia and shall not be present in bitstreams conforming to this version of this Specification.

Decoders shall ignore reserved values of mps_pic_struct_type.

It is a requirement of bitstream conformance that when mps_pic_struct_type is present that only one of the following conditions, for all pictures in the current CVS, is true: – The value of mps_pic_struct_type is equal to 0, 7 or 8. – The value of mps_pic_struct_type is equal to 1, 2, 9, 10, 11 or 12. – The value of mps_pic_struct_type is equal to 3, 4, 5 or 6.

mps_source_scan_type_idc specifies the scan type with the same semantics as for scan_type_idc.

mps_duplicate_flag indicates whether the current picture should be indicated as a duplicate of a previous picture in output order. When mps_duplicate_flag is equal to 1 the current picture is indicated to be a duplicate of the previous picture. When mps_duplicate_flag is equal to 0 the current picture is not indicated to be a duplicate of the previous picture.

6.16.11. Metadata temporal point info semantics

frame_presentation_time_length_minus_1 plus 1 specifies the length of the frame_presentation_time syntax element, in bits.

frame_presentation_time specifies the presentation time of the frame in clock ticks DispCT counted from the presentation time of the previous key frame random access point or a key frame dependent recovery point for the operating point that is being decoded if the current frame is associated with a key frame random access point, a key frame recovery point or a frame following a delayed random access point and preceding the associated key frame dependent recovery point. It specifies the presentation time of the frame in clock ticks DispCT counted from the presentation time of the most recent key frame random access point or a key frame dependent recovery point if the current frame is not associated with a random access point or if the current frame follows a key frame dependent recovery point. The syntax element is signaled as a fixed length unsigned integer with a length in bits given by frame_presentation_time_length_minus_1 + 1. The frame_presentation_time is the remainder of a modulo 1 << (frame_presentation_time_length_minus_1 + 1) counter.

6.17. Frame header OBU semantics

6.17.1. General frame header semantics

It is a requirement of bitstream conformance that a sequence header OBU has been received before a frame header.

If isFirst is equal to 1, it is a requirement of bitstream conformance that SeenFrameHeader is equal to 0.

If isFirst is equal to 0, it is a requirement of bitstream conformance that SeenFrameHeader is equal to 1.

frame_header_copy is a function call that indicates that a copy of the previous frame_header should be inserted at this point.

Note: Bitstreams may resend the header within different tile group OBUs to allow for improved error resilience. However, the copies must contain identical contents to the original frame_header.

Note: The contents of frame_header are copied bit for bit but this does not include the bits sent before frame_header. This means that the duplicate copies have a different bit alignment within bytes when compared to the original version.

TileNum is a variable giving the index (zero-based) of the current tile.

decode_frame_wrapup is a function call that indicates that the decode frame wrapup process specified in § 7.2 Decode frame wrapup process should be invoked.

6.17.2. Uncompressed header semantics

bridge_frame_ref_idx specifies which reference frame is used in a bridge frame.

cur_mfh_id specifies which multi-frame header to use.

If cur_mfh_id is greater than 0, it is a requirement of bitstream conformance that a multi-frame header OBU with mfh_id_minus1 equal to cur_mfh_id - 1 is present in the bitstream at some point before the syntax element cur_mfh_id, and after the last time the sequence header changed.

Note: This constraint means that multi-frame headers do not persist across sequence header changes, but can be reused in different coded video sequences.

seq_header_id_in_frame_header specifies which sequence header is associated with this frame.

load_sequence_header( id ) specifies that all the syntax elements and variables saved by a previous call to save_sequence_header are loaded from the area of memory indexed by id.

It is a requirement of bitstream conformance that id corresponds to an area of memory that was saved.

After the sequence header is loaded, if cur_mfh_id is greater than 0, it is a requirement of bitstream conformance that both the following are true:

  • mfh_frame_width_minus_1[ cur_mfh_id ] is less than or equal to max_frame_width_minus_1.

  • mfh_frame_height_minus_1[ cur_mfh_id ] is less than or equal to max_frame_height_minus_1.

activate_layer_configuration_record( id ) specifies that the layer configuration records corresponding to the given id are activated. A lcr_global_info syntax structure is activated if the value of lcr_global_config_record_id is equal to id. A lcr_local_info syntax structure is activated if lcr_global_id[ obu_xlayer_id ] is equal to id.

show_existing_frame equal to 1, indicates the frame indexed by frame_to_show_map_idx is to be output; show_existing_frame equal to 0 indicates that further processing is required.

frame_to_show_map_idx specifies the frame to be output. It is only available if show_existing_frame is 1.

derive_sef_order_hint specifies how the order hint for the show existing frame is derived. derive_sef_order_hint equal to 1 specifies that the order hint is derived from the reference frame. derive_sef_order_hint equal to 0 specifies that the order hint is explicitly signaled via the syntax element sef_order_hint.

If derive_sef_order_hint is equal to 1, it is a requirement of bitstream conformance that the reference frame at slot frame_to_show_map_idx has not already been shown.

If derive_sef_order_hint is equal to 1, it is a requirement of bitstream conformance that RefImplicitOutputFrame[ frame_to_show_map_idx ] is equal to 0.

sef_order_hint is used to compute OrderHint.

If derive_sef_order_hint is equal to 0, it is a requirement of bitstream conformance that the computed value for OrderHint is less than or equal to get_max_disp_order_hint( 0 ).

FrameType specifies the type of the frame:

FrameType Name of FrameType
0 KEY_FRAME
1 INTER_FRAME
2 INTRA_ONLY_FRAME
3 SWITCH_FRAME

frame_is_inter specifies if the frame is an inter frame.

long_term_id specifies a long term id number for the current frame.

num_key_ref_frames specifies the number of ref_long_term_id syntax elements to be read.

ref_long_term_id[ i ] specifies a value of long_term_id for a reference frame.

Note: The ref_long_term_id is used to restrict the reference frames allowed to just the long term reference frames with matching long term ids. Not all long term reference frames need to be mentioned in this list, but only the mentioned ones can be used.

immediate_output_frame equal to 1 specifies that this frame shall be immediately queued for output once decoded. This frame may also be additionally output using the show_existing_frame mechanism. immediate_output_frame equal to 0 specifies that this frame should not be immediately queued for output and that the output of this picture depends on additional syntax elements in the bitstream.

If still_picture is equal to 1, it is a requirement of bitstream conformance that FrameType is equal to KEY_FRAME and immediate_output_frame is equal to 1.

implicit_output_frame equal to 1 specifies that the frame will be output by the output frame buffers process specified specified in § 7.20.6 Output frame buffers process. This frame can also be additionally output using the show_existing_frame mechanism. implicit_output_frame equal to 0 specifies that the frame is not output using the output frame buffers process but can be output using the show_existing_frame mechanism. When not present, the value of implicit_output_frame is equal to 0.

frame_size_override_flag equal to 0 specifies that the frame size is equal to the size in the sequence header. frame_size_override_flag equal to 1 specifies that the frame size will either be specified as the size of one of the reference frames, or computed from the frame_width_minus_1 and frame_height_minus_1 syntax elements.

order_hint is used to compute OrderHint.

OrderHint specifies OrderHintBits least significant bits of the expected output order for this frame.

Note: There is no requirement that OrderHint should reflect the true output order. As a guideline, the motion vector prediction is expected to be more accurate if the true output order is used for frames that will be shown later. If a frame is never to be shown (e.g. it has been constructed as an average of several frames for reference purposes), the encoder is free to choose whichever value of OrderHint will give the best compression.

signal_primary_ref_frame specifies that the primary_ref_frame syntax element is present.

disable_cross_frame_cdf_init equal to 1 specifies that the CDF values are set to default values instead of being taken from a reference frame. disable_cross_frame_cdf_init equal to 0 specifies that the CDF values may be taken from another reference frame (depending on the value of other syntax elements).

Note: The intention of setting disable_cross_frame_cdf_init equal to 1 is to allow frames to be arithmetically decoded in parallel.

primary_ref_frame specifies which reference frame contains the CDF values and other state that should be loaded at the start of the frame.

It is a requirement of bitstream conformance that when primary_ref_frame is present in the bitstream primary_ref_frame is either equal to PRIMARY_REF_NONE, or PRIMARY_REF_NONE is less than NumTotalRefs.

Note: NumTotalRefs will be computed later in the decode process.

If primary_ref_frame is not equal to PRIMARY_REF_NONE, it is a requirement of bitstream conformance that OrderHints[ primary_ref_frame ] is not equal to RESTRICTED_OH.

change_drl equal to 1 indicates that max_drl_bits_minus_1 is changed from the value in the sequence header.

max_drl_bits_minus_1 controls the number of bits read for drl_idx for inter blocks.

flush_implicit_output_frames( ) is a function call that indicates that the flush implicit output frames process specified in § 7.20.5 Flush implicit output frames process is invoked.

bridge_frame_overwrite_flag equal to 1 specifies that the syntax element refresh_frame_flags is present. bridge_frame_overwrite_flag equal to 0 specifies that the refresh_frame_flags will be inferred such that just the frame indicated by bridge_frame_ref_idx will be updated.

has_refresh_frame_flags equal to 1 specifies that the syntax element frame_to_refresh is present. has_refresh_frame_flags equal to 0 specifies that the syntax element frame_to_refresh is not present and that refresh_frame_flags is inferred equal to 0.

frame_to_refresh specifies which reference frame slot will be updated with the current frame after it is decoded.

It is a requirement of bitstream conformance that frame_to_refresh is less than NumRefFrames.

refresh_frame_flags contains a bitmask that specifies which reference frame slots will be updated with the current frame after it is decoded.

If FrameType is equal to INTRA_ONLY_FRAME and NumRefFrames is greater than 1, it is a requirement of bitstream conformance that refresh_frame_flags is not equal to (1 << NumRefFrames) - 1.

Note: This restriction encourages encoders to correctly label random access points (by forcing FrameType to be equal to KEY_FRAME when an intra frame is used to reset the decoding process).

If isRegular is equal to 0 (i.e. this is a leading frame), it is a requirement of bitstream conformance that refresh_frame_flags & OlkRefresh[ i ] is equal to 0 for all i = 0..MAX_NUM_MLAYERS-1.

Note: This restriction forbids leading frames from overwriting frames that will be used by regular frames. This is needed to allow random access decoding to operate correctly.

See § 7.22 Reference frame update process for details of the frame update process.

frame_explicit_ref_frame_map specifies if num_total_refs is present in this frame.

num_total_refs allows the number of references for this frame to be adjusted from the default values.

If num_total_refs is present, it is a requirement of bitstream conformance that num_total_refs is less than or equal to ActiveNumRefFrames.

use_bru equal to 1 specifies that this frame does a backwards reference update.

bru_ref specifies which reference is updated.

bru_inactive equal to 1 specifies that the whole frame is inactive.

If use_bru is equal to 1, it is a requirement of bitstream conformance that all the following are true:

  • OrderHint is greater than or equal to RefOrderHint[ i ] for i in the range 0..NumRefFrames-1 where RefValid[ i ] is equal to 1,

  • immediate_output_frame is equal to 1,

  • bru_ref is less than NumTotalRefs,

  • OrderHints[ bru_ref ] is not equal to RESTRICTED_OH,

  • RefFrameWidth[ ref_frame_idx[ bru_ref] ] is equal to FrameWidth,

  • RefFrameHeight[ ref_frame_idx[ bru_ref ] ] is equal to FrameHeight.

get_ref_frames is a function call that indicates the conceptual point where the default ref_frame_idx values are prepared. When this function is called, the get ref frames process specified in § 7.6 Get ref frames process is invoked.

get_past_future_cur_ref_lists is a function call that indicates the get past future cur ref lists process process specified in § 7.7 Get past future cur ref lists process is invoked.

ref_frame_idx[ i ] specifies which reference frames are used by inter frames. It is a requirement of bitstream conformance that RefValid[ ref_frame_idx[ i ] ] is equal to 1, and that the selected reference frames match the current frame in bit depth, profile, chroma subsampling, and color space.

Note: Syntax elements indicate a reference (an integer between 0 and 6). These references are looked up in the ref_frame_idx array to find which reference frame should be used during inter prediction. There is no requirement that the values in ref_frame_idx should be distinct.

If obu_type is equal to OBU_RAS_FRAME, it is a requirement of bitstream conformance that long_term_id_in_use( RefLongTermId[ ref_frame_idx[ i ] ] ) is equal to 1.

It is a requirement of bitstream conformance that MLayerDependencyMap[ obu_mlayer_id ][ RefMLayerId[ ref_frame_idx[ i ] ] ] is equal to 1.

It is a requirement of bitstream conformance that TLayerDependencyMap[ obu_tlayer_id ][ RefTLayerId[ ref_frame_idx[ i ] ] ] is equal to 1.

If use_bru is equal to 1, it is a requirement of bitstream conformance that the RefCounter[ref_frame_idx[bru_ref]] is not the same as RefCounter[ref_frame_idx[i]] for any value of i not equal to bru_ref in the range 0..NumTotalRefs-1.

Note: This constraint means that it is not legal to store a decoded frame into two reference frames via the refresh_frame_flags mechanism, and then only update one of the reference frames via a backwards reference update. This means an implementation of a decoder can keep a single copy of each decoded frame.

Once the frame size has been determined, it is a requirement of bitstream conformance that all the following conditions are satisfied for i=0..NumTotalRefs-1:

  • 2 * FrameWidth >= RefFrameWidth[ ref_frame_idx[ i ] ]

  • 2 * FrameHeight >= RefFrameHeight[ ref_frame_idx[ i ] ]

  • FrameWidth <= 16 * RefFrameWidth[ ref_frame_idx[ i ] ]

  • FrameHeight <= 16 * RefFrameHeight[ ref_frame_idx[ i ] ]

use_qtr_precision_mv equal to 1 specifies that motion vectors are specified to quarter pel precision.

allow_high_precision_mv equal to 0 specifies that motion vectors are specified to half pel precision; allow_high_precision_mv equal to 1 specifies that motion vectors are specified to eighth pel precision.

FrameMvPrecision specifies the default precision used for specifying motion vectors:

FrameMvPrecision Name of FrameMvPrecision
0 MV_PRECISION_EIGHT_PEL
1 MV_PRECISION_FOUR_PEL
2 MV_PRECISION_TWO_PEL
3 MV_PRECISION_ONE_PEL
4 MV_PRECISION_HALF_PEL
5 MV_PRECISION_QUARTER_PEL
6 MV_PRECISION_EIGHTH_PEL
7 NUM_MV_PRECISIONS

frame_enabled_motion_modes specifies which motion modes are allowed in this frame.

use_ref_frame_mvs equal to 1 specifies that motion vector information from a previous frame can be used when decoding the current frame. use_ref_frame_mvs equal to 0 specifies that this information will not be used.

tmvp_sample_step_minus1 plus 1 specifies the step used during temporal motion vector prediction. A higher step means that motion vectors are projected at fewer locations and the motion field is interpolated at the locations that have been stepped over.

allow_lf_sub_pu specifies if the loop filter filters subblock edges.

TipFrameMode specifies how TIP frames are generated and used:

TipFrameMode Name of TipFrameMode
0 TIP_FRAME_DISABLED
1 TIP_FRAME_AS_REF
2 TIP_FRAME_AS_OUTPUT

Note: TIP_FRAME_DISABLED means no TIP will be used. TIP_FRAME_AS_REF means individual blocks can be coded as TIP blocks. TIP_FRAME_AS_OUTPUT means that the whole frame is automatically generated from TIP blocks.

tip_frame_mode equal to 1 specifies that TipFrameMode is equal to TIP_FRAME_AS_REF. tip_frame_mode equal to 0 specifies that TipFrameMode is equal to TIP_FRAME_DISABLED.

If is_tip_frame() is equal to 1, it is a requirement of bitstream conformance that the computed value for TipFrameMode is equal to TIP_FRAME_AS_OUTPUT.

allow_tip_hole_fill specifies whether holes in the TIP motion field are filled in.

apply_loopfilter_tip specified if the loop filter should be applied after computing the TIP frame.

tip_global_wtd_index specifies an index that chooses the weighting factor of the two reference frames used in TIP.

tip_mv_zero equal to 1 indicates that TipGlobalMv is equal to 0. tip_mv_zero equal to 0 indicates that additional syntax elements are read to compute TipGlobalMv.

TipGlobalMv is the TIP global motion vector (this provides an offset to the normal TIP motion vectors).

tip_mv_row and tip_mv_col give the absolute value of the TIP global motion vector.

tip_mv_row_sign and tip_mv_col_sign give the sign of the TIP global motion vector.

tip_sharp and tip_regular specify the type of interpolation used in the TIP process.

max_drl_bits_minus_1 plus 1 specifies the maximum number of times the drl_mode syntax element is read within read_drl_idx.

max_bvp_drl_bits_minus_1 plus 1 specifies the maximum number of times the drl_mode syntax element is read within read_drl_idx for blocks using intra block copy.

disable_cdf_update specifies whether the CDF update in the symbol decoding process should be disabled.

qm_index specifies which entry in the qm_y, qm_u, qm_v arrays gives the quantization matrix level for a particular segment.

It is a requirement of bitstream conformance that qm_index is less than or equal to pic_qm_num_minus1.

allow_tcq specifies whether TCQ is enabled.

motion_field_estimation is a function call which indicates that the motion field estimation process in § 7.8 Motion field estimation process should be invoked.

setup_tip_motion_field is a function call which indicates that the setup TIP motion field process in § 7.9 Setup TIP motion field process should be invoked.

fill_tpl_mvs_sample_gap is a function call which indicates that the fill temporal motion vectors sample gap process specified in § 7.9.5 Fill temporal motion vectors sample gap process is invoked.

OrderHints specifies the expected output order for each reference frame.

CodedLossless is a variable that is equal to 1 when all segments use lossless encoding. In this case, the loop filter, CDEF filter, and loop restoration are disabled.

It is a requirement of bitstream conformance that delta_q_present is equal to 0 when CodedLossless is equal to 1.

allow_parity_hiding equal to 1 specifies that this frame can hide the parity of some DC coefficients.

allow_bawp equal to 1 indicates that the syntax element use_bawp can be present. allow_bawp equal to 0 indicates that the syntax element use_bawp is not present. (this means that BAWP cannot be signaled if allow_bawp is equal to 0.)

allow_warpmv_mode equal to 1 indicates that the syntax element warp_mv can be present. allow_warpmv_mode equal to 0 indicates that the syntax element warp_mv is not present. (This means that YMode cannot be equal to WARPMV if allow_warpmv_mode is equal to 0.)

reduced_tx_set equal to 1 specifies that the frame is restricted to a reduced subset of the full set of transform types.

Note: When reduced_tx_set is equal to 1, the UV transform can still be inferred within compute_tx_type to use a transform type outside of the reduced set.

setup_past_independence is a function call that indicates that this frame can be decoded without dependence on previous coded frames. When this function is invoked the following takes place:

  • FeatureData[ i ][ j ] and FeatureEnabled[ i ][ j ] are set equal to 0 for i = 0..MAX_SEGMENTS-1 and j = 0..SEG_LVL_MAX-1.

  • PrevSegmentIds[ row ][ col ] is set equal to 0 for row = 0..MiRows-1 and col = 0..MiCols-1.

  • PrevGmParams[ ref ][ i ] is set equal to ( ( i % 3 == 2 ) ? 1 << WARPEDMODEL_PREC_BITS : 0 ) for ref = 0..REFS_PER_FRAME - 1, for i = 0..5.

  • ccso_planes[ plane ] is set equal to 0 for plane = 0..2.

init_non_coeff_cdfs is a function call that indicates that the CDF tables which are not used in the coeffs( ) syntax structure should be initialised. When this function is invoked, the following steps apply:

  • WarpMvCdf is set to a copy of Default_Warp_Mv_Cdf.

  • TipPredModeCdf is set to a copy of Default_Tip_Pred_Mode_Cdf.

  • WarpIdxCdf is set to a copy of Default_Warp_Idx_Cdf.

  • WarpWithMvdCdf is set to a copy of Default_Warp_With_Mvd_Cdf.

  • IsWarpCdf is set to a copy of Default_Is_Warp_Cdf.

  • UseGdfCdf is set to a copy of Default_Use_Gdf_Cdf.

  • BruModeCdf is set to a copy of Default_Bru_Mode_Cdf.

  • CdefIndex0Cdf is set to a copy of Default_Cdef_Index0_Cdf.

  • CdefIndexMinus1With3Cdf is set to a copy of Default_Cdef_Index_Minus1_With3_Cdf.

  • CdefIndexMinus1With4Cdf is set to a copy of Default_Cdef_Index_Minus1_With4_Cdf.

  • CdefIndexMinus1With5Cdf is set to a copy of Default_Cdef_Index_Minus1_With5_Cdf.

  • CdefIndexMinus1With6Cdf is set to a copy of Default_Cdef_Index_Minus1_With6_Cdf.

  • CdefIndexMinus1With7Cdf is set to a copy of Default_Cdef_Index_Minus1_With7_Cdf.

  • CdefIndexMinus1With8Cdf is set to a copy of Default_Cdef_Index_Minus1_With8_Cdf.

  • WarpDeltaPrecisionCdf is set to a copy of Default_Warp_Precision_Cdf.

  • WarpDeltaParamLowCdf is set to a copy of Default_Warp_Delta_Param_Low_Cdf.

  • WarpDeltaParamHighCdf is set to a copy of Default_Warp_Delta_Param_High_Cdf.

  • WarpDeltaParamSignCdf is set to a copy of Default_Warp_Delta_Param_Sign_Cdf.

  • YModeSetCdf is set to a copy of Default_Y_Mode_Set_Cdf.

  • YModeIndexCdf is set to a copy of Default_Y_Mode_Index_Cdf.

  • YModeOffsetCdf is set to a copy of Default_Y_Mode_Offset_Cdf.

  • CwpIdxCdf is set to a copy of Default_Cwp_Idx_Cdf.

  • FscModeCdf is set to a copy of Default_Fsc_Mode_Cdf.

  • MrlIndexCdf is set to a copy of Default_Mrl_Index_Cdf.

  • MrlSecIndexCdf is set to a copy of Default_Mrl_Sec_Index_Cdf.

  • UseDpcmYCdf is set to a copy of Default_Use_Dpcm_Y_Cdf.

  • DpcmModeYCdf is set to a copy of Default_Dpcm_Mode_Y_Cdf.

  • UseDpcmUvCdf is set to a copy of Default_Use_Dpcm_UV_Cdf.

  • DpcmModeUvCdf is set to a copy of Default_Dpcm_Mode_UV_Cdf.

  • UVModeCflNotAllowedCdf is set to a copy of Default_Uv_Mode_Cfl_Not_Allowed_Cdf.

  • IsCflCdf is set to a copy of Default_Is_Cfl_Cdf.

  • IntrabcCdf is set to a copy of Default_Intrabc_Cdf.

  • IntrabcPrecisionCdf is set to a copy of Default_Intrabc_Precision_Cdf.

  • IntrabcModeCdf is set to a copy of Default_Intrabc_Mode_Cdf.

  • MorphPredCdf is set to a copy of Default_Morph_Pred_Cdf.

  • RegionTypeCdf is set to a copy of Default_Region_Type_Cdf.

  • DipModeCdf is set to a copy of Default_Dip_Mode_Cdf.

  • UseDipCdf is set to a copy of Default_Use_Dip_Cdf.

  • DoSquareSplitCdf is set to a copy of Default_Do_Square_Split_Cdf.

  • DoSplitCdf is set to a copy of Default_Do_Split_Cdf.

  • RectTypeCdf is set to a copy of Default_Rect_Type_Cdf.

  • DoExtPartitionCdf is set to a copy of Default_Do_Ext_Partition_Cdf.

  • DoUneven4wayPartitionCdf is set to a copy of Default_Do_Uneven_4way_Partition_Cdf.

  • SegIdExtFlagCdf is set to a copy of Default_Seg_Id_Ext_Flag_Cdf.

  • SegmentIdCdf is set to a copy of Default_Segment_Id_Cdf.

  • SegmentIdExtCdf is set to a copy of Default_Segment_Id_Ext_Cdf.

  • SegmentIdPredictedCdf is set to a copy of Default_Segment_Id_Predicted_Cdf.

  • If reduced_tx_part_set is equal to 0, TxPartitionTypeCdf is set to a copy of Default_Tx_Partition_Type_Cdf.

  • If reduced_tx_part_set is equal to 1, TxPartitionTypeCdf is set to a copy of Default_Tx_Partition_Type_Reduced_Cdf.

  • Tx2or3PartitionTypeCdf is set to a copy of Default_Tx_2or3_Partition_Type_Cdf.

  • TxDoPartitionCdf is set to a copy of Default_Tx_Do_Partition_Cdf.

  • LosslessTxSizeCdf is set to a copy of Default_Lossless_Tx_Size_Cdf.

  • LosslessInterTxTypeCdf is set to a copy of Default_Lossless_Inter_Tx_Type_Cdf.

  • SecTxTypeCdf is set to a copy of Default_Sec_Tx_Type_Cdf.

  • CctxTypeCdf is set to a copy of Default_Cctx_Type_Cdf.

  • MostProbableStxSetCdf is set to a copy of Default_Most_Probable_Stx_Set_Cdf.

  • MostProbableStxSetAdstCdf is set to a copy of Default_Most_Probable_Stx_Set_Adst_Cdf.

  • InterpFilterCdf is set to a copy of Default_Interp_Filter_Cdf.

  • UseLocalWarpCdf is set to a copy of Default_Use_Local_Warp_Cdf.

  • UseExtendWarpCdf is set to a copy of Default_Use_Extend_Warp_Cdf.

  • InterpFilterCdf is set to a copy of Default_Interp_Filter_Cdf.

  • SingleModeCdf is set to a copy of Default_Single_Mode_Cdf.

  • UseBawpCdf is set to a copy of Default_Use_Bawp_Cdf.

  • UseBawpChromaCdf is set to a copy of Default_Use_Bawp_Chroma_Cdf.

  • ExplicitBawpCdf is set to a copy of Default_Explicit_Bawp_Cdf.

  • ExplicitBawpScaleCdf is set to a copy of Default_Explicit_Bawp_Scale_Cdf.

  • IsJointCdf is set to a copy of Default_Is_Joint_Cdf.

  • CompoundModeNonJointCdf is set to a copy of Default_Compound_Mode_Non_Joint_Cdf.

  • CompoundModeSameRefsCdf is set to a copy of Default_Compound_Mode_Same_Refs_Cdf.

  • UseOptflowCdf is set to a copy of Default_Use_Optflow_Cdf.

  • TipModeCdf is set to a copy of Default_Tip_Mode_Cdf.

  • UseRefinemvCdf is set to a copy of Default_Use_Refinemv_Cdf.

  • DrlModeCdf is set to a copy of Default_Drl_Mode_Cdf.

  • SkipDrlModeCdf is set to a copy of Default_Skip_Drl_Mode_Cdf.

  • TipDrlModeCdf is set to a copy of Default_Tip_Drl_Mode_Cdf.

  • IsInterCdf is set to a copy of Default_Is_Inter_Cdf.

  • CompModeCdf is set to a copy of Default_Comp_Mode_Cdf.

  • SkipModeCdf is set to a copy of Default_Skip_Mode_Cdf.

  • SkipCdf is set to a copy of Default_Skip_Cdf.

  • CompRef0Cdf is set to a copy of Default_Comp_Ref0_Cdf.

  • CompRef1Cdf is set to a copy of Default_Comp_Ref1_Cdf.

  • SingleRefCdf is set to a copy of Default_Single_Ref_Cdf.

  • UseMostProbablePrecisionCdf is set to a copy of Default_Use_Most_Probable_Precision_Cdf.

  • PbMvPrecisionCdf is set to a copy of Default_Pb_Mv_Precision_Cdf.

  • MvJointAdaptiveCdf is set to a copy of Default_Mv_Joint_Adaptive_Cdf.

  • AmvdIndicesCdf is set to a copy of Default_Amvd_Indices_Cdf.

  • JointShellSetCdf[ i ] is set to a copy of Default_Joint_Shell_Set_Cdf for i = 0..MV_CONTEXTS-1.

  • JointShell0Class0Cdf[ i ] is set to a copy of Default_Joint_Shell0_Class0_Cdf for i = 0..MV_CONTEXTS-1.

  • JointShell1Class0Cdf[ i ] is set to a copy of Default_Joint_Shell1_Class0_Cdf for i = 0..MV_CONTEXTS-1.

  • JointShell3Class0Cdf[ i ] is set to a copy of Default_Joint_Shell3_Class0_Cdf for i = 0..MV_CONTEXTS-1.

  • JointShell4Class0Cdf[ i ] is set to a copy of Default_Joint_Shell4_Class0_Cdf for i = 0..MV_CONTEXTS-1.

  • JointShell5Class0Cdf[ i ] is set to a copy of Default_Joint_Shell5_Class0_Cdf for i = 0..MV_CONTEXTS-1.

  • JointShell6Class0Cdf[ i ] is set to a copy of Default_Joint_Shell6_Class0_Cdf for i = 0..MV_CONTEXTS-1.

  • JointShell0Class1Cdf[ i ] is set to a copy of Default_Joint_Shell0_Class1_Cdf for i = 0..MV_CONTEXTS-1.

  • JointShell1Class1Cdf[ i ] is set to a copy of Default_Joint_Shell1_Class1_Cdf for i = 0..MV_CONTEXTS-1.

  • JointShell3Class1Cdf[ i ] is set to a copy of Default_Joint_Shell3_Class1_Cdf for i = 0..MV_CONTEXTS-1.

  • JointShell4Class1Cdf[ i ] is set to a copy of Default_Joint_Shell4_Class1_Cdf for i = 0..MV_CONTEXTS-1.

  • JointShell5Class1Cdf[ i ] is set to a copy of Default_Joint_Shell5_Class1_Cdf for i = 0..MV_CONTEXTS-1.

  • JointShell6Class1Cdf[ i ] is set to a copy of Default_Joint_Shell6_Class1_Cdf for i = 0..MV_CONTEXTS-1.

  • JointShellLastTwoClassesCdf[ i ] is set to a copy of Default_Joint_Shell_Last_Two_Classes_Cdf for i = 0..MV_CONTEXTS-1.

  • ShellOffsetLowClassCdf[ i ] is set to a copy of Default_Shell_Offset_Low_Class_Cdf for i = 0..MV_CONTEXTS-1.

  • ShellOffsetClass2Cdf[ i ] is set to a copy of Default_Shell_Offset_Class2_Cdf for i = 0..MV_CONTEXTS-1.

  • ShellOffsetOtherClassCdf[ i ] is set to a copy of Default_Shell_Offset_Other_Class_Cdf for i = 0..MV_CONTEXTS-1.

  • ColMvGreaterCdf[ i ] is set to a copy of Default_Col_Mv_Greater_Cdf for i = 0..MV_CONTEXTS-1.

  • ColMvIndexCdf[ i ] is set to a copy of Default_Col_Mv_Index_Cdf for i = 0..MV_CONTEXTS-1.

  • JmvdScaleModeCdf is set to a copy of Default_Jmvd_Scale_Mode_Cdf.

  • JmvdAdaptiveScaleModeCdf is set to a copy of Default_Jmvd_Adaptive_Scale_Mode_Cdf.

  • PaletteYModeCdf is set to a copy of Default_Palette_Y_Mode_Cdf.

  • IdentityRowYCdf is set to a copy of Default_Identity_Row_Y_Cdf.

  • PaletteYSizeCdf is set to a copy of Default_Palette_Y_Size_Cdf.

  • PaletteSize2YColorCdf is set to a copy of Default_Palette_Size_2_Y_Color_Cdf.

  • PaletteSize3YColorCdf is set to a copy of Default_Palette_Size_3_Y_Color_Cdf.

  • PaletteSize4YColorCdf is set to a copy of Default_Palette_Size_4_Y_Color_Cdf.

  • PaletteSize5YColorCdf is set to a copy of Default_Palette_Size_5_Y_Color_Cdf.

  • PaletteSize6YColorCdf is set to a copy of Default_Palette_Size_6_Y_Color_Cdf.

  • PaletteSize7YColorCdf is set to a copy of Default_Palette_Size_7_Y_Color_Cdf.

  • PaletteSize8YColorCdf is set to a copy of Default_Palette_Size_8_Y_Color_Cdf.

  • DeltaQCdf is set to a copy of Default_Delta_Q_Cdf.

  • IntraTxTypeLongCdf is set to a copy of Default_Intra_Tx_Type_Long_Cdf.

  • InterTxTypeLongCdf is set to a copy of Default_Inter_Tx_Type_Long_Cdf.

  • IsLongSideDctCdf is set to a copy of Default_Is_Long_Side_Dct_Cdf.

  • IntraTxTypeSet1Cdf is set to a copy of Default_Intra_Tx_Type_Set1_Cdf.

  • IntraTxTypeSet2Cdf is set to a copy of Default_Intra_Tx_Type_Set2_Cdf.

  • InterTxTypeSet1Cdf is set to a copy of Default_Inter_Tx_Type_Set1_Cdf.

  • InterTxTypeSet2Cdf is set to a copy of Default_Inter_Tx_Type_Set2_Cdf.

  • InterTxTypeSet3Cdf is set to a copy of Default_Inter_Tx_Type_Set3_Cdf.

  • InterTxTypeSet4Cdf is set to a copy of Default_Inter_Tx_Type_Set4_Cdf.

  • InterTxTypeIndexSet1Cdf is set to a copy of Default_Inter_Tx_Type_Index_Set1_Cdf.

  • InterTxTypeIndexSet2Cdf is set to a copy of Default_Inter_Tx_Type_Index_Set2_Cdf.

  • InterTxTypeOffsetSet1Cdf is set to a copy of Default_Inter_Tx_Type_Offset_Set1_Cdf.

  • InterTxTypeOffsetSet2Cdf is set to a copy of Default_Inter_Tx_Type_Offset_Set2_Cdf.

  • InterIntraCdf is set to a copy of Default_Inter_Intra_Cdf.

  • WarpInterIntraCdf is set to a copy of Default_Warp_Inter_Intra_Cdf.

  • CflSignCdf is set to a copy of Default_Cfl_Sign_Cdf.

  • WedgeInterIntraCdf is set to a copy of Default_Wedge_Inter_Intra_Cdf.

  • CompGroupIdxCdf is set to a copy of Default_Comp_Group_Idx_Cdf.

  • CompoundTypeCdf is set to a copy of Default_Compound_Type_Cdf.

  • InterIntraModeCdf is set to a copy of Default_Inter_Intra_Mode_Cdf.

  • WedgeQuadCdf is set to a copy of Default_Wedge_Quad_Cdf.

  • WedgeAngleCdf is set to a copy of Default_Wedge_Angle_Cdf.

  • WedgeDist1Cdf is set to a copy of Default_Wedge_Dist1_Cdf.

  • WedgeDist2Cdf is set to a copy of Default_Wedge_Dist2_Cdf.

  • CflAlphaCdf is set to a copy of Default_Cfl_Alpha_Cdf.

  • CflIndexCdf is set to a copy of Default_Cfl_Index_Cdf.

  • CflMhDirCdf is set to a copy of Default_Cfl_Mh_Dir_Cdf.

  • CflMhccpCdf is set to a copy of Default_Cfl_Mhccp_Cdf.

  • UseAmvdCdf is set to a copy of Default_Use_Amvd_Cdf.

  • CcsoBlkCdf is set to a copy of Default_Ccso_Blk_Cdf.

  • UseWienerNsCdf is set to a copy of Default_Use_Wiener_Ns_Cdf.

  • WienerNsLengthCdf is set to a copy of Default_Wiener_Ns_Length_Cdf.

  • WienerNsUvSymCdf is set to a copy of Default_Wiener_Ns_Uv_Sym_Cdf.

  • WienerNsBaseCdf is set to a copy of Default_Wiener_Ns_Base_Cdf.

  • UsePcWienerCdf is set to a copy of Default_Use_Pc_Wiener_Cdf.

  • FlexRestorationTypeCdf is set to a copy of Default_Flex_Restoration_Type_Cdf.

init_coeff_cdfs( ) is a function call that indicates that the CDF tables used in the coeffs( ) syntax structure should be initialised. When this function is invoked, the following steps apply:

  • The variable idx is derived as follows:

    • If base_q_idx is less than or equal to 90, idx is set equal to 0.

    • Otherwise, if base_q_idx is less than or equal to 140, idx is set equal to 1.

    • Otherwise, if base_q_idx is less than or equal to 190, idx is set equal to 2.

    • Otherwise, idx is set equal to 3.

  • The cumulative distribution function arrays are reset to default values as follows:

    • TxbSkipCdf is set to a copy of Default_Txb_Skip_Cdf[ idx ].

    • EobPt16Cdf is set to a copy of Default_Eob_Pt_16_Cdf[ idx ].

    • EobPt32Cdf is set to a copy of Default_Eob_Pt_32_Cdf[ idx ].

    • EobPt64Cdf is set to a copy of Default_Eob_Pt_64_Cdf[ idx ].

    • EobPt128Cdf is set to a copy of Default_Eob_Pt_128_Cdf[ idx ].

    • EobPt256Cdf is set to a copy of Default_Eob_Pt_256_Cdf[ idx ].

    • EobPt512Cdf is set to a copy of Default_Eob_Pt_512_Cdf[ idx ].

    • EobPt1024Cdf is set to a copy of Default_Eob_Pt_1024_Cdf[ idx ].

    • EobExtraCdf is set to a copy of Default_Eob_Extra_Cdf[ idx ].

    • DcSignCdf is set to a copy of Default_Dc_Sign_Cdf[ idx ].

    • VTxbSkipCdf is set to a copy of Default_V_Txb_Skip_Cdf[ idx ].

    • CoeffBaseEobCdf is set to a copy of Default_Coeff_Base_Eob_Cdf[ idx ].

    • CoeffBaseLfEobCdf is set to a copy of Default_Coeff_Base_Lf_Eob_Cdf[ idx ].

    • CoeffBaseCdf is set to a copy of Default_Coeff_Base_Cdf[ idx ].

    • CoeffBaseLfCdf is set to a copy of Default_Coeff_Base_Lf_Cdf[ idx ].

    • CoeffBasePhCdf is set to a copy of Default_Coeff_Base_Ph_Cdf[ idx ].

    • CoeffBrCdf is set to a copy of Default_Coeff_Br_Cdf[ idx ].

    • CoeffBrLfCdf is set to a copy of Default_Coeff_Br_Lf_Cdf[ idx ].

    • CoeffBrUvCdf is set to a copy of Default_Coeff_Br_Uv_Cdf[ idx ].

    • CoeffBaseLfUvCdf is set to a copy of Default_Coeff_Base_Lf_Uv_Cdf[ idx ].

    • CoeffBaseLfEobUvCdf is set to a copy of Default_Coeff_Base_Lf_Eob_Uv_Cdf[ idx ].

    • CoeffBaseUvCdf is set to a copy of Default_Coeff_Base_Uv_Cdf[ idx ].

    • CoeffBaseEobUvCdf is set to a copy of Default_Coeff_Base_Eob_Uv_Cdf[ idx ].

    • CoeffBaseBobCdf is set to a copy of Default_Coeff_Base_Bob_Cdf[ idx ].

    • CoeffBrIdtxCdf is set to a copy of Default_Coeff_Br_Idtx_Cdf[ idx ].

    • CoeffBaseIdtxCdf is set to a copy of Default_Coeff_Base_Idtx_Cdf[ idx ].

    • IdtxSignCdf is set to a copy of Default_Idtx_Sign_Cdf[ idx ].

load_cdfs( ctx ) is a function call that indicates that the CDF tables are loaded from frame context number ctx in the range 0 to (NUM_REF_FRAMES - 1). When this function is invoked, a copy of each CDF array mentioned in the semantics for init_coeff_cdfs and init_non_coeff_cdfs is loaded from an area of memory indexed by ctx. (The memory contents of these frame contexts have been initialized by previous calls to save_cdfs).

blend_cdfs( ctx ) is a function call that indicates that the CDF tables are blended with the contents of frame context number ctx in the range 0 to (NUM_REF_FRAMES - 1). When this function is invoked, a blend is made of the CDF values for each of the CDF arrays mentioned in the semantics for init_coeff_cdfs and init_non_coeff_cdfs.

The blend works for each CDF of the cdf array in turn by calling the blend_cdf function with a reference to the CDF, a reference to the previously saved CDF for context ctx, and the length of each CDF as inputs.

The blend_cdf function (which updates the CDF with a small amount of the previously saved CDF) is specified as:

blend_cdf( cdf, savedCdf, sz ) {    for( i = 0; i < sz - 2; i++ ) {        cdf[ i ] = (1 << 15) -                    ( ( (1 << 15) - savedCdf[ i ] +                       7 * ((1 << 15) - cdf[ i ]) + 4) >> 3 )    }    i2 = sz - 1    cdf[ i2 ] = (savedCdf[ i2 ] + 7 * cdf[ i2 ] + 4) >> 3

load_previous( ) is a function call that indicates that information from a previous frame (denoted by prevFrame) may be loaded for use in decoding the current frame. When this function is invoked the following ordered steps apply:

  1. The variable prevFrame is set equal to ref_frame_idx[ DerivedPrimaryRefFrame ].

  2. PrevGmParams is set equal to SavedGmParams[ prevFrame ].

  3. The function load_segmentation_params( prevFrame ) specified in § 7.23 Reference frame loading process is invoked.

load_previous_segment_ids( ) is a function call that indicates that a segmentation map from a previous frame (denoted by prevFrame) may be loaded for use in decoding the current frame. When this function is invoked the segmentation map contained in PrevSegmentIds is set as follows:

  1. The variable prevFrame is set equal to ref_frame_idx[ DerivedPrimaryRefFrame ].

  2. If segmentation_enabled is equal to 1, RefMiCols[ prevFrame ] is equal to MiCols, and RefMiRows[ prevFrame ] is equal to MiRows, PrevSegmentIds[ row ][ col ] is set equal to SavedSegmentIds[ prevFrame ][ row ][ col ] for row = 0..MiRows-1, for col = 0..MiCols-1.

    Otherwise, PrevSegmentIds[ row ][ col ] is set equal to 0 for row = 0..MiRows-1, for col = 0..MiCols-1.

6.17.3. Frame optical flow refine type semantics

opfl_refine_type specifies how optical flow refinement is signaled with the same semantics as enable_opfl_refine.

Note: It is not possible for opfl_refine_type to be set to REFINE_AUTO.

opfl_refine_all is used to set the value of opfl_refine_type when it does not fit in a single bit.

6.17.4. Screen content params semantics

allow_screen_content_tools equal to 1 indicates that intra blocks may use palette encoding; allow_screen_content_tools equal to 0 indicates that palette encoding is never used.

force_integer_mv equal to 1 specifies that motion vectors will always be integers. force_integer_mv equal to 0 specifies that motion vectors can contain fractional bits.

6.17.5. Intra block copy params semantics

allow_intrabc equal to 1 indicates that intra block copy may be used in this frame. allow_intrabc equal to 0 indicates that intra block copy is not allowed in this frame.

allow_global_intrabc equal to 1 indicates that block copy with large motion vectors can be used in the frame.

allow_local_intrabc equal to 1 indicates that block copy from within the local area can be used in the frame.

change_bvp_drl equal to 1 indicates that max_bvp_drl_bits_minus_1 is changed from the value in the sequence header.

max_bvp_drl_bits_minus_1 controls the number of bits read for drl_idx for intra BC.

6.17.6. Frame size semantics

frame_width_minus_1 plus one is the width of the frame in luma samples.

frame_height_minus_1 plus one is the height of the frame in luma samples.

It is a requirement of bitstream conformance that frame_width_minus_1 is less than or equal to max_frame_width_minus_1.

It is a requirement of bitstream conformance that frame_height_minus_1 is less than or equal to max_frame_height_minus_1.

If FrameIsIntra is equal to 0 (indicating that this frame may use inter prediction), the requirements described in the frame size with refs semantics of [section 6.8.6] must also be satisfied.

6.17.7. Frame size with bridge semantics

bridge_frame_width_minus_1 plus 1 specifies the target width of the bridge frame.

bridge_frame_height_minus_1 plus 1 specifies the target height of the bridge frame.

Note: Bridge frames are used to make frames smaller. If the reference frame is already smaller than the target size then the frame dimensions are unchanged.

6.17.8. Frame size with refs semantics

For inter frames, the frame size is either set equal to the size of a reference frame, or can be sent explicitly.

found_ref equal to 1 indicates that the frame dimensions can be inferred from reference frame i where i is the loop counter in the syntax parsing process for frame_size_with_refs. found_ref equal to 0 indicates that the frame dimensions are not inferred from reference frame i.

It is a requirement of bitstream conformance that RefOrderHint[ ref_frame_idx[ i ] ] is not equal to RESTRICTED_OH.

Once the FrameWidth and FrameHeight have been computed for an inter frame, it is a requirement of bitstream conformance that for all values of i in the range 0..(REFS_PER_FRAME - 1), all the following conditions are true:

  • 2 * FrameWidth >= RefFrameWidth[ ref_frame_idx[ i ] ]

  • 2 * FrameHeight >= RefFrameHeight[ ref_frame_idx[ i ] ]

  • FrameWidth <= 16 * RefFrameWidth[ ref_frame_idx[ i ] ]

  • FrameHeight <= 16 * RefFrameHeight[ ref_frame_idx[ i ] ]

Note: This is a requirement even if all the blocks in an inter frame are coded using intra prediction.

6.17.9. Compute image size function semantics

MiCols is the number of 4x4 block columns in the frame.

MiRows is the number of 4x4 block rows in the frame.

CropLeft, CropTop, CropWidth, CropHeight express the size of the cropped window to output.

It is a requirement of bitstream conformance that:

  • CropWidth is greater than 0.

  • CropHeight is greater than 0.

If Monochrome is equal to 0, it is a requirement of bitstream conformance that:

  • CropLeft is equal to ((CropLeft >> SubsamplingX) << SubsamplingX).

  • CropTop is equal to ((CropTop >> SubsamplingY) << SubsamplingY).

6.17.10. Interpolation filter semantics

is_filter_switchable equal to 1 indicates that the filter selection is signaled at the block level; is_filter_switchable equal to 0 indicates that the filter selection is signaled at the frame level.

interpolation_filter specifies the filter selection used for performing inter prediction:

interpolation_filter Name of interpolation_filter
0 EIGHTTAP
1 EIGHTTAP_SMOOTH
2 EIGHTTAP_SHARP
3 BILINEAR
4 SWITCHABLE

6.17.11. Loop filter params semantics

allow_lf_sub_pu specifies if the loop filter filters subblock edges.

apply_loop_filter is an array containing flags that specify if the loop filter is applied for a particular plane and direction. Different values of apply_loop_filter from the array are used depending on the image plane being filtered, and the edge direction (vertical or horizontal) being filtered.

lf_delta_q_present equal to 1 means that a delta quantizer for the loop filter is present. lf_delta_q_present equal to 0 means that the delta quantizer is not present.

lf_delta_q is used to adjust the quantizer for the loop filter.

The loop filter process is described in § 7.16 Loop filter process.

6.17.12. Quantization params semantics

The residual is specified via decoded coefficients which are adjusted by one of four quantization parameters before the inverse transform is applied. The choice depends on the plane (Y or UV) and coefficient position (DC/AC coefficient). The dequantization process is specified in § 7.13 Reconstruction and dequantization.

base_q_idx indicates the base frame qindex. This is used for Y AC coefficients and as the base value for the other quantizers.

DeltaQYDc indicates the Y DC quantizer relative to base_q_idx.

diff_uv_delta equal to 1 indicates that the U and V delta quantizer values are coded separately. diff_uv_delta equal to 0 indicates that the U and V delta quantizer values share a common value.

DeltaQUDc indicates the U DC quantizer relative to base_q_idx.

DeltaQUAc indicates the U AC quantizer relative to base_q_idx.

DeltaQVDc indicates the V DC quantizer relative to base_q_idx.

DeltaQVAc indicates the V AC quantizer relative to base_q_idx.

6.17.13. Setup QM params semantics

using_qmatrix specifies that the quantizer matrix will be used to compute quantizers.

pic_qm_num_minus1 plus 1 specifies the number of qm_y syntax elements present.

qm_y specifies the level in the quantizer matrix that should be used for luma plane decoding.

It is a requirement of bitstream conformance that QmNumPlanes[ qm_y ] is equal to NumPlanes.

It is a requirement of bitstream conformance that MLayerDependencyMap[ obu_mlayer_id ][ QmMLayerId[ qm_y[ i ] ] ] is equal to 1.

It is a requirement of bitstream conformance that TLayerDependencyMap[ obu_tlayer_id ][ QmTLayerId[ qm_y[ i ] ] ] is equal to 1.

qm_uv_same_as_y specifies that qm_u and qm_v match qm_y.

qm_u specifies the level in the quantizer matrix that should be used for chroma U plane decoding.

It is a requirement of bitstream conformance that QmNumPlanes[ qm_u ] is equal to NumPlanes.

It is a requirement of bitstream conformance that MLayerDependencyMap[ obu_mlayer_id ][ QmMLayerId[ qm_u[ i ] ] ] is equal to 1.

It is a requirement of bitstream conformance that TLayerDependencyMap[ obu_tlayer_id ][ QmTLayerId[ qm_u[ i ] ] ] is equal to 1.

qm_v specifies the level in the quantizer matrix that should be used for chroma V plane decoding.

It is a requirement of bitstream conformance that QmNumPlanes[ qm_v ] is equal to NumPlanes.

It is a requirement of bitstream conformance that MLayerDependencyMap[ obu_mlayer_id ][ QmMLayerId[ qm_v[ i ] ] ] is equal to 1.

It is a requirement of bitstream conformance that TLayerDependencyMap[ obu_tlayer_id ][ QmTLayerId[ qm_v[ i ] ] ] is equal to 1.

6.17.14. Delta quantizer semantics

delta_coded specifies that the delta_q syntax element is present.

delta_q specifies an offset (relative to base_q_idx) for a particular quantization parameter.

6.17.15. Segmentation params semantics

AV2 provides a means of segmenting the image and then applying various adjustments at the segment level.

Up to 16 segments may be specified for any given frame. For each of these segments it is possible to specify:

  1. A quantizer (absolute value or delta).

  2. A block skip mode that implies both the use of a (0,0) motion vector and that no residual will be coded.

  3. A forced use of global motion vector

Each of these data values for each segment may be individually updated at the frame level. Where a value is not updated in a given frame, the value from a previous frame, indicated by DerivedPrimaryRefFrame, persists. The exceptions to this are key frames, intra only frames or other frames where independence from past frame values is required (for example to enable error resilience). In such cases all values are reset as described in the semantics for setup_past_independence.

reuse_seg_info equal to 1 indicates that the segment data and enables are reused (from the sequence header or multi-frame header). reuse_seg_info equal to 0 indicates that the segment data and enables are present in the current syntax structure.

SegIdPreSkip equal to 1 indicates that the segment id will be read before the skip_flag syntax element. SegIdPreSkip equal to 0 indicates that the skip_flag syntax element will be read first.

LastActiveSegId indicates the highest numbered segment id that has some enabled feature. This is used when decoding the segment id to only decode choices corresponding to used segments.

segmentation_enabled equal to 1 indicates that this frame makes use of the segmentation tool; segmentation_enabled equal to 0 indicates that the frame does not use segmentation.

segmentation_update_map equal to 1 indicates that the segmentation map is updated during the decoding of this frame. segmentation_update_map equal to 0 means that the segmentation map from a previous frame, indicated by DerivedPrimaryRefFrame, is used.

segmentation_temporal_update equal to 1 indicates that the updates to the segmentation map are coded relative to the existing segmentation map. segmentation_temporal_update equal to 0 indicates that the new segmentation map is coded without reference to the existing segmentation map.

6.17.16. Tile info semantics

reuse_tile_info equal to 1 specifies that the tile parameters are reused. reuse_tile_info equal to 0 specifies that the tile parameters are present.

TileColsLog2 specifies the base 2 logarithm of the desired number of tiles across the frame.

TileCols specifies the number of tiles across the frame. It is a requirement of bitstream conformance that TileCols is less than or equal to MAX_TILE_COLS.

TileRowsLog2 specifies the base 2 logarithm of the desired number of tiles down the frame.

Note: For small frame sizes the actual number of tiles in the frame may be smaller than the desired number because the tile size is rounded up to a multiple of the maximum superblock size.

TileRows specifies the number of tiles down the frame. It is a requirement of bitstream conformance that TileRows is less than or equal to MAX_TILE_ROWS.

MiColStarts is an array specifying the start column (in units of 4x4 luma samples) for each tile across the image.

MiRowStarts is an array specifying the start row (in units of 4x4 luma samples) for each tile down the image.

context_update_tile_id specifies which tile to use for the CDF update. It is a requirement of bitstream conformance that context_update_tile_id is less than TileCols * TileRows.

tile_size_bytes_minus_1 is used to compute TileSizeBytes.

TileSizeBytes specifies the number of bytes needed to code each tile size.

6.17.17. Tile params semantics

uniform_tile_spacing_flag equal to 1 means that the tiles are roughly uniformly spaced across the frame. (All tiles are roughly the same size except for the ones at the right and bottom edge which can be smaller.) uniform_tile_spacing_flag equal to 0 means that the tile sizes are coded.

increment_tile_cols_log2 is used to compute tileColsLog2.

increment_tile_rows_log2 is used to compute tileRowsLog2.

tileWidthSb is used to specify the width of each tile in units of superblocks. It is a requirement of bitstream conformance that tileWidthSb is less than or equal to maxTileWidthSb.

tileHeightSb is used to specify the height of each tile in units of superblocks. It is a requirement of bitstream conformance that tileWidthSb * tileHeightSb is less than or equal to maxTileAreaSb.

If uniform_tile_spacing_flag is equal to 0, it is a requirement of bitstream conformance that startSb is equal to sbCols when the loop writing sbColStarts exits.

If uniform_tile_spacing_flag is equal to 0, it is a requirement of bitstream conformance that startSb is equal to sbRows when the loop writing sbRowStarts exits.

Note: The requirements on startSb ensure that the sizes of each tile add up to the full size of the frame when measured in superblocks.

width_in_sbs_minus_1 specifies the width of a tile minus 1 in units of superblocks.

height_in_sbs_minus_1 specifies the height of a tile minus 1 in units of superblocks.

maxTileHeightSb specifies the maximum height (in units of superblocks) that can be used for a tile (to avoid making tiles with too much area).

6.17.18. Quantizer index delta parameters semantics

delta_q_present specifies whether quantizer index delta values are present.

delta_q_res specifies the left shift which should be applied to decoded quantizer index delta values.

6.17.19. GDF params semantics

gdf_frame_enable specifies if GDF filtering is enabled in the frame.

gdf_per_block specifies if a block level enable is present for GDF.

gdf_pic_qc_idx specifies an adjustment to the quantizer used in GDF filtering.

gdf_pic_scale_idx specifies a scaling for the predicted adjustment used in GDF filtering.

6.17.20. CDEF params semantics

cdef_frame_enable specifies if CDEF filtering is enabled in the frame.

cdef_damping_minus_3 controls the amount of damping in the deringing filter.

cdef_strengths_minus1 plus one specifies the number of strengths settings used for CDEF.

cdef_on_skip_txfm_frame_enable specifies if CDEF filtering is enabled on skipped transform blocks.

cdef_y_pri_zero specifies that cdef_y_pri_strength is equal to 0.

cdef_uv_pri_zero specifies that cdef_uv_pri_strength is equal to 0.

cdef_y_pri_strength and cdef_uv_pri_strength specify the strength of the primary filter.

cdef_y_sec_strength and cdef_uv_sec_strength specify the strength of the secondary filter.

6.17.21. Loop restoration params semantics

tool_index is used to compute FrameRestorationType by choosing one of the enabled tools.

FrameRestorationType specifies the type of restoration used for each plane as follows:

FrameRestorationType Name of FrameRestorationType
0 RESTORE_NONE
1 RESTORE_PC_WIENER
2 RESTORE_WIENER_NONSEP
3 RESTORE_SWITCHABLE

UsesLr indicates if any plane uses loop restoration.

frame_filters_on specifies that the Wiener filters are specified at the frame level (instead of being specified in each loop restoration unit).

temporal_pred_flag specifies that the frame level Wiener filters should be taken from a previous reference frame.

rst_ref_pic_idx specifies which reference to use for the frame level Wiener filters.

If temporal_pred_flag[ plane ] is equal to 1, it is a requirement of bitstream conformance that rst_ref_pic_idx is less than numRefFrames.

If temporal_pred_flag[ plane ] is equal to 1, it is a requirement of bitstream conformance that RefFrameFiltersOn[ refIdx ][ refPlane ] is equal to 1.

num_filter_classes_idx specifies an index into Decode_Num_Filter_Classes that gives the number of classes used in the frame level pixel classified Wiener filter.

lr_luma_use_half_size specifies that luma uses a restoration size of half the maximum size.

lr_luma_use_max_size specifies that luma uses a restoration size of the maximum size.

lr_luma_use_quarter_size specifies that luma uses a restoration size of quarter the maximum size.

lr_chroma_use_half_size specifies that chroma uses a restoration size of half the maximum size.

lr_chroma_use_max_size specifies that chroma uses a restoration size of the maximum size.

lr_chroma_use_quarter_size specifies that chroma uses a restoration size of quarter the maximum size.

LoopRestorationSize[plane] specifies the size of loop restoration units in units of samples in the current plane.

If usesChromaLr is equal to 1, it is a requirement of bitstream conformance that 64 >> SubsamplingY is less than or equal to LoopRestorationSize[ 1 ].

Note: This ensures that restoration units are not smaller than the restoration stripe height.

It is a requirement of bitstream conformance that check_ru_size() is equal to 1, where the function check_ru_size is defined as:

check_ru_size() {  maxPlaneRuSize = Max( LoopRestorationSize[0],       LoopRestorationSize[1] << Max(SubsamplingX, SubsamplingY) )  for ( i = 0; i < TileCols - 1; i++ ) {      tileWidth = (MiColStarts[ i + 1 ] - MiColStarts[ i ]) * MI_SIZE      if ( tileWidth % maxPlaneRuSize != 0) return 0  }  for ( i = 0; i < TileRows - 1; i++ ) {      tileHeight = (MiRowStarts[ i + 1 ] - MiRowStarts[ i ]) * MI_SIZE      if( tileHeight % maxPlaneRuSize != 0) return 0  }  return 1}

Note: This check ensures that restoration units do not cross internal tile boundaries.

6.17.22. CCSO params semantics

ccso_frame_flag equal to 1 specifies that CCSO can be used on this frame. ccso_frame_flag equal to 0 specifies that CCSO is not enabled for this frame.

ccso_planes[plane] specifies if CCSO is enabled for a particular plane.

reuse_ccso specifies if the CCSO parameters are reused from a previous decoded frame.

sb_reuse_ccso specifies if the CCSO block level enable flags are reused from a previous decoded frame.

ccso_ref_idx specifies which reference contains the parameters to reuse.

SavedCcsoPlanes[i][plane] is defined to be the value of ccso_planes[planes] when save_ccso_params(i,plane) was last called.

SavedCcsoLumaSizeLog2[i][plane] is defined to be the value of CcsoLumaSizeLog2 when save_ccso_params(i,plane) was last called.

When ccso_ref_idx is present in the bitstream the following requirements apply:

  • It is a requirement of bitstream conformance that ccso_ref_idx[plane] is less than NumTotalRefs.

  • It is a requirement of bitstream conformance that SavedCcsoPlanes[ idx ][ plane ] is equal to 1.

  • It is a requirement of bitstream conformance that RefOrderHint[ idx ] is not equal to RESTRICTED_OH.

When ccso_ref_idx is present in the bitstream and sb_reuse_ccso[plane] is equal to 1, the following requirements apply:

  • It is a requirement of bitstream conformance that RefMiRows[ idx ] is equal to MiRows.

  • It is a requirement of bitstream conformance that RefMiCols[ idx ] is equal to MiCols.

  • It is a requirement of bitstream conformance that SavedCcsoLumaSizeLog2[ idx ] is equal to CcsoLumaSizeLog2.

  • It is a requirement of bitstream conformance that CcsoLumaSizeLog2 is equal to CCSO_LUMA_SIZE_LOG2.

load_ccso_params is a function call defined in § 7.22 Reference frame update process.

ccso_bo_only specifies that a smaller set of CCSO parameters are present.

ccso_quant_idx and ccso_scale_idx specify the quantization index and scaling for CCSO filtering.

ccso_ext_filter specifies the CCSO filter type.

It is a requirement of bitstream conformance that ccso_ext_filter is not equal to 7.

ccso_max_band_log2 specifies the base 2 logarithm of the maximum number of bands for CCSO filtering.

It is a requirement of bitstream conformance that 1 << ccso_max_band_log2 is less than or equal to CCSO_BAND_NUM.

ccso_edge_clf is used to reduce the number of classes used within CCSO filtering.

ccso_offset_idx is used to compute the sample offset by providing an index into the Ccso_Offset table.

6.17.23. TX mode semantics

tx_mode_select is used to compute TxMode.

TxMode specifies how the transform size is determined:

TxMode Name of TxMode
0 ONLY_4X4
1 TX_MODE_LARGEST
2 TX_MODE_SELECT

For tx_mode equal to TX_MODE_LARGEST, the inverse transform will use the largest transform size that fits inside the block.

For tx_mode equal to ONLY_4X4, the inverse transform will use only 4x4 transforms.

For tx_mode equal to TX_MODE_SELECT, the choice of transform size is specified explicitly for each block.

6.17.24. Skip mode params semantics

SkipModeFrame[ list ] specifies the initial frames to use for compound prediction when skip_mode is equal to 1. (These frames are used for motion vector prediction, but may change when an entry is selected from the motion vector stack.)

skip_mode_present equal to 1 specifies that the syntax element skip_mode will be present. skip_mode_present equal to 0 specifies that skip_mode will not be used for this frame.

6.17.25. Frame reference mode semantics

reference_select equal to 1 specifies that the mode info for inter blocks contains the syntax element comp_mode that indicates whether to use single or compound reference prediction. reference_select equal to 0 specifies that all inter blocks will use single prediction.

6.17.26. Global motion params semantics

use_global_motion specifies if any global motion parameters are present.

our_ref specifies a reference of the current frame. The base warp will be taken from one set of the parameters saved for this reference.

If our_ref is not equal to NumTotalRefs, it is a requirement of bitstream conformance that OrderHints[ our_ref ] is not equal to RESTRICTED_OH.

their_ref specifies a reference that was used by the our_ref reference. The base warp will be taken from the warp used by our_ref when it was predicting from their_ref.

It is a requirement of bitstream conformance that SavedOrderHints[ refIdx ][ their_ref ] is not equal to RESTRICTED_OH.

is_global specifies whether global motion parameters are present for a particular reference frame.

is_rot_zoom specifies whether a particular reference frame uses rotation and zoom global motion.

6.17.27. Global param semantics

precBits specifies the number of fractional bits used for representing gm_params[ref][idx]. All global motion parameters are stored in the model with WARPEDMODEL_PREC_BITS fractional bits, but the parameters are encoded with less precision.

6.17.28. Decode signed subexp with ref semantics

Note: decode_signed_subexp_with_ref will return a value in the range low to high - 1 (inclusive).

6.17.29. Decode unsigned subexp with ref semantics

Note: decode_unsigned_subexp_with_ref will return a value in the range 0 to mx - 1 (inclusive).

6.17.30. Decode subexp semantics

subexp_final_bits provide the final bits that are read once the appropriate range has been determined.

subexp_more_bits equal to 0 specifies that the parameter is in the range mk to mk+a-1. subexp_more_bits equal to 1 specifies that the parameter is greater than mk+a-1.

subexp_bits specifies the value of the parameter minus mk.

6.17.31. Film grain config semantics

apply_grain equal to 1 specifies that film grain should be added to this frame. apply_grain equal to 0 specifies that film grain should not be added.

fgm_id specifies which film grain model to use.

It is a requirement of bitstream conformance that FilmGrainPresent[ fgm_id ] is equal to 1.

Note: This checks that a film grain model is present corresponding to fgm_id, but only at some point in the bitstream. In particular, it is not a requirement that the film grain model is sent in each coded video sequence, so care needs to be taken with random access decoding that an appropriate model is used.

grain_seed specifies the starting value for the pseudo-random numbers used during film grain synthesis.

If apply_grain is equal to 1, it is a requirement of bitstream conformance that all of the following are true:

  • TLayerDependencyMap[obu_tlayer_id][FgmTLayerId[fgm_id]] is equal to 1,

  • MLayerDependencyMap[obu_mlayer_id][FgmMLayerId[fgm_id]] is equal to 1,

  • FgmChromaIdc[ fgm_id ] is equal to chroma_format_idc.

load_grain_model(idx) is a function call that indicates that all the syntax elements read in film_grain_model should be set equal to the values stored in an area of memory indexed by idx.

6.17.32. Film grain model semantics

chroma_scaling_from_luma specifies that the chroma scaling is inferred from the luma scaling.

num_y_points specifies the number of points for the piece-wise linear scaling function of the luma component.

It is a requirement of bitstream conformance that num_y_points is less than or equal to 14.

point_value_increment_bits_minus1 plus 1 specifies the number of bits in the syntax element point_y_value (and corresponding chroma syntax elements).

point_scaling_bits_minus5 plus 5 specifies the number of bits in the syntax element point_y_scaling (and corresponding chroma syntax elements).

point_y_value[ i ] represents the x (luma value) coordinate for the i-th point of the piecewise linear scaling function for luma component. The values are signaled on the scale of 0..255. (In case of 10 bit video, these values correspond to luma values divided by 4. In case of 12 bit video, these values correspond to luma values divided by 16.)

If i is greater than 0, it is a requirement of bitstream conformance that point_y_value[ i ] is greater than point_y_value[ i - 1 ] and less than 256. (this ensures the x coordinates are specified in increasing order).

Note: This conformance requirement refers to the final values of point_y_value afer the addition of point_y_value[ i - 1 ].

point_y_scaling[ i ] represents the scaling (output) value for the i-th point of the piecewise linear scaling function for luma component.

num_cb_points specifies the number of points for the piece-wise linear scaling function of the cb component.

It is a requirement of bitstream conformance that num_cb_points is less than or equal to 14.

point_cb_value[ i ] represents the x coordinate for the i-th point of the piece-wise linear scaling function for cb component. The values are signaled on the scale of 0..255.

If i is greater than 0, it is a requirement of bitstream conformance that point_cb_value[ i ] is greater than point_cb_value[ i - 1 ] and less than 256.

point_cb_scaling[ i ] represents the scaling (output) value for the i-th point of the piecewise linear scaling function for cb component.

num_cr_points specifies represents the number of points for the piece-wise linear scaling function of the cr component.

It is a requirement of bitstream conformance that num_cr_points is less than or equal to 14.

If subX is equal to 1 and subY is equal to 1 and num_cb_points is equal to 0, it is a requirement of bitstream conformance that num_cr_points is equal to 0.

If subX is equal to 1 and subY is equal to 1 and num_cb_points is not equal to 0, it is a requirement of bitstream conformance that num_cr_points is not equal to 0.

Note: These requirements ensure that for 4:2:0 chroma subsampling, film grain noise will be applied to both chroma components, or to neither. There is no restriction for 4:2:2 or 4:4:4 chroma subsampling.

point_cr_value[ i ] represents the x coordinate for the i-th point of the piece-wise linear scaling function for cr component. The values are signaled on the scale of 0..255.

If i is greater than 0, it is a requirement of bitstream conformance that point_cr_value[ i ] is greater than point_cr_value[ i - 1 ] and less than 256.

point_cr_scaling[ i ] represents the scaling (output) value for the i-th point of the piecewise linear scaling function for cr component.

grain_scaling_minus_8 represents the shift – 8 applied to the values of the chroma component. The grain_scaling_minus_8 can take values of 0..3 and determines the range and quantization step of the standard deviation of film grain.

ar_coeff_lag specifies the number of auto-regressive coefficients for luma and chroma.

bits_per_ar_coeff_y_minus5 plus 5 specifies the number of bits in the syntax element ar_coeffs_y_plus_128.

bits_per_ar_coeff_cb_minus5 plus 5 specifies the number of bits in the syntax element ar_coeffs_cb_plus_128.

bits_per_ar_coeff_cr_minus5 plus 5 specifies the number of bits in the syntax element ar_coeffs_cr_plus_128.

ar_coeffs_y_plus_128[ i ] specifies auto-regressive coefficients used for the Y plane.

ar_coeffs_cb_plus_128[ i ] specifies auto-regressive coefficients used for the U plane.

ar_coeffs_cr_plus_128[ i ] specifies auto-regressive coefficients used for the V plane.

ar_coeff_shift_minus_6 specifies the range of the auto-regressive coefficients. Values of 0, 1, 2, and 3 correspond to the ranges for auto-regressive coefficients of [-2, 2), [-1, 1), [-0.5, 0.5) and [-0.25, 0.25) respectively.

grain_scale_shift specifies how much the Gaussian random numbers should be scaled down during the grain synthesis process.

cb_mult represents a multiplier for the cb component used in derivation of the input index to the cb component scaling function.

cb_luma_mult represents a multiplier for the average luma component used in derivation of the input index to the cb component scaling function.

cb_offset represents an offset used in derivation of the input index to the cb component scaling function.

cr_mult represents a multiplier for the cr component used in derivation of the input index to the cr component scaling function.

cr_luma_mult represents a multiplier for the average luma component used in derivation of the input index to the cr component scaling function.

cr_offset represents an offset used in derivation of the input index to the cr component scaling function.

overlap_flag equal to 1 indicates that the overlap between film grain blocks shall be applied. overlap_flag equal to 0 indicates that the overlap between film grain blocks shall not be applied.

clip_to_restricted_range equal to 1 indicates that clipping to the restricted (studio) range shall be applied to the sample values after adding the film grain. clip_to_restricted_range equal to 0 indicates that clipping to the full range shall be applied to the sample values after adding the film grain.

mc_identity is used to adjust the clipping range for film grain.

film_grain_block_size equal to 0 indicates that a film grain block size of 16 by 16 is used. film_grain_block_size equal to 1 indicates that a film grain block size of 32 by 32 is used.

6.18. Tile group OBU semantics

is_first_tile_group equal to 1 specifies that this is the first tile group for the current frame. is_first_tile_group equal to 0 specifies that this is not the first tile group for the current frame.

It is a requirement of bitstream conformance that SeenFrameHeader is not equal to is_first_tile_group.

restricted_prediction_switch equal to 1 specifies that certain reference frames will be marked as restricted.

Note: This allows future frames to use sample values from both the switch frame and other reference frames. However, the other reference frames are marked as restricted to indicate that only the sample values can be used, and not any of the other information associated with a reference frame. This is needed because switch frames switch between bitstreams so the other information is not consistent and cannot be used for parsing syntax elements.

uncompressed_header_flag equal to 1 specifies that the frame header is present. uncompressed_header_flag equal to 0 specifies that the frame header is not present.

NumTiles specifies the total number of tiles in the frame.

tile_start_and_end_present_flag specifies whether tg_start and tg_end are present. If tg_start and tg_end are not present, this tile group covers the entire frame.

tg_start specifies the zero-based index of the first tile in the current tile group.

It is a requirement of bitstream conformance that the value of tg_start is equal to the value of TileNum at the point that tile_group_payload is invoked.

tg_end specifies the zero-based index of the last tile in the current tile group.

It is a requirement of bitstream conformance that the value of tg_end is greater than or equal to tg_start.

It is a requirement of bitstream conformance that the value of tg_end for the last tile group in each frame is equal to NumTiles - 1.

Note: These requirements ensure that conceptually all tile groups are present and received in order for the purposes of specifying the decode process.

bru_tile_active equal to 0 specifies that a whole tile is inactive. bru_tile_active equal to 1 specifies that the bru_mode syntax element is present for each superblock in a tile.

6.19. Tile group payload semantics

6.19.1. General tile group payload semantics

frame_end_update_cdf is a function call that indicates that the frame CDF arrays are set equal to the saved CDFs. This process is described in § 7.5 Frame end update CDF process.

tile_size_minus_1 is used to compute tileSize.

tileSize specifies the size in bytes of the next coded tile.

Note: This size includes any padding bytes if added by the exit process for the Symbol decoder. The size does not include the bytes used for tile_size_minus_1 or syntax elements sent before tile_size_minus_1. For the last tile in the tile group, tileSize is computed instead of being read and includes the OBU trailing bits.

decode_frame_wrapup is a function call that indicates that the decode frame wrapup process specified in § 7.2 Decode frame wrapup process should be invoked.

6.19.2. Decode tile semantics

clear_left_context is a function call that indicates that some arrays are initialized. When this function is invoked the arrays WarpBankSize, WarpBankStart, RefMvBankSize, RefMvBankStart, LeftLevelContext, LeftDcContext, LeftMiSizes, and LeftSegPredContext are initialized as follows:

for (i = 0; i < MiRows; i++) {    for (plane = 0; plane < 3; plane++) {        LeftDcContext[ plane ][ i ] = 0        LeftLevelContext[ plane ][ i ] = 0    }    LeftSegPredContext[ i ] = 0}sbSize4 = Num_4x4_Blocks_High[ SbSize ]numSbs = (MiRows + sbSize4 - 1) / sbSize4for (i = 0; i < numSbs * sbSize4; i++) {    LeftMiSizes[ 0 ][ i ] = BLOCK_256X256    LeftMiSizes[ 1 ][ i ] = BLOCK_256X256}for(ref = 0; ref < REFS_PER_FRAME; ref++) {    WarpBankSize[ ref ] = 0    WarpBankStart[ ref ] = 0}for(ref = 0; ref < BANK_REFS_PER_FRAME * (BANK_REFS_PER_FRAME + 1); ref++) {    RefMvBankSize[ ref ] = 0    RefMvBankStart[ ref ] = 0}

clear_above_context is a function call that indicates that some arrays used to determine the probabilities are initialized. When this function is invoked the arrays AboveLevelContext, AboveDcContext, AboveMiSizes, and AboveSegPredContext are initialized as follows:

for (i = 0; i < MiCols; i++) {    for (plane = 0; plane < 3; plane++) {        AboveDcContext[ plane ][ i ] = 0        AboveLevelContext[ plane ][ i ] = 0    }    AboveSegPredContext[ i ] = 0}sbSize4 = Num_4x4_Blocks_Wide[ SbSize ]numSbs = (MiCols + sbSize4 - 1) / sbSize4for (i = 0; i < numSbs * sbSize4; i++) {    AboveMiSizes[ 0 ][ i ] = BLOCK_256X256    AboveMiSizes[ 1 ][ i ] = BLOCK_256X256}

TreeType specifies which syntax elements are present as follows:

TreeType Name of TreeType
0 SHARED_PART
1 LUMA_PART
2 CHROMA_PART

When TreeType is equal to LUMA_PART, syntax elements related to the luma plane are present. When TreeType is equal to CHROMA_PART, syntax elements related to the chroma plane are present. Otherwise (TreeType is equal to SHARED_PART), both luma and chroma syntax elements can be present.

ReadDeltas specifies whether the current block may read delta values for the quantizer index and loop filter. If the entire superblock is skipped the delta values are not read, otherwise delta values for the quantizer index and loop filter are read on the first block of a superblock. If delta_q_present is equal to 0, no delta values are read for the quantizer index.

bru_mode specifies the type of superblock as follows:

bru_mode Name of bru_mode
0 BRU_INACTIVE
1 BRU_SUPPORT
2 BRU_ACTIVE

Note: bru_mode is also used outside BRU frames to determine if the syntax elements are parsed. In bridge frames, syntax is inferred, so bru_mode is BRU_INACTIVE. In normal frames, syntax is parsed, so bru_mode is BRU_ACTIVE.

6.19.3. Reset reference motion vector bank function semantics

WarpBankHits counts how many times the WarpBankParams have been searched in the superblock.

RefMvBankHits counts how many times update_ref_mv_bank has been called in the superblock.

RefMvUnitHits counts how many times update_ref_mv_bank has been called since the last time the current block was aligned to a unit boundary. The unit size is define relative to the superblock size such that a grid of 8 by 8 units fit within the superblock.

RefMvRemainHits defines how many calls to update_ref_mv_bank are allowed. This variable decreases when update_ref_mv_bank is called, but can be increased if a large block is processed that is aligned to a unit boundary.

6.19.4. Clear block decoded flags function semantics

BlockDecoded is an array which stores one boolean value per 4x4 sample block per plane in the current superblock, plus a border of one 4x4 sample block on all sides of the superblock. Except for the borders, a value of 1 in BlockDecoded indicates that the corresponding 4x4 sample block has been decoded. The borders are used when computing above-right and below-left availability along the top and left edges of the superblock.

6.19.5. Decode partition semantics

The parameter hasChroma specifies that this partition contains one or more blocks with chroma mode information.

The parameter chromaOffset specifies whether the minimum size for chroma blocks has been reached. chromaOffset equal to 0 specifies that the minimum size has not been reached (in this case the chroma block will be the same size as the luma block). chromaOffset equal to 1 specifies that the minimum size has been reached (in this case the chroma block has stopped splitting so may be a different size to the luma block).

If chromaOffset is equal to 1 and hasChroma is equal to 1 and TreeType is not equal to LUMA_PART and NumPlanes is greater than 1, it is a requirement of bitstream conformance that r is less than MiRows or c is less than MiCols.

Note: This requirement ensures that chroma info is always present. To satisfy this requirement, only certain partition choices can be made near the edge.

If r is less than MiRows or c is less than MiCols, then if hasChroma is equal to 1 it is a requirement of bitstream conformance that get_plane_residual_size( chromaOffset ? ChromaMiSize : subSize, 1, 1 ) is not equal to BLOCK_INVALID.

Note: This requirement of bitstream conformance applies to the values of variables chromaOffset, ChromaMiSize, and subSize at the point just before the line if ( partition == PARTITION_NONE ) {.

ChromaMiRow is a variable holding the vertical location of the chroma block in units of 4x4 luma samples.

ChromaMiCol is a variable holding the horizontal location of the chroma block in units of 4x4 luma samples.

ChromaMiSize is a variable holding the size of the chroma block with values having the same interpretation for the variable subSize. The size corresponds to the amount of luma samples that are covered by the chroma block.

The variable partition specifies how a block is partitioned:

partition Name of partition
0 PARTITION_NONE
1 PARTITION_HORZ
2 PARTITION_VERT
3 PARTITION_HORZ_3
4 PARTITION_VERT_3
5 PARTITION_HORZ_4A
6 PARTITION_HORZ_4B
7 PARTITION_VERT_4A
8 PARTITION_VERT_4B
9 PARTITION_SPLIT

Note: PARTITION_HORZ_3 and PARTITION_VERT_3 split into four parts by first splitting in a ratio 1:2:1, and then splitting the middle section in the perpendicular direction.

The variable subSize is computed from partition and indicates the size of the component blocks within this block:

subSize Name of subSize
0 BLOCK_4X4
1 BLOCK_4X8
2 BLOCK_8X4
3 BLOCK_8X8
4 BLOCK_8X16
5 BLOCK_16X8
6 BLOCK_16X16
7 BLOCK_16X32
8 BLOCK_32X16
9 BLOCK_32X32
10 BLOCK_32X64
11 BLOCK_64X32
12 BLOCK_64X64
13 BLOCK_64X128
14 BLOCK_128X64
15 BLOCK_128X128
16 BLOCK_128X256
17 BLOCK_256X128
18 BLOCK_256X256
19 BLOCK_4X16
20 BLOCK_16X4
21 BLOCK_8X32
22 BLOCK_32X8
23 BLOCK_16X64
24 BLOCK_64X16
25 BLOCK_4X32
26 BLOCK_32X4
27 BLOCK_8X64
28 BLOCK_64X8
29 BLOCK_4X64
30 BLOCK_64X4

Note: When a partition splits into blocks of different sizes, the first and final blocks will be of size subSize.

The dimensions of these blocks are given in width, height order (e.g. BLOCK_8X16 corresponds to a block that is 8 samples wide, and 16 samples high).

ChromaFollowsLuma is a variable that is used to decide whether the chroma partitioning should follow luma. The chroma partitioning follows luma if luma is split and none of the split partitions contains a block smaller than 32 by 32.

ChromaPartitionKnown is an array that records where the chroma partitioning is already known (as it is forced to follow the luma partitioning).

region_type equal to INTRA_REGION indicates that the luma partition tree is sent first, followed by information about a single chroma block. All blocks in this case will be intra blocks.

6.19.6. Read partition semantics

do_split equal to 1 specifies that the block should be split further. do_split equal to 0 specifies that no further splitting is required.

do_square_split equal to 1 specifies that the block is split into 4 square parts. do_square_split equal to 0 specifies that the block is not split into 4 square parts.

rect_type specifies the direction in which the block should be split. rect_type is equal to RECT_HORZ for a horizontal cut. rect_type is equal to RECT_VERT for a vertical cut.

do_ext_partition specifies whether to use extended partitions. do_ext_partition equal to 0 specifies that the block is split into two. do_ext_partition equal to 1 specifies that the block is split into four.

do_uneven_4way_partition specifies whether to use an uneven partition.

uneven_4way_partition_type specifies the type of uneven partition.

Rect_Part_Table is a lookup table for finding the chosen partition.

6.19.7. Decode block semantics

MiRow is a variable holding the vertical location of the block in units of 4x4 luma samples.

MiCol is a variable holding the horizontal location of the block in units of 4x4 luma samples.

MiSize is a variable holding the size of the block with values having the same interpretation for the variable subSize.

HasChroma is a variable that specifies whether chroma information is coded for this block.

Variable AvailU is equal to 0 if the information from the block above cannot be used on the luma plane; AvailU is equal to 1 if the information from the block above can be used on the luma plane.

Variable AvailL is equal to 0 if the information from the block to the left can not be used on the luma plane; AvailL is equal to 1 if the information from the block to the left can be used on the luma plane.

Variables AvailUChroma and AvailLChroma have the same significance as AvailU and AvailL, but on the chroma planes.

SubMvs contains motion vectors for each 4x4 subblock. SubMvs are initialized in decode block, but can get adjusted if the block is predicted with a warped prediction.

The function call to motion_field_motion_vector_storage indicates that the motion field motion vector storage process specified in § 7.21 Motion field motion vector storage process is invoked.

After all the syntax elements have been read for the block, if is_inter is equal to 0, it is a requirement of bitstream conformance that seg_feature_active(SEG_LVL_SKIP) is equal to 0.

After the local variables bwh and bh4 have been computed in the decode block syntax, it is a requirement of bitstream conformance that bw4 is less than or equal to bh4 * MaxPbAspectRatio, and that bh4 is less than or equal to bw4 * MaxPbAspectRatio.

6.19.8. Mode info semantics

This switches between different ways of reading the mode info for different frame types.

6.19.9. BRU mode info semantics

This syntax is used for inactive and support BRU blocks.

6.19.10. Intra frame mode info semantics

This syntax is used when coding an intra block within an intra frame.

use_intrabc equal to 1 specifies that intra block copy should be used for this block. use_intrabc equal to 0 specifies that intra block copy should not be used.

6.19.11. Read intra block copy semantics

This syntax is used when coding a motion vector for intra block copy.

intrabc_mode equal to 1 indicates that there is no motion vector difference. intrabc_mode equal to 1 indicates that a motion vector difference is present.

intrabc_drl_mode is used to select a predicted motion vector from the stack.

intrabc_precision is used to decide the motion vector precision for intra block copy.

morph_pred specifies if morphological prediction (which tries to adjust the brightness of the samples to match the context) should be used.

If morph_pred is equal to 1, it is a requirement of bitstream conformance that is_offset_mv_valid( -1, -1 ) is equal to 1.

The function is_offset_mv_valid is defined as:

is_offset_mv_valid( dx, dy ) {    offsetMv[0] = Mv[0][0] + dy * 8    offsetMv[1] = Mv[0][1] + dx * 8    return is_mv_valid( offsetMv )}

Note: This constraint ensures that the extra reference pixels fetched are also valid for intra block copy prediction.

6.19.12. Read intra Y mode semantics

use_dpcm_y specifies if DPCM should be used for luma.

dpcm_mode_y is used to compute the direction for intra prediction when using DPCM.

y_mode_set equal to 0 specifies that y_mode_index is present. y_mode_set equal to 1 specifies that y_second_mode is present.

y_mode_index and y_mode_offset are used to send the first set of YMode choices.

y_second_mode is used to send the second set of YMode choices.

fsc_mode is used to control if the block should use forward skip coding of the coefficients and the type of transform.

mrl_index specifies the distance of the reference samples used for intra prediction.

mrl_sec_index specifies if the block should use a secondary intra prediction.

YMode specifies the direction of intra prediction filtering:

YMode Name of YMode
0 DC_PRED
1 V_PRED
2 H_PRED
3 D45_PRED
4 D135_PRED
5 D113_PRED
6 D157_PRED
7 D203_PRED
8 D67_PRED
9 SMOOTH_PRED
10 SMOOTH_V_PRED
11 SMOOTH_H_PRED
12 PAETH_PRED

AngleDeltaY is computed from y_mode_index, y_mode_offset, and y_second_mode to produce the final luma angle offset value, which may be positive or negative.

6.19.13. Read intra UV mode semantics

use_dpcm_uv specifies if DPCM should be used for chroma.

dpcm_mode_uv is used to compute the direction for intra prediction when using DPCM.

cflAllowed works out if chroma from luma is allowed. (It is allowed if the luma size fits inside a 64 by 64 block, and a single transform block will be used for chroma.)

is_cfl specifies if chroma from luma prediction is used for chroma.

uv_mode and uv_mode_idx are used to compute the UVMode.

It is a requirement of bitstream conformance that uv_mode_idx is less than or equal to 5.

UVMode specifies the chrominance intra prediction mode using values with the same interpretation as in the semantics for YMode, with an additional mode UV_CFL_PRED.

UVMode Name of UVMode
0 DC_PRED
1 V_PRED
2 H_PRED
3 D45_PRED
4 D135_PRED
5 D113_PRED
6 D157_PRED
7 D203_PRED
8 D67_PRED
9 SMOOTH_PRED
10 SMOOTH_V_PRED
11 SMOOTH_H_PRED
12 PAETH_PRED
13 UV_CFL_PRED

AngleDeltaUV is computed from uv_mode and may be positive or negative.

6.19.14. Intra segment ID semantics

Lossless is a variable which, if equal to 1, indicates that the block is coded using a special 4x4 transform designed for encoding frames that are bit-identical with the original frames.

6.19.15. Read segment ID semantics

seg_id_ext_flag and segment_id specify which segment is associated with the current intra block being decoded. It is first read from the stream, and then postprocessed based on the predicted segment id.

It is a requirement of bitstream conformance that the postprocessed value of segment_id (i.e. the value returned by neg_deinterleave) is in the range 0 to LastActiveSegId (inclusive of endpoints).

6.19.16. Skip mode semantics

skip_mode equal to 1 indicates that this block will use some default settings (that correspond to compound prediction) and so most of the mode info is skipped. skip_mode equal to 0 indicates that the mode info is not skipped.

6.19.17. Skip semantics

skip_flag equal to 0 indicates that there may be some transform coefficients to read for this block; skip_flag equal to 1 indicates that there are no transform coefficients.

6.19.18. Quantizer index delta semantics

delta_q_abs specifies the absolute value of the quantizer index delta value being decoded. If delta_q_abs is equal to DELTA_Q_SMALL, the value is encoded using delta_q_rem_bits and delta_q_abs_bits.

delta_q_rem_bits and delta_q_abs_bits encode the absolute value of the quantizer index delta value being decoded, where the absolute value of the quantizer index delta value is of the form:

(1 << delta_q_rem_bits) + delta_q_abs_bits + 1

delta_q_sign_bit equal to 0 indicates that the quantizer index delta value is positive; delta_q_sign_bit equal to 1 indicates that the quantizer index delta value is negative.

6.19.19. TX size semantics

lossless_tx_size specifies if a 8x8 or 4x4 transform size is used for a lossless block.

TxSize specifies the transform size to be used for this block:

TxSize Name of TxSize
0 TX_4X4
1 TX_8X8
2 TX_16X16
3 TX_32X32
4 TX_64X64
5 TX_4X8
6 TX_8X4
7 TX_8X16
8 TX_16X8
9 TX_16X32
10 TX_32X16
11 TX_32X64
12 TX_64X32
13 TX_4X16
14 TX_16X4
15 TX_8X32
16 TX_32X8
17 TX_16X64
18 TX_64X16
19 TX_4X32
20 TX_32X4
21 TX_8X64
22 TX_64X8
23 TX_4X64
24 TX_64X4
255 TX_INVALID

Note: TxSize is determined for skipped intra blocks because TxSize controls the granularity of the intra prediction.

6.19.20. Block TX size semantics

LumaTxSizes is an array that holds the luma transform sizes.

LumaTxMiddle is an array that records whether the transform block was from the middle of a transform partition. (This information is important for intra prediction as top-right and bottom-left values are marked unavailable for middle blocks.)

6.19.21. Read TX partition semantics

tx_do_partition equal to 1 specifies that the block should be split into smaller transform sizes. tx_do_partition equal to 0 specifies that the block should not be split any more.

tx_partition_type and tx_2or3_partition_type are used to indicate the transform partition.

txPartition specifies the transform partition:

txPartition Name of txPartition
0 TX_PARTITION_NONE
1 TX_PARTITION_SPLIT
2 TX_PARTITION_HORZ
3 TX_PARTITION_VERT
4 TX_PARTITION_HORZ4
5 TX_PARTITION_VERT4
6 TX_PARTITION_HORZ5
7 TX_PARTITION_VERT5

It is a requirement of bitstream conformance that the return value of the function set_tx_size is not equal to TX_INVALID.

6.19.22. Inter frame mode info semantics

This reads syntax elements for blocks within an inter frame.

6.19.23. Inter segment ID semantics

seg_id_predicted equal to 1 specifies that the segment_id is taken from the segmentation map. seg_id_predicted equal to 0 specifies that the syntax element segment_id is parsed.

Note: It is allowed for seg_id_predicted to be equal to 0 even if the value coded for the segment_id is equal to predictedSegmentId.

6.19.24. Is inter semantics

is_inter equal to 0 specifies that the block is an intra block; is_inter equal to 1 specifies that the block is an inter block.

Note: When intra block copy is used within an inter frame, the syntax element is_inter is read as 0, but then modified to equal 1 as the motion vector prediction uses the IsInters array to detect blocks with motion vectors and intra block copy includes motion vectors.

use_intrabc equal to 1 specifies that intra block copy should be used for this block. use_intrabc equal to 0 specifies that intra block copy should not be used.

6.19.25. Intra block mode info semantics

This syntax is used when coding an intra block within an inter frame.

6.19.26. Inter block mode info semantics

This syntax is used when coding an inter block.

tip_pred_mode is used to compute the YMode when using TIP.

is_warp specifies that the YMode is either WARPMV or WARP_NEWMV.

warp_mv specifies that the YMode should be set to WARPMV.

use_amvd specifies that an asymmetric motion vector difference is used.

single_mode, is_joint, compound_mode_non_joint, and compound_mode_same_refs specify how the motion vector used by inter prediction is obtained. An offset is added to compute YMode as follows:

YMode Name of YMode
14 NEARMV
15 GLOBALMV
16 NEWMV
17 WARPMV
18 WARP_NEWMV
19 NEAR_NEARMV
20 NEAR_NEWMV
21 NEW_NEARMV
22 GLOBAL_GLOBALMV
23 NEW_NEWMV
24 JOINT_NEWMV

Note: The intra modes take values 0 to 13 so these YMode values start at 14.

use_optflow specifies that optical flow is used for this block.

use_bawp equal to 1 specifies that BAWP is used for this block for luma samples.

explicit_bawp equal to 1 specifies that BAWP scaling factor is based on OrderHints.

explicit_bawp_scale specifies the sign for BAWP scaling factor delta based on OrderHints.

use_bawp_chroma equal to 1 specifies that BAWP is used for this block for chroma samples.

warp_idx equal to 0 specifies that a particular warp reference candidate is used to compute the warp parameters.

warpmv_with_mvd specifies that a motion vector difference is present which will be used to compute the warp parameters.

jmvd_scale_mode specifies a parameter used while scaling motion vectors in joint mode.

use_most_probable_precision equal to 1 specifies that the frame level precision should be used for motion vectors. use_most_probable_precision equal to 0 specifies that the syntax element pb_mv_precision is read to determine the precision.

pb_mv_precision is used to compute the precision for motion vectors.

cwp_idx is used to compute the compound weighting factor.

interp_filter specifies the type of filter used in inter prediction. Values 0..3 are allowed with the same interpretation as for interpolation_filter.

Note: The syntax element interpolation_filter from the uncompressed header can specify the type of filter to be used for the whole frame. If it is set to SWITCHABLE then the interp_filter syntax element is read from the bitstream for every inter block.

When all the syntax elements have been read in the inter block mode info syntax, if use_bru is equal to 1, it is a requirement of bitstream conformance that:

  • RefFrame[0] is not equal to bru_ref

  • RefFrame[1] is not equal to bru_ref

When all the syntax elements have been read in the inter block mode info syntax, if use_bru is equal to 1 and RefFrame[0] is equal to TIP_FRAME, it is a requirement of bitstream conformance that:

  • ClosestPast is not equal to bru_ref

  • ClosestFuture is not equal to bru_ref

6.19.27. Read warp delta semantics

warp_delta_precision is used to specifies whether high precision warp parameters are used.

warp_delta_param_low, warp_delta_param_high, and warp_delta_param_sign are used to compute a warp parameter as an offset from the predicted value.

6.19.28. Read drl idx semantics

RefMvIdx specifies which candidate in the RefStackMv should be used.

RefMvIdx0 specifies which candidate in the RefStack0Mvs should be used.

RefMvIdx1 specifies which candidate in the RefStack1Mvs should be used.

drl_mode is a bit sent for candidates in the motion vector stack to indicate if they should be used. drl_mode equal to 0 means to use the current value of idx. drl_mode equal to 1 says to continue searching. DRL stands for "Dynamic Reference List".

6.19.29. DIP mode info semantics

use_dip is a bit specifying whether or not data driven intra prediction can be used.

dip_mode and dip_transpose are parameters used in the data driven intra prediction process.

6.19.30. Ref frames semantics

tip_mode specifies if TIP is used for the block.

comp_mode specifies whether single or compound prediction is used:

comp_mode Name of comp_mode
0 SINGLE_REFERENCE
1 COMPOUND_REFERENCE

SINGLE_REFERENCE indicates that the inter block uses only a single reference frame to generate motion compensated prediction.

COMPOUND_REFERENCE indicates that the inter block uses compound mode.

RefFrame[ 0 ] specifies which frame is used to compute the predicted samples for this block:

RefFrame[ 0 ] Name of ref_frame
7 TIP_FRAME
8 INTRA_FRAME

Note: Values from 0 to 6 are also allowed, but do not have a name. These values correspond to using different inter frames for reference.

RefFrame[ 1 ] specifies which additional frame is used in compound prediction:

RefFrame[ 1 ] Name of ref_frame
-1 NONE (this block uses single prediction)
8 INTRA_FRAME (this block uses inter intra prediction)

Note: Values from 0 to 6 are also allowed, but do not have a name. These values correspond to using different inter frames for reference.

6.19.31. Read compound ref semantics

If read_compound_ref is called, it is a requirement of bitstream conformance that NumTotalRefs is greater than 0.

comp_ref equal to 1 means that reference ref should be used for inter prediction by this block.

6.19.32. Read single ref semantics

If read_single_ref is called, it is a requirement of bitstream conformance that NumTotalRefs is greater than 0.

single_ref equal to 1 means that reference ref should be used for inter prediction by this block.

6.19.33. Assign MV semantics

mv_sign equal to 0 means that the motion vector difference is positive; mv_sign equal to 1 means that the motion vector difference is negative.

It is a requirement of bitstream conformance that whenever assign_mv returns, the function is_mv_valid( Mv[0] ) would return 1, where is_mv_valid is defined as:

is_mv_valid( mv ) {    if ( !use_intrabc ) {        return 1    }    bw = Block_Width[ MiSize ]    bh = Block_Height[ MiSize ]    bottomBorder = (mv[ 0 ] & 7) != 0 ? 1 : 0    rightBorder = (mv[ 1 ] & 7) != 0 ? 1 : 0    deltaRow = mv[ 0 ] >> 3    deltaCol = mv[ 1 ] >> 3    srcTopEdge = MiRow * MI_SIZE + deltaRow    srcLeftEdge = MiCol * MI_SIZE + deltaCol    srcBottomEdge = srcTopEdge + bh + bottomBorder    srcRightEdge = srcLeftEdge + bw + rightBorder    if (HasChroma) {        srcLeftEdge = ChromaMiCol * MI_SIZE + deltaCol        srcTopEdge = ChromaMiRow * MI_SIZE + deltaRow    }    if ( srcTopEdge < MiRowStart * MI_SIZE ||         srcLeftEdge < MiColStart * MI_SIZE ||         srcBottomEdge > MiRowEnd * MI_SIZE ||         srcRightEdge > MiColEnd * MI_SIZE ) {        return 0    }    if ( allow_local_intrabc ) {        tmpCol = MiCol        tmpRow = MiRow        if ( (!enable_sdp || !FrameIsIntra) && HasChroma) {            bw = Block_Width[ ChromaMiSize ]            tmpCol = ChromaMiCol            bh = Block_Height[ ChromaMiSize ]            tmpRow = ChromaMiRow        }        tmpTopEdge = tmpRow * MI_SIZE + deltaRow        tmpLeftEdge = tmpCol * MI_SIZE + deltaCol        tmpBottomEdge = tmpTopEdge + bh - 1 + bottomBorder        tmpRightEdge = tmpLeftEdge + bw - 1 + rightBorder        if (check_valid_local_ibc(tmpLeftEdge, tmpTopEdge) &&            check_valid_local_ibc(tmpRightEdge, tmpBottomEdge)) {            return 1        }    }    if (!allow_global_intrabc) {        return 0    }    sbH = Block_Height[ SbSize ]    activeSbRow = (MiRow * MI_SIZE) / sbH    activeSb64Col = (MiCol * MI_SIZE) >> 6    srcSbRow = (srcBottomEdge - 1) / sbH    srcSb64Col = (srcRightEdge - 1) >> 6    activeSb64Row = (MiRow * MI_SIZE) >> 6    isBottomLeft = (activeSb64Col & 1) == 0 && (activeSb64Row & 1) == 1    if (AllowExtraIBCRange && isBottomLeft) {        sb64Residual = -1    } else {        sb64Residual = 0    }    totalSb64PerRow = ((MiColEnd - MiColStart - 1) >> 4) + 1    activeSb64 = activeSbRow * totalSb64PerRow + activeSb64Col    srcSb64 = srcSbRow * totalSb64PerRow + srcSb64Col    if ( srcSb64 >= activeSb64 - INTRABC_DELAY_SB64 - sb64Residual) {        return 0    }    gradient = INTRABC_DELAY_SB64 + (Block_Width[ SbSize ] / 64)    wfOffset = gradient * (activeSbRow - srcSbRow)    if ( srcSbRow > activeSbRow ||         srcSb64Col >= activeSb64Col - INTRABC_DELAY_SB64 +                       wfOffset - sb64Residual ) {        return 0    }    return 1}

Note: The purpose of this function is to limit the maximum size of motion vectors and also, if use_intrabc is equal to 1, to additionally constrain the motion vector in order that the data is fetched from parts of the tile that have already been decoded.

Note: The constraints when allow_local_intrabc is equal to 1 are intended to allow an implementation that stores the four most recently decoded 64x64 regions of the image in a cache.

The function check_valid_local_ibc (which checks if a location is within the allowed intra block copy buffers) is specified as:

check_valid_local_ibc( x, y ) {    if ( (!enable_sdp || !FrameIsIntra) && HasChroma) {        actCol = ChromaMiCol        actRow = ChromaMiRow    } else {        actCol = MiCol        actRow = MiRow    }    if (x >= actCol * MI_SIZE && y >= actRow * MI_SIZE) {        return 0    }    if ( !IBCCoded[y >> MI_SIZE_LOG2][x >> MI_SIZE_LOG2] ) {        return 0    }    bufCol = x >> IBC_BUFFER_SIZE_LOG2    bufRow = y >> IBC_BUFFER_SIZE_LOG2    bufIdx = ibc_buffer_index(bufRow, bufCol)    inCurrent = bufCol == IBCBufferCurCol && bufRow == IBCBufferCurRow    if (!inCurrent) {        if ( !IBCBufferValid[bufIdx] ||             bufCol != IBCBufferCol[bufIdx] ||             bufRow != IBCBufferRow[bufIdx] ) {            return 0        }    }    if ( bufIdx == ibc_buffer_index(IBCBufferCurRow, IBCBufferCurCol) ) {        if (!inCurrent) {            coloY = (y & (IBC_BUFFER_SIZE - 1)) |                     (IBCBufferCurRow << IBC_BUFFER_SIZE_LOG2)            coloX = (x & (IBC_BUFFER_SIZE - 1)) |                     (IBCBufferCurCol << IBC_BUFFER_SIZE_LOG2)            if ( IBCCoded[ coloY >> MI_SIZE_LOG2 ][ coloX >> MI_SIZE_LOG2 ] ) {                return 0            }        }    }    return 1}

6.19.34. Read motion mode semantics

use_extend_warp equal to 1 means that EXTENDWARP is used.

use_local_warp equal to 1 means that LOCALWARP is used.

6.19.35. Read inter intra semantics

inter_intra equal to 1 specifies that an inter prediction should be blended with an intra prediction.

warp_inter_intra equal to 1 specifies that an inter prediction should be blended with an intra prediction for a WARPMV block.

interintra_mode specifies the type of intra prediction to be used:

interintra_mode Name of interintra_mode
0 II_DC_PRED
1 II_V_PRED
2 II_H_PRED
3 II_SMOOTH_PRED

wedge_interintra equal to 1 specifies that wedge blending should be used. wedge_interintra equal to 0 specifies that intra blending should be used.

6.19.36. Read compound type semantics

comp_group_idx equal to 0 indicates that the compound_type syntax element is not present and that an averaging scheme should be used for blending. comp_group_idx equal to 1 indicates that the compound_type syntax element is present.

compound_type specifies how the two predictions should be blended together:

compound_type Name of compound_type
0 COMPOUND_WEDGE
1 COMPOUND_DIFFWTD
2 COMPOUND_AVERAGE
3 COMPOUND_INTRA

Note: COMPOUND_AVERAGE and COMPOUND_INTRA cannot be directly signaled with the compound_type syntax element but are inferred from other syntax elements.

wedge_sign specifies the sign of the wedge blend.

mask_type specifies the type of mask to be used during blending:

mask_type Name of mask_type
0 UNIFORM_45
1 UNIFORM_45_INV

6.19.37. Read refine mv semantics

use_refinemv indicates that motion vector refinement should be used for this block.

DecidedAgainstRefinemv indicates that use_refinemv was originally set to 1 in the bitstream, but later cleared due to incompatible compound weights. In this case the reference code does not apply motion vector refinement, but uses a different interpolation filter.

6.19.38. Read wedge mode semantics

wedge_quad and wedge_angle are used to specify the wedge angle.

wedge_dist1 specifies the distance to the wedge for angles where a distance of 0 is allowed.

wedge_dist2 specifies the distance to the wedge for angles where a distance of 0 is not allowed.

wedgeAngle gives the angle of the wedge:

wedgeAngle Name of wedgeAngle
0 WEDGE_0
1 WEDGE_14
2 WEDGE_27
3 WEDGE_45
4 WEDGE_63
5 WEDGE_90
6 WEDGE_117
7 WEDGE_135
8 WEDGE_153
9 WEDGE_166
10 WEDGE_180
11 WEDGE_194
12 WEDGE_207
13 WEDGE_225
14 WEDGE_243
15 WEDGE_270
16 WEDGE_297
17 WEDGE_315
18 WEDGE_333
19 WEDGE_346

6.19.39. MV semantics

MvCtx is used to determine which CDFs to use for the motion vector syntax elements.

mv_joint specifies which components of the motion vector difference are non-zero:

mv_joint Name of mv_joint Changes row Changes col
0 MV_JOINT_ZERO No No
1 MV_JOINT_HNZVZ No Yes
2 MV_JOINT_HZVNZ Yes No
3 MV_JOINT_HNZVNZ Yes Yes

The motion vector difference is added to the PredMvs to compute the final motion vector in BlockMvs.

shell_set, shell_class, and joint_shell_last_two_classes are used to specify the class of the motion vector difference. A higher class means that the motion vector difference represents a larger update.

shell_offset_low_class is used to compute shellClassOffset when shell_class is equal to 0 or 1.

shell_offset_class2 and shell_offset_class2_high are used to compute shellClassOffset when shell_class is equal to 2.

shell_offset_other_class is used to compute shellClassOffset when shell_class is greater than 2.

col_mv_greater is used as part of a truncated unary coding for the variable col.

col_remainder is used to increment the variable col if the maximum unary value has been reached.

shellIndex is the sum of both motion vector components.

col_mv_index specifies which component of the motion vector will be computed based on the known sum. The other component will be set equal to the variable col.

6.19.40. MV component semantics

amvd_index is used to compute the size of the motion vector difference via a table lookup.

6.19.41. Compute prediction semantics

The prediction for inter and inter intra blocks is triggered within compute_prediction. However, intra prediction is done at the transform block granularity so predict_intra is also called from transform_block.

predW and predH are variables containing the smallest size that can be used for inter prediction. (This size may be increased for chroma blocks if not all blocks use inter prediction.)

predict_inter is a function call that indicates the conceptual point where inter prediction happens. When this function is called, the inter prediction process specified in § 7.12.3 Inter prediction process is invoked.

predict_intra is a function call that indicates the conceptual point where intra prediction happens. When this function is called, the intra prediction process specified in § 7.12.2 Intra prediction process is invoked.

wedge_mask is a function call that indicates the wedge mask process specified in § 7.12.3.27 Wedge mask process is invoked.

intra_mode_variant_mask is a function call that indicates the wedge mask process specified in § 7.12.3.29 Intra mode variant mask process is invoked.

mask_blend is a function call that indicates the wedge mask process specified in § 7.12.3.30 Mask blend process is invoked.

Note: The predict_inter, predict_intra, wedge_mask, intra_mode_variant_mask, mask_blend functions do not affect the syntax decode process. predict_inter does affect the SubMvs array which is used by the motion vector prediction process, but motion vector prediction is not required for syntax decode.

Note: The chroma residual block size is always at least 4 in width and height. This means that no transform width or height smaller than 4 is required. As such, a chroma residual may actually cover several luma blocks.

6.19.42. Residual semantics

The residual consists of a number of transform blocks.

If the block is wider or higher than 64 luma samples, then the residual is split into 64 by 64 chunks.

6.19.43. Transform block semantics

reconstruct is a function call that indicates the conceptual point where inverse transform and reconstruction happens. When this function is called, the reconstruction process specified in § 7.13.3 Reconstruct process is invoked.

predict_palette is a function call that indicates the conceptual point where palette prediction happens. When this function is called, the palette prediction process specified in § 7.12.4 Palette prediction process is invoked.

predict_chroma_from_luma is a function call that indicates the conceptual point where predicting chroma from luma happens. When this function is called, the predict chroma from luma process specified in § 7.12.5 Predict chroma from luma process is invoked.

LoopfilterTxSizes is an array that stores the transform size for each plane and position for use in loop filtering. LoopfilterTxSizes[ plane ][ row ][ col ] stores the transform size where row and col are in units of 4x4 samples.

Note: The transform size is always equal for planes 1 and 2.

6.19.44. Coefficients semantics

TxTypes is an array which stores at a 4x4 luma sample granularity the transform type to be used.

Note: The transform type is only read for luma transform blocks, the chroma uses the transform type for a corresponding luma block. Chroma blocks will only use transform types that have been written for the current residual block.

Quant is an array storing the quantised coefficients for the current transform block.

It is a requirement of bitstream conformance that the values written into Quant are greater than -1 << 20 and less than 1 << 20.

QuantSign is an array storing the sign of the quantised coefficients for the current transform block, or zero for zero coefficients.

Note: It is possible for QuantSign[pos] to be not equal to zero when Quant[pos] is equal to zero as the quantised coefficients can wrap around.

all_zero equal to 1 specifies that all coefficients are zero.

eob_extra and eob_extra_bit specify the position of the last non-zero coefficient by being used to compute the variable eob.

cctx_type specifies the angle for the cross component transform:

cctx_type Name of cctx_type
0 CCTX_NONE
1 CCTX_45
2 CCTX_30
3 CCTX_60
4 CCTX_MINUS45
5 CCTX_MINUS30
6 CCTX_MINUS60

eob_pt_16, eob_pt_32, eob_pt_64, eob_pt_128, eob_pt_256, eob_pt_512, eob_pt_1024, eob_pt_256_extra, eob_pt_512_extra, eob_pt_1024_extra: syntax elements used to compute eob.

It is a requirement of bitstream conformance that eob_pt_512_extra is not equal to 3.

eob is a variable that indicates the index of the end of block. This index is equal to one plus the index of the last non-zero coefficient.

coeff_base_eob is a syntax element used to compute the base level of the last non-zero coefficient.

Note: The base level is set to coeff_base_eob plus 1 because this coefficient is known to be non-zero.

coeff_base_bob is a syntax element used to compute the base level of the first non-zero coefficient.

coeff_base specifies the base level of a coefficient.

coeff_base_idtx specifies the base level of a coefficient when using forward skip coding.

idtx_sign specifies the sign of the coefficients when using forward skip coding.

dc_sign specifies the sign of the DC coefficient.

dc_sign_horz_vert specifies the sign of the DC coefficients when using horizontal or vertical transform classes.

sign_bit specifies the sign of a non-zero AC coefficient.

coeff_br specifies an increment to the coefficient.

coeff_br_idtx specifies an increment to the coefficient when using forward skip coding.

AboveLevelContext and LeftLevelContext are arrays that store at a 4 sample granularity the cumulative sum of coefficient levels.

AboveDcContext and LeftDcContext are arrays that store at a 4 sample granularity 2 bits signaling the sign of the DC coefficient (zero being counted as a separate sign).

6.19.45. Read quantized coefficient semantics

q_length_bit is used to specify the prefix of the extra bits required to code the coefficient.

golomb_length_bit is used to compute the number of extra bits required to code the coefficient.

If length is equal to 20, it is a requirement of bitstream conformance that golomb_length_bit is equal to 1.

coeff_rem specifies the values of the extra bits.

6.19.46. Read CFL alphas semantics

cfl_mhccp and cfl_index specify how the chroma from luma parameters are prepared:

cfl_index Name of cfl_index
0 CFL_EXPLICIT
1 CFL_DERIVED_ALPHA
2 CFL_MULTI

cfl_mh_dir specifies a direction used by MHCCP.

cfl_alpha_signs contains the sign of the alpha values for U and V packed together into a single syntax element with 8 possible values. (The combination of two zero signs is prohibited as it is redundant with DC intra prediction.)

cfl_alpha_signs Name of signU Name of signV
0 CFL_SIGN_ZERO CFL_SIGN_NEG
1 CFL_SIGN_ZERO CFL_SIGN_POS
2 CFL_SIGN_NEG CFL_SIGN_ZERO
3 CFL_SIGN_NEG CFL_SIGN_NEG
4 CFL_SIGN_NEG CFL_SIGN_POS
5 CFL_SIGN_POS CFL_SIGN_ZERO
6 CFL_SIGN_POS CFL_SIGN_NEG
7 CFL_SIGN_POS CFL_SIGN_POS

signU contains the sign of the alpha value for the U component:

signU Name of signU
0 CFL_SIGN_ZERO
1 CFL_SIGN_NEG
2 CFL_SIGN_POS

signV contains the sign of the alpha value for the V component with the same interpretation as for signU.

cfl_alpha_u contains the absolute value of alpha minus one for the U component.

cfl_alpha_v contains the absolute value of alpha minus one for the V component.

CflAlphaU contains the signed value of the alpha component for the U component.

CflAlphaV contains the signed value of the alpha component for the V component.

6.19.47. Palette mode info semantics

has_palette_y is a boolean value specifying whether a palette is encoded for the Y plane.

palette_size_y_minus_2 is used to compute PaletteSizeY.

PaletteSizeY is a variable holding the Y plane palette size.

use_palette_color_cache_y, if equal to 1, indicates that for a particular palette entry in the luma palette, the cached entry should be used.

palette_colors_y is an array holding the Y plane palette colors.

palette_num_extra_bits_y is used to calculate the number of bits used to store each palette delta value for the luma palette.

palette_delta_y is a delta value for the luma palette.

6.19.48. Transform type semantics

set specifies the transform set.

is_inter set Name of transform set
Don’t care 0 TX_SET_DCTONLY
Don’t care 1 TX_SET_WIDE_64
Don’t care 2 TX_SET_HIGH_64
Don’t care 3 TX_SET_WIDE_32
Don’t care 4 TX_SET_HIGH_32
0 5 TX_SET_INTRA_1
0 6 TX_SET_INTRA_2
1 5 TX_SET_INTER_1
1 6 TX_SET_INTER_2
1 7 TX_SET_DCT_IDTX
1 8 TX_SET_DCT_IDTX_IDDCT

lossless_inter_tx_type is used to specify the transform type for 4 by 4 lossless inter transform blocks.

is_long_side_dct specifies if the long side of a block should use a DCT transform.

inter_tx_type and inter_tx_type_offset specify the transform type for inter blocks.

intra_tx_type is used in the computation of the transform type for intra blocks. The transform type depends on intra_tx_type and the intra direction for the block.

sec_tx_type specifies the secondary transform type.

most_probable_stx_set is used to compute the kernel used for the secondary transform.

6.19.49. Palette tokens semantics

palette_direction equal to 0 specifies that the palette is read row by row. palette_direction equal to 1 specifies that the palette is read column by column.

identity_row_y equal to 0 specifies that each sample is coded individually. identity_row_y equal to 1 specifies that each line of luma samples in the block contains a constant color. identity_row_y equal to 2 specifies that each line is copied from the previous line.

It is a requirement of bitstream conformance that i is greater than 0 if identity_row_y is equal to 2.

Note: When palette direction is equal to 0, the lines mentioned in identity_row_y refer to rows. When direction is equal to 1, the lines refer to columns.

color_index_map_y holds the index in palette_colors_y for the block’s Y plane top left sample.

palette_color_idx_y holds the index in ColorOrder for a sample in the block’s Y plane.

6.19.50. Palette color context function semantics

ColorOrder is an array holding the mapping from an encoded index to the palette. ColorOrder is ranked in order of frequency of occurrence of each color in the neighborhood of the current block, weighted by closeness to the current block.

ColorContextHash is a variable derived from the distribution of colors in the neighborhood of the current block, which is used to determine the probability context used to decode palette_color_idx_y and palette_color_idx_uv.

6.19.51. Read CDEF semantics

cdef_idx specifies which CDEF filtering parameters should be used for a particular 64 by 64 block. A value of -1 means that CDEF is disabled for that block.

cdef_index0 specifies that cdef_idx is equal to 0.

cdef_index_minus1 plus 1 specifies the value of cdef_idx.

6.19.52. Read CCSO semantics

ccso_blk specifies if CCSO is enabled for a particular plane and CCSO block.

6.19.53. Read GDF semantics

use_gdf specifies if GDF is enabled for a particular block.

6.19.54. Read loop restoration semantics

This contains syntax for any new restoration units that are covered.

6.19.55. Read loop restoration unit semantics

use_wiener_ns specifies if the non-separable Wiener filter should be used.

use_pc_wiener specifies if the pixel classified filter should be used.

flex_restoration_type equal to 1 specifies if a particular enabled tool should be used.

6.19.56. Read Wiener NS semantics

matchIndices is used to determine the reference values for the Wiener coefficients.

use_alt_group equal to 0 specifies that the predicted group is used. use_alt_group equal to 1 specifies that a different group to the predicted group is used.

group_bit is used when there is more than one alternative group.

merged_param specifies if a previous set of parameters should be used for loop restoration.

use_bank indicates that a particular bank of parameters should be used for loop restoration.

wiener_ns_length is used to compute the number of coefficients to read.

wiener_ns_uv_sym specifies if the chroma filter is symmetric.

wiener_ns_base is used to compute the base level of a coefficient.

wiener_ns_rem is used to provide an increment for a coefficient.

subexp_more_bools equal to 0 specifies that the parameter is in the range mk to mk+a-1. subexp_more_bools equal to 1 specifies that the parameter is greater than mk+a-1.

subexp_unif_bools specifies the value of the parameter minus mk.

subexp_bools specifies the value of the parameter minus mk.