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

本文详细介绍了AV1编码标准中的OBU(Obu)比特流格式,涵盖OBU的通用语法、序列头OBU、时域分隔符OBU、填充OBU和元数据OBU的详细结构。通过对每个OBU类型的解析,包括其头部、扩展头、尾随位等关键元素,解码器可以理解并处理AV1视频流。
摘要由CSDN通过智能技术生成

Table of Contents

5.1 概述

5.2 低开销比特流格式

5.3 OBU语法

5.3.1 通用OBU语法

5.3.2 obu_header语法

5.3.3 obu_extension_heade语法

5.3.4 trailing_bits语法

5.3.5 byte_alignment语法

5.4 reserved_obu语法

5.5 序列头OBU语法

5.5.1 通用序列头OBU语法

5.5.2 color_config语法

5.5.3 timing_info语法

5.5.4 解码模型信息语法

5.5.5 操作参数信息语法

5.6 时域分隔符OBU语法

5.7 填充OBU语法

5.8 元数据OBU语法

5.8.1 通用元数据OBU语法

5.8.2 元数据ITUT T35语法

5.8.3 元数据高动态范围内容亮度等级语法

5.8.4 元数据高动态范围控制显示色域语法

5.8.5 元数据可伸缩性语法

5.8.6 可伸缩性结构语法

5.8.7 元数据时间码语法


5.1 概述

本节以表格形式进行语法结构的介绍,并且将在第6章中介绍每个语法元素的具体含义。

5.2 低开销比特流格式

本规格定义了一种低开销的比特流格式,通过使用本节后续提到的定义内容,以OBU语法元素序列的形式构建比特流格式。

使用该格式的必要条件为obu_has_size_field = 1。

对于需要更容易跳过帧或时间单位的格式的应用,附件B中定义了长度分隔的比特流格式。

衍生规范(例如,能够将AV1视频与音频或字幕一起存储的容器格式)应指明其依赖于哪种格式。

另外,也允许将OBU打包成比特流格式的其他方法。

5.3 OBU语法

5.3.1 通用OBU语法

open_bitstream_unit( sz )
{
    obu_header()
    if ( obu_has_size_field )
    {
        obu_size               // Type leb128()
    }
    else
    {
        obu_size = sz - 1 - obu_extension_flag
    }
    startPosition = get_position( )
    if ( obu_type != OBU_SEQUENCE_HEADER 
            && obu_type != OBU_TEMPORAL_DELIMITER 
            && OperatingPointIdc != 0 && obu_extension_flag == 1 )
    {
        inTemporalLayer = (OperatingPointIdc >> temporal_id ) & 1
        inSpatialLayer = (OperatingPointIdc >> ( spatial_id + 8 ) ) & 1
        if ( !inTemporalLayer || ! inSpatialLayer )
        {
            drop_obu( )
            return
        }
    }
    if ( obu_type == OBU_SEQUENCE_HEADER )
        sequence_header_obu( )
    else if ( obu_type == OBU_TEMPORAL_DELIMITER )
        temporal_delimiter_obu( )
    else if ( obu_type == OBU_FRAME_HEADER )
        frame_header_obu( )
    else if ( obu_type == OBU_REDUNDANT_FRAME_HEADER )
        frame_header_obu( )
    else if ( obu_type == OBU_TILE_GROUP )
        tile_group_obu( obu_size )
    else if ( obu_type == OBU_METADATA )
        metadata_obu( )
    else if ( obu_type == OBU_FRAME )
        frame_obu( obu_size )
    else if ( obu_type == OBU_TILE_LIST )
        tile_list_obu( )
    else if ( obu_type == OBU_PADDING )
        padding_obu( )
    else
        reserved_obu( )
    currentPosition = get_position( )
    payloadBits = currentPosition - startPosition
    if ( obu_size > 0 && obu_type != OBU_TILE_GROUP 
        && obu_type != OBU_TILE_LIST 
        && obu_type != OBU_FRAME ) 
    {
        trailing_bits( obu_size * 8 - payloadBits )
    }
}

5.3.2 obu_header语法

obu_header()
{
    obu_forbidden_bit          // Type f(1)
    obu_type                   // Type f(4)
    obu_extension_flag         // Type f(1)
    obu_has_size_field         // Type f(1)
    obu_reserved_1bit          // Type f(1)
    if ( obu_extension_flag == 1 )
        obu_extension_header()
}

5.3.3 obu_extension_heade语法

obu_extension_header()
{
    temporal_id     // Type f(3)
    spatial_id      // Type f(2)
    extension_header_reserved_3bits     // Type f(3)
}

5.3.4 trailing_bits语法

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

5.3.5 byte_alignment语法

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

5.4 reserved_obu语法

reserved_obu( )
{
}

