One-pass encoding of key frame with temporal filtering.
Now we only encode the temporal filtered key frame once.
Avoid the slowdown introduced in this CL:
https://aomedia-review.googlesource.com/c/aom/+/90081
Performance:
150 frams, VBR, spd1:
avg_psnr ovr_psnr ssim
lowres -0.088 -0.146 -0.125
midres 0.162 0.029 0.305
STATS_CHANGED
Change-Id: I7f71fb707f187d49c9cf65c72019082c234bd6f8
diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c
index 09df541..e050f29 100644
--- a/av1/encoder/encode_strategy.c
+++ b/av1/encoder/encode_strategy.c
@@ -24,9 +24,11 @@
#endif // CONFIG_MISMATCH_DEBUG
#include "av1/common/onyxc_int.h"
+#include "av1/common/reconinter.h"
#include "av1/encoder/encoder.h"
#include "av1/encoder/encode_strategy.h"
+#include "av1/encoder/encodeframe.h"
#include "av1/encoder/firstpass.h"
#include "av1/encoder/pass2_strategy.h"
#include "av1/encoder/temporal_filter.h"
@@ -1199,6 +1201,22 @@
}
#if !CONFIG_REALTIME_ONLY
+void setup_mi(AV1_COMP *const cpi, YV12_BUFFER_CONFIG *src) {
+ AV1_COMMON *const cm = &cpi->common;
+ const int num_planes = av1_num_planes(cm);
+ MACROBLOCK *const x = &cpi->td.mb;
+ MACROBLOCKD *const xd = &x->e_mbd;
+
+ av1_setup_src_planes(x, src, 0, 0, num_planes, cm->seq_params.sb_size);
+
+ av1_setup_block_planes(xd, cm->seq_params.subsampling_x,
+ cm->seq_params.subsampling_y, num_planes);
+
+ xd->mi = cm->mi_grid_base;
+ xd->mi[0] = cm->mi;
+ x->mbmi_ext = cpi->mbmi_ext_base;
+}
+
// 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().
@@ -1238,25 +1256,31 @@
// Apply filtering to key frame and encode.
if (apply_filtering) {
- const int num_planes = av1_num_planes(cm);
+ // 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);
+
// Keep a copy of the source image.
+ const int num_planes = av1_num_planes(cm);
aom_yv12_copy_frame(frame_input->source, &cpi->source_kf_buffer,
num_planes);
- // TODO(chengchen): Encode the key frame, this is a workaround to get
- // internal data structures properly initialized, for example, mi, x, xd.
- // Do not pack bitstream in this case.
- cpi->pack_bitstream = 0;
- if (av1_encode(cpi, dest, frame_input, frame_params, frame_results) !=
- AOM_CODEC_OK) {
- return AOM_CODEC_ERROR;
- }
- // Produce the filtered key frame.
av1_temporal_filter(cpi, -1);
aom_extend_frame_borders(&cpi->alt_ref_buffer, num_planes);
- *temporal_filtered = 1;
- // Set frame_input source to temporal filtered key frame.
+ // Use the filtered frame for encoding.
frame_input->source = &cpi->alt_ref_buffer;
- // Encode the filtered key frame. Pack bitstream.
+ *temporal_filtered = 1;
cpi->pack_bitstream = 1;
if (av1_encode(cpi, dest, frame_input, frame_params, frame_results) !=
AOM_CODEC_OK) {