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

本文档定义了Alliance for Open Media AV1(Alliance for Open Media Video 1)视频编解码器的比特流格式和解码过程。
摘要由CSDN通过智能技术生成

Table of Contents

5.11 Tile组OBU语法

5.11.1 tile_group_obu语法

5.11.2 decode_tile语法

5.11.3 clear_block_decoded_flags函数

5.11.4 decode_partition语法

5.11.5 decode_block语法

5.11.6 mode_info语法

5.11.7 intra_frame_mode_info语法

5.11.8 intra_segment_id语法

5.11.9 read_segment_id语法

5.11.10 read_skip_mode语法

5.11.11 read_skip语法

5.11.12 read_delta_qindex语法

5.11.13 read_delta_lf语法

5.11.14 seg_feature_active_idx函数

5.11.15 read_tx_size语法

5.11.16 read_block_tx_size语法

5.11.17 read_var_tx_size语法

5.11.18 inter_frame_mode_info语法

5.11.19 inter_segment_id语法

5.11.20 read_is_inter语法

5.11.21 get_segment_id函数

5.11.22 intra_block_mode_info语法

5.11.23 inter_block_mode_info语法

5.11.24 filter_intra_mode_info语法

5.11.25 read_ref_frames语法

5.11.26 assign_mv语法

5.11.27 read_motion_mode语法

5.11.28 read_interintra_mode语法

5.11.29 read_compound_type语法

5.11.30 get_mode函数

5.11.31 read_mv语法

5.11.32 read_mv_component语法

5.11.33 compute_prediction语法

5.11.34 residual语法

5.11.35 transform_block语法

5.11.36 transform_tree语法

5.11.37 get_tx_size函数

5.11.38 get_plane_residual_size函数

5.11.39 coeffs语法

5.11.40 compute_tx_type函数

5.11.41 get_mrow_scan函数

5.11.42 intra_angle_info_y语法

5.11.43 intra_angle_info_uv语法

5.11.44 is_directional_mode语法

5.11.45 read_cfl_alphas语法

5.11.46 palette_mode_info语法

5.11.47 transform_type语法

5.11.48 get_tx_set语法

5.11.49 palette_tokens语法

5.11.50 get_palette_color_context函数

5.11.51 is_inside函数

5.11.52 is_inside_filter_region函数

5.11.53 clamp_mv_row函数

5.11.54 clamp_mv_col函数

5.11.55 clear_cdef函数

5.11.56 read_cdef语法

5.11.57 read_Ir语法

5.11.58 read_lr_unit语法

5.12 Tile列表OBU语法

5.12.1 tile_list_obu语法

5.12.2 tile_list_entry语法


5.11 Tile组OBU语法

5.11.1 tile_group_obu语法

tile_group_obu( sz ) 
{
    NumTiles = TileCols * TileRows
    startBitPos = get_position( )
    tile_start_and_end_present_flag = 0
    if ( NumTiles > 1 )
        tile_start_and_end_present_flag           // Type f(1)
    if ( NumTiles == 1 || !tile_start_and_end_present_flag ) 
    {
        tg_start = 0
        tg_end = NumTiles - 1
    } 
    else 
    {
        tileBits = TileColsLog2 + TileRowsLog2
        tg_start            // Type f(tileBits)
        tg_end            // Type f(tileBits)
    }
    byte_alignment( )
    endBitPos = get_position( )
    headerBytes = (endBitPos - startBitPos) / 8
    sz -= headerBytes
    for ( TileNum = tg_start; TileNum <= tg_end; TileNum++ ) 
    {
        tileRow = TileNum / TileCols
        tileCol = TileNum % TileCols
        lastTile = TileNum == tg_end
        if ( lastTile ) 
        {
            tileSize = sz
        } 
        else 
        {
            tile_size_minus_1            // Type le(TileSizeBytes)
            tileSize = tile_size_minus_1 + 1
            sz -= tileSize + TileSizeBytes
        }
        MiRowStart = MiRowStarts[ tileRow ]
        MiRowEnd = MiRowStarts[ tileRow + 1 ]
        MiColStart = MiColStarts[ tileCol ]
        MiColEnd = MiColStarts[ tileCol + 1 ]
        CurrentQIndex = base_q_idx
        init_symbol( tileSize )
        decode_tile( )
        exit_symbol( )
    }
    if ( tg_end == NumTiles - 1 ) 
    {
        if ( !disable_frame_end_update_cdf ) 
        {
            frame_end_update_cdf( )
        }
        decode_frame_wrapup( )
        SeenFrameHeader = 0
    }
}

