《AV1 Bitstream & Decoding Process Specification》,译名:AV1比特流及解码规范-Chapter 05-语法结构-Section 09~10

本文详细介绍了AV1比特流解码规范中帧数据头OBU(frame_header_obu)的语法结构,包括frame_header、uncompressed_header、render_size、loop_filter_params等关键部分,以及与解码相关的函数如get_relative_dist、mark_ref_frames等。内容涵盖了帧尺寸、超级分辨率参数、量化参数、循环滤波、分段参数、全局运动参数等多个方面。
摘要由CSDN通过智能技术生成

Table of Contents

5.9 帧数据头OBU语法

5.9.1 frame_header_obu语法

5.9.2 uncompressed_header语法

5.9.3 get_relative_dist函数

5.9.4 mark_ref_frames函数

5.9.6 render_size语法

5.9.7 frame_size_with_refs语法

5.9.8 superres_params语法

5.9.9 compute_image_size函数

5.9.10 read_interpolation_filter语法

5.9.11 loop_filter_params语法

5.9.12 quantization_params语法

5.9.13 read_delta_q语法

5.9.14 segmentation_params语法

5.9.15 tile_info语法

5.9.16 tile_log2函数

5.9.17 delta_q_params语法

5.9.18 delta_lf_params语法

5.9.19 cdef_params语法

5.9.20 lr_params语法

5.9.21 read_tx_mode语法

5.9.22 skip_mode_params语法

5.9.23 frame_reference_mode语法

5.9.24 global_motion_params语法

5.9.25 read_global_param语法

5.9.26 decode_signed_subexp_with_ref语法

5.9.27 decode_unsigned_subexp_with_ref语法

5.9.28 decode_subexp语法

5.9.29 inverse_recenter函数

5.9.30 film_grain_params语法

5.9.31 temporal_point_info语法

5.10 帧OBU语法


5.9 帧数据头OBU语法

5.9.1 frame_header_obu语法

frame_header_obu( ) 
{
    if ( SeenFrameHeader == 1 )
    {
        frame_header_copy()
    } 
    else 
    {
        SeenFrameHeader = 1
        uncompressed_header( )
        if ( show_existing_frame ) 
        {
            decode_frame_wrapup( )
            SeenFrameHeader = 0
        } 
        else 
        {
            TileNum = 0
            SeenFrameHeader = 1
        }
    }
}

5.9.2 uncompressed_header语法

