1,函数功能
函数从名称上来看就可以得到是要抑制噪声再进行编码,顺序一般为先进行噪声估算,根据噪声估算的结果得到一个noise_level,根据这个noise_level和其他的属性(编码次数,帧类型,帧用途等)进行av1_temporal_filter时空域的滤波,然后进入av1_encode进行下一步编码
2,代码学习
// Apply temporal filtering to key frames and encode the filtered frame.
// If the current frame is not key frame, this function is identical to
// av1_encode().
/*第三层编码
*该函数会实施降噪操作
*通过函数av1_estimate_noise_from_single_plane()使用soble梯度算子评估噪声程度。
*若噪声程度、帧类型(要求为KEY_FRAME)和其他一些条件成立,则会对该帧进行时域滤波。
*时域滤波通过av1_temporal_filter()完成。
*此后调用函数av1_encode()进行编码。
*/
static int denoise_and_encode(AV1_COMP *const cpi, uint8_t *const dest,
EncodeFrameInput *const frame_input,
EncodeFrameParams *const frame_params,
EncodeFrameResults *const frame_results,
int *temporal_filtered) {
//判读是否关键帧,是关键帧的话就直接av1_encode
if (frame_params->frame_type != KEY_FRAME) {
cpi->pack_bitstream = 1;
if (av1_encode(cpi, dest, frame_input, frame_params, frame_results) !=
AOM_CODEC_OK) {
return AOM_CODEC_ERROR;
}
return AOM_CODEC_OK;
}
//如果不是关键帧
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
AV1_COMMON *const cm = &cpi->common;
double noise_level;
const int use_hbd = frame_input->source->flags & YV12_FLAG_HIGHBITDEPTH;
//高低bit不同估算噪声水平
if (use_hbd) {
noise_level = highbd_estimate_noise(
frame_input->source->y_buffer, frame_input->source->y_crop_width,
frame_input->source->y_crop_height, frame_input->source->y_stride,
cm->seq_params.bit_depth, EDGE_THRESHOLD);
} else {
noise_level = estimate_noise(frame_input->source->y_buffer,
frame_input->source->y_crop_width,
frame_input->source->y_crop_height,
frame_input->source->y_stride, EDGE_THRESHOLD);
}
const int apply_filtering =
oxcf->pass == 2 && frame_params->frame_type == KEY_FRAME &&
cpi->rc.frames_to_key > NUM_KEY_FRAME_DENOISING && noise_level > 0 &&
!is_lossless_requested(oxcf) && oxcf->arnr_max_frames > 0;
// Apply filtering to key frame and encode.
// 对关键帧进行过滤并且编码
if (apply_filtering) {
// Initialization for frame motion estimation.
//帧运动估计的初始化。
MACROBLOCKD *const xd = &cpi->td.mb.e_mbd;
av1_init_context_buffers(cm);
setup_mi(cpi, frame_input->source);
av1_init_macroblockd(cm, xd, NULL);
memset(cpi->mbmi_ext_base, 0,
cm->mi_rows * cm->mi_cols * sizeof(*cpi->mbmi_ext_base));
av1_set_speed_features_framesize_independent(cpi, oxcf->speed);
av1_set_speed_features_framesize_dependent(cpi, oxcf->speed);
av1_set_rd_speed_thresholds(cpi);
av1_setup_frame_buf_refs(cm);
av1_setup_frame_sign_bias(cm);
av1_frame_init_quantizer(cpi);
av1_setup_past_independence(cm);
//保存一个原始图像的buffer
const int num_planes = av1_num_planes(cm);
aom_yv12_copy_frame(frame_input->source, &cpi->source_kf_buffer,
num_planes);
av1_temporal_filter(cpi, -1);
aom_extend_frame_borders(&cpi->alt_ref_buffer, num_planes);
// Use the filtered frame for encoding.
frame_input->source = &cpi->alt_ref_buffer;
*temporal_filtered = 1;
cpi->pack_bitstream = 1;
if (av1_encode(cpi, dest, frame_input, frame_params, frame_results) !=
AOM_CODEC_OK) {
return AOM_CODEC_ERROR;
}
// Set frame_input source to true source for psnr calculation.
//保留一份原来的buffer用于计算psnr
if (oxcf->arnr_max_frames > 0 && *temporal_filtered) {
aom_yv12_copy_frame(&cpi->source_kf_buffer, cpi->source, num_planes);
aom_yv12_copy_frame(&cpi->source_kf_buffer, cpi->unscaled_source,
num_planes);
}
} else {
// Encode other frames.
cpi->pack_bitstream = 1;
if (av1_encode(cpi, dest, frame_input, frame_params, frame_results) !=
AOM_CODEC_OK) {
return AOM_CODEC_ERROR;
}
}
return AOM_CODEC_OK;
}
#endif // !CONFIG_REALTIME_ONLY
网友评论