5.11.2 decode_tile语法

decode_tile( ) 
{
    clear_above_context( )
    for ( i = 0; i < FRAME_LF_COUNT; i++ )
        DeltaLF[ i ] = 0
    for ( plane = 0; plane < NumPlanes; plane++ ) 
    {
        for ( pass = 0; pass < 2; pass++ ) 
        {
            RefSgrXqd[ plane ][ pass ] = Sgrproj_Xqd_Mid[ pass ]
            for ( i = 0; i < WIENER_COEFFS; i++ ) 
            {
                RefLrWiener[ plane ][ pass ][ i ] = Wiener_Taps_Mid[ i ]
            }
        }
    }
    sbSize = use_128x128_superblock ? BLOCK_128X128 : BLOCK_64X64
    sbSize4 = Num_4x4_Blocks_Wide[ sbSize ]
    for ( r = MiRowStart; r < MiRowEnd; r += sbSize4 ) 
    {
        clear_left_context( )
        for ( c = MiColStart; c < MiColEnd; c += sbSize4 ) 
        {
            ReadDeltas = delta_q_present
            clear_cdef( r, c )
            clear_block_decoded_flags( r, c, sbSize4 )
            read_lr( r, c, sbSize )
            decode_partition( r, c, sbSize )
        }
    }
}

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

Wiener_Taps_Mid[3] = { 3, -7, 15 }
Sgrproj_Xqd_Mid[2] = { -32, 31 }

5.11.3 clear_block_decoded_flags函数

clear_block_decoded_flags( r, c, sbSize4 )
{
    for ( plane = 0; plane < NumPlanes; plane++ ) 
    {
        subX = (plane > 0) ? subsampling_x : 0
        subY = (plane > 0) ? subsampling_y : 0
        sbWidth4 = ( MiColEnd - c ) >> subX
        sbHeight4 = ( MiRowEnd - r ) >> subY
        for ( y = -1; y <= ( sbSize4 >> subY ); y++ )
            for ( x = -1; x <= ( sbSize4 >> subX ); x++ ) 
            {
                if ( y < 0 && x < sbWidth4 )
                    BlockDecoded[ plane ][ y ][ x ] = 1
                else if ( x < 0 && y < sbHeight4 )
                    BlockDecoded[ plane ][ y ][ x ] = 1
                else
                    BlockDecoded[ plane ][ y ][ x ] = 0
            }
        BlockDecoded[ plane ][ sbSize4 >> subY ][ -1 ] = 0
    }
}

5.11.4 decode_partition语法

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

5.11.5 decode_block语法

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

其中的reset_block_context()定义如下,

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

5.11.6 mode_info语法

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

5.11.7 intra_frame_mode_info语法

intra_frame_mode_info( ) 
{
    skip = 0
    if ( SegIdPreSkip )
        intra_segment_id( )
    skip_mode = 0
    read_skip( )
    if ( !SegIdPreSkip )
        intra_segment_id( )
    read_cdef( )
    read_delta_qindex( )
    read_delta_lf( )
    ReadDeltas = 0
    RefFrame[ 0 ] = INTRA_FRAME
    RefFrame[ 1 ] = NONE
    if ( allow_intrabc ) 
    {
        use_intrabc            // Type S()
    } 
    else 
    {
        use_intrabc = 0
    }
    if ( use_intrabc ) 
    {
        is_inter = 1
        YMode = DC_PRED
        UVMode = DC_PRED
        motion_mode = SIMPLE
        compound_type = COMPOUND_AVERAGE
        PaletteSizeY = 0
        PaletteSizeUV = 0
        interp_filter[ 0 ] = BILINEAR
        interp_filter[ 1 ] = BILINEAR
        find_mv_stack( 0 )
        assign_mv( 0 )
    } 
    else 
    {
        is_inter = 0
        intra_frame_y_mode            // Type S()
        YMode = intra_frame_y_mode
        intra_angle_info_y( )
        if ( HasChroma ) 
        {
            uv_mode            // Type S()
            UVMode = uv_mode
            if ( UVMode == UV_CFL_PRED ) 
            {
                read_cfl_alphas( )
            }
            intra_angle_info_uv( )
        }
        PaletteSizeY = 0
        PaletteSizeUV = 0
        if ( MiSize >= BLOCK_8X8 
            && Block_Width[ MiSize ] <= 64 
            && Block_Height[ MiSize ] <= 64 
            && allow_screen_content_tools ) 
        {
            palette_mode_info( )
        }
        filter_intra_mode_info( )
    }
}