uncompressed_header( ) 
{
    if ( frame_id_numbers_present_flag ) 
    {
        idLen = (additional_frame_id_length_minus_1 + delta_frame_id_length_minus_2 + 3)
    }
    allFrames = (1 << NUM_REF_FRAMES) - 1
    if ( reduced_still_picture_header ) 
    {
        show_existing_frame = 0
        frame_type = KEY_FRAME
        FrameIsIntra = 1
        show_frame = 1
        showable_frame = 0
    } 
    else 
    {
        show_existing_frame            // Type f(1)
        if ( show_existing_frame == 1 ) 
        {
            frame_to_show_map_idx            // Type f(3)
            if ( decoder_model_info_present_flag && !equal_picture_interval ) 
            {
                temporal_point_info( )
            }
            refresh_frame_flags = 0
            if ( frame_id_numbers_present_flag ) 
            {
                display_frame_id            // Type f(idLen)
            }
            frame_type = RefFrameType[ frame_to_show_map_idx ]
            if ( frame_type == KEY_FRAME ) 
            {
                refresh_frame_flags = allFrames
            }
            if ( film_grain_params_present ) 
            {
                load_grain_params( frame_to_show_map_idx )
            }
            return
        }
        frame_type           // Type f(2)
        FrameIsIntra = (frame_type == INTRA_ONLY_FRAME || frame_type == KEY_FRAME)
        show_frame            // Type f(1)
        if ( show_frame && decoder_model_info_present_flag && !equal_picture_interval ) 
        {
            temporal_point_info( )
        }
        if ( show_frame ) 
        {
            showable_frame = frame_type != KEY_FRAME
        } 
        else 
        {
            showable_frame           // Type f(1)
        }
        if ( frame_type == SWITCH_FRAME || ( frame_type == KEY_FRAME && show_frame ) )
            error_resilient_mode = 1
        else
            error_resilient_mode           // Type f(1)
    }
    if ( frame_type == KEY_FRAME && show_frame ) 
    {
        for ( i = 0; i < NUM_REF_FRAMES; i++ ) 
        {
            RefValid[ i ] = 0
            RefOrderHint[ i ] = 0
        }
        for ( i = 0; i < REFS_PER_FRAME; i++ ) 
        {
            OrderHints[ LAST_FRAME + i ] = 0
        }
    }
    disable_cdf_update            // Type f(1)
    if ( seq_force_screen_content_tools == SELECT_SCREEN_CONTENT_TOOLS ) 
    {
        allow_screen_content_tools           // Type f(1)
    } 
    else 
    {
        allow_screen_content_tools = seq_force_screen_content_tools
    }
    if ( allow_screen_content_tools ) 
    {
        if ( seq_force_integer_mv == SELECT_INTEGER_MV ) 
        {
            force_integer_mv            // Type f(1)
        } 
        else 
        {
            force_integer_mv = seq_force_integer_mv
        }
    } 
    else 
    {
        force_integer_mv = 0
    }
    if ( FrameIsIntra ) 
    {
        force_integer_mv = 1
    }
    if ( frame_id_numbers_present_flag ) 
    {
        PrevFrameID = current_frame_id
        current_frame_id            // Type f(idLen)
        mark_ref_frames( idLen )
    } 
    else 
    {
        current_frame_id = 0
    }
    if ( frame_type == SWITCH_FRAME )
        frame_size_override_flag = 1
    else if ( reduced_still_picture_header )
        frame_size_override_flag = 0
    else
        frame_size_override_flag           // Type f(1)
    order_hint            // Type f(OrderHintBits)
    OrderHint = order_hint
    if ( FrameIsIntra || error_resilient_mode ) 
    {
        primary_ref_frame = PRIMARY_REF_NONE
    } 
    else 
    {
        primary_ref_frame           // Type f(3)
    }
    if ( decoder_model_info_present_flag ) 
    {
        buffer_removal_time_present_flag            // Type f(1)
        if ( buffer_removal_time_present_flag ) 
        {
            for ( opNum = 0; opNum <= operating_points_cnt_minus_1; opNum++ ) 
            {
                if ( decoder_model_present_for_this_op[ opNum ] ) 
                {
                    opPtIdc = operating_point_idc[ opNum ]
                    inTemporalLayer = ( opPtIdc >> temporal_id ) & 1
                    inSpatialLayer = ( opPtIdc >> ( spatial_id + 8 ) ) & 1
                    if ( opPtIdc == 0 || ( inTemporalLayer && inSpatialLayer ) ) 
                    {
                        n = buffer_removal_time_length_minus_1 + 1
                        buffer_removal_time[ opNum ]            // Type f(n)
                    }
                }
            }
        }
    }
    allow_high_precision_mv = 0
    use_ref_frame_mvs = 0
    allow_intrabc = 0
    if ( frame_type == SWITCH_FRAME || ( frame_type == KEY_FRAME && show_frame ) ) 
    {
        refresh_frame_flags = allFrames
    } 
    else 
    {
        refresh_frame_flags            // Type f(8)
    }
    if ( !FrameIsIntra || refresh_frame_flags != allFrames ) 
    {
        if ( error_resilient_mode && enable_order_hint ) 
        {
            for ( i = 0; i < NUM_REF_FRAMES; i++) 
            {
                ref_order_hint[ i ]            // Type f(OrderHintBits)
                if ( ref_order_hint[ i ] != RefOrderHint[ i ] ) 
                {
                    RefValid[ i ] = 0
                }
            }
        }
    }
    if ( FrameIsIntra ) 
    {
        frame_size( )
        render_size( )
        if ( allow_screen_content_tools && UpscaledWidth == FrameWidth ) 
        {
            allow_intrabc            // Type f(1)
        }
    } 
    else 
    {
        if ( !enable_order_hint ) 
        {
            frame_refs_short_signaling = 0
        } 
        else 
        {
            frame_refs_short_signaling            // Type f(1)
            if ( frame_refs_short_signaling ) 
            {
                last_frame_idx           // Type f(3)
                gold_frame_idx           // Type f(3)
                set_frame_refs()
            }
        }
        for ( i = 0; i < REFS_PER_FRAME; i++ ) 
        {
            if ( !frame_refs_short_signaling )
                ref_frame_idx[ i ]           // Type f(3)
            if ( frame_id_numbers_present_flag ) 
            {
                n = delta_frame_id_length_minus_2 + 2
                delta_frame_id_minus_1           // Type f(n)
                DeltaFrameId = delta_frame_id_minus_1 + 1
                expectedFrameId[ i ] = ((current_frame_id + (1 << idLen) - DeltaFrameId ) % (1 << idLen))
            }
        }
        if ( frame_size_override_flag && !error_resilient_mode ) 
        {
            frame_size_with_refs( )
        } 
        else 
        {
            frame_size( )
            render_size( )
        }
        if ( force_integer_mv ) 
        {
            allow_high_precision_mv = 0
        } 
        else 
        {
            allow_high_precision_mv            // Type f(1)
        }
        read_interpolation_filter( )
        is_motion_mode_switchable           // Type f(1)
        if ( error_resilient_mode || !enable_ref_frame_mvs ) 
        {
            use_ref_frame_mvs = 0
        } 
        else 
        {
            use_ref_frame_mvs            // Type f(1)
        }
        for ( i = 0; i < REFS_PER_FRAME; i++ ) 
        {
            refFrame = LAST_FRAME + i
            hint = RefOrderHint[ ref_frame_idx[ i ] ]
            OrderHints[ refFrame ] = hint
            if ( !enable_order_hint ) 
            {
                RefFrameSignBias[ refFrame ] = 0
            } 
            else 
            {
                RefFrameSignBias[ refFrame ] = get_relative_dist( hint, OrderHint) > 0
            }
        }
    }
    if ( reduced_still_picture_header || disable_cdf_update )
        disable_frame_end_update_cdf = 1
    else
        disable_frame_end_update_cdf           // Type f(1)
    if ( primary_ref_frame == PRIMARY_REF_NONE ) 
    {
        init_non_coeff_cdfs( )
        setup_past_independence( )
    } 
    else 
    {
        load_cdfs( ref_frame_idx[ primary_ref_frame ] )
        load_previous( )
    }
    if ( use_ref_frame_mvs == 1 )
        motion_field_estimation( )
    tile_info( )
    quantization_params( )
    segmentation_params( )
    delta_q_params( )
    delta_lf_params( )
    if ( primary_ref_frame == PRIMARY_REF_NONE ) 
    {
    init_coeff_cdfs( )
    } 
    else 
    {
        load_previous_segment_ids( )
    }
    CodedLossless = 1
    for ( segmentId = 0; segmentId < MAX_SEGMENTS; segmentId++ ) 
    {
        qindex = get_qindex( 1, segmentId )
        LosslessArray[ segmentId ] = qindex == 0 && DeltaQYDc == 0 &&
        DeltaQUAc == 0 && DeltaQUDc == 0 &&
        DeltaQVAc == 0 && DeltaQVDc == 0
        if ( !LosslessArray[ segmentId ] )
            CodedLossless = 0
        if ( using_qmatrix )
        {
            if ( LosslessArray[ segmentId ] ) 
            {
                SegQMLevel[ 0 ][ segmentId ] = 15
                SegQMLevel[ 1 ][ segmentId ] = 15
                SegQMLevel[ 2 ][ segmentId ] = 15
            } 
            else 
            {
                SegQMLevel[ 0 ][ segmentId ] = qm_y
                SegQMLevel[ 1 ][ segmentId ] = qm_u
                SegQMLevel[ 2 ][ segmentId ] = qm_v
            }
        }
    }
    AllLossless = CodedLossless && ( FrameWidth == UpscaledWidth )
    loop_filter_params( )
    cdef_params( )
    lr_params( )
    read_tx_mode( )
    frame_reference_mode( )
    skip_mode_params( )
    if ( FrameIsIntra || error_resilient_mode || !enable_warped_motion )
        allow_warped_motion = 0
    else
        allow_warped_motion           // Type f(1)
    reduced_tx_set            // Type f(1)
    global_motion_params( )
    film_grain_params( )
}

