summaryrefslogtreecommitdiff
path: root/vp9
diff options
context:
space:
mode:
Diffstat (limited to 'vp9')
-rw-r--r--vp9/encoder/vp9_encodeframe.c32
-rw-r--r--vp9/encoder/vp9_firstpass.c23
-rw-r--r--vp9/encoder/vp9_rd.h5
-rw-r--r--vp9/encoder/vp9_rdopt.c87
-rw-r--r--vp9/encoder/vp9_temporal_filter.c21
5 files changed, 113 insertions, 55 deletions
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index 9574c097a..f92705a81 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -125,19 +125,17 @@ static const uint16_t VP9_HIGH_VAR_OFFS_12[64] = {
};
#endif // CONFIG_VP9_HIGHBITDEPTH
-unsigned int vp9_get_sby_perpixel_variance(VP9_COMP *cpi,
- const struct buf_2d *ref,
- BLOCK_SIZE bs) {
+unsigned int vp9_get_sby_variance(VP9_COMP *cpi, const struct buf_2d *ref,
+ BLOCK_SIZE bs) {
unsigned int sse;
const unsigned int var =
cpi->fn_ptr[bs].vf(ref->buf, ref->stride, VP9_VAR_OFFS, 0, &sse);
- return ROUND_POWER_OF_TWO(var, num_pels_log2_lookup[bs]);
+ return var;
}
#if CONFIG_VP9_HIGHBITDEPTH
-unsigned int vp9_high_get_sby_perpixel_variance(VP9_COMP *cpi,
- const struct buf_2d *ref,
- BLOCK_SIZE bs, int bd) {
+unsigned int vp9_high_get_sby_variance(VP9_COMP *cpi, const struct buf_2d *ref,
+ BLOCK_SIZE bs, int bd) {
unsigned int var, sse;
switch (bd) {
case 10:
@@ -157,8 +155,24 @@ unsigned int vp9_high_get_sby_perpixel_variance(VP9_COMP *cpi,
CONVERT_TO_BYTEPTR(VP9_HIGH_VAR_OFFS_8), 0, &sse);
break;
}
- return (unsigned int)ROUND64_POWER_OF_TWO((int64_t)var,
- num_pels_log2_lookup[bs]);
+ return var;
+}
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+unsigned int vp9_get_sby_perpixel_variance(VP9_COMP *cpi,
+ const struct buf_2d *ref,
+ BLOCK_SIZE bs) {
+ return ROUND_POWER_OF_TWO(vp9_get_sby_variance(cpi, ref, bs),
+ num_pels_log2_lookup[bs]);
+}
+
+#if CONFIG_VP9_HIGHBITDEPTH
+unsigned int vp9_high_get_sby_perpixel_variance(VP9_COMP *cpi,
+ const struct buf_2d *ref,
+ BLOCK_SIZE bs, int bd) {
+ return (unsigned int)ROUND64_POWER_OF_TWO(
+ (int64_t)vp9_high_get_sby_variance(cpi, ref, bs, bd),
+ num_pels_log2_lookup[bs]);
}
#endif // CONFIG_VP9_HIGHBITDEPTH
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index d09acf78b..caa58e7a8 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -2010,8 +2010,7 @@ static double calc_kf_frame_boost(VP9_COMP *cpi,
return VPXMIN(frame_boost, max_boost * boost_q_correction);
}
-static int calc_arf_boost(VP9_COMP *cpi, int offset, int f_frames, int b_frames,
- int *f_boost, int *b_boost) {
+static int calc_arf_boost(VP9_COMP *cpi, int f_frames, int b_frames) {
TWO_PASS *const twopass = &cpi->twopass;
int i;
double boost_score = 0.0;
@@ -2026,7 +2025,7 @@ static int calc_arf_boost(VP9_COMP *cpi, int offset, int f_frames, int b_frames,
// Search forward from the proposed arf/next gf position.
for (i = 0; i < f_frames; ++i) {
- const FIRSTPASS_STATS *this_frame = read_frame_stats(twopass, i + offset);
+ const FIRSTPASS_STATS *this_frame = read_frame_stats(twopass, i);
if (this_frame == NULL) break;
// Update the motion related elements to the boost calculation.
@@ -2036,8 +2035,7 @@ static int calc_arf_boost(VP9_COMP *cpi, int offset, int f_frames, int b_frames,
// We want to discount the flash frame itself and the recovery
// frame that follows as both will have poor scores.
- flash_detected = detect_flash(twopass, i + offset) ||
- detect_flash(twopass, i + offset + 1);
+ flash_detected = detect_flash(twopass, i) || detect_flash(twopass, i + 1);
// Accumulate the effect of prediction quality decay.
if (!flash_detected) {
@@ -2053,7 +2051,7 @@ static int calc_arf_boost(VP9_COMP *cpi, int offset, int f_frames, int b_frames,
this_frame_mv_in_out, GF_MAX_BOOST);
}
- *f_boost = (int)boost_score;
+ arf_boost = (int)boost_score;
// Reset for backward looking loop.
boost_score = 0.0;
@@ -2066,7 +2064,7 @@ static int calc_arf_boost(VP9_COMP *cpi, int offset, int f_frames, int b_frames,
// Search backward towards last gf position.
for (i = -1; i >= -b_frames; --i) {
- const FIRSTPASS_STATS *this_frame = read_frame_stats(twopass, i + offset);
+ const FIRSTPASS_STATS *this_frame = read_frame_stats(twopass, i);
if (this_frame == NULL) break;
// Update the motion related elements to the boost calculation.
@@ -2076,8 +2074,7 @@ static int calc_arf_boost(VP9_COMP *cpi, int offset, int f_frames, int b_frames,
// We want to discount the the flash frame itself and the recovery
// frame that follows as both will have poor scores.
- flash_detected = detect_flash(twopass, i + offset) ||
- detect_flash(twopass, i + offset + 1);
+ flash_detected = detect_flash(twopass, i) || detect_flash(twopass, i + 1);
// Cumulative effect of prediction quality decay.
if (!flash_detected) {
@@ -2092,9 +2089,8 @@ static int calc_arf_boost(VP9_COMP *cpi, int offset, int f_frames, int b_frames,
calc_frame_boost(cpi, this_frame, &sr_accumulator,
this_frame_mv_in_out, GF_MAX_BOOST);
}
- *b_boost = (int)boost_score;
+ arf_boost += (int)boost_score;
- arf_boost = (*f_boost + *b_boost);
if (arf_boost < ((b_frames + f_frames) * 20))
arf_boost = ((b_frames + f_frames) * 20);
arf_boost = VPXMAX(arf_boost, MIN_ARF_GF_BOOST);
@@ -2439,8 +2435,6 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
const double av_err = get_distribution_av_err(cpi, twopass);
unsigned int allow_alt_ref = is_altref_enabled(cpi);
- int f_boost = 0;
- int b_boost = 0;
int flash_detected;
int active_max_gf_interval;
int active_min_gf_interval;
@@ -2606,8 +2600,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
: VPXMAX(0, rc->frames_to_key - i);
// Calculate the boost for alt ref.
- rc->gfu_boost =
- calc_arf_boost(cpi, 0, forward_frames, i - 1, &f_boost, &b_boost);
+ rc->gfu_boost = calc_arf_boost(cpi, forward_frames, (i - 1));
rc->source_alt_ref_pending = 1;
// Test to see if multi arf is appropriate.
diff --git a/vp9/encoder/vp9_rd.h b/vp9/encoder/vp9_rd.h
index 230508718..59022c106 100644
--- a/vp9/encoder/vp9_rd.h
+++ b/vp9/encoder/vp9_rd.h
@@ -194,10 +194,15 @@ void vp9_setup_pred_block(const MACROBLOCKD *xd,
int vp9_get_intra_cost_penalty(const struct VP9_COMP *const cpi,
BLOCK_SIZE bsize, int qindex, int qdelta);
+unsigned int vp9_get_sby_variance(struct VP9_COMP *cpi,
+ const struct buf_2d *ref, BLOCK_SIZE bs);
unsigned int vp9_get_sby_perpixel_variance(struct VP9_COMP *cpi,
const struct buf_2d *ref,
BLOCK_SIZE bs);
#if CONFIG_VP9_HIGHBITDEPTH
+unsigned int vp9_high_get_sby_variance(struct VP9_COMP *cpi,
+ const struct buf_2d *ref, BLOCK_SIZE bs,
+ int bd);
unsigned int vp9_high_get_sby_perpixel_variance(struct VP9_COMP *cpi,
const struct buf_2d *ref,
BLOCK_SIZE bs, int bd);
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index afdb60f18..2ba6378c5 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -2876,57 +2876,82 @@ void vp9_rd_pick_intra_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, RD_COST *rd_cost,
// This function is designed to apply a bias or adjustment to an rd value based
// on the relative variance of the source and reconstruction.
-#define LOW_VAR_THRESH 16
-#define VLOW_ADJ_MAX 25
-#define VHIGH_ADJ_MAX 8
+#define VERY_LOW_VAR_THRESH 2
+#define LOW_VAR_THRESH 5
+#define VAR_MULT 100
+static unsigned int max_var_adjust[VP9E_CONTENT_INVALID] = { 16, 16, 100 };
+
static void rd_variance_adjustment(VP9_COMP *cpi, MACROBLOCK *x,
BLOCK_SIZE bsize, int64_t *this_rd,
MV_REFERENCE_FRAME ref_frame,
unsigned int source_variance) {
MACROBLOCKD *const xd = &x->e_mbd;
- unsigned int recon_variance;
+ unsigned int rec_variance;
+ unsigned int src_variance;
+ unsigned int src_rec_min;
unsigned int absvar_diff = 0;
- int64_t var_error = 0;
- int64_t var_factor = 0;
+ unsigned int var_factor = 0;
+ unsigned int adj_max;
+ vp9e_tune_content content_type = cpi->oxcf.content;
if (*this_rd == INT64_MAX) return;
#if CONFIG_VP9_HIGHBITDEPTH
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
- recon_variance = vp9_high_get_sby_perpixel_variance(cpi, &xd->plane[0].dst,
+ if (source_variance > 0) {
+ rec_variance = vp9_high_get_sby_perpixel_variance(cpi, &xd->plane[0].dst,
bsize, xd->bd);
+ src_variance = source_variance;
+ } else {
+ rec_variance =
+ vp9_high_get_sby_variance(cpi, &xd->plane[0].dst, bsize, xd->bd);
+ src_variance =
+ vp9_high_get_sby_variance(cpi, &x->plane[0].src, bsize, xd->bd);
+ }
} else {
- recon_variance =
- vp9_get_sby_perpixel_variance(cpi, &xd->plane[0].dst, bsize);
+ if (source_variance > 0) {
+ rec_variance =
+ vp9_get_sby_perpixel_variance(cpi, &xd->plane[0].dst, bsize);
+ src_variance = source_variance;
+ } else {
+ rec_variance = vp9_get_sby_variance(cpi, &xd->plane[0].dst, bsize);
+ src_variance = vp9_get_sby_variance(cpi, &x->plane[0].src, bsize);
+ }
}
#else
- recon_variance = vp9_get_sby_perpixel_variance(cpi, &xd->plane[0].dst, bsize);
+ if (source_variance > 0) {
+ rec_variance = vp9_get_sby_perpixel_variance(cpi, &xd->plane[0].dst, bsize);
+ src_variance = source_variance;
+ } else {
+ rec_variance = vp9_get_sby_variance(cpi, &xd->plane[0].dst, bsize);
+ src_variance = vp9_get_sby_variance(cpi, &x->plane[0].src, bsize);
+ }
#endif // CONFIG_VP9_HIGHBITDEPTH
- if ((source_variance + recon_variance) > LOW_VAR_THRESH) {
- absvar_diff = (source_variance > recon_variance)
- ? (source_variance - recon_variance)
- : (recon_variance - source_variance);
+ // Lower of source (raw per pixel value) and recon variance. Note that
+ // if the source per pixel is 0 then the recon value here will not be per
+ // pixel (see above) so will likely be much larger.
+ src_rec_min = VPXMIN(source_variance, rec_variance);
- var_error = ((int64_t)200 * source_variance * recon_variance) /
- (((int64_t)source_variance * source_variance) +
- ((int64_t)recon_variance * recon_variance));
- var_error = 100 - var_error;
- }
+ if (src_rec_min > LOW_VAR_THRESH) return;
+
+ absvar_diff = (src_variance > rec_variance) ? (src_variance - rec_variance)
+ : (rec_variance - src_variance);
+
+ adj_max = max_var_adjust[content_type];
+
+ var_factor =
+ (unsigned int)((int64_t)VAR_MULT * absvar_diff) / VPXMAX(1, src_variance);
+ var_factor = VPXMIN(adj_max, var_factor);
- // Source variance above a threshold and ref frame is intra.
- // This case is targeted mainly at discouraging intra modes that give rise
- // to a predictor with a low spatial complexity compared to the source.
- if ((source_variance > LOW_VAR_THRESH) && (ref_frame == INTRA_FRAME) &&
- (source_variance > recon_variance)) {
- var_factor = VPXMIN(absvar_diff, VPXMIN(VLOW_ADJ_MAX, var_error));
- // A second possible case of interest is where the source variance
- // is very low and we wish to discourage false texture or motion trails.
- } else if ((source_variance < (LOW_VAR_THRESH >> 1)) &&
- (recon_variance > source_variance)) {
- var_factor = VPXMIN(absvar_diff, VPXMIN(VHIGH_ADJ_MAX, var_error));
- }
*this_rd += (*this_rd * var_factor) / 100;
+
+ if (content_type == VP9E_CONTENT_FILM) {
+ if (src_rec_min <= VERY_LOW_VAR_THRESH) {
+ if (ref_frame == INTRA_FRAME) *this_rd *= 2;
+ if (bsize > 6) *this_rd *= 2;
+ }
+ }
}
// Do we have an internal image edge (e.g. formatting bars).
diff --git a/vp9/encoder/vp9_temporal_filter.c b/vp9/encoder/vp9_temporal_filter.c
index 630794156..2758c42ae 100644
--- a/vp9/encoder/vp9_temporal_filter.c
+++ b/vp9/encoder/vp9_temporal_filter.c
@@ -350,6 +350,27 @@ void vp9_temporal_filter_iterate_row_c(VP9_COMP *cpi, ThreadData *td,
td->mb.mv_limits.col_max =
((mb_cols - 1 - mb_col) * 16) + (17 - 2 * VP9_INTERP_EXTEND);
+ if (cpi->oxcf.content == VP9E_CONTENT_FILM) {
+ unsigned int src_variance;
+ struct buf_2d src;
+
+ src.buf = f->y_buffer + mb_y_offset;
+ src.stride = f->y_stride;
+
+#if CONFIG_VP9_HIGHBITDEPTH
+ if (mbd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
+ src_variance =
+ vp9_high_get_sby_perpixel_variance(cpi, &src, BLOCK_16X16, mbd->bd);
+ } else {
+ src_variance = vp9_get_sby_perpixel_variance(cpi, &src, BLOCK_16X16);
+ }
+#else
+ src_variance = vp9_get_sby_perpixel_variance(cpi, &src, BLOCK_16X16);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+ if (src_variance <= 2) strength = VPXMAX(0, (int)strength - 2);
+ }
+
for (frame = 0; frame < frame_count; frame++) {
const uint32_t thresh_low = 10000;
const uint32_t thresh_high = 20000;