ref: aec12b097630b9751bcf33306b4f4291c6b98b67
parent: bb01ac96ecee7aa62e4ef1fbf1bdf9518e72e687
author: Jingning Han <jingning@google.com>
date: Fri Mar 15 07:42:39 EDT 2019
Setup AQ mode for perceptual quality Adapt the quantization to provide higher quality at smooth regions where the Wiener variance is smaller. Change-Id: Ibfd594d1de2ba34d2440d0aa7991b0fdac057ea5
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -3594,7 +3594,7 @@
wiener_variance += cpi->mb_wiener_variance[row * cm->mb_cols + col];
kmeans_data = &cpi->kmeans_data_arr[cpi->kmeans_data_size++];
- kmeans_data->value = log(1 + wiener_variance);
+ kmeans_data->value = log(1.0 + wiener_variance) / log(2.0);
kmeans_data->pos = mi_row * cpi->kmeans_data_stride + mi_col;
if (wiener_variance)
wiener_variance /=
@@ -5874,17 +5874,23 @@
}
// Frame segmentation
- if (cpi->sf.enable_wiener_variance && cm->show_frame) {
- int mi_row, mi_col;
- cpi->kmeans_data_size = 0;
- cpi->kmeans_ctr_num = 5;
+ if (cpi->sf.enable_wiener_variance) {
+ vp9_disable_segmentation(&cm->seg);
+ if (cm->show_frame) {
+ int mi_row, mi_col;
+ cpi->kmeans_data_size = 0;
+ cpi->kmeans_ctr_num = 5;
- for (mi_row = 0; mi_row < cm->mi_rows; mi_row += MI_BLOCK_SIZE)
- for (mi_col = 0; mi_col < cm->mi_cols; mi_col += MI_BLOCK_SIZE)
- wiener_var_rdmult(cpi, BLOCK_64X64, mi_row, mi_col, cpi->rd.RDMULT);
+ for (mi_row = 0; mi_row < cm->mi_rows; mi_row += MI_BLOCK_SIZE)
+ for (mi_col = 0; mi_col < cm->mi_cols; mi_col += MI_BLOCK_SIZE)
+ wiener_var_rdmult(cpi, BLOCK_64X64, mi_row, mi_col, cpi->rd.RDMULT);
- vp9_kmeans(cpi->kmeans_ctr_ls, cpi->kmeans_boundary_ls, cpi->kmeans_ctr_num,
- cpi->kmeans_data_arr, cpi->kmeans_data_size);
+ vp9_kmeans(cpi->kmeans_ctr_ls, cpi->kmeans_boundary_ls,
+ cpi->kmeans_ctr_num, cpi->kmeans_data_arr,
+ cpi->kmeans_data_size);
+
+ vp9_perceptual_aq_mode_setup(cpi, &cm->seg);
+ }
}
{
--- a/vp9/encoder/vp9_segmentation.c
+++ b/vp9/encoder/vp9_segmentation.c
@@ -9,6 +9,7 @@
*/
#include <limits.h>
+#include <math.h>
#include "vpx_mem/vpx_mem.h"
@@ -55,6 +56,46 @@
for (i = 0; i < MAX_SEGMENTS; ++i) {
vp9_set_segdata(seg, i, SEG_LVL_ALT_Q, 2 * (i - (MAX_SEGMENTS / 2)));
+ vp9_enable_segfeature(seg, i, SEG_LVL_ALT_Q);
+ }
+}
+
+void vp9_perceptual_aq_mode_setup(struct VP9_COMP *cpi,
+ struct segmentation *seg) {
+ const VP9_COMMON *cm = &cpi->common;
+ const int seg_counts = cpi->kmeans_ctr_num;
+ const int base_qindex = cm->base_qindex;
+ const double base_qstep = vp9_convert_qindex_to_q(base_qindex, cm->bit_depth);
+ const double mid_ctr = cpi->kmeans_ctr_ls[seg_counts / 2];
+ const double var_diff_scale = 8.0;
+ int i;
+
+ assert(seg_counts <= MAX_SEGMENTS);
+
+ vp9_enable_segmentation(seg);
+ vp9_clearall_segfeatures(seg);
+ seg->abs_delta = SEGMENT_DELTADATA;
+
+ for (i = 0; i < seg_counts / 2; ++i) {
+ double wiener_var_diff = mid_ctr - cpi->kmeans_ctr_ls[i];
+ double target_qstep = base_qstep / (1.0 + wiener_var_diff / var_diff_scale);
+ int target_qindex = vp9_convert_q_to_qindex(target_qstep, cm->bit_depth);
+ assert(wiener_var_diff >= 0.0);
+
+ vp9_set_segdata(seg, i, SEG_LVL_ALT_Q, target_qindex - base_qindex);
+ vp9_enable_segfeature(seg, i, SEG_LVL_ALT_Q);
+ }
+
+ vp9_set_segdata(seg, i, SEG_LVL_ALT_Q, 0);
+ vp9_enable_segfeature(seg, i, SEG_LVL_ALT_Q);
+
+ for (; i < seg_counts; ++i) {
+ double wiener_var_diff = cpi->kmeans_ctr_ls[i] - mid_ctr;
+ double target_qstep = base_qstep * (1.0 + wiener_var_diff / var_diff_scale);
+ int target_qindex = vp9_convert_q_to_qindex(target_qstep, cm->bit_depth);
+ assert(wiener_var_diff >= 0.0);
+
+ vp9_set_segdata(seg, i, SEG_LVL_ALT_Q, target_qindex - base_qindex);
vp9_enable_segfeature(seg, i, SEG_LVL_ALT_Q);
}
}
--- a/vp9/encoder/vp9_segmentation.h
+++ b/vp9/encoder/vp9_segmentation.h
@@ -28,6 +28,9 @@
void vp9_psnr_aq_mode_setup(struct segmentation *seg);
+void vp9_perceptual_aq_mode_setup(struct VP9_COMP *cpi,
+ struct segmentation *seg);
+
// The values given for each segment can be either deltas (from the default
// value chosen for the frame) or absolute values.
//