Dual ARF changes: Buffer index selection.
Add indirection to the section of buffer indices.
This is to help simplify things in the future if we
have other codec features that switch indices.
Limit the max GF interval for static sections to fit
the gf_group structures.
Change-Id: I38310daaf23fd906004c0e8ee3e99e15570f84cb
diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c
index ed52999..c69ed16 100644
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -904,8 +904,7 @@
(cpi->refresh_golden_frame << cpi->alt_fb_idx);
} else {
int arf_idx = cpi->alt_fb_idx;
-
- if ((cpi->pass == 2) && cpi->multi_arf_enabled) {
+ if (cpi->pass == 2) {
const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
arf_idx = gf_group->arf_update_idx[gf_group->index];
}
diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c
index e917a47..ca3946c 100644
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -1514,7 +1514,7 @@
} else { /* For non key/golden frames */
if (cpi->refresh_alt_ref_frame) {
int arf_idx = cpi->alt_fb_idx;
- if ((cpi->pass == 2) && cpi->multi_arf_enabled) {
+ if (cpi->pass == 2) {
const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
arf_idx = gf_group->arf_update_idx[gf_group->index];
}
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index f2e89b8..6fb263f 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -1282,6 +1282,18 @@
return MAX((int)(((int64_t)boost * total_group_bits) / allocation_chunks), 0);
}
+// Current limit on maximum number of active arfs in a GF/ARF group.
+#define MAX_ACTIVE_ARFS 2
+#define ARF_SLOT1 2
+#define ARF_SLOT2 3
+// This function indirects the choice of buffers for arfs.
+// At the moment the values are fixed but this may change as part of
+// the integration process with other codec features that swap buffers around.
+static void get_arf_buffer_indices(unsigned char *arf_buffer_indices) {
+ arf_buffer_indices[0] = ARF_SLOT1;
+ arf_buffer_indices[1] = ARF_SLOT2;
+}
+
static void allocate_gf_group_bits(VP9_COMP *cpi, int64_t gf_group_bits,
double group_error, int gf_arf_bits) {
RATE_CONTROL *const rc = &cpi->rc;
@@ -1298,10 +1310,13 @@
double err_fraction;
int mid_boost_bits = 0;
int middle_frame_idx;
+ unsigned char arf_buffer_indices[MAX_ACTIVE_ARFS];
key_frame = cpi->common.frame_type == KEY_FRAME ||
vp9_is_upper_layer_key_frame(cpi);
+ get_arf_buffer_indices(arf_buffer_indices);
+
// For key frames the frame target rate is already set and it
// is also the golden frame.
if (!key_frame) {
@@ -1309,14 +1324,14 @@
twopass->gf_group.update_type[0] = OVERLAY_UPDATE;
twopass->gf_group.rf_level[0] = INTER_NORMAL;
twopass->gf_group.bit_allocation[0] = 0;
- twopass->gf_group.arf_update_idx[0] = 2;
- twopass->gf_group.arf_ref_idx[0] = 2;
+ twopass->gf_group.arf_update_idx[0] = arf_buffer_indices[0];
+ twopass->gf_group.arf_ref_idx[0] = arf_buffer_indices[0];
} else {
twopass->gf_group.update_type[0] = GF_UPDATE;
twopass->gf_group.rf_level[0] = GF_ARF_STD;
twopass->gf_group.bit_allocation[0] = gf_arf_bits;
- twopass->gf_group.arf_update_idx[0] = 2;
- twopass->gf_group.arf_ref_idx[0] = 2;
+ twopass->gf_group.arf_update_idx[0] = arf_buffer_indices[0];
+ twopass->gf_group.arf_ref_idx[0] = arf_buffer_indices[0];
}
// Step over the golden frame / overlay frame
@@ -1331,18 +1346,20 @@
// Store the bits to spend on the ARF if there is one.
if (rc->source_alt_ref_pending) {
- // A portion of the gf / arf extra bits are set asside for lower level
- // boosted frames in the middle of the group.
- mid_boost_bits = gf_arf_bits >> 5;
- gf_arf_bits -= (gf_arf_bits >> 5);
+ if (cpi->multi_arf_enabled) {
+ // A portion of the gf / arf extra bits are set asside for lower level
+ // boosted frames in the middle of the group.
+ mid_boost_bits += gf_arf_bits >> 5;
+ gf_arf_bits -= (gf_arf_bits >> 5);
+ }
twopass->gf_group.update_type[frame_index] = ARF_UPDATE;
twopass->gf_group.rf_level[frame_index] = GF_ARF_STD;
twopass->gf_group.bit_allocation[frame_index] = gf_arf_bits;
twopass->gf_group.arf_src_offset[frame_index] =
(unsigned char)(rc->baseline_gf_interval - 1);
- twopass->gf_group.arf_update_idx[frame_index] = 2;
- twopass->gf_group.arf_ref_idx[frame_index] = 2;
+ twopass->gf_group.arf_update_idx[frame_index] = arf_buffer_indices[0];
+ twopass->gf_group.arf_ref_idx[frame_index] = arf_buffer_indices[0];
++frame_index;
if (cpi->multi_arf_enabled) {
@@ -1351,8 +1368,8 @@
twopass->gf_group.rf_level[frame_index] = GF_ARF_LOW;
twopass->gf_group.arf_src_offset[frame_index] =
(unsigned char)((rc->baseline_gf_interval >> 1) - 1);
- twopass->gf_group.arf_update_idx[frame_index] = 3;
- twopass->gf_group.arf_ref_idx[frame_index] = 2;
+ twopass->gf_group.arf_update_idx[frame_index] = arf_buffer_indices[1];
+ twopass->gf_group.arf_ref_idx[frame_index] = arf_buffer_indices[0];
++frame_index;
}
}
@@ -1362,6 +1379,7 @@
// Allocate bits to the other frames in the group.
for (i = 0; i < rc->baseline_gf_interval - 1; ++i) {
+ int arf_idx = 0;
if (EOF == input_stats(twopass, &frame_stats))
break;
@@ -1378,17 +1396,11 @@
mid_boost_bits += (target_frame_size >> 4);
target_frame_size -= (target_frame_size >> 4);
- if (frame_index <= middle_frame_idx) {
- twopass->gf_group.arf_update_idx[frame_index] = 3;
- twopass->gf_group.arf_ref_idx[frame_index] = 3;
- } else {
- twopass->gf_group.arf_update_idx[frame_index] = 2;
- twopass->gf_group.arf_ref_idx[frame_index] = 2;
- }
- } else {
- twopass->gf_group.arf_update_idx[frame_index] = 2;
- twopass->gf_group.arf_ref_idx[frame_index] = 2;
+ if (frame_index <= middle_frame_idx)
+ arf_idx = 1;
}
+ twopass->gf_group.arf_update_idx[frame_index] = arf_buffer_indices[arf_idx];
+ twopass->gf_group.arf_ref_idx[frame_index] = arf_buffer_indices[arf_idx];
target_frame_size = clamp(target_frame_size, 0,
MIN(max_bits, (int)total_group_bits));
@@ -1400,23 +1412,27 @@
++frame_index;
}
+ // Note:
+ // We need to configure the frame at the end of the sequence + 1 that will be
+ // the start frame for the next group. Otherwise prior to the call to
+ // vp9_rc_get_second_pass_params() the data will be undefined.
+ twopass->gf_group.arf_update_idx[frame_index] = arf_buffer_indices[0];
+ twopass->gf_group.arf_ref_idx[frame_index] = arf_buffer_indices[0];
+
if (rc->source_alt_ref_pending) {
+ twopass->gf_group.update_type[frame_index] = OVERLAY_UPDATE;
+ twopass->gf_group.rf_level[frame_index] = INTER_NORMAL;
+
+ // Final setup for second arf and its overlay.
if (cpi->multi_arf_enabled) {
twopass->gf_group.bit_allocation[2] =
twopass->gf_group.bit_allocation[middle_frame_idx] + mid_boost_bits;
twopass->gf_group.update_type[middle_frame_idx] = OVERLAY_UPDATE;
twopass->gf_group.bit_allocation[middle_frame_idx] = 0;
}
-
- // Configure the overlay frame at the end of the sequence that will also
- // be the start frame of the next group. The reason for doing this here
- // is that on entry to vp9_get_compressed_data() for the overlay
- // frame, but before the call to vp9_rc_get_second_pass_params() the
- // data will otherwise be undefined.
- twopass->gf_group.update_type[frame_index] = OVERLAY_UPDATE;
- twopass->gf_group.rf_level[frame_index] = INTER_NORMAL;
- twopass->gf_group.arf_update_idx[frame_index] = 2;
- twopass->gf_group.arf_ref_idx[frame_index] = 2;
+ } else {
+ twopass->gf_group.update_type[frame_index] = GF_UPDATE;
+ twopass->gf_group.rf_level[frame_index] = GF_ARF_STD;
}
}
diff --git a/vp9/encoder/vp9_firstpass.h b/vp9/encoder/vp9_firstpass.h
index 61268ff..1ee56a3 100644
--- a/vp9/encoder/vp9_firstpass.h
+++ b/vp9/encoder/vp9_firstpass.h
@@ -51,12 +51,12 @@
typedef struct {
unsigned char index;
- RATE_FACTOR_LEVEL rf_level[MAX_LAG_BUFFERS * 2];
- FRAME_UPDATE_TYPE update_type[MAX_LAG_BUFFERS * 2];
- unsigned char arf_src_offset[MAX_LAG_BUFFERS * 2];
- unsigned char arf_update_idx[MAX_LAG_BUFFERS * 2];
- unsigned char arf_ref_idx[MAX_LAG_BUFFERS * 2];
- int bit_allocation[MAX_LAG_BUFFERS * 2];
+ RATE_FACTOR_LEVEL rf_level[(MAX_LAG_BUFFERS * 2) + 1];
+ FRAME_UPDATE_TYPE update_type[(MAX_LAG_BUFFERS * 2) + 1];
+ unsigned char arf_src_offset[(MAX_LAG_BUFFERS * 2) + 1];
+ unsigned char arf_update_idx[(MAX_LAG_BUFFERS * 2) + 1];
+ unsigned char arf_ref_idx[(MAX_LAG_BUFFERS * 2) + 1];
+ int bit_allocation[(MAX_LAG_BUFFERS * 2) + 1];
} GF_GROUP;
typedef struct {
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index c39d90b..e110983 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -1356,6 +1356,8 @@
// Extended interval for genuinely static scenes
rc->static_scene_max_gf_interval = oxcf->key_freq >> 1;
+ if (rc->static_scene_max_gf_interval > (MAX_LAG_BUFFERS * 2))
+ rc->static_scene_max_gf_interval = MAX_LAG_BUFFERS * 2;
if (is_altref_enabled(oxcf)) {
if (rc->static_scene_max_gf_interval > oxcf->lag_in_frames - 1)