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 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 | 71 |
72 static int total_adj_weak_thresh(BLOCK_SIZE bs, int increase_denoising) { | 72 static int total_adj_weak_thresh(BLOCK_SIZE bs, int increase_denoising) { |
73 return widths[bs] * heights[bs] * (increase_denoising ? 3 : 2); | 73 return widths[bs] * heights[bs] * (increase_denoising ? 3 : 2); |
74 } | 74 } |
75 | 75 |
76 static VP9_DENOISER_DECISION denoiser_filter(const uint8_t *sig, int sig_stride, | 76 static VP9_DENOISER_DECISION denoiser_filter(const uint8_t *sig, int sig_stride, |
77 const uint8_t *mc_avg, | 77 const uint8_t *mc_avg, |
78 int mc_avg_stride, | 78 int mc_avg_stride, |
79 uint8_t *avg, int avg_stride, | 79 uint8_t *avg, int avg_stride, |
80 int increase_denoising, | 80 int increase_denoising, |
81 BLOCK_SIZE bs) { | 81 BLOCK_SIZE bs, |
| 82 int motion_magnitude) { |
82 int r, c; | 83 int r, c; |
83 const uint8_t *sig_start = sig; | 84 const uint8_t *sig_start = sig; |
84 const uint8_t *mc_avg_start = mc_avg; | 85 const uint8_t *mc_avg_start = mc_avg; |
85 uint8_t *avg_start = avg; | 86 uint8_t *avg_start = avg; |
86 int diff, adj, absdiff, delta; | 87 int diff, adj, absdiff, delta; |
87 int adj_val[] = {3, 4, 6}; | 88 int adj_val[] = {3, 4, 6}; |
88 int total_adj = 0; | 89 int total_adj = 0; |
| 90 int shift_inc = 1; |
| 91 |
| 92 /* If motion_magnitude is small, making the denoiser more aggressive by |
| 93 * increasing the adjustment for each level. Add another increment for |
| 94 * blocks that are labeled for increase denoising. */ |
| 95 if (motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD) { |
| 96 if (increase_denoising) { |
| 97 shift_inc = 2; |
| 98 } |
| 99 adj_val[0] += shift_inc; |
| 100 adj_val[1] += shift_inc; |
| 101 adj_val[2] += shift_inc; |
| 102 } |
89 | 103 |
90 // First attempt to apply a strong temporal denoising filter. | 104 // First attempt to apply a strong temporal denoising filter. |
91 for (r = 0; r < heights[bs]; ++r) { | 105 for (r = 0; r < heights[bs]; ++r) { |
92 for (c = 0; c < widths[bs]; ++c) { | 106 for (c = 0; c < widths[bs]; ++c) { |
93 diff = mc_avg[c] - sig[c]; | 107 diff = mc_avg[c] - sig[c]; |
94 absdiff = abs(diff); | 108 absdiff = abs(diff); |
95 | 109 |
96 if (absdiff <= absdiff_thresh(bs, increase_denoising)) { | 110 if (absdiff <= absdiff_thresh(bs, increase_denoising)) { |
97 avg[c] = mc_avg[c]; | 111 avg[c] = mc_avg[c]; |
98 total_adj += diff; | 112 total_adj += diff; |
(...skipping 24 matching lines...) Expand all Loading... |
123 } | 137 } |
124 | 138 |
125 // If the strong filter did not modify the signal too much, we're all set. | 139 // If the strong filter did not modify the signal too much, we're all set. |
126 if (abs(total_adj) <= total_adj_strong_thresh(bs, increase_denoising)) { | 140 if (abs(total_adj) <= total_adj_strong_thresh(bs, increase_denoising)) { |
127 return FILTER_BLOCK; | 141 return FILTER_BLOCK; |
128 } | 142 } |
129 | 143 |
130 // Otherwise, we try to dampen the filter if the delta is not too high. | 144 // Otherwise, we try to dampen the filter if the delta is not too high. |
131 delta = ((abs(total_adj) - total_adj_strong_thresh(bs, increase_denoising)) | 145 delta = ((abs(total_adj) - total_adj_strong_thresh(bs, increase_denoising)) |
132 >> 8) + 1; | 146 >> 8) + 1; |
133 if (delta > delta_thresh(bs, increase_denoising)) { | 147 |
| 148 if (delta >= delta_thresh(bs, increase_denoising)) { |
134 return COPY_BLOCK; | 149 return COPY_BLOCK; |
135 } | 150 } |
136 | 151 |
137 mc_avg = mc_avg_start; | 152 mc_avg = mc_avg_start; |
138 avg = avg_start; | 153 avg = avg_start; |
139 sig = sig_start; | 154 sig = sig_start; |
140 for (r = 0; r < heights[bs]; ++r) { | 155 for (r = 0; r < heights[bs]; ++r) { |
141 for (c = 0; c < widths[bs]; ++c) { | 156 for (c = 0; c < widths[bs]; ++c) { |
142 diff = mc_avg[c] - sig[c]; | 157 diff = mc_avg[c] - sig[c]; |
143 adj = abs(diff); | 158 adj = abs(diff); |
144 if (adj > delta) { | 159 if (adj > delta) { |
145 adj = delta; | 160 adj = delta; |
146 } | 161 } |
147 if (diff > 0) { | 162 if (diff > 0) { |
| 163 // Diff positive means we made positive adjustment above |
| 164 // (in first try/attempt), so now make negative adjustment to bring |
| 165 // denoised signal down. |
148 avg[c] = MAX(0, avg[c] - adj); | 166 avg[c] = MAX(0, avg[c] - adj); |
| 167 total_adj -= adj; |
| 168 } else { |
| 169 // Diff negative means we made negative adjustment above |
| 170 // (in first try/attempt), so now make positive adjustment to bring |
| 171 // denoised signal up. |
| 172 avg[c] = MIN(UINT8_MAX, avg[c] + adj); |
149 total_adj += adj; | 173 total_adj += adj; |
150 } else { | |
151 avg[c] = MIN(UINT8_MAX, avg[c] + adj); | |
152 total_adj -= adj; | |
153 } | 174 } |
154 } | 175 } |
155 sig += sig_stride; | 176 sig += sig_stride; |
156 avg += avg_stride; | 177 avg += avg_stride; |
157 mc_avg += mc_avg_stride; | 178 mc_avg += mc_avg_stride; |
158 } | 179 } |
159 | 180 |
160 // We can use the filter if it has been sufficiently dampened | 181 // We can use the filter if it has been sufficiently dampened |
161 if (abs(total_adj) <= total_adj_weak_thresh(bs, increase_denoising)) { | 182 if (abs(total_adj) <= total_adj_weak_thresh(bs, increase_denoising)) { |
162 return FILTER_BLOCK; | 183 return FILTER_BLOCK; |
(...skipping 15 matching lines...) Expand all Loading... |
178 src += src_stride; | 199 src += src_stride; |
179 } | 200 } |
180 } | 201 } |
181 | 202 |
182 static VP9_DENOISER_DECISION perform_motion_compensation(VP9_DENOISER *denoiser, | 203 static VP9_DENOISER_DECISION perform_motion_compensation(VP9_DENOISER *denoiser, |
183 MACROBLOCK *mb, | 204 MACROBLOCK *mb, |
184 BLOCK_SIZE bs, | 205 BLOCK_SIZE bs, |
185 int increase_denoising, | 206 int increase_denoising, |
186 int mi_row, | 207 int mi_row, |
187 int mi_col, | 208 int mi_col, |
188 PICK_MODE_CONTEXT *ctx | 209 PICK_MODE_CONTEXT *ctx, |
| 210 int *motion_magnitude |
189 ) { | 211 ) { |
190 int mv_col, mv_row; | 212 int mv_col, mv_row; |
191 int sse_diff = ctx->zeromv_sse - ctx->newmv_sse; | 213 int sse_diff = ctx->zeromv_sse - ctx->newmv_sse; |
192 MV_REFERENCE_FRAME frame; | 214 MV_REFERENCE_FRAME frame; |
193 MACROBLOCKD *filter_mbd = &mb->e_mbd; | 215 MACROBLOCKD *filter_mbd = &mb->e_mbd; |
194 MB_MODE_INFO *mbmi = &filter_mbd->mi[0]->mbmi; | 216 MB_MODE_INFO *mbmi = &filter_mbd->mi[0]->mbmi; |
195 | 217 |
196 MB_MODE_INFO saved_mbmi; | 218 MB_MODE_INFO saved_mbmi; |
197 int i, j; | 219 int i, j; |
198 struct buf_2d saved_dst[MAX_MB_PLANE]; | 220 struct buf_2d saved_dst[MAX_MB_PLANE]; |
199 struct buf_2d saved_pre[MAX_MB_PLANE][2]; // 2 pre buffers | 221 struct buf_2d saved_pre[MAX_MB_PLANE][2]; // 2 pre buffers |
200 | 222 |
201 // We will restore these after motion compensation. | 223 // We will restore these after motion compensation. |
202 saved_mbmi = *mbmi; | 224 saved_mbmi = *mbmi; |
203 for (i = 0; i < MAX_MB_PLANE; ++i) { | 225 for (i = 0; i < MAX_MB_PLANE; ++i) { |
204 for (j = 0; j < 2; ++j) { | 226 for (j = 0; j < 2; ++j) { |
205 saved_pre[i][j] = filter_mbd->plane[i].pre[j]; | 227 saved_pre[i][j] = filter_mbd->plane[i].pre[j]; |
206 } | 228 } |
207 saved_dst[i] = filter_mbd->plane[i].dst; | 229 saved_dst[i] = filter_mbd->plane[i].dst; |
208 } | 230 } |
209 | 231 |
210 mv_col = ctx->best_sse_mv.as_mv.col; | 232 mv_col = ctx->best_sse_mv.as_mv.col; |
211 mv_row = ctx->best_sse_mv.as_mv.row; | 233 mv_row = ctx->best_sse_mv.as_mv.row; |
212 | 234 |
| 235 *motion_magnitude = mv_row * mv_row + mv_col * mv_col; |
| 236 |
213 frame = ctx->best_reference_frame; | 237 frame = ctx->best_reference_frame; |
214 | 238 |
215 // If the best reference frame uses inter-prediction and there is enough of a | 239 // If the best reference frame uses inter-prediction and there is enough of a |
216 // difference in sum-squared-error, use it. | 240 // difference in sum-squared-error, use it. |
217 if (frame != INTRA_FRAME && | 241 if (frame != INTRA_FRAME && |
218 sse_diff > sse_diff_thresh(bs, increase_denoising, mv_row, mv_col)) { | 242 sse_diff > sse_diff_thresh(bs, increase_denoising, mv_row, mv_col)) { |
219 mbmi->ref_frame[0] = ctx->best_reference_frame; | 243 mbmi->ref_frame[0] = ctx->best_reference_frame; |
220 mbmi->mode = ctx->best_sse_inter_mode; | 244 mbmi->mode = ctx->best_sse_inter_mode; |
221 mbmi->mv[0] = ctx->best_sse_mv; | 245 mbmi->mv[0] = ctx->best_sse_mv; |
222 } else { | 246 } else { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 if (mv_row * mv_row + mv_col * mv_col > | 314 if (mv_row * mv_row + mv_col * mv_col > |
291 8 * noise_motion_thresh(bs, increase_denoising)) { | 315 8 * noise_motion_thresh(bs, increase_denoising)) { |
292 return COPY_BLOCK; | 316 return COPY_BLOCK; |
293 } | 317 } |
294 return FILTER_BLOCK; | 318 return FILTER_BLOCK; |
295 } | 319 } |
296 | 320 |
297 void vp9_denoiser_denoise(VP9_DENOISER *denoiser, MACROBLOCK *mb, | 321 void vp9_denoiser_denoise(VP9_DENOISER *denoiser, MACROBLOCK *mb, |
298 int mi_row, int mi_col, BLOCK_SIZE bs, | 322 int mi_row, int mi_col, BLOCK_SIZE bs, |
299 PICK_MODE_CONTEXT *ctx) { | 323 PICK_MODE_CONTEXT *ctx) { |
| 324 int motion_magnitude = 0; |
300 VP9_DENOISER_DECISION decision = FILTER_BLOCK; | 325 VP9_DENOISER_DECISION decision = FILTER_BLOCK; |
301 YV12_BUFFER_CONFIG avg = denoiser->running_avg_y[INTRA_FRAME]; | 326 YV12_BUFFER_CONFIG avg = denoiser->running_avg_y[INTRA_FRAME]; |
302 YV12_BUFFER_CONFIG mc_avg = denoiser->mc_running_avg_y; | 327 YV12_BUFFER_CONFIG mc_avg = denoiser->mc_running_avg_y; |
303 uint8_t *avg_start = block_start(avg.y_buffer, avg.y_stride, mi_row, mi_col); | 328 uint8_t *avg_start = block_start(avg.y_buffer, avg.y_stride, mi_row, mi_col); |
304 uint8_t *mc_avg_start = block_start(mc_avg.y_buffer, mc_avg.y_stride, | 329 uint8_t *mc_avg_start = block_start(mc_avg.y_buffer, mc_avg.y_stride, |
305 mi_row, mi_col); | 330 mi_row, mi_col); |
306 struct buf_2d src = mb->plane[0].src; | 331 struct buf_2d src = mb->plane[0].src; |
307 | 332 |
308 decision = perform_motion_compensation(denoiser, mb, bs, | 333 decision = perform_motion_compensation(denoiser, mb, bs, |
309 denoiser->increase_denoising, | 334 denoiser->increase_denoising, |
310 mi_row, mi_col, ctx); | 335 mi_row, mi_col, ctx, |
| 336 &motion_magnitude); |
311 | 337 |
312 if (decision == FILTER_BLOCK) { | 338 if (decision == FILTER_BLOCK) { |
313 decision = denoiser_filter(src.buf, src.stride, | 339 decision = denoiser_filter(src.buf, src.stride, |
314 mc_avg_start, mc_avg.y_stride, | 340 mc_avg_start, mc_avg.y_stride, |
315 avg_start, avg.y_stride, | 341 avg_start, avg.y_stride, |
316 0, bs); | 342 0, bs, motion_magnitude); |
317 } | 343 } |
318 | 344 |
319 if (decision == FILTER_BLOCK) { | 345 if (decision == FILTER_BLOCK) { |
320 copy_block(src.buf, src.stride, avg_start, avg.y_stride, bs); | 346 copy_block(src.buf, src.stride, avg_start, avg.y_stride, bs); |
321 } else { // COPY_BLOCK | 347 } else { // COPY_BLOCK |
322 copy_block(avg_start, avg.y_stride, src.buf, src.stride, bs); | 348 copy_block(avg_start, avg.y_stride, src.buf, src.stride, bs); |
323 } | 349 } |
324 } | 350 } |
325 | 351 |
326 static void copy_frame(YV12_BUFFER_CONFIG dest, const YV12_BUFFER_CONFIG src) { | 352 static void copy_frame(YV12_BUFFER_CONFIG dest, const YV12_BUFFER_CONFIG src) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 denoiser->running_avg_y[INTRA_FRAME]); | 389 denoiser->running_avg_y[INTRA_FRAME]); |
364 } | 390 } |
365 } | 391 } |
366 } | 392 } |
367 | 393 |
368 void vp9_denoiser_reset_frame_stats(PICK_MODE_CONTEXT *ctx) { | 394 void vp9_denoiser_reset_frame_stats(PICK_MODE_CONTEXT *ctx) { |
369 ctx->zeromv_sse = UINT_MAX; | 395 ctx->zeromv_sse = UINT_MAX; |
370 ctx->newmv_sse = UINT_MAX; | 396 ctx->newmv_sse = UINT_MAX; |
371 } | 397 } |
372 | 398 |
373 void vp9_denoiser_update_frame_stats(VP9_DENOISER *denoiser, MB_MODE_INFO *mbmi, | 399 void vp9_denoiser_update_frame_stats(MB_MODE_INFO *mbmi, unsigned int sse, |
374 unsigned int sse, PREDICTION_MODE mode, | 400 PREDICTION_MODE mode, |
375 PICK_MODE_CONTEXT *ctx) { | 401 PICK_MODE_CONTEXT *ctx) { |
376 // TODO(tkopp): Use both MVs if possible | 402 // TODO(tkopp): Use both MVs if possible |
377 if (mbmi->mv[0].as_int == 0 && sse < ctx->zeromv_sse) { | 403 if (mbmi->mv[0].as_int == 0 && sse < ctx->zeromv_sse) { |
378 ctx->zeromv_sse = sse; | 404 ctx->zeromv_sse = sse; |
379 ctx->best_zeromv_reference_frame = mbmi->ref_frame[0]; | 405 ctx->best_zeromv_reference_frame = mbmi->ref_frame[0]; |
380 } | 406 } |
381 | 407 |
382 if (mode == NEWMV) { | 408 if (mode == NEWMV) { |
383 ctx->newmv_sse = sse; | 409 ctx->newmv_sse = sse; |
384 ctx->best_sse_inter_mode = mode; | 410 ctx->best_sse_inter_mode = mode; |
385 ctx->best_sse_mv = mbmi->mv[0]; | 411 ctx->best_sse_mv = mbmi->mv[0]; |
386 ctx->best_reference_frame = mbmi->ref_frame[0]; | 412 ctx->best_reference_frame = mbmi->ref_frame[0]; |
387 } | 413 } |
388 } | 414 } |
389 | 415 |
390 int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height, | 416 int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height, |
391 int ssx, int ssy, int border) { | 417 int ssx, int ssy, |
| 418 #if CONFIG_VP9_HIGHBITDEPTH |
| 419 int use_highbitdepth, |
| 420 #endif |
| 421 int border) { |
392 int i, fail; | 422 int i, fail; |
393 assert(denoiser != NULL); | 423 assert(denoiser != NULL); |
394 | 424 |
395 for (i = 0; i < MAX_REF_FRAMES; ++i) { | 425 for (i = 0; i < MAX_REF_FRAMES; ++i) { |
396 fail = vp9_alloc_frame_buffer(&denoiser->running_avg_y[i], width, height, | 426 fail = vp9_alloc_frame_buffer(&denoiser->running_avg_y[i], width, height, |
397 ssx, ssy, border); | 427 ssx, ssy, |
| 428 #if CONFIG_VP9_HIGHBITDEPTH |
| 429 use_highbitdepth, |
| 430 #endif |
| 431 border); |
398 if (fail) { | 432 if (fail) { |
399 vp9_denoiser_free(denoiser); | 433 vp9_denoiser_free(denoiser); |
400 return 1; | 434 return 1; |
401 } | 435 } |
402 #ifdef OUTPUT_YUV_DENOISED | 436 #ifdef OUTPUT_YUV_DENOISED |
403 make_grayscale(&denoiser->running_avg_y[i]); | 437 make_grayscale(&denoiser->running_avg_y[i]); |
404 #endif | 438 #endif |
405 } | 439 } |
406 | 440 |
407 fail = vp9_alloc_frame_buffer(&denoiser->mc_running_avg_y, width, height, | 441 fail = vp9_alloc_frame_buffer(&denoiser->mc_running_avg_y, width, height, |
408 ssx, ssy, border); | 442 ssx, ssy, |
| 443 #if CONFIG_VP9_HIGHBITDEPTH |
| 444 use_highbitdepth, |
| 445 #endif |
| 446 border); |
409 if (fail) { | 447 if (fail) { |
410 vp9_denoiser_free(denoiser); | 448 vp9_denoiser_free(denoiser); |
411 return 1; | 449 return 1; |
412 } | 450 } |
413 #ifdef OUTPUT_YUV_DENOISED | 451 #ifdef OUTPUT_YUV_DENOISED |
414 make_grayscale(&denoiser->running_avg_y[i]); | 452 make_grayscale(&denoiser->running_avg_y[i]); |
415 #endif | 453 #endif |
416 denoiser->increase_denoising = 0; | 454 denoiser->increase_denoising = 0; |
417 | 455 |
418 return 0; | 456 return 0; |
(...skipping 25 matching lines...) Expand all Loading... |
444 for (r = 0; r < yuv->uv_height / 2; ++r) { | 482 for (r = 0; r < yuv->uv_height / 2; ++r) { |
445 for (c = 0; c < yuv->uv_width / 2; ++c) { | 483 for (c = 0; c < yuv->uv_width / 2; ++c) { |
446 u[c] = UINT8_MAX / 2; | 484 u[c] = UINT8_MAX / 2; |
447 v[c] = UINT8_MAX / 2; | 485 v[c] = UINT8_MAX / 2; |
448 } | 486 } |
449 u += yuv->uv_stride + yuv->uv_width / 2; | 487 u += yuv->uv_stride + yuv->uv_width / 2; |
450 v += yuv->uv_stride + yuv->uv_width / 2; | 488 v += yuv->uv_stride + yuv->uv_width / 2; |
451 } | 489 } |
452 } | 490 } |
453 #endif | 491 #endif |
OLD | NEW |