Skip to content

Latest commit

 

History

History
4013 lines (3664 loc) · 129 KB

06.bitstream.syntax.md

File metadata and controls

4013 lines (3664 loc) · 129 KB

Bitstream Syntax

This section presents the bitstream syntax in a tabular form. The meaning of each of the syntax elements is presented in [Section 6][].

OBU Syntax

open_bitstream_unit( sz ) {
    obu_header()
    sz -= 1 + obu_extension_flag
    if ( obu_type == OBU_SEQUENCE_HEADER )
        sequence_header_obu()
    else if ( obu_type == OBU_TD )
        temporal_delimiter_obu()
    else if ( obu_type == OBU_FRAME_HEADER )
        frame_header_obu( )
    else if ( obu_type == OBU_TILE_GROUP )
        tile_group_obu( sz )
    else if ( obu_type == OBU_METADATA )
        metadata_obu( sz )
    else if ( obu_type == OBU_PADDING )
        padding_obu()
    else
        reserved_obu( sz )
    trailing_bits()
}

{:.syntax }

OBU Header Syntax

obu_header() {
    @@obu_forbidden_bit                                                        f(1)
    @@obu_type                                                                 f(4)
    @@obu_reserved_2bits                                                       f(2)
    @@obu_extension_flag                                                       f(1)
    if ( obu_extension_flag == 1 )
        obu_extension_header()
}    

{:.syntax }

OBU Extension Header Syntax

obu_extension_header() {
    @@temporal_id                                                              f(3)
    @@enhancement_id                                                           f(2)
    @@extension_header_reserved_3bits                                          f(3)
}    

{:.syntax }

Trailing Bits Syntax

trailing_bits( ) {
    while ( get_position( ) & 7 )
        @@zero_bit                                                             f(1)
}

{:.syntax }

Reserved OBU Syntax

reserved_obu( sz ) {
    for ( i = 0; i < sz; i++ )
        @@reserved_obu_payload_byte                                            f(8)
}    

{:.syntax }

Sequence Header OBU Syntax

sequence_header_obu( ) {
    @@profile_low_bit                                                          f(1)
    @@profile_high_bit                                                         f(1)
    Profile = (profile_high_bit << 1) + profile_low_bit
    @@level[ 0 ]                                                               f(4)
    @@enhancement_layers_cnt                                                   f(2)
    for ( i = 1; i <= enhancement_layers_cnt; i++ )
        @@level[ i ]                                                           f(4)
    @@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)
    @@frame_id_numbers_present_flag                                            f(1)
    if ( frame_id_numbers_present_flag ) {    
        @@delta_frame_id_length_minus2                                         f(4)
        @@frame_id_length_minus1                                               f(3)
    }    
    color_config( )
    @@timing_info_present_flag                                                 f(1)
    if ( timing_info_present_flag ) {
        timing_info( )
    }
    @@film_grain_params_present                                                f(1)
}    

{:.syntax }

Color Config Syntax

color_config( ) {
    @@high_bitdepth                                                            f(1)
    if ( Profile >= 2 && high_bitdepth ) {
        @@twelve_bit                                                           f(1)
        BitDepth = twelve_bit ? 12 : 10
    } else {
        BitDepth = high_bitdepth ? 10 : 8
    }
    if ( Profile == 1 ) {
        monochrome = 0
    } else {
        @@monochrome                                                           f(1)
    }
    NumPlanes = monochrome ? 1 : 3
    @@color_description_present_flag                                           f(1)
    if ( color_description_present_flag ) {
        @@color_primaries                                                      f(8)
        @@transfer_characteristics                                             f(8)
        @@matrix_coefficients                                                  f(8)
    } else {
        color_primaries = CP_UNSPECIFIED
        transfer_characteristics = TC_UNSPECIFIED
        matrix_coefficients = MC_UNSPECIFIED
    }
    if ( monochrome ) {
        color_range = 1
        subsampling_x = 1
        subsampling_y = 1
        chroma_sample_position = CSP_UNKNOWN
    } else if ( color_primaries == CP_BT_709 &&
                transfer_characteristics == TC_SRGB &&
                matrix_coefficients == MC_IDENTITY ) {
        subsampling_x = 0
        subsampling_y = 0
    } else {
        @@color_range                                                          f(1)
        if ( Profile == 0 ) {
            subsampling_x = 1
            subsampling_y = 1
        } else if ( Profile == 1 ) {
            subsampling_x = 0
            subsampling_y = 0
        } else {
            if ( BitDepth == 12 ) {
                @@subsampling_x                                                f(1)
                if ( subsampling_x )
                    @@subsampling_y                                            f(1)
                else
                    subsampling_y = 0
            } else {
                subsampling_x = 1
                subsampling_y = 0
            }
        } 
        if (subsampling_x && subsampling_y) {
            @@chroma_sample_position                                           f(2)
        }
    }
    @@separate_uv_delta_q                                                      f(1)
}

{:.syntax }

Timing Info Syntax

timing_info( ) {
    @@num_units_in_tick                                                        f(32)
    @@time_scale                                                               f(32)
    @@equal_picture_interval                                                   f(1)
    if (equal_picture_interval)
       @@num_ticks_per_picture_minus1                                          uvlc()
}

{:.syntax }

Temporal Delimiter OBU Syntax

temporal_delimiter_obu( ) {
    SeenFrameHeader = 0
}

{:.syntax }

Note: The temporal delimiter has an empty payload. {:.alert .alert-info }

Padding OBU Syntax

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

{:.syntax }

Metadata OBU Syntax

metadata_obu( sz ) {
    @@metadata_type                                                            f(16)
    if ( metadata_type == METADATA_TYPE_PRIVATE_DATA )
        metadata_private_data( sz − 2 )
    else if ( metadata_type == METADATA_TYPE_HDR_CLL ) 
        metadata_hdr_cll( sz − 2 )
    else if ( metadata_type == METADATA_TYPE_HDR_MDCV )
        metadata_hdr_mdcv( sz − 2 )
    else if ( metadata_type == METADATA_TYPE_SCALABILITY )
        metadata_scalability( sz − 2 )
}

{:.syntax }

Metadata Private Data Syntax

metadata_private_data( sz ) {
    for ( i = 0; i < sz; i++ )
        @@metadata_private_data_payload_byte[ i ]                              f(8)
}

{:.syntax }

Metadata High Dynamic Range Content Light Level Syntax

metadata_hdr_cll( sz ) {
    @@max_cll                                                                  f(16)
    @@max_fall                                                                 f(16)
}

{:.syntax }

Metadata High Dynamic Range Mastering Display Color Volume Syntax

metadata_hdr_mdcv( sz ) {
    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)
}

{:.syntax }

Metadata Scalability Syntax

metadata_scalability( sz ) {
    @@scalability_mode_idc                                                     f(8)
    if (scalability_mode_idc == SCALABILITY_SS)
        scalability_structure(  sz – 1 )
}

{:.syntax }

Scalability structure syntax

scalability_structure( sz ) {
    @@enhancement_layers_cnt                                                   f(2)
    @@enhancement_layer_dimensions_present_flag                                f(1)
    @@enhancement_layer_description_present_flag                               f(1)
    @@temporal_group_description_present_flag                                  f(1)
    @@scalability_structure_reserved_3bits                                     f(3)
    if ( enhancement_layer_dimensions_present_flag ) {
        for ( i = 0; i <= enhancement_layers_cnt ; i++ ) {
            @@enhancement_layer_max_width[ i ]                                f(16)
            @@enhancement_layer_max_height[ i ]                                f(16)
        }
    }
    if ( enhancement_layer_description_present_flag ) {
        for ( i = 0; i <= enhancement_layers_cnt; i++ )
            @@enhancement_layer_ref_id[ i ]                                    f(8)
    }
    if (temporal_group_description_present_flag) {
        @@temporal_group_size                                                  f(8)
        for ( i = 0; i < temporal_group_size; i++ ) {
            @@temporal_group_temporal_id[ i ]                                  f(3)
            @@temporal_group_switching_up_point_flag[ i ]                      f(1)
            @@temporal_group_ref_cnt[ i ]                                      f(2)
            @@temporal_group_reserved_2bits[ i ]                               f(2)
            for ( j = 0; j < temporal_group_ref_cnt[ i ]; j++ ) {
                @@temporal_group_ref_pic_diff[ i ][ j ]                        f(8)
            }
        }
    }
}

{:.syntax }

Frame Header OBU Syntax

frame_header_obu( ) {
    if ( SeenFrameHeader == 1 ) {
        frame_header_copy()
    } else {
        SeenFrameHeader = 1
        uncompressed_header( )
        trailing_bits( )
        if ( show_existing_frame ) {
            decode_frame( )
            SeenFrameHeader = 0
        } else {
            TileNum = 0
            MaxTileSize = 0
            SeenFrameHeader = 1
        }
    }
}

{:.syntax }

Uncompressed Header Syntax

uncompressed_header( ) {
    idLen = frame_id_length_minus1 + delta_frame_id_length_minus2 + 3
    @@show_existing_frame                                                      f(1)
    if ( show_existing_frame == 1 ) {
        @@frame_to_show_map_idx                                                f(3)
        refresh_frame_flags = 0
        for ( i = 0; i < FRAME_LF_COUNT; i++ )
            loop_filter_level[ i ] = 0
        if (frame_id_numbers_present_flag) {
            @@display_frame_id                                                 f(idLen)
        }
        CurrentVideoFrame += 1
        film_grain_params( )
        return
    }
    @@frame_type                                                               f(2)
    @@show_frame                                                               f(1)
    @@error_resilient_mode                                                     f(1)
    if ( frame_id_numbers_present_flag ) {
        @@current_frame_id                                                     f(idLen)
    }
    @@frame_size_override_flag                                                 f(1)
    FrameIsIntra = (frame_type == INTRA_ONLY_FRAME || 
                    frame_type == KEY_FRAME)
    allow_intrabc = 0
    force_integer_mv = 1
    allow_high_precision_mv = 0
    can_use_previous = 0
    if ( frame_type == KEY_FRAME ) {
        frame_size( )
        render_size( )
        @@use_128x128_superblock                                               f(1)
        @@allow_screen_content_tools                                           f(1)
        if (allow_screen_content_tools) {
            @@allow_intrabc                                                    f(1)
        }
        refresh_frame_flags = 0xFF
        CurrentVideoFrame = 0
        if (allow_screen_content_tools) {
            @@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 = 0
        }
    } else {
        if ( frame_type == INTRA_ONLY_FRAME ) {
            @@refresh_frame_flags                                              f(8)
            frame_size( )
            render_size( )
            @@use_128x128_superblock                                           f(1)
            @@allow_screen_content_tools                                       f(1)
            if (allow_screen_content_tools) {
                @@allow_intrabc                                                f(1)
            }
        } else {
            if (frame_type == SWITCH_FRAME ) {
                refresh_frame_flags = 0xFF
            } else {
                @@refresh_frame_flags                                          f(8)
            }
            for( i = 0; i < REFS_PER_FRAME; i++ ) {
                @@ref_frame_idx[ i ]                                           f(3)
                if (frame_id_numbers_present_flag) {
                    n = delta_frame_id_length_minus2 + 2
                    @@delta_frame_id_minus1                                    f(n)
                    DeltaFrameId = delta_frame_id_minus1 + 1
                    RefFrameId = ((current_frame_id -
                                  DeltaFrameId ) % (1 << idLen))
                }
            }
            if ( frame_size_override_flag && !error_resilient_mode ) {
                frame_size_with_refs( )
            } else {
                frame_size( )
                render_size( )
            }
            if ( seq_force_integer_mv == SELECT_INTEGER_MV )
                @@force_integer_mv                                             f(1)
            else
                force_integer_mv = seq_force_integer_mv
            if ( force_integer_mv ) {
                allow_high_precision_mv = 0
            } else {
                @@allow_high_precision_mv                                      f(1)
            }
            read_interpolation_filter( )
            if ( error_resilient_mode ) {
                can_use_previous = 0
            } else {
                @@can_use_previous                                             f(1)
            }
        }
    }
    if (show_frame == 0) {
        @@frame_offset_update                                                  f(5)
        OrderHint = CurrentVideoFrame + frame_offset_update
    } else {
        OrderHint = CurrentVideoFrame
        CurrentVideoFrame += 1
    }
    if ( !FrameIsIntra ) {
        for( i = 0; i < REFS_PER_FRAME; i++ ) {
            refFrame = LAST_FRAME + i
            hint = RefOrderHint[ ref_frame_idx[ i ] ]
            OrderHints[ refFrame ] = hint
            if (frame_type == SWITCH_FRAME ) {
                RefFrameSignBias[ refFrame ] = 0
            } else {
                RefFrameSignBias[ refFrame ] = hint > OrderHint
            }
        }
    }
    if ( error_resilient_mode ) {
        frame_parallel_decoding_mode = 1
    } else {
        @@frame_parallel_decoding_mode                                         f(1)
    }
    if ( FrameIsIntra || error_resilient_mode ) {
        setup_past_independence ( )
    } else {
        load_cdfs( ref_frame_idx[ 0 ] )
        load_previous( )
    }
    tile_info( )
    loop_filter_params( )
    quantization_params( )
    segmentation_params( )
    delta_q_params( )
    delta_lf_params( )
    AllLossless = 1
    for ( segmentId = 0; segmentId < MAX_SEGMENTS; segmentId++ ) {
        qindex = get_qindex( 1, segmentId )
        LosslessArray[ segmentId ] = qindex == 0 && DeltaQYDc == 0 &&
                                     DeltaQUAc == 0 && DeltaQUDc == 0 &&
                                     DeltaQVAc == 0 && DeltaQVDc == 0
        if ( !LosslessArray[ segmentId ] )
            AllLossless = 0
        if ( using_qmatrix ) {
            if ( LosslessArray[ segmentId ] ) {
                qmLevel = 15
            } else {
                qmLevel = min_qmlevel + ( base_q_idx * ( max_qmlevel - min_qmlevel + 1 ) ) / 256
            }
            SegQMLevel[ segmentId ] = qmLevel
        }
    }
    cdef_params( )
    lr_params( )
    read_tx_mode( )
    frame_reference_mode( )
    skip_mode_params( )
    @@reduced_tx_set                                                           f(1)
    global_motion_params( )
    if ( show_frame ) {
        film_grain_params( )
    }
}

{:.syntax }

Frame Size Syntax

frame_size( ) {
    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 = max_frame_width_minus_1 + 1
        FrameHeight = max_frame_height_minus_1 + 1
    }
    compute_image_size( )
    superres_params( )
}

{:.syntax }

Render Size Syntax

render_size( ) {
    @@render_and_frame_size_different                                          f(1)
    if ( render_and_frame_size_different == 1 ) {
        @@render_width_minus_1                                                 f(16)
        @@render_height_minus_1                                                f(16)
        RenderWidth = render_width_minus_1 + 1
        RenderHeight = render_height_minus_1 + 1
    } else {
        RenderWidth = FrameWidth
        RenderHeight = FrameHeight
    }
}

{:.syntax }

Frame Size with Refs Syntax

