ref: 944ede0285215f6dbdc4d47a1c896e7f7e3e212c
parent: c70552c01ed48f46ba9f6ba41c9555b34fd37bce
author: Jim Bankoski <[email protected]>
date: Fri Jul 6 11:45:34 EDT 2018
Make Sharpness parameter affect visual sharpness 1: Lower rdmult used in trellis optimization 2: Shut off the end of block optimization that tries end of block at every sub position if any of the coefficients are > 1. 3: Change the rounding and zbin factor according to sharpness. 4: Disable the skip block check that calculates RD using SSE from predictor. Change-Id: I247b61a26fa22f12f8b684e7cd6d4e368de7c3e4
--- a/test/vpxenc.sh
+++ b/test/vpxenc.sh
@@ -429,6 +429,42 @@
fi
}
+vpxenc_vp9_webm_sharpness() {
+ if [ "$(vpxenc_can_encode_vp9)" = "yes" ]; then
+ local sharpnesses="0 1 2 3 4 5 6 7"
+ local output="${VPX_TEST_OUTPUT_DIR}/vpxenc_vp9_webm_sharpness.ivf"
+ local last_size=0
+ local this_size=0
+
+ for sharpness in ${sharpnesses}; do
+
+ vpxenc $(yuv_input_hantro_collage) \
+ --sharpness="${sharpness}" \
+ --codec=vp9 \
+ --limit=1 \
+ --cpu-used=2 \
+ --end-usage=q \
+ --cq-level=40 \
+ --output="${output}" \
+ "${passes}"
+
+ if [ ! -e "${output}" ]; then
+ elog "Output file does not exist."
+ return 1
+ fi
+
+ this_size=$(stat -c '%s' "${output}")
+ if [ "${this_size}" -lt "${last_size}" ]; then
+ elog "Higher sharpness value yielded lower file size."
+ echo "${this_size}" " < " "${last_size}"
+ return 1
+ fi
+ last_size="${this_size}"
+
+ done
+ fi
+}
+
vpxenc_tests="vpxenc_vp8_ivf
vpxenc_vp8_webm
vpxenc_vp8_webm_rt
@@ -441,7 +477,9 @@
vpxenc_vp9_ivf_lossless
vpxenc_vp9_ivf_minq0_maxq0
vpxenc_vp9_webm_lag10_frames20
- vpxenc_vp9_webm_non_square_par"
+ vpxenc_vp9_webm_non_square_par
+ vpxenc_vp9_webm_sharpness"
+
if [ "$(vpx_config_option_enabled CONFIG_REALTIME_ONLY)" != "yes" ]; then
vpxenc_tests="$vpxenc_tests
vpxenc_vp8_webm_2pass
--- a/vp9/encoder/vp9_block.h
+++ b/vp9/encoder/vp9_block.h
@@ -116,6 +116,12 @@
int *nmvsadcost_hp[2];
int **mvsadcost;
+ // sharpness is used to disable skip mode and change rd_mult
+ int sharpness;
+
+ // aq mode is used to adjust rd based on segment.
+ int adjust_rdmult_by_segment;
+
// These define limits to motion vector components to prevent them
// from extending outside the UMV borders
MvLimits mv_limits;
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -5475,6 +5475,8 @@
x->optimize = sf->optimize_coefficients == 1 && cpi->oxcf.pass != 1;
#endif
if (xd->lossless) x->optimize = 0;
+ x->sharpness = cpi->oxcf.sharpness;
+ x->adjust_rdmult_by_segment = (cpi->oxcf.aq_mode == VARIANCE_AQ);
cm->tx_mode = select_tx_mode(cpi, xd);
--- a/vp9/encoder/vp9_encodemb.c
+++ b/vp9/encoder/vp9_encodemb.c
@@ -77,13 +77,19 @@
const scan_order *const so = get_scan(xd, tx_size, plane_type, block);
const int16_t *const scan = so->scan;
const int16_t *const nb = so->neighbors;
+ const MODE_INFO *mbmi = xd->mi[0];
+ const int sharpness = mb->sharpness;
+ const int64_t rdadj = (int64_t)mb->rdmult * plane_rd_mult[ref][plane_type];
const int64_t rdmult =
- ((int64_t)mb->rdmult * plane_rd_mult[ref][plane_type]) >> 1;
+ (sharpness == 0 ? rdadj >> 1
+ : (rdadj * (8 - sharpness + mbmi->segment_id)) >> 4);
+
const int64_t rddiv = mb->rddiv;
int64_t rd_cost0, rd_cost1;
int64_t rate0, rate1;
int16_t t0, t1;
int i, final_eob;
+ int count_high_values_after_eob = 0;
#if CONFIG_VP9_HIGHBITDEPTH
const uint16_t *cat6_high_cost = vp9_get_high_cost_table(xd->bd);
#else
@@ -263,6 +269,7 @@
assert(distortion0 <= distortion_for_zero);
token_cache[rc] = vp9_pt_energy_class[t0];
}
+ if (sharpness > 0 && abs(qcoeff[rc]) > 1) count_high_values_after_eob++;
assert(accu_error >= 0);
x_prev = qcoeff[rc]; // Update based on selected quantized value.
@@ -273,6 +280,7 @@
if (best_eob_cost_cur < best_block_rd_cost) {
best_block_rd_cost = best_eob_cost_cur;
final_eob = i + 1;
+ count_high_values_after_eob = 0;
if (use_x1) {
before_best_eob_qc = x1;
before_best_eob_dqc = dqc1;
@@ -284,19 +292,31 @@
}
}
}
- assert(final_eob <= eob);
- if (final_eob > 0) {
- int rc;
- assert(before_best_eob_qc != 0);
- i = final_eob - 1;
- rc = scan[i];
- qcoeff[rc] = before_best_eob_qc;
- dqcoeff[rc] = before_best_eob_dqc;
- }
- for (i = final_eob; i < eob; i++) {
- int rc = scan[i];
- qcoeff[rc] = 0;
- dqcoeff[rc] = 0;
+ if (count_high_values_after_eob > 0) {
+ final_eob = eob - 1;
+ for (; final_eob >= 0; final_eob--) {
+ const int rc = scan[final_eob];
+ const int x = qcoeff[rc];
+ if (x) {
+ break;
+ }
+ }
+ final_eob++;
+ } else {
+ assert(final_eob <= eob);
+ if (final_eob > 0) {
+ int rc;
+ assert(before_best_eob_qc != 0);
+ i = final_eob - 1;
+ rc = scan[i];
+ qcoeff[rc] = before_best_eob_qc;
+ dqcoeff[rc] = before_best_eob_dqc;
+ }
+ for (i = final_eob; i < eob; i++) {
+ int rc = scan[i];
+ qcoeff[rc] = 0;
+ dqcoeff[rc] = 0;
+ }
}
mb->plane[plane].eobs[block] = final_eob;
return final_eob;
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -1876,6 +1876,7 @@
int last_w = cpi->oxcf.width;
int last_h = cpi->oxcf.height;
+ vp9_init_quantizer(cpi);
if (cm->profile != oxcf->profile) cm->profile = oxcf->profile;
cm->bit_depth = oxcf->bit_depth;
cm->color_space = oxcf->color_space;
--- a/vp9/encoder/vp9_picklpf.c
+++ b/vp9/encoder/vp9_picklpf.c
@@ -150,7 +150,7 @@
VP9_COMMON *const cm = &cpi->common;
struct loopfilter *const lf = &cm->lf;
- lf->sharpness_level = cm->frame_type == KEY_FRAME ? 0 : cpi->oxcf.sharpness;
+ lf->sharpness_level = 0;
if (method == LPF_PICK_MINIMAL_LPF && lf->filter_level) {
lf->filter_level = 0;
--- a/vp9/encoder/vp9_quantize.c
+++ b/vp9/encoder/vp9_quantize.c
@@ -220,13 +220,20 @@
int i, q, quant;
for (q = 0; q < QINDEX_RANGE; q++) {
- const int qzbin_factor = get_qzbin_factor(q, cm->bit_depth);
- const int qrounding_factor = q == 0 ? 64 : 48;
+ int qzbin_factor = get_qzbin_factor(q, cm->bit_depth);
+ int qrounding_factor = q == 0 ? 64 : 48;
+ const int sharpness_adjustment = 16 * (7 - cpi->oxcf.sharpness) / 7;
+ if (cpi->oxcf.sharpness > 0 && q > 0) {
+ qzbin_factor = 64 + sharpness_adjustment;
+ qrounding_factor = 64 - sharpness_adjustment;
+ }
+
for (i = 0; i < 2; ++i) {
int qrounding_factor_fp = i == 0 ? 48 : 42;
if (q == 0) qrounding_factor_fp = 64;
-
+ if (cpi->oxcf.sharpness > 0)
+ qrounding_factor_fp = 64 - sharpness_adjustment;
// y
quant = i == 0 ? vp9_dc_quant(q, cm->y_dc_delta_q, cm->bit_depth)
: vp9_ac_quant(q, 0, cm->bit_depth);
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -763,7 +763,8 @@
rd = VPXMIN(rd1, rd2);
if (plane == 0) {
x->zcoeff_blk[tx_size][block] =
- !x->plane[plane].eobs[block] || (rd1 > rd2 && !xd->lossless);
+ !x->plane[plane].eobs[block] ||
+ (x->sharpness == 0 && rd1 > rd2 && !xd->lossless);
x->sum_y_eobs[tx_size] += x->plane[plane].eobs[block];
}