5.9.3 get_relative_dist函数

get_relative_dist( a, b ) 
{
    if ( !enable_order_hint )
        return 0
    diff = a - b
    m = 1 << (OrderHintBits - 1)
    diff = (diff & (m - 1)) - (diff & m)
    return diff
}

5.9.4 mark_ref_frames函数

mark_ref_frames( idLen ) 
{
    diffLen = delta_frame_id_length_minus_2 + 2
    for ( i = 0; i < NUM_REF_FRAMES; i++ ) 
    {
        if ( current_frame_id > ( 1 << diffLen ) ) 
        {
            if ( RefFrameId[ i ] > current_frame_id || RefFrameId[ i ] < ( current_frame_id - ( 1 << diffLen ) ) )
                RefValid[ i ] = 0
        } 
        else 
        {
            if ( RefFrameId[ i ] > current_frame_id && RefFrameId[ i ] < ( ( 1 << idLen ) + current_frame_id - ( 1 << diffLen ) ) )
                RefValid[ i ] = 0
        }
    }
}

5.9.6 render_size语法

render_size( )
{
    render_and_frame_size_different           // Type f(1)
    if ( render_and_frame_size_different == 1 ) 
    {
        render_width_minus_1           // Type f(16)
        render_height_minus_1           // Type f(16)
        RenderWidth = render_width_minus_1 + 1
        RenderHeight = render_height_minus_1 + 1
    } 
    else 
    {
        RenderWidth = UpscaledWidth
        RenderHeight = FrameHeight
    }
}