frame_size_with_refs( ) {
    for ( i = 0; i < REFS_PER_FRAME; i++ ) {
        @@found_ref                                                            f(1)
        if ( found_ref == 1 ) {
            FrameWidth = RefFrameWidth[ ref_frame_idx[ i ] ]
            FrameHeight = RefFrameHeight[ ref_frame_idx[ i ] ]
            RenderWidth = FrameWidth
            RenderHeight = FrameHeight
            break
        }
    }
    if ( found_ref == 0 ) {
        frame_size( )
        render_size( )
    } else {
        compute_image_size( )
        superres_params( )
    }
}

{:.syntax }

Superres Params Syntax

superres_params() {
  @@use_superres                                                               f(1)
  if (use_superres) {
    @@coded_denom                                                              f(SUPERRES_DENOM_BITS)
    SuperresDenom = coded_denom + SUPERRES_DENOM_MIN
  } else {
    SuperresDenom = SUPERRES_NUM
  }
  UpscaledWidth = FrameWidth
  FrameWidth = (UpscaledWidth * SUPERRES_NUM +
                (SuperresDenom / 2)) / SuperresDenom
}

{:.syntax }

Compute Image Size Function

compute_image_size( ) {
    MiCols = 2 * ( ( FrameWidth + 7 ) >> 3 )
    MiRows = 2 * ( ( FrameHeight + 7 ) >> 3 )
}

{:.syntax }

Interpolation Filter Syntax

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

{:.syntax }

Loop Filter Params Syntax

loop_filter_params( ) {
    if ( allow_intrabc ) {
        loop_filter_level[ 0 ] = 0
        loop_filter_level[ 1 ] = 0
        return
    }
    @@loop_filter_level[ 0 ]                                                   f(6)
    @@loop_filter_level[ 1 ]                                                   f(6)
    if ( NumPlanes > 1 ) {
        if ( loop_filter_level[ 0 ] || loop_filter_level[ 1 ] ) {
            @@loop_filter_level[ 2 ]                                           f(6)
            @@loop_filter_level[ 3 ]                                           f(6)
        }
    }
    @@loop_filter_sharpness                                                    f(3)
    @@loop_filter_delta_enabled                                                f(1)
    if ( loop_filter_delta_enabled == 1 ) {
        @@loop_filter_delta_update                                             f(1)
        if ( loop_filter_delta_update == 1 ) {
            for ( i = 0; i < TOTAL_REFS_PER_FRAME; i++ ) {
                @@update_ref_delta                                             f(1)
                if ( update_ref_delta == 1 )
                    @@loop_filter_ref_deltas[ i ]                              su(6)
            }
            for ( i = 0; i < 2; i++ ) {
                @@update_mode_delta                                            f(1)
                if ( update_mode_delta == 1 )
                    @@loop_filter_mode_deltas[ i ]                             su(6)
            }
        }
    }
}

{:.syntax }

Quantization Params Syntax

quantization_params( ) {
    @@base_q_idx                                                               f(8)
    DeltaQYDc = read_delta_q( )
    if ( NumPlanes > 1 ) {
        if ( separate_uv_delta_q )
          @@diff_uv_delta                                                      f(1)
        else
          diff_uv_delta = 0
        DeltaQUDc = read_delta_q( )
        DeltaQUAc = read_delta_q( )
        if ( diff_uv_delta ) {
          DeltaQVDc = read_delta_q( )
          DeltaQVAc = read_delta_q( )
        } else {
          DeltaQVDc = DeltaQUDc
          DeltaQVAc = DeltaQUAc
        }
    } else {
        DeltaQUDc = 0
        DeltaQUDc = 0
        DeltaQVAc = 0
        DeltaQVAc = 0
    }
    @@using_qmatrix                                                            f(1)
    if (using_qmatrix) {
        @@min_qmlevel                                                          f(4)
        @@max_qmlevel                                                          f(4)
    }
}

{:.syntax }

Delta Quantizer Syntax

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

{:.syntax }

Segmentation Params Syntax

segmentation_params( ) {
    @@segmentation_enabled                                                     f(1)
    SegIdPreSkip = 0
    if ( segmentation_enabled == 1 ) {
        if ( FrameIsIntra || error_resilient_mode ) {
            segmentation_update_map = 1
            segmentation_temporal_update = 0
        } else {
            @@segmentation_update_map                                          f(1)
            if ( segmentation_update_map == 1 )
                @@segmentation_temporal_update                                 f(1)
        }
        @@segmentation_update_data                                             f(1)
        if ( segmentation_update_data == 1 ) {
            for ( i = 0; i < MAX_SEGMENTS; i++ ) {
                for ( j = 0; j < SEG_LVL_MAX; j++ ) {
                    feature_value = 0
                    @@feature_enabled                                          f(1)
                    FeatureEnabled[ i ][ j ] = feature_enabled
                    if ( feature_enabled == 1 ) {
                        if ( j >= SEG_LVL_REF_FRAME ) {
                            SegIdPreSkip = 1
                        }
                        LastActiveSegId = i
                        bitsToRead = Segmentation_Feature_Bits[ j ]
                        limit = Segmentation_Feature_Max[ j ]
                        if ( Segmentation_Feature_Signed[ j ] == 1 ) {
                            feature_value                                      su(bitsToRead)
                            clippedValue = Clip3( -limit, limit, feature_value)
                        } else {
                            feature_value                                      f(bitsToRead)
                            clippedValue = Clip3( 0, limit, feature_value)
                        }
                    }
                    FeatureData[ i ][ j ] = clippedValue
                }
            }
        }
    }
}

{:.syntax }

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

Segmentation_Feature_Bits[ SEG_LVL_MAX ]   = { 8, 6, 6, 6, 6, 3, 0, 0 }
Segmentation_Feature_Signed[ SEG_LVL_MAX ] = { 1, 1, 1, 1, 1, 0, 0, 0 }
Segmentation_Feature_Max[ SEG_LVL_MAX ] = { 
  255, MAX_LOOP_FILTER, MAX_LOOP_FILTER, 
  MAX_LOOP_FILTER, MAX_LOOP_FILTER, 7,
  0, 0 }

Tile Info Syntax

tile_info ( ) {
    sbCols = use_128x128_superblock ? ( ( MiCols + 31 ) >> 5 ) : ( ( MiCols + 15 ) >> 4 )
    sbRows = use_128x128_superblock ? ( ( MiRows + 31 ) >> 5 ) : ( ( MiRows + 15 ) >> 4 )
    sbShift = use_128x128_superblock ? 5 : 4
    minLog2TileCols = tile_log2(MAX_TILE_WIDTH_SB, sbCols)
    maxLog2TileCols = tile_log2(1, Min(sbCols, MAX_TILE_COLS))
    maxLog2TileRows = tile_log2(1, Min(sbRows, MAX_TILE_ROWS))
    minLog2Tiles = Max(minLog2TileCols, 
                       tile_log2(MAX_TILE_AREA_SB, sbRows * sbCols))
                       
    @@uniform_tile_spacing_flag                                                f(1)
    if ( uniform_tile_spacing_flag ) {
        TileColsLog2 = minLog2TileCols
        while ( TileColsLog2 < maxLog2TileCols ) {
            @@increment_tile_cols_log2                                         f(1)
            if ( increment_tile_cols_log2 == 1 )
                TileColsLog2++
            else
                break
        }
        sizeSb = (sbCols + (1 << TileColsLog2) - 1) >> TileColsLog2
        i = 0
        for (startSb = 0; startSb < sbCols; startSb += sizeSb) {
          MiColStarts[ i ] = startSb << sbShift
          i += 1
        }
        MiColStarts[i] = MiCols
        TileCols = i
        
        minLog2TileRows = Max( minLog2Tiles - TileColsLog2, 0)
        maxTileHeightSb = sbRows >> minLog2TileRows
        TileRowsLog2 = minLog2TileRows
        while ( TileRowsLog2 < maxLog2TileRows ) {
            @@increment_tile_rows_log2                                         f(1)
            if ( increment_tile_rows_log2 == 1 )
                TileRowsLog2++
            else
                break
        }
        sizeSb = (sbCols + (1 << TileRowsLog2) - 1) >> TileRowsLog2
        i = 0
        for (startSb = 0; startSb < sbRows; startSb += sizeSb) {
          MiRowStarts[ i ] = startSb << sbShift
          i += 1
        }
        MiRowStarts[i] = MiRows
        TileRows = i
    } else {
        widestTileSb = 0
        startSb = 0
        for ( i = 0; startSb < sbCols && i < MAX_TILE_COLS; i++ ) {
            MiColStarts[ i ] = startSb << sbShift
            maxWidth = Min(sbCols - startSb, MAX_TILE_WIDTH_SB)
            sizeSb = decode_uniform(maxWidth) + 1
            widestTileSb = Max( sizeSb, widestTileSb )
            startSb += sizeSb
        }
        MiColStarts[i] = MiCols
        TileCols = i
        TileColsLog2 = tile_log2(1, TileCols)

        if ( minLog2Tiles > 0 )
            maxTileAreaSb = (sbRows * sbCols) >> (minLog2Tiles + 1)
        else
            maxTileAreaSb = sbRows * sbCols
        maxTileHeightSb = Max( maxTileAreaSb / widestTileSb, 1 )

        startSb = 0
        for ( i = 0; startSb < sbRows && i < MAX_TILE_ROWS; i++ ) {
            MiRowStarts[ i ] = startSb << sbShift
            maxHeight = Min(sbRows - startSb, maxTileHeightSb)
            sizeSb = decode_uniform(maxHeight) + 1
            startSb += sizeSb
        }
        MiRowStarts[ i ] = MiRows
        TileRows = i
        TileRowsLog2 = tile_log2(1, TileRows)
    }
    startMi = 0
    maxTileHeightMi = maxTileHeightSb << sbShift
    for (i = 0; i < TileRows; i++) {
      if (MiRowStarts[i+1] - startMi > maxTileHeightMi) {
        AllowDependentTileRow[i] = 0
        startMi = MiRowStarts[i+1]
      } else {
        AllowDependentTileRow[i] = 1
      }
    }
    AllowDependentTileRow[ 0 ] = 0
    if ( TileRowsLog2 > 0 )
        @@dependent_tiles                                                      f(1)
    else
        dependent_tiles = 0
    if ( TileColsLog2 > 0 )
        @@loop_filter_across_tiles_v                                           f(1)
    else
        loop_filter_across_tiles_v = 0
    if ( TileRowsLog2 > 0 )
        @@loop_filter_across_tiles_h                                           f(1)
    else
        loop_filter_across_tiles_h = 0
    @@tile_size_bytes_minus_1                                                  f(2)
    TileSizeBytes = tile_size_bytes_minus_1 + 1
}

{:.syntax }

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
}

{:.syntax }

Quantizer Index Delta Parameters Syntax

delta_q_params( ) {
    segmentQuantizerActive = 0
    for ( i = 0; i < MAX_SEGMENTS; i++ ) {
        if ( seg_feature_active_idx( i, SEG_LVL_ALT_Q ) ) {
            segmentQuantizerActive = 1
        }
    }
    delta_q_res = 0
    delta_q_present = 0
    if ( segmentQuantizerActive == 0 && base_q_idx > 0 ) {
        @@delta_q_present                                                      f(1)
    }
    if ( delta_q_present ) {
        @@delta_q_res                                                          f(2)
    }
}

{:.syntax }

Loop Filter Delta Parameters Syntax

delta_lf_params( ) {
    delta_lf_present = 0
    delta_lf_res = 0
    delta_lf_multi = 0
    if ( delta_q_present ) {
        @@delta_lf_present                                                     f(1)
        if ( delta_lf_present ) {
            @@delta_lf_res                                                     f(2)
            @@delta_lf_multi                                                   f(1)
        }
    }
}

{:.syntax }

CDEF Params Syntax

cdef_params( ) {
    if ( allow_intrabc || AllLossless ) {
        return
    }
    @@cdef_damping_minus_3                                                 f(2)
    CdefDamping = cdef_damping_minus_3 + 3
    @@cdef_bits                                                            f(2)
    for (i = 0; i < (1 << cdef_bits); i++) {
        @@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_strength[i]                                      f(4)
            @@cdef_uv_sec_strength[i]                                      f(2)
            if (cdef_uv_sec_strength[i] == 3)
                cdef_uv_sec_strength[i] += 1
        }
    }
}

{:.syntax }

Loop Restoration Params Syntax

lr_params( ) {
    if ( allow_intrabc ) {
        return
    }
    usesLr = 0
    usesChromaLr = 0
    for (i = 0; i < NumPlanes; i++) {
        @@lr_type                                                              f(2)
        FrameRestorationType[i] = Remap_Lr_Type[lr_type]
        if (FrameRestorationType[i] != RESTORE_NONE) {
            usesLr = 1
            if ( i > 0 ) {
                usesChromaLr = 1
            }
        }
    }
    if ( usesLr ) {
        @@lr_unit_shift                                                        f(1)
        if ( lr_unit_shift ) {
            @@lr_unit_extra_shift                                              f(1)
            lr_unit_shift += lr_unit_extra_shift
        }
        LoopRestorationSize[ 0 ] = RESTORATION_TILESIZE_MAX >> (2 - lr_unit_shift)
        if (subsampling_x && subsampling_y && usesChromaLr ) {
            @@lr_uv_shift                                                      f(1)
        } else {
            lr_uv_shift = 0
        }
        LoopRestorationSize[1] = LoopRestorationSize[0] >> lr_uv_shift
        LoopRestorationSize[2] = LoopRestorationSize[0] >> lr_uv_shift
    }
}

{:.syntax }

where Remap_Lr_Type is a constant lookup table specified as:

Remap_Lr_Type[4] = {
  RESTORE_NONE, RESTORE_SWITCHABLE, RESTORE_WIENER, RESTORE_SGRPROJ
}

TX Mode Syntax

read_tx_mode( ) {
    if ( AllLossless == 1 ) {
        TxMode = ONLY_4X4
    } else {
        @@tx_mode_select                                                       f(1)
        if ( tx_mode_select ) {
            TxMode = TX_MODE_SELECT
        } else {
            TxMode = TX_MODE_LARGEST
        }
    }
}

{:.syntax }

Skip Mode Params Syntax

skip_mode_params( ) {
    if ( FrameIsIntra || !reference_select ) {
        skipModeAllowed = 0
    } else {
        forwardIdx = -1
        backwardIdx = -1
        for( i = 0; i < REFS_PER_FRAME; i++ ) {
            refHint = RefOrderHint[ ref_frame_idx[ i ] ]
            if ( refHint < OrderHint ) {
                if ( forwardIdx < 0 || refHint > forwardHint ) {
                    forwardIdx = i
                    forwardHint = refHint
                }
            } else if ( refHint > OrderHint ) {
                if ( backwardIdx < 0 || refHint < backwardHint ) {
                    backwardIdx = i
                    backwardHint = refHint
                }
            }
        }
        if ( forwardIdx < 0 ) {
            skipModeAllowed = 0
        } else if ( backwardIdx >= 0 ) {
            skipModeAllowed = 1
            ForwardFrame = LAST_FRAME + forwardIdx
            BackwardFrame = LAST_FRAME + backwardIdx
        } else {
            for( i = 0; i < REFS_PER_FRAME; i++ ) {
                refHint = RefOrderHint[ ref_frame_idx[ i ] ]
                if ( refHint < forwardHint ) {
                    if ( backwardIdx < 0 || refHint > backwardHint ) {
                        backwardIdx = i
                        backwardHint = refHint
                    }
                }
            }
            if ( backwardIdx < 0 ) {
                skipModeAllowed = 0
            } else {
                skipModeAllowed = 1
                ForwardFrame = LAST_FRAME + Min(forwardIdx, backwardIdx)
                BackwardFrame = LAST_FRAME + Max(forwardIdx, backwardIdx)
            }
        }
    }
    if ( skipModeAllowed ) {
        @@skip_mode_present                                                    f(1)
    } else {
        skip_mode_present = 0
    }
}

