Table of Contents
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)
}
}