VVC解码流程(6)—Slice Header

[u(1)] sh_picture_header_in_slice_header_flag:等于1表示PH语法结构存在于slice header 中。

[ue(v)] sh_slice_type

[u(1)] sh_num_ref_idx_active_override_flag
[ue(v)] sh_num_ref_idx_active_minus1[ i ]
[u(1)] sh_cabac_init_flag
[u(1)] sh_dep_quant_used_flag
[u(1)] sh_sign_data_hiding_used_flag

VVC解码流程(5)—Picture Header

Picture Header可以以单独的Non-VCL NALU (PH_NUT) 进行传输,也可以放在Slice Header中进行传输。

[u(1)] ph_gdr_or_irap_pic_flag:等于1表示当前图片是GDR或IRAP图片。
[u(1)] ph_non_ref_pic_flag:等于1表示非参考图片。
[u(1)] ph_gdr_pic_flag:等于1表示GDR图片。
[u(1)] ph_inter_slice_allowed_flag:等于0表示图片的所有Slice的sh_slice_type等于2。等于1指定图片中可能有也可能没有sh_slice_type等于0或1的一个或多个Slice。
[u(1)] ph_intra_slice_allowed_flag:等于0指定图片的所有Slice的sh_slice_type等于0或1。ph_intra_slice_allowed_flag等于1表示图片中可能有也可能没有sh_slice_type等于2的一个或多个编码切片。当不存在时,ph_intra_sice_allowed_flags的值被推断为等于1。

[ue(v)] ph_pic_parameter_set_id:pps_id, 取值范围0-63。
[u(v)] ph_pic_order_cnt_lsb:指定当前图片的图片顺序计数模MaxPicOrderCntLsb。ph_pic_order_cnt_lsb语法元素的长度为sps_log2_max_pic_oorder_cnt_lsb_minus4+4位。ph_pic_order_cnt_lsb的值应在0到MaxPicOrderCntLsb−1的范围内,包括0和1。

[u(1)] ph_alf_enabled_flag:enable ALF.
[u(3)] ph_num_alf_aps_ids_luma:指定当前图片中的slice引用的的ALF APS的数量。
[u(3)] ph_alf_aps_id_luma[ i ]:指示luma引用的是哪几个APS。
[u(1)] ph_alf_cb_enabled_flag:enable cb ALF。
[u(1)] ph_alf_cr_enabled_flag:enable cr ALF。
[u(3)] ph_alf_aps_id_chroma:指示chroma引用的是哪个APS。
[u(1)] ph_alf_cc_cb_enabled_flag:enable cb CCALF。
[u(3)] ph_alf_cc_cb_aps_id:指示cb引用的是哪个APS。
[u(1)] ph_alf_cc_cr_enabled_flag:enable cr CCALF。
[u(3)] ph_alf_cc_cr_aps_id:指示cr引用的是哪个APS。

[u(1)] ph_lmcs_enabled_flag:enable LMCS。
[u(2)] ph_lmcs_aps_id:指示引用的是哪个APS。
[u(1)] ph_chroma_residual_scale_flag:等于1表示启用色度残差缩放。

[u(1)] ph_explicit_scaling_list_enabled_flag:
[u(3)] ph_scaling_list_aps_id:指示引用的是哪个APS。

[u(1)] ph_pic_output_flag:

[u(1)] ph_partition_constraints_override_flag:

[ue(v)] ph_cu_qp_delta_subdiv_intra_slice:指定了传递cu_qp_delta_abs和cu_qp_delta_sign_flag的 intra slice 中编码单元的最大cbSubdiv值。
[ue(v)] ph_cu_chroma_qp_offset_subdiv_intra_slice:指定传递cu_chroma_qp_offset_flag的 intra slice 中编码单元的最大cbSubdiv值。
[ue(v)] ph_cu_qp_delta_subdiv_inter_slice:指定了传递cu_qp_delta_abs和cu_qp_delta_sign_flag的 inter slice 中编码单元的最大cbSubdiv值。
[ue(v)] ph_cu_chroma_qp_offset_subdiv_inter_slice:指定传递cu_chroma_qp_offset_flag的 inter slice 中编码单元的最大cbSubdiv值。

[u(1)] ph_temporal_mvp_enabled_flag:
[u(1)] ph_collocated_from_l0_flag:
[ue(v)] ph_collocated_ref_idx:
[u(1)] ph_mmvd_fullpel_only_flag
[u(1)] ph_mvd_l1_zero_flag:
[u(1)] ph_bdof_disabled_flag:
[u(1)] ph_dmvr_disabled_flag:
[u(1)] ph_prof_disabled_flag:

[se(v)] ph_qp_delta:指定了用于图片中编码块的QpY的初始值,直到被编码单元层中的CuQpDeltaVal的值修改为止。

[u(1)] ph_joint_cbcr_sign_flag:
[u(1)] ph_sao_luma_enabled_flag:
[u(1)] ph_sao_chroma_enabled_flag:

VVC解码流程(4)—PPS

[u(6)] pps_pic_parameter_set_id:pps_id, 取值范围0-63。
[u(4)] pps_seq_parameter_set_id:pps_id, 取值范围0-15。
[u(1)] pps_mixed_nalu_types_in_pic_flag:等于1指定引用pps的每个图片具有多个VCL NAL单元,并且VCL NALs单元不具有相同的NAL_unit_type值。
[ue(v)] pps_pic_width_in_luma_samples:8的整数倍,且小于sps_pic_width_max_in_luma_samples。
[ue(v)] pps_pic_height_in_luma_samples:8的整数倍,且小于sps_pic_width_max_in_luma_samples。
[u(1)] pps_conformance_window_flag:裁剪窗口。
[u(1)] pps_scaling_window_explicit_signalling_flag:scaling窗口。
[u(1)] pps_output_flag_present_flag:等于1指定ph_pic_output_flag语法元素可以存在于引用pps的ph语法结构中。
[u(1)] pps_no_pic_partition_flag:等于1表示不对参考PPS的每个图片应用划分,指的是tile或者slice划分。
[u(1)] pps_subpic_id_mapping_present_flag:subpic相关。
[u(1)] pps_cabac_init_present_flag:等于1表示sh_cabac_init_flag存在于引用pps的sh中。
[ue(v)] pps_num_ref_idx_default_active_minus1[ i ] :范围为0-14,指定P/B参考帧个数。
[u(1)] pps_rpl1_idx_present_flag:等于0指定rpl_sps_flag[1]和rpl_idx[1]不存在于引用pps的ph或sh中。
[u(1)] pps_weighted_pred_flag:等于0表示加权预测不应用于引用PPS的P个切片。
[u(1)] pps_weighted_bipred_flag:等于0表示不将显式加权预测应用于引用PPS的B切片。
[u(1)] pps_ref_wraparound_enabled_flag:等于1的指定对引用pps的图片启用水平环绕运动补偿。
[se(v)] pps_init_qp_minus26:加26指定了参考PPS的每个slice的SliceQpY的初始值。当解码ph_qp_delta的非零值时,SliceQpY的初始值在picture级别进行修改,或者当解码sh_qp_derta的非零时,在slice级别进行修改。pps_init_qp_minus26的值应在−(26+QpBdOffset)到+37的范围内。
[u(1)] pps_cu_qp_delta_enabled_flag:等于1表示ph_cu_qp_delta_subdiv_intra_slice和ph_cu_6qp_delta_sindter_slice语法元素中的一个或两个存在于引用PPS的ph语法结构中。
[u(1)] pps_chroma_tool_offsets_present_flag:等于1表示色度工具偏移相关的语法元素存在于PPS RBSP语法结构中,包括chroma qp offset,JCBCR qp offset。
[u(1)] pps_deblocking_filter_control_present_flag:等于1表示PPS中存在deblocking滤波器控制语法元素。
[u(1)] pps_picture_header_extension_present_flag:等于0表示在引用PPS的PH语法结构中不存在PH扩展语法元素。
[u(1)] pps_slice_header_extension_present_flag:等于0表示在引用PPS的SH语法结构中不存在SH扩展语法元素。
[u(1)] pps_extension_flag:等于0表示pps RBSP语法结构中不存在pps_extension_data_flag语法元素。