5.9.7 frame_size_with_refs语法

frame_size_with_refs( ) 
{
    for ( i = 0; i < REFS_PER_FRAME; i++ ) 
    {
        found_ref           // Type f(1)
        if ( found_ref == 1 ) 
        {
            UpscaledWidth = RefUpscaledWidth[ ref_frame_idx[ i ] ]
            FrameWidth = UpscaledWidth
            FrameHeight = RefFrameHeight[ ref_frame_idx[ i ] ]
            RenderWidth = RefRenderWidth[ ref_frame_idx[ i ] ]
            RenderHeight = RefRenderHeight[ ref_frame_idx[ i ] ]
            break
        }
    }
    if ( found_ref == 0 ) 
    {
        frame_size( )
        render_size( )
    } 
    else 
    {
        superres_params( )
        compute_image_size( )
    }
}

5.9.8 superres_params语法

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

5.9.9 compute_image_size函数

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

5.9.10 read_interpolation_filter语法

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

5.9.11 loop_filter_params语法

loop_filter_params( ) 
{
    if ( CodedLossless || allow_intrabc ) 
    {
        loop_filter_level[ 0 ] = 0
        loop_filter_level[ 1 ] = 0
        loop_filter_ref_deltas[ INTRA_FRAME ] = 1
        loop_filter_ref_deltas[ LAST_FRAME ] = 0
        loop_filter_ref_deltas[ LAST2_FRAME ] = 0
        loop_filter_ref_deltas[ LAST3_FRAME ] = 0
        loop_filter_ref_deltas[ BWDREF_FRAME ] = 0
        loop_filter_ref_deltas[ GOLDEN_FRAME ] = -1
        loop_filter_ref_deltas[ ALTREF_FRAME ] = -1
        loop_filter_ref_deltas[ ALTREF2_FRAME ] = -1
        for ( i = 0; i < 2; i++ ) 
        {
            loop_filter_mode_deltas[ i ] = 0
        }
        return
    }
    loop_filter_level[ 0 ]           // Type f(6)
    loop_filter_level[ 1 ]            // Type f(6)
    if ( NumPlanes > 1 ) 
    {
        if ( loop_filter_level[ 0 ] || loop_filter_level[ 1 ] ) 
        {
            loop_filter_level[ 2 ]            // Type f(6)
            loop_filter_level[ 3 ]           // Type f(6)
        }
    }
    loop_filter_sharpness            // Type f(3)
    loop_filter_delta_enabled            // Type f(1)
    if ( loop_filter_delta_enabled == 1 ) 
    {
        loop_filter_delta_update            // Type f(1)
        if ( loop_filter_delta_update == 1 ) 
        {
            for ( i = 0; i < TOTAL_REFS_PER_FRAME; i++ )
            {
                update_ref_delta           // Type f(1)
                if ( update_ref_delta == 1 )
                    loop_filter_ref_deltas[ i ]            // Type su(1+6)
            }
            for ( i = 0; i < 2; i++ ) 
            {
                update_mode_delta            // Type f(1)
                if ( update_mode_delta == 1 )
                    loop_filter_mode_deltas[ i ]            // Type su(1+6)
            }
        }
    }
}

