Commit e9b15e2b authored by Zoe Liu's avatar Zoe Liu

Add encoder support to ALTREF2

This CL adds the use of ALTREF2_FRAME to both single / comp reference
prediction at the encoder side. In particular, the encoder keeps the
distant altref as ALTREF, and uses the internal extra altrefs to
refresh ALTREF2.

Compared with the baseline (ext_tx and global_motion disabled simply
for speed concern):
(a) lowres: avg_psnr -0.395% ovr_psnr -0.393% ssim -0.329%
(b) midres: avg_psnr -0.419% ovr_psnr -0.431% ssim -0.444%
(c) AWCY High Latency:
   PSNR | PSNR Cb | PSNR Cr | PSNR HVS |    SSIM | MS SSIM | CIEDE 2000
-0.6661 | -0.5988 | -0.6669 |  -0.6993 | -0.6988 | -0.7303 | -0.6051
(d) AWCY Low Latency:
  PSNR | PSNR Cb | PSNR Cr | PSNR HVS |   SSIM | MS SSIM | CIEDE 2000
0.0720 | -0.0505 |  0.1501 |   0.0670 | 0.0842 |  0.0517 |     0.0158

TODO list:
(1) To have altref2 incorporated with ext-comp-refs;
(2) To have altref2 fully work with new-multisymbol;
(3) To re-collect the initial default probs/cdfs;
(4) To tune the encoder gf group structure design for altref2.