VVC解码流程(3)—SPS

SPS中包含了很多参数和控制信息。

[u(4)] sps_seq_parameter_set_id:sps_id, 取值范围0-15。
[u(4)] sps_video_parameter_set_id:vps_id, 取值范围0-15。
[u(3)] sps_max_sublayers_minus1: 加1指最大时域子层, 取值范围0-6。
[u(2)] sps_chroma_format_idc:chroma采样方式,取值范围0-3。

[u(2)] sps_log2_ctu_size_minus5:加5表示lumaCTU尺寸,取值范围为0-2,3保留,即支持32×32,64×64,128×128大小的CTU。
[u(1)] sps_ptl_dpb_hrd_params_present_flag:等于1表示在SPS中确定profile_tier_level( )、dpb_parameters( )、general_timing_hrd_parameters( )和ols_timing_hrd_parameters( )语法。

如果sps_ptl_dpb_hrd_params_present_flag等于1,执行profile_tier_level( 1, sps_max_sublayers_minus1 ):
[u(7)] general_profile_idc:指定profile。
[u(1)] general_tier_flag:指定tier。
[u(8)] general_level_idc:指定level
[u(1)] ptl_frame_only_constraint_flag:等于 1 表示 CLVS 传送表示场的图片,等于 0 表示 CLVS 传送表示帧的图片。
[u(1)] ptl_multilayer_enabled_flag:等于 1 指定 CVS 可能包含多个层,等于 0 指定 所有 slice 都应具有相同的 nuh_layer_id 值。
[u(1)] gci_present_flag:等于 1 表示展现 General constraints information。会对SPS的某些值的范围加以限制。
[f(1)] gci_alignment_zero_bit:补充0以字节对齐。
[u(1)] ptl_sublayer_level_present_flag[ i ]:对于第i子层,值等于 1 指定在 profile_tier_level( ) 语法结构中存在级别信息。值等于 0 指定在 profile_tier_level( ) 语法结构中不存在级别信息。
[u(1)] ptl_reserved_zero_bit:补充0以字节对齐。
[u(8)] sublayer_level_idc[ i ]:如果 ptl_sublayer_level_present_flag[ i ] 为1,则 sublayer_level_idc[ i ] 为时域子层指定 level。
[u(8)] ptl_num_sub_profiles:指定 general_sub_profile_idc[ i ] 语法元素的数量。
[u(32)] general_sub_profile_idc[ i ]:内容未在标准中指定,一般不用。

[u(1)] sps_gdr_enabled_flag:等于1指定在CLVS中可以打开GDR帧。
[u(1)] sps_ref_pic_resampling_enabled_flag:支持参考帧重采样(RPR)。
[u(1)] sps_res_change_in_clvs_allowed_flag:允许CLVS中的空域分辨率发生改变。
[ue(v)] sps_pic_width_max_in_luma_samples:luma样本的最大宽度,不能等于0,是8的整数倍。
[ue(v)] sps_pic_height_max_in_luma_samples:luma样本的最大宽度,不能等于0,是8的整数倍。
[u(1)] sps_conformance_window_flag:是否要裁剪窗口,一般不用。
[u(1)] sps_subpic_info_present_flag:显示subpic的信息,一般不用。
[ue(v)] sps_bitdepth_minus8:luma和chroma的位深度,取值范围0-2。
[u(1)] sps_entropy_coding_sync_enabled_flag:指定WPP是否打开。
[u(1)] sps_entry_point_offsets_present_flag:指定在slice header中是否展示entry_point_offsets。
[u(4)] sps_log2_max_pic_order_cnt_lsb_minus4:指定最大poc值的LSB,MaxPicOrderCntLsb = 2( sps_log2_max_pic_order_cnt_lsb_minus4 + 4 ),取值范围为0-12。
[u(1)] sps_poc_msb_cycle_flag:指定在ph中可以使用ph_poc_msb_cycle_present_flag。
[ue(v)] sps_poc_msb_cycle_len_minus1:取值范围为0 到 32 − sps_log2_max_pic_order_cnt_lsb_minus4 − 5。
[u(1)] sps_num_extra_ph_bytes:等于0。
[u(1)] sps_num_extra_sh_bytes:等于0。

[ue(v)] dpb_max_dec_pic_buffering_minus1[ i ]:指定最大DPB size。
[ue(v)] dpb_max_num_reorder_pics[ i ]:按解码顺序位于之前并且输出顺序位于之后的允许图片的最大数量。
[ue(v)] dpb_max_latency_increase_plus1[ i ]:不等于0时表示按输出顺序位于之前并且解码顺序位于之后的允许图片的最大数量。等于0时,MaxLatencyPictures[ i ] = dpb_max_num_reorder_pics[ i ] + dpb_max_latency_increase_plus1[ i ] − 1

[ue(v)] sps_log2_min_luma_coding_block_size_minus2:取值范围为 Min( 4, sps_log2_ctu_size_minus5 + 3 )
[u(1)] sps_partition_constraints_override_enabled_flag:等于 1 指定在引用 SPS 的 PH 语法结构中存在 ph_partition_constraints_override_flag。
[ue(v)] sps_log2_diff_min_qt_min_cb_intra_slice_luma:指定I slice最小QT叶节点 size 与最小coding_block_size之间的差值。
[ue(v)] sps_max_mtt_hierarchy_depth_intra_slice_luma:指定I slice MTT的最大深度。
[ue(v)] sps_log2_diff_max_bt_min_qt_intra_slice_luma:指定I slice 最大可以进行二叉树划分的块与最小QT叶节点之间的块尺寸差值。
[ue(v)] sps_log2_diff_max_tt_min_qt_intra_slice_luma:指定I slice 最大可以进行三叉树划分的块与最小QT叶节点之间的块尺寸差值。
[u(1)] sps_qtbtt_dual_tree_intra_flag:dual_tree。
[ue(v)] sps_log2_diff_min_qt_min_cb_intra_slice_chroma:指定I slice chroma最小QT叶节点 size 与最小coding_block_size之间的差值。
[ue(v)] sps_max_mtt_hierarchy_depth_intra_slice_chroma:指定I slice chroma MTT的最大深度。
[ue(v)] sps_log2_diff_max_bt_min_qt_intra_slice_chroma:指定I slice chroma 最大可以进行二叉树划分的块与最小QT叶节点之间的块尺寸差值。
[ue(v)] sps_log2_diff_max_tt_min_qt_intra_slice_chroma:指定I slice chroma 最大可以进行三叉树划分的块与最小QT叶节点之间的块尺寸差值。
[ue(v)] sps_log2_diff_min_qt_min_cb_inter_slice:指定P/B slice最小QT叶节点 size 与最小coding_block_size之间的差值。
[ue(v)] sps_max_mtt_hierarchy_depth_inter_slice:指定P/B slice MTT的最大深度。
[ue(v)] sps_log2_diff_max_bt_min_qt_inter_slice:指定P/B slice 最大可以进行二叉树划分的块与最小QT叶节点之间的块尺寸差值。
[ue(v)] sps_log2_diff_max_tt_min_qt_inter_slice:指定P/B slice 最大可以进行三叉树划分的块与最小QT叶节点之间的块尺寸差值。

[u(1)] sps_max_luma_transform_size_64_flag:等于1表示Max TU size=64,等于0表示Max TU size=32。
[u(1)] sps_transform_skip_enabled_flag:transform_skip。
[ue(v)] sps_log2_transform_skip_max_size_minus2:指定最大ts size。
[u(1)] sps_bdpcm_enabled_flag:bdpcm。
[u(1)] sps_mts_enabled_flag:mts。
[u(1)] sps_explicit_mts_intra_enabled_flag:mts_intra。
[u(1)] sps_explicit_mts_inter_enabled_flag:mts_inter。
[u(1)] sps_lfnst_enabled_flag:lfnst。

[u(1)] sps_joint_cbcr_enabled_flag:joint_cbcr。
[u(1)] sps_same_qp_table_for_chroma_flag:等于 1 指定仅发送一个色度 QP 映射表,并且当 sps_joint_cbcr_enabled_flag 等于 1 时,此表适用于 Cb 和 Cr 残差,此外还适用于joint Cb-Cr 残差。sps_same_qp_table_for_chroma_flag 等于 0 指定在 SPS 中发送色度 QP 映射表,其中两个用于 Cb 和 Cr,当 sps_joint_cbcr_enabled_flag 等于 1 时,还有一个用于joint Cb-Cr。当不存在时,sps_same_qp_table_for_chroma_flag 的值推断为等于 1。
[se(v)] sps_qp_table_start_minus26[ i ]:加 26 指定用于描述第 i 个色度 QP 映射表的起始亮度和色度 QP。sps_qp_table_start_minus26[ i ] 的值应在 −26 − QpBdOffset 至 36 的范围内。如果不存在,则 sps_qp_table_start_minus26[ i ] 的值推断为等于 0。
[ue(v)] sps_num_points_in_qp_table_minus1[ i ]:加 1 指定用于描述第 i 个色度 QP 映射表的点数。
[ue(v)] sps_delta_qp_in_val_minus1[ i ][ j ]:指定用于导出第 i 个色度 QP 映射表的第 j 个枢轴点的输入坐标的增量值。
[ue(v)] sps_delta_qp_diff_val[ i ][ j ]:指定用于导出第 i 个色度 QP 映射表的第 j 个枢轴点的输出坐标的增量值。


[u(1)] sps_sao_enabled_flag:sao。
[u(1)] sps_alf_enabled_flag:alf。
[u(1)] sps_ccalf_enabled_flag:ccalf。
[u(1)] sps_lmcs_enabled_flag:lmcs。
[u(1)] sps_weighted_pred_flag:weighted_pred。
[u(1)] sps_weighted_bipred_flag:weighted_bipred。
[u(1)] sps_long_term_ref_pics_flag:long_term_ref_pics。

[u(1)] sps_idr_rpl_present_flag:等于 1 指定 RPL 语法元素可以存在于 nal_unit_type 等于 IDR_N_LP 或 IDR_W_RADL 的slice的sh中。
[u(1)] sps_rpl1_same_as_rpl0_flag:rpl1与rpl0一样。
[ue(v)] sps_num_ref_pic_lists[ i ]:指定有多少个rpl。
[ue(v)] num_ref_entries[ listIdx ][ rplsIdx ]:指定rpl中有多少帧。
[u(1)] ltrp_in_header_flag[ listIdx ][ rplsIdx ]:等于 0 指定 ref_pic_list_struct( listIdx, rplsIdx ) 语法结构中指示的 LTRP 条目的 POC LSB 存在于同一语法结构中。 ltrp_in_header_flag[ listIdx ][ rplsIdx ] 等于 1 指定
ref_pic_list_struct( listIdx, rplsIdx ) 语法结构中指示的 LTRP 条目的 POC LSB 不存在于同一语法结构中。 当 sps_long_term_ref_pics_flag 等于 1 且 rplsIdx 等于 sps_num_ref_pic_lists[ listIdx ] 时,
ltrp_in_header_flag[ listIdx ][ rplsIdx ] 的值推断为等于 1。
[u(1)] st_ref_pic_flag[ listIdx ][ rplsIdx ][ i ]:short-term reference。
[ue(v)] abs_delta_poc_st[ listIdx ][ rplsIdx ][ i ]:abs_delta_poc。
[u(1)] strp_entry_sign_flag[ listIdx ][ rplsIdx ][ i ]:sign。
[u(1)] rpls_poc_lsb_lt[ listIdx ][ rplsIdx ][ j++ ]:指定long-term 参考帧的poc_lsb。

[u(1)] sps_ref_wraparound_enabled_flag:ref_wraparound。
[u(1)] sps_temporal_mvp_enabled_flag:temporal_mvp。
[u(1)] sps_sbtmvp_enabled_flag:sbtmvp。
[u(1)] sps_amvr_enabled_flag:amvr。
[u(1)] sps_bdof_enabled_flag:bdof。
[u(1)] sps_bdof_control_present_in_ph_flag:bdof_control_present_in_ph。
[u(1)] sps_smvd_enabled_flag:smvd。
[u(1)] sps_dmvr_enabled_flag:dmvr。
[u(1)] sps_dmvr_control_present_in_ph_flag:dmvr_control_present_in_ph。
[u(1)] sps_mmvd_enabled_flag:mmvd。
[u(1)] sps_mmvd_fullpel_only_enabled_flag:mmvd_fullpel_only。
[u(1)] sps_bdof_enabled_flag:bdof。
[u(1)] sps_bdof_control_present_in_ph_flag:bdof_control_present_in_ph。
[u(1)] sps_smvd_enabled_flag:smvd。

[ue(v)] sps_six_minus_max_num_merge_cand:MaxNumMergeCand = 6 − sps_six_minus_max_num_merge_cand。取值范围0-5。

[u(1)] sps_sbt_enabled_flag:sbt。
[u(1)] sps_affine_enabled_flag:affine。
[ue(v)] sps_five_minus_max_num_subblock_merge_cand:MaxNumSubblockMergeCand = 5 − sps_five_minus_max_num_subblock_merge_cand。取值范围0-4。
[u(1)] sps_6param_affine_enabled_flag:6param_affine。
[u(1)] sps_affine_amvr_enabled_flag:affine_amvr。
[u(1)] sps_affine_prof_enabled_flag:affine_prof。
[u(1)] sps_prof_control_present_in_ph_flag:prof_control_present_in_ph。
[u(1)] sps_bcw_enabled_flag:bcw。
[u(1)] sps_ciip_enabled_flag:ciip。
[u(1)] sps_gpm_enabled_flag:gpm。
[ue(v)] sps_max_num_merge_cand_minus_max_num_gpm_cand:MaxNumGpmMergeCand = MaxNumMergeCand −
sps_max_num_merge_cand_minus_max_num_gpm_cand。
[ue(v)] sps_log2_parallel_merge_level_minus2:影响merge候选的导出。