{:.syntax }

Frame Reference Mode Syntax

frame_reference_mode( ) {
    compoundReferenceAllowed = 0
    if ( !FrameIsIntra ) {
        bufIdx = ref_frame_idx[0]
        refOffset0 = RefOrderHint[bufIdx]

        for (ref = LAST_FRAME + 1; ref <= ALTREF_FRAME; ref++) {
            bufIdx = ref_frame_idx[ref - LAST_FRAME]
            refOffset = RefOrderHint[bufIdx]
            if (refOffset != refOffset0) {
                compoundReferenceAllowed = 1
                break
            }
        }
    }
    if ( compoundReferenceAllowed ) {
        @@reference_select                                                     f(1)
    } else {
        reference_select = 0
    }
    if ( FrameIsIntra ) {
        allow_interintra_compound = 0
    } else {
        @@allow_interintra_compound                                            f(1)
    }
    if ( FrameIsIntra || !reference_select) {
        allow_masked_compound = 0
    } else {
        @@allow_masked_compound                                                f(1)
    }
}

{:.syntax }

Global Motion Params Syntax

global_motion_params( ) {
    if ( FrameIsIntra || error_resilient_mode || !can_use_previous) {
        for (ref = LAST_FRAME; ref <= ALTREF_FRAME; ref++) {
            gm_type[ref] = IDENTITY
            for ( i = 0; i < 6; i++ )
                gm_params[ ref ][ i ] = (i%3 == 2) ? 1 << WARPEDMODEL_PREC_BITS : 0
        }
    }
    if ( FrameIsIntra )
        return
    for (ref = LAST_FRAME; ref <= ALTREF_FRAME; ref++) {
        @@is_global                                                            f(1)
        if (is_global) {
            @@is_rot_zoom                                                      f(1)
            if (is_rot_zoom) {
                type = ROTZOOM
            } else {
                @@is_translation                                               f(1)
                type = is_translation ? TRANSLATION : AFFINE
            }
        } else {
            type = IDENTITY
        }
        gm_type[ref] = type

        if (type >= ROTZOOM) {
            read_global_param(type,ref,2)
            read_global_param(type,ref,3)
            if (type == AFFINE) {
                read_global_param(type,ref,4)
                read_global_param(type,ref,5)
            } else {
                gm_params[ref][4] = -gm_params[ref][3]
                gm_params[ref][5] = gm_params[ref][2]
            }
        }
        if (type >= TRANSLATION) {
            read_global_param(type,ref,0)
            read_global_param(type,ref,1)
        }
    }
}

{:.syntax }

Global Param Syntax

read_global_param( type, ref, idx ) {
    absBits = GM_ABS_ALPHA_BITS
    precBits = GM_ALPHA_PREC_BITS
    if (idx < 2) {
        if (type == TRANSLATION) {
            absBits = GM_ABS_TRANS_ONLY_BITS - !allow_high_precision_mv
            precBits = GM_TRANS_ONLY_PREC_BITS - !allow_high_precision_mv
        } else {
            absBits = GM_ABS_TRANS_BITS
            precBits = GM_TRANS_PREC_BITS
        }
    }
    precDiff = WARPEDMODEL_PREC_BITS - precBits
    round = (i % 3) == 2 ? (1 << WARPEDMODEL_PREC_BITS) : 0
    sub = (i % 3) == 2 ? (1 << precDiff) : 0
    mx = (1 << absBits)
    r = (gm_params[ref][idx] >> precDiff) - sub
    gm_params[ref][idx] = (decode_signed_subexp_with_ref( -mx, mx + 1, r ) << precDiff) + round
}

{:.syntax }

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 Zero MV process. {:.alert .alert-info }

Decode Signed Subexp With Ref Syntax

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

{:.syntax }

Decode Unsigned Subexp With Ref Syntax

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

{:.syntax }

Decode Subexp Syntax

decode_subexp( numSyms ) {
    i = 0
    mk = 0
    k = 3
    while (1) {
        b2 = i ? k + i - 1 : k
        a = 1 << b2
        if (numSyms <= mk + 3 * a) {
            return decode_uniform(numSyms - mk) + mk
        } else {
            @@subexp_more_bits                                                 f(1)
            if (subexp_more_bits) {
               i++
               mk += a
            } else {
               @@subexp_bits                                                   f(b2)
               return subexp_bits + mk
            }
        }
    }
}

{:.syntax }

Decode Uniform Syntax

decode_uniform( n ) {
    w = floor(log2(n)) + 1
    m = (1 << w) - n
    @@v                                                                        f( w - 1 )
    if (v < m)
        return v
    @@extra_bit                                                                f( 1 )
    return (v << 1) - m + extra_bit
}

{:.syntax }

Inverse Recenter Function

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

{:.syntax }

Inv Recenter Noneg Function

inv_recenter_nonneg( v, m ) {
    if ( v > 2 * m )
        return v
    if ( v & 1 )
        return m - ((v + 1) >> 1)
    return m + (v >> 1)
}

{:.syntax }

Film Grain Params Syntax

film_grain_params( ) {
    if ( !film_grain_params_present ) {
        return
    }
    @@apply_grain                                                              f(1)
    if ( !apply_grain ) {
        return
    }
    @@grain_seed                                                               f(16)
    @@update_grain                                                             f(1)
    if ( !update_grain ) {
        return
    }
    @@num_y_points                                                             f(4)
    for ( i = 0; i < num_y_points; i++ ) {
        @@scaling_points_y[ i ][ 0 ]                                           f(8)
        @@scaling_points_y[ i ][ 1 ]                                           f(8)
    }
    @@chroma_scaling_from_luma                                                 f(1)
    if ( !chroma_scaling_from_luma ) {
        @@num_cb_points                                                        f(4)
        for ( i = 0; i < num_cb_points; i++ ) {
            @@scaling_points_cb[ i ][ 0 ]                                      f(8)
            @@scaling_points_cb[ i ][ 1 ]                                      f(8)
        }
        @@num_cr_points                                                        f(4)
        for ( i = 0; i < num_cr_points; i++ ) {
            @@scaling_points_cr[ i ][ 0 ]                                      f(8)
            @@scaling_points_cr[ i ][ 1 ]                                      f(8)
        }
    } else {
        num_cb_points = 0
        num_cr_points = 0
    }
    @@grain_scaling_minus_8                                                    f(2)
    @@ar_coeff_lag                                                             f(2)
    numPosLuma = 2 * ar_coeff_lag * ( ar_coeff_lag + 1 )
    numPosChroma = numPosLuma + 1
    if (num_y_points) {
        for ( i = 0; i < numPosLuma; i++ )
            @ar_coeffs_y_plus_128[ i ]                                         f(8)
    }
    if ( chroma_scaling_from_luma || num_cb_points ) {
        for ( i = 0; i < numPosChroma; i++ )
            @@ar_coeffs_cb_plus_128[ i ]                                       f(8)
    }
    if ( chroma_scaling_from_luma || num_cr_points ) {
        for ( i = 0; i < numPosChroma; i++ )
            @@ar_coeffs_cr_plus_128[ i ]                                       f(8)
    }
    @@ar_coeff_shift_minus_6                                                   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)
}

{:.syntax }

Tile Group OBU Syntax

tile_group_obu( sz ) {
    NumTiles = TileCols * TileRows
    startBitPos = get_position( )
    tileBits = TileColsLog2 + TileRowsLog2
    @@tg_start                                                                 f(tileBits)
    @@tg_end                                                                   f(tileBits)
    trailing_bits( )
    endBitPos = get_position( )
    headerBytes = (endBitPos - startBitPos) / 8
    sz -= headerBytes
    
    for ( TileNum = tg_start; TileNum <= tg_end; TileNum++ ) {
        TileRow = TileNum / TileCols
        TileCol = TileNum % TileCols
        lastTile = TileNum == tg_end
        if ( lastTile ) {
            tile_size = sz
        } else {
            @@tile_size                                                        le(TileSizeBytes)
            sz -= tile_size + TileSizeBytes
        }
        MiRowStart = MiRowStarts[ TileRow ]
        MiRowEnd = MiRowStarts[ TileRow + 1 ]
        MiColStart = MiColStarts[ TileCol ]
        MiColEnd = MiColStarts[ TileCol + 1 ]
        CurrentQIndex = base_q_idx
        init_bool( tile_size )
        decode_tile( )
        exit_bool( )
    }
    if (tg_end == NumTiles - 1) {
        if ( !error_resilient_mode && !frame_parallel_decoding_mode ) {
            update_cdf( )
        }
        decode_frame( )
        SeenFrameHeader = 0
    }
}

{:.syntax }

Decode Tile Syntax

decode_tile( ) {
    if ( !dependent_tiles || 
         (TileCol == 0 && !AllowDependentTileRow[ TileRow ]) ) {
        clear_above_context( )
    }
    for ( i = 0; i < FRAME_LF_COUNT; i++ )
        DeltaLF[ i ] = 0
    for ( plane = 0; plane < NumPlanes; plane++ ) {
        for ( pass = 0; pass < 2; pass++ ) {
            RefSgrXqd[ plane ][ pass ] = Sgrproj_Xqd_Mid[ pass ]
            for ( i = 0; i < WIENER_COEFFS; i++ ) {
                RefLrWiener[ plane ][ pass ][ i ] = Wiener_Taps_Mid[ i ]
            }
        }
    }
    sbSize = use_128x128_superblock ? BLOCK_128X128 : BLOCK_64X64
    sbSize4 = Num_4x4_Blocks_Wide[ sbSize ]
    for ( r = MiRowStart; r < MiRowEnd; r += sbSize4 ) {
        clear_left_context( )
        for ( c = MiColStart; c < MiColEnd; c += sbSize4 ) {
            ReadDeltas = delta_q_present
            clear_cdef( r, c )
            clear_block_decoded_flags( c < ( MiColEnd - 1 ) )
            decode_lr( r, c, sbSize )
            decode_partition( r, c, sbSize )
        }
    }
}

{:.syntax }

where Sgrproj_Xqd_Mid and Wiener_Taps_Mid are constant lookup tables specified as:

Wiener_Taps_Mid[3] = {  3,  -7,  15 }

Sgrproj_Xqd_Mid[2] = { -32,  31 }

Clear Block Decoded Flags Function

clear_block_decoded_flags( notLastColumn ) {
    sbSize = use_128x128_superblock ? 128 : 64
    for ( plane = 0; plane < NumPlanes; plane++ ) {
        subX = (plane > 0) ? subsampling_x : 0
        subY = (plane > 0) ? subsampling_y : 0
        for ( y = -1; y <= ( sbSize >> ( MI_SIZE_LOG2 + subY ) ); y++ ) 
            for ( x = -1; x <= ( sbSize >> ( MI_SIZE_LOG2 + subX ) ); x++ ) {
                BlockDecoded[ plane ][ y ][ x ] = ( y < 0 || x < 0 )
            }
        BlockDecoded[ plane ][ -1 ][ sbSize >> ( MI_SIZE_LOG2 + subX ) ] = notLastColumn
        BlockDecoded[ plane ][ sbSize >> ( MI_SIZE_LOG2 + subY ) ][ -1 ] = 0
    }
}

{:.syntax }

Decode Partition Syntax

decode_partition( r, c, bSize ) {
    if ( r >= MiRows || c >= MiCols )
        return 0
    AvailU = is_inside( r - 1, c )
    AvailL = is_inside( r, c - 1 )
    num4x4 = Num_4x4_Blocks_Wide[ bSize ]
    halfBlock4x4 = num4x4 >> 1
    quarterBlock4x4 = halfBlock4x4 >> 1
    hasRows = ( r + halfBlock4x4 ) < MiRows
    hasCols = ( c + halfBlock4x4 ) < MiCols
    if (bSize < BLOCK_8X8) {
        partition = PARTITION_NONE
    } else if ( hasRows && hasCols ) {
        @@partition                                                            S
    } else if ( hasCols ) {
        @@split_or_horz                                                        S
        partition = split_or_horz ? PARTITION_SPLIT : PARTITION_HORZ
    } else if ( hasRows ) {
        @@split_or_vert                                                        S
        partition = split_or_vert ? PARTITION_SPLIT : PARTITION_VERT
    } else {
        partition = PARTITION_SPLIT
    }
    subSize = Partition_Subsize[ partition ][ bSize ]
    splitSize = Partition_Subsize[ PARTITION_SPLIT ][ bSize ]
    if ( partition == PARTITION_NONE ) {
        decode_block( r, c, subSize )
    } else if ( partition == PARTITION_HORZ ) {
        decode_block( r, c, subSize )
        if ( hasRows )
            decode_block( r + halfBlock4x4, c, subSize )
    } else if ( partition == PARTITION_VERT ) {
        decode_block( r, c, subSize )
        if ( hasCols )
            decode_block( r, c + halfBlock4x4, subSize )
    } else if ( partition == PARTITION_SPLIT ) {
        decode_partition( r, c, subSize )
        decode_partition( r, c + halfBlock4x4, subSize )
        decode_partition( r + halfBlock4x4, c, subSize )
        decode_partition( r + halfBlock4x4, c + halfBlock4x4, subSize )
    } else if ( partition == PARTITION_HORZ_A ) {
        decode_block( r, c, splitSize )
        decode_block( r, c + halfBlock4x4, splitSize )
        decode_block( r + halfBlock4x4, c, subSize )
    } else if ( partition == PARTITION_HORZ_B ) {
        decode_block( r, c, subSize )
        decode_block( r + halfBlock4x4, c, splitSize )
        decode_block( r + halfBlock4x4, c + halfBlock4x4, splitSize )
    } else if ( partition == PARTITION_VERT_A ) {
        decode_block( r, c, splitSize )
        decode_block( r + halfBlock4x4, c, splitSize )
        decode_block( r, c + halfBlock4x4, subSize )
    } else if ( partition == PARTITION_VERT_B ) {
        decode_block( r, c, subSize )
        decode_block( r, c + halfBlock4x4, splitSize )
        decode_block( r + halfBlock4x4, c + halfBlock4x4, splitSize )
    } else if ( partition == PARTITION_HORZ_4 ) {
        decode_block( r + quarterBlock4x4 * 0, c, subSize )
        decode_block( r + quarterBlock4x4 * 1, c, subSize )
        decode_block( r + quarterBlock4x4 * 2, c, subSize )
        decode_block( r + quarterBlock4x4 * 3, c, subSize )
    } else {
        decode_block( r, c + quarterBlock4x4 * 0, subSize )
        decode_block( r, c + quarterBlock4x4 * 1, subSize )
        decode_block( r, c + quarterBlock4x4 * 2, subSize )
        decode_block( r, c + quarterBlock4x4 * 3, subSize )
    }
}

{:.syntax }

Decode Block Syntax