注意:预留的OBU没有定义语法。obu_type预留值用于供将来使用。如果解码器不理解obu_type,则应忽略整个OBU。忽略OBU的操作可以基于obu_size来完成。对于该OBU类型而言,载荷数据的有效内容的最后一个字节被认为是不等于零的。此规则用于防止系统丢弃有效字节,该系统会将尾随零字节解释为OBU中尾随位的延续。这意味着当该OBU类型存在任何有效载荷数据时,有效载荷数据(包括尾随位)至少有一个字节是不等于0的。

5.5 序列头OBU语法

5.5.1 通用序列头OBU语法

sequence_header_obu( )
{
    seq_profile          // Type f(3)
    still_picture       // Type f(1)
    reduced_still_picture_header      // Type f(1)
    if ( reduced_still_picture_header )
    {
        timing_info_present_flag = 0
        decoder_model_info_present_flag = 0
        initial_display_delay_present_flag = 0
        operating_points_cnt_minus_1 = 0
        operating_point_idc[ 0 ] = 0
        seq_level_idx[ 0 ]      // Type f(5)
        seq_tier[ 0 ] = 0
        decoder_model_present_for_this_op[ 0 ] = 0
        initial_display_delay_present_for_this_op[ 0 ] = 0
    }
    else
    {
        timing_info_present_flag       // Type f(1)
        if ( timing_info_present_flag )
        {
            timing_info( )
            decoder_model_info_present_flag      // Type f(1)
            if ( decoder_model_info_present_flag )
            {
                decoder_model_info( )
            }
        }
        else
        {
            decoder_model_info_present_flag = 0
        }
        initial_display_delay_present_flag      // Type f(1)
        operating_points_cnt_minus_1      // Type f(5)
        for ( i = 0; i <= operating_points_cnt_minus_1; i++ )
        {
            operating_point_idc[ i ]      // Type f(12)
            seq_level_idx[ i ]      // Type f(5)
            if ( seq_level_idx[ i ] > 7 )
            {
                seq_tier[ i ]      // Type f(1)
            }
            else
            {
                seq_tier[ i ] = 0
            }
            if ( decoder_model_info_present_flag )
            {
                decoder_model_present_for_this_op[ i ]      // Type f(1)
                if ( decoder_model_present_for_this_op[ i ] ) 
                {
                    operating_parameters_info( i )
                }
            } 
            else 
            {
                decoder_model_present_for_this_op[ i ] = 0
            }

            if ( initial_display_delay_present_flag ) 
            {
                initial_display_delay_present_for_this_op[ i ]      // Type f(1)
                if ( initial_display_delay_present_for_this_op[ i ] ) 
                {
                    initial_display_delay_minus_1[ i ]      // Type f(4)
                }
            }
        }
    }

    operatingPoint = choose_operating_point( )
    OperatingPointIdc = operating_point_idc[ operatingPoint ]
    frame_width_bits_minus_1      // Type f(4)
    frame_height_bits_minus_1      // Type f(4)
    n = frame_width_bits_minus_1 + 1
    max_frame_width_minus_1      // Type f(n)
    n = frame_height_bits_minus_1 + 1
    max_frame_height_minus_1     // Type f(n)

    if ( reduced_still_picture_header )
        frame_id_numbers_present_flag = 0
    else
        frame_id_numbers_present_flag      // Type f(1)

    if ( frame_id_numbers_present_flag ) 
    {
        delta_frame_id_length_minus_2      // Type f(4)
        additional_frame_id_length_minus_1      // Type f(3)
    }

    use_128x128_superblock      // Type f(1)
    enable_filter_intra      // Type f(1)    
    enable_intra_edge_filter      // Type f(1)

    if ( reduced_still_picture_header ) 
    {
        enable_interintra_compound = 0
        enable_masked_compound = 0
        enable_warped_motion = 0
        enable_dual_filter = 0
        enable_order_hint = 0
        enable_jnt_comp = 0
        enable_ref_frame_mvs = 0
        seq_force_screen_content_tools = SELECT_SCREEN_CONTENT_TOOLS
        seq_force_integer_mv = SELECT_INTEGER_MV
        OrderHintBits = 0
    } 
    else 
    {
        enable_interintra_compound     // Type f(1)
        enable_masked_compound      // Type f(1)
        enable_warped_motion     // Type f(1)
        enable_dual_filter     // Type f(1)
        enable_order_hint      // Type f(1)

        if ( enable_order_hint ) 
        {
            enable_jnt_comp     // Type f(1)
            enable_ref_frame_mvs     // Type f(1)
        } 
        else 
        {
            enable_jnt_comp = 0
            enable_ref_frame_mvs = 0
        }

        seq_choose_screen_content_tools      // Type f(1)

        if ( seq_choose_screen_content_tools ) 
        {
            seq_force_screen_content_tools = SELECT_SCREEN_CONTENT_TOOLS
        } 
        else 
        {
            seq_force_screen_content_tools     // Type f(1)
        }

        if ( seq_force_screen_content_tools > 0 )
        {
            seq_choose_integer_mv     // Type f(1)

            if ( seq_choose_integer_mv ) 
            {
                seq_force_integer_mv = SELECT_INTEGER_MV
            }        
            else 
            {
                seq_force_integer_mv     // Type f(1)
            }

        }        
        else 
        {
            seq_force_integer_mv = SELECT_INTEGER_MV
        }

        if ( enable_order_hint ) 
        {
            order_hint_bits_minus_1     // Type f(3)
            OrderHintBits = order_hint_bits_minus_1 + 1
        } 
        else 
        {
            OrderHintBits = 0
        }

    }

    enable_superres                // Type f(1)
    enable_cdef                    // Type f(1)
    enable_restoration             // Type f(1)
    color_config( )
    film_grain_params_present      // Type f(1)
}