[u(1)] sps_isp_enabled_flag:isp。
[u(1)] sps_mrl_enabled_flag:mrl。
[u(1)] sps_mip_enabled_flag:mip。
[u(1)] sps_cclm_enabled_flag:cclm。
[u(1)] sps_chroma_horizontal_collocated_flag:chroma_horizontal_collocated。
[u(1)] sps_chroma_vertical_collocated_flag:chroma_vertical_collocated。
[u(1)] sps_palette_enabled_flag:palette。

[ue(v)] sps_min_qp_prime_ts:指定ts允许的最小量化参数。
[u(1)] sps_ibc_enabled_flag:ibc。
[ue(v)] sps_six_minus_max_num_ibc_merge_cand
[u(1)] sps_ladf_enabled_flag:ladf, HDR tool。
[u(1)] sps_explicit_scaling_list_enabled_flag:explicit_scaling_list。
[u(1)] sps_dep_quant_enabled_flag:dep_quant。
[u(1)] sps_sign_data_hiding_enabled_flag:sign_data_hiding。
[u(1)] sps_virtual_boundaries_enabled_flag:virtual_boundaries。

[u(1)] sps_field_seq_flag
[u(1)] sps_vui_parameters_present_flag









VVC解码流程(2)—NAL unit header

一个NALU单元包含两部分,即2个字节的 NALU header 和 NALU payload 组成。NALU payload 即 raw byte sequence payload (RBSP),这里不多赘述,本文只详细介绍 NALU header。

NALU header由固定的两个字节组成,下面这个语法元素表可以看到。

forbidden_zero_bit :始终为0。

nuh_reserved_zero_bit :值为0,解码器应允许 nuh_reserved_zero_bit 的值等于1出现在语法中,并应忽略(即从比特流中删除并丢弃)nuh_reserved_zero_bit 等于1的NALU。

nuh_layer_id: 表示NALU属于哪个层,用于RPR和可扩展编码,对于普通类型的编码,nuh_layer_id为0。

nal_unit_type:表示NALU的类型,5个bit,一共可以表示32种类型,目前VVC共有22中NALU类型,分别是8种VCL NALU和14种non-VCL NALU。

8种VCL NALU如下:

相对于HEVC,GDR是一种新的NALU类型,另外7中类型在HEVC码流中的NALU中有详细介绍。

14种non-VCL NALU如下:

相对于HEVC,新增了OPI_NUT, DCI_NUT, PREFIX_APS_NUT, SUFFIX_APS_NUT, PU_NUT。常用的non-VCL NALU是SPS_NUT, PPS_NUT, PREFIX_APS_NUT, SUFFIX_APS_NUT。

nuh_temporal_id_plus1:表示分层编码中temporal layer,VCL NALU就表示对应的层,例如 IDR_W_RADL 对应的 nuh_temporal_id_plus1 为1, STSA_NUT对应的 nuh_temporal_id_plus1 应该大于1。对于non-VCL NALU,nuh_temporal_id_plus1的值有一些特殊限制,但一般情况下的值基本都是1。

VVC解码流程(1)—NALU start code

视频码流是由多个NALU组成的,start code是为了识别NALU,当解码器识别出start code,就认为是一个新的NALU到来。

NALU start code是0x000001或者0x00000001,如果NALU是DCI_NUT, OPI_NUT, VPS_NUT, SPS_NUT, PPS_NUT, PREFIX_APS_NUT, or SUFFIX_APS_NUT这些类型,则NALU start code是0x00000001,否则是0x000001

跟随在NALU start code后面的两个字节为 NAL unit header syntax。

下图中黄色的部分是SPS NALU.

Matrix-Based Intra Prediction(MIP)

VVC的 MIP 模式代表了通过数据驱动方法设计的帧内预测器的新概念。整个MIP过程的概述如图6所示。W和H表示给定块的宽度和高度,MIP的输入由直接位于块上方的W个参考样本refT和直接位于块左侧的H个参考样本refL组成。从这个输入中,MIP帧内预测样本是通过应用平均化、矩阵矢量乘法和线性插值来生成的。

给定变换块上支持的MIP模式的数目nMIP对于mipSizeId=0为16,对于mipSize Id=1为8,对于mipSizeId=2为6。这里,对于4×4个块,mipSizeId设置为0,对于8×8个块和正好具有长度为4的一侧的块,mipSizeId设置为1,对于所有其他块,设置为2。每个MIP模式可以被转置,这是由标志mipTranspose确定的。

1) Averaging

在平均步骤中,上边界样本refT和左边界样本refL被减少到较小的边界redT和redL,对于4×4个块,boundarySize=2,对于所有其他块,boundarySize=4。如果W=boundarySize·2n,则redT定义为:

\(\operatorname{redT}[i]=(\sum_{j=0}^{2^n-1}\operatorname{refT}[2^n\cdot i+j]+(1\ll(n-1)))\gg n,\)

其中0≤i<boundarySize。类似地定义了左简化边界redL。两个边界redT和redL连接到单个简化边界pTemp。这里,如果模式没有转置,则先取redT,否则先取redL。为了减小其对于典型信号特征的幅度,pTemp被转换为一个向量通过

\(\text{p}[0]=2^{B-1}-\text{pTemp}[0];\quad\text{p}[i]=\text{pTemp}[i]-\text{pTemp}[0],\)

其中B表示比特深度,0<i<2·boundarySize。

2) Matrix Vector Multiplication

在第二步中,在缩减边界之外,通过矩阵向量多重叠加生成大小为predSize·predSize的缩减预测信号predMip,如果mipSizeId(W, H)∈{0,1},predSize(W, H))=4,否则predSize(W, H)=8。对于第k个MIP预测模式,0≤k<nMIP,计算(9)

\(\text{predMip}=(A_k\cdot\text{p+32}\cdot1)\gg6+\text{pTemp}[0]\cdot1.\)

在这个等式中,Ak是一个矩阵,其行数为predSize·predSize,列数等于p的大小。此外,“·”表示矩阵向量乘法,1表示大小为predSize.predSize的一个矩阵的向量,并且按元素应用右移。之后,对predMip的分量应用范围[0,2B−1)的clip。

如果水平和垂直上采样因子被设置为 upHor=W/predSize并且upVer=H/predSize,则信号predMip分别在块的每个upHor和upVer采样位置定义最终预测信号pred。更准确地说,如果 0≤x<predSize 和 0≤y<predSze,对于mipTranspose=0,pred定义为:

\(\begin{aligned}\text{pred}[(x+1)\cdot\text{upHor}-1,(y+1)\cdot\text{upVer}-1]\\=\text{predMip}[y\cdot\text{predSize }+x].\end{aligned}\)

对于mipTranspose=1,pred是通过交换最后一个方程右侧的x和y来定义的。

3) Linear Interpolation

在最后一个步骤中,在剩余的样本位置,通过线性插值导出pred的值,其中首先执行水平插值,然后执行垂直插值。这里,对于水平插值,通过参考样本将预测扩展到左侧。

4) Specification of the MIP Matrices

