summaryrefslogtreecommitdiff
path: root/vp9/encoder
diff options
context:
space:
mode:
authorPaul Wilkins <paulwilkins@google.com>2015-01-20 15:23:57 -0800
committerPaul Wilkins <paulwilkins@google.com>2015-01-26 14:55:36 -0800
commitfd070220ff9bb531acd0ba7c67b84684aad0ef50 (patch)
tree718dc82aa3a8669998a798163569475c3c523168 /vp9/encoder
parent9f6eba419a876598aa7edaee9e99610fcbf6362b (diff)
downloadlibvpx-fd070220ff9bb531acd0ba7c67b84684aad0ef50.tar
libvpx-fd070220ff9bb531acd0ba7c67b84684aad0ef50.tar.gz
libvpx-fd070220ff9bb531acd0ba7c67b84684aad0ef50.tar.bz2
libvpx-fd070220ff9bb531acd0ba7c67b84684aad0ef50.zip
Adjust active maxq for GF groups.
Currently disabled by default: enabled using #define GROUP_ADAPTIVE_MAXQ In this patch the active max Q is adjusted for each GF group based on the vbr bit allocation and raw first pass group error. This will tend to give a lower q for easy sections and a higher value for very hard sections. As such it is expected to improve quality in some of the easier sections where quality issues have been reported. This change tends to hurt overall psnr but help average psnr. SSIM also shows a small gain. Average results for derf, yt, std-hd and yt-hd test sets were as follows (%change for average psnr, overal psnr and ssim):- derf +0.291, - 0.252, -0.021 yt +6.466, -1.436, +0.552 std-hd +0.490, +0.014, +0.380 yt-hd +5.565, - 1.573, +0.099 Change-Id: Icc015499cebbf2a45054a05e8e31f3dfb43f944a
Diffstat (limited to 'vp9/encoder')
-rw-r--r--vp9/encoder/vp9_firstpass.c88
-rw-r--r--vp9/encoder/vp9_firstpass.h5
2 files changed, 77 insertions, 16 deletions
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index 3b0f2f012..9fc63e3f0 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -38,6 +38,8 @@
#define OUTPUT_FPF 0
#define ARF_STATS_OUTPUT 0
+#define GROUP_ADAPTIVE_MAXQ 0
+
#define BOOST_BREAKOUT 12.5
#define BOOST_FACTOR 12.5
#define ERR_DIVISOR 128.0
@@ -54,6 +56,7 @@
#define NEW_MV_MODE_PENALTY 32
#define SVC_FACTOR_PT_LOW 0.45
#define DARK_THRESH 64
+#define DEFAULT_GRP_WEIGHT 1.0
#define DOUBLE_DIVIDE_CHECK(x) ((x) < 0 ? (x) - 0.000001 : (x) + 0.000001)
@@ -1082,8 +1085,9 @@ static double calc_correction_factor(double err_per_mb,
#define EDIV_SIZE_FACTOR 800
static int get_twopass_worst_quality(const VP9_COMP *cpi,
- const FIRSTPASS_STATS *stats,
- int section_target_bandwidth) {
+ const double section_err,
+ int section_target_bandwidth,
+ double group_weight_factor) {
const RATE_CONTROL *const rc = &cpi->rc;
const VP9EncoderConfig *const oxcf = &cpi->oxcf;
@@ -1092,7 +1096,6 @@ static int get_twopass_worst_quality(const VP9_COMP *cpi,
} else {
const int num_mbs = (cpi->oxcf.resize_mode != RESIZE_NONE)
? cpi->initial_mbs : cpi->common.MBs;
- const double section_err = stats->coded_error / stats->count;
const double err_per_mb = section_err / num_mbs;
const double speed_term = 1.0 + 0.04 * oxcf->speed;
const double ediv_size_correction = num_mbs / EDIV_SIZE_FACTOR;
@@ -1101,9 +1104,11 @@ static int get_twopass_worst_quality(const VP9_COMP *cpi,
int q;
int is_svc_upper_layer = 0;
+
if (is_two_pass_svc(cpi) && cpi->svc.spatial_layer_id > 0)
is_svc_upper_layer = 1;
+
// Try and pick a max Q that will be high enough to encode the
// content at the given rate.
for (q = rc->best_quality; q < rc->worst_quality; ++q) {
@@ -1113,9 +1118,10 @@ static int get_twopass_worst_quality(const VP9_COMP *cpi,
is_svc_upper_layer ? SVC_FACTOR_PT_LOW :
FACTOR_PT_LOW, FACTOR_PT_HIGH, q,
cpi->common.bit_depth);
- const int bits_per_mb = vp9_rc_bits_per_mb(INTER_FRAME, q,
- factor * speed_term,
- cpi->common.bit_depth);
+ const int bits_per_mb =
+ vp9_rc_bits_per_mb(INTER_FRAME, q,
+ factor * speed_term * group_weight_factor,
+ cpi->common.bit_depth);
if (bits_per_mb <= target_norm_bits_per_mb)
break;
}
@@ -1699,6 +1705,9 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
double boost_score = 0.0;
double old_boost_score = 0.0;
double gf_group_err = 0.0;
+#if GROUP_ADAPTIVE_MAXQ
+ double gf_group_raw_error = 0.0;
+#endif
double gf_first_frame_err = 0.0;
double mod_frame_err = 0.0;
@@ -1742,8 +1751,12 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
// If this is a key frame or the overlay from a previous arf then
// the error score / cost of this frame has already been accounted for.
- if (cpi->common.frame_type == KEY_FRAME || rc->source_alt_ref_active)
+ if (cpi->common.frame_type == KEY_FRAME || rc->source_alt_ref_active) {
gf_group_err -= gf_first_frame_err;
+#if GROUP_ADAPTIVE_MAXQ
+ gf_group_raw_error -= this_frame->coded_error;
+#endif
+ }
// Motion breakout threshold for loop below depends on image size.
mv_ratio_accumulator_thresh =
@@ -1782,6 +1795,9 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
// Accumulate error score of frames in this gf group.
mod_frame_err = calculate_modified_err(twopass, oxcf, this_frame);
gf_group_err += mod_frame_err;
+#if GROUP_ADAPTIVE_MAXQ
+ gf_group_raw_error += this_frame->coded_error;
+#endif
if (EOF == input_stats(twopass, &next_frame))
break;
@@ -1863,6 +1879,9 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
if (EOF == input_stats(twopass, this_frame))
break;
gf_group_err += calculate_modified_err(twopass, oxcf, this_frame);
+#if GROUP_ADAPTIVE_MAXQ
+ gf_group_raw_error += this_frame->coded_error;
+#endif
}
rc->baseline_gf_interval = new_gf_interval;
}
@@ -1893,6 +1912,29 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
// Calculate the bits to be allocated to the gf/arf group as a whole
gf_group_bits = calculate_total_gf_group_bits(cpi, gf_group_err);
+#if GROUP_ADAPTIVE_MAXQ
+ // Calculate an estimate of the maxq needed for the group.
+ // We are more agressive about correcting for sections
+ // where there could be significant overshoot than for easier
+ // sections where we do not wish to risk creating an overshoot
+ // of the allocated bit budget.
+ if ((cpi->oxcf.rc_mode != VPX_Q) && (rc->baseline_gf_interval > 1)) {
+ const int vbr_group_bits_per_frame =
+ (int)(gf_group_bits / rc->baseline_gf_interval);
+ const double group_av_err = gf_group_raw_error / rc->baseline_gf_interval;
+ const int tmp_q =
+ get_twopass_worst_quality(cpi, group_av_err, vbr_group_bits_per_frame,
+ twopass->kfgroup_inter_fraction);
+
+ if (tmp_q < twopass->baseline_worst_quality) {
+ twopass->active_worst_quality =
+ (tmp_q + twopass->baseline_worst_quality + 1) / 2;
+ } else {
+ twopass->active_worst_quality = tmp_q;
+ }
+ }
+#endif
+
// Calculate the extra bits to be used for boosted frame(s)
gf_arf_bits = calculate_boost_bits(rc->baseline_gf_interval,
rc->gfu_boost, gf_group_bits);
@@ -2116,7 +2158,7 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
// Reset to the start of the group.
reset_fpf_position(twopass, start_position);
- kf_group_err = 0;
+ kf_group_err = 0.0;
// Rescan to get the correct error data for the forced kf group.
for (i = 0; i < rc->frames_to_key; ++i) {
@@ -2226,6 +2268,16 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
kf_bits = calculate_boost_bits((rc->frames_to_key - 1),
rc->kf_boost, twopass->kf_group_bits);
+ // Work out the fraction of the kf group bits reserved for the inter frames
+ // within the group after discounting the bits for the kf itself.
+ if (twopass->kf_group_bits) {
+ twopass->kfgroup_inter_fraction =
+ (double)(twopass->kf_group_bits - kf_bits) /
+ (double)twopass->kf_group_bits;
+ } else {
+ twopass->kfgroup_inter_fraction = 1.0;
+ }
+
twopass->kf_group_bits -= kf_bits;
// Save the bits to spend on the key frame.
@@ -2316,7 +2368,6 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
GF_GROUP *const gf_group = &twopass->gf_group;
int frames_left;
FIRSTPASS_STATS this_frame;
- FIRSTPASS_STATS this_frame_copy;
int target_rate;
LAYER_CONTEXT *const lc = is_two_pass_svc(cpi) ?
@@ -2374,9 +2425,14 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
// Special case code for first frame.
const int section_target_bandwidth = (int)(twopass->bits_left /
frames_left);
- const int tmp_q = get_twopass_worst_quality(cpi, &twopass->total_left_stats,
- section_target_bandwidth);
+ const double section_error =
+ twopass->total_left_stats.coded_error / twopass->total_left_stats.count;
+ const int tmp_q =
+ get_twopass_worst_quality(cpi, section_error,
+ section_target_bandwidth, DEFAULT_GRP_WEIGHT);
+
twopass->active_worst_quality = tmp_q;
+ twopass->baseline_worst_quality = tmp_q;
rc->ni_av_qi = tmp_q;
rc->last_q[INTER_FRAME] = tmp_q;
rc->avg_q = vp9_convert_qindex_to_q(tmp_q, cm->bit_depth);
@@ -2388,13 +2444,13 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
if (EOF == input_stats(twopass, &this_frame))
return;
- // Local copy of the current frame's first pass stats.
- this_frame_copy = this_frame;
-
// Keyframe and section processing.
if (rc->frames_to_key == 0 || (cpi->frame_flags & FRAMEFLAGS_KEY)) {
+ FIRSTPASS_STATS this_frame_copy;
+ this_frame_copy = this_frame;
// Define next KF group and assign bits to it.
- find_next_key_frame(cpi, &this_frame_copy);
+ find_next_key_frame(cpi, &this_frame);
+ this_frame = this_frame_copy;
} else {
cm->frame_type = INTER_FRAME;
}
@@ -2423,7 +2479,7 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
// Define a new GF/ARF group. (Should always enter here for key frames).
if (rc->frames_till_gf_update_due == 0) {
- define_gf_group(cpi, &this_frame_copy);
+ define_gf_group(cpi, &this_frame);
rc->frames_till_gf_update_due = rc->baseline_gf_interval;
if (lc != NULL)
diff --git a/vp9/encoder/vp9_firstpass.h b/vp9/encoder/vp9_firstpass.h
index a8e4987cc..34767706a 100644
--- a/vp9/encoder/vp9_firstpass.h
+++ b/vp9/encoder/vp9_firstpass.h
@@ -109,11 +109,16 @@ typedef struct {
// Error score of frames still to be coded in kf group
int64_t kf_group_error_left;
+
+ // The fraction for a kf groups total bits allocated to the inter frames
+ double kfgroup_inter_fraction;
+
int sr_update_lag;
int kf_zeromotion_pct;
int last_kfgroup_zeromotion_pct;
int gf_zeromotion_pct;
+ int baseline_worst_quality;
int active_worst_quality;
int extend_minq;
int extend_maxq;