summaryrefslogtreecommitdiff
path: root/vp9/encoder
diff options
context:
space:
mode:
authorJingning Han <jingning@google.com>2014-11-04 14:32:04 -0800
committerJingning Han <jingning@google.com>2014-11-05 21:17:09 -0800
commitcaaf63b2c4d5e4ae18f0ae796fb92e4509450a0d (patch)
tree104e836615d5fddbd1247367038e666037b2874e /vp9/encoder
parent7e491de1c487186bd2adb6b6907b8d0d1869f846 (diff)
downloadlibvpx-caaf63b2c4d5e4ae18f0ae796fb92e4509450a0d.tar
libvpx-caaf63b2c4d5e4ae18f0ae796fb92e4509450a0d.tar.gz
libvpx-caaf63b2c4d5e4ae18f0ae796fb92e4509450a0d.tar.bz2
libvpx-caaf63b2c4d5e4ae18f0ae796fb92e4509450a0d.zip
Rework cut-off decisions in cyclic refresh aq mode
This commit removes the cyclic aq mode dependency on in_static_area and reworks the corresponding cut-off thresholds. It improves the compression performance of speed -5 by 1.47% in PSNR and 2.07% in SSIM, and the compression performance of speed -6 by 3.10% in PSNR and 5.25% in SSIM. Speed wise, about 1% faster in both settings at high bit-rates. Change-Id: I1ffc775afdc047964448d9dff5751491ba4ff4a9
Diffstat (limited to 'vp9/encoder')
-rw-r--r--vp9/encoder/vp9_aq_cyclicrefresh.c20
-rw-r--r--vp9/encoder/vp9_block.h2
-rw-r--r--vp9/encoder/vp9_context_tree.h5
-rw-r--r--vp9/encoder/vp9_encodeframe.c43
4 files changed, 29 insertions, 41 deletions
diff --git a/vp9/encoder/vp9_aq_cyclicrefresh.c b/vp9/encoder/vp9_aq_cyclicrefresh.c
index 514ff7a52..1fc4ecdee 100644
--- a/vp9/encoder/vp9_aq_cyclicrefresh.c
+++ b/vp9/encoder/vp9_aq_cyclicrefresh.c
@@ -94,19 +94,17 @@ static int candidate_refresh_aq(const CYCLIC_REFRESH *cr,
const MB_MODE_INFO *mbmi,
BLOCK_SIZE bsize, int use_rd) {
if (use_rd) {
+ MV mv = mbmi->mv[0].as_mv;
// If projected rate is below the thresh_rate (well below target,
// so undershoot expected), accept it for lower-qp coding.
if (cr->projected_rate_sb < cr->thresh_rate_sb)
return 1;
// Otherwise, reject the block for lower-qp coding if any of the following:
- // 1) prediction block size is below min_block_size
- // 2) mode is non-zero mv and projected distortion is above thresh_dist
- // 3) mode is an intra-mode (we may want to allow some of this under
+ // 1) mode uses large mv
+ // 2) mode is an intra-mode (we may want to allow some of this under
// another thresh_dist)
- else if (bsize < cr->min_block_size ||
- (mbmi->mv[0].as_int != 0 &&
- cr->projected_dist_sb > cr->thresh_dist_sb) ||
- !is_inter_block(mbmi))
+ else if (mv.row > 32 || mv.row < -32 ||
+ mv.col > 32 || mv.col < -32 || !is_inter_block(mbmi))
return 0;
else
return 1;
@@ -135,8 +133,7 @@ void vp9_cyclic_refresh_update_segment(VP9_COMP *const cpi,
const int xmis = MIN(cm->mi_cols - mi_col, bw);
const int ymis = MIN(cm->mi_rows - mi_row, bh);
const int block_index = mi_row * cm->mi_cols + mi_col;
- const int refresh_this_block = cpi->mb.in_static_area ||
- candidate_refresh_aq(cr, mbmi, bsize, use_rd);
+ const int refresh_this_block = candidate_refresh_aq(cr, mbmi, bsize, use_rd);
// Default is to not update the refresh map.
int new_map_value = cr->map[block_index];
int x = 0; int y = 0;
@@ -161,6 +158,7 @@ void vp9_cyclic_refresh_update_segment(VP9_COMP *const cpi,
// Leave it marked as block that is not candidate for refresh.
new_map_value = 1;
}
+
// Update entries in the cyclic refresh map with new_map_value, and
// copy mbmi->segment_id into global segmentation map.
for (y = 0; y < ymis; y++)
@@ -214,8 +212,8 @@ void vp9_cyclic_refresh_setup(VP9_COMP *const cpi) {
if (cpi->sf.use_nonrd_pick_mode) {
// May want to be more conservative with thresholds in non-rd mode for now
// as rate/distortion are derived from model based on prediction residual.
- cr->thresh_rate_sb = (rc->sb64_target_rate * 256) >> 3;
- cr->thresh_dist_sb = 4 * (int)(q * q);
+ cr->thresh_rate_sb = (rc->sb64_target_rate * 256);
+ cr->thresh_dist_sb = 16 * (int)(q * q);
}
cr->num_seg_blocks = 0;
diff --git a/vp9/encoder/vp9_block.h b/vp9/encoder/vp9_block.h
index 5194c4c27..12fb886dc 100644
--- a/vp9/encoder/vp9_block.h
+++ b/vp9/encoder/vp9_block.h
@@ -98,8 +98,6 @@ struct macroblock {
// note that token_costs is the cost when eob node is skipped
vp9_coeff_cost token_costs[TX_SIZES];
- int in_static_area;
-
int optimize;
// indicate if it is in the rd search loop or encoding process
diff --git a/vp9/encoder/vp9_context_tree.h b/vp9/encoder/vp9_context_tree.h
index 47d9580a8..1710783e7 100644
--- a/vp9/encoder/vp9_context_tree.h
+++ b/vp9/encoder/vp9_context_tree.h
@@ -46,6 +46,11 @@ typedef struct {
int64_t tx_rd_diff[TX_MODES];
int64_t best_filter_diff[SWITCHABLE_FILTER_CONTEXTS];
+ // TODO(jingning) Use RD_COST struct here instead. This involves a boarder
+ // scope of refactoring.
+ int rate;
+ int64_t dist;
+
#if CONFIG_VP9_TEMPORAL_DENOISING
unsigned int newmv_sse;
unsigned int zeromv_sse;
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index b87a28332..fdc8e653f 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -641,6 +641,9 @@ static void update_state(VP9_COMP *cpi, PICK_MODE_CONTEXT *ctx,
// Else for cyclic refresh mode update the segment map, set the segment id
// and then update the quantizer.
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ) {
+
+ vp9_cyclic_refresh_set_rate_and_dist_sb(cpi->cyclic_refresh,
+ ctx->rate, ctx->dist);
vp9_cyclic_refresh_update_segment(cpi, &xd->mi[0].src_mi->mbmi,
mi_row, mi_col, bsize, 1);
}
@@ -910,6 +913,9 @@ static void rd_pick_sb_modes(VP9_COMP *cpi,
// refactored to provide proper exit/return handle.
if (rd_cost->rate == INT_MAX)
rd_cost->rdcost = INT64_MAX;
+
+ ctx->rate = rd_cost->rate;
+ ctx->dist = rd_cost->dist;
}
static void update_stats(VP9_COMMON *cm, const MACROBLOCK *x) {
@@ -1334,6 +1340,8 @@ static void update_state_rt(VP9_COMP *cpi, PICK_MODE_CONTEXT *ctx,
: cm->last_frame_seg_map;
mbmi->segment_id = vp9_get_segment_id(cm, map, bsize, mi_row, mi_col);
} else {
+ vp9_cyclic_refresh_set_rate_and_dist_sb(cpi->cyclic_refresh,
+ ctx->rate, ctx->dist);
// Setting segmentation map for cyclic_refresh
vp9_cyclic_refresh_update_segment(cpi, mbmi, mi_row, mi_col, bsize, 1);
}
@@ -1725,10 +1733,6 @@ static void rd_use_partition(VP9_COMP *cpi,
vp9_select_in_frame_q_segment(cpi, mi_row, mi_col,
output_enabled, chosen_rdc.rate);
}
-
- if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
- vp9_cyclic_refresh_set_rate_and_dist_sb(cpi->cyclic_refresh,
- chosen_rdc.rate, chosen_rdc.dist);
encode_sb(cpi, tile_info, tp, mi_row, mi_col, output_enabled, bsize,
pc_tree);
}
@@ -2467,10 +2471,6 @@ static void rd_pick_partition(VP9_COMP *cpi,
if ((cpi->oxcf.aq_mode == COMPLEXITY_AQ) && cm->seg.update_map)
vp9_select_in_frame_q_segment(cpi, mi_row, mi_col, output_enabled,
best_rdc.rate);
- if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
- vp9_cyclic_refresh_set_rate_and_dist_sb(cpi->cyclic_refresh,
- best_rdc.rate, best_rdc.dist);
-
encode_sb(cpi, tile_info, tp, mi_row, mi_col, output_enabled,
bsize, pc_tree);
}
@@ -2638,7 +2638,7 @@ static void nonrd_pick_sb_modes(VP9_COMP *cpi,
mbmi->sb_type = bsize;
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && cm->seg.enabled)
- if (mbmi->segment_id && x->in_static_area)
+ if (mbmi->segment_id)
x->rdmult = vp9_cyclic_refresh_get_rdmult(cpi->cyclic_refresh);
if (vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP))
@@ -2651,6 +2651,9 @@ static void nonrd_pick_sb_modes(VP9_COMP *cpi,
if (rd_cost->rate == INT_MAX)
vp9_rd_cost_reset(rd_cost);
+
+ ctx->rate = rd_cost->rate;
+ ctx->dist = rd_cost->dist;
}
static void fill_mode_info_sb(VP9_COMMON *cm, MACROBLOCK *x,
@@ -2973,11 +2976,6 @@ static void nonrd_pick_partition(VP9_COMP *cpi,
vp9_select_in_frame_q_segment(cpi, mi_row, mi_col, output_enabled,
best_rdc.rate);
}
-
- if (oxcf->aq_mode == CYCLIC_REFRESH_AQ)
- vp9_cyclic_refresh_set_rate_and_dist_sb(cpi->cyclic_refresh,
- best_rdc.rate, best_rdc.dist);
-
encode_sb_rt(cpi, tile_info, tp, mi_row, mi_col, output_enabled,
bsize, pc_tree);
}
@@ -3114,12 +3112,8 @@ static void nonrd_select_partition(VP9_COMP *cpi,
}
}
- if (bsize == BLOCK_64X64 && output_enabled) {
- if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
- vp9_cyclic_refresh_set_rate_and_dist_sb(cpi->cyclic_refresh,
- rd_cost->rate, rd_cost->dist);
+ if (bsize == BLOCK_64X64 && output_enabled)
encode_sb_rt(cpi, tile_info, tp, mi_row, mi_col, 1, bsize, pc_tree);
- }
}
@@ -3232,13 +3226,9 @@ static void nonrd_use_partition(VP9_COMP *cpi,
break;
}
- if (bsize == BLOCK_64X64 && output_enabled) {
- if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
- vp9_cyclic_refresh_set_rate_and_dist_sb(cpi->cyclic_refresh,
- rd_cost->rate, rd_cost->dist);
+ if (bsize == BLOCK_64X64 && output_enabled)
encode_sb_rt(cpi, &tile_data->tile_info, tp, mi_row, mi_col,
1, bsize, pc_tree);
- }
}
static void encode_nonrd_sb_row(VP9_COMP *cpi,
@@ -3263,7 +3253,6 @@ static void encode_nonrd_sb_row(VP9_COMP *cpi,
const int idx_str = cm->mi_stride * mi_row + mi_col;
MODE_INFO *mi = cm->mi + idx_str;
BLOCK_SIZE bsize;
- x->in_static_area = 0;
x->source_variance = UINT_MAX;
vp9_zero(x->pred_mv);
vp9_rd_cost_init(&dummy_rdc);
@@ -3290,10 +3279,8 @@ static void encode_nonrd_sb_row(VP9_COMP *cpi,
break;
case REFERENCE_PARTITION:
set_offsets(cpi, tile_info, mi_row, mi_col, BLOCK_64X64);
- x->in_static_area = is_background(cpi, tile_info, mi_row, mi_col);
-
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && cm->seg.enabled &&
- xd->mi[0].src_mi->mbmi.segment_id && x->in_static_area) {
+ xd->mi[0].src_mi->mbmi.segment_id) {
auto_partition_range(cpi, tile_info, mi_row, mi_col,
&sf->min_partition_size,
&sf->max_partition_size);