Change-Id: I6ad63fd65afa903d3bba20acdb68e3b67acf7fdf
parent da4d8b9c
......@@ -1590,12 +1590,22 @@ static void read_ref_frames(AV1_COMMON *const cm, MACROBLOCKD *const xd,
const int ctx0 = av1_get_pred_context_single_ref_p1(xd);
#if CONFIG_VAR_REFS
int bit0;
#if CONFIG_ALTREF2
// Test need to explicitly code (L,L2,L3,G) vs (BWD,ALT2,ALT) branch node
// in tree
if ((L_OR_L2(cm) || L3_OR_G(cm)) &&
(BWD_OR_ALT2(cm) || ALTREF_IS_VALID(cm)))
bit0 = READ_REF_BIT(single_ref_p1);
else
bit0 = (BWD_OR_ALT2(cm) || ALTREF_IS_VALID(cm));
#else // !CONFIG_ALTREF2
// Test need to explicitly code (L,L2,L3,G) vs (BWD,ALT) branch node in
// tree
if ((L_OR_L2(cm) || L3_OR_G(cm)) && BWD_OR_ALT(cm))
bit0 = READ_REF_BIT(single_ref_p1);
else
bit0 = BWD_OR_ALT(cm);
#endif // CONFIG_ALTREF2
#else // !CONFIG_VAR_REFS
const int bit0 = READ_REF_BIT(single_ref_p1);
#endif // CONFIG_VAR_REFS
......@@ -1605,10 +1615,11 @@ static void read_ref_frames(AV1_COMMON *const cm, MACROBLOCKD *const xd,
const int ctx1 = av1_get_pred_context_single_ref_p2(xd);
#if CONFIG_VAR_REFS
int bit1;
// Test need to explicitly code (BWD/ALT2) vs (ALT) branch node in tree
#if CONFIG_ALTREF2
// Test need to explicitly code (BWD/ALT2) vs (ALT) branch node in tree
const int bit1_uncertain = BWD_OR_ALT2(cm) && ALTREF_IS_VALID(cm);
#else // !CONFIG_ALTREF2
// Test need to explicitly code (BWD) vs (ALT) branch node in tree
const int bit1_uncertain = BWD_AND_ALT(cm);
#endif // CONFIG_ALTREF2
if (bit1_uncertain)
......
......@@ -1153,6 +1153,29 @@ static void write_ref_frames(const AV1_COMMON *cm, const MACROBLOCKD *xd,
#endif // CONFIG_VAR_REFS
}
#if CONFIG_ALTREF2
#if CONFIG_VAR_REFS
// Test need to explicitly code (BWD,ALT2) vs (ALT) branch node in tree
if (BWD_OR_ALT2(cm) && ALTREF_IS_VALID(cm)) {
#endif // CONFIG_VAR_REFS
const int bit_bwd = mbmi->ref_frame[1] == ALTREF_FRAME;
WRITE_REF_BIT(bit_bwd, comp_bwdref_p);
if (!bit_bwd) {
#if CONFIG_VAR_REFS
// Test need to explicitly code (BWD,ALT2) vs (ALT) branch node in
// tree
if (BWD_AND_ALT2(cm))
#endif // CONFIG_VAR_REFS
WRITE_REF_BIT(mbmi->ref_frame[1] == ALTREF2_FRAME, comp_bwdref_p1);
}
#if CONFIG_VAR_REFS
}
#endif // CONFIG_VAR_REFS
#else // !CONFIG_ALTREF2
#if CONFIG_VAR_REFS
// Test need to explicitly code (BWD) vs (ALT) branch node in tree
if (BWD_AND_ALT(cm)) {
......@@ -1163,22 +1186,50 @@ static void write_ref_frames(const AV1_COMMON *cm, const MACROBLOCKD *xd,
}
#endif // CONFIG_VAR_REFS
#endif // CONFIG_ALTREF2
#else // !CONFIG_EXT_REFS
const int bit = mbmi->ref_frame[0] == GOLDEN_FRAME;
WRITE_REF_BIT(bit, comp_ref_p);
#endif // CONFIG_EXT_REFS
} else {
#if CONFIG_EXT_REFS
const int bit0 = (mbmi->ref_frame[0] == ALTREF_FRAME ||
mbmi->ref_frame[0] == BWDREF_FRAME);
const int bit0 = (mbmi->ref_frame[0] <= ALTREF_FRAME &&
mbmi->ref_frame[0] >= BWDREF_FRAME);
#if CONFIG_VAR_REFS
#if CONFIG_ALTREF2
// Test need to explicitly code (L,L2,L3,G) vs (BWD,ALT2,ALT) branch node
// in tree
if ((L_OR_L2(cm) || L3_OR_G(cm)) &&
(BWD_OR_ALT2(cm) || ALTREF_IS_VALID(cm)))
#else // !CONFIG_ALTREF2
// Test need to explicitly code (L,L2,L3,G) vs (BWD,ALT) branch node in
// tree
if ((L_OR_L2(cm) || L3_OR_G(cm)) && BWD_OR_ALT(cm))
#endif // CONFIG_ALTREF2
#endif // CONFIG_VAR_REFS
WRITE_REF_BIT(bit0, single_ref_p1);
if (bit0) {
#if CONFIG_ALTREF2
#if CONFIG_VAR_REFS
// Test need to explicitly code (BWD,ALT2) vs (ALT) branch node in tree
if (BWD_OR_ALT2(cm) && ALTREF_IS_VALID(cm)) {
#endif // CONFIG_VAR_REFS
const int bit1 = mbmi->ref_frame[0] == ALTREF_FRAME;
WRITE_REF_BIT(bit1, single_ref_p2);
if (!bit1) {
#if CONFIG_VAR_REFS
// Test need to explicitly code (BWD) vs (ALT2) branch node in tree
if (BWD_AND_ALT2(cm))
#endif // CONFIG_VAR_REFS
WRITE_REF_BIT(mbmi->ref_frame[0] == ALTREF2_FRAME, single_ref_p6);
}
#if CONFIG_VAR_REFS
}
#endif // CONFIG_VAR_REFS
#else // !CONFIG_ALTREF2
#if CONFIG_VAR_REFS
// Test need to explicitly code (BWD) vs (ALT) branch node in tree
if (BWD_AND_ALT(cm)) {
......@@ -1188,6 +1239,7 @@ static void write_ref_frames(const AV1_COMMON *cm, const MACROBLOCKD *xd,
#if CONFIG_VAR_REFS
}
#endif // CONFIG_VAR_REFS
#endif // CONFIG_ALTREF2
} else {
const int bit2 = (mbmi->ref_frame[0] == LAST3_FRAME ||
mbmi->ref_frame[0] == GOLDEN_FRAME);
......@@ -3638,13 +3690,19 @@ static int get_refresh_mask(AV1_COMP *cpi) {
// LAST3_FRAME.
refresh_mask |=
(cpi->refresh_last_frame << cpi->lst_fb_idxes[LAST_REF_FRAMES - 1]);
#if CONFIG_ALTREF2
refresh_mask |= (cpi->refresh_bwd_ref_frame << cpi->bwd_fb_idx);
refresh_mask |= (cpi->refresh_alt2_ref_frame << cpi->alt2_fb_idx);
#else // !CONFIG_ALTREF2
if (cpi->rc.is_bwd_ref_frame && cpi->num_extra_arfs) {
// We have swapped the virtual indices
refresh_mask |= (cpi->refresh_bwd_ref_frame << cpi->arf_map[0]);
} else {
refresh_mask |= (cpi->refresh_bwd_ref_frame << cpi->bwd_fb_idx);
}
#else
#endif // CONFIG_ALTREF2
#else // !CONFIG_EXT_REFS
refresh_mask |= (cpi->refresh_last_frame << cpi->lst_fb_idx);
#endif // CONFIG_EXT_REFS
......@@ -3662,9 +3720,13 @@ static int get_refresh_mask(AV1_COMP *cpi) {
return refresh_mask | (cpi->refresh_golden_frame << cpi->alt_fb_idx);
} else {
#if CONFIG_EXT_REFS
#if CONFIG_ALTREF2
const int arf_idx = cpi->alt_fb_idx;
#else // !CONFIG_ALTREF2
const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
int arf_idx = cpi->arf_map[gf_group->arf_update_idx[gf_group->index]];
#else
const int arf_idx = cpi->arf_map[gf_group->arf_update_idx[gf_group->index]];
#endif // CONFIG_ALTREF2
#else // !CONFIG_EXT_REFS
int arf_idx = cpi->alt_fb_idx;
if ((cpi->oxcf.pass == 2) && cpi->multi_arf_allowed) {
const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
......
......@@ -1491,6 +1491,9 @@ static void rd_pick_sb_modes(const AV1_COMP *const cpi, TileDataEnc *tile_data,
if ((rd_cost->rate != INT_MAX) && (aq_mode == COMPLEXITY_AQ) &&
(bsize >= BLOCK_16X16) &&
(cm->frame_type == KEY_FRAME || cpi->refresh_alt_ref_frame ||
#if CONFIG_EXT_REFS && CONFIG_ALTREF2
cpi->refresh_alt2_ref_frame ||
#endif // CONFIG_EXT_REFS && CONFIG_ALTREF2
(cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref))) {
av1_caq_select_segment(cpi, x, bsize, mi_row, mi_col, rd_cost->rate);
}
......@@ -1664,6 +1667,11 @@ static void update_stats(const AV1_COMMON *const cm, ThreadData *td, int mi_row,
counts->comp_bwdref[av1_get_pred_context_comp_bwdref_p(cm, xd)][0]
[ref1 == ALTREF_FRAME]++;
#if CONFIG_ALTREF2
if (ref1 != ALTREF_FRAME)
counts->comp_bwdref[av1_get_pred_context_comp_bwdref_p1(cm, xd)]
[1][ref1 == ALTREF2_FRAME]++;
#endif // CONFIG_ALTREF2
#else // !CONFIG_EXT_REFS
counts->comp_ref[av1_get_pred_context_comp_ref_p(cm, xd)][0]
[ref0 == GOLDEN_FRAME]++;
......@@ -1673,12 +1681,18 @@ static void update_stats(const AV1_COMMON *const cm, ThreadData *td, int mi_row,
#endif // CONFIG_EXT_COMP_REFS
} else {
#if CONFIG_EXT_REFS
const int bit = (ref0 == ALTREF_FRAME || ref0 == BWDREF_FRAME);
const int bit = (ref0 >= BWDREF_FRAME);
counts->single_ref[av1_get_pred_context_single_ref_p1(xd)][0][bit]++;
if (bit) {
assert(ref0 <= ALTREF_FRAME);
counts->single_ref[av1_get_pred_context_single_ref_p2(xd)][1]
[ref0 != BWDREF_FRAME]++;
[ref0 == ALTREF_FRAME]++;
#if CONFIG_ALTREF2
if (ref0 != ALTREF_FRAME)
counts->single_ref[av1_get_pred_context_single_ref_p6(xd)][5]
[ref0 == ALTREF2_FRAME]++;
#endif // CONFIG_ALTREF2
} else {
const int bit1 = !(ref0 == LAST2_FRAME || ref0 == LAST_FRAME);
counts
......@@ -4671,6 +4685,9 @@ static int check_dual_ref_flags(AV1_COMP *cpi) {
#if CONFIG_EXT_REFS
!!(ref_flags & AOM_LAST2_FLAG) + !!(ref_flags & AOM_LAST3_FLAG) +
!!(ref_flags & AOM_BWD_FLAG) +
#if CONFIG_ALTREF2
!!(ref_flags & AOM_ALT2_FLAG) +
#endif // CONFIG_ALTREF2
#endif // CONFIG_EXT_REFS
!!(ref_flags & AOM_ALT_FLAG)) >= 2;
}
......@@ -4702,7 +4719,11 @@ static MV_REFERENCE_FRAME get_frame_type(const AV1_COMP *cpi) {
else if (cpi->rc.is_src_frame_alt_ref && cpi->refresh_golden_frame)
#endif
return ALTREF_FRAME;
else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)
else if (cpi->refresh_golden_frame ||
#if CONFIG_EXT_REFS && CONFIG_ALTREF2
cpi->refresh_alt2_ref_frame ||
#endif // CONFIG_EXT_REFS && CONFIG_ALTREF2
cpi->refresh_alt_ref_frame)
return GOLDEN_FRAME;
else
// TODO(zoeliu): To investigate whether a frame_type other than
......@@ -5389,8 +5410,13 @@ void av1_encode_frame(AV1_COMP *cpi) {
cm->comp_fwd_ref[2] = LAST3_FRAME;
cm->comp_fwd_ref[3] = GOLDEN_FRAME;
cm->comp_bwd_ref[0] = BWDREF_FRAME;
#if CONFIG_ALTREF2
cm->comp_bwd_ref[1] = ALTREF2_FRAME;
cm->comp_bwd_ref[2] = ALTREF_FRAME;
#else // !CONFIG_ALTREF2
cm->comp_bwd_ref[1] = ALTREF_FRAME;
#else
#endif // CONFIG_ALTREF2
#else // CONFIG_EXT_REFS
cm->comp_fixed_ref = ALTREF_FRAME;
cm->comp_var_ref[0] = LAST_FRAME;
cm->comp_var_ref[1] = GOLDEN_FRAME;
......
This diff is collapsed.
......@@ -107,8 +107,11 @@ typedef enum {
FRAMEFLAGS_GOLDEN = 1 << 1,
#if CONFIG_EXT_REFS
FRAMEFLAGS_BWDREF = 1 << 2,
#if CONFIG_ALTREF2
// TODO(zoeliu): To determine whether a frame flag is needed for ALTREF2_FRAME
#endif // CONFIG_ALTREF2
FRAMEFLAGS_ALTREF = 1 << 3,
#else
#else // !CONFIG_EXT_REFS
FRAMEFLAGS_ALTREF = 1 << 2,
#endif // CONFIG_EXT_REFS
} FRAMETYPE_FLAGS;
......@@ -407,8 +410,11 @@ typedef struct AV1_COMP {
#endif // CONFIG_EXT_REFS
int gld_fb_idx;
#if CONFIG_EXT_REFS
int bwd_fb_idx; // BWD_REF_FRAME
#endif // CONFIG_EXT_REFS
int bwd_fb_idx; // BWDREF_FRAME
#if CONFIG_ALTREF2
int alt2_fb_idx; // ALTREF2_FRAME
#endif // CONFIG_ALTREF2
#endif // CONFIG_EXT_REFS
int alt_fb_idx;
int last_show_frame_buf_idx; // last show frame buffer index
......@@ -417,6 +423,9 @@ typedef struct AV1_COMP {
int refresh_golden_frame;
#if CONFIG_EXT_REFS
int refresh_bwd_ref_frame;
#if CONFIG_ALTREF2
int refresh_alt2_ref_frame;
#endif // CONFIG_ALTREF2
#endif // CONFIG_EXT_REFS
int refresh_alt_ref_frame;
......@@ -667,6 +676,10 @@ static INLINE int get_ref_frame_map_idx(const AV1_COMP *cpi,
#if CONFIG_EXT_REFS
else if (ref_frame == BWDREF_FRAME)
return cpi->bwd_fb_idx;
#if CONFIG_ALTREF2
else if (ref_frame == ALTREF2_FRAME)
return cpi->alt2_fb_idx;
#endif // CONFIG_ALTREF2
#endif // CONFIG_EXT_REFS
else
return cpi->alt_fb_idx;
......
......@@ -1666,7 +1666,7 @@ static void get_arf_buffer_indices(unsigned char *arf_buffer_indices) {
arf_buffer_indices[0] = ARF_SLOT1;
arf_buffer_indices[1] = ARF_SLOT2;
}
#endif
#endif // !CONFIG_EXT_REFS
static void allocate_gf_group_bits(AV1_COMP *cpi, int64_t gf_group_bits,
double group_error, int gf_arf_bits) {
......@@ -1726,6 +1726,7 @@ static void allocate_gf_group_bits(AV1_COMP *cpi, int64_t gf_group_bits,
// 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;
......@@ -1763,6 +1764,7 @@ static void allocate_gf_group_bits(AV1_COMP *cpi, int64_t gf_group_bits,
#endif // CONFIG_EXT_REFS
// Store the bits to spend on the ARF if there is one.
// === [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;
......@@ -1792,8 +1794,8 @@ static void allocate_gf_group_bits(AV1_COMP *cpi, int64_t gf_group_bits,
// 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[0] =
frame_index + cpi->num_extra_arfs + gf_group->arf_src_offset[1] + 1;
arf_pos[0] = frame_index + cpi->num_extra_arfs +
gf_group->arf_src_offset[frame_index] + 1;
for (i = 0; i < cpi->num_extra_arfs; ++i) {
arf_pos[i + 1] =
frame_index + (cpi->num_extra_arfs - i) * (ext_arf_interval + 2);
......@@ -1808,10 +1810,15 @@ static void allocate_gf_group_bits(AV1_COMP *cpi, int64_t gf_group_bits,
#if CONFIG_EXT_REFS
// Insert an extra ARF
// === [frame_index == 2] ===
if (cpi->num_extra_arfs) {
#if CONFIG_ALTREF2
gf_group->update_type[frame_index] = INTNL_ARF_UPDATE;
#else // !CONFIG_ALTREF2
gf_group->update_type[frame_index] = ARF_UPDATE;
// Note (weitinglin): GF_ARF_LOW is also used as an identifier
// for internal ALT_REF's:
// Note (weitinglin): GF_ARF_LOW is also used as an identifier
// for internal ALT_REF's:
#endif // CONFIG_ALTREF2
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;
......@@ -1819,7 +1826,7 @@ static void allocate_gf_group_bits(AV1_COMP *cpi, int64_t gf_group_bits,
++frame_index;
}
accumulative_subgroup_interval += subgroup_interval[cpi->num_extra_arfs];
#else
#else // !CONFIG_EXT_ARFS
if (cpi->multi_arf_enabled) {
// Set aside a slot for a level 1 arf.
gf_group->update_type[frame_index] = ARF_UPDATE;
......@@ -1875,8 +1882,11 @@ static void allocate_gf_group_bits(AV1_COMP *cpi, int64_t gf_group_bits,
clamp(target_frame_size, 0, AOMMIN(max_bits, (int)total_group_bits));
#if CONFIG_EXT_REFS
// If we are going to have ARFs, check if we can have BWDREF in this
// subgroup.
// 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 &&
......@@ -1953,16 +1963,20 @@ static void allocate_gf_group_bits(AV1_COMP *cpi, int64_t gf_group_bits,
++frame_index;
#if CONFIG_EXT_REFS
// Check if we need to update the ARF
// Check if we need to update the ARF.
if (is_sg_bipred_enabled && cpi->num_extra_arfs && which_arf > 0 &&
frame_index > arf_pos[which_arf]) {
--which_arf;
accumulative_subgroup_interval += subgroup_interval[which_arf] + 1;
// Meet the new subgroup. Reset the bipred_group_end flag;
// 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) {
#if CONFIG_ALTREF2
gf_group->update_type[frame_index] = INTNL_ARF_UPDATE;
#else // !CONFIG_ALTREF2
gf_group->update_type[frame_index] = ARF_UPDATE;
#endif // CONFIG_ALTREF2
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;
......@@ -1991,11 +2005,15 @@ static void allocate_gf_group_bits(AV1_COMP *cpi, int64_t gf_group_bits,
#if CONFIG_EXT_REFS
if (cpi->num_extra_arfs) {
// Overwrite the update_type for internal ARF's:
// Change from LF_UPDATE to INTNL_OVERLAY_UPDATE.
for (i = cpi->num_extra_arfs; i > 0; --i) {
int arf_pos_in_gf = (i == cpi->num_extra_arfs ? 2 : arf_pos[i + 1] + 1);
gf_group->bit_allocation[arf_pos_in_gf] =
gf_group->bit_allocation[arf_pos[i]];
gf_group->update_type[arf_pos[i]] = INTNL_OVERLAY_UPDATE;
// Encoder's choice: Set show_existing_frame == 1 for both internal
// ARF's, and hence allocate zero bit for both internal OVERLAY frames.
gf_group->bit_allocation[arf_pos[i]] = 0;
gf_group->rf_level[arf_pos[i]] = INTER_NORMAL;
}
......@@ -2702,7 +2720,7 @@ static void find_next_key_frame(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) {
static void configure_buffer_updates(AV1_COMP *cpi) {
TWO_PASS *const twopass = &cpi->twopass;
// Wei-Ting: Should we define another function to take care of
// NOTE(weitinglin): Should we define another function to take care of
// cpi->rc.is_$Source_Type to make this function as it is in the comment?
cpi->rc.is_src_frame_alt_ref = 0;
......@@ -2714,19 +2732,29 @@ static void configure_buffer_updates(AV1_COMP *cpi) {
#endif // CONFIG_EXT_REFS
switch (twopass->gf_group.update_type[twopass->gf_group.index]) {
case KF_UPDATE:
case KF_UPDATE: cpi->refresh_last_frame = 1; cpi->refresh_golden_frame = 1;
#if CONFIG_EXT_REFS
cpi->refresh_bwd_ref_frame = 1;
#if CONFIG_ALTREF2
cpi->refresh_alt2_ref_frame = 1;
#endif // CONFIG_ALTREF2
#endif // CONFIG_EXT_REFS
cpi->refresh_last_frame = 1;
cpi->refresh_golden_frame = 1;
cpi->refresh_alt_ref_frame = 1;
break;
case LF_UPDATE:
case LF_UPDATE: cpi->refresh_last_frame = 1; cpi->refresh_golden_frame = 0;
#if CONFIG_EXT_REFS
// If we have extra ALT_REFs, we can use the farthest ALT (ALT0) as
// the BWD_REF.
cpi->refresh_bwd_ref_frame = 0;
#if CONFIG_ALTREF2
cpi->refresh_alt2_ref_frame = 0;
#endif // CONFIG_ALTREF2
#endif // CONFIG_EXT_REFS
cpi->refresh_alt_ref_frame = 0;
#if CONFIG_EXT_REFS && !CONFIG_ALTREF2
// If we have extra ALT_REFs, we may use the farthest ALT (ALT0) as
// the BWDREF_FRAME, as LF_UPDATE frames do not have BWDREF_FRAME
// available as their reference.
if (cpi->num_extra_arfs) {
int tmp = cpi->bwd_fb_idx;
......@@ -2735,21 +2763,21 @@ static void configure_buffer_updates(AV1_COMP *cpi) {
cpi->arf_map[0] = tmp;
cpi->rc.is_bwd_ref_frame = 1;
} else {
cpi->rc.is_bwd_ref_frame = 0;
}
#endif // CONFIG_EXT_REFS
cpi->refresh_last_frame = 1;
cpi->refresh_golden_frame = 0;
cpi->refresh_alt_ref_frame = 0;
#endif // CONFIG_EXT_REFS && !CONFIG_ALTREF2
break;
case GF_UPDATE:
// TODO(zoeliu): To further investigate whether 'refresh_last_frame' is
// needed.
cpi->refresh_last_frame = 1;
cpi->refresh_golden_frame = 1;
#if CONFIG_EXT_REFS
cpi->refresh_bwd_ref_frame = 0;
#if CONFIG_ALTREF2
cpi->refresh_alt2_ref_frame = 0;
#endif // CONFIG_ALTREF2
#endif // CONFIG_EXT_REFS
cpi->refresh_last_frame = 1;
cpi->refresh_golden_frame = 1;
cpi->refresh_alt_ref_frame = 0;
break;
......@@ -2758,17 +2786,25 @@ static void configure_buffer_updates(AV1_COMP *cpi) {
cpi->refresh_golden_frame = 1;
#if CONFIG_EXT_REFS
cpi->refresh_bwd_ref_frame = 0;
#if CONFIG_ALTREF2
cpi->refresh_alt2_ref_frame = 0;
#endif // CONFIG_ALTREF2
#endif // CONFIG_EXT_REFS
cpi->refresh_alt_ref_frame = 0;
cpi->rc.is_src_frame_alt_ref = 1;
break;
case ARF_UPDATE:
case ARF_UPDATE: cpi->refresh_last_frame = 0; cpi->refresh_golden_frame = 0;
#if CONFIG_EXT_REFS
#if CONFIG_ALTREF2
// NOTE: BWDREF does not get updated along with ALTREF_FRAME.
cpi->refresh_bwd_ref_frame = 0;
cpi->refresh_alt2_ref_frame = 0;
#else // !CONFIG_ALTREF2
cpi->refresh_bwd_ref_frame = 1;
#endif // CONFIG_ALTREF2
#endif // CONFIG_EXT_REFS
cpi->refresh_last_frame = 0;
cpi->refresh_golden_frame = 0;
cpi->refresh_alt_ref_frame = 1;
break;
......@@ -2777,8 +2813,12 @@ static void configure_buffer_updates(AV1_COMP *cpi) {
cpi->refresh_last_frame = 0;
cpi->refresh_golden_frame = 0;
cpi->refresh_bwd_ref_frame = 1;
#if CONFIG_ALTREF2
cpi->refresh_alt2_ref_frame = 0;
#endif // CONFIG_ALTREF2
cpi->refresh_alt_ref_frame = 0;
cpi->rc.is_bwd_ref_frame = 1;
#if !CONFIG_ALTREF2
if (cpi->num_extra_arfs) {
// Allow BRF use the farthest ALT_REF (ALT0) as BWD_REF by swapping
// the virtual indices.
......@@ -2790,13 +2830,19 @@ static void configure_buffer_updates(AV1_COMP *cpi) {
cpi->alt_fb_idx = cpi->arf_map[0];
cpi->arf_map[0] = tmp;
}
#endif // !CONFIG_ALTREF2
cpi->rc.is_bwd_ref_frame = 1;
break;
case LAST_BIPRED_UPDATE:
cpi->refresh_last_frame = 1;
cpi->refresh_golden_frame = 0;
cpi->refresh_bwd_ref_frame = 0;
#if CONFIG_ALTREF2
cpi->refresh_alt2_ref_frame = 0;
#endif // CONFIG_ALTREF2
cpi->refresh_alt_ref_frame = 0;
cpi->rc.is_last_bipred_frame = 1;
break;
......@@ -2804,7 +2850,11 @@ static void configure_buffer_updates(AV1_COMP *cpi) {
cpi->refresh_last_frame = 1;
cpi->refresh_golden_frame = 0;
cpi->refresh_bwd_ref_frame = 0;
#if CONFIG_ALTREF2
cpi->refresh_alt2_ref_frame = 0;
#endif // CONFIG_ALTREF2
cpi->refresh_alt_ref_frame = 0;
cpi->rc.is_bipred_frame = 1;
break;
......@@ -2812,10 +2862,24 @@ static void configure_buffer_updates(AV1_COMP *cpi) {
cpi->refresh_last_frame = 1;
cpi->refresh_golden_frame = 0;
cpi->refresh_bwd_ref_frame = 0;
#if CONFIG_ALTREF2
cpi->refresh_alt2_ref_frame = 0;
#endif // CONFIG_ALTREF2
cpi->refresh_alt_ref_frame = 0;
cpi->rc.is_src_frame_alt_ref = 1;
cpi->rc.is_src_frame_ext_arf = 1;
break;
#if CONFIG_ALTREF2
case INTNL_ARF_UPDATE:
cpi->refresh_last_frame = 0;
cpi->refresh_golden_frame = 0;
cpi->refresh_bwd_ref_frame = 0;
cpi->refresh_alt2_ref_frame = 1;
cpi->refresh_alt_ref_frame = 0;
break;
#endif // CONFIG_ALTREF2
#endif // CONFIG_EXT_REFS
default: assert(0); break;
......@@ -2857,7 +2921,11 @@ void av1_rc_get_second_pass_params(AV1_COMP *cpi) {
// If this is an arf frame then we dont want to read the stats file or
// advance the input pointer as we already have what we need.
if (gf_group->update_type[gf_group->index] == ARF_UPDATE) {
if (gf_group->update_type[gf_group->index] == ARF_UPDATE
#if CONFIG_EXT_REFS && CONFIG_ALTREF2
|| gf_group->update_type[gf_group->index] == INTNL_ARF_UPDATE
#endif // CONFIG_EXT_REFS && CONFIG_ALTREF2
) {
configure_buffer_updates(cpi);
target_rate = gf_group->bit_allocation[gf_group->index];
target_rate = av1_rc_clamp_pframe_target_size(cpi, target_rate);
......
......@@ -101,8 +101,13 @@ typedef enum {
LAST_BIPRED_UPDATE = 6, // Last Bi-predictive Frame
BIPRED_UPDATE = 7, // Bi-predictive Frame, but not the last one
INTNL_OVERLAY_UPDATE = 8, // Internal Overlay Frame
#if CONFIG_ALTREF2
INTNL_ARF_UPDATE = 9, // Internal Altref Frame (candidate for ALTREF2)
FRAME_UPDATE_TYPES = 10
#else // !CONFIG_ALTREF2
FRAME_UPDATE_TYPES = 9
#else
#endif // CONFIG_ALTREF2
#else // !CONFIG_EXT_REFS
FRAME_UPDATE_TYPES = 5
#endif // CONFIG_EXT_REFS
} FRAME_UPDATE_TYPE;
......
......@@ -579,8 +579,11 @@ static int calc_active_worst_quality_one_pass_vbr(const AV1_COMP *cpi) {
active_worst_quality =
curr_frame == 0 ? rc->worst_quality : rc->last_q[KEY_FRAME] * 2;
} else {
if (!rc->is_src_frame_alt_ref &&
(cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
if (!rc->is_src_frame_alt_ref && (cpi->refresh_golden_frame ||
#if CONFIG_EXT_REFS && CONFIG_ALTREF2
cpi->refresh_alt2_ref_frame ||
#endif // CONFIG_EXT_REFS && CONFIG_ALTREF2
cpi->refresh_alt_ref_frame)) {
active_worst_quality = curr_frame == 1 ? rc->last_q[KEY_FRAME] * 5 / 4
: rc->last_q[INTER_FRAME];
} else {
......@@ -1005,8 +1008,11 @@ static int rc_pick_q_and_bounds_two_pass(const AV1_COMP *cpi, int *bottom_index,
active_best_quality +=
av1_compute_qdelta(rc, q_val, q_val * q_adj_factor, cm->bit_depth);
}
} else if (!rc->is_src_frame_alt_ref &&
(cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
} else if (!rc->is_src_frame_alt_ref && (cpi->refresh_golden_frame ||
#if CONFIG_EXT_REFS && CONFIG_ALTREF2
cpi->refresh_alt2_ref_frame ||
#endif // CONFIG_EXT_REFS && CONFIG_ALTREF2
cpi->refresh_alt_ref_frame)) {
// Use the lower of active_worst_quality and recent
// average Q as basis for GF/ARF best Q limit unless last frame was
// a key frame.
......@@ -1026,7 +1032,11 @@ static int rc_pick_q_and_bounds_two_pass(const AV1_COMP *cpi, int *bottom_index,
active_best_quality = active_best_quality * 15 / 16;
} else if (oxcf->rc_mode == AOM_Q) {
#if CONFIG_EXT_REFS && CONFIG_ALTREF2
if (!cpi->refresh_alt_ref_frame && !cpi->refresh_alt2_ref_frame) {
#else
if (!cpi->refresh_alt_ref_frame) {
#endif // CONFIG_EXT_REFS && CONFIG_ALTREF2
active_best_quality = cq_level;
} else {
active_best_quality = get_gf_active_quality(rc, q, cm->bit_depth);
......