From 022590427c22d4a78593f2a115df0abca5a2769f Mon Sep 17 00:00:00 2001 From: Zoe Liu Date: Tue, 19 Jun 2018 12:08:55 -0700 Subject: [PATCH] Add hierarchical structure in GF group Change-Id: I06fc4b0ad5a45c49e10a9601a2356fbc6e93d6da --- vp9/encoder/vp9_encoder.h | 8 ++ vp9/encoder/vp9_firstpass.c | 226 +++++++++++++++++++++++++++++++++++- vp9/encoder/vp9_firstpass.h | 4 + vp9/encoder/vp9_ratectrl.h | 3 + 4 files changed, 240 insertions(+), 1 deletion(-) diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h index d6d32abf9..cfb77994c 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -746,6 +746,14 @@ typedef struct VP9_COMP { 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; diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 2ec7dc51f..c13576343 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -2120,6 +2120,220 @@ static double calculate_group_score(VP9_COMP *cpi, double av_score, 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 @@ static void allocate_gf_group_bits(VP9_COMP *cpi, int64_t gf_group_bits, 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; diff --git a/vp9/encoder/vp9_firstpass.h b/vp9/encoder/vp9_firstpass.h index c4bccfc85..958dc128d 100644 --- a/vp9/encoder/vp9_firstpass.h +++ b/vp9/encoder/vp9_firstpass.h @@ -41,6 +41,8 @@ typedef struct { #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 @@ typedef struct { 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; diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h index c1b210677..5f4e66fe3 100644 --- a/vp9/encoder/vp9_ratectrl.h +++ b/vp9/encoder/vp9_ratectrl.h @@ -106,6 +106,9 @@ typedef struct { 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. -- 2.49.0