5.5.2 color_config语法

color_config( ) 
{
    high_bitdepth      // Type f(1)

    if ( seq_profile == 2 && high_bitdepth ) 
    {
        twelve_bit      // Type f(1)
        BitDepth = twelve_bit ? 12 : 10
    } 
    else if ( seq_profile <= 2 ) 
    {
        BitDepth = high_bitdepth ? 10 : 8
    }

    if ( seq_profile == 1 ) 
    {
        mono_chrome = 0
    } 
    else 
    {
        mono_chrome     // Type f(1)
    }

    NumPlanes = mono_chrome ? 1 : 3
    color_description_present_flag     // Type f(1)

    if ( color_description_present_flag ) 
    {
        color_primaries     // Type f(8)
        transfer_characteristics      // Type f(8)
        matrix_coefficients      // Type f(8)
    } 
    else 
    {
        color_primaries = CP_UNSPECIFIED
        transfer_characteristics = TC_UNSPECIFIED
        matrix_coefficients = MC_UNSPECIFIED
    }

    if ( mono_chrome ) 
    {
        color_range      // Type f(1)
        subsampling_x = 1
        subsampling_y = 1
        chroma_sample_position = CSP_UNKNOWN
        separate_uv_delta_q = 0
        return
    } 
    else if ( color_primaries == CP_BT_709 
            && transfer_characteristics == TC_SRGB 
            && matrix_coefficients == MC_IDENTITY ) 
    {
        color_range = 1
        subsampling_x = 0
        subsampling_y = 0
    } 
    else 
    {
        color_range     // Type f(1)

        if ( seq_profile == 0 ) 
        {
            subsampling_x = 1
            subsampling_y = 1
        } 
        else if ( seq_profile == 1 ) 
        {
            subsampling_x = 0
            subsampling_y = 0
        } 
        else 
        {
            if ( BitDepth == 12 ) 
            {
                subsampling_x     // Type f(1)

                if ( subsampling_x )
                    subsampling_y     // Type f(1)
                else
                    subsampling_y = 0
            } 
            else 
            {
                subsampling_x = 1
                subsampling_y = 0
            }
        }

        if ( subsampling_x && subsampling_y ) 
        {
            chroma_sample_position      // Type f(2)
        }
    }

    separate_uv_delta_q      // Type f(1)
}

5.5.3 timing_info语法

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

5.5.4 解码模型信息语法

decoder_model_info( ) 
{
    buffer_delay_length_minus_1     // Type f(5)
    num_units_in_decoding_tick     // Type f(32)
    buffer_removal_time_length_minus_1    // Type f(5) 
    frame_presentation_time_length_minus_1    // Type f(5)
}

5.5.5 操作参数信息语法

operating_parameters_info( op ) 
{
    n = buffer_delay_length_minus_1 + 1
    decoder_buffer_delay[ op ]     // Type f(n)
    encoder_buffer_delay[ op ]     // Type f(n)
    low_delay_mode_flag[ op ]      // Type f(1)
}

5.6 时域分隔符OBU语法

temporal_delimiter_obu( ) 
{
    SeenFrameHeader = 0
}

注意:时域分隔符具有空载荷。

5.7 填充OBU语法

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

注意:obu_padding_length不会在比特流中进行编码,但是可以使用obu_size减去尾随字节数来计算。实际上,由于要跳过填充数据,因此解码器不需要确定该长度和尾随字节数。他们可以根据obu_size来进行忽略整个OBU的操作。针对该OBU类型,有效载荷数据的有效内容的最后一个字节被认为不等于零。此规则用于防止系统将有效字节丢弃,该系统将尾随零字节解释为OBU中尾随位的延续。这意味着当该OBU类型存在任何有效载荷数据时,其有效载荷数据(包括尾随位)至少有一个字节不等于0。

5.8 元数据OBU语法