decode_block( r, c, subSize ) {
    MiRow = r
    MiCol = c
    MiSize = subSize
    AvailU = is_inside( r - 1, c )
    AvailL = is_inside( r, c - 1 )
    bw4 = Num_4x4_Blocks_Wide[ subSize ]
    bh4 = Num_4x4_Blocks_High[ subSize ]
    if ( bh4 == 1 && subsampling_y && (MiRow & 1) == 0 )
        HasChroma = 0
    else if ( bw4 == 1 && subsampling_x && (MiCol & 1) == 0 )
        HasChroma = 0
    else
        HasChroma = NumPlanes > 1
    mode_info( )
    if ( skip )
        reset_block_context( bw4, bh4 )
    for ( y = 0; y < bh4; y++ ) {
        for ( x = 0; x < bw4; x++ ) {
            YModes [ r + y ][ c + x ] = YMode
            for( refList = 0; refList < 2; refList++ )
                RefFrames[ r + y ][ c + x ][ refList ] = RefFrame[ refList ]
            if ( is_inter ) {
                if ( !use_intrabc ) {
                  CompGroupIdxs[ r + y ][ c + x ] = comp_group_idx
                  CompoundIdxs[ r + y ][ c + x ] = compound_idx
                }
                for ( dir = 0; dir < 2; dir++ ) {
                    InterpFilters[ r + y ][ c + x ][ dir ] = interp_filter[ dir ]
                }
                for( refList = 0; refList < 2; refList++ ) {
                    Mvs[ r + y ][ c + x ][ refList ] = Mv[ refList ]
                    PredMvs[ r + y ][ c + x ][ refList ] = PredMv[ refList ]
                }
            }
        }
    }
    residual( )
    for ( y = 0; y < bh4; y++ ) {
        for ( x = 0; x < bw4; x++ ) {
            IsInters[ r + y ][ c + x ] = is_inter
            SkipModes[ r + y ][ c + x ] = skip_mode
            Skips[ r + y ][ c + x ] = skip
            TxSizes[ r + y ][ c + x ] = TxSize
            MiSizes[ r + y ][ c + x ] = MiSize
            TileNums[ r + y ][ c + x ] = TileNum
            SegmentIds[ r + y ][ c + x ] = segment_id
            PaletteSizes[ 0 ][ r + y ][ c + x ] = PaletteSizeY
            PaletteSizes[ 1 ][ r + y ][ c + x ] = PaletteSizeUV
            for ( i = 0; i < PaletteSizeY; i++ )
                PaletteColors[ 0 ][ r + y ][ c + x ][ i ] = palette_colors_y[ i ]
            for ( i = 0; i < PaletteSizeUV; i++ )
                PaletteColors[ 1 ][ r + y ][ c + x ][ i ] = palette_colors_u[ i ]
            for ( i = 0; i < FRAME_LF_COUNT; i++ )
                DeltaLFs[ r + y ][ c + x ][ i ] = DeltaLF[ i ]
        }
    }
}

{:.syntax }

where reset_block_context( ) is specified as:

reset_block_context( bw4, bh4 ) {
    mask = use_128x128_superblock ? 255 : 127
    for ( plane = 0; plane < 1 + 2 * HasChroma; plane++ ) {
        subX = (plane > 0) ? subsampling_x : 0
        subY = (plane > 0) ? subsampling_y : 0
        for ( i = MiCol >> subX; i < ( ( MiCol + bw4 ) >> subX ); i++) {
            AboveLevelContext[ plane ][ i ] = 0
            AboveDcContext[ plane ][ i ] = 0
        }
        for ( i = MiRow >> subY; i < ( ( MiRow + bh4 ) >> subY ); i++) {
            LeftLevelContext[ plane ][ i & mask ] = 0
            LeftDcContext[ plane ][ i & mask ] = 0
        }
    }
}

Mode Info Syntax

mode_info( ) {
    if ( FrameIsIntra )
        intra_frame_mode_info( )
    else
        inter_frame_mode_info( )
}

{:.syntax }

Intra Frame Mode Info Syntax

intra_frame_mode_info( ) {
    skip = 0
    if ( SegIdPreSkip )
        intra_segment_id( )
    skip_mode = 0
    read_skip( )
    if ( !SegIdPreSkip )
        intra_segment_id( )
    read_cdef( )
    read_delta_qindex( )
    read_delta_lf( )
    ReadDeltas = 0
    RefFrame[ 0 ] = INTRA_FRAME
    RefFrame[ 1 ] = NONE
    if ( allow_intrabc ) {
        @@use_intrabc                                                          S
    } else {
        use_intrabc = 0
    }
    if ( use_intrabc ) {
        is_inter = 1
        read_inter_tx_size( )
        YMode = DC_PRED
        UVMode = DC_PRED
        PaletteSizeY = 0
        PaletteSizeUV = 0
        interp_filter[ 0 ] = BILINEAR
        interp_filter[ 1 ] = BILINEAR
        find_mv_stack( 0 )
        assign_mv( 0 )
    } else {
        is_inter = 0
        read_tx_size( 1 )
        @@intra_frame_y_mode                                                   S
        YMode = intra_frame_y_mode
        if (HasChroma) {
            @@uv_mode                                                          S
            UVMode = uv_mode
            if (UVMode == UV_CFL_PRED) {
                read_cfl_alphas( )
            }
        }
        intra_angle_info( )
        PaletteSizeY = 0
        PaletteSizeUV = 0
        if ( Block_Width[ MiSize ] <= 64  &&
             Block_Height[ MiSize ] <= 64 &&
             allow_screen_content_tools ) {
            palette_mode_info( )
        }
        use_filter_intra = 0
        filter_intra_mode_info( )
    }
}

{:.syntax }

Intra Segment ID Syntax

intra_segment_id( ) {
    if ( segmentation_enabled && segmentation_update_map )
        read_segment_id( )
    else
        segment_id = 0
    Lossless = LosslessArray[ segment_id ]
}

{:.syntax }

Read Segment ID Syntax

read_segment_id( ) {
    if ( AvailU && AvailL )
        prevUL = PrevSegmentIds[ MiRow - 1 ][ MiCol - 1 ]
    else
        prevUL = -1
    if ( AvailU )
        prevU = PrevSegmentIds[ MiRow - 1 ][ MiCol ]
    else
        prevU = -1
    if ( AvailL )
        prevL = PrevSegmentIds[ MiRow ][ MiCol - 1 ]
    else
        prevL = -1
    if (prevU == -1)
        pred = prevL == -1 ? 0 : prevL
    else if (prevL == -1)
        pred = prevU
    else
        pred = (prevUL == prevU) ? prevU : prevL
    if ( skip ) {
        segment_id = pred
    } else {
        @@segment_id                                                           S
        segment_id = neg_deinterleave( segment_id, pred, 
                                       LastActiveSegId + 1 )
    }
}

{:.syntax }

where neg_deinterleave is a function defined as:

neg_deinterleave(int diff, int ref, int 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)
  }
}

Skip Mode Syntax

read_skip_mode() {
    if ( seg_feature_active( SEG_LVL_SKIP ) || 
         !skip_mode_present ||
         Block_Width[ MiSize ] < 8 ||
         Block_Height[ MiSize ] < 8 ) {
        skip_mode = 0
    } else {
        @@skip_mode                                                            S
    }
}

{:.syntax }

Skip Syntax

read_skip() {
    if ( seg_feature_active( SEG_LVL_SKIP ) ) {
        skip = 1
    } else {
        @@skip                                                                 S
    }
}

{:.syntax }

Quantizer Index Delta Syntax

read_delta_qindex( ) {
    sbSize = use_128x128_superblock ? BLOCK_128X128 : BLOCK_64X64
    if ( MiSize == sbSize && skip )
        return
    if ( 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) + 1
        }
        if (delta_q_abs) {
            @@delta_q_sign_bit                                                 L(1)
            reducedDeltaQIndex = delta_q_sign_bit ? -delta_q_abs : delta_q_abs
            CurrentQIndex = Clip3(1, 255, CurrentQIndex + (reducedDeltaQIndex << delta_q_res))
        }
    }
}

{:.syntax }

Loop Filter Delta Syntax

read_delta_lf( ) {
    sbSize = use_128x128_superblock ? BLOCK_128X128 : BLOCK_64X64
    if ( MiSize == sbSize && skip )
        return
    if ( ReadDeltas && delta_lf_present ) {
        for ( i = 0; i < ( delta_lf_multi ? FRAME_LF_COUNT : 1 ); i++ ) {
            @@delta_lf_abs                                                     S
            if ( delta_lf_abs == DELTA_LF_SMALL ) {
                @@delta_lf_rem_bits                                            L(3)
                n = delta_lf_rem_bits + 1
                @@delta_lf_abs_bits                                            L(n)
                deltaLfAbs = delta_lf_abs_bits +
                               ( 1 << n ) + 1
            } else {
                deltaLfAbs = delta_lf_abs
            }
            if ( deltaLfAbs ) {
                @@delta_lf_sign_bit                                            L(1)
                reducedDeltaLfLevel = delta_lf_sign_bit ?
                                      -deltaLfAbs :
                                       deltaLfAbs
                DeltaLF[ i ] = Clip3( 0, MAX_LOOP_FILTER, DeltaLF[ i ] +
                                  (reducedDeltaLfLevel << delta_lf_res) )
            }
        }
    }
}

{:.syntax }

Segmentation Feature Active Function

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

seg_feature_active( feature ) {
    return seg_feature_active_idx( segment_id, feature )
}

{:.syntax }

TX Size Syntax

read_tx_size( allowSelect ) {
    largestTxSize = Tx_Mode_To_Biggest_Tx_Size[ TxMode ]
    maxTxSize = Max_Tx_Size[ MiSize ]
    maxRectTxSize = Max_Tx_Size_Rect[ MiSize ]
    maxTxDepth = Max_Tx_Depth[ MiSize ]
    
    if ( MiSize > BLOCK_4X4 ) {
        if ( allowSelect && TxMode == TX_MODE_SELECT ) {
            @@tx_depth                                                         S
            TxSize = maxRectTxSize
            for ( i = 0; i < tx_depth; i++ )
                TxSize = Split_Tx_Size[ TxSize ]
        } else {
            if ( MiSize == BLOCK_4X4 )
                TxSize = Min( maxTxSize, largestTxSize )
            else if ( Tx_Size_Sqr[ maxRectTxSize ] <= largestTxSize )
                TxSize = maxRectTxSize
            else
                TxSize = largestTxSize
        }
    } else {
        TxSize = maxRectTxSize
    }
}

{:.syntax }

The Max_Tx_Depth table specifies the maximum transform depth which can be encoded for each block size:

Max_Tx_Depth[ BLOCK_SIZES ] = {
    0, 1, 1, 1,
    2, 2, 2, 3,
    3, 3, 4, 4,
    4, 4, 4, 4,
}

The Tx_Mode_To_Biggest_Tx_Size table is defined as:

Tx_Mode_To_Biggest_Tx_Size[ TX_MODES ] = {
    TX_4X4,
    TX_64X64,
    TX_64X64
}

Inter TX Size Syntax

read_inter_tx_size is used in inter frames to read the transform sizes.

Either a single transform size is used for the whole block, or a tree of transform sizes is generated.

As the maximum transform size is 32 samples, a block may require several transform trees to be coded.

read_inter_tx_size( ) {
    bw4 = Num_4x4_Blocks_Wide[ MiSize ]
    bh4 = Num_4x4_Blocks_High[ MiSize ]
    if (TxMode == TX_MODE_SELECT && 
          MiSize > BLOCK_4X4 && is_inter &&
          !skip && !Lossless) {
        MinTxSize = TX_32X32
        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_var_tx_size( row, col, maxTxSz, 0 )
    } else {
        read_tx_size(!skip || !is_inter)
        for ( row = MiRow; row < MiRow + bh4; row++ )
            for ( col = MiCol; col < MiCol + bw4; col++ )
                InterTxSizes[ row ][ col ] = TxSize
        MinTxSize = TxSize
    }
}

{:.syntax }

Var TX Size Syntax

read_var_tx_size is used to read a transform size tree.

The original transform size may be square or rectangular, but only square transform sizes are produced if split.

read_var_tx_size( row, col, txSz, depth) {
    if ( row >= MiRows || col >= MiCols )
        return
    if (txSz == TX_4X4 || depth == MAX_VARTX_DEPTH) {
        txfm_split = 0
    } else {
        @@txfm_split                                                           S
    }
    w4 = Tx_Width[ txSz ] / MI_SIZE
    h4 = Tx_Height[ txSz ] / MI_SIZE
    if (txfm_split) {
        subTxSz = Split_Tx_Size[ txSz ]
        step4 = Tx_Width[ subTxSz ] / MI_SIZE
        for (i = 0; i < h4; i += step4)
            for (j = 0; j < w4; j += step4)
                read_var_tx_size( row + i, col + j, subTxSz, depth+1)
    } else {
        for (i = 0; i < h4; i++ )
            for (j = 0; j < w4; j++ )
                InterTxSizes[ row + i ][ col + j ] = txSz
        MinTxSize = ( Tx_Width[ MinTxSize ] * Tx_Height[ MinTxSize ] <=
                      Tx_Width[ txSz ] * Tx_Height[ txSz ] ) ? MinTxSize : txSz
        TxSize = txSz
    }
}

{:.syntax }

Inter Frame Mode Info Syntax

inter_frame_mode_info( ) {
    use_intrabc = 0
    LeftRefFrame[ 0 ] = AvailL ? RefFrames[ MiRow ][ MiCol-1 ][ 0 ] : INTRA_FRAME
    AboveRefFrame[ 0 ] = AvailU ? RefFrames[ MiRow-1 ][ MiCol ][ 0 ] : INTRA_FRAME
    LeftRefFrame[ 1 ] = AvailL ? RefFrames[ MiRow ][ MiCol-1 ][ 1 ] : NONE
    AboveRefFrame[ 1 ] = AvailU ? RefFrames[ MiRow-1 ][ MiCol ][ 1 ] : NONE
    LeftIntra = LeftRefFrame[ 0 ] <= INTRA_FRAME
    AboveIntra = AboveRefFrame[ 0 ] <= INTRA_FRAME
    LeftSingle = LeftRefFrame[ 1 ] <= INTRA_FRAME
    AboveSingle = AboveRefFrame[ 1 ] <= INTRA_FRAME
    skip = 0
    inter_segment_id( 1 )
    read_skip_mode( )
    read_skip( )
    if ( !SegIdPreSkip )
        inter_segment_id( 0 )
    Lossless = LosslessArray[ segment_id ]
    read_cdef( )
    read_delta_qindex( )
    read_delta_lf( )
    ReadDeltas = 0
    read_is_inter( )
    read_inter_tx_size( )
    if ( is_inter )
        inter_block_mode_info( )
    else
        intra_block_mode_info( )
}

{:.syntax }

Inter Segment ID Syntax

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