5.9.12 quantization_params语法

quantization_params( ) 
{
    base_q_idx           // Type f(8)
    DeltaQYDc = read_delta_q( )
    if ( NumPlanes > 1 ) 
    {
        if ( separate_uv_delta_q )
            diff_uv_delta            // Type f(1)
        else
            diff_uv_delta = 0
        DeltaQUDc = read_delta_q( )
        DeltaQUAc = read_delta_q( )
        if ( diff_uv_delta ) 
        {
            DeltaQVDc = read_delta_q( )
            DeltaQVAc = read_delta_q( )
        } 
        else 
        {
            DeltaQVDc = DeltaQUDc
            DeltaQVAc = DeltaQUAc
        }
    } 
    else 
    {
        DeltaQUDc = 0
        DeltaQUAc = 0
        DeltaQVDc = 0
        DeltaQVAc = 0
    }
    using_qmatrix            // Type f(1)
    if ( using_qmatrix ) 
    {
        qm_y            // Type f(4)
        qm_u            // Type f(4)
        if ( !separate_uv_delta_q )
            qm_v = qm_u
        else
            qm_v            // Type f(4)
    }
}

5.9.13 read_delta_q语法

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

5.9.14 segmentation_params语法

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

该语法中所使用的常量查找表定义如下,

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

5.9.15 tile_info语法

tile_info ( ) 
{
    sbCols = use_128x128_superblock ? ( ( MiCols + 31 ) >> 5 ) : ( ( MiCols + 15 ) >> 4 )
    sbRows = use_128x128_superblock ? ( ( MiRows + 31 ) >> 5 ) : ( ( MiRows + 15 ) >> 4 )
    sbShift = use_128x128_superblock ? 5 : 4
    sbSize = sbShift + 2
    maxTileWidthSb = MAX_TILE_WIDTH >> sbSize
    maxTileAreaSb = MAX_TILE_AREA >> ( 2 * sbSize )
    minLog2TileCols = tile_log2(maxTileWidthSb, sbCols)
    maxLog2TileCols = tile_log2(1, Min(sbCols, MAX_TILE_COLS))
    maxLog2TileRows = tile_log2(1, Min(sbRows, MAX_TILE_ROWS))
    minLog2Tiles = Max(minLog2TileCols,
    tile_log2(maxTileAreaSb, sbRows * sbCols))
    uniform_tile_spacing_flag           // Type f(1)
    if ( uniform_tile_spacing_flag ) 
    {
        TileColsLog2 = minLog2TileCols
        while ( TileColsLog2 < maxLog2TileCols ) 
        {
            increment_tile_cols_log2            // Type f(1)
            if ( increment_tile_cols_log2 == 1 )
                TileColsLog2++
            else
                break
        }
        tileWidthSb = (sbCols + (1 << TileColsLog2) - 1) >> TileColsLog2
        i = 0
        for ( startSb = 0; startSb < sbCols; startSb += tileWidthSb ) 
        {
            MiColStarts[ i ] = startSb << sbShift
            i += 1
        }
        MiColStarts[i] = MiCols
        TileCols = i
        minLog2TileRows = Max( minLog2Tiles - TileColsLog2, 0)
        TileRowsLog2 = minLog2TileRows
        while ( TileRowsLog2 < maxLog2TileRows ) 
        {
            increment_tile_rows_log2           // Type f(1)
            if ( increment_tile_rows_log2 == 1 )
                TileRowsLog2++
            else
                break
        }
        tileHeightSb = (sbRows + (1 << TileRowsLog2) - 1) >> TileRowsLog2
        i = 0
        for ( startSb = 0; startSb < sbRows; startSb += tileHeightSb ) 
        {
            MiRowStarts[ i ] = startSb << sbShift
            i += 1
        }
        MiRowStarts[i] = MiRows
        TileRows = i
    } 
    else 
    {
        widestTileSb = 0
        startSb = 0
        for ( i = 0; startSb < sbCols; i++ ) 
        {
            MiColStarts[ i ] = startSb << sbShift
            maxWidth = Min(sbCols - startSb, maxTileWidthSb)
            width_in_sbs_minus_1            // Type ns(maxWidth)
            sizeSb = width_in_sbs_minus_1 + 1
            widestTileSb = Max( sizeSb, widestTileSb )
            startSb += sizeSb
        }
        MiColStarts[i] = MiCols
        TileCols = i
        TileColsLog2 = tile_log2(1, TileCols)
        if ( minLog2Tiles > 0 )
            maxTileAreaSb = (sbRows * sbCols) >> (minLog2Tiles + 1)
        else
            maxTileAreaSb = sbRows * sbCols
        maxTileHeightSb = Max( maxTileAreaSb / widestTileSb, 1 )
        startSb = 0
        for ( i = 0; startSb < sbRows; i++ ) 
        {
            MiRowStarts[ i ] = startSb << sbShift
            maxHeight = Min(sbRows - startSb, maxTileHeightSb)
            height_in_sbs_minus_1            // Type ns(maxHeight)
            sizeSb = height_in_sbs_minus_1 + 1
            startSb += sizeSb
        }
        MiRowStarts[ i ] = MiRows
        TileRows = i
        TileRowsLog2 = tile_log2(1, TileRows)
    }
    if ( TileColsLog2 > 0 || TileRowsLog2 > 0 ) 
    {
        context_update_tile_id            // Type f(TileRowsLog2 + TileColsLog2)
        tile_size_bytes_minus_1            // Type f(2)
        TileSizeBytes = tile_size_bytes_minus_1 + 1
    } 
    else 
    {
    context_update_tile_id = 0
    }
}

