Update the target frame size boost for VBR mode
Results:
30-frames 60-frames
lowres -0.371 -0.284
midres -0.419 -0.406
STATS_CHANGED
Change-Id: Ia1592cc6ac77d968dcaab30db9374dfbc4aa9f7b
diff --git a/av1/encoder/firstpass.c b/av1/encoder/firstpass.c
index 80d3afc..98bd04e 100644
--- a/av1/encoder/firstpass.c
+++ b/av1/encoder/firstpass.c
@@ -1585,6 +1585,12 @@
gf_group->arf_src_offset[i], gf_group->arf_pos_in_gf[i],
gf_group->arf_update_idx[i], gf_group->pyramid_level[i]);
}
+
+ fprintf(fid, "number of nodes in each level: \n");
+ for (int i = 0; i < MAX_PYRAMID_LVL; ++i) {
+ fprintf(fid, "lvl %d: %d ", i, gf_group->pyramid_lvl_nodes[i]);
+ }
+ fprintf(fid, "\n");
fclose(fid);
}
#endif // CHCEK_GF_PARAMETER
@@ -1612,7 +1618,8 @@
gf_group->arf_src_offset[*frame_ind] = 0;
gf_group->arf_pos_in_gf[*frame_ind] = 0;
gf_group->arf_update_idx[*frame_ind] = arf_ind;
- gf_group->pyramid_level[*frame_ind] = level;
+ gf_group->pyramid_level[*frame_ind] = 0;
+ ++gf_group->pyramid_lvl_nodes[0];
++(*frame_ind);
}
} else {
@@ -1624,6 +1631,7 @@
gf_group->arf_pos_in_gf[*frame_ind] = 0;
gf_group->arf_update_idx[*frame_ind] = 1; // mark all internal ARF 1
gf_group->pyramid_level[*frame_ind] = level;
+ ++gf_group->pyramid_lvl_nodes[level];
++(*frame_ind);
// set parameters for frames displayed before this frame
@@ -1655,6 +1663,12 @@
int frame_index = 0;
gf_group->pyramid_height = get_pyramid_height(gf_interval);
+ assert(gf_group->pyramid_height <= MAX_PYRAMID_LVL);
+
+ for (int lvl = 0; lvl < MAX_PYRAMID_LVL; ++lvl) {
+ gf_group->pyramid_lvl_nodes[lvl] = 0;
+ }
+
// At the beginning of each GF group it will be a key or overlay frame,
gf_group->update_type[frame_index] = OVERLAY_UPDATE;
gf_group->arf_src_offset[frame_index] = 0;
@@ -2113,6 +2127,18 @@
gf_group->brf_src_offset[frame_index] = 0;
}
+#if USE_SYMM_MULTI_LAYER
+#define LEAF_REDUCTION_FACTOR 0.75f
+#define LVL_3_BOOST_FACTOR 0.8f
+#define LVL_2_BOOST_FACTOR 0.3f
+
+static float_t lvl_budget_factor[MAX_PYRAMID_LVL - 1][MAX_PYRAMID_LVL - 1] = {
+ { 1, 0, 0 },
+ { LVL_3_BOOST_FACTOR, 0, 0 }, // Leaking budget works better
+ { LVL_3_BOOST_FACTOR, (1 - LVL_3_BOOST_FACTOR) * LVL_2_BOOST_FACTOR,
+ (1 - LVL_3_BOOST_FACTOR) * (1 - LVL_2_BOOST_FACTOR) }
+};
+#endif // USE_SYMM_MULTI_LAYER
static void allocate_gf_group_bits(AV1_COMP *cpi, int64_t gf_group_bits,
double group_error, int gf_arf_bits) {
RATE_CONTROL *const rc = &cpi->rc;
@@ -2201,15 +2227,25 @@
#if USE_SYMM_MULTI_LAYER
} else if (cpi->new_bwdref_update_rule &&
gf_group->update_type[frame_index] == INTNL_OVERLAY_UPDATE) {
+ assert(gf_group->pyramid_height <= MAX_PYRAMID_LVL &&
+ gf_group->pyramid_height >= 0 &&
+ "non-valid height for a pyramid structure");
+
int arf_pos = gf_group->arf_pos_in_gf[frame_index];
gf_group->bit_allocation[frame_index] = 0;
gf_group->bit_allocation[arf_pos] = target_frame_size;
#if MULTI_LVL_BOOST_VBR_CQ
- if (gf_group->pyramid_level[arf_pos] == (gf_group->pyramid_height - 1))
- gf_group->bit_allocation[arf_pos] += target_frame_size;
- else
- gf_group->bit_allocation[arf_pos] += (target_frame_size >> 1);
+ const int pyr_h = gf_group->pyramid_height - 2;
+ const int this_lvl = gf_group->pyramid_level[arf_pos];
+ const int dist2top = gf_group->pyramid_height - 1 - this_lvl;
+
+ const float_t budget =
+ LEAF_REDUCTION_FACTOR * gf_group->pyramid_lvl_nodes[0];
+ const float_t lvl_boost = budget * lvl_budget_factor[pyr_h][dist2top] /
+ gf_group->pyramid_lvl_nodes[this_lvl];
+
+ gf_group->bit_allocation[arf_pos] += (int)(target_frame_size * lvl_boost);
#endif // MULTI_LVL_BOOST_VBR_CQ
#endif // USE_SYMM_MULTI_LAYER
} else {
@@ -2217,9 +2253,12 @@
gf_group->update_type[frame_index] == INTNL_OVERLAY_UPDATE);
gf_group->bit_allocation[frame_index] = target_frame_size;
#if MULTI_LVL_BOOST_VBR_CQ
- if (cpi->new_bwdref_update_rule)
- gf_group->bit_allocation[frame_index] -= (target_frame_size >> 1);
-#endif
+ if (cpi->new_bwdref_update_rule) {
+ float_t reduced_factor = LEAF_REDUCTION_FACTOR;
+ gf_group->bit_allocation[frame_index] -=
+ (int)(target_frame_size * reduced_factor);
+ }
+#endif // MULTI_LVL_BOOST_VBR_CQ
}
++frame_index;
diff --git a/av1/encoder/firstpass.h b/av1/encoder/firstpass.h
index a953f9e..4b7325a 100644
--- a/av1/encoder/firstpass.h
+++ b/av1/encoder/firstpass.h
@@ -118,6 +118,7 @@
unsigned char arf_pos_in_gf[(MAX_LAG_BUFFERS * 2) + 1];
unsigned char pyramid_level[(MAX_LAG_BUFFERS * 2) + 1];
unsigned char pyramid_height;
+ unsigned char pyramid_lvl_nodes[MAX_PYRAMID_LVL];
#endif
unsigned char brf_src_offset[(MAX_LAG_BUFFERS * 2) + 1];
unsigned char bidir_pred_enabled[(MAX_LAG_BUFFERS * 2) + 1];
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index 1da5862..d5c46a4 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -28,6 +28,7 @@
#if CONFIG_FIX_GF_LENGTH
#define FIXED_GF_LENGTH 16
+#define MAX_PYRAMID_LVL 4
#define USE_SYMM_MULTI_LAYER 1
#define REDUCE_LAST_ALT_BOOST 1
#define REDUCE_LAST_GF_LENGTH 1