1,函数功能
该函数主要置量化相关的参数和分块信息后进行编码,编码之后会根据打包的码流大小判断是否谁需要重新编码(loop)。
2,代码学习
static int encode_with_recode_loop(AV1_COMP *cpi, size_t *size, uint8_t *dest) {
AV1_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc;
const int allow_recode = (cpi->sf.recode_loop != DISALLOW_RECODE);
set_size_independent_vars(cpi);
cpi->source->buf_8bit_valid = 0;
av1_setup_frame_size(cpi);
int top_index = 0, bottom_index = 0;
int q = 0, q_low = 0, q_high = 0;
set_size_dependent_vars(cpi, &q, &bottom_index, &top_index);
q_low = bottom_index;
q_high = top_index;
// Loop variables
int loop_count = 0;
int loop_at_this_size = 0;
int loop = 0;
int overshoot_seen = 0;
int undershoot_seen = 0;
int low_cr_seen = 0;
#if CONFIG_COLLECT_COMPONENT_TIMING
printf("\n Encoding a frame:");
#endif
do {//loop为1的话
loop = 0;
aom_clear_system_state();
// if frame was scaled calculate global_motion_search again if already
// done
//帧的缩放做过了的话再次进行全局运动搜索(即全局运动搜索的标志位置0)
if (loop_count > 0 && cpi->source && cpi->global_motion_search_done) {
if (cpi->source->y_crop_width != cm->width ||
cpi->source->y_crop_height != cm->height) {
cpi->global_motion_search_done = 0;
}
}
//帧缩放
cpi->source =
av1_scale_if_required(cm, cpi->unscaled_source, &cpi->scaled_source);
//前一帧缩放
if (cpi->unscaled_last_source != NULL) {
cpi->last_source = av1_scale_if_required(cm, cpi->unscaled_last_source,
&cpi->scaled_last_source);
}
//关键帧或者只能帧内编码的时候
if (!frame_is_intra_only(cm)) {
if (loop_count > 0) {
release_scaled_references(cpi);//释放帧间参考帧列表
}
scale_references(cpi);//量化参考帧列表
}
av1_set_quantizer(cm, q);
av1_init_quantizer(cpi);
av1_set_variance_partition_thresholds(cpi, q, 0);
//printf("Frame %d/%d: q = %d, frame_type = %d superres_denom = %d\n",
// cm->current_frame.frame_number, cm->show_frame, q,
// cm->current_frame.frame_type, cm->superres_scale_denominator);
if (loop_count == 0) {
setup_frame(cpi);
} else if (get_primary_ref_frame_buf(cm) == NULL) {
// Base q-index may have changed, so we need to assign proper default coef
// probs before every iteration.
av1_default_coef_probs(cm);
av1_setup_frame_contexts(cm);
}
//根据量化建立索引?
if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
av1_vaq_frame_setup(cpi);
} else if (cpi->oxcf.aq_mode == COMPLEXITY_AQ) {
av1_setup_in_frame_q_adj(cpi);
} else if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && !allow_recode) {
suppress_active_map(cpi);
av1_cyclic_refresh_setup(cpi);
apply_active_map(cpi);
}
if (cm->seg.enabled) {//如果分块的话
if (!cm->seg.update_data && cm->prev_frame) {//前一帧存在并且划分未更新
segfeatures_copy(&cm->seg, &cm->prev_frame->seg);//复制前一帧的划分给cm-seg
} else {
av1_calculate_segdata(&cm->seg);//前一帧不存在则计算当前的&cm->seg
}
} else {//不进行划分则直接申请cm->seg的空间
memset(&cm->seg, 0, sizeof(cm->seg));
}
segfeatures_copy(&cm->cur_frame->seg, &cm->seg);//将cm->seg赋予当前帧的划分
if (allow_recode) save_coding_context(cpi);
#if CONFIG_COLLECT_COMPONENT_TIMING
start_timing(cpi, av1_encode_frame_time);
#endif
// transform / motion compensation build reconstruction frame
av1_encode_frame(cpi);//编码
#if CONFIG_COLLECT_COMPONENT_TIMING
end_timing(cpi, av1_encode_frame_time);
#endif
aom_clear_system_state();
// Dummy pack of the bitstream using up to date stats to get an
// accurate estimate of output frame size to determine if we need
// to recode.,根据已经编码好的码流大小判断是否进行重新编码
if (cpi->sf.recode_loop >= ALLOW_RECODE_KFARFGF) {
restore_coding_context(cpi);
finalize_encoded_frame(cpi);
int largest_tile_id = 0; // Output from bitstream: unused here
if (av1_pack_bitstream(cpi, dest, size, &largest_tile_id) != AOM_CODEC_OK)
return AOM_CODEC_ERROR;
rc->projected_frame_size = (int)(*size) << 3;
restore_coding_context(cpi);
}
//重新编码
if (allow_recode) {
// Update q and decide whether to do a recode loop
recode_loop_update_q(cpi, &loop, &q, &q_low, &q_high, top_index,
bottom_index, &undershoot_seen, &overshoot_seen,
&low_cr_seen, loop_at_this_size);
}
// Special case for overlay frame.
if (rc->is_src_frame_alt_ref &&
rc->projected_frame_size < rc->max_frame_bandwidth)
loop = 0;
if (allow_recode && !cpi->sf.gm_disable_recode &&
recode_loop_test_global_motion(cpi)) {
loop = 1;
}
if (cpi->tpl_model_pass == 1) {
assert(cpi->oxcf.enable_tpl_model == 2);
av1_tpl_setup_forward_stats(cpi);
cpi->tpl_model_pass = 0;
loop = 1;
}
if (loop) {
++loop_count;
++loop_at_this_size;
#if CONFIG_INTERNAL_STATS
++cpi->tot_recode_hits;
#endif
}
#if CONFIG_COLLECT_COMPONENT_TIMING
if (loop) printf("\n Recoding:");
#endif
} while (loop);
return AOM_CODEC_OK;
}
网友评论