summaryrefslogtreecommitdiff
path: root/vp9
diff options
context:
space:
mode:
Diffstat (limited to 'vp9')
-rw-r--r--vp9/encoder/vp9_denoiser.c142
-rw-r--r--vp9/encoder/vp9_denoiser.h8
-rw-r--r--vp9/encoder/vp9_encoder.c7
-rw-r--r--vp9/encoder/vp9_pickmode.c18
-rw-r--r--vp9/encoder/vp9_speed_features.c4
5 files changed, 166 insertions, 13 deletions
diff --git a/vp9/encoder/vp9_denoiser.c b/vp9/encoder/vp9_denoiser.c
index 687b4c2b2..ae78b69b4 100644
--- a/vp9/encoder/vp9_denoiser.c
+++ b/vp9/encoder/vp9_denoiser.c
@@ -20,17 +20,129 @@ int vp9_denoiser_filter() {
return 0;
}
+int update_running_avg(uint8_t *mc_avg, int mc_avg_stride, uint8_t *avg,
+ int avg_stride, uint8_t *sig, int sig_stride,
+ int increase_denoising, BLOCK_SIZE bs) {
+ int r, c;
+ int diff, adj, absdiff;
+ int shift_inc1 = 0, shift_inc2 = 1;
+ int adj_val[] = {3, 4, 6};
+ int total_adj = 0;
+
+ if (increase_denoising) {
+ shift_inc1 = 1;
+ shift_inc2 = 2;
+ }
+
+ for (r = 0; r < heights[bs]; ++r) {
+ for (c = 0; c < widths[bs]; ++c) {
+ diff = mc_avg[c] - sig[c];
+ absdiff = abs(diff);
+
+ if (absdiff <= 3 + shift_inc1) {
+ avg[c] = mc_avg[c];
+ total_adj += diff;
+ } else {
+ switch (absdiff) {
+ case 4: case 5: case 6: case 7:
+ adj = adj_val[0];
+ case 8: case 9: case 10: case 11:
+ case 12: case 13: case 14: case 15:
+ adj = adj_val[1];
+ default:
+ adj = adj_val[2];
+ }
+ if (diff > 0) {
+ avg[c] = MIN(UINT8_MAX, sig[c] + adj);
+ total_adj += adj;
+ } else {
+ avg[c] = MAX(0, sig[c] - adj);
+ total_adj -= adj;
+ }
+ }
+ }
+ sig += sig_stride;
+ avg += avg_stride;
+ mc_avg += mc_avg_stride;
+ }
+ return total_adj;
+}
+
+uint8_t *block_start(uint8_t *framebuf, int stride, int mi_row, int mi_col) {
+ return framebuf + (stride * mi_row) + mi_col;
+}
+
+void copy_block(uint8_t *dest, int dest_stride,
+ uint8_t *src, int src_stride, BLOCK_SIZE bs) {
+ int r, c;
+ for (r = 0; r < heights[bs]; ++r) {
+ for (c = 0; c < widths[bs]; ++c) {
+ dest[c] = src[c];
+ }
+ dest += dest_stride;
+ src += src_stride;
+ }
+ return;
+}
+
void vp9_denoiser_denoise(VP9_DENOISER *denoiser,
MACROBLOCK *mb, MODE_INFO **grid,
int mi_row, int mi_col, BLOCK_SIZE bs) {
+ int decision = COPY_BLOCK;
+
+ YV12_BUFFER_CONFIG avg = denoiser->running_avg_y[INTRA_FRAME];
+ struct buf_2d src = mb->plane[0].src;
+
+ update_running_avg(denoiser->mc_running_avg_y.y_buffer,
+ denoiser->mc_running_avg_y.y_stride,
+ denoiser->running_avg_y[INTRA_FRAME].y_buffer,
+ denoiser->running_avg_y[INTRA_FRAME].y_stride,
+ mb->plane[0].src.buf, mb->plane[0].src.stride, 0, bs);
+
+ if (decision == FILTER_BLOCK) {
+ }
+ if (decision == COPY_BLOCK) {
+ copy_block(block_start(avg.y_buffer, avg.y_stride, mi_row, mi_col),
+ avg.y_stride,
+ block_start(src.buf, src.stride, mi_row, mi_col),
+ src.stride,
+ bs);
+ }
return;
}
+void copy_frame(YV12_BUFFER_CONFIG dest, YV12_BUFFER_CONFIG src) {
+ memcpy(dest.buffer_alloc, src.buffer_alloc, src.buffer_alloc_sz);
+}
+
void vp9_denoiser_update_frame_info(VP9_DENOISER *denoiser,
+ YV12_BUFFER_CONFIG src,
FRAME_TYPE frame_type,
int refresh_alt_ref_frame,
int refresh_golden_frame,
int refresh_last_frame) {
+ int i;
+ if (frame_type == KEY_FRAME) {
+ copy_frame(denoiser->running_avg_y[LAST_FRAME], src);
+ for (i = 2; i < MAX_REF_FRAMES - 1; i++) {
+ copy_frame(denoiser->running_avg_y[i],
+ denoiser->running_avg_y[LAST_FRAME]);
+ }
+ } else { /* For non key frames */
+ if (refresh_alt_ref_frame) {
+ copy_frame(denoiser->running_avg_y[ALTREF_FRAME],
+ denoiser->running_avg_y[INTRA_FRAME]);
+ }
+ if (refresh_golden_frame) {
+ copy_frame(denoiser->running_avg_y[GOLDEN_FRAME],
+ denoiser->running_avg_y[INTRA_FRAME]);
+ }
+ if (refresh_last_frame) {
+ copy_frame(denoiser->running_avg_y[LAST_FRAME],
+ denoiser->running_avg_y[INTRA_FRAME]);
+ }
+ }
+
return;
}
@@ -39,11 +151,39 @@ void vp9_denoiser_update_frame_stats() {
}
int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height,
- int border) {
+ int ssx, int ssy, int border) {
+ int i, fail;
+ assert(denoiser);
+
+ for (i = 0; i < MAX_REF_FRAMES; ++i) {
+ fail = vp9_alloc_frame_buffer(&denoiser->running_avg_y[i], width, height,
+ ssx, ssy, border);
+ if (fail) {
+ vp9_denoiser_free(denoiser);
+ return 1;
+ }
+ }
+
+ fail = vp9_alloc_frame_buffer(&denoiser->mc_running_avg_y, width, height,
+ ssx, ssy, border);
+ if (fail) {
+ vp9_denoiser_free(denoiser);
+ return 1;
+ }
+
return 0;
}
void vp9_denoiser_free(VP9_DENOISER *denoiser) {
+ int i;
+ for (i = 0; i < MAX_REF_FRAMES; ++i) {
+ if (&denoiser->running_avg_y[i] != NULL) {
+ vp9_free_frame_buffer(&denoiser->running_avg_y[i]);
+ }
+ }
+ if (&denoiser->mc_running_avg_y != NULL) {
+ vp9_free_frame_buffer(&denoiser->mc_running_avg_y);
+ }
return;
}
diff --git a/vp9/encoder/vp9_denoiser.h b/vp9/encoder/vp9_denoiser.h
index a7a8d9329..81fc7ebe5 100644
--- a/vp9/encoder/vp9_denoiser.h
+++ b/vp9/encoder/vp9_denoiser.h
@@ -12,6 +12,7 @@
#define VP9_ENCODER_DENOISER_H_
#include "vp9/encoder/vp9_block.h"
+#include "vpx_scale/yv12config.h"
#ifdef __cplusplus
extern "C" {
@@ -23,11 +24,12 @@ enum vp9_denoiser_decision {
};
typedef struct vp9_denoiser {
- struct buf_2d running_avg_y;
- struct buf_2d mc_running_avg_y;
+ YV12_BUFFER_CONFIG running_avg_y[MAX_REF_FRAMES];
+ YV12_BUFFER_CONFIG mc_running_avg_y;
} VP9_DENOISER;
void vp9_denoiser_update_frame_info(VP9_DENOISER *denoiser,
+ YV12_BUFFER_CONFIG src,
FRAME_TYPE frame_type,
int refresh_alt_ref_frame,
int refresh_golden_frame,
@@ -40,7 +42,7 @@ void vp9_denoiser_denoise(VP9_DENOISER *denoiser,
void vp9_denoiser_update_frame_stats();
int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height,
- int border);
+ int ssx, int ssy, int border);
void vp9_denoiser_free(VP9_DENOISER *denoiser);
diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c
index 525eccd56..b464361fd 100644
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -683,6 +683,12 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) {
#if CONFIG_DENOISING
vp9_denoiser_alloc(&(cpi->denoiser), cm->width, cm->height,
+ // TODO(tkopp) An unrelated bug causes
+ // cm->subsampling_{x,y} to be uninitialized at this point
+ // in execution. For now we assume YUV-420, which is x/y
+ // subsampling of 1.
+ 1, 1,
+ // cm->subsampling_x, cm->subsampling_y,
VP9_ENC_BORDER_IN_PIXELS);
#endif
}
@@ -1558,6 +1564,7 @@ void vp9_update_reference_frames(VP9_COMP *cpi) {
}
#if CONFIG_DENOISING
vp9_denoiser_update_frame_info(&cpi->denoiser,
+ *cpi->Source,
cpi->common.frame_type,
cpi->refresh_alt_ref_frame,
cpi->refresh_golden_frame,
diff --git a/vp9/encoder/vp9_pickmode.c b/vp9/encoder/vp9_pickmode.c
index 3f4fcd1e1..b7972b77a 100644
--- a/vp9/encoder/vp9_pickmode.c
+++ b/vp9/encoder/vp9_pickmode.c
@@ -172,15 +172,15 @@ static void model_rd_for_sb_y(VP9_COMP *cpi, BLOCK_SIZE bsize,
else
x->skip_txfm = 0;
- // TODO(jingning) This is a temporary solution to account for frames with
- // light changes. Need to customize the rate-distortion modeling for non-RD
- // mode decision.
- if ((sse >> 3) > var)
- sse = var;
- vp9_model_rd_from_var_lapndz(var + sse, 1 << num_pels_log2_lookup[bsize],
- ac_quant >> 3, &rate, &dist);
- *out_rate_sum = rate;
+ vp9_model_rd_from_var_lapndz(sse - var, 1 << num_pels_log2_lookup[bsize],
+ dc_quant >> 3, &rate, &dist);
+ *out_rate_sum = rate >> 1;
*out_dist_sum = dist << 3;
+
+ vp9_model_rd_from_var_lapndz(var, 1 << num_pels_log2_lookup[bsize],
+ ac_quant >> 3, &rate, &dist);
+ *out_rate_sum += rate;
+ *out_dist_sum += dist << 4;
}
// TODO(jingning) placeholder for inter-frame non-RD mode decision.
@@ -469,7 +469,7 @@ int64_t vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
// Perform intra prediction search, if the best SAD is above a certain
// threshold.
if (!x->skip && best_rd > inter_mode_thresh &&
- bsize < cpi->sf.max_intra_bsize) {
+ bsize <= cpi->sf.max_intra_bsize) {
for (this_mode = DC_PRED; this_mode <= DC_PRED; ++this_mode) {
vp9_predict_intra_block(xd, 0, b_width_log2(bsize),
mbmi->tx_size, this_mode,
diff --git a/vp9/encoder/vp9_speed_features.c b/vp9/encoder/vp9_speed_features.c
index 6beb87234..83d900d42 100644
--- a/vp9/encoder/vp9_speed_features.c
+++ b/vp9/encoder/vp9_speed_features.c
@@ -270,6 +270,10 @@ static void set_rt_speed_feature(VP9_COMP *cpi, SPEED_FEATURES *sf,
sf->source_var_thresh = 360;
sf->tx_size_search_method = USE_TX_8X8;
+ // TODO(yunqingwang): max_intra_bsize is used to decide if DC_PRED mode
+ // is checked for a partition block. Later, we can try to allow large
+ // partitions to do intra mode checking.
+ sf->max_intra_bsize = BLOCK_8X8;
}
if (speed >= 7) {