Commit f452fdfe authored by Zoe Liu's avatar Zoe Liu

Speed up ref selection by enforcing max 6 frames

A speedup feature that enforces the maximum number of reference frames
to evaluate for each arbitrary frame to be 6, as opposed to the maximum
syntax-allowed number of reference frames which is 7, through the
following rules:

(1) When all the possible reference frames are availble, we reduce the
    number of reference frames (7) by 1 by removing one reference
    frame;
(2) Always retain GOLDEN_FARME/ALTEF_FRAME;
(3) Check the earliest 2 remaining reference frames, and there are two
    options to remove one reference frame:
    (a) Remove the one with the lower quality factor; Otherwise if
    both frames have been coded at the same quality level, remove the
    earliest reference frame;
    (b) Always remove the earliest reference frame.
    Currently set option (a).

This patch has demonstrated an encoder speedup of ~8.5%. It is under
speed2 with "selective_ref_frame >= 2". (May be considered to move
to speed1 later once the coding performance impact is evaluated
further.)

Using the following configure setups, the coding performance has been
dropped on Google test sets (50 frames) in BDRate by ~0.2% for lowres
and by ~0.1% for midres:
--enable-experimental --disable-convolve-round --disable-ext-partition
--disable-ext-partition-types --disable-txk-sel --disable-txm