inter_segment_id( preSkip ) {
    if ( segmentation_enabled ) {
        predictedSegmentId = get_segment_id( )
        if ( segmentation_update_map ) {
            if ( preSkip && !SegIdPreSkip ) {
                segment_id = 0
                return
            }
            if ( !preSkip ) {
                if ( skip ) {
                    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
    }
}

{:.syntax }

Is Inter Syntax

read_is_inter( ) {
    if ( skip_mode ) {
        is_inter = 1
    } else if ( seg_feature_active ( SEG_LVL_REF_FRAME ) ) {
        is_inter = FeatureData[ segment_id ][ SEG_LVL_REF_FRAME ] != INTRA_FRAME
    } else {
        @@is_inter                                                             S
    }
}

{:.syntax }

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( ) {
    bw4 = Num_4x4_Blocks_Wide[ MiSize ]
    bh4 = Num_4x4_Blocks_High[ MiSize ]
    xMis = Min( MiCols - MiCol, bw4 )
    yMis = Min( MiRows - MiRow, bh4 )
    seg = 7
    for ( y = 0; y < yMis; y++ )
        for ( x = 0; x < xMis; x++ )
            seg = Min( seg, PrevSegmentIds[ MiRow + y ][ MiCol + x ] )
    return seg
}

{:.syntax }

Intra Block Mode Info Syntax

intra_block_mode_info( ) {
    RefFrame[ 0 ] = INTRA_FRAME
    RefFrame[ 1 ] = NONE
    @@y_mode                                                                   S
    YMode = y_mode
    if (HasChroma) {
        @@uv_mode                                                              S
        UVMode = uv_mode
        if (UVMode == UV_CFL_PRED) {
            read_cfl_alphas( )
        }
    }
    intra_angle_info( )
    PaletteSizeY = 0
    PaletteSizeUV = 0
    if ( Block_Width[ MiSize ] <= 64  &&
         Block_Height[ MiSize ] <= 64 &&
         allow_screen_content_tools )
        palette_mode_info( )
    use_filter_intra = 0
    filter_intra_mode_info( )
}

{:.syntax }

Inter Block Mode Info Syntax

inter_block_mode_info( ) {
    PaletteSizeY = 0
    PaletteSizeUV = 0
    use_filter_intra = 0
    read_ref_frames( )
    for ( j = 0; j < 2; j++ ) {
        if ( RefFrame[ j ] > INTRA_FRAME ) {
            find_mv_stack( j )
            find_mv_list( j )
        }
    }
    isCompound = RefFrame[ 1 ] > INTRA_FRAME
    if ( isCompound ) {
        compound_context( )
        find_mv_stack( -1 )
    }
    if ( skip_mode ) {
        YMode = NEAREST_NEARESTMV
    } else if ( seg_feature_active( SEG_LVL_SKIP ) ||
         seg_feature_active( SEG_LVL_GLOBALMV ) ) {
        YMode = GLOBALMV
    } else if ( isCompound ) {
        @@compound_mode                                                        S
        YMode = NEAREST_NEARESTMV + compound_mode
    } else {
        @@new_mv                                                               S
        if ( new_mv == 0 ) {
            YMode = NEWMV
        } else {
            @@zero_mv                                                          S
            if ( zero_mv == 0 ) {
                YMode = GLOBALMV
            } else {
                @@ref_mv                                                       S
                YMode = (ref_mv == 0) ? NEARESTMV : NEARMV
            }
        }
    }
    RefMvIdx = 0
    if (YMode == NEWMV || YMode == NEW_NEWMV) {
        for (idx = 0; idx < 2; idx++) {
            if (NumMvFound > idx + 1) {
                @@drl_mode                                                     S
                if (drl_mode == 0) {
                  RefMvIdx = idx
                  break
                }
                RefMvIdx = idx + 1
            }
        }
    } else if ( has_nearmv( ) ) {
        RefMvIdx = 1
        for (idx = 1; idx < 3; idx++) {
            if (NumMvFound > idx + 1) {
                @@drl_mode                                                     S
                if ( drl_mode == 0 ) {
                    RefMvIdx = idx
                    break
                }
                RefMvIdx = idx + 1
            }
        }
    }
    assign_mv( isCompound )
    read_interintra_mode( isCompound )
    read_motion_mode( isCompound )
    read_compound_type( isCompound )
    if ( interpolation_filter == SWITCHABLE ) {
        for ( dir = 0; dir < 2; dir++ ) {
            if ( needs_interp_filter( ) ) {
                @@interp_filter[ dir ]                                         S
            } else {
                interp_filter[ dir ] = EIGHTTAP
            }
        }
    } else {
        for ( dir = 0; dir < 2; dir++ )
            interp_filter[ dir ] = interpolation_filter
    }
}

{:.syntax }

The function has_nearmv is defined as:

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

{:.syntax }

The function needs_interp_filter is defined as:

needs_interp_filter( ) {
    if (YMode == GLOBALMV) {
        return gm_type[ RefFrame[ 0 ] ] <= TRANSLATION
    } else if (YMode == GLOBAL_GLOBALMV ) {
        return gm_type[ RefFrame[ 0 ] ] <= TRANSLATION || gm_type[ RefFrame[ 1 ] ] <= TRANSLATION
    } else {
        return 1
    }
}

{:.syntax }

Filter Intra Mode Info Syntax

filter_intra_mode_info( ) {
    if ( YMode == DC_PRED && PaletteSizeY == 0 &&
         Max( Tx_Width[ TxSize ], Tx_Height[ TxSize ] ) <= 32 ) {
        @@use_filter_intra                                                     S
        if ( use_filter_intra ) {
            @@filter_intra_mode                                                S
        }
    }
}

{:.syntax }

Ref Frames Syntax

read_ref_frames( ) {
    if ( skip_mode ) {
        RefFrame[ 0 ] = ForwardFrame
        RefFrame[ 1 ] = BackwardFrame
    } else if ( seg_feature_active( SEG_LVL_REF_FRAME ) ) {
        RefFrame[ 0 ] = FeatureData[ segment_id ][ SEG_LVL_REF_FRAME ]
        RefFrame[ 1 ] = NONE
    } else if ( seg_feature_active( SEG_LVL_SKIP ) ||
                seg_feature_active( SEG_LVL_GLOBALMV ) ) {
        RefFrame[ 0 ] = LAST_FRAME
        RefFrame[ 1 ] = NONE
    } else {
        if ( reference_select )
            @@comp_mode                                                        S
        else
            comp_mode = SINGLE_REFERENCE
        if ( comp_mode == COMPOUND_REFERENCE ) {
            @@comp_ref_type                                                    S
            if (comp_ref_type == UNIDIR_COMP_REFERENCE) {
                @@uni_comp_ref                                                 S
                if (uni_comp_ref) {
                    RefFrame[0] = BWDREF_FRAME
                    RefFrame[1] = ALTREF_FRAME
                } else {
                    @@uni_comp_ref_p1                                          S
                    if (uni_comp_ref_p1) {
                        @@uni_comp_ref_p2                                      S
                        if (uni_comp_ref_p2) {
                          RefFrame[0] = LAST_FRAME
                          RefFrame[1] = GOLDEN_FRAME
                        } else {
                          RefFrame[0] = LAST_FRAME
                          RefFrame[1] = LAST3_FRAME
                        }
                    } else {
                        RefFrame[0] = LAST_FRAME
                        RefFrame[1] = LAST2_FRAME
                    }
                }
            } else {
                @@comp_ref                                                     S
                if ( comp_ref == 0 ) {
                    @@comp_ref_p1                                              S
                    RefFrame[ 0 ] = comp_ref_p1 ?
                                    LAST_FRAME : LAST2_FRAME
                } else {
                    @@comp_ref_p2                                              S
                    RefFrame[ 0 ] = comp_ref_p2 ?
                                    GOLDEN_FRAME : LAST3_FRAME
                }
                @@comp_bwdref                                                  S
                if ( comp_bwdref == 0 ) {
                    @@comp_bwdref_p1                                           S
                    RefFrame[ 1 ] = comp_bwdref_p1 ?
                                     ALTREF2_FRAME : BWDREF_FRAME
                } else {
                    RefFrame[ 1 ] = ALTREF_FRAME
                }
            }
        } else {
            @@single_ref_p1                                                    S
            if ( single_ref_p1 ) {
                @@single_ref_p2                                                S
                if ( single_ref_p2 == 0 ) {
                    @@single_ref_p6                                            S
                    RefFrame[ 0 ] = single_ref_p6 ?
                                     ALTREF2_FRAME : BWDREF_FRAME
                } else {
                    RefFrame[ 0 ] = ALTREF_FRAME
                }
            } else {
                @@single_ref_p3                                                S
                if ( single_ref_p3 ) {
                    @@single_ref_p5                                            S
                    RefFrame[ 0 ] = single_ref_p5 ?
                                     GOLDEN_FRAME : LAST3_FRAME
                } else {
                    @@single_ref_p4                                            S
                    RefFrame[ 0 ] = single_ref_p4 ?
                                     LAST2_FRAME : LAST_FRAME
                }
            }
            RefFrame[ 1 ] = NONE
        }
    }
}

{:.syntax }

Assign MV Syntax

assign_mv( isCompound ) {
    bw = Block_Width[ MiSize ]
    bh = Block_Height[ MiSize ]
    Mv[ 1 ] = ZeroMvs[ 1 ]
    PredMv[ 1 ] = ZeroMvs[ 1 ]
    for ( i = 0; i < 1 + isCompound; i++ ) {
        if ( use_intrabc ) {
            compMode = NEWMV
        } else {
            compMode = get_mode( i )
        }
        if ( use_intrabc ) {
            PredMv[ 0 ] = RefListMv[ i ][ 0 ]
            if ( PredMv[ 0 ][ 0 ] == 0 && PredMv[ 0 ][ 1 ] == 0 ) {
                PredMv[ 0 ] = RefListMv[ i ][ 1 ]
            }
            if ( PredMv[ 0 ][ 0 ] == 0 && PredMv[ 0 ][ 1 ] == 0 ) {
                sbSize = use_128x128_superblock ? BLOCK_128X128 : BLOCK_64X64
                sbSize4 = Num_4x4_Blocks_High[ sbSize ]
                if ( MiRow - sbSize4 < MiRowStart ) {
                    PredMv[ 0 ][ 0 ] = 0
                    PredMv[ 0 ][ 1 ] = (-sbSize - INTRABC_DELAY_PIXELS) * 8
                } else {
                    PredMv[ 0 ][ 0 ] = -sbSize * 8
                    PredMv[ 0 ][ 1 ] = 0
                }
            }
        }
        else if ( compMode == GLOBALMV ) {
            PredMv[ i ] = ZeroMvs[ i ]
        } else {
            pos = ( compMode == NEARESTMV ) ? 0 : RefMvIdx
            useStack = pos < NumMvFound
            if ( compMode == NEWMV && NumMvFound <= 1)
                useStack = 0
            if ( useStack ) {
                PredMv[ i ] = RefStackMv[ pos ][ i ]
                if ( YMode == NEARMV && pos > 1 ) {
                    // No clamping
                } else {
                    PredMv[ i ][ 0 ] = clamp_mv_row( PredMv[ i ][ 0 ], MV_BORDER + bh * 8)
                    PredMv[ i ][ 1 ] = clamp_mv_col( PredMv[ i ][ 1 ], MV_BORDER + bw * 8)
                }
            } else {
                PredMv[ i ] = RefListMv[ i ][ pos ]
            }
        }
        if ( compMode == NEWMV ) {
            read_mv( i )
        }
    }
}

{:.syntax }

Read Motion Mode Syntax

read_motion_mode( isCompound ) {
    if ( skip_mode ) {
        motion_mode = SIMPLE
        return
    }
    if ( Min( Block_Width[ MiSize ],
              Block_Height[ MiSize ] ) < 8 ) {
        motion_mode = SIMPLE
        return
    }
    if ( !force_integer_mv && 
         ( YMode == GLOBALMV || YMode == GLOBAL_GLOBALMV ) ) {
        if (gm_type[ RefFrame[ 0 ] ] > TRANSLATION) {
            motion_mode = SIMPLE
            return
        }
    }
    if ( isCompound || !has_overlappable_candidates( ) ) {
        motion_mode = SIMPLE
        return
    }
    find_warp_samples()
    if ( force_integer_mv || NumSamples == 0) {
        @@use_obmc                                                             S
        motion_mode = use_obmc ? OBMC : SIMPLE
    } else {
        @@motion_mode                                                          S
    }
}

{:.syntax }

Read Inter Intra Syntax

read_interintra_mode( isCompound ) {
    if ( !skip_mode && allow_interintra_compound && !isCompound && 
         MiSize >= BLOCK_8X8 && MiSize <= BLOCK_32X32) {
        @@interintra                                                           S
        if (interintra) {
            @@interintra_mode                                                  S
            RefFrame[1] = INTRA_FRAME
            AngleDeltaY = 0
            AngleDeltaUV = 0
            n = Wedge_Bits[ MiSize ]
            if ( n > 0 ) {
                @@wedge_interintra                                             S
                if (wedge_interintra) {
                    @@wedge_index                                              L(n)
                    wedge_sign = 0
                }
            } else {
                wedge_interintra = 0
            }
        }
    } else {
        interintra = 0
    }
}

{:.syntax }

Read Compound Type Syntax

read_compound_type( isCompound ) {
    comp_group_idx = 0
    compound_idx = 1
    if ( skip_mode ) {
        compound_type = COMPOUND_DISTANCE
        return
    }
    if ( isCompound ) {
        if ( allow_masked_compound && Wedge_Bits[ MiSize ] > 0 ) {
            @@comp_group_idx                                                   S
        } else {
            comp_group_idx = 0
        }
        if ( comp_group_idx == 0 ) {
            @@compound_idx                                                     S
            compound_type = compound_idx ? COMPOUND_DISTANCE :
                                           COMPOUND_AVERAGE
            return
        }
    }
    if ( allow_masked_compound && isCompound &&
         motion_mode == SIMPLE && MiSize >= BLOCK_8X8) {
        n = Wedge_Bits[ MiSize ]
        if ( n == 0 ) {
            compound_type = COMPOUND_SEG
        } else {
            @@compound_type                                                    S
        }
        if ( compound_type == COMPOUND_WEDGE ) {
            @@wedge_index                                                      L(n)
            @@wedge_sign                                                       L(1)
        } else if ( compound_type == COMPOUND_SEG ) {
            @@mask_type                                                        L(1)
        }
    } else {
        if ( interintra ) {
            compound_type = wedge_interintra ? COMPOUND_WEDGE : COMPOUND_INTRA
        } else {
            compound_type = COMPOUND_AVERAGE
        }
    }
}

{:.syntax }

Get Mode Function

get_mode( refList ) {
    if ( refList == 0 ) {
        if (YMode < NEAREST_NEARESTMV)
            compMode = YMode
        else if (YMode == NEW_NEWMV || YMode == NEW_NEARESTMV || YMode == NEW_NEARMV)
            compMode = NEWMV
        else if (YMode == NEAREST_NEARESTMV || YMode == NEAREST_NEWMV)
            compMode = NEARESTMV
        else if (YMode == NEAR_NEARMV || YMode == NEAR_NEWMV)
            compMode = NEARMV
        else
            compMode = GLOBALMV
    } else {
        if (YMode == NEW_NEWMV || YMode == NEAREST_NEWMV || YMode == NEAR_NEWMV)
            compMode = NEWMV
        else if (YMode == NEAREST_NEARESTMV || YMode == NEW_NEARESTMV)
            compMode = NEARESTMV
        else if (YMode == NEAR_NEARMV || YMode == NEW_NEARMV)
            compMode = NEARMV
        else
            compMode = GLOBALMV
    }
    return compMode
}

{:.syntax }

MV Syntax

read_mv( ref ) {
    diffMv[ 0 ] = 0
    diffMv[ 1 ] = 0
    if ( use_intrabc ) {
        MvCtx = MV_INTRABC_CONTEXT
    } else {
        if ( RefMvIdx < NumMvFound && 
             WeightStack[ RefMvIdx ] >= REF_CAT_LEVEL ) {
            MvCtx = MvCtxStack[ RefMvIdx ][ ref ]
        } else {
            MvCtx = 0
        }
    }
    @@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 )
    Mv[ ref ][ 0 ] = PredMv[ ref ][ 0 ] + diffMv[ 0 ]
    Mv[ ref ][ 1 ] = PredMv[ ref ][ 1 ] + diffMv[ 1 ]
}

{:.syntax }

MV Component Syntax

read_mv_component( comp ) {
    @@mv_sign                                                                  S
    @@mv_class                                                                 S
    if ( mv_class == MV_CLASS_0 ) {
        @@mv_class0_bit                                                        S
        if ( force_integer_mv )
            mv_class0_fr = 3
        else
            @@mv_class0_fr                                                     S
        if ( allow_high_precision_mv )
            @@mv_class0_hp                                                     S
        else
            mv_class0_hp = 1
        mag = ( ( mv_class0_bit << 3 ) |
                ( mv_class0_fr << 1 ) |
                  mv_class0_hp ) + 1
    } else {
        d = 0
        for ( i = 0; i < mv_class; i++ ) {
            @@mv_bit                                                           S
            d |= mv_bit << i
        }
        mag = CLASS0_SIZE << ( mv_class + 2 )
        if ( force_integer_mv )
            mv_fr = 3
        else
            @@mv_fr                                                            S
        if ( allow_high_precision_mv )
            @@mv_hp                                                            S
        else
            mv_hp = 1
        mag += ( ( d << 3 ) | ( mv_fr << 1 ) | mv_hp ) + 1
    }
    return mv_sign ? -mag : mag
}

{:.syntax }

Residual Syntax

residual( ) {
    palette_tokens( )

    sbMask = use_128x128_superblock ? 31 : 15
    
    widthChunks = Max( 1, Block_Width[ MiSize ] >> 6 )
    heightChunks = Max( 1, Block_Height[ MiSize ] >> 6 )
    
    miSizeChunk = ( widthChunks > 1 || heightChunks > 1 ) ? BLOCK_64X64 : MiSize
    
    for ( chunkY = 0; chunkY < heightChunks; chunkY++ ) {
        for ( chunkX = 0; chunkX < widthChunks; chunkX++ ) {
            miRowChunk = MiRow + ( chunkY << 4 )
            miColChunk = MiCol + ( chunkX << 4 )
            subBlockMiRow = miRowChunk & sbMask
            subBlockMiCol = miColChunk & sbMask
            
            for ( plane = 0; plane < 1 + HasChroma * 2; plane++ ) {
                txSz = Lossless ? TX_4X4 : get_tx_size( plane, TxSize )
                stepX = Tx_Width[ txSz ] >> 2
                stepY = Tx_Height[ txSz ] >> 2
                planeSz = get_plane_residual_size( miSizeChunk, 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) ? subsampling_x : 0
                subY = (plane > 0) ? subsampling_y : 0
                baseX = (miColChunk >> subX) * MI_SIZE
                baseY = (miRowChunk >> subY) * MI_SIZE
                candRow = (MiRow >> subY) << subY
                candCol = (MiCol >> subX) << subX

                IsInterIntra = ( is_inter && RefFrame[ 1 ] == INTRA_FRAME )
                IsCFL = (plane > 0 && !is_inter && UVMode == UV_CFL_PRED)

                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
                } else {
                    mode = DC_PRED
                }

                if ( IsInterIntra || IsCFL ) {
                    predict_intra( plane, baseX, baseY,
                                   AvailL,
                                   AvailU,
                                   BlockDecoded[ plane ]
                                               [ ( subBlockMiRow >> subY ) - 1 ]
                                               [ ( subBlockMiCol >> subX ) + num4x4W ],
                                   BlockDecoded[ plane ]
                                               [ ( subBlockMiRow >> subY ) + num4x4H ]
                                               [ ( subBlockMiCol >> subX ) - 1 ],
                                   mode,
                                   log2W, log2H )
                }

                if ( is_inter ) {
                    predW = Block_Width[ miSizeChunk ] >> subX
                    predH = Block_Height[ miSizeChunk ] >> subY
                    someUseIntra = 0
                    for( r = 0; r < num4x4H; r++ )
                        for( c = 0; c < num4x4W; c++ )
                            if ( RefFrames[ candRow + r ][ candCol + c ][ 0 ] == INTRA_FRAME )
                                someUseIntra = 1
                    if ( someUseIntra ) {
                        predW = num4x4W * 4
                        predH = num4x4H * 4
                        candRow = MiRow
                        candCol = MiCol
                    }
                    r = 0
                    for( y = 0; y < num4x4H * 4; y += predH ) {
                        c = 0
                        for( x = 0; x < num4x4W * 4; x += predW ) {
                            predict_inter( plane, baseX + x, baseY + y,
                                           predW, predH,
                                           candRow + r, candCol + c)
                            c++
                        }
                        r++
                    }
                }

                if ( is_inter ) {
                    transform_tree( plane, baseX, baseY, num4x4W * 4, num4x4H * 4 )
                } else {
                    baseXBlock = (MiCol >> subX) * MI_SIZE
                    baseYBlock = (MiRow >> subY) * MI_SIZE
                    for( y = 0; y < num4x4H; y += stepY )
                        for( x = 0; x < num4x4W; x += stepX )
                            transform_block( plane, baseXBlock, baseYBlock, txSz,
                                             x + ( chunkX << 4 ),
                                             y + ( chunkY << 4 ) )
                }
            }
        }
    }
}

{:.syntax }

Transform Block Syntax

transform_block(plane, baseX, baseY, txSz, x, y) {
    startX = baseX + 4 * x
    startY = baseY + 4 * y
    subX = (plane > 0) ? subsampling_x : 0
    subY = (plane > 0) ? subsampling_y : 0
    row = ( startY << subY ) >> MI_SIZE_LOG2
    col = ( startX << subX ) >> MI_SIZE_LOG2
    sbMask = use_128x128_superblock ? 31 : 15
    subBlockMiRow = row & sbMask
    subBlockMiCol = col & sbMask
    stepX = Tx_Width[ txSz ] >> MI_SIZE_LOG2
    stepY = Tx_Height[ txSz ] >> MI_SIZE_LOG2
    maxX = (MiCols * MI_SIZE) >> subX
    maxY = (MiRows * MI_SIZE) >> subY
    if ( startX >= maxX || startY >= maxY ) {
        return
    }
    if ( !is_inter ) {
        if ( ( ( plane == 0 ) && PaletteSizeY ) ||
             ( ( plane != 0 ) && PaletteSizeUV ) ) {
            predict_palette( plane, startX, startY, x, y, txSz )
        } else if ( IsCFL ) {
            predict_chroma_from_luma( plane, startX, startY, txSz )
        } else {
            mode = ( plane == 0 ) ? YMode : UVMode
            log2W = Tx_Width_Log2[ txSz ]
            log2H = Tx_Height_Log2[ txSz ]
            predict_intra( plane, startX, startY,
                           AvailL || x > 0,
                           AvailU || y > 0,
                           BlockDecoded[ plane ]
                                       [ ( subBlockMiRow >> subY ) + y - 1 ]
                                       [ ( subBlockMiCol >> subX ) + x + stepX ],
                           BlockDecoded[ plane ]
                                       [ ( subBlockMiRow >> subY ) + y + stepY ]
                                       [ ( subBlockMiCol >> subX ) + x - 1 ],
                           mode,
                           log2W, log2H )
        }
        if (plane == 0) {
            MaxLumaW = startX + stepX * 4
            MaxLumaH = startY + stepY * 4
        }
    }
    if ( !skip ) {
        eob = coeffs( plane, startX, startY, txSz )
        if ( eob > 0 )
            reconstruct( plane, startX, startY, txSz )
    }
    for ( i = 0; i < stepY; i++ ) {
        for ( j = 0; j < stepX; j++ ) {
            LoopfilterTxSizes[ plane ]
                             [ (row >> subY) + i ]
                             [ (col >> subX) + j ] = txSz
            BlockDecoded[ plane ]
                        [ ( subBlockMiRow >> subY ) + y + i ]
                        [ ( subBlockMiCol >> subX ) + x + j ] = 1
        }
    }
}

{:.syntax }

Transform Tree Syntax

transform_tree is used to read a number of transform blocks arranged in a transform tree.

transform_tree( plane, startX, startY, w, h ) {
    subX = (plane > 0) ? subsampling_x : 0
    subY = (plane > 0) ? subsampling_y : 0
    maxX = (MiCols * MI_SIZE) >> subX
    maxY = (MiRows * MI_SIZE) >> subY
    if ( startX >= maxX || startY >= maxY ) {
        return
    }
    row = ( startY << subY ) >> MI_SIZE_LOG2
    col = ( startX << subX ) >> MI_SIZE_LOG2
    lumaTxSz = InterTxSizes[ row ][ col ]
    lumaW = Tx_Width[ lumaTxSz ]
    lumaH = Tx_Height[ lumaTxSz ]
    uses64 = w >= 64 || h >= 64 
    isSubsampled = subX || subY
    if ( (isSubsampled && !uses64) ||
         (!isSubsampled && w <= lumaW && h <= lumaH) ) {
        txSz = find_tx_size( w, h )
        transform_block( plane, startX, startY, txSz, 0, 0 )
    } else {
        if ( w > h ) {
            transform_tree( plane, startX, startY, w/2, h )
            transform_tree( plane, startX + w / 2, startY, w/2, h )
        } else if ( w < h ) {
            transform_tree( plane, startX, startY, w, h/2 )
            transform_tree( plane, startX, startY + h/2, w, h/2 )
        } else {
            transform_tree( plane, startX, startY, w/2, h/2 )
            transform_tree( plane, startX + w/2, startY, w/2, h/2 )
            transform_tree( plane, startX, startY + h/2, w/2, h/2 )
            transform_tree( plane, startX + w/2, startY + h/2, w/2, h/2 )
        }
    }
}

{:.syntax }

where find_tx_size finds the transform size matching the given dimensions and is defined as:

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

Get TX Size Function

get_tx_size( plane, txSz ) {
    if ( plane == 0 )
        return txSz
    uvTx = Max_Tx_Size_Rect[ get_plane_residual_size( MiSize, plane ) ]
    if ( Tx_Width[ uvTx ] == 64 || Tx_Height[ uvTx ] == 64 )
        return TX_32X32
    return uvTx
}

{:.syntax }

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 ) {
    subx = plane > 0 ? subsampling_x : 0
    suby = plane > 0 ? subsampling_y : 0
    return Subsampled_Size[ subsize ][ subx ][ suby ]
}

{:.syntax }

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_INVALID, BLOCK_4X8} },
  { {BLOCK_16X8,    BLOCK_INVALID},  {BLOCK_8X8,     BLOCK_8X4} },
  { {BLOCK_16X16,   BLOCK_16X8},     {BLOCK_8X16,    BLOCK_8X8} },
  { {BLOCK_16X32,   BLOCK_16X16},    {BLOCK_INVALID, BLOCK_8X16} },
  { {BLOCK_32X16,   BLOCK_INVALID},  {BLOCK_16X16,   BLOCK_16X8} },
  { {BLOCK_32X32,   BLOCK_32X16},    {BLOCK_16X32,   BLOCK_16X16} },
  { {BLOCK_32X64,   BLOCK_32X32},    {BLOCK_INVALID, BLOCK_16X32} },
  { {BLOCK_64X32,   BLOCK_INVALID},  {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_4X16,    BLOCK_4X8},      {BLOCK_INVALID, BLOCK_4X8} },
  { {BLOCK_16X4,    BLOCK_INVALID},  {BLOCK_8X4,     BLOCK_8X4} },
  { {BLOCK_8X32,    BLOCK_8X16},     {BLOCK_INVALID, BLOCK_4X16} },
  { {BLOCK_32X8,    BLOCK_INVALID},  {BLOCK_16X8,    BLOCK_16X4} },
  { {BLOCK_16X64,   BLOCK_16X32},    {BLOCK_INVALID, BLOCK_8X32} },
  { {BLOCK_64X16,   BLOCK_INVALID},  {BLOCK_32X16,   BLOCK_32X8} },
  { {BLOCK_32X128,  BLOCK_32X64},    {BLOCK_INVALID, BLOCK_16X64} },
  { {BLOCK_128X32,  BLOCK_INVALID},  {BLOCK_64X32,   BLOCK_64X16} },
}

Coefficients Syntax

