summaryrefslogtreecommitdiff
path: root/vp9/encoder
diff options
context:
space:
mode:
Diffstat (limited to 'vp9/encoder')
-rw-r--r--vp9/encoder/vp9_block.h2
-rw-r--r--vp9/encoder/vp9_denoiser.c3
-rw-r--r--vp9/encoder/vp9_encodeframe.c13
-rw-r--r--vp9/encoder/vp9_encoder.h1
-rw-r--r--vp9/encoder/vp9_pickmode.c26
5 files changed, 36 insertions, 9 deletions
diff --git a/vp9/encoder/vp9_block.h b/vp9/encoder/vp9_block.h
index 61a886e71..bdd666286 100644
--- a/vp9/encoder/vp9_block.h
+++ b/vp9/encoder/vp9_block.h
@@ -168,6 +168,8 @@ struct macroblock {
uint8_t skip_low_source_sad;
+ uint8_t lowvar_highsumdiff;
+
uint8_t last_sb_high_content;
// For each superblock: saves the content value (e.g., low/high sad/sumdiff)
diff --git a/vp9/encoder/vp9_denoiser.c b/vp9/encoder/vp9_denoiser.c
index b92557a9c..5a5ca1f94 100644
--- a/vp9/encoder/vp9_denoiser.c
+++ b/vp9/encoder/vp9_denoiser.c
@@ -573,7 +573,8 @@ void vp9_denoiser_set_noise_level(VP9_DENOISER *denoiser, int noise_level) {
int64_t vp9_scale_part_thresh(int64_t threshold, VP9_DENOISER_LEVEL noise_level,
int content_state) {
if ((content_state == kLowSadLowSumdiff) ||
- (content_state == kHighSadLowSumdiff) || noise_level == kDenHigh)
+ (content_state == kHighSadLowSumdiff) ||
+ (content_state == kLowVarHighSumdiff) || noise_level == kDenHigh)
return (3 * threshold) >> 1;
else
return (5 * threshold) >> 2;
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index 12dc226da..fca378b57 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -495,11 +495,13 @@ int64_t scale_part_thresh_sumdiff(int64_t threshold_base, int speed, int width,
if (width <= 640 && height <= 480)
return (5 * threshold_base) >> 2;
else if ((content_state == kLowSadLowSumdiff) ||
- (content_state == kHighSadLowSumdiff))
+ (content_state == kHighSadLowSumdiff) ||
+ (content_state == kLowVarHighSumdiff))
return (5 * threshold_base) >> 2;
} else if (speed == 7) {
if ((content_state == kLowSadLowSumdiff) ||
- (content_state == kHighSadLowSumdiff)) {
+ (content_state == kHighSadLowSumdiff) ||
+ (content_state == kLowVarHighSumdiff)) {
return (5 * threshold_base) >> 2;
}
}
@@ -994,6 +996,11 @@ static void avg_source_sad(VP9_COMP *cpi, MACROBLOCK *x, int shift,
else
x->content_state_sb = ((tmp_sse - tmp_variance) < 25) ? kHighSadLowSumdiff
: kHighSadHighSumdiff;
+
+ // Detect large lighting change.
+ if (tmp_variance < (tmp_sse >> 3) && (tmp_sse - tmp_variance) > 10000)
+ x->content_state_sb = kLowVarHighSumdiff;
+
if (cpi->content_state_sb_fd != NULL) {
if (tmp_sad < avg_source_sad_threshold2) {
// Cap the increment to 255.
@@ -1061,6 +1068,7 @@ static int choose_partitioning(VP9_COMP *cpi, const TileInfo *const tile,
content_state == kLowSadHighSumdiff)
? 1
: 0;
+ x->lowvar_highsumdiff = (content_state == kLowVarHighSumdiff) ? 1 : 0;
if (cpi->content_state_sb_fd != NULL)
x->last_sb_high_content = cpi->content_state_sb_fd[sb_offset2];
// If source_sad is low copy the partition without computing the y_sad.
@@ -4110,6 +4118,7 @@ static void encode_nonrd_sb_row(VP9_COMP *cpi, ThreadData *td,
x->color_sensitivity[1] = 0;
x->sb_is_skin = 0;
x->skip_low_source_sad = 0;
+ x->lowvar_highsumdiff = 0;
x->content_state_sb = 0;
if (seg->enabled) {
diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h
index 94ebc3b6f..64571be64 100644
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -137,6 +137,7 @@ typedef enum {
kLowSadHighSumdiff = 2,
kHighSadLowSumdiff = 3,
kHighSadHighSumdiff = 4,
+ kLowVarHighSumdiff = 5,
} CONTENT_STATE_SB;
typedef struct VP9EncoderConfig {
diff --git a/vp9/encoder/vp9_pickmode.c b/vp9/encoder/vp9_pickmode.c
index 9c6138f6d..c82930f56 100644
--- a/vp9/encoder/vp9_pickmode.c
+++ b/vp9/encoder/vp9_pickmode.c
@@ -170,6 +170,14 @@ static int combined_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
}
vp9_set_mv_search_range(&x->mv_limits, &ref_mv);
+ // Limit motion vector for large lightning change.
+ if (cpi->oxcf.speed > 5 && x->lowvar_highsumdiff) {
+ x->mv_limits.col_min = VPXMAX(x->mv_limits.col_min, -10);
+ x->mv_limits.row_min = VPXMAX(x->mv_limits.row_min, -10);
+ x->mv_limits.col_max = VPXMIN(x->mv_limits.col_max, 10);
+ x->mv_limits.row_max = VPXMIN(x->mv_limits.row_max, 10);
+ }
+
assert(x->mv_best_ref_index[ref] <= 2);
if (x->mv_best_ref_index[ref] < 2)
mvp_full = x->mbmi_ext->ref_mvs[ref][x->mv_best_ref_index[ref]].as_mv;
@@ -1219,7 +1227,8 @@ static INLINE void find_predictors(
static void vp9_NEWMV_diff_bias(const NOISE_ESTIMATE *ne, MACROBLOCKD *xd,
PREDICTION_MODE this_mode, RD_COST *this_rdc,
BLOCK_SIZE bsize, int mv_row, int mv_col,
- int is_last_frame) {
+ int is_last_frame, int lowvar_highsumdiff,
+ int is_skin) {
// Bias against MVs associated with NEWMV mode that are very different from
// top/left neighbors.
if (this_mode == NEWMV) {
@@ -1266,9 +1275,12 @@ static void vp9_NEWMV_diff_bias(const NOISE_ESTIMATE *ne, MACROBLOCKD *xd,
// If noise estimation is enabled, and estimated level is above threshold,
// add a bias to LAST reference with small motion, for large blocks.
if (ne->enabled && ne->level >= kMedium && bsize >= BLOCK_32X32 &&
- is_last_frame && mv_row < 8 && mv_row > -8 && mv_col < 8 && mv_col > -8) {
- this_rdc->rdcost = 7 * this_rdc->rdcost >> 3;
- }
+ is_last_frame && mv_row < 8 && mv_row > -8 && mv_col < 8 && mv_col > -8)
+ this_rdc->rdcost = 7 * (this_rdc->rdcost >> 3);
+ else if (lowvar_highsumdiff && !is_skin && bsize >= BLOCK_16X16 &&
+ is_last_frame && mv_row < 16 && mv_row > -16 && mv_col < 16 &&
+ mv_col > -16)
+ this_rdc->rdcost = 7 * (this_rdc->rdcost >> 3);
}
#if CONFIG_VP9_TEMPORAL_DENOISING
@@ -1966,7 +1978,8 @@ void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, TileDataEnc *tile_data,
vp9_NEWMV_diff_bias(&cpi->noise_estimate, xd, this_mode, &this_rdc, bsize,
frame_mv[this_mode][ref_frame].as_mv.row,
frame_mv[this_mode][ref_frame].as_mv.col,
- ref_frame == LAST_FRAME);
+ ref_frame == LAST_FRAME, x->lowvar_highsumdiff,
+ x->sb_is_skin);
}
// Skipping checking: test to see if this block can be reconstructed by
@@ -2048,7 +2061,8 @@ void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, TileDataEnc *tile_data,
if (best_rdc.rdcost == INT64_MAX ||
((!force_skip_low_temp_var || bsize < BLOCK_32X32) &&
perform_intra_pred && !x->skip && best_rdc.rdcost > inter_mode_thresh &&
- bsize <= cpi->sf.max_intra_bsize && !x->skip_low_source_sad)) {
+ bsize <= cpi->sf.max_intra_bsize && !x->skip_low_source_sad &&
+ !x->lowvar_highsumdiff)) {
struct estimate_block_intra_args args = { cpi, x, DC_PRED, 1, 0 };
int i;
TX_SIZE best_intra_tx_size = TX_SIZES;