rtc: Refactor to allow avg_frame_low_motion when aq-mode=0
avg_frame_low_motion, which is used in various places in rtc
code patch, was only updated when aq_mode=3, even though it can
be used when aq_mode=0. This change makes the update/compuation
of avg_frame_low_motion for rtc encoding, regardless of aq_mode.
No change in stats when aq_mode=3.
Change-Id: I67adc5108b0875f3f699abafd9948b28d118d14e
diff --git a/av1/encoder/aq_cyclicrefresh.c b/av1/encoder/aq_cyclicrefresh.c
index 79f5b97..bbab748 100644
--- a/av1/encoder/aq_cyclicrefresh.c
+++ b/av1/encoder/aq_cyclicrefresh.c
@@ -266,7 +266,6 @@
void av1_init_cyclic_refresh_counters(MACROBLOCK *const x) {
x->actual_num_seg1_blocks = 0;
x->actual_num_seg2_blocks = 0;
- x->cnt_zeromv = 0;
}
// Accumulate cyclic refresh counters.
@@ -274,39 +273,6 @@
CYCLIC_REFRESH *const cyclic_refresh, const MACROBLOCK *const x) {
cyclic_refresh->actual_num_seg1_blocks += x->actual_num_seg1_blocks;
cyclic_refresh->actual_num_seg2_blocks += x->actual_num_seg2_blocks;
- cyclic_refresh->cnt_zeromv += x->cnt_zeromv;
-}
-
-void av1_cyclic_refresh_postencode(AV1_COMP *const cpi) {
- AV1_COMMON *const cm = &cpi->common;
- const CommonModeInfoParams *const mi_params = &cm->mi_params;
- CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
- RATE_CONTROL *const rc = &cpi->rc;
- SVC *const svc = &cpi->svc;
- const int avg_cnt_zeromv =
- 100 * cr->cnt_zeromv / (mi_params->mi_rows * mi_params->mi_cols);
-
- if (!cpi->ppi->use_svc ||
- (cpi->ppi->use_svc &&
- !cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame &&
- cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1)) {
- rc->avg_frame_low_motion =
- (rc->avg_frame_low_motion == 0)
- ? avg_cnt_zeromv
- : (3 * rc->avg_frame_low_motion + avg_cnt_zeromv) / 4;
- // For SVC: set avg_frame_low_motion (only computed on top spatial layer)
- // to all lower spatial layers.
- if (cpi->ppi->use_svc &&
- svc->spatial_layer_id == svc->number_spatial_layers - 1) {
- for (int i = 0; i < svc->number_spatial_layers - 1; ++i) {
- const int layer = LAYER_IDS_TO_IDX(i, svc->temporal_layer_id,
- svc->number_temporal_layers);
- LAYER_CONTEXT *const lc = &svc->layer_context[layer];
- RATE_CONTROL *const lrc = &lc->rc;
- lrc->avg_frame_low_motion = rc->avg_frame_low_motion;
- }
- }
- }
}
void av1_cyclic_refresh_set_golden_update(AV1_COMP *const cpi) {
diff --git a/av1/encoder/aq_cyclicrefresh.h b/av1/encoder/aq_cyclicrefresh.h
index 79ed5f9..ecb5d6d 100644
--- a/av1/encoder/aq_cyclicrefresh.h
+++ b/av1/encoder/aq_cyclicrefresh.h
@@ -72,10 +72,6 @@
*/
int rdmult;
/*!
- * Count of zero motion vectors
- */
- int cnt_zeromv;
- /*!
* Cyclic refresh map.
*/
int8_t *map;
@@ -249,21 +245,6 @@
void av1_accumulate_cyclic_refresh_counters(
CYCLIC_REFRESH *const cyclic_refresh, const MACROBLOCK *const x);
-/*!\brief Update stats after encoding frame.
- *
- * Update the number of block encoded with segment 1 and 2,
- * and update the number of blocks encoded with small/zero motion.
- *
- * \ingroup cyclic_refresh
- * \callgraph
- * \callergraph
- *
- * \param[in] cpi Top level encoder structure
- *
- * \return Updates the \c cpi->cyclic_refresh with the new stats.
- */
-void av1_cyclic_refresh_postencode(struct AV1_COMP *const cpi);
-
/*!\brief Set golden frame update interval nased on cyclic refresh.
*
* \ingroup cyclic_refresh
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index d7ac132..8ca0d3f 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -147,6 +147,17 @@
};
/*!\endcond */
+void av1_init_rtc_counters(MACROBLOCK *const x) {
+ av1_init_cyclic_refresh_counters(x);
+ x->cnt_zeromv = 0;
+}
+
+void av1_accumulate_rtc_counters(AV1_COMP *cpi, const MACROBLOCK *const x) {
+ if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ)
+ av1_accumulate_cyclic_refresh_counters(cpi->cyclic_refresh, x);
+ cpi->rc.cnt_zeromv += x->cnt_zeromv;
+}
+
unsigned int av1_get_perpixel_variance(const AV1_COMP *cpi,
const MACROBLOCKD *xd,
const struct buf_2d *ref,
@@ -1162,15 +1173,10 @@
cpi->td.rd_counts.seg_tmp_pred_cost[1] = 0;
cpi->td.mb.e_mbd.tile_ctx = &this_tile->tctx;
cpi->td.mb.tile_pb_ctx = &this_tile->tctx;
- // Reset cyclic refresh counters.
- av1_init_cyclic_refresh_counters(&cpi->td.mb);
-
+ av1_init_rtc_counters(&cpi->td.mb);
av1_encode_tile(cpi, &cpi->td, tile_row, tile_col);
- // Accumulate cyclic refresh params.
- if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ &&
- !frame_is_intra_only(&cpi->common))
- av1_accumulate_cyclic_refresh_counters(cpi->cyclic_refresh,
- &cpi->td.mb);
+ if (!frame_is_intra_only(&cpi->common))
+ av1_accumulate_rtc_counters(cpi, &cpi->td.mb);
cpi->intrabc_used |= cpi->td.intrabc_used;
cpi->deltaq_used |= cpi->td.deltaq_used;
}
@@ -1569,7 +1575,7 @@
} else {
cpi->cyclic_refresh->actual_num_seg1_blocks = 0;
cpi->cyclic_refresh->actual_num_seg2_blocks = 0;
- cpi->cyclic_refresh->cnt_zeromv = 0;
+ cpi->rc.cnt_zeromv = 0;
}
av1_frame_init_quantizer(cpi);
diff --git a/av1/encoder/encodeframe.h b/av1/encoder/encodeframe.h
index 36b38d5..ce32fb4 100644
--- a/av1/encoder/encodeframe.h
+++ b/av1/encoder/encodeframe.h
@@ -31,6 +31,11 @@
struct AV1_COMP;
struct ThreadData;
+void av1_init_rtc_counters(struct macroblock *const x);
+
+void av1_accumulate_rtc_counters(struct AV1_COMP *cpi,
+ const struct macroblock *const x);
+
void av1_setup_src_planes(struct macroblock *x,
const struct yv12_buffer_config *src, int mi_row,
int mi_col, const int num_planes, BLOCK_SIZE bsize);
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index b050bb4..4dafcbe 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -2264,6 +2264,36 @@
cdef_restoration_frame(cpi, cm, xd, use_restoration, use_cdef);
}
+static void update_motion_stat(AV1_COMP *const cpi) {
+ AV1_COMMON *const cm = &cpi->common;
+ const CommonModeInfoParams *const mi_params = &cm->mi_params;
+ RATE_CONTROL *const rc = &cpi->rc;
+ SVC *const svc = &cpi->svc;
+ const int avg_cnt_zeromv =
+ 100 * cpi->rc.cnt_zeromv / (mi_params->mi_rows * mi_params->mi_cols);
+ if (!cpi->ppi->use_svc ||
+ (cpi->ppi->use_svc &&
+ !cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame &&
+ cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1)) {
+ rc->avg_frame_low_motion =
+ (rc->avg_frame_low_motion == 0)
+ ? avg_cnt_zeromv
+ : (3 * rc->avg_frame_low_motion + avg_cnt_zeromv) / 4;
+ // For SVC: set avg_frame_low_motion (only computed on top spatial layer)
+ // to all lower spatial layers.
+ if (cpi->ppi->use_svc &&
+ svc->spatial_layer_id == svc->number_spatial_layers - 1) {
+ for (int i = 0; i < svc->number_spatial_layers - 1; ++i) {
+ const int layer = LAYER_IDS_TO_IDX(i, svc->temporal_layer_id,
+ svc->number_temporal_layers);
+ LAYER_CONTEXT *const lc = &svc->layer_context[layer];
+ RATE_CONTROL *const lrc = &lc->rc;
+ lrc->avg_frame_low_motion = rc->avg_frame_low_motion;
+ }
+ }
+ }
+}
+
/*!\brief Encode a frame without the recode loop, usually used in one-pass
* encoding and realtime coding.
*
@@ -2483,10 +2513,8 @@
// transform / motion compensation build reconstruction frame
av1_encode_frame(cpi);
- // Update some stats from cyclic refresh.
- if (q_cfg->aq_mode == CYCLIC_REFRESH_AQ && !cpi->rc.rtc_external_ratectrl &&
- !frame_is_intra_only(cm))
- av1_cyclic_refresh_postencode(cpi);
+ if (!cpi->rc.rtc_external_ratectrl && !frame_is_intra_only(cm))
+ update_motion_stat(cpi);
// Adjust the refresh of the golden (longer-term) reference based on QP
// selected for this frame. This is for CBR with 1 layer/non-svc RTC mode.
diff --git a/av1/encoder/ethread.c b/av1/encoder/ethread.c
index 45f7e17..bc34d36 100644
--- a/av1/encoder/ethread.c
+++ b/av1/encoder/ethread.c
@@ -1195,11 +1195,9 @@
EncWorkerData *const thread_data = (EncWorkerData *)worker->data1;
cpi->intrabc_used |= thread_data->td->intrabc_used;
cpi->deltaq_used |= thread_data->td->deltaq_used;
- // Accumulate cyclic refresh params.
- if (cpi->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ &&
- !frame_is_intra_only(&cpi->common))
- av1_accumulate_cyclic_refresh_counters(cpi->cyclic_refresh,
- &thread_data->td->mb);
+ // Accumulate rtc counters.
+ if (!frame_is_intra_only(&cpi->common))
+ av1_accumulate_rtc_counters(cpi, &thread_data->td->mb);
if (thread_data->td != &cpi->td) {
// Keep these conditional expressions in sync with the corresponding ones
// in prepare_enc_workers().
@@ -1294,8 +1292,8 @@
}
av1_alloc_mb_data(cpi, &thread_data->td->mb);
- // Reset cyclic refresh counters.
- av1_init_cyclic_refresh_counters(&thread_data->td->mb);
+ // Reset rtc counters.
+ av1_init_rtc_counters(&thread_data->td->mb);
if (thread_data->td->counts != &cpi->counts) {
memcpy(thread_data->td->counts, &cpi->counts, sizeof(cpi->counts));
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index aef5bc5..486fda3 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -235,6 +235,7 @@
/*!\cond */
// Track amount of low motion in scene
int avg_frame_low_motion;
+ int cnt_zeromv;
// signals if number of blocks with motion is high
int high_num_blocks_with_motion;