Allintra: Allocate 'mv_costs' conditionally
The structure 'mv_costs' is a member of the MACROBLOCK structure
and the same is allocated conditionally by avoiding the allocation
for allintra encoding mode.
For AVIF image encode with speed = 6,
HEAP Memory reduction(%)
Resolution threads=1 threads=4
640x360 3.37 8.08
768x512 2.20 5.53
832x480 2.24 6.21
1280x720 1.17 3.71
HEAP memory reduction was measured using the following command.
$valgrind --tool=massif ./avifenc ...
Change-Id: Ibd9a9ff9d67886ed644233eb280d1c0d549fb717
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 62ea28d..a78c7f9 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -1134,7 +1134,10 @@
// Set cost update frequency configuration.
oxcf->cost_upd_freq.coeff = (COST_UPDATE_TYPE)extra_cfg->coeff_cost_upd_freq;
oxcf->cost_upd_freq.mode = (COST_UPDATE_TYPE)extra_cfg->mode_cost_upd_freq;
- oxcf->cost_upd_freq.mv = (COST_UPDATE_TYPE)extra_cfg->mv_cost_upd_freq;
+ // Avoid MV cost update for allintra encoding mode.
+ oxcf->cost_upd_freq.mv = (cfg->kf_max_dist != 0)
+ ? (COST_UPDATE_TYPE)extra_cfg->mv_cost_upd_freq
+ : COST_UPD_OFF;
oxcf->cost_upd_freq.dv = (COST_UPDATE_TYPE)extra_cfg->dv_cost_upd_freq;
// Set frame resize mode configuration.
diff --git a/av1/encoder/encoder_alloc.h b/av1/encoder/encoder_alloc.h
index 01719c5..3030ea7 100644
--- a/av1/encoder/encoder_alloc.h
+++ b/av1/encoder/encoder_alloc.h
@@ -77,8 +77,11 @@
aom_free(cpi->td.mb.mv_costs);
cpi->td.mb.mv_costs = NULL;
}
- CHECK_MEM_ERROR(cm, cpi->td.mb.mv_costs,
- (MvCosts *)aom_calloc(1, sizeof(MvCosts)));
+ // Avoid the memory allocation of 'mv_costs' for allintra encoding mode.
+ if (cpi->oxcf.kf_cfg.key_freq_max != 0) {
+ CHECK_MEM_ERROR(cm, cpi->td.mb.mv_costs,
+ (MvCosts *)aom_calloc(1, sizeof(MvCosts)));
+ }
if (cpi->td.mb.dv_costs) {
aom_free(cpi->td.mb.dv_costs);
diff --git a/av1/encoder/mcomp.c b/av1/encoder/mcomp.c
index 1a53c23..ef7cb1f 100644
--- a/av1/encoder/mcomp.c
+++ b/av1/encoder/mcomp.c
@@ -41,9 +41,14 @@
mv_cost_params->mv_cost_type = MV_COST_ENTROPY;
mv_cost_params->error_per_bit = errorperbit;
mv_cost_params->sad_per_bit = sadperbit;
- mv_cost_params->mvjcost = mv_costs->nmv_joint_cost;
- mv_cost_params->mvcost[0] = mv_costs->mv_cost_stack[0];
- mv_cost_params->mvcost[1] = mv_costs->mv_cost_stack[1];
+ // For allintra encoding mode, 'mv_costs' is not allocated. Hence, the
+ // population of mvjcost and mvcost are avoided. In case of IntraBC, these
+ // values are populated from 'dv_costs' in av1_set_ms_to_intra_mode().
+ if (mv_costs != NULL) {
+ mv_cost_params->mvjcost = mv_costs->nmv_joint_cost;
+ mv_cost_params->mvcost[0] = mv_costs->mv_cost_stack[0];
+ mv_cost_params->mvcost[1] = mv_costs->mv_cost_stack[1];
+ }
}
static INLINE void init_ms_buffers(MSBuffers *ms_buffers, const MACROBLOCK *x) {
diff --git a/av1/encoder/mv_prec.h b/av1/encoder/mv_prec.h
index 11dcdd8..55108b6 100644
--- a/av1/encoder/mv_prec.h
+++ b/av1/encoder/mv_prec.h
@@ -33,6 +33,9 @@
AV1_COMP *cpi, int allow_high_precision_mv,
int cur_frame_force_integer_mv) {
MvCosts *const mv_costs = cpi->td.mb.mv_costs;
+ // Avoid accessing 'mv_costs' when it is not allocated.
+ if (mv_costs == NULL) return;
+
const int copy_hp = cpi->common.features.allow_high_precision_mv =
allow_high_precision_mv && !cur_frame_force_integer_mv;
diff --git a/av1/encoder/rd.c b/av1/encoder/rd.c
index d88f563..8d28f43 100644
--- a/av1/encoder/rd.c
+++ b/av1/encoder/rd.c
@@ -620,6 +620,9 @@
void av1_fill_mv_costs(const nmv_context *nmvc, int integer_mv, int usehp,
MvCosts *mv_costs) {
+ // Avoid accessing 'mv_costs' when it is not allocated.
+ if (mv_costs == NULL) return;
+
mv_costs->nmv_cost[0] = &mv_costs->nmv_cost_alloc[0][MV_MAX];
mv_costs->nmv_cost[1] = &mv_costs->nmv_cost_alloc[1][MV_MAX];
mv_costs->nmv_cost_hp[0] = &mv_costs->nmv_cost_hp_alloc[0][MV_MAX];