5.11.8 intra_segment_id语法

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

5.11.9 read_segment_id语法

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

其中的neg_deinterleave()定义如下,

neg_deinterleave(diff, ref, max) 
{
    if ( !ref )
        return diff
    if ( ref >= (max - 1) )
        return max - diff - 1
    if ( 2 * ref < max ) 
    {
        if ( diff <= 2 * ref ) 
        {
            if ( diff & 1 )
                return ref + ((diff + 1) >> 1)
            else
                return ref - (diff >> 1)
        }
        return diff
    } 
    else 
    {
        if ( diff <= 2 * (max - ref - 1) ) 
        {
            if ( diff & 1 )
                return ref + ((diff + 1) >> 1)
            else
                return ref - (diff >> 1)
        }
        return max - (diff + 1)
    }
}

5.11.10 read_skip_mode语法

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

5.11.11 read_skip语法

read_skip() 
{
    if ( SegIdPreSkip && seg_feature_active( SEG_LVL_SKIP ) ) 
    {
        skip = 1
    } 
    else 
    {
        skip            // Type S()
    }
}

5.11.12 read_delta_qindex语法

read_delta_qindex( ) 
{
    sbSize = use_128x128_superblock ? BLOCK_128X128 : BLOCK_64X64
    if ( MiSize == sbSize && skip )
        return
    if ( ReadDeltas ) 
    {
        delta_q_abs            // Type S()
        if ( delta_q_abs == DELTA_Q_SMALL ) 
        {
            delta_q_rem_bits            // Type L(3)
            delta_q_rem_bits++
            delta_q_abs_bits            // Type L(delta_q_rem_bits)
            delta_q_abs = delta_q_abs_bits + (1 << delta_q_rem_bits) + 1
        }
        if ( delta_q_abs ) 
        {
            delta_q_sign_bit            // Type L(1)
            reducedDeltaQIndex = delta_q_sign_bit ? -delta_q_abs : delta_q_abs
            CurrentQIndex = Clip3(1, 255, CurrentQIndex + (reducedDeltaQIndex << delta_q_res))
        }
    }
}

5.11.13 read_delta_lf语法

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

5.11.14 seg_feature_active_idx函数

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

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

5.11.15 read_tx_size语法

read_tx_size( allowSelect ) 
{
    if ( Lossless ) 
    {
        TxSize = TX_4X4
        return
    }
    maxRectTxSize = Max_Tx_Size_Rect[ MiSize ]
    maxTxDepth = Max_Tx_Depth[ MiSize ]
    TxSize = maxRectTxSize
    if ( MiSize > BLOCK_4X4 && allowSelect && TxMode == TX_MODE_SELECT ) 
    {
        tx_depth            // Type S()
        for ( i = 0; i < tx_depth; i++ )
            TxSize = Split_Tx_Size[ TxSize ]
    }
}

其中Max_Tx_Depth定义了每个块尺寸的最大变换深度,

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

注意:Max_Tx_Depth包含必须拆分变换以达到4x4变换大小的次数。它可能大于MAX_TX_DEPTH。但是,因为tx_depth只能编码0到2范围内的值,所以无法进行变换深度大于MAX_TX_DEPTH的编码。

5.11.16 read_block_tx_size语法

read_block_tx_size( ) 
{
    bw4 = Num_4x4_Blocks_Wide[ MiSize ]
    bh4 = Num_4x4_Blocks_High[ MiSize ]
    if ( TxMode == 
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值