summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Wilkins <paulwilkins@google.com>2014-11-07 16:32:50 +0000
committerPaul Wilkins <paulwilkins@google.com>2014-11-20 16:23:35 -0800
commitd0312379991b81f2aec5a1fa4a50406ca764cdee (patch)
treec9c4838405f185adde18b7777b113bcd727627ff
parent3d1e8c9a85d0bb16049cb1622f1d2d9a034c5379 (diff)
downloadlibvpx-d0312379991b81f2aec5a1fa4a50406ca764cdee.tar
libvpx-d0312379991b81f2aec5a1fa4a50406ca764cdee.tar.gz
libvpx-d0312379991b81f2aec5a1fa4a50406ca764cdee.tar.bz2
libvpx-d0312379991b81f2aec5a1fa4a50406ca764cdee.zip
Add variance restriction to AQ2.
Add an additional restriction to bit/complexity based segmentation based on spatial variance. Only lower Q when both the number of bits spent in the initial encoding pass and the spatial complexity are below a threshold. This will prevent the low Q segments being used just because there is a surfeit of bits. Small metrics gains especially opsnr. derf ~0.2% std-hd ~0.3% Change-Id: I6a8496d466d673f9b0e2b2ca6304ea7b6d8e1cce
-rw-r--r--vp9/encoder/vp9_aq_complexity.c15
-rw-r--r--vp9/encoder/vp9_aq_complexity.h4
-rw-r--r--vp9/encoder/vp9_aq_variance.c10
-rw-r--r--vp9/encoder/vp9_aq_variance.h1
-rw-r--r--vp9/encoder/vp9_encodeframe.c6
5 files changed, 23 insertions, 13 deletions
diff --git a/vp9/encoder/vp9_aq_complexity.c b/vp9/encoder/vp9_aq_complexity.c
index f7fca0cde..3762c53d7 100644
--- a/vp9/encoder/vp9_aq_complexity.c
+++ b/vp9/encoder/vp9_aq_complexity.c
@@ -11,8 +11,9 @@
#include <limits.h>
#include <math.h>
+#include "vp9/encoder/vp9_aq_variance.h"
+#include "vp9/encoder/vp9_encodeframe.h"
#include "vp9/common/vp9_seg_common.h"
-
#include "vp9/encoder/vp9_segmentation.h"
#define AQ_C_SEGMENTS 3
@@ -22,6 +23,7 @@ static const double aq_c_q_adj_factor[AQ_C_STRENGTHS][AQ_C_SEGMENTS] =
{{1.0, 1.0, 1.0}, {1.0, 2.0, 1.0}, {1.0, 1.5, 2.5}};
static const double aq_c_transitions[AQ_C_STRENGTHS][AQ_C_SEGMENTS] =
{{1.0, 1.0, 1.0}, {1.0, 0.25, 0.0}, {1.0, 0.5, 0.25}};
+static const double aq_c_var_thresholds[AQ_C_SEGMENTS] = {100.0, 12.0, 10.0};
static int get_aq_c_strength(int q_index, vpx_bit_depth_t bit_depth) {
// Approximate base quatizer (truncated to int)
@@ -94,7 +96,7 @@ void vp9_setup_in_frame_q_adj(VP9_COMP *cpi) {
// An "aq_strength" value determines how many segments are supported,
// the set of transition points to use and the extent of the quantizer
// adjustment for each segment (configured in vp9_setup_in_frame_q_adj()).
-void vp9_select_in_frame_q_segment(VP9_COMP *cpi,
+void vp9_select_in_frame_q_segment(VP9_COMP *cpi, BLOCK_SIZE bs,
int mi_row, int mi_col,
int output_enabled, int projected_rate) {
VP9_COMMON *const cm = &cpi->common;
@@ -118,6 +120,10 @@ void vp9_select_in_frame_q_segment(VP9_COMP *cpi,
(bw * bh);
const int aq_strength = get_aq_c_strength(cm->base_qindex, cm->bit_depth);
const int active_segments = aq_c_active_segments[aq_strength];
+ double logvar;
+
+ vp9_setup_src_planes(&cpi->mb, cpi->Source, mi_row, mi_col);
+ logvar = vp9_log_block_var(cpi, &cpi->mb, bs);
// The number of segments considered and the transition points used to
// select them is determined by the "aq_strength" value.
@@ -127,8 +133,9 @@ void vp9_select_in_frame_q_segment(VP9_COMP *cpi,
// with no Q adjustment.
segment = active_segments - 1;
while (segment > 0) {
- if (projected_rate <
- (target_rate * aq_c_transitions[aq_strength][segment])) {
+ if ((projected_rate <
+ target_rate * aq_c_transitions[aq_strength][segment]) &&
+ (logvar < aq_c_var_thresholds[segment])) {
break;
}
--segment;
diff --git a/vp9/encoder/vp9_aq_complexity.h b/vp9/encoder/vp9_aq_complexity.h
index af031a46c..6f82aac37 100644
--- a/vp9/encoder/vp9_aq_complexity.h
+++ b/vp9/encoder/vp9_aq_complexity.h
@@ -19,10 +19,10 @@ extern "C" {
struct VP9_COMP;
// Select a segment for the current SB64.
-void vp9_select_in_frame_q_segment(struct VP9_COMP *cpi, int mi_row, int mi_col,
+void vp9_select_in_frame_q_segment(struct VP9_COMP *cpi, BLOCK_SIZE bs,
+ int mi_row, int mi_col,
int output_enabled, int projected_rate);
-
// This function sets up a set of segments with delta Q values around
// the baseline frame quantizer.
void vp9_setup_in_frame_q_adj(struct VP9_COMP *cpi);
diff --git a/vp9/encoder/vp9_aq_variance.c b/vp9/encoder/vp9_aq_variance.c
index fbf3cff09..df65696b1 100644
--- a/vp9/encoder/vp9_aq_variance.c
+++ b/vp9/encoder/vp9_aq_variance.c
@@ -126,12 +126,14 @@ static unsigned int block_variance(VP9_COMP *cpi, MACROBLOCK *x,
}
}
-int vp9_block_energy(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs) {
- double energy;
+double vp9_log_block_var(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs) {
unsigned int var = block_variance(cpi, x, bs);
-
vp9_clear_system_state();
+ return log(var + 1.0);
+}
- energy = 0.9 * (log(var + 1.0) - 10.0);
+int vp9_block_energy(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs) {
+ double energy;
+ energy = 0.9 * (vp9_log_block_var(cpi, x, bs) - 10.0);
return clamp((int)round(energy), ENERGY_MIN, ENERGY_MAX);
}
diff --git a/vp9/encoder/vp9_aq_variance.h b/vp9/encoder/vp9_aq_variance.h
index ac144fb32..a0effa311 100644
--- a/vp9/encoder/vp9_aq_variance.h
+++ b/vp9/encoder/vp9_aq_variance.h
@@ -22,6 +22,7 @@ unsigned int vp9_vaq_segment_id(int energy);
void vp9_vaq_frame_setup(VP9_COMP *cpi);
int vp9_block_energy(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs);
+double vp9_log_block_var(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs);
#ifdef __cplusplus
} // extern "C"
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index 93e85292a..7ab240b01 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -1699,7 +1699,7 @@ static void rd_use_partition(VP9_COMP *cpi,
// and and if necessary apply a Q delta using segmentation to get
// closer to the target.
if ((cpi->oxcf.aq_mode == COMPLEXITY_AQ) && cm->seg.update_map) {
- vp9_select_in_frame_q_segment(cpi, mi_row, mi_col,
+ vp9_select_in_frame_q_segment(cpi, bsize, mi_row, mi_col,
output_enabled, chosen_rdc.rate);
}
encode_sb(cpi, tile_info, tp, mi_row, mi_col, output_enabled, bsize,
@@ -2438,7 +2438,7 @@ static void rd_pick_partition(VP9_COMP *cpi,
// and and if necessary apply a Q delta using segmentation to get
// closer to the target.
if ((cpi->oxcf.aq_mode == COMPLEXITY_AQ) && cm->seg.update_map)
- vp9_select_in_frame_q_segment(cpi, mi_row, mi_col, output_enabled,
+ vp9_select_in_frame_q_segment(cpi, bsize, mi_row, mi_col, output_enabled,
best_rdc.rate);
encode_sb(cpi, tile_info, tp, mi_row, mi_col, output_enabled,
bsize, pc_tree);
@@ -2943,7 +2943,7 @@ static void nonrd_pick_partition(VP9_COMP *cpi,
// and and if necessary apply a Q delta using segmentation to get
// closer to the target.
if ((oxcf->aq_mode == COMPLEXITY_AQ) && cm->seg.update_map) {
- vp9_select_in_frame_q_segment(cpi, mi_row, mi_col, output_enabled,
+ vp9_select_in_frame_q_segment(cpi, bsize, mi_row, mi_col, output_enabled,
best_rdc.rate);
}
encode_sb_rt(cpi, tile_info, tp, mi_row, mi_col, output_enabled,