5.8.1 通用元数据OBU语法

metadata_obu( ) 
{
    metadata_type     // Type leb128()
    if ( metadata_type == METADATA_TYPE_ITUT_T35 )
        metadata_itut_t35( )
    else if ( metadata_type == METADATA_TYPE_HDR_CLL )
        metadata_hdr_cll( )
    else if ( metadata_type == METADATA_TYPE_HDR_MDCV )
        metadata_hdr_mdcv( )
    else if ( metadata_type == METADATA_TYPE_SCALABILITY )
        metadata_scalability( )
    else if ( metadata_type == METADATA_TYPE_TIMECODE )
        metadata_timecode( )
}

注意:当metadata_type等于预留值或用户私有值时,本规范中未定义metadata_obu的确切语法。如果解码器不理解metadata_type,则应忽略整个OBU。针对该OBU类型,有效载荷数据的有效内容的最后一个字节被认为不等于零。此规则用于防止系统将有效字节丢弃,该系统将尾随零字节解释为OBU中尾随位的延续。这意味着当该OBU类型存在任何有效载荷数据时,其有效载荷数据(包括尾随位)至少有一个字节不等于0。

5.8.2 元数据ITUT T35语法

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

注意:本规范中未定义itu_t_t35_payload_bytes的确切语法,其定义在扩展规范中。如果解码器不理解itu_t_t35_payload_bytes,则应忽略整个OBU。针对该OBU类型,有效载荷数据的有效内容的最后一个字节被认为不等于零。此规则用于防止系统将有效字节丢弃,该系统将尾随零字节解释为OBU中尾随位的延续。这意味着当该OBU类型存在任何有效载荷数据时,其有效载荷数据(包括尾随位)至少有一个字节不等于0。

5.8.3 元数据高动态范围内容亮度等级语法

metadata_hdr_cll( ) 
{
    max_cll     // Type f(16)
    max_fall    // Type f(16)
}

5.8.4 元数据高动态范围控制显示色域语法

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

5.8.5 元数据可伸缩性语法

metadata_scalability( ) 
{
    scalability_mode_idc      // Type f(8)
    if ( scalability_mode_idc == SCALABILITY_SS )
        scalability_structure( )
}

5.8.6 可伸缩性结构语法

scalability_structure( ) 
{
    spatial_layers_cnt_minus_1                  // Type f(2)
    spatial_layer_dimensions_present_flag       // Type f(1)
    spatial_layer_description_present_flag      // Type f(1)
    temporal_group_description_present_flag     // Type f(1)
    scalability_structure_reserved_3bits        // Type f(3)
    if ( spatial_layer_dimensions_present_flag ) 
    {
        for ( i = 0; i <= spatial_layers_cnt_minus_1 ; i++ ) 
        {
            spatial_layer_max_width[ i ]        // Type f(16)
            spatial_layer_max_height[ i ]       // Type f(16)
        }
    }

    if ( spatial_layer_description_present_flag ) 
    {
        for ( i = 0; i <= spatial_layers_cnt_minus_1; i++ )
            spatial_layer_ref_id[ i ]      // Type f(8)
    }

    if ( temporal_group_description_present_flag ) 
    {
        temporal_group_size       // Type f(8)
        for ( i = 0; i < temporal_group_size; i++ ) 
        {
            temporal_group_temporal_id[ i ]                          // Type f(3)
            temporal_group_temporal_switching_up_point_flag[ i ]     // Type f(1)
            temporal_group_spatial_switching_up_point_flag[ i ]      // Type f(1)
            temporal_group_ref_cnt[ i ]                              // Type f(3)
            for ( j = 0; j < temporal_group_ref_cnt[ i ]; j++ )
            {
                temporal_group_ref_pic_diff[ i ][ j ]       // Type f(8)
            }
        }
    }
}

5.8.7 元数据时间码语法

metadata_timecode( ) 
{
    counting_type f(5)
    full_timestamp_flag       // Type f(1)
    discontinuity_flag        // Type f(1)
    cnt_dropped_flag          // Type f(1)
    n_frames                  // Type f(9)

    if ( full_timestamp_flag ) 
    {
        seconds_value       // Type f(6)
        minutes_value       // Type f(6)
        hours_value         // Type f(5)
    } 
    else 
    {
        seconds_flag      // Type f(1)
        if ( seconds_flag ) 
        {
            seconds_value      // Type f(6)
            minutes_flag       // Type f(1)
            if ( minutes_flag ) 
            {
                minutes_value       // Type f(6)
                hours_flag          // Type f(1)
                if ( hours_flag ) 
                {
                    hours_value       // Type f(5)
                }
            }
        }
    }

    time_offset_length      // Type f(5)

    if ( time_offset_length > 0 ) 
    {
        time_offset_value f(time_offset_length)
    }
}

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值