1,函数功能
配置tile中superblock的属性,配置编码顺序,inter编码初始化运动搜索,rd_pick_partition()进入下一层编码
2,代码学习
static void encode_sb_row(AV1_COMP *cpi, ThreadData *td, TileDataEnc *tile_data,
int mi_row, TOKENEXTRA **tp, int use_nonrd_mode) {
AV1_COMMON *const cm = &cpi->common;
const int num_planes = av1_num_planes(cm);//平面
const TileInfo *const tile_info = &tile_data->tile_info;//tile信息
MACROBLOCK *const x = &td->mb;//Ymode
MACROBLOCKD *const xd = &x->e_mbd;
const SPEED_FEATURES *const sf = &cpi->sf;
const int sb_cols_in_tile = av1_get_sb_cols_in_tile(cm, tile_data->tile_info);//列位置
const BLOCK_SIZE sb_size = cm->seq_params.sb_size;//本帧用的sb大小
const int mib_size = cm->seq_params.mib_size;//以MI块大小为单位的super块的MI块大小
const int mib_size_log2 = cm->seq_params.mib_size_log2;//MI块大小的对数值
const int sb_row = (mi_row - tile_info->mi_row_start) >> mib_size_log2;//行位置
#if CONFIG_COLLECT_COMPONENT_TIMING
start_timing(cpi, encode_sb_time);
#endif
// Initialize the left context for the new SB row
av1_zero_left_context(xd);
// Reset delta for every tile,初始化qp
if (mi_row == tile_info->mi_row_start || cpi->row_mt) {
if (cm->delta_q_info.delta_q_present_flag)
xd->current_qindex = cm->base_qindex;
if (cm->delta_q_info.delta_lf_present_flag) {
av1_reset_loop_filter_delta(xd, av1_num_planes(cm));
}
}
reset_thresh_freq_fact(x);//Ymode
// Code each SB in the row
for (int mi_col = tile_info->mi_col_start, sb_col_in_tile = 0;
mi_col < tile_info->mi_col_end; mi_col += mib_size, sb_col_in_tile++) {
(*(cpi->row_mt_sync_read_ptr))(&tile_data->row_mt_sync, sb_row,
sb_col_in_tile);
if (tile_data->allow_update_cdf && (cpi->row_mt == 1) &&
(tile_info->mi_row_start != mi_row)) {
if ((tile_info->mi_col_start == mi_col)) {
// restore frame context of 1st column sb
memcpy(xd->tile_ctx, x->row_ctx, sizeof(*xd->tile_ctx));
} else {
int wt_left = AVG_CDF_WEIGHT_LEFT;
int wt_tr = AVG_CDF_WEIGHT_TOP_RIGHT;
if (tile_info->mi_col_end > (mi_col + mib_size))
avg_cdf_symbols(xd->tile_ctx, x->row_ctx + sb_col_in_tile, wt_left,
wt_tr);
else
avg_cdf_symbols(xd->tile_ctx, x->row_ctx + sb_col_in_tile - 1,
wt_left, wt_tr);
}
}
switch (cpi->oxcf.coeff_cost_upd_freq) {
case COST_UPD_TILE: // Tile level
if (mi_row != tile_info->mi_row_start) break;
AOM_FALLTHROUGH_INTENDED;
case COST_UPD_SBROW: // SB row level in tile
if (mi_col != tile_info->mi_col_start) break;
AOM_FALLTHROUGH_INTENDED;
case COST_UPD_SB: // SB level//系数填充
av1_fill_coeff_costs(&td->mb, xd->tile_ctx, num_planes);
break;
default: assert(0);
}
switch (cpi->oxcf.mode_cost_upd_freq) {//
case COST_UPD_TILE: // Tile level
if (mi_row != tile_info->mi_row_start) break;
AOM_FALLTHROUGH_INTENDED;
case COST_UPD_SBROW: // SB row level in tile
if (mi_col != tile_info->mi_col_start) break;
AOM_FALLTHROUGH_INTENDED;
case COST_UPD_SB: // SB level模式填充
av1_fill_mode_rates(cm, x, xd->tile_ctx);
break;
default: assert(0);
}
switch (cpi->oxcf.mv_cost_upd_freq) {
case COST_UPD_TILE: // Tile level
if (mi_row != tile_info->mi_row_start) break;
AOM_FALLTHROUGH_INTENDED;
case COST_UPD_SBROW: // SB row level in tile
if (mi_col != tile_info->mi_col_start) break;
AOM_FALLTHROUGH_INTENDED;
case COST_UPD_SB: // SB level运动填充
av1_fill_mv_costs(xd->tile_ctx, cm, x);
break;
default: assert(0);
}
x->mb_rd_record.num = x->mb_rd_record.index_start = 0;
if (!use_nonrd_mode) {
av1_zero(x->txb_rd_record_8X8);
av1_zero(x->txb_rd_record_16X16);
av1_zero(x->txb_rd_record_32X32);
av1_zero(x->txb_rd_record_64X64);
av1_zero(x->txb_rd_record_intra);
av1_zero(x->picked_ref_frames_mask);
av1_zero(x->pred_mv);
}
PC_TREE *const pc_root = td->pc_root[mib_size_log2 - MIN_MIB_SIZE_LOG2];
pc_root->index = 0;
//初始化运动向量
if ((sf->simple_motion_search_split ||
sf->simple_motion_search_prune_rect ||
sf->simple_motion_search_early_term_none) &&
!frame_is_intra_only(cm) && !use_nonrd_mode) {
init_simple_motion_search_mvs(pc_root);
}
#if !CONFIG_REALTIME_ONLY
td->mb.cnn_output_valid = 0;
#endif
xd->cur_frame_force_integer_mv = cm->cur_frame_force_integer_mv;//获取运动矢量(整数)
x->sb_energy_level = 0;
if (cm->delta_q_info.delta_q_present_flag)
setup_delta_q(cpi, td, x, tile_info, mi_row, mi_col, num_planes);//qp
td->mb.cb_coef_buff = av1_get_cb_coeff_buffer(cpi, mi_row, mi_col);
const int idx_str = cm->mi_stride * mi_row + mi_col;
MB_MODE_INFO **mi = cm->mi_grid_base + idx_str;
x->source_variance = UINT_MAX;
x->simple_motion_pred_sse = UINT_MAX;
const struct segmentation *const seg = &cm->seg;
int seg_skip = 0;
if (seg->enabled) {//划分
const uint8_t *const map =
seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map;
const int segment_id =
map ? get_segment_id(cm, map, sb_size, mi_row, mi_col) : 0;
seg_skip = segfeature_active(seg, segment_id, SEG_LVL_SKIP);
}
// Realtime non-rd path.
if (!(sf->partition_search_type == FIXED_PARTITION || seg_skip) &&
!cpi->partition_search_skippable_frame &&
sf->partition_search_type == VAR_BASED_PARTITION && use_nonrd_mode) {
set_offsets_without_segment_id(cpi, tile_info, x, mi_row, mi_col,
sb_size);
av1_choose_var_based_partitioning(cpi, tile_info, x, mi_row, mi_col);
td->mb.cb_offset = 0;
nonrd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, sb_size,
pc_root);
} else {
#if !CONFIG_REALTIME_ONLY
int dummy_rate;
int64_t dummy_dist;
RD_STATS dummy_rdc;
av1_invalid_rd_stats(&dummy_rdc);
adjust_rdmult_tpl_model(cpi, x, mi_row, mi_col);
if (sf->partition_search_type == FIXED_PARTITION || seg_skip) {//根据划分模式遍历划分
set_offsets(cpi, tile_info, x, mi_row, mi_col, sb_size);
const BLOCK_SIZE bsize =
seg_skip ? sb_size : sf->always_this_block_size;
set_fixed_partitioning(cpi, tile_info, mi, mi_row, mi_col, bsize);
//遍历所有划分和模式
rd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, sb_size,
&dummy_rate, &dummy_dist, 1, pc_root);
} else if (cpi->partition_search_skippable_frame) {
set_offsets(cpi, tile_info, x, mi_row, mi_col, sb_size);
const BLOCK_SIZE bsize =
get_rd_var_based_fixed_partition(cpi, x, mi_row, mi_col);
set_fixed_partitioning(cpi, tile_info, mi, mi_row, mi_col, bsize);
rd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, sb_size,
&dummy_rate, &dummy_dist, 1, pc_root);
} else {
reset_partition(pc_root, sb_size);
#if CONFIG_COLLECT_COMPONENT_TIMING
start_timing(cpi, rd_pick_partition_time);
#endif
BLOCK_SIZE max_sq_size = BLOCK_128X128;
switch (cpi->oxcf.max_partition_size) {//确定最大划分
case 4: max_sq_size = BLOCK_4X4; break;
case 8: max_sq_size = BLOCK_8X8; break;
case 16: max_sq_size = BLOCK_16X16; break;
case 32: max_sq_size = BLOCK_32X32; break;
case 64: max_sq_size = BLOCK_64X64; break;
case 128: max_sq_size = BLOCK_128X128; break;
default: assert(0); break;
}
max_sq_size = AOMMIN(max_sq_size, sb_size);
BLOCK_SIZE min_sq_size = BLOCK_4X4;
switch (cpi->oxcf.min_partition_size) {//确定最小划分
case 4: min_sq_size = BLOCK_4X4; break;
case 8: min_sq_size = BLOCK_8X8; break;
case 16: min_sq_size = BLOCK_16X16; break;
case 32: min_sq_size = BLOCK_32X32; break;
case 64: min_sq_size = BLOCK_64X64; break;
case 128: min_sq_size = BLOCK_128X128; break;
default: assert(0); break;
}
if (use_auto_max_partition(cpi, sb_size, mi_row, mi_col)) {//自动划分
float features[FEATURE_SIZE_MAX_MIN_PART_PRED] = { 0.0f };
av1_get_max_min_partition_features(cpi, x, mi_row, mi_col, features);
max_sq_size =
AOMMIN(av1_predict_max_partition(cpi, x, features), max_sq_size);
}
min_sq_size = AOMMIN(min_sq_size, max_sq_size);
//划分完下一层入口
rd_pick_partition(cpi, td, tile_data, tp, mi_row, mi_col, sb_size,
max_sq_size, min_sq_size, &dummy_rdc, dummy_rdc,
pc_root, NULL);
#if CONFIG_COLLECT_COMPONENT_TIMING
end_timing(cpi, rd_pick_partition_time);
#endif
}
#endif // !CONFIG_REALTIME_ONLY
}
// TODO(angiebird): Let inter_mode_rd_model_estimation support multi-tile.
if (cpi->sf.inter_mode_rd_model_estimation == 1 && cm->tile_cols == 1 &&
cm->tile_rows == 1) {
av1_inter_mode_data_fit(tile_data, x->rdmult);
}
if (tile_data->allow_update_cdf && (cpi->row_mt == 1) &&
(tile_info->mi_row_end > (mi_row + mib_size))) {
if (sb_cols_in_tile == 1)
memcpy(x->row_ctx, xd->tile_ctx, sizeof(*xd->tile_ctx));
else if (sb_col_in_tile >= 1)
memcpy(x->row_ctx + sb_col_in_tile - 1, xd->tile_ctx,
sizeof(*xd->tile_ctx));
}
(*(cpi->row_mt_sync_write_ptr))(&tile_data->row_mt_sync, sb_row,
sb_col_in_tile, sb_cols_in_tile);
}
#if CONFIG_COLLECT_COMPONENT_TIMING
end_timing(cpi, encode_sb_time);
#endif
}
网友评论