coeffs( plane, startX, startY, txSz ) {
    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 = ( txSz == TX_16X64 || txSz == TX_64X16 ) ? 512 :
                Min( 1024, Tx_Width[ txSz ] * Tx_Height[ txSz ] )
    
    for ( c = 0; c < segEob; c++ )
        Quant[c] = 0
    for ( i = 0; i < 64; i++ )
        for ( j = 0; j < 64; j++ )
            Dequant[ i ][ j ] = 0
    
    eob = 0
    culLevel = 0
    dcCategory = 0
    
    @@all_zero                                                                 S
    if ( all_zero ) {
        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 {
        if ( plane == 0 )
            transform_type( x4, y4, txSz )
        PlaneTxType = compute_tx_type( plane, txSz, x4, y4 )
        scan = get_scan( plane, txSz )
    
        eobMultisize = Tx_Width_Log2[ txSz ] + Tx_Height_Log2[ txSz ] - 4
        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
            eobPt = eob_pt_256 + 1
        } else if ( eobMultisize == 5 ) {
            @@eob_pt_512                                                       S
            eobPt = eob_pt_512 + 1
        } else {
            @@eob_pt_1024                                                      S
            eobPt = eob_pt_1024 + 1
        }

        eob = ( eobPt < 2 ) ? eobPt : ( ( 1 << ( eobPt - 2 ) ) + 1 )
        eobShift = Max( -1, eobPt - 3 )
        if ( eobShift >= 0 ) {
            @@eob_extra                                                        S
            if ( eob_extra ) {
                eob += ( 1 << eobShift )
            }

            for ( i = 1; i < Max( 0, eobPt - 2 ); i++ ) {
                eobShift = Max( 0, eobPt - 2 ) - 1 - i
                @@eob_extra_bit                                                L(1)
                if ( eob_extra_bit ) {
                    eob += ( 1 << eobShift )
                }
            }
        }
        for ( c = eob - 1; c >= 0; c-- ) {
            if ( c == ( eob - 1 ) ) {
                @@coeff_base_eob                                               S
                level = coeff_base_eob + 1
            } else {
                @@coeff_base                                                   S
                level = coeff_base
            }
            Quant[ scan[ c ] ] = level
        }
        
        for ( c = 0; c < eob; c++ ) {
            if ( Quant[ scan[ c ] ] != 0 ) {
                if ( c == 0 ) {
                    @@dc_sign                                                  S
                    signs[ c ] = dc_sign
                } else {
                    @@sign_bit                                                 L(1)
                    signs[ c ] = sign_bit
                }
            } else {
                signs[ c ] = 0
            }
        }
        
        for ( c = eob - 1; c >= 0; c-- ) {
            pos = scan[ c ]
            if ( Quant[ pos ] > NUM_BASE_LEVELS ) {
              for ( idx = 0;
                    idx < COEFF_BASE_RANGE / ( BR_CDF_SIZE - 1 );
                    idx++ ) {
                  @@coeff_br                                                   S
                  Quant[ pos ] += coeff_br
                  if ( coeff_br < ( BR_CDF_SIZE - 1 ) )
                      break
              }
              if ( Quant[ pos ] >
                  ( NUM_BASE_LEVELS + COEFF_BASE_RANGE ) ) {
                  length = 0
                  do {
                      length++
                      @@golomb_length_bit                                      L(1)
                  } while ( !golomb_length_bit )
                  x = 1
                  for ( i = length - 2; i >= 0; i-- ) {
                      @@golomb_data_bit                                        L(1)
                      x = ( x << 1 ) | golomb_data_bit
                  }
                  Quant[ pos ] = x + COEFF_BASE_RANGE + NUM_BASE_LEVELS
              }
            }
        }
        
        for ( c = 0; c < eob; c++ ) {
            culLevel += Quant[ scan[ c ] ]
        }
        
        coeffMin = - ( 1 << ( 7 + BitDepth ) )
        coeffMax = ( 1 << ( 7 + BitDepth ) ) - 1
        
        for ( c = 0; c < eob; c++ ) {
            if ( signs[ c ] )
                Quant[ scan[ c ] ] = - Quant[ scan[ c ] ]
            Quant[ scan[ c ] = Clip3( coeffMin, coeffMax, Quant[ scan[ c ] ] )
        }

        culLevel = Min( 63, culLevel )
        
        if ( Quant[ 0 ] < 0 ) {
            dcCategory = 1
        } else if ( Quant[ 0 ] > 0 ) {
            dcCategory = 2
        }
    }
    
    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
}

{:.syntax }

Compute Transform Type Function

compute_tx_type( plane, txSz, blockX, blockY ) {
    txSzSqrUp = Tx_Size_Sqr_Up[ txSz ]
    
    if ( Lossless || txSzSqrUp > TX_32X32 )
        return DCT_DCT
        
    set = get_tx_set( txSz )
    
    if ( plane == 0 ) {
        txType = TxTypes[ blockY ][ blockX ]
        if ( !Tx_Type_In_Set[ set ][ txType ] )
            return DCT_DCT
        return txType
    }
    
    if ( RefFrame[ 0 ] != INTRA_FRAME ) {
        txType = TxTypes[ blockY << subsampling_y ][ blockX << subsampling_x ]
        if ( !Tx_Type_In_Set[ set ][ txType ] )
            return DCT_DCT
        return txType
    }
    
    txType = Mode_To_Txfm[ UVMode ]
    if ( !Tx_Type_In_Set[ set ][ txType ] )
        return DCT_DCT
    return txType
}

{:.syntax }

Get Scan Function

get_mrow_scan( txSz ) {
    if ( txSz == TX_4X4 )
        return Mrow_Scan_4x4
    else if ( txSz == TX_4X8 )
        return Mrow_Scan_4x8
    else if ( txSz == TX_8X4 )
        return Mrow_Scan_8x4
    else if ( txSz == TX_8X8 )
        return Mrow_Scan_8x8
    else if ( txSz == TX_8X16 )
        return Mrow_Scan_8x16
    else if ( txSz == TX_16X8 )
        return Mrow_Scan_16x8
    else if ( txSz == TX_16X16 )
        return Mrow_Scan_16x16
    else if ( txSz == TX_16X32 )
        return Mrow_Scan_16x32
    else if ( txSz == TX_32X16 )
        return Mrow_Scan_32x16
    else if ( txSz == TX_4X16 )
        return Mrow_Scan_4x16
    else if ( txSz == TX_16X4 )
        return Mrow_Scan_16x4
    else if ( txSz == TX_8X32 )
        return Mrow_Scan_8x32
    else if ( txSz == TX_32X8 )
        return Mrow_Scan_32x8
    return Mrow_Scan_32x32
}

get_row_scan( txSz ) {
    if ( txSz == TX_4X4 )
        return Row_Scan_4x4
    else if ( txSz == TX_8X8 )
        return Row_Scan_8x8
    return Row_Scan_16x16
}

get_mcol_scan( txSz ) {
    if ( txSz == TX_4X4 )
        return Mcol_Scan_4x4
    else if ( txSz == TX_4X8 )
        return Mcol_Scan_4x8
    else if ( txSz == TX_8X4 )
        return Mcol_Scan_8x4
    else if ( txSz == TX_8X8 )
        return Mcol_Scan_8x8
    else if ( txSz == TX_8X16 )
        return Mcol_Scan_8x16
    else if ( txSz == TX_16X8 )
        return Mcol_Scan_16x8
    else if ( txSz == TX_16X16 )
        return Mcol_Scan_16x16
    else if ( txSz == TX_16X32 )
        return Mcol_Scan_16x32
    else if ( txSz == TX_32X16 )
        return Mcol_Scan_32x16
    else if ( txSz == TX_4X16 )
        return Mcol_Scan_4x16
    else if ( txSz == TX_16X4 )
        return Mcol_Scan_16x4
    else if ( txSz == TX_8X32 )
        return Mcol_Scan_8x32
    else if ( txSz == TX_32X8 )
        return Mcol_Scan_32x8
    return Mcol_Scan_32x32
}

get_col_scan( txSz ) {
    if ( txSz == TX_4X4 )
        return Col_Scan_4x4
    else if ( txSz == TX_8X8 )
        return Col_Scan_8x8
    return Col_Scan_16x16
}

get_default_scan( txSz ) {
    if ( txSz == TX_4X4 )
        return Default_Scan_4x4
    else if ( txSz == TX_4X8 )
        return Default_Scan_4x8
    else if ( txSz == TX_8X4 )
        return Default_Scan_8x4
    else if ( txSz == TX_8X8 )
        return Default_Scan_8x8
    else if ( txSz == TX_8X16 )
        return Default_Scan_8x16
    else if ( txSz == TX_16X8 )
        return Default_Scan_16x8
    else if ( txSz == TX_16X16 )
        return Default_Scan_16x16
    else if ( txSz == TX_16X32 )
        return Default_Scan_16x32
    else if ( txSz == TX_32X16 )
        return Default_Scan_32x16
    else if ( txSz == TX_4X16 )
        return Default_Scan_4x16
    else if ( txSz == TX_16X4 )
        return Default_Scan_16x4
    else if ( txSz == TX_8X32 )
        return Default_Scan_8x32
    else if ( txSz == TX_32X8 )
        return Default_Scan_32X8
    return Default_Scan_32x32
}

get_scan( plane, txSz ) {
    if ( txSz == TX_16X64 ) {
        return Default_Scan_16x32
    }
    if ( txSz == TX_64X16 ) {
        return Default_Scan_32x16
    }
    if ( Tx_Size_Sqr_Up[ txSz ] == TX_64X64 ) {
        return Default_Scan_32x32
    }
    
    if ( PlaneTxType == IDTX ) {
        return get_mrow_scan( txSz )
    }
    
    preferRow = ( PlaneTxType == ADST_DCT ||
                  PlaneTxType == V_DCT ||
                  PlaneTxType == V_ADST ||
                  PlaneTxType == V_FLIPADST )

    preferCol = ( PlaneTxType == DCT_ADST ||
                  PlaneTxType == H_DCT ||
                  PlaneTxType == H_ADST ||
                  PlaneTxType == H_FLIPADST )

    usesIdTx  = ( PlaneTxType == V_DCT ||
                  PlaneTxType == V_ADST ||
                  PlaneTxType == V_FLIPADST ||
                  PlaneTxType == H_DCT ||
                  PlaneTxType == H_ADST ||
                  PlaneTxType == H_FLIPADST )

    preferRaster = !( ( txSz == TX_4X4 ||
                        txSz == TX_8X8 ||
                        txSz == TX_16X16 ) && !is_inter )

    if ( !usesIdTx ) {
        if ( txSz == TX_32X32 ) {
            return Default_Scan_32x32
        } else if ( is_inter && Abs( Tx_Width_Log2[ txSz ] - Tx_Height_Log2[ txSz ] ) < 2 ) {
            preferRow = 0
            preferCol = 0
        }
    }

    if (preferRow) {
        return preferRaster ? get_mrow_scan( txSz ) : get_row_scan( txSz )
    } else if (preferCol) {
        return preferRaster ? get_mcol_scan( txSz ) : get_col_scan( txSz )
    }
    return get_default_scan( txSz )
}

{:.syntax }

Intra Angle Info Syntax

intra_angle_info( ) {
    if ( MiSize >= BLOCK_8X8 ) {
        if ( is_directional_mode( YMode ) ) {
            @@angle_delta_y                                                    S
            AngleDeltaY = angle_delta_y - MAX_ANGLE_DELTA
        }
        if ( is_directional_mode( UVMode ) ) {
            @@angle_delta_uv                                                   S
            AngleDeltaUV = angle_delta_uv - MAX_ANGLE_DELTA
        }
    }
}

{:.syntax }

Is Directional Mode Function

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

{:.syntax }

Read CFL Alphas Syntax

read_cfl_alphas() {
    @@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
    }
}

{:.syntax }

Palette Mode Info Syntax

palette_mode_info( ) {
    bsizeCtx = Mi_Width_Log2[ MiSize ] + Mi_Height_Log2[ MiSize ]
    if ( 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( 0 )
            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, ceil( log2( range ) ) )
                idx++
            }
            sort( palette_colors_y, 0, PaletteSizeY - 1 )
        }
    }
    if ( UVMode == DC_PRED && HasChroma ) {
        @@has_palette_uv                                                       S
        if ( has_palette_uv ) {
            @@palette_size_uv_minus_2                                          S
            PaletteSizeUV = palette_size_uv_minus_2 + 2
            cacheN = get_palette_cache( 1 )
            idx = 0
            for ( i = 0; i < cacheN && idx < PaletteSizeUV; i++ ) {
                @@use_palette_color_cache_u                                    L(1)
                if ( use_palette_color_cache_u ) {
                    palette_colors_u[ idx ] = PaletteCache[ i ]
                    idx++
                }
            }
            if ( idx < PaletteSizeUV ) {
                @@palette_colors_u[ idx ]                                      L(BitDepth)
                idx++
            }
            if ( idx < PaletteSizeUV ) {
                minBits = BitDepth - 3
                @@palette_num_extra_bits_u                                     L(2)
                paletteBits = minBits + palette_num_extra_bits_u
            }
            while ( idx < PaletteSizeUV ) {
                @@palette_delta_u                                              L(paletteBits)
                palette_colors_u[ idx ] = 
                          Clip1( palette_colors_u[ idx - 1 ] +
                                 palette_delta_u )
                range = ( 1 << BitDepth ) - palette_colors_u[ idx ]
                paletteBits = Min( paletteBits, ceil( log2( range ) ) )
                idx++
            }
            sort( palette_colors_u, 0, PaletteSizeUV - 1 )
            
            @@delta_encode_palette_colors_v                                    L(1)
            if ( delta_encode_palette_colors_v ) {
                minBits = BitDepth - 4
                maxVal = 1 << BitDepth
                @@palette_num_extra_bits_v                                     L(2)
                paletteBits = minBits + palette_num_extra_bits_v
                @@palette_colors_v[ 0 ]                                        L(BitDepth)
                for ( idx = 1; idx < PaletteSizeUV; idx++ ) {
                    @@palette_delta_v                                          L(paletteBits)
                    if ( palette_delta_v ) {
                        @@palette_delta_sign_bit_v                             L(1)
                        if ( palette_delta_sign_bit_v ) {
                            palette_delta_v = -palette_delta_v
                        }
                    }
                    val = palette_colors_v[ idx - 1 ] + palette_delta_v
                    if ( val < 0 ) val += maxVal
                    if ( val >= maxVal ) val -= maxVal
                    palette_colors_v[ idx ] = Clip1( val )
                }
            } else {
                for ( idx = 0; idx < PaletteSizeUV; idx++ ) {
                    @@palette_colors_v[ idx ]                                  L(BitDepth)
                }
            }
        }
    }
}

{:.syntax }

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. {:.alert .alert-info }

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

get_palette_cache( plane ) {
    aboveN = 0
    if ( ( ( MiRow * MI_SIZE ) % 64 ) && AvailU ) {
        aboveN = PaletteSizes[ plane ][ MiRow - 1 ][ MiCol ]
    }
    leftN = 0
    if ( AvailL ) {
        leftN = PaletteSizes[ plane ][ MiRow ][ MiCol - 1 ]
    }
    aboveIdx = 0
    leftIdx = 0
    n = 0
    while ( aboveIdx < aboveN  && leftIdx < leftN ) {
        aboveC = PaletteColors[ plane ][ MiRow - 1 ][ MiCol ][ aboveIdx ]
        leftC = PaletteColors[ plane ][ MiRow ][ MiCol - 1 ][ leftIdx ]
        if ( leftC < aboveC ) {
            if ( n == 0 || leftC != PaletteCache[ n - 1 ] ) {
                PaletteCache[ n ] = leftC
                n++
            }
            leftIdx++
        } else {
            if ( n == 0 || aboveC != PaletteCache[ n - 1 ] ) {
                PaletteCache[ n ] = aboveC
                n++
            }
            aboveIdx++
            if ( leftC == aboveC ) {
                leftIdx++
            }
        }
    }
    while ( aboveIdx < aboveN ) {
        val = PaletteColors[ plane ][ MiRow - 1 ][ MiCol ][ aboveIdx ]
        aboveIdx++
        if ( n == 0 || val != PaletteCache[ n - 1 ] ) {
            PaletteCache[ n ] = val
            n++
        }
    }
    while ( leftIdx < leftN ) {
        val = PaletteColors[ plane ][ MiRow ][ MiCol - 1 ][ leftIdx ]
        leftIdx++
        if ( n == 0 || val != PaletteCache[ n - 1 ] ) {
            PaletteCache[ n ] = val
            n++
        }
    }
    return n
}

{:.syntax }

Note: get_palette_cache is equivalent to sorting the available palette colors from above and left together and removing any duplicates. {:.alert .alert-info }

Transform Type Syntax

transform_type( x4, y4, txSz ) {
    set = get_tx_set( txSz )

    if ( set > 0 &&
         ( segmentation_enabled ? get_qindex( 1, segment_id ) : base_q_idx ) > 0 &&
         !skip &&
         !seg_feature_active( SEG_LVL_SKIP ) ) {
        if ( is_inter ) {
            @@inter_tx_type                                                    S
            if ( set == 1 )
                TxType = Tx_Type_Inter_Inv_Set1[ inter_tx_type ]
            else if ( set == 2 )
                TxType = Tx_Type_Inter_Inv_Set2[ inter_tx_type ]
            else
                TxType = Tx_Type_Inter_Inv_Set3[ inter_tx_type ]
        } else {
            @@intra_tx_type                                                    S
            if ( set == 1 )
                TxType = Tx_Type_Intra_Inv_Set1[ intra_tx_type ]
            else
                TxType = Tx_Type_Intra_Inv_Set2[ intra_tx_type ]
        }
    } else {
        TxType = DCT_DCT
    }
    for ( i = 0; i < ( Tx_Width[ txSz ] >> 2 ); i++ ) {
        for ( j = 0; j < ( Tx_Height[ txSz ] >> 2 ); j++ ) {
            TxTypes[ y4 + j ][ x4 + i ] = TxType
        }
    }
}