5.9.16 tile_log2函数

tile_log2的返回值为k的最小值,能够符合blkSize << k大于等于目标值。

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

5.9.17 delta_q_params语法

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

5.9.18 delta_lf_params语法

delta_lf_params( ) 
{
    delta_lf_present = 0
    delta_lf_res = 0
    delta_lf_multi = 0
    if ( delta_q_present ) 
    {
        if ( !allow_intrabc )
        delta_lf_present            // Type f(1)
        if ( delta_lf_present ) 
        {
            delta_lf_res            // Type f(2)
            delta_lf_multi           // Type f(1)
        }
    }
}

5.9.19 cdef_params语法

cdef_params( ) 
{
    if ( CodedLossless || allow_intrabc || !enable_cdef) 
    {
        cdef_bits = 0
        cdef_y_pri_strength[0] = 0
        cdef_y_sec_strength[0] = 0
        cdef_uv_pri_strength[0] = 0
        cdef_uv_sec_strength[0] = 0
        CdefDamping = 3
        return
    }
    cdef_damping_minus_3           // Type f(2)
    CdefDamping = cdef_damping_minus_3 + 3
    cdef_bits           // Type f(2)
    for ( i = 0; i < (1 << cdef_bits); i++ ) 
    {
        cdef_y_pri_strength[i]           // Type f(4)
        cdef_y_sec_strength[i]            // Type f(2)
        if ( cdef_y_sec_strength[i] == 3 )
            cdef_y_sec_strength[i] += 1
        if ( NumPlanes > 1 ) 
        {
            cdef_uv_pri_strength[i]           // Type f(4)
            cdef_uv_sec_strength[i]            // Type f(2)
            if ( cdef_uv_sec_strength[i] == 3 )
                cdef_uv_sec_strength[i] += 1
        }
    }
}

5.9.20 lr_params语法

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

其中的常量查找表定义如下,

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

5.9.21 read_tx_mode语法

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

5.9.22 skip_mode_params语法