Change-Id: I84317bae00bfd90b2c3d301858a849f441974e6f
parent 49fad89a
......@@ -3671,6 +3671,115 @@ static int refs_are_one_sided(const AV1_COMMON *cm) {
one_sided_refs = 0;
return one_sided_refs;
}
// Enforce the number of references for each arbitrary frame limited to
// (INTER_REFS_PER_FRAME - 1)
static void enforce_max_ref_frames(AV1_COMP *cpi) {
AV1_COMMON *const cm = &cpi->common;
static const int flag_list[TOTAL_REFS_PER_FRAME] = { 0,
AOM_LAST_FLAG,
AOM_LAST2_FLAG,
AOM_LAST3_FLAG,
AOM_GOLD_FLAG,
AOM_BWD_FLAG,
AOM_ALT2_FLAG,
AOM_ALT_FLAG };
MV_REFERENCE_FRAME ref_frame;
int total_valid_refs = 0;
(void)flag_list;
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
if (cpi->ref_frame_flags & flag_list[ref_frame]) total_valid_refs++;
}
// NOTE(zoeliu): When all the possible reference frames are availble, we
// reduce the number of reference frames by 1, following the rules of:
// (1) Retain GOLDEN_FARME/ALTEF_FRAME;
// (2) Check the earliest 2 remaining reference frames, and remove the one
// with the lower quality factor, otherwise if both have been coded at
// the same quality level, remove the earliest reference frame.
if (total_valid_refs == INTER_REFS_PER_FRAME) {
unsigned int min_ref_offset = UINT_MAX;
unsigned int second_min_ref_offset = UINT_MAX;
MV_REFERENCE_FRAME earliest_ref_frames[2] = { LAST3_FRAME, LAST2_FRAME };
int earliest_buf_idxes[2] = { 0 };
// Locate the earliest two reference frames except GOLDEN/ALTREF.
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
// Retain GOLDEN/ALTERF
if (ref_frame == GOLDEN_FRAME || ref_frame == ALTREF_FRAME) continue;
const int buf_idx = cm->frame_refs[ref_frame - LAST_FRAME].idx;
if (buf_idx >= 0) {
const unsigned int ref_offset =
cm->buffer_pool->frame_bufs[buf_idx].cur_frame_offset;
if (min_ref_offset == UINT_MAX) {
min_ref_offset = ref_offset;
earliest_ref_frames[0] = ref_frame;
earliest_buf_idxes[0] = buf_idx;
} else {
if (ref_offset < min_ref_offset) {
second_min_ref_offset = min_ref_offset;
earliest_ref_frames[1] = earliest_ref_frames[0];
earliest_buf_idxes[1] = earliest_buf_idxes[0];
min_ref_offset = ref_offset;
earliest_ref_frames[0] = ref_frame;
earliest_buf_idxes[0] = buf_idx;
} else if (ref_offset < second_min_ref_offset) {
second_min_ref_offset = ref_offset;
earliest_ref_frames[1] = ref_frame;
earliest_buf_idxes[1] = buf_idx;
}
}
}
}
// Check the coding quality factors of the two earliest reference frames.
RATE_FACTOR_LEVEL ref_rf_level[2];
double ref_rf_deltas[2];
for (int i = 0; i < 2; ++i) {
ref_rf_level[i] = cpi->frame_rf_level[earliest_buf_idxes[i]];
ref_rf_deltas[i] = rate_factor_deltas[ref_rf_level[i]];
}
(void)ref_rf_level;
(void)ref_rf_deltas;
#define USE_RF_LEVEL_TO_ENFORCE 1
#if USE_RF_LEVEL_TO_ENFORCE
// If both earliest two reference frames are coded using the same rate-
// factor, disable the earliest reference frame; Otherwise disable the
// reference frame that uses a lower rate-factor delta.
const MV_REFERENCE_FRAME ref_frame_to_disable =
(ref_rf_deltas[0] <= ref_rf_deltas[1]) ? earliest_ref_frames[0]
: earliest_ref_frames[1];
#else
// Always disable the earliest reference frame
const MV_REFERENCE_FRAME ref_frame_to_disable = earliest_ref_frames[0];
#endif // USE_RF_LEVEL_TO_ENFORCE
#undef USE_RF_LEVEL_TO_ENFORCE
#if 0
printf("===Enforce: Frame_offset=%d, earliest refs: %d-%d(%d,%4.2f) and "
"%d-%d(%d,%4.2f), ref_frame_to_disable=%d\n",
cm->frame_offset, earliest_ref_frames[0], min_ref_offset,
ref_rf_level[0], ref_rf_deltas[0], earliest_ref_frames[1],
second_min_ref_offset, ref_rf_level[1], ref_rf_deltas[1],
ref_frame_to_disable);
#endif // 0
switch (ref_frame_to_disable) {
case LAST_FRAME: cpi->ref_frame_flags &= ~AOM_LAST_FLAG; break;
case LAST2_FRAME: cpi->ref_frame_flags &= ~AOM_LAST2_FLAG; break;
case LAST3_FRAME: cpi->ref_frame_flags &= ~AOM_LAST3_FLAG; break;
case BWDREF_FRAME: cpi->ref_frame_flags &= ~AOM_BWD_FLAG; break;
case ALTREF2_FRAME: cpi->ref_frame_flags &= ~AOM_ALT2_FLAG; break;
default: break;
}
}
}
#endif // CONFIG_FRAME_MARKER
static void encode_frame_internal(AV1_COMP *cpi) {
......@@ -4055,6 +4164,7 @@ void av1_encode_frame(AV1_COMP *cpi) {
cm->frame_offset = cm->current_video_frame;
}
av1_setup_frame_buf_refs(cm);
if (cpi->sf.selective_ref_frame >= 2) enforce_max_ref_frames(cpi);
#if CONFIG_FRAME_SIGN_BIAS
av1_setup_frame_sign_bias(cm);
#endif // CONFIG_FRAME_SIGN_BIAS
......
......@@ -5239,8 +5239,11 @@ static void dump_filtered_recon_frames(AV1_COMP *cpi) {
(buf_idx >= 0)
? (int)cm->buffer_pool->frame_bufs[buf_idx].cur_frame_offset
: -1;
printf(" %d(%c)", ref_offset,
(cpi->ref_frame_flags & flag_list[ref_frame]) ? 'Y' : 'N');
printf(
" %d(%c-%d-%4.2f)", ref_offset,
(cpi->ref_frame_flags & flag_list[ref_frame]) ? 'Y' : 'N',
(buf_idx >= 0) ? (int)cpi->frame_rf_level[buf_idx] : -1,
(buf_idx >= 0) ? rate_factor_deltas[cpi->frame_rf_level[buf_idx]] : -1);
}
printf(" ]\n");
#endif // CONFIG_FRAME_MARKER
......@@ -6527,6 +6530,12 @@ int av1_get_compressed_data(AV1_COMP *cpi, unsigned int *frame_flags,
if (cm->new_fb_idx == INVALID_IDX) return -1;
#if CONFIG_FRAME_MARKER
// Retain the RF_LEVEL for the current newly coded frame.
cpi->frame_rf_level[cm->new_fb_idx] =
cpi->twopass.gf_group.rf_level[cpi->twopass.gf_group.index];
#endif // CONFIG_FRAME_MARKER
cm->cur_frame = &pool->frame_bufs[cm->new_fb_idx];
#if CONFIG_HIGHBITDEPTH
cm->cur_frame->buf.buf_8bit_valid = 0;
......
......@@ -470,6 +470,9 @@ typedef struct AV1_COMP {
int mbgraph_n_frames; // number of frames filled in the above
int static_mb_pct; // % forced skip mbs by segmentation
int ref_frame_flags;
#if CONFIG_FRAME_MARKER
RATE_FACTOR_LEVEL frame_rf_level[FRAME_BUFFERS];
#endif // CONFIG_FRAME_MARKER
SPEED_FEATURES sf;
......
......@@ -921,14 +921,6 @@ static int rc_pick_q_and_bounds_one_pass_vbr(const AV1_COMP *cpi, int width,
}
int av1_frame_type_qdelta(const AV1_COMP *cpi, int rf_level, int q) {
static const double rate_factor_deltas[RATE_FACTOR_LEVELS] = {
1.00, // INTER_NORMAL
0.80, // INTER_LOW
1.50, // INTER_HIGH
1.25, // GF_ARF_LOW
2.00, // GF_ARF_STD
2.00, // KF_STD
};
static const FRAME_TYPE frame_type[RATE_FACTOR_LEVELS] = {
INTER_FRAME, INTER_FRAME, INTER_FRAME, INTER_FRAME, INTER_FRAME, KEY_FRAME
};
......
......@@ -38,6 +38,15 @@ typedef enum {
RATE_FACTOR_LEVELS = 6
} RATE_FACTOR_LEVEL;
static const double rate_factor_deltas[RATE_FACTOR_LEVELS] = {
1.00, // INTER_NORMAL
0.80, // INTER_LOW
1.50, // INTER_HIGH
1.25, // GF_ARF_LOW
2.00, // GF_ARF_STD
2.00, // KF_STD
};
typedef struct {
int resize_width;
int resize_height;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment