diff options
Diffstat (limited to 'vp9')
-rw-r--r-- | vp9/encoder/vp9_denoiser.c | 142 | ||||
-rw-r--r-- | vp9/encoder/vp9_denoiser.h | 8 | ||||
-rw-r--r-- | vp9/encoder/vp9_encoder.c | 7 | ||||
-rw-r--r-- | vp9/encoder/vp9_pickmode.c | 18 | ||||
-rw-r--r-- | vp9/encoder/vp9_speed_features.c | 4 |
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) { |