(9)中出现的每个矩阵Ak由 mipSizeId 和 MIP 模式 k 唯一地确定。其条目可以使用7位精度来表示。此外,对于mipSizeId=2,每个Ak的第一列是零,因为对应的MIP模式将恒定边界信号映射到相同值的恒定预测信号。因此,总的来说,为MIP指定了16个大小为16×4的矩阵,用于mipSizeId=0,8个大小为16*8的矩阵,用作mipSizeId=1,以及6个大小为64×7的矩阵,用来mipSizeId=2。

5) Computational Complexity and Memory Requirement of MIP

生成MIP预测所需的每个样本的平均乘法次数最多为四次,因此不大于VVC的传统帧内预测模式。因此,可以观察到,尽管MIP用于超过20%的帧内块,但不会产生任何解码器运行时开销。此外,根据前一节,存储所有MIP矩阵Ak的条目的总存储器需求为4144字节。

6) MIP as a Video-Coding Tool Designed by Data-Driven Methods

VVC中MIP模式的最终设计可以被视为最初提出的基于神经网络的帧内预测模式的低复杂度变体。虽然数据驱动训练算法的关键方面也被用于确定矩阵Ak的参数,但最终用于VVC的设计代表了与初始变体不同的增益复杂度权衡的操作点。复杂度降低的中心步骤是预测的输入的下采样和输出的上采样。通过这种方式,矩阵的大小可以显著减小,并且相同的矩阵可以用于不同的块形状。

编译反馈优化(PGO)

原文: 字节跳动在PGO反馈优化技术上的探索与实践

PGO(Profile-guided optimization)通常也叫做 FDO(Feedback-directed optimization),它是一种编译优化技术,它的原理是编译器使用程序的运行时 profiling 信息,生成更高质量的代码,从而提高程序的性能。

传统的编译器优化通常借助于程序的静态分析结果以及启发式规则实现,而在被提供了运行时的 profiling 信息后,编译器可以对应用进行更好的优化。通常来说编译反馈优化能获得 10%-15% 的性能收益,对于特定特征的应用(例如使用编译反馈优化 Clang本身)收益高达 30%。

编译反馈优化通常包括以下手段:

  1. Inlining,例如函数 A 频繁调用函数 B,B 函数相对小,则编译器会根据计算得出的 threshold 和 cost 选择是否将函数 B inline 到函数 A 中。
  2. ICP(Indirect call promotion),如果间接调用(Call Register)非常频繁地调用同一个被调用函数,则编译器会插入针对目标地址的比较和跳转指令。使得该被调用函数后续有了 inlining 和更多被优化机会,同时增加了 icache 的命中率,减少了分支预测的失败率。
  3. Register allocation,编译器能使用运行时数据做更好的寄存器分配。
  4. Basic block optimization,编译器能根据基本块的执行次数进行优化,将频繁执行的基本块放置在接近的位置,从而优化 data locality,减少访存开销。
  5. Size/speed optimization,编译器根据函数的运行时信息,对频繁执行的函数选择性能高于代码密度的优化策略。
  6. Function layout,类似于 Basic block optimization,编译器根据 Caller/Callee 的信息,将更容易在一条执行路径上的函数放在相同的段中。
  7. Condition branch optimization,编译器根据跳转信息,将更容易执行的分支放在比较指令之后,增加icache 命中率。
  8. Memory intrinsics,编译器根据 intrinsics 的调用频率选择是否将其展开,也能根据 intrinsics 接收的参数优化 memcpy 等 intrinsics 的实现。

编译器需要 profiling 信息对应用进行优化,profile 的获取通常有两种方式:

  • Instrumentation-based(基于插桩)
  • Sample-based(基于采样)

Instrumentation

Instrumentation-based PGO 的流程分为三步骤:

  • 编译器对程序源码插桩编译,生成插桩后的程序(instrumented program)。
  • 运行插桩后的程序,生成 profile 文件。
  • 编译器使用 profile 文件,再次对源码进行编译。

Instrumentation-based PGO 对代码插桩包括:

1. 插入计数器(counter)

  • 对编译器 IR 计算 MST,计算频繁跳转的边,对不在 MST 上的边插入计数器,用于减少插桩代码对运行时性能的影响。
  • 在函数入口插入计数器。

2. 插入探针(probes)

  • 收集间接函数调用地址(indirect call addresses)。
  • 收集部分函数的参数值。

Sampling

Sample-based PGO 的流程同样分为三步骤:

  • 编译器对程序源码进行编译,生成带调试信息的程序(program with debug information)。
  • 运行带调试信息的程序,使用 profiler(例如linux perf)采集运行时的性能数据。
  • 编译器使用 profile 文件,再次对源码进行编译。

其中步骤2采集的数据为二进制级别采样数据(例如 linux perf 使用 perf record 命令收集得到 perf.data 文件)。二进制采样数据通常包含的是程序的 PC 值,我们需要使用工具,读取被采样程序的调试信息(例如使用 AutoFDO 等工具),将程序的原始二进制采样数据生成程序源码行号对应的采样数据,提供给编译器使用。

比较

对比 sampled-based PGO,Instrumentation-based PGO 的优点采集的性能数据较为准确,但繁琐的流程使其在业务上难以大规模落地,主要原因有以下几点:

  • 应用二进制编译时间长,引入的额外编译流程影响了开发、版本发布的效率。
  • 产品迭代速度快,代码更新频繁,热点信息与应用瓶颈变化快。而 instrumented-based PGO 无法使用旧版本收集的 profile 数据编译新版本,需要频繁地使用插桩后的最新版本收集性能数据。
  • 插桩引入了额外的性能开销,这些性能开销会影响业务应用的性能特征,收集的 profile 不能准确地表示正常版本的性能特征,从而降低优化的效果,使得 instrumented-based PGO 的优点不再明显。

使用 Sample-based PGO 方案可以有效地解决以上问题:

  • 无需引入额外的编译流程,为程序添加额外的调试信息不会明显地降低编译效率。
  • Sample-based PGO 对过时的 profile 有一定的容忍性,不会对优化效果产生较大影响。
  • 采样引入的额外性能开销很小,可以忽略不计,不会对业务应用的性能特征造成影响。

Adaptive Loop Filter (ALF)

Karczewicz, Marta, et al. “VVC in-loop filters.” IEEE Transactions on Circuits and Systems for Video Technology 31.10 (2021): 3907-3925.

A. Filter Shapes, Linear Filtering and Adaptive Clipping

ALF被应用于SAO的输出样本。亮度和色度分量分别支持7×7菱形和5×5菱形两种滤波器形状,如图2所示。在图2中,每个正方形对应于亮度或色度样本,中心正方形对应于待滤波的DC样本。为了减少信令开销和乘法次数,滤波器系数使用点对称。每个整数滤波器系数\(c_i\)用7-bit分数精度表示。此外,为了保持DC中性,一个滤波器的系数之和必须等于128,这是具有7-bit分数精度的1.0的定点表示(1):

\(\begin{aligned}2\sum_{i=0}^{N-2}c_i+c_{N-1}=128. & \left({\mathbf{1}}\right)\end{aligned}\)

在等式(1)中,对于 7 × 7 和 5 × 5 滤波器形状,系数 N 的数量分别等于 13 和 7。

通过将系数 \(c_i\) 应用于重构样本值 \(R(x, y)\)来导出坐标 (x, y) 处的滤波样本值 \(\tilde{R}(x,y)\),如下所示(2):

\(\begin{aligned}\tilde{R}(x,y)=&\left[\sum_{i=0}^{N-2}c_i\left(R\left(x+x_i,y+y_i\right)+R\left(x-x_i,y-y_i\right)\right) \\
+c_{N-1}R\left(x,y\right)+64\right]>>7,& \left({\mathbf{2}}\right)\end{aligned}\)

其中 \((x + x_i, y + y_i)\) 和 \((x − x_i, y − y_i)\) 是对应于第 i 个系数 \(c_i\) 的重构样本的坐标。 由于等式(1)的约束,等式(2)可以写为(3):

\(\begin{aligned}
\tilde{R}\left(x,y\right)& =R\left(x,y\right) \\
&+\left\{\left[\sum_{i=0}^{N-2}c_i\left(R\left(x+x_i,y+y_i\right)-R\left(x,y\right)\right)\right.\right. \\
&\left.+\sum_{i=0}^{N-2}c_i\left(R\left(x-x_i,y-y_i\right)-R\left(x,y\right)\right)+64\right] \\
&\left.>>7\right\}.& \left({\mathbf{3}}\right)
\end{aligned}\)

基于等式(3),通过将待滤波样本\(R(x, y)\)与其相邻样本之间的差的加权和添加到重构样本\(R(x, y)\)来获得滤波样本 \(\tilde{R}(x,y)\)。

等式(3)中的系数对于处于与待滤波样本相同的相对几何位置的所有样本是相同的。与仅考虑图片样本的几何接近度的线性滤波器不同,诸如双边滤波器的非线性滤波器也可以基于样本值的相似性来调整其系数。因此,双边滤波器可以在保留边缘的同时有效地去除噪声。为了允许ALF滤波器考虑样本之间的空间关系和值相似性,在等式(3)中添加clip相邻样本值和当前待滤波样本之间的差的可能性。当启用非线性ALF时,方程(3)修改如下:

\(\begin{aligned}
\tilde{R}\left(x,y\right)& =R\left(x,y\right) +\left[(\sum_{i=0}^{N-2}c_if_i+64)>>7 \right] & \left({\mathbf{4}}\right)
\end{aligned}\)

其中

\(\begin{aligned}f_i&=\min\left(b_i,\max\left(-b_i,R\left(x+x_i,y+y_i\right)-R\left(x,y\right)\right)\right)\\ &+\min\left(b_i,\max\left(-b_i,R\left(x-x_i,y-y_i\right)-R\left(x,y\right)\right)\right) & \left({\mathbf{5}}\right)\end{aligned}\)

\(b_i\)是由clipping索引\(d_i\)确定的系数\(c_i\)的clipping参数。\(b_i\)推导如下:

\(\left.b_i=\left\{\begin{array}{ll}2^{BD},&\text{when }d_i=0\\2^{BD-1-2d_i},&\text{otherwise}\end{array}\right.\right.\left({\mathbf{6}}\right)\)

其中BD是样本比特深度,\(d_i\)可以是0、1、2或3。

B. Luma Sub-Block Level Filter Adaptation

子块级滤波器自适应仅应用于亮度分量。每个4×4亮度块根据其方向性和2D拉普拉斯活动进行分类。首先,计算水平、垂直和两个对角线方向的样本梯度值:

\(\begin{aligned}
H_{k,l}=\left|2R\left(k,l\right)-R\left(k-1,l\right)-R\left(k+1,l\right)\right|, \\
V_{k,l}=\left|2R\left(k,l\right)-R\left(k,l-1\right)-R\left(k,l+1\right)\right|, \\
D0_{k,l}=\left|2R\left(k,l\right)-R\left(k-1,l-1\right)-R\left(k+1,l+1\right)\right|, \\
D1_{k,l}=\left|2R\left(k,l\right)-R\left(k-1,l+1\right)-R\left(k+1,l-1\right)\right|. & \left({\mathbf{7}}\right) \end{aligned} \)

基于样本梯度,子块水平梯度\(g_h\)、垂直梯度\(g_v\)和两个对角线梯度\(g_{d0}\)和\(g_{d1}\)计算如下:

\(\begin{aligned}
g_h=\sum_{k=i-2}^{i+5}+\sum_{l=j-2}^{i+5}H_{k,l}, \\
g_v=\sum_{k=i-2}^{i+5}+\sum_{l=j-2}^{i+5}V_{k,l}, \\
g_{d0}=\sum_{k=i-2}^{i+5}+\sum_{l=j-2}^{i+5}D0_{k,l}, \\
g_{d1}=\sum_{k=i-2}^{i+5}+\sum_{l=j-2}^{i+5}D1_{k,l},
& \left({\mathbf{8}}\right)\end{aligned}\)

索引\(i\)和\(j\)是指4×4亮度块中左上角样本的坐标。从等式(8)中可以看出,覆盖目标4×4块的10×10亮度窗口内的样本梯度之和用于对该块进行分类。为了降低复杂性,只计算10×10窗口中间隔样本的梯度,如图3所示。其他采样梯度的值设置为0。

其次,分配方向性D,子块水平和垂直梯度的最大值和最小值的比值:

\(g_{h,v}^{max}=max(g_h, g_v),g_{h,v}^{min}=min(g_h,g_v) \left({\mathbf{9}}\right)\)

以及两个子块对角线梯度的最大值和最小值之比:

\(g_{d0,d1}^{max}=max(g_{d0}, g_{d1}),g_{d0,d1}^{min}=min(g_{d0},g_{d1}) \left({\mathbf{10}}\right)\)

相互比较并且与一组阈值t1和t2进行比较:

步骤1:如果\(g_{h,v}^{max} \le t1\cdot g_{h,v}^{min}\)和\(g_{d0,d1}^{max} \le t1\cdot g_{d0,d1}^{min}\),D都设置为0(块被归类为“texture”)。

步骤2:如果\(g_{h,v}^{max} / g_{h,v}^{min}>g_{d0,d1}^{max} /g_{d0,d1}^{min}\),则在步骤3中计算方向性D,否则在步骤4中计算。。

步骤3:如果\(g_{h,v}^{max}>t2\cdot g_{h,v}^{min}\),D设置为2(块被归类为“强水平/垂直”),否则D设置为1(块被分类为“弱水平/垂直“)。

步骤4:如果\(g_{d0,d1}^{max}>t2\cdot g_{d0,d1}^{min}\),D设置为4(块被归类为“强对角线”),否则D设置为3(块被分类为“弱对角线”)。

只有在前面的步骤中没有分配给D的值的情况下,才执行上述D计算中的每个后续步骤。第三,活动值A计算为:

\(A=\left(\sum_{k=i-2}^{i+5}\sum_{l=j-2}^{j+5}\left(V_{k,l}+H_{k,l}\right)\right)>>\left(BD-2\right). \left({\mathbf{11}}\right)\)

A被进一步映射到0到4的范围:\(\hat A=Q_{min(A,15)}\),其中\(Q_n=\{0, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4\}\)。最后,每个4×4亮度块被分类为25类中的一类:

\(C=5D+\hat A \left({\mathbf{12}}\right)\)

每个类都可以分配自己的滤波器。

在对每个4×4亮度块进行滤波之前,根据表I中指定的子块梯度值,对滤波器系数应用几何变换,如90度旋转、对角线或垂直翻转,如图4所示。这相当于将这些变换应用于滤波器支持区域中的样本。目标是对齐不同块的方向性,以减少ALF类的数量,进而减少滤波器系数。应用几何变换允许具有水平边的4×4块和具有垂直边的4×4块都具有相同的方向性D。

C. Coding Tree Block Level Filter Adaptation

除了亮度4×4块级滤波器自适应外,ALF还支持CTB级滤波器自适应。亮度CTB可以使用为当前slice计算的滤波器集或者为已经编码的slice计算的一个滤波器集。它还可以使用16个离线训练的过滤器集中的一个。在每个亮度CTB内,所选滤波器集中的哪个滤波器应应用于每个4×4块,由该块的等式(12)中计算的类别C确定。

Chroma仅使用CTB级滤波器自适应。一个片中的色度分量最多可以使用8个滤波器。每个CTB可以选择这些过滤器中的一个。

D. Syntax Design

滤波器系数和clipping索引被携带在ALF APS中。ALF APS可以包括多达8个色度滤波器和一个具有多达25个滤波器的亮度滤波器组。对于25个亮度类别中的每一个,还包括索引\(i_C\)。具有相同索引\(i_C\)的类共享相同的滤波器。通过合并不同的类,减少了表示滤波器系数所需的比特数。滤波器系数的绝对值使用后面跟有非零系数的符号位的0阶Exp-Golomb码来表示。当clipping被启用时,还使用两位固定长度代码来用信号通知每个滤波器系数的clipping索引。APS内的ALF系数和clipping索引所需的存储最多为3480比特。解码器可以同时使用多达8个ALF APS。

滤波器控制语法元素包括两种类型的信息。首先,ALF开/关标志在序列、图片、Slice和CTB级别用信号通知。只有在相应级别启用亮度ALF时,才能在图片和切片级别启用色度ALF。第二,如果在图片、Slice和CTB级别启用ALF,则在该级别用信号通知滤波器使用信息。如果图片内的所有Slice都使用相同的APS,则参考ALF APS ID以Slice级别或图片级别进行编码。亮度分量可以参考多达7个ALF APS,色度分量可以参考1个ALF APS。对于亮度CTB,用信号通知指示使用哪个ALF APS或离线训练的亮度滤波器集的索引。对于色度CTB,索引指示使用参考APS中的哪个滤波器。

E. Line Buffer Reduction

为了减少ALF的存储需求,VVC采用了行缓冲边界处理。在VVC中,行缓冲器边界被放置在水平CTU边界之上的4个亮度样本和2个色度样本。当将ALF应用于行缓冲区边界一侧的样本时,不能使用行缓冲区边缘另一侧的样本。

图5给出了两个例子,其中4×4亮度块与行缓冲区边界相邻。当将ALF应用于图5(a)中的行E至H中的4×4亮度块时,如果没有行缓冲区边界处理,则需要使用DBF和SAO过滤的行B至K的样本。在较低的CTU可用之前,DBF和SAO过滤器不能应用于行A到D。因此,在没有行缓冲器的情况下,ALF不能应用于行E至H中的样本,直到较低的CTU可用为止。结果,除了行A到D之外,从E到K的7个亮度行将必须存储在用于亮度ALF的行缓冲器中。类似地,4个附加色度行将必须存储在色度ALF的行缓冲器中。

图5还说明了当对与行缓冲区边界相邻的4×4亮度块进行分类时样本梯度值的计算。为了计算与行缓冲区边界相邻的样本梯度值(标记为×),应用重复填充来替换无法使用的样本。例如,在图5(a)中,用行E中的样本替换行D中的样本。行缓冲区边界另一侧的所有样本梯度值都设置为0。由于我们将一些样本梯度值设置为0,从而减少了样本梯度的总和,因此方程(11)中的A推导按如下比例缩放:

\(A=\left(\sum_{k=i-2}^{i+5}\sum_{l=j-2}^{j+5}\left(V_{k,l}+H_{k,l}\right)\cdot 3 \right)>>\left(BD-1\right). \left({\mathbf{13}}\right)\)

行缓冲区边界滤波应用如图6所示的对称样本填充,其中p12标记待滤波样本,p0至p24是SAO之后的样本值,p’0至p’24是修改后的样本值。当待滤波样本的滤波器形状不越过行缓冲区边界时,在滤波过程中使用SAO之后的样本值。否则,将在滤波过程中使用修改后的值。与重复填充相比,对称样本填充已被证明可以产生不太明显的视觉伪影。然而,当要滤波的样本位于最靠近行缓冲区边界的行中时,如图6(a)所示,2D滤波器等效于水平滤波器,它仍然会引入明显的视觉伪影。

通过将滤波器强度减少8倍来最小化这些伪影,从而得出以下公式,其中等式(4)中的偏移7被偏移10代替:

\(\tilde{R}\left(x,y\right)=R\left(x,y\right)+\left[\left(\sum_{i=0}^{N-2}c_if_i+512\right)>>10\right]\)

F. ALF Encoder Design in VTM

这里描述VTM-9.0中的ALF编码器实现。编码器通过最小化率失真成本来计算ALF语法元素的值,所述率失真成本是失真的加权和,所述失真被测量为原始样本和应用ALF滤波器之后的样本之间的平方误差,以及传输ALF语法元素所需的比特数。滤波器系数是通过求解Wiener-Hopf方程来计算的。采用平方误差估计方法,允许在不执行实际滤波操作的情况下计算滤波失真。针对clipping 索引的所有可能组合收集计算滤波器系数和估计失真所需的统计信息。分别收集每个CTB的统计数据,在亮度成分的情况下,收集每个CTU的每个类别的统计数据。

1) 亮度分量:对于每个图片,基于该图片的统计信息,获得亮度分量的新滤波器集,表示为FY,D,如下所示:
(1) 编码器通过合并启用ALF的CTB的统计信息来导出滤波器集FY,D。在第一次迭代中,假设为所有CTB启用ALF。
(2) 基于使用导出的滤波器计算的速率失真成本和CTB的统计来为每个CTB确定是否应用ALF滤波器。

步骤1)和2)重复4次。

当设计在步骤1)中设置的亮度滤波器时,编码器首先为25个亮度类别中的每一个计算滤波器。然后将合并算法应用于这25个滤波器。在每次迭代中,通过合并两个滤波器,该算法将滤波器的数量减少1。为了确定应该合并哪两个滤波器,对于每对剩余的滤波器,编码器通过分别合并两个滤波器和相应的统计数据来重新设计滤波器。使用重新设计的滤波器,然后估计失真。编码器以最小的失真合并该对。获得25个滤波器组,第一组具有25个滤波器,第二组具有24个滤波器,以此类推,直到第25组包含单个滤波器。选择最小化率失真成本的集合,包括对滤波器系数进行编码所需的比特。

在设计滤波器时,迭代计算clipping 索引和N−1滤波器系数,直到平方误差不减小。在每次迭代中,clipping 索引的值都会逐一更新,从索引d0开始,一直到达到索引dN−2。更新索引时,最多测试3个选项:保持其值不变、增加1或减少1。针对这3个值计算滤波器系数和近似失真,并选择使平方误差最小化的值。在第一次迭代开始时,clipping 索引的值被初始化为2,或者当合并两个滤波器时,di的值被设置为这些滤波器的对应剪裁索引的平均值。

亮度分量还可以使用离线训练的滤波器集和可用ALF APS中携带的亮度滤波器集。通过访问APS,从最近发信号到最后一个,编码器获得多达7个亮度滤波器组,这些滤波器组表示为FiY,APS,其中i=0,。。。,NAPS−1。亮度ALF语法元素的最终值是通过选择滤波器集Fij的最佳组合来获得的,其中i=0,1和j=0,。。。,NAPS