skip_mode_params( ) 
{
    if ( FrameIsIntra || !reference_select || !enable_order_hint ) 
    {
        skipModeAllowed = 0
    } 
    else 
    {
        forwardIdx = -1
        backwardIdx = -1
        for ( i = 0; i < REFS_PER_FRAME; i++ ) 
        {
            refHint = RefOrderHint[ ref_frame_idx[ i ] ]
            if ( get_relative_dist( refHint, OrderHint ) < 0 ) 
            {
                if ( forwardIdx < 0 || get_relative_dist( refHint, forwardHint) > 0 ) 
                {
                    forwardIdx = i
                    forwardHint = refHint
                }
            } 
            else if ( get_relative_dist( refHint, OrderHint) > 0 ) 
            {
                if ( backwardIdx < 0 || get_relative_dist( refHint, backwardHint) < 0 ) 
                {
                    backwardIdx = i
                    backwardHint = refHint
                }
            }
        }
        if ( forwardIdx < 0 ) 
        {
            skipModeAllowed = 0
        } 
        else if ( backwardIdx >= 0 ) 
        {
            skipModeAllowed = 1
            SkipModeFrame[ 0 ] = LAST_FRAME + Min(forwardIdx, backwardIdx)
            SkipModeFrame[ 1 ] = LAST_FRAME + Max(forwardIdx, backwardIdx)
        } 
        else 
        {
            secondForwardIdx = -1
            for ( i = 0; i < REFS_PER_FRAME; i++ ) 
            {
                refHint = RefOrderHint[ ref_frame_idx[ i ] ]
                if ( get_relative_dist( refHint, forwardHint ) < 0 ) 
                {
                    if ( secondForwardIdx < 0 || get_relative_dist( refHint, secondForwardHint ) > 0 ) 
                    {
                        secondForwardIdx = i
                        secondForwardHint = refHint
                    }
                }
            }
            if ( secondForwardIdx < 0 ) 
            {
                skipModeAllowed = 0
            } 
            else 
            {
                skipModeAllowed = 1
                SkipModeFrame[ 0 ] = LAST_FRAME + Min(forwardIdx, secondForwardIdx)
                SkipModeFrame[ 1 ] = LAST_FRAME + Max(forwardIdx, secondForwardIdx)
            }
        }
    }
    if ( skipModeAllowed ) 
    {
        skip_mode_present           // Type f(1)
    } 
    else 
    {
        skip_mode_present = 0
    }
}

5.9.23 frame_reference_mode语法

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

5.9.24 global_motion_params语法

global_motion_params( ) 
{
    for ( ref = LAST_FRAME; ref <= ALTREF_FRAME; ref++ ) 
    {
        GmType[ ref ] = IDENTITY
        for ( i = 0; i < 6; i++ ) 
        {
            gm_params[ ref ][ i ] = ( ( i % 3 == 2 ) ? 1 << WARPEDMODEL_PREC_BITS : 0 )
        }
    }
    if ( FrameIsIntra )
        return
    for ( ref = LAST_FRAME; ref <= ALTREF_FRAME; ref++ ) 
    {
        is_global           // Type f(1)
        if ( is_global ) 
        {
            is_rot_zoom           // Type f(1)
            if ( is_rot_zoom ) 
            {
                type = ROTZOOM
            } 
            else 
            {
                is_translation            // Type f(1)
                type = is_translation ? TRANSLATION : AFFINE
            }
        } 
        else 
        {
            type = IDENTITY
        }
        GmType[ref] = type
        if ( type >= ROTZOOM )
         {
            read_global_param(type,ref,2)
            read_global_param(type,ref,3)
            if ( type == AFFINE ) 
            {
                read_global_param(type,ref,4)
                read_global_param(type,ref,5)
            } 
            else 
            {
                gm_params[ref][4] = -gm_params[ref][3]
                gm_params[ref][5] = gm_params[ref][2]
            }
        }
        if ( type >= TRANSLATION ) 
        {
            read_global_param(type,ref,0)
            read_global_param(type,ref,1)
        }
    }
}

5.9.25 read_global_param语法

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

注意:当force_integer_mv等于1时,转换组件仍会读取一些小数位。但是,这些小数位将在Setup Global MV处理过程中被舍弃。

