一 四叉树划分
AV1标准包含矩形划分,PARTITION_HORZ, PARTITION_VERT, PARTITION_HORZ_4等,而set_child_to_be_considered 仅仅处理四叉树,PARTITION_SPLIT 的递归。正在补充注释说明矩形划分由其它逻辑处理。
递归划分原理
AV1的块划分是四叉树,每个块可以划分成4个方形子块
128x128 -> 4个64x64
AV1 还有矩形子块划分PARTITION_HOEZ/PARTITION_VERT / HORZ_4 /VERT_4 等
是在同一深度上对父方块做出的形状选择,水平二分,垂直二分,4:1等
由块几何表,svt_aom_blk_geom_mds 和d1 阶段决策如 svt_aom_d1_non_square_block_decision
处理,不在此递归中,此处负责是否继续按照四叉树再分一层,的递归标记。
正在更新函数内部那处 四叉树 的注释,使其与上述说明一致。
计算4个子块的索引
AV1的块划分是四叉树,每个块划分成4个子块,左上,右上,左下,右下
child_block_idx_1 第一个子块 左上的索引 = 父块索引 + d1 深度偏移
definitions.h 定义了多种划分类型:
PARITION_HOEZ, PARTITION_VERT, PARTITION_HORZ_A/B, PARTITION_VERT_A/B、PARTITION_HORZ_4、PARTITION_VERT_4 等。
BlockGeom 里有shape, PART_N, PART_H, PART_V 和bwidth, / bheight 几何表里面已经包含了4x8, 8x4, 16x32等矩形块
矩形划分的cost 比较在d1阶段,例如svt_aom_d1_non_square_block_decision
原注释不准确的地方
写的是AV1的块划分是四叉树,容易让人认为是AV1只有四叉树,
- set_child_to_be_considered 只做一件事 :对"四叉树(PARTITION_SPLIT) "这一种划分方式做递归------即"当前方形块要不要再拆成 4 个方形子块",并只计算/标记这 4 个子块的索引。
- 矩形划分 是在同一深度 上、对同一个父方块做的形状选择 (选不划分、水平二分、垂直二分、4:1 等),由预定义的块几何表和 d1 决策处理,不在这条递归里 。
1 递归划分原理,明确写本函数只处理四叉树,PARTITION_SPLIT递归,并补充说明AV1 还有矩形划分,由块几何表和d1 决策处理,不在此递归中。
2 计算4个子块
二 帧内帧间决策
I_SLICE 整帧只能帧内,不做帧间ME,SB不会选帧间
P_SLICE/B_SLICE 允许帧间 每个块再在 帧内/帧间 里选
相关逻辑主要在enc_dec_process.c 用pcs->slice_type 控制例如,
是否做ME,是否允许VERY_LIGHT_PDO
I_SLICE 下128x128块的特殊处理,
是否用参考帧信息作PD0/PD1
帧内是否参与搜索由intra_ctrls.enable_intra, skip_intra等控制,
enc_mode_config.c 的set_intra_ctrls.
2 块级,帧内vs帧间的实际决策,RD选最优候选
每个块是在同一批候选,帧内+帧间 里做的RD比较,选cost 最小的候选;该候选的是inter则块为帧间,否则为帧内,没有单独的先选帧内/帧间 再选自模式步骤
候选来源,帧内+帧间 一起进候选列表
在product coding loop .c 的md_encode_block里
帧内,inject_intra_candidates, inject_filter_candidates, inject_intra_bc_candidates, inject_palette_candidates 等
帧间 svt_aom_inject_inter_candidates等
这些候选都会进入同一个候选列表,后面统一算cost。
选最优候选并写入predictions_mode_flag
在mode_decision.c里
svt_aom_product_full_mode_decision
在buffer_ptr_array里按照full_cost 选lowest_cost_index ,得到最佳候选cand_bf / cand
然后设置块级结果
mode_decision.c
blk_ptr->prediction_mode_flag = is_inter_mode(cand->pred_mode)?INTER_MODE:INTRA_MODE;
blk_ptr->use_intrabs = cand->use_intrabs;
blk_ptr->pred_mode = cand->pred_mode;
svt_aom_product_full_mode_decision_light_pd1
Light PD1路径下同样根据已经选中的候选设置,prediction_mode_flag
SB里每个块是帧内还是帧间的决策,就发生在这里选中的最佳候选的pred_mode是Inter则为INTER_MODE,否则为INTRA_MODE
调用链
md_encode_block product_coding_loop.c 里会做多阶段MD MDS0->MDS1 ,最后在某一节顿啊调用svt_aom_product_full_mode_decision,或者light_pd1 版本。得到当前块的最优候选并写回blk_ptr 含有prediction_mode_flag
svt_aom_mode_decision_sb遍历SB内各个块,对每个块调用process_block->md_encode_block ,因此每个块的帧内/帧间都在md_encode_block里通过上述full mode decision决定的。
SB决策为帧内和帧间的块级逻辑,就在mode_decision.c的svt_aom_product_full_mode_decision 里通过选cost最小的候选间接的搭配帧内/帧间,并写入blk_ptr->prediction_mode_flag。