· 16个离线训练的滤波器集,
· FY,D,如果i=1,
· F0Y,APS ,…, Fj-1Y,APS, 如果j>0

2) 色度分量:基于当前图片统计,计算色度滤波器组FC,D。导出8个色度滤波器组,表示为FiC,D,其中i=1,2,。。。,7, 8.滤波器组FiC,D包含i个滤波器。滤波器组FiC,D如下获得:

1) 当前图片被均匀地划分为i个区域。对于每个区域,通过合并该区域中所有CTB的统计信息来计算色度滤波器。
2) 对于图片中的每个色度CTB,ALF开/关标志和来自集合FiC,D的滤波器索引被确定为最小化估计的速率失真成本。
3) FiC,D中的每个滤波器通过合并色度CTB的统计来重新设计,其中在步骤2)中为其选择了当前要重新设计的滤波器。
4) 步骤2)和3)重复i+1次。

选择使速率失真成本最小化的滤波器组FiC,D作为色度滤波器组FC,D。最后,编码器从可用的APS中选择FC,D或滤波器组之一,以用于色度分量。

Bi-Directional Optical Flow (BDOF)

传统的双向预测是来自先前编码的图片的两个预测块的加权组合。 两个MV用于分别从List0参考图片和List1参考图片获得两个预测块。 然而,由于基于块的MC的限制,两个预测块内的样本之间通常存在剩余位移。 BDOF 的目的是在原始块级 MV 之上补偿每个预测样本的精细位移。

与基于块的运动补偿相反,MV 的细化值不在 BDOF 中用信号表示。 BDOF应用于常规Merge模式中或非SMVD的帧间模式中的CU的亮度CB。 BDOF 仅限于宽度和高度大于或等于 8 个亮度样本且亮度样本数量大于或等于 128 的 CU。

BDOF 建立在光流概念的基础上。 令 I(i, j,t) 为样本在位置 (i, j) 和时间 t 处的亮度值。 假设物体运动过程中每个样本的亮度恒定,此时的光流微分方程可以表示为(1):

\(\begin{aligned}&0=\frac{\partial I}{\partial t}+v_x\frac{\partial I}{\partial x}+v_y\frac{\partial I}{\partial y}.\end{aligned}\)

如图 8 所示,在每个样本位置,描述从 Ic 到 I0 的剩余小位移的运动 (vx , vy ) 与其从 Ic 到 I1 的运动对称。 这里,Ic、I0 和 I1 分别是当前块以及来自列表 0 和列表 1 参考图片的两个预测块中的亮度值数组。 为了简单起见,假设相对于两个参考图片的剩余运动幅度相同且方向相反。 这一假设反映在只有当两个不同的参考图片在 POC 中与当前图片具有相等距离时才应用 BDOF 的约束。

基于对称运动模型,式(1)可用于从两个方向估计Ic中每个样本的值,一个来自I0中的对应A,另一个来自I1中的对应B。 (vx , vy ) 的值是通过最小化具有精细运动的两个预测之间的差异来计算的(2)(3):

\((v_x,v_y):\min\sum_{(i,j)\in\Omega}\Delta^2(i,j);\)

\(\begin{aligned}
\Delta\left(i,j\right)=& I_0(i,j)-I_1(i,j) \\
&+v_x(\frac{\partial I_0(i,j)}{\partial x}+\frac{\partial I_1(i,j)}{\partial x}) \\
&+v_y(\frac{\partial I_0(i,j)}{\partial y}+\frac{\partial I_1(i,j)}{\partial y}).
\end{aligned}\)

这里(i,j)是预测块内样本的空间坐标,Ω是该样本的区域。 对离散样本数组 I0(i, j) 和 I1(i, j) 进行空间导数的近似(4)(5):

\(\begin{aligned}\frac{\partial I_{0,1}(i,j)}{\partial x}&=(I_{0,1}(i+1,j)-I_{0,1}(i-1,j))\gg1\end{aligned}\)
\(\begin{aligned}\frac{\partial I_{0,1}(i,j)}{\partial y}&=(I_{0,1}(i,j+1)-I_{0,1}(i,j-1))\gg1\end{aligned}\)

为了降低推导局部剩余运动的计算复杂度,假设每个 4 × 4 子块内的向量 (vx , vy ) 恒定。 它计算一次并由子块中的所有样本共享。 此外,为了使导出的运动场更加稳定,每个 4 × 4 子块的 (vx , vy ) 是根据中心包含 4 × 4 子块的扩展 6 × 6 区域(在(2)中记为 Ω )计算的。

(2) 中的优化问题可以通过将两个偏导数设置为零来解决,所得线性方程组近似求解为(4)-(9):

\(\begin{aligned}v_x=-\frac{S_4}{S_1},\quad v_y=-\frac{S_5+v_xS_3}{S_2}\end{aligned}\)
\(\begin{aligned}S_1&=\sum_{(i,j)\in\Omega}\vartheta_x(i,j)\cdot\vartheta_x(i,j),\end{aligned}\)
\(\begin{aligned}S_2&=\sum_{(i,j)\in\Omega}\vartheta_y(i,j)\cdot\vartheta_y(i,j),\end{aligned}\)
\(\begin{aligned}S_3&=\sum_{(i,j)\in\Omega}\vartheta_x(i,j)\cdot\vartheta_y(i,j),\end{aligned}\)
\(\begin{aligned}S_4&=\sum_{(i,j)\in\Omega}\vartheta_t(i,j)\cdot\vartheta_x(i,j),\end{aligned}\)
\(\begin{aligned}S_5&=\sum_{(i,j)\in\Omega}\vartheta_t(i,j)\cdot\vartheta_y(i,j),\end{aligned}\)

全部是自相关和互相关参数,ϑx (i, j) 和 ϑy(i, j) 是水平和垂直梯度,ϑt(i, j) 是位置 (i, j) 处样本的时间梯度 j,计算公式为(10)-(12):

\(\vartheta_x(i,j)=\frac{\partial I_0(i,j)}{\partial x}+\frac{\partial I_1(i,j)}{\partial x}\)
\(\begin{aligned}\vartheta_y(i,j)&=\frac{\partial I_0(i,j)}{\partial y}+\frac{\partial I_1(i,j)}{\partial y}\end{aligned}\)
\(\vartheta_t(i,j)=I_0(i,j)-I_1(i,j).\)

导出 (vx , vy) 后,通过沿着运动轨迹对列表 0 和列表 1 预测样本进行插值来计算块当前位置 (i, j) 处的最终双向预测信号 Ic(i, j)(如图8所示)基于Hermite插值,即

\(\begin{aligned}I’c(i,j)&=\frac{1}{2}(I_0(i,j)+I_1(i,j)+\sigma_{\mathrm{BDOF}}),\end{aligned}\)
\(\begin{aligned}\sigma_{\mathrm{BDOF}}&=v_{x}(\frac{\partial I_{0}(i,j)}{\partial x}-\frac{\partial I_{1}(i,j)}{\partial x})\\&+v_{\mathrm{y}}(\frac{\partial I_{0}(i,j)}{\partial y}-\frac{\partial I_{1}(i,j)}{\partial y}).\end{aligned}\)