summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Wilkins <paulwilkins@google.com>2014-08-15 14:49:34 +0100
committerPaul Wilkins <paulwilkins@google.com>2014-09-18 12:53:48 +0100
commitc389b37bb4c6e488a2b562248fd4d5dfddbe783a (patch)
treecb7f898fa808046d2b0a866f32ca3ebf9e6e943a
parent4e066299d943e2ae8965dcc0f40fa3690f1b89c4 (diff)
downloadlibvpx-c389b37bb4c6e488a2b562248fd4d5dfddbe783a.tar
libvpx-c389b37bb4c6e488a2b562248fd4d5dfddbe783a.tar.gz
libvpx-c389b37bb4c6e488a2b562248fd4d5dfddbe783a.tar.bz2
libvpx-c389b37bb4c6e488a2b562248fd4d5dfddbe783a.zip
Substantial reworking of code for arf and kf groups.
Substantial restructuring of the way we estimate the rate of decay in prediction quality and determine the arf interval and amount of boost used. Also other changes to support moving to a lower first pass Q which exposes some new features and allows us to better distinguish genuinely static blocks from low motion or noisy blocks. Net gains now visible on all the test sets with std-hd PSNR up 1.87%. There are still some bad outlier cases but most of these are low motion or slide show type content where the metrics are already high at any given rate. The best + case is up by more than 10%. Change-Id: I18e25170053bdf3188f493ff8062f48a74515815
-rw-r--r--vp9/encoder/vp9_firstpass.c271
-rw-r--r--vp9/encoder/vp9_firstpass.h3
-rw-r--r--vp9/encoder/vp9_ratectrl.c89
-rw-r--r--vp9/encoder/vp9_ratectrl.h1
4 files changed, 201 insertions, 163 deletions
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index df82be5ec..e9b5aa258 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -35,26 +35,28 @@
#include "vp9/encoder/vp9_rd.h"
#include "vp9/encoder/vp9_variance.h"
-#define OUTPUT_FPF 0
-
-#define IIFACTOR 12.5
-#define IIKFACTOR1 12.5
-#define IIKFACTOR2 15.0
-#define RMAX 512.0
-#define GF_RMAX 96.0
-#define ERR_DIVISOR 150.0
-#define MIN_DECAY_FACTOR 0.1
-#define SVC_FACTOR_PT_LOW 0.45
-#define FACTOR_PT_LOW 0.5
-#define FACTOR_PT_HIGH 0.9
-
-#define KF_MB_INTRA_MIN 150
-#define GF_MB_INTRA_MIN 100
+#define OUTPUT_FPF 0
+#define ARF_STATS_OUTPUT 0
+
+#define BOOST_FACTOR 12.5
+#define ERR_DIVISOR 100.0
+#define FACTOR_PT_LOW 0.5
+#define FACTOR_PT_HIGH 0.9
+#define FIRST_PASS_Q 10.0
+#define GF_MAX_BOOST 96.0
+#define INTRA_MODE_PENALTY 1024
+#define KF_MAX_BOOST 128.0
+#define MIN_DECAY_FACTOR 0.01
+#define MIN_GF_INTERVAL 4
+#define MIN_KF_BOOST 300
+#define NEW_MV_MODE_PENALTY 32
+#define SVC_FACTOR_PT_LOW 0.45
#define DOUBLE_DIVIDE_CHECK(x) ((x) < 0 ? (x) - 0.000001 : (x) + 0.000001)
-#define MIN_KF_BOOST 300
-#define MIN_GF_INTERVAL 4
+#if ARF_STATS_OUTPUT
+unsigned int arf_count = 0;
+#endif
static void swap_yv12(YV12_BUFFER_CONFIG *a, YV12_BUFFER_CONFIG *b) {
YV12_BUFFER_CONFIG temp = *a;
@@ -299,7 +301,7 @@ static void first_pass_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
int num00, tmp_err, n;
const BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
vp9_variance_fn_ptr_t v_fn_ptr = cpi->fn_ptr[bsize];
- const int new_mv_mode_penalty = 256;
+ const int new_mv_mode_penalty = NEW_MV_MODE_PENALTY;
int step_param = 3;
int further_steps = (MAX_MVSEARCH_STEPS - 1) - step_param;
@@ -364,7 +366,7 @@ static int find_fp_qindex(vpx_bit_depth_t bit_depth) {
int i;
for (i = 0; i < QINDEX_RANGE; ++i)
- if (vp9_convert_qindex_to_q(i, bit_depth) >= 30.0)
+ if (vp9_convert_qindex_to_q(i, bit_depth) >= FIRST_PASS_Q)
break;
if (i == QINDEX_RANGE)
@@ -414,7 +416,7 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) {
int mvcount = 0;
int intercount = 0;
int second_ref_count = 0;
- int intrapenalty = 256;
+ const int intrapenalty = INTRA_MODE_PENALTY;
int neutral_count = 0;
int new_mv_count = 0;
int sum_in_vectors = 0;
@@ -830,12 +832,18 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) {
vp9_clear_system_state();
{
FIRSTPASS_STATS fps;
+ // The minimum error here insures some bit alocation to frames even
+ // in static regions. The allocation per MB declines for larger formats
+ // where the typical "real" energy per MB also falls.
+ // Initial estimate here uses sqrt(mbs) to define the min_err, where the
+ // number of mbs is propotional to image area.
+ const double min_err = 200 * sqrt(cm->MBs);
fps.frame = cm->current_video_frame;
fps.spatial_layer_id = cpi->svc.spatial_layer_id;
- fps.intra_error = (double)(intra_error >> 8);
- fps.coded_error = (double)(coded_error >> 8);
- fps.sr_coded_error = (double)(sr_coded_error >> 8);
+ fps.coded_error = (double)(coded_error >> 8) + min_err;
+ fps.sr_coded_error = (double)(sr_coded_error >> 8) + min_err;
+ fps.intra_error = (double)(intra_error >> 8) + min_err;
fps.count = 1.0;
fps.pcnt_inter = (double)intercount / cm->MBs;
fps.pcnt_second_ref = (double)second_ref_count / cm->MBs;
@@ -1033,17 +1041,6 @@ void vp9_init_second_pass(VP9_COMP *cpi) {
10000000.0);
}
- // Calculate a minimum intra value to be used in determining the IIratio
- // scores used in the second pass. We have this minimum to make sure
- // that clips that are static but "low complexity" in the intra domain
- // are still boosted appropriately for KF/GF/ARF.
- if (!is_two_pass_svc) {
- // We don't know the number of MBs for each layer at this point.
- // So we will do it later.
- twopass->kf_intra_err_min = KF_MB_INTRA_MIN * cpi->common.MBs;
- twopass->gf_intra_err_min = GF_MB_INTRA_MIN * cpi->common.MBs;
- }
-
// This variable monitors how far behind the second ref update is lagging.
twopass->sr_update_lag = 1;
@@ -1067,34 +1064,58 @@ void vp9_init_second_pass(VP9_COMP *cpi) {
// Reset the vbr bits off target counter
cpi->rc.vbr_bits_off_target = 0;
+
+ // Static sequence monitor variables.
+ twopass->kf_zeromotion_pct = 100;
+ twopass->last_kfgroup_zeromotion_pct = 100;
}
-// This function gives an estimate of how badly we believe the prediction
-// quality is decaying from frame to frame.
-static double get_prediction_decay_rate(const VP9_COMMON *cm,
- const FIRSTPASS_STATS *next_frame) {
- // Look at the observed drop in prediction quality between the last frame
- // and the GF buffer (which contains an older frame).
- const double mb_sr_err_diff = (next_frame->sr_coded_error -
- next_frame->coded_error) / cm->MBs;
- const double second_ref_decay = mb_sr_err_diff <= 512.0
- ? fclamp(pow(1.0 - (mb_sr_err_diff / 512.0), 0.5), 0.85, 1.0)
- : 0.85;
-
- return MIN(second_ref_decay, next_frame->pcnt_inter);
+#define SR_DIFF_PART 0.0015
+#define MOTION_AMP_PART 0.003
+#define INTRA_PART 0.005
+#define DEFAULT_DECAY_LIMIT 0.75
+#define LOW_SR_DIFF_TRHESH 0.1
+#define SR_DIFF_MAX 128.0
+
+static double get_sr_decay_rate(const VP9_COMMON *cm,
+ const FIRSTPASS_STATS *frame) {
+ double sr_diff = (frame->sr_coded_error - frame->coded_error) / cm->MBs;
+ double sr_decay = 1.0;
+ const double motion_amplitude_factor =
+ frame->pcnt_motion * ((frame->mvc_abs + frame->mvr_abs) / 2);
+ const double pcnt_intra = 100 * (1.0 - frame->pcnt_inter);
+
+ if ((sr_diff > LOW_SR_DIFF_TRHESH)) {
+ sr_diff = MIN(sr_diff, SR_DIFF_MAX);
+ sr_decay = 1.0 - (SR_DIFF_PART * sr_diff) -
+ (MOTION_AMP_PART * motion_amplitude_factor) -
+ (INTRA_PART * pcnt_intra);
+ }
+ return MAX(sr_decay, MIN(DEFAULT_DECAY_LIMIT, frame->pcnt_inter));
}
// This function gives an estimate of how badly we believe the prediction
// quality is decaying from frame to frame.
-static double get_zero_motion_factor(const FIRSTPASS_STATS *frame) {
- const double sr_ratio = frame->coded_error /
- DOUBLE_DIVIDE_CHECK(frame->sr_coded_error);
+static double get_zero_motion_factor(const VP9_COMMON *cm,
+ const FIRSTPASS_STATS *frame) {
const double zero_motion_pct = frame->pcnt_inter -
frame->pcnt_motion;
-
- return MIN(sr_ratio, zero_motion_pct);
+ double sr_decay = get_sr_decay_rate(cm, frame);
+ return MIN(sr_decay, zero_motion_pct);
}
+#define ZM_POWER_FACTOR 0.75
+
+static double get_prediction_decay_rate(const VP9_COMMON *cm,
+ const FIRSTPASS_STATS *next_frame) {
+ const double sr_decay_rate = get_sr_decay_rate(cm, next_frame);
+ const double zero_motion_factor =
+ (0.95 * pow((next_frame->pcnt_inter - next_frame->pcnt_motion),
+ ZM_POWER_FACTOR));
+
+ return MAX(zero_motion_factor,
+ (sr_decay_rate + ((1.0 - sr_decay_rate) * zero_motion_factor)));
+}
// Function to test for a condition where a complex transition is followed
// by a static section. For example in slide shows where there is a fade
@@ -1172,19 +1193,17 @@ static void accumulate_frame_motion_stats(const FIRSTPASS_STATS *stats,
}
}
-// Calculate a baseline boost number for the current frame.
-static double calc_frame_boost(const TWO_PASS *twopass,
+#define BASELINE_ERR_PER_MB 1000.0
+static double calc_frame_boost(VP9_COMP *cpi,
const FIRSTPASS_STATS *this_frame,
- double this_frame_mv_in_out) {
+ double this_frame_mv_in_out,
+ double max_boost) {
double frame_boost;
- // Underlying boost factor is based on inter intra error ratio.
- if (this_frame->intra_error > twopass->gf_intra_err_min)
- frame_boost = (IIFACTOR * this_frame->intra_error /
- DOUBLE_DIVIDE_CHECK(this_frame->coded_error));
- else
- frame_boost = (IIFACTOR * twopass->gf_intra_err_min /
- DOUBLE_DIVIDE_CHECK(this_frame->coded_error));
+ // Underlying boost factor is based on inter error ratio.
+ frame_boost = (BASELINE_ERR_PER_MB * cpi->common.MBs) /
+ DOUBLE_DIVIDE_CHECK(this_frame->coded_error);
+ frame_boost = frame_boost * BOOST_FACTOR;
// Increase boost for frames where new data coming into frame (e.g. zoom out).
// Slightly reduce boost if there is a net balance of motion out of the frame
@@ -1195,7 +1214,7 @@ static double calc_frame_boost(const TWO_PASS *twopass,
else
frame_boost += frame_boost * (this_frame_mv_in_out / 2.0);
- return MIN(frame_boost, GF_RMAX);
+ return MIN(frame_boost, max_boost);
}
static int calc_arf_boost(VP9_COMP *cpi, int offset,
@@ -1236,8 +1255,9 @@ static int calc_arf_boost(VP9_COMP *cpi, int offset,
? MIN_DECAY_FACTOR : decay_accumulator;
}
- boost_score += decay_accumulator * calc_frame_boost(twopass, this_frame,
- this_frame_mv_in_out);
+ boost_score += decay_accumulator * calc_frame_boost(cpi, this_frame,
+ this_frame_mv_in_out,
+ GF_MAX_BOOST);
}
*f_boost = (int)boost_score;
@@ -1274,8 +1294,9 @@ static int calc_arf_boost(VP9_COMP *cpi, int offset,
? MIN_DECAY_FACTOR : decay_accumulator;
}
- boost_score += decay_accumulator * calc_frame_boost(twopass, this_frame,
- this_frame_mv_in_out);
+ boost_score += decay_accumulator * calc_frame_boost(cpi, this_frame,
+ this_frame_mv_in_out,
+ GF_MAX_BOOST);
}
*b_boost = (int)boost_score;
@@ -1585,7 +1606,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
gf_group_err -= gf_first_frame_err;
// Motion breakout threshold for loop below depends on image size.
- mv_ratio_accumulator_thresh = (cpi->common.width + cpi->common.height) / 10.0;
+ mv_ratio_accumulator_thresh = (cpi->common.width + cpi->common.height) / 4.0;
// Work out a maximum interval for the GF group.
// If the image appears almost completely static we can extend beyond this.
@@ -1629,11 +1650,13 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
if (!flash_detected) {
last_loop_decay_rate = loop_decay_rate;
loop_decay_rate = get_prediction_decay_rate(&cpi->common, &next_frame);
+
decay_accumulator = decay_accumulator * loop_decay_rate;
// Monitor for static sections.
- zero_motion_accumulator = MIN(zero_motion_accumulator,
- get_zero_motion_factor(&next_frame));
+ zero_motion_accumulator =
+ MIN(zero_motion_accumulator,
+ get_zero_motion_factor(&cpi->common, &next_frame));
// Break clause to detect very still sections after motion. For example,
// a static image after a fade or other transition.
@@ -1645,8 +1668,9 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
}
// Calculate a boost number for this frame.
- boost_score += decay_accumulator * calc_frame_boost(twopass, &next_frame,
- this_frame_mv_in_out);
+ boost_score += decay_accumulator * calc_frame_boost(cpi, &next_frame,
+ this_frame_mv_in_out,
+ GF_MAX_BOOST);
// Break out conditions.
if (
@@ -1655,38 +1679,21 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
(
// Don't break out with a very short interval.
(i > MIN_GF_INTERVAL) &&
- ((boost_score > 125.0) || (next_frame.pcnt_inter < 0.75)) &&
(!flash_detected) &&
((mv_ratio_accumulator > mv_ratio_accumulator_thresh) ||
(abs_mv_in_out_accumulator > 3.0) ||
(mv_in_out_accumulator < -2.0) ||
- ((boost_score - old_boost_score) < IIFACTOR)))) {
+ ((boost_score - old_boost_score) < BOOST_FACTOR)))) {
boost_score = old_boost_score;
break;
}
*this_frame = next_frame;
-
old_boost_score = boost_score;
}
twopass->gf_zeromotion_pct = (int)(zero_motion_accumulator * 1000.0);
- // Don't allow a gf too near the next kf.
- if ((rc->frames_to_key - i) < MIN_GF_INTERVAL) {
- while (i < (rc->frames_to_key + !rc->next_key_frame_forced)) {
- ++i;
-
- if (EOF == input_stats(twopass, this_frame))
- break;
-
- if (i < rc->frames_to_key) {
- mod_frame_err = calculate_modified_err(twopass, oxcf, this_frame);
- gf_group_err += mod_frame_err;
- }
- }
- }
-
// Set the interval until the next gf.
if (cpi->common.frame_type == KEY_FRAME || rc->source_alt_ref_active)
rc->baseline_gf_interval = i - 1;
@@ -1713,10 +1720,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
// Should we use the alternate reference frame.
if (allow_alt_ref &&
(i < cpi->oxcf.lag_in_frames) &&
- (i >= MIN_GF_INTERVAL) &&
- // For real scene cuts (not forced kfs) don't allow arf very near kf.
- (rc->next_key_frame_forced ||
- (i <= (rc->frames_to_key - MIN_GF_INTERVAL)))) {
+ (i >= MIN_GF_INTERVAL)) {
// Calculate the boost for alt ref.
rc->gfu_boost = calc_arf_boost(cpi, 0, (i - 1), (i - 1), &f_boost,
&b_boost);
@@ -1727,7 +1731,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
(cpi->multi_arf_allowed && (rc->baseline_gf_interval >= 6) &&
(zero_motion_accumulator < 0.995)) ? 1 : 0;
} else {
- rc->gfu_boost = (int)boost_score;
+ rc->gfu_boost = MAX((int)boost_score, 125);
rc->source_alt_ref_pending = 0;
}
@@ -1782,6 +1786,9 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
}
}
+// TODO(PGW) Re-examine the use of II ration in this code in the light of#
+// changes elsewhere
+#define KF_II_MAX 128.0
static int test_candidate_kf(TWO_PASS *twopass,
const FIRSTPASS_STATS *last_frame,
const FIRSTPASS_STATS *this_frame,
@@ -1811,11 +1818,11 @@ static int test_candidate_kf(TWO_PASS *twopass,
// Examine how well the key frame predicts subsequent frames.
for (i = 0; i < 16; ++i) {
- double next_iiratio = (IIKFACTOR1 * local_next_frame.intra_error /
+ double next_iiratio = (BOOST_FACTOR * local_next_frame.intra_error /
DOUBLE_DIVIDE_CHECK(local_next_frame.coded_error));
- if (next_iiratio > RMAX)
- next_iiratio = RMAX;
+ if (next_iiratio > KF_II_MAX)
+ next_iiratio = KF_II_MAX;
// Cumulative effect of decay in prediction quality.
if (local_next_frame.pcnt_inter > 0.85)
@@ -1870,7 +1877,9 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
FIRSTPASS_STATS next_frame;
FIRSTPASS_STATS last_frame;
int kf_bits = 0;
+ int loop_decay_counter = 0;
double decay_accumulator = 1.0;
+ double av_decay_accumulator = 0.0;
double zero_motion_accumulator = 1.0;
double boost_score = 0.0;
double kf_mod_err = 0.0;
@@ -2024,42 +2033,38 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
// Reset the first pass file position.
reset_fpf_position(twopass, start_position);
- // Scan through the kf group collating various stats used to deteermine
+ // Scan through the kf group collating various stats used to determine
// how many bits to spend on it.
decay_accumulator = 1.0;
boost_score = 0.0;
- for (i = 0; i < rc->frames_to_key; ++i) {
+ for (i = 0; i < (rc->frames_to_key - 1); ++i) {
if (EOF == input_stats(twopass, &next_frame))
break;
// Monitor for static sections.
- zero_motion_accumulator =MIN(zero_motion_accumulator,
- get_zero_motion_factor(&next_frame));
-
- // For the first few frames collect data to decide kf boost.
- if (i <= (rc->max_gf_interval * 2)) {
- double r;
- if (next_frame.intra_error > twopass->kf_intra_err_min)
- r = (IIKFACTOR2 * next_frame.intra_error /
- DOUBLE_DIVIDE_CHECK(next_frame.coded_error));
- else
- r = (IIKFACTOR2 * twopass->kf_intra_err_min /
- DOUBLE_DIVIDE_CHECK(next_frame.coded_error));
+ zero_motion_accumulator =
+ MIN(zero_motion_accumulator,
+ get_zero_motion_factor(&cpi->common, &next_frame));
- if (r > RMAX)
- r = RMAX;
+ // Not all frames in the group are necessarily used in calculating boost.
+ if ((i <= rc->max_gf_interval) ||
+ ((i <= (rc->max_gf_interval * 4)) && (decay_accumulator > 0.5))) {
+ const double frame_boost =
+ calc_frame_boost(cpi, this_frame, 0, KF_MAX_BOOST);
// How fast is prediction quality decaying.
if (!detect_flash(twopass, 0)) {
- const double loop_decay_rate = get_prediction_decay_rate(&cpi->common,
- &next_frame);
+ const double loop_decay_rate =
+ get_prediction_decay_rate(&cpi->common, &next_frame);
decay_accumulator *= loop_decay_rate;
decay_accumulator = MAX(decay_accumulator, MIN_DECAY_FACTOR);
+ av_decay_accumulator += decay_accumulator;
+ ++loop_decay_counter;
}
-
- boost_score += (decay_accumulator * r);
+ boost_score += (decay_accumulator * frame_boost);
}
}
+ av_decay_accumulator /= (double)loop_decay_counter;
reset_fpf_position(twopass, start_position);
@@ -2071,14 +2076,12 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
calculate_section_intra_ratio(start_position, twopass->stats_in_end,
rc->frames_to_key);
- // Work out how many bits to allocate for the key frame itself.
- rc->kf_boost = (int)boost_score;
-
- if (rc->kf_boost < (rc->frames_to_key * 3))
- rc->kf_boost = (rc->frames_to_key * 3);
- if (rc->kf_boost < MIN_KF_BOOST)
- rc->kf_boost = MIN_KF_BOOST;
+ // Apply various clamps for min and max boost
+ rc->kf_boost = (int)(av_decay_accumulator * boost_score);
+ rc->kf_boost = MAX(rc->kf_boost, (rc->frames_to_key * 3));
+ rc->kf_boost = MAX(rc->kf_boost, MIN_KF_BOOST);
+ // Work out how many bits to allocate for the key frame itself.
kf_bits = calculate_boost_bits((rc->frames_to_key - 1),
rc->kf_boost, twopass->kf_group_bits);
@@ -2216,11 +2219,6 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
vp9_clear_system_state();
- if (lc != NULL && twopass->kf_intra_err_min == 0) {
- twopass->kf_intra_err_min = KF_MB_INTRA_MIN * cpi->common.MBs;
- twopass->gf_intra_err_min = GF_MB_INTRA_MIN * cpi->common.MBs;
- }
-
if (cpi->oxcf.rc_mode == VPX_Q) {
twopass->active_worst_quality = cpi->oxcf.cq_level;
} else if (cm->current_video_frame == 0 ||
@@ -2286,6 +2284,18 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
rc->frames_till_gf_update_due = rc->baseline_gf_interval;
if (lc != NULL)
cpi->refresh_golden_frame = 1;
+
+#if ARF_STATS_OUTPUT
+ {
+ FILE *fpfile;
+ fpfile = fopen("arf.stt", "a");
+ ++arf_count;
+ fprintf(fpfile, "%10d %10d %10d %10ld\n",
+ cm->current_video_frame, rc->kf_boost, arf_count, rc->gfu_boost);
+
+ fclose(fpfile);
+ }
+#endif
}
configure_buffer_updates(cpi);
@@ -2325,6 +2335,7 @@ void vp9_twopass_postencode_update(VP9_COMP *cpi) {
if (cpi->common.frame_type != KEY_FRAME &&
!vp9_is_upper_layer_key_frame(cpi)) {
twopass->kf_group_bits -= bits_used;
+ twopass->last_kfgroup_zeromotion_pct = twopass->kf_zeromotion_pct;
}
twopass->kf_group_bits = MAX(twopass->kf_group_bits, 0);
diff --git a/vp9/encoder/vp9_firstpass.h b/vp9/encoder/vp9_firstpass.h
index aaa6b0311..0b82d32fa 100644
--- a/vp9/encoder/vp9_firstpass.h
+++ b/vp9/encoder/vp9_firstpass.h
@@ -93,8 +93,6 @@ typedef struct {
double modified_error_min;
double modified_error_max;
double modified_error_left;
- double kf_intra_err_min;
- double gf_intra_err_min;
#if CONFIG_FP_MB_STATS
uint8_t *frame_mb_stats_buf;
@@ -110,6 +108,7 @@ typedef struct {
int sr_update_lag;
int kf_zeromotion_pct;
+ int last_kfgroup_zeromotion_pct;
int gf_zeromotion_pct;
int active_worst_quality;
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index 94c0b64dd..9b6c77398 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -126,10 +126,10 @@ static void init_minq_luts(int *kf_low_m, int *kf_high_m,
int i;
for (i = 0; i < QINDEX_RANGE; i++) {
const double maxq = vp9_convert_qindex_to_q(i, bit_depth);
- kf_low_m[i] = get_minq_index(maxq, 0.000001, -0.0004, 0.125, bit_depth);
- kf_high_m[i] = get_minq_index(maxq, 0.000002, -0.0012, 0.50, bit_depth);
+ kf_low_m[i] = get_minq_index(maxq, 0.000001, -0.0004, 0.150, bit_depth);
+ kf_high_m[i] = get_minq_index(maxq, 0.0000021, -0.00125, 0.55, bit_depth);
arfgf_low[i] = get_minq_index(maxq, 0.0000015, -0.0009, 0.30, bit_depth);
- arfgf_high[i] = get_minq_index(maxq, 0.0000021, -0.00125, 0.50, bit_depth);
+ arfgf_high[i] = get_minq_index(maxq, 0.0000021, -0.00125, 0.55, bit_depth);
inter[i] = get_minq_index(maxq, 0.00000271, -0.00113, 0.90, bit_depth);
rtc[i] = get_minq_index(maxq, 0.00000271, -0.00113, 0.70, bit_depth);
}
@@ -175,7 +175,7 @@ int vp9_rc_bits_per_mb(FRAME_TYPE frame_type, int qindex,
double correction_factor,
vpx_bit_depth_t bit_depth) {
const double q = vp9_convert_qindex_to_q(qindex, bit_depth);
- int enumerator = frame_type == KEY_FRAME ? 3300000 : 2250000;
+ int enumerator = frame_type == KEY_FRAME ? 2700000 : 1800000;
// q based adjustment to baseline enumerator
enumerator += (int)(enumerator * q) >> 12;
@@ -610,7 +610,7 @@ static int rc_pick_q_and_bounds_one_pass_cbr(const VP9_COMP *cpi,
if (frame_is_intra_only(cm)) {
active_best_quality = rc->best_quality;
- // Handle the special case for key frames forced when we have75 reached
+ // Handle the special case for key frames forced when we have reached
// the maximum key frame interval. Here force the Q to a range
// based on the ambient Q to reduce the risk of popping.
if (rc->this_key_frame_forced) {
@@ -880,6 +880,7 @@ static int rc_pick_q_and_bounds_one_pass_vbr(const VP9_COMP *cpi,
return q;
}
+#define STATIC_MOTION_THRESH 95
static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi,
int *bottom_index,
int *top_index) {
@@ -894,16 +895,31 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi,
ASSIGN_MINQ_TABLE(cm->bit_depth, inter_minq);
if (frame_is_intra_only(cm) || vp9_is_upper_layer_key_frame(cpi)) {
- // Handle the special case for key frames forced when we have75 reached
+ // Handle the special case for key frames forced when we have reached
// the maximum key frame interval. Here force the Q to a range
// based on the ambient Q to reduce the risk of popping.
if (rc->this_key_frame_forced) {
- int qindex = rc->last_boosted_qindex;
- double last_boosted_q = vp9_convert_qindex_to_q(qindex, cm->bit_depth);
- int delta_qindex = vp9_compute_qdelta(rc, last_boosted_q,
- last_boosted_q * 0.75,
- cm->bit_depth);
- active_best_quality = MAX(qindex + delta_qindex, rc->best_quality);
+ double last_boosted_q;
+ int delta_qindex;
+ int qindex;
+
+ if (cpi->twopass.last_kfgroup_zeromotion_pct >= STATIC_MOTION_THRESH) {
+ qindex = MIN(rc->last_kf_qindex, rc->last_boosted_qindex);
+ active_best_quality = qindex;
+ last_boosted_q = vp9_convert_qindex_to_q(qindex, cm->bit_depth);
+ delta_qindex = vp9_compute_qdelta(rc, last_boosted_q,
+ last_boosted_q * 1.25,
+ cm->bit_depth);
+ active_worst_quality = MIN(qindex + delta_qindex, active_worst_quality);
+
+ } else {
+ qindex = rc->last_boosted_qindex;
+ last_boosted_q = vp9_convert_qindex_to_q(qindex, cm->bit_depth);
+ delta_qindex = vp9_compute_qdelta(rc, last_boosted_q,
+ last_boosted_q * 0.75,
+ cm->bit_depth);
+ active_best_quality = MAX(qindex + delta_qindex, rc->best_quality);
+ }
} else {
// Not forced keyframe.
double q_adj_factor = 1.0;
@@ -972,18 +988,12 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi,
}
}
- // Clip the active best and worst quality values to limits.
- active_best_quality = clamp(active_best_quality,
- rc->best_quality, rc->worst_quality);
- active_worst_quality = clamp(active_worst_quality,
- active_best_quality, rc->worst_quality);
-
- *top_index = active_worst_quality;
- *bottom_index = active_best_quality;
-
#if LIMIT_QRANGE_FOR_ALTREF_AND_KEY
vp9_clear_system_state();
- {
+ // Static forced key frames Q restrictions dealt with elsewhere.
+ if (!((frame_is_intra_only(cm) || vp9_is_upper_layer_key_frame(cpi))) ||
+ !rc->this_key_frame_forced ||
+ (cpi->twopass.last_kfgroup_zeromotion_pct < STATIC_MOTION_THRESH)) {
const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
const double rate_factor_deltas[RATE_FACTOR_LEVELS] = {
1.00, // INTER_NORMAL
@@ -997,27 +1007,43 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi,
int qdelta = vp9_compute_qdelta_by_rate(&cpi->rc, cm->frame_type,
active_worst_quality, rate_factor,
cm->bit_depth);
- *top_index = active_worst_quality + qdelta;
- *top_index = (*top_index > *bottom_index) ? *top_index : *bottom_index;
+ active_worst_quality = active_worst_quality + qdelta;
+ active_worst_quality = MAX(active_worst_quality, active_best_quality);
}
#endif
+ // Clip the active best and worst quality values to limits.
+ active_best_quality = clamp(active_best_quality,
+ rc->best_quality, rc->worst_quality);
+ active_worst_quality = clamp(active_worst_quality,
+ active_best_quality, rc->worst_quality);
+
if (oxcf->rc_mode == VPX_Q) {
q = active_best_quality;
// Special case code to try and match quality with forced key frames.
- } else if ((cm->frame_type == KEY_FRAME) && rc->this_key_frame_forced) {
- q = rc->last_boosted_qindex;
+ } else if ((frame_is_intra_only(cm) || vp9_is_upper_layer_key_frame(cpi)) &&
+ rc->this_key_frame_forced) {
+ // If static since last kf use better of last boosted and last kf q.
+ if (cpi->twopass.last_kfgroup_zeromotion_pct >= STATIC_MOTION_THRESH) {
+ q = MIN(rc->last_kf_qindex, rc->last_boosted_qindex);
+ } else {
+ q = rc->last_boosted_qindex;
+ }
} else {
q = vp9_rc_regulate_q(cpi, rc->this_frame_target,
active_best_quality, active_worst_quality);
- if (q > *top_index) {
+ if (q > active_worst_quality) {
// Special case when we are targeting the max allowed rate.
if (rc->this_frame_target >= rc->max_frame_bandwidth)
- *top_index = q;
+ active_worst_quality = q;
else
- q = *top_index;
+ q = active_worst_quality;
}
}
+ clamp(q, active_best_quality, active_worst_quality);
+
+ *top_index = active_worst_quality;
+ *bottom_index = active_best_quality;
assert(*top_index <= rc->worst_quality &&
*top_index >= rc->best_quality);
@@ -1161,11 +1187,12 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) {
// better than that already stored.
// This is used to help set quality in forced key frames to reduce popping
if ((qindex < rc->last_boosted_qindex) ||
- ((cpi->static_mb_pct < 100) &&
- ((cm->frame_type == KEY_FRAME) || cpi->refresh_alt_ref_frame ||
+ (((cm->frame_type == KEY_FRAME) || cpi->refresh_alt_ref_frame ||
(cpi->refresh_golden_frame && !rc->is_src_frame_alt_ref)))) {
rc->last_boosted_qindex = qindex;
}
+ if (cm->frame_type == KEY_FRAME)
+ rc->last_kf_qindex = qindex;
update_buffer_level(cpi, rc->projected_frame_size);
diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h
index 2ced8e6dd..edfb9fce9 100644
--- a/vp9/encoder/vp9_ratectrl.h
+++ b/vp9/encoder/vp9_ratectrl.h
@@ -42,6 +42,7 @@ typedef struct {
int sb64_target_rate;
int last_q[FRAME_TYPES]; // Separate values for Intra/Inter
int last_boosted_qindex; // Last boosted GF/KF/ARF q
+ int last_kf_qindex; // Q index of the last key frame coded.
int gfu_boost;
int last_boost;