5.9.26 decode_signed_subexp_with_ref语法

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

注意:decode_signed_subexp_with_ref的返回值范围为low~(high-1)。

5.9.27 decode_unsigned_subexp_with_ref语法

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

注意:decode_unsigned_subexp_with_ref的返回值范围为0~(mx-1)。

5.9.28 decode_subexp语法

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

5.9.29 inverse_recenter函数

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

5.9.30 film_grain_params语法

film_grain_params( ) 
{
    if ( !film_grain_params_present || (!show_frame && !showable_frame) ) 
    {
        reset_grain_params()
        return
    }
    apply_grain           // Type f(1)
    if ( !apply_grain ) 
    {
        reset_grain_params()
        return
    }
    grain_seed           // Type f(16)
    if ( frame_type == INTER_FRAME )
        update_grain            // Type f(1)
    else
        update_grain = 1
    if ( !update_grain ) 
    {
        film_grain_params_ref_idx           // Type f(3)
        tempGrainSeed = grain_seed
        load_grain_params( film_grain_params_ref_idx )
        grain_seed = tempGrainSeed
        return
    }
    num_y_points           // Type f(4)
    for ( i = 0; i < num_y_points; i++ ) 
    {
        point_y_value[ i ]           // Type f(8)
        point_y_scaling[ i ]            // Type f(8)
    }
    if ( mono_chrome ) 
    {
        chroma_scaling_from_luma = 0
    } 
    else 
    {
        chroma_scaling_from_luma            // Type f(1)
    }
    if ( mono_chrome || chroma_scaling_from_luma || ( subsampling_x == 1 && subsampling_y == 1 && num_y_points == 0 )) 
    {
        num_cb_points = 0
        num_cr_points = 0
    } 
    else 
    {
        num_cb_points            // Type f(4)
        for ( i = 0; i < num_cb_points; i++ ) 
        {
            point_cb_value[ i ]           // Type f(8)
            point_cb_scaling[ i ]            // Type f(8)
        }
        num_cr_points           // Type f(4)
        for ( i = 0; i < num_cr_points; i++ ) 
        {
            point_cr_value[ i ]           // Type f(8)
            point_cr_scaling[ i ]            // Type f(8)
        }
    }
    grain_scaling_minus_8            // Type f(2)
    ar_coeff_lag            // Type f(2)
    numPosLuma = 2 * ar_coeff_lag * ( ar_coeff_lag + 1 )
    if ( num_y_points ) 
    {
        numPosChroma = numPosLuma + 1
        for ( i = 0; i < numPosLuma; i++ )
            ar_coeffs_y_plus_128[ i ]            // Type f(8)
    } 
    else 
    {
        numPosChroma = numPosLuma
    }
    if ( chroma_scaling_from_luma || num_cb_points ) 
    {
        for ( i = 0; i < numPosChroma; i++ )
            ar_coeffs_cb_plus_128[ i ]            // Type f(8)
    }
    if ( chroma_scaling_from_luma || num_cr_points ) 
    {
        for ( i = 0; i < numPosChroma; i++ )
            ar_coeffs_cr_plus_128[ i ]            // Type f(8)
    }    
    ar_coeff_shift_minus_6           // Type f(2)
    grain_scale_shift            // Type f(2)
    if ( num_cb_points ) 
    {
        cb_mult            // Type f(8)
        cb_luma_mult           // Type f(8)
        cb_offset           // Type f(9)
    }
    if ( num_cr_points ) 
    {
        cr_mult           // Type f(8)
        cr_luma_mult            // Type f(8)
        cr_offset           // Type f(9)
    }
    overlap_flag           // Type f(1)
    clip_to_restricted_range           // Type f(1)
}

5.9.31 temporal_point_info语法

temporal_point_info( )
{
    n = frame_presentation_time_length_minus_1 + 1
    frame_presentation_time           // Type f(n)
}

5.10 帧OBU语法

frame_obu( sz )
{
    startBitPos = get_position( )
    frame_header_obu( )
    byte_alignment( )
    endBitPos = get_position( )
    headerBytes = (endBitPos - startBitPos) / 8
    sz -= headerBytes
    tile_group_obu( sz )
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值