| 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 |