{:.syntax }

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

Tx_Type_Intra_Inv_Set1[ 7 ]  = { IDTX, DCT_DCT, V_DCT, H_DCT, ADST_ADST, ADST_DCT, DCT_ADST }
Tx_Type_Intra_Inv_Set2[ 5 ]  = { IDTX, DCT_DCT, ADST_ADST, ADST_DCT, DCT_ADST }
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 }

Get Transform Set Function

get_tx_set( txSz ) {
    txSzSqr = Tx_Size_Sqr[ txSz ]
    txSzSqrUp = Tx_Size_Sqr_Up[ txSz ]
    if ( txSzSqrUp > TX_32X32 )
        return TX_SET_DCTONLY
    if ( is_inter ) {
        if ( reduced_tx_set || txSzSqrUp == TX_32X32 ) return TX_SET_INTER_3
        else if ( txSzSqr == TX_16X16 ) return TX_SET_INTER_2
        return TX_SET_INTER_1
    }
    else {
        if ( txSzSqrUp == TX_32X32 ) return TX_SET_DCTONLY
        else if ( reduced_tx_set ) return TX_SET_INTRA_2
        else if ( txSzSqr == TX_16X16 ) return TX_SET_INTRA_2
        return TX_SET_INTRA_1
    }
}

{:.syntax }

Palette Tokens Syntax

palette_tokens( ) {
    blockHeight = Block_Height[ MiSize ]
    blockWidth = Block_Width[ MiSize ]
    onscreenHeight = Min( blockHeight, (MiRows - MiRow) * MI_SIZE )
    onscreenWidth = Min( blockWidth, (MiCols - MiCol) * MI_SIZE )

    if ( PaletteSizeY ) {
        @@color_index_map_y                                                    U(PaletteSizeY)
        ColorMapY[0][0] = color_index_map_y
        for ( i = 1; i < onscreenHeight + onscreenWidth - 1; i++ ) {
            for ( j = Min( i, onscreenWidth - 1 ); j >= Max( 0, i - onscreenHeight + 1 ); j-- ) {
                get_palette_color_context( ColorMapY, ( i - j ), j, PaletteSizeY )
                @@palette_color_idx_y                                   S
                ColorMapY[ i - j ][ j ] = ColorOrder[ palette_color_idx_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 ]
            }
        }
    }

    if ( PaletteSizeUV ) {
        @@color_index_map_uv                                                   U(PaletteSizeUV)
        ColorMapUV[0][0] = color_index_map_uv
        blockHeight = blockHeight >> subsampling_y
        blockWidth = blockWidth >> subsampling_x
        onscreenHeight = onscreenHeight >> subsampling_y
        onscreenWidth = onscreenWidth >> subsampling_x
        if ( blockWidth < 4 ) {
            blockWidth += 2
            onscreenWidth += 2
        }
        if ( blockHeight < 4 ) {
            blockHeight += 2
            onscreenHeight += 2
        }

        for ( i = 1; i < onscreenHeight + onscreenWidth - 1; i++ ) {
            for ( j = Min( i, onscreenWidth - 1 ); j >= Max( 0, i - onscreenHeight + 1 ); j-- ) {
                get_palette_color_context( ColorMapUV, ( i - j ), j, PaletteSizeUV )
                @@palette_color_idx_uv                                  S
                ColorMapUV[ i - j ][ j ] = ColorOrder[ palette_color_idx_uv ]
            }
        }
        for ( i = 0; i < onscreenHeight; i++ ) {
            for ( j = onscreenWidth; j < blockWidth; j++ ) {
                ColorMapUV[ i ][ j ] = ColorMapUV[ i ][ onscreenWidth - 1 ]
            }
        }
        for ( i = onscreenHeight; i < blockHeight; i++ ) {
            for ( j = 0; j < blockWidth; j++ ) {
                ColorMapUV[ i ][ j ] = ColorMapUV[ onscreenHeight - 1 ][ j ]
            }
        }
    }
}

{:.syntax }

Palette Color Context Function

get_palette_color_context( colorMap, r, c, n ) {
    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
            }
        }
        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 ]
    }
}

{:.syntax }

Is Inside Function

is_inside determines whether a candidate position is accessible. Moving across the top tile edge is allowed when dependent_tiles is equal to 1 and allowed by the AllowDependentTileRow array, but moving across the other tile edges is always prohibited.

is_inside( candidateR, candidateC ) {
    if (candidateC >= MiColStart &&
        candidateC < MiColEnd &&
        candidateR < MiRowEnd) {
        if (candidateR >= MiRowStart)
            return 1
        if (dependent_tiles && AllowDependentTileRow[ TileRow ])
            return 1
    }
    return 0
}

{:.syntax }

Is Inside Filter Region Function

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

is_inside_filter_region( candidateR, candidateC ) {
    colStart = loop_filter_across_tiles_v ? 0 : MiColStart
    colEnd = loop_filter_across_tiles_v ? MiCols : MiColEnd
    rowStart = loop_filter_across_tiles_h ? 0 : MiRowStart
    rowEnd = loop_filter_across_tiles_h ? MiRows : MiRowEnd
    return (candidateC >= colStart &&
            candidateC < colEnd &&
            candidateR >= rowStart &&
            candidateR < rowEnd)
}

{:.syntax }

Check References Functions

This section defines some simple helper functions used in other parts of the specification:

check_backward(refFrame) {
  return ( (refFrame >= BWDREF_FRAME) && (refFrame <= ALTREF_FRAME) )
} 

check_last_or_last2(refFrame) {
  return ( (refFrame == LAST_FRAME) || (refFrame == LAST2_FRAME) )
}

check_golden_or_last3(refFrame) {
  return ( (refFrame == GOLDEN_FRAME) || (refFrame == LAST3_FRAME) )
}

check_last(refFrame) {
  return (refFrame == LAST_FRAME)
}

check_last2(refFrame) {
  return (refFrame == LAST2_FRAME)
}

check_last3(refFrame) {
  return (refFrame == LAST3_FRAME)
}

check_golden(refFrame) {
  return (refFrame == GOLDEN_FRAME)
}

{:.syntax }

Clamp MV Row Function

clamp_mv_row( mvec, border ) {
    bh4 = Num_4x4_Blocks_High[ MiSize ]
    mbToTopEdge = -((MiRow * MI_SIZE) * 8)
    mbToBottomEdge = ((MiRows - bh4 - MiRow) * MI_SIZE) * 8
    return Clip3( mbToTopEdge - border, mbToBottomEdge + border, mvec )
}

{:.syntax }

Clamp MV Col Function

clamp_mv_col( mvec, border ) {
    bw4 = Num_4x4_Blocks_Wide[ MiSize ]
    mbToLeftEdge = -((MiCol * MI_SIZE) * 8)
    mbToRightEdge = ((MiCols - bw4 - MiCol) * MI_SIZE) * 8
    return Clip3( mbToLeftEdge - border, mbToRightEdge + border, mvec )
}

{:.syntax }

Clear CDEF Function

clear_cdef( r, c ) {
    cdef_idx[ r ][ c ] = -1
    if ( use_128x128_superblock ) {
        cdefSize4 = Num_4x4_Blocks_Wide[ BLOCK_64X64 ]
        cdef_idx[ r ][ c + cdefSize4 ] = -1
        cdef_idx[ r + cdefSize4][ c ] = -1
        cdef_idx[ r + cdefSize4][ c + cdefSize4 ] = -1
    }
}

{:.syntax }

Read CDEF Syntax

read_cdef( ) {
    if ( allow_intrabc || AllLossless) {
        return
    }
    cdefSize4 = Num_4x4_Blocks_Wide[ BLOCK_64X64 ]
    cdefMask4 = ~(cdefSize4 - 1)
    r = MiRow & cdefMask4
    c = MiCol & cdefMask4
    if ( cdef_idx[ r ][ c ] == -1 ) {
        @@cdef_idx[ r ][ c ]                                               L(cdef_bits)
        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 ]
            }
        }
    }
}

{:.syntax }

Decode Loop Restoration Syntax

decode_lr( r, c, bSize ) {
    if ( allow_intrabc ) {
        return
    }
    w = Num_4x4_Blocks_Wide[ bSize ]
    h = Num_4x4_Blocks_High[ bSize ]
    for (plane = 0; plane < NumPlanes; plane++) {
        if (FrameRestorationType[ plane ] == RESTORE_NONE)
            continue
        subX = (plane == 0) ? 0 : subsampling_x
        subY = (plane == 0) ? 0 : subsampling_y
        unitSize = LoopRestorationSize[ plane ]
        tileLeft = upscale_mi_to_pos(MiColStart, plane)
        tileRight = upscale_mi_to_pos(MiColEnd, plane)
        unitRows = count_units_in_tile( unitSize, (MiRowEnd - MiRowStart) * ( MI_SIZE >> subY ) )
        unitCols = count_units_in_tile( unitSize, tileRight - tileLeft )
        relMiRow = r - MiRowStart
        relMiCol = c - MiColStart
        unitRowStart = ( relMiRow * ( MI_SIZE >> subY) + unitSize - 1 ) / unitSize
        unitRowEnd = Min( unitRows, ( (relMiRow + h) * ( MI_SIZE >> subY) + unitSize - 1 ) / unitSize)
        if ( use_superres ) {
            numerator = (MI_SIZE >> subX) * SuperresDenom
            denominator = unitSize * SUPERRES_NUM
        } else {
            numerator = MI_SIZE >> subX
            denominator = unitSize
        }
        unitColStart = ( relMiCol * numerator + denominator - 1 ) / denominator
        unitColEnd = Min( unitCols, ( (relMiCol + w) * numerator + denominator - 1 ) / denominator)
        for (unitRow = unitRowStart; unitRow < unitRowEnd; unitRow++) {
            for (unitCol = unitColStart; unitCol < unitColEnd; unitCol++) {
                decode_lr_unit(plane, unitRow, unitCol)
            }
        }
    }
}

{:.syntax }

where count_units_in_tile is a function specified as:

count_units_in_tile(unitSize, tileSize) {
    return Max((tileSize + (unitSize >> 1)) / unitSize, 1)
}

and upscale_mi_to_pos is a function that converts a x position (in units of 4x4 luma blocks) to an upsampled sample position in the specified plane specified as:

upscale_mi_to_pos( miX, plane ) {
  if (plane > 0) {
      subX = subsampling_x
  } else {
      subX = 0
  }
  if ( miX == MiCols ) {
      return Round2( UpscaledWidth, subX )
  }
  downscaleX = ( miX * MI_SIZE ) >> subX
  if ( use_superres ) {
    upscaleX = ( downscaleX * SuperresDenom ) / SUPERRES_NUM
  } else {
    upscaleX = downscaleX
  }
  return upscaleX
}

Decode Loop Restoration Unit Syntax

decode_lr_unit(plane, unitRow, unitCol) {
    if (FrameRestorationType[ plane ] == RESTORE_NONE) {
        restoration_type = RESTORE_NONE
    } else if (FrameRestorationType[ plane ] == RESTORE_WIENER) {
        @@use_wiener                                                           S
        restoration_type = use_wiener ? RESTORE_WIENER : RESTORE_NONE
    } else if (FrameRestorationType[ plane ] == RESTORE_SGRPROJ) {
        @@use_sgrproj                                                          S
        restoration_type = use_sgrproj ? RESTORE_SGRPROJ : RESTORE_NONE
    } else {
        @@restoration_type                                                     S
    }
    LrType[ TileNum ][ plane ][ unitRow ][ unitCol ] = restoration_type
    if (restoration_type == RESTORE_WIENER) {
        for ( pass = 0; pass < 2; pass++ ) {
            if (plane) {
                firstCoeff = 1
                LrWiener[ TileNum ][ plane ]
                        [ unitRow ][ unitCol ][ pass ][0] = 0
            } else {
                firstCoeff = 0
            }
            for (j = firstCoeff; j < 3; j++) {
                min = Wiener_Taps_Min[ j ]
                max = Wiener_Taps_Max[ j ]
                k = Wiener_Taps_K[ j ]
                v = decode_signed_subexp_with_ref_bool(
                        min, max + 1, k, RefLrWiener[ plane ][ pass ][ j ] )
                LrWiener[ TileNum ][ plane ]
                        [ unitRow ][ unitCol ][ pass ][ j ] = v
                RefLrWiener[ plane ][ pass ][ j ] = v
            }
        }
    } else if (restoration_type == RESTORE_SGRPROJ) {
        @@lr_sgr_set                                                           U(SGRPROJ_PARAMS_BITS)
        LrSgrSet[ TileNum ][ plane ][ unitRow ][ unitCol ] = lr_sgr_set
        for (i = 0; i < 2; i++) {
            min = Sgrproj_Xqd_Min[i]
            max = Sgrproj_Xqd_Max[i]
            v = decode_signed_subexp_with_ref_bool(
                     min, max + 1, SGRPROJ_PRJ_SUBEXP_K, RefSgrXqd[ plane ][ i ])
            LrSgrXqd[ TileNum ][ plane ][ unitRow ][ unitCol ][ i ] = v
            RefSgrXqd[ plane ][ i ] = v
        }
    } 
}

{:.syntax }

where Wiener_Taps_Min, Wiener_Taps_Max, ,Wiener_Taps_K, Sgrproj_Xqd_Min, and Sgrproj_Xqd_Max are constant lookup tables:

Wiener_Taps_Min[3] = { -5, -23, -17 }
Wiener_Taps_Max[3] = { 10,   8,  46 }
Wiener_Taps_K[3] = { 1, 2, 3 }

Sgrproj_Xqd_Min[2] = { -96, -32 }
Sgrproj_Xqd_Max[2] = {  31,  95 }

and decode_signed_subexp_with_ref_bool is a function specified as follows:

decode_signed_subexp_with_ref_bool( low, high, k, r ) {
    x = decode_unsigned_subexp_with_ref_bool(high - low, k, r - low)
    return x + low
}

decode_unsigned_subexp_with_ref_bool( mx, k, r ) {
    v = decode_subexp_bool( mx, k )
    if ((r << 1) <= mx) {
        return inverse_recenter(r, v)
    } else {
        return mx - 1 - inverse_recenter(mx - 1 - r, v)
    }
}

decode_subexp_bool( numSyms, k ) {
    i = 0
    mk = 0
    while (1) {
        b2 = i ? k + i - 1 : k
        a = 1 << b2
        if (numSyms <= mk + 3 * a) {
            @@subexp_unif_bools                                                U(numSyms - mk)
            return subexp_unif_bools + mk
        } else {
            @@subexp_more_bools                                                L(1)
            if (subexp_more_bools) {
               i++
               mk += a
            } else {
               @@subexp_bools                                                  L(b2)
               return subexp_bools + mk
            }
        }
    }
}

{:.syntax }

Note: The decode_signed_subexp_with_ref_bool function is the same as the decode_signed_subexp_with_ref function except that the bits used to represent the symbol are arithmetic coded instead of being read directly from the bitstream. {:.alert .alert-info }