| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include "denoising.h" | 11 #include "denoising.h" |
| 12 | 12 |
| 13 #include "vp8/common/reconinter.h" | 13 #include "vp8/common/reconinter.h" |
| 14 #include "vpx/vpx_integer.h" | 14 #include "vpx/vpx_integer.h" |
| 15 #include "vpx_mem/vpx_mem.h" | 15 #include "vpx_mem/vpx_mem.h" |
| 16 #include "vp8_rtcd.h" | 16 #include "vp8_rtcd.h" |
| 17 | 17 |
| 18 static const unsigned int NOISE_MOTION_THRESHOLD = 25 * 25; | 18 static const unsigned int NOISE_MOTION_THRESHOLD = 25 * 25; |
| 19 /* SSE_DIFF_THRESHOLD is selected as ~95% confidence assuming | 19 /* SSE_DIFF_THRESHOLD is selected as ~95% confidence assuming |
| 20 * var(noise) ~= 100. | 20 * var(noise) ~= 100. |
| 21 */ | 21 */ |
| 22 static const unsigned int SSE_DIFF_THRESHOLD = 16 * 16 * 20; | 22 static const unsigned int SSE_DIFF_THRESHOLD = 16 * 16 * 20; |
| 23 static const unsigned int SSE_THRESHOLD = 16 * 16 * 40; | 23 static const unsigned int SSE_THRESHOLD = 16 * 16 * 40; |
| 24 static const unsigned int SSE_THRESHOLD_HIGH = 16 * 16 * 60; |
| 24 | 25 |
| 25 /* | 26 /* |
| 26 * The filter function was modified to reduce the computational complexity. | 27 * The filter function was modified to reduce the computational complexity. |
| 27 * Step 1: | 28 * Step 1: |
| 28 * Instead of applying tap coefficients for each pixel, we calculated the | 29 * Instead of applying tap coefficients for each pixel, we calculated the |
| 29 * pixel adjustments vs. pixel diff value ahead of time. | 30 * pixel adjustments vs. pixel diff value ahead of time. |
| 30 * adjustment = filtered_value - current_raw | 31 * adjustment = filtered_value - current_raw |
| 31 * = (filter_coefficient * diff + 128) >> 8 | 32 * = (filter_coefficient * diff + 128) >> 8 |
| 32 * where | 33 * where |
| 33 * filter_coefficient = (255 << 8) / (256 + ((absdiff * 330) >> 3)); | 34 * filter_coefficient = (255 << 8) / (256 + ((absdiff * 330) >> 3)); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 47 * [-7, -4] -3 -4 | 48 * [-7, -4] -3 -4 |
| 48 * [-3, 3] diff diff | 49 * [-3, 3] diff diff |
| 49 * [4, 7] 3 4 | 50 * [4, 7] 3 4 |
| 50 * [8, 15] 4 5 | 51 * [8, 15] 4 5 |
| 51 * [16, 255] 6 7 | 52 * [16, 255] 6 7 |
| 52 */ | 53 */ |
| 53 | 54 |
| 54 int vp8_denoiser_filter_c(unsigned char *mc_running_avg_y, int mc_avg_y_stride, | 55 int vp8_denoiser_filter_c(unsigned char *mc_running_avg_y, int mc_avg_y_stride, |
| 55 unsigned char *running_avg_y, int avg_y_stride, | 56 unsigned char *running_avg_y, int avg_y_stride, |
| 56 unsigned char *sig, int sig_stride, | 57 unsigned char *sig, int sig_stride, |
| 57 unsigned int motion_magnitude) | 58 unsigned int motion_magnitude, |
| 59 int increase_denoising) |
| 58 { | 60 { |
| 59 unsigned char *running_avg_y_start = running_avg_y; | 61 unsigned char *running_avg_y_start = running_avg_y; |
| 60 unsigned char *sig_start = sig; | 62 unsigned char *sig_start = sig; |
| 61 int r, c, i; | 63 int sum_diff_thresh; |
| 64 int r, c; |
| 62 int sum_diff = 0; | 65 int sum_diff = 0; |
| 63 int adj_val[3] = {3, 4, 6}; | 66 int adj_val[3] = {3, 4, 6}; |
| 64 | 67 int shift_inc1 = 0; |
| 68 int shift_inc2 = 1; |
| 65 /* If motion_magnitude is small, making the denoiser more aggressive by | 69 /* If motion_magnitude is small, making the denoiser more aggressive by |
| 66 * increasing the adjustment for each level. */ | 70 * increasing the adjustment for each level. Add another increment for |
| 71 * blocks that are labeled for increase denoising. */ |
| 67 if (motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD) | 72 if (motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD) |
| 68 { | 73 { |
| 69 for (i = 0; i < 3; i++) | 74 if (increase_denoising) { |
| 70 adj_val[i] += 1; | 75 shift_inc1 = 1; |
| 76 shift_inc2 = 2; |
| 77 } |
| 78 adj_val[0] += shift_inc2; |
| 79 adj_val[1] += shift_inc2; |
| 80 adj_val[2] += shift_inc2; |
| 71 } | 81 } |
| 72 | 82 |
| 73 for (r = 0; r < 16; ++r) | 83 for (r = 0; r < 16; ++r) |
| 74 { | 84 { |
| 75 for (c = 0; c < 16; ++c) | 85 for (c = 0; c < 16; ++c) |
| 76 { | 86 { |
| 77 int diff = 0; | 87 int diff = 0; |
| 78 int adjustment = 0; | 88 int adjustment = 0; |
| 79 int absdiff = 0; | 89 int absdiff = 0; |
| 80 | 90 |
| 81 diff = mc_running_avg_y[c] - sig[c]; | 91 diff = mc_running_avg_y[c] - sig[c]; |
| 82 absdiff = abs(diff); | 92 absdiff = abs(diff); |
| 83 | 93 |
| 84 /* When |diff| < 4, use pixel value from last denoised raw. */ | 94 // When |diff| <= |3 + shift_inc1|, use pixel value from |
| 85 if (absdiff <= 3) | 95 // last denoised raw. |
| 96 if (absdiff <= 3 + shift_inc1) |
| 86 { | 97 { |
| 87 running_avg_y[c] = mc_running_avg_y[c]; | 98 running_avg_y[c] = mc_running_avg_y[c]; |
| 88 sum_diff += diff; | 99 sum_diff += diff; |
| 89 } | 100 } |
| 90 else | 101 else |
| 91 { | 102 { |
| 92 if (absdiff >= 4 && absdiff <= 7) | 103 if (absdiff >= 4 && absdiff <= 7) |
| 93 adjustment = adj_val[0]; | 104 adjustment = adj_val[0]; |
| 94 else if (absdiff >= 8 && absdiff <= 15) | 105 else if (absdiff >= 8 && absdiff <= 15) |
| 95 adjustment = adj_val[1]; | 106 adjustment = adj_val[1]; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 116 } | 127 } |
| 117 } | 128 } |
| 118 } | 129 } |
| 119 | 130 |
| 120 /* Update pointers for next iteration. */ | 131 /* Update pointers for next iteration. */ |
| 121 sig += sig_stride; | 132 sig += sig_stride; |
| 122 mc_running_avg_y += mc_avg_y_stride; | 133 mc_running_avg_y += mc_avg_y_stride; |
| 123 running_avg_y += avg_y_stride; | 134 running_avg_y += avg_y_stride; |
| 124 } | 135 } |
| 125 | 136 |
| 126 if (abs(sum_diff) > SUM_DIFF_THRESHOLD) | 137 sum_diff_thresh= SUM_DIFF_THRESHOLD; |
| 138 if (increase_denoising) sum_diff_thresh = SUM_DIFF_THRESHOLD_HIGH; |
| 139 if (abs(sum_diff) > sum_diff_thresh) |
| 127 return COPY_BLOCK; | 140 return COPY_BLOCK; |
| 128 | 141 |
| 129 vp8_copy_mem16x16(running_avg_y_start, avg_y_stride, sig_start, sig_stride); | 142 vp8_copy_mem16x16(running_avg_y_start, avg_y_stride, sig_start, sig_stride); |
| 130 return FILTER_BLOCK; | 143 return FILTER_BLOCK; |
| 131 } | 144 } |
| 132 | 145 |
| 133 int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height) | 146 int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height) |
| 134 { | 147 { |
| 135 int i; | 148 int i; |
| 136 assert(denoiser); | 149 assert(denoiser); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 180 void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser, | 193 void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser, |
| 181 MACROBLOCK *x, | 194 MACROBLOCK *x, |
| 182 unsigned int best_sse, | 195 unsigned int best_sse, |
| 183 unsigned int zero_mv_sse, | 196 unsigned int zero_mv_sse, |
| 184 int recon_yoffset, | 197 int recon_yoffset, |
| 185 int recon_uvoffset) | 198 int recon_uvoffset) |
| 186 { | 199 { |
| 187 int mv_row; | 200 int mv_row; |
| 188 int mv_col; | 201 int mv_col; |
| 189 unsigned int motion_magnitude2; | 202 unsigned int motion_magnitude2; |
| 190 | 203 unsigned int sse_thresh; |
| 191 MV_REFERENCE_FRAME frame = x->best_reference_frame; | 204 MV_REFERENCE_FRAME frame = x->best_reference_frame; |
| 192 MV_REFERENCE_FRAME zero_frame = x->best_zeromv_reference_frame; | 205 MV_REFERENCE_FRAME zero_frame = x->best_zeromv_reference_frame; |
| 193 | 206 |
| 194 enum vp8_denoiser_decision decision = FILTER_BLOCK; | 207 enum vp8_denoiser_decision decision = FILTER_BLOCK; |
| 195 | 208 |
| 196 if (zero_frame) | 209 if (zero_frame) |
| 197 { | 210 { |
| 198 YV12_BUFFER_CONFIG *src = &denoiser->yv12_running_avg[frame]; | 211 YV12_BUFFER_CONFIG *src = &denoiser->yv12_running_avg[frame]; |
| 199 YV12_BUFFER_CONFIG *dst = &denoiser->yv12_mc_running_avg; | 212 YV12_BUFFER_CONFIG *dst = &denoiser->yv12_mc_running_avg; |
| 200 YV12_BUFFER_CONFIG saved_pre,saved_dst; | 213 YV12_BUFFER_CONFIG saved_pre,saved_dst; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 265 } | 278 } |
| 266 filter_xd->pre = saved_pre; | 279 filter_xd->pre = saved_pre; |
| 267 filter_xd->dst = saved_dst; | 280 filter_xd->dst = saved_dst; |
| 268 *mbmi = saved_mbmi; | 281 *mbmi = saved_mbmi; |
| 269 | 282 |
| 270 } | 283 } |
| 271 | 284 |
| 272 mv_row = x->best_sse_mv.as_mv.row; | 285 mv_row = x->best_sse_mv.as_mv.row; |
| 273 mv_col = x->best_sse_mv.as_mv.col; | 286 mv_col = x->best_sse_mv.as_mv.col; |
| 274 motion_magnitude2 = mv_row * mv_row + mv_col * mv_col; | 287 motion_magnitude2 = mv_row * mv_row + mv_col * mv_col; |
| 275 if (best_sse > SSE_THRESHOLD || motion_magnitude2 | 288 sse_thresh = SSE_THRESHOLD; |
| 289 if (x->increase_denoising) sse_thresh = SSE_THRESHOLD_HIGH; |
| 290 |
| 291 if (best_sse > sse_thresh || motion_magnitude2 |
| 276 > 8 * NOISE_MOTION_THRESHOLD) | 292 > 8 * NOISE_MOTION_THRESHOLD) |
| 277 { | 293 { |
| 278 decision = COPY_BLOCK; | 294 decision = COPY_BLOCK; |
| 279 } | 295 } |
| 280 | 296 |
| 281 if (decision == FILTER_BLOCK) | 297 if (decision == FILTER_BLOCK) |
| 282 { | 298 { |
| 283 unsigned char *mc_running_avg_y = | 299 unsigned char *mc_running_avg_y = |
| 284 denoiser->yv12_mc_running_avg.y_buffer + recon_yoffset; | 300 denoiser->yv12_mc_running_avg.y_buffer + recon_yoffset; |
| 285 int mc_avg_y_stride = denoiser->yv12_mc_running_avg.y_stride; | 301 int mc_avg_y_stride = denoiser->yv12_mc_running_avg.y_stride; |
| 286 unsigned char *running_avg_y = | 302 unsigned char *running_avg_y = |
| 287 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset; | 303 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset; |
| 288 int avg_y_stride = denoiser->yv12_running_avg[INTRA_FRAME].y_stride; | 304 int avg_y_stride = denoiser->yv12_running_avg[INTRA_FRAME].y_stride; |
| 289 | 305 |
| 290 /* Filter. */ | 306 /* Filter. */ |
| 291 decision = vp8_denoiser_filter(mc_running_avg_y, mc_avg_y_stride, | 307 decision = vp8_denoiser_filter(mc_running_avg_y, mc_avg_y_stride, |
| 292 running_avg_y, avg_y_stride, | 308 running_avg_y, avg_y_stride, |
| 293 x->thismb, 16, motion_magnitude2); | 309 x->thismb, 16, motion_magnitude2, |
| 310 x->increase_denoising); |
| 294 } | 311 } |
| 295 if (decision == COPY_BLOCK) | 312 if (decision == COPY_BLOCK) |
| 296 { | 313 { |
| 297 /* No filtering of this block; it differs too much from the predictor, | 314 /* No filtering of this block; it differs too much from the predictor, |
| 298 * or the motion vector magnitude is considered too big. | 315 * or the motion vector magnitude is considered too big. |
| 299 */ | 316 */ |
| 300 vp8_copy_mem16x16( | 317 vp8_copy_mem16x16( |
| 301 x->thismb, 16, | 318 x->thismb, 16, |
| 302 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset
, | 319 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset
, |
| 303 denoiser->yv12_running_avg[INTRA_FRAME].y_stride); | 320 denoiser->yv12_running_avg[INTRA_FRAME].y_stride); |
| 304 } | 321 } |
| 305 } | 322 } |
| OLD | NEW |