ref: 022590427c22d4a78593f2a115df0abca5a2769f
parent: 3c4bfc6f2ce8af5817f56d80764c274354334d44
author: Zoe Liu <zoeliu@google.com>
date: Tue Jun 19 08:08:55 EDT 2018
Add hierarchical structure in GF group Change-Id: I06fc4b0ad5a45c49e10a9601a2356fbc6e93d6da
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -746,6 +746,14 @@
uint8_t *count_arf_frame_usage;
uint8_t *count_lastgolden_frame_usage;
+ // Parameters on multi-layer ALTREFs
+ int num_extra_arfs;
+ int arf_pos_in_gf[MAX_EXT_ARFS + 1];
+ int arf_pos_for_ovrly[MAX_EXT_ARFS + 1];
+
+ int extra_arf_allowed;
+ int bwd_ref_allowed;
+
vpx_roi_map_t roi;
} VP9_COMP;
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -2120,6 +2120,220 @@
return score_total;
}
+static void define_gf_multi_arf_structure(VP9_COMP *cpi) {
+ RATE_CONTROL *const rc = &cpi->rc;
+ TWO_PASS *const twopass = &cpi->twopass;
+ GF_GROUP *const gf_group = &twopass->gf_group;
+ int i;
+ int frame_index = 0;
+ const int key_frame = cpi->common.frame_type == KEY_FRAME;
+
+ // The use of bi-predictive frames are only enabled when following 3
+ // conditions are met:
+ // (1) ALTREF is enabled;
+ // (2) The bi-predictive group interval is at least 2; and
+ // (3) The bi-predictive group interval is strictly smaller than the
+ // golden group interval.
+ const int is_bipred_enabled =
+ cpi->bwd_ref_allowed && rc->source_alt_ref_pending &&
+ rc->bipred_group_interval &&
+ rc->bipred_group_interval <=
+ (rc->baseline_gf_interval - rc->source_alt_ref_pending);
+ int bipred_group_end = 0;
+ int bipred_frame_index = 0;
+
+ const unsigned char ext_arf_interval =
+ (unsigned char)(rc->baseline_gf_interval / (cpi->num_extra_arfs + 1) - 1);
+ int which_arf = cpi->num_extra_arfs;
+ int subgroup_interval[MAX_EXT_ARFS + 1];
+ int is_sg_bipred_enabled = is_bipred_enabled;
+ int accumulative_subgroup_interval = 0;
+
+ // For key frames the frame target rate is already set and it
+ // is also the golden frame.
+ // === [frame_index == 0] ===
+ if (!key_frame) {
+ if (rc->source_alt_ref_active) {
+ gf_group->update_type[frame_index] = OVERLAY_UPDATE;
+ gf_group->rf_level[frame_index] = INTER_NORMAL;
+ } else {
+ gf_group->update_type[frame_index] = GF_UPDATE;
+ gf_group->rf_level[frame_index] = GF_ARF_STD;
+ }
+ gf_group->arf_update_idx[frame_index] = 0;
+ gf_group->arf_ref_idx[frame_index] = 0;
+ }
+
+ gf_group->bidir_pred_enabled[frame_index] = 0;
+ gf_group->brf_src_offset[frame_index] = 0;
+
+ frame_index++;
+
+ bipred_frame_index++;
+
+ // === [frame_index == 1] ===
+ if (rc->source_alt_ref_pending) {
+ gf_group->update_type[frame_index] = ARF_UPDATE;
+ gf_group->rf_level[frame_index] = GF_ARF_STD;
+ gf_group->arf_src_offset[frame_index] =
+ (unsigned char)(rc->baseline_gf_interval - 1);
+
+ gf_group->arf_update_idx[frame_index] = 0;
+ gf_group->arf_ref_idx[frame_index] = 0;
+
+ gf_group->bidir_pred_enabled[frame_index] = 0;
+ gf_group->brf_src_offset[frame_index] = 0;
+ // NOTE: "bidir_pred_frame_index" stays unchanged for ARF_UPDATE frames.
+
+ // Work out the ARFs' positions in this gf group
+ // NOTE: ALT_REFs' are indexed inversely, but coded in display order
+ // (except for the original ARF). In the example of three ALT_REF's,
+ // We index ALTREF's as: KEY ----- ALT2 ----- ALT1 ----- ALT0
+ // but code them in the following order:
+ // KEY-ALT0-ALT2 ----- OVERLAY2-ALT1 ----- OVERLAY1 ----- OVERLAY0
+ //
+ // arf_pos_for_ovrly[]: Position for OVERLAY
+ // arf_pos_in_gf[]: Position for ALTREF
+ cpi->arf_pos_for_ovrly[0] = frame_index + cpi->num_extra_arfs +
+ gf_group->arf_src_offset[frame_index] + 1;
+ for (i = 0; i < cpi->num_extra_arfs; ++i) {
+ cpi->arf_pos_for_ovrly[i + 1] =
+ frame_index + (cpi->num_extra_arfs - i) * (ext_arf_interval + 2);
+ subgroup_interval[i] = cpi->arf_pos_for_ovrly[i] -
+ cpi->arf_pos_for_ovrly[i + 1] - (i == 0 ? 1 : 2);
+ }
+ subgroup_interval[cpi->num_extra_arfs] =
+ cpi->arf_pos_for_ovrly[cpi->num_extra_arfs] - frame_index -
+ (cpi->num_extra_arfs == 0 ? 1 : 2);
+
+ ++frame_index;
+
+ // Insert an extra ARF
+ // === [frame_index == 2] ===
+ if (cpi->num_extra_arfs) {
+ gf_group->update_type[frame_index] = INTNL_ARF_UPDATE;
+ gf_group->rf_level[frame_index] = GF_ARF_LOW;
+ gf_group->arf_src_offset[frame_index] = ext_arf_interval;
+
+ gf_group->arf_update_idx[frame_index] = which_arf;
+ gf_group->arf_ref_idx[frame_index] = 0;
+ ++frame_index;
+ }
+ accumulative_subgroup_interval += subgroup_interval[cpi->num_extra_arfs];
+ }
+
+ for (i = 0; i < rc->baseline_gf_interval - rc->source_alt_ref_pending; ++i) {
+ gf_group->arf_update_idx[frame_index] = which_arf;
+ gf_group->arf_ref_idx[frame_index] = which_arf;
+
+ // If we are going to have ARFs, check whether we can have BWDREF in this
+ // subgroup, and further, whether we can have ARF subgroup which contains
+ // the BWDREF subgroup but contained within the GF group:
+ //
+ // GF group --> ARF subgroup --> BWDREF subgroup
+ if (rc->source_alt_ref_pending) {
+ is_sg_bipred_enabled =
+ is_bipred_enabled &&
+ (subgroup_interval[which_arf] > rc->bipred_group_interval);
+ }
+
+ // NOTE: 1. BIDIR_PRED is only enabled when the length of the bi-predictive
+ // frame group interval is strictly smaller than that of the GOLDEN
+ // FRAME group interval.
+ // 2. Currently BIDIR_PRED is only enabled when alt-ref is on.
+ if (is_sg_bipred_enabled && !bipred_group_end) {
+ const int cur_brf_src_offset = rc->bipred_group_interval - 1;
+
+ if (bipred_frame_index == 1) {
+ // --- BRF_UPDATE ---
+ gf_group->update_type[frame_index] = BRF_UPDATE;
+ gf_group->rf_level[frame_index] = GF_ARF_LOW;
+ gf_group->brf_src_offset[frame_index] = cur_brf_src_offset;
+ } else if (bipred_frame_index == rc->bipred_group_interval) {
+ // --- LAST_BIPRED_UPDATE ---
+ gf_group->update_type[frame_index] = LAST_BIPRED_UPDATE;
+ gf_group->rf_level[frame_index] = INTER_NORMAL;
+ gf_group->brf_src_offset[frame_index] = 0;
+
+ // Reset the bi-predictive frame index.
+ bipred_frame_index = 0;
+ } else {
+ // --- BIPRED_UPDATE ---
+ gf_group->update_type[frame_index] = BIPRED_UPDATE;
+ gf_group->rf_level[frame_index] = INTER_NORMAL;
+ gf_group->brf_src_offset[frame_index] = 0;
+ }
+ gf_group->bidir_pred_enabled[frame_index] = 1;
+
+ bipred_frame_index++;
+ // Check whether the next bi-predictive frame group would entirely be
+ // included within the current golden frame group.
+ // In addition, we need to avoid coding a BRF right before an ARF.
+ if (bipred_frame_index == 1 &&
+ (i + 2 + cur_brf_src_offset) >= accumulative_subgroup_interval) {
+ bipred_group_end = 1;
+ }
+ } else {
+ gf_group->update_type[frame_index] = LF_UPDATE;
+ gf_group->rf_level[frame_index] = INTER_NORMAL;
+ gf_group->bidir_pred_enabled[frame_index] = 0;
+ gf_group->brf_src_offset[frame_index] = 0;
+ }
+
+ ++frame_index;
+
+ // Check if we need to update the ARF.
+ if (is_sg_bipred_enabled && cpi->num_extra_arfs && which_arf > 0 &&
+ frame_index > cpi->arf_pos_for_ovrly[which_arf]) {
+ --which_arf;
+ accumulative_subgroup_interval += subgroup_interval[which_arf] + 1;
+
+ // Meet the new subgroup; Reset the bipred_group_end flag.
+ bipred_group_end = 0;
+ // Insert another extra ARF after the overlay frame
+ if (which_arf) {
+ gf_group->update_type[frame_index] = INTNL_ARF_UPDATE;
+ gf_group->rf_level[frame_index] = GF_ARF_LOW;
+ gf_group->arf_src_offset[frame_index] = ext_arf_interval;
+
+ gf_group->arf_update_idx[frame_index] = which_arf;
+ gf_group->arf_ref_idx[frame_index] = 0;
+ ++frame_index;
+ }
+ }
+ }
+
+ // NOTE: We need to configure the frame at the end of the sequence + 1 that
+ // is the start frame for the next group. Otherwise prior to the call to
+ // av1_rc_get_second_pass_params() the data will be undefined.
+ gf_group->arf_update_idx[frame_index] = 0;
+ gf_group->arf_ref_idx[frame_index] = 0;
+
+ if (rc->source_alt_ref_pending) {
+ gf_group->update_type[frame_index] = OVERLAY_UPDATE;
+ gf_group->rf_level[frame_index] = INTER_NORMAL;
+
+ cpi->arf_pos_in_gf[0] = 1;
+ if (cpi->num_extra_arfs) {
+ // Overwrite the update_type for extra-ARF's corresponding internal
+ // OVERLAY's: Change from LF_UPDATE to INTNL_OVERLAY_UPDATE.
+ for (i = cpi->num_extra_arfs; i > 0; --i) {
+ cpi->arf_pos_in_gf[i] =
+ (i == cpi->num_extra_arfs ? 2 : cpi->arf_pos_for_ovrly[i + 1] + 1);
+
+ gf_group->update_type[cpi->arf_pos_for_ovrly[i]] = INTNL_OVERLAY_UPDATE;
+ gf_group->rf_level[cpi->arf_pos_for_ovrly[i]] = INTER_NORMAL;
+ }
+ }
+ } else {
+ gf_group->update_type[frame_index] = GF_UPDATE;
+ gf_group->rf_level[frame_index] = GF_ARF_STD;
+ }
+
+ gf_group->bidir_pred_enabled[frame_index] = 0;
+ gf_group->brf_src_offset[frame_index] = 0;
+}
+
static void define_gf_group_structure(VP9_COMP *cpi) {
RATE_CONTROL *const rc = &cpi->rc;
TWO_PASS *const twopass = &cpi->twopass;
@@ -2248,7 +2462,17 @@
double this_frame_score = 1.0;
// Define the GF structure and specify
- define_gf_group_structure(cpi);
+ cpi->bwd_ref_allowed = 0;
+ cpi->extra_arf_allowed = 0;
+
+ cpi->num_extra_arfs = 0;
+ cpi->num_extra_arfs = cpi->extra_arf_allowed ? cpi->num_extra_arfs : 0;
+
+ if (cpi->bwd_ref_allowed) {
+ define_gf_multi_arf_structure(cpi);
+ } else {
+ define_gf_group_structure(cpi);
+ }
key_frame = cpi->common.frame_type == KEY_FRAME;
--- a/vp9/encoder/vp9_firstpass.h
+++ b/vp9/encoder/vp9_firstpass.h
@@ -41,6 +41,8 @@
#define INVALID_ROW -1
+#define MAX_EXT_ARFS 2
+
typedef struct {
double frame_mb_intra_factor;
double frame_mb_brightness_factor;
@@ -130,6 +132,8 @@
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];
+ unsigned char brf_src_offset[(MAX_LAG_BUFFERS * 2) + 1];
+ unsigned char bidir_pred_enabled[(MAX_LAG_BUFFERS * 2) + 1];
int bit_allocation[(MAX_LAG_BUFFERS * 2) + 1];
} GF_GROUP;
--- a/vp9/encoder/vp9_ratectrl.h
+++ b/vp9/encoder/vp9_ratectrl.h
@@ -106,6 +106,9 @@
int source_alt_ref_active;
int is_src_frame_alt_ref;
+ // Length of the bi-predictive frame group interval
+ int bipred_group_interval;
+
int avg_frame_bandwidth; // Average frame size target for clip
int min_frame_bandwidth; // Minimum allocation used for any frame
int max_frame_bandwidth; // Maximum burst rate allowed for a frame.