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 <limits.h> |
| 12 |
11 #include "denoising.h" | 13 #include "denoising.h" |
12 | 14 |
13 #include "vp8/common/reconinter.h" | 15 #include "vp8/common/reconinter.h" |
14 #include "vpx/vpx_integer.h" | 16 #include "vpx/vpx_integer.h" |
15 #include "vpx_mem/vpx_mem.h" | 17 #include "vpx_mem/vpx_mem.h" |
16 #include "vp8_rtcd.h" | 18 #include "vp8_rtcd.h" |
17 | 19 |
18 static const unsigned int NOISE_MOTION_THRESHOLD = 25 * 25; | 20 static const unsigned int NOISE_MOTION_THRESHOLD = 25 * 25; |
19 /* SSE_DIFF_THRESHOLD is selected as ~95% confidence assuming | 21 /* SSE_DIFF_THRESHOLD is selected as ~95% confidence assuming |
20 * var(noise) ~= 100. | 22 * var(noise) ~= 100. |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 } else { | 328 } else { |
327 return COPY_BLOCK; | 329 return COPY_BLOCK; |
328 } | 330 } |
329 } | 331 } |
330 | 332 |
331 vp8_copy_mem8x8(running_avg_uv_start, avg_uv_stride, sig_start, | 333 vp8_copy_mem8x8(running_avg_uv_start, avg_uv_stride, sig_start, |
332 sig_stride); | 334 sig_stride); |
333 return FILTER_BLOCK; | 335 return FILTER_BLOCK; |
334 } | 336 } |
335 | 337 |
| 338 void vp8_denoiser_set_parameters(VP8_DENOISER *denoiser, int mode) { |
| 339 assert(mode > 0); // Denoiser is allocated only if mode > 0. |
| 340 if (mode == 1) { |
| 341 denoiser->denoiser_mode = kDenoiserOnYOnly; |
| 342 } else if (mode == 2) { |
| 343 denoiser->denoiser_mode = kDenoiserOnYUV; |
| 344 } else if (mode == 3) { |
| 345 denoiser->denoiser_mode = kDenoiserOnYUVAggressive; |
| 346 } else { |
| 347 denoiser->denoiser_mode = kDenoiserOnAdaptive; |
| 348 } |
| 349 if (denoiser->denoiser_mode != kDenoiserOnYUVAggressive) { |
| 350 denoiser->denoise_pars.scale_sse_thresh = 1; |
| 351 denoiser->denoise_pars.scale_motion_thresh = 8; |
| 352 denoiser->denoise_pars.scale_increase_filter = 0; |
| 353 denoiser->denoise_pars.denoise_mv_bias = 95; |
| 354 denoiser->denoise_pars.pickmode_mv_bias = 100; |
| 355 denoiser->denoise_pars.qp_thresh = 0; |
| 356 denoiser->denoise_pars.consec_zerolast = UINT_MAX; |
| 357 } else { |
| 358 denoiser->denoise_pars.scale_sse_thresh = 2; |
| 359 denoiser->denoise_pars.scale_motion_thresh = 16; |
| 360 denoiser->denoise_pars.scale_increase_filter = 1; |
| 361 denoiser->denoise_pars.denoise_mv_bias = 60; |
| 362 denoiser->denoise_pars.pickmode_mv_bias = 60; |
| 363 denoiser->denoise_pars.qp_thresh = 100; |
| 364 denoiser->denoise_pars.consec_zerolast = 10; |
| 365 } |
| 366 } |
| 367 |
336 int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height, | 368 int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height, |
337 int num_mb_rows, int num_mb_cols) | 369 int num_mb_rows, int num_mb_cols, int mode) |
338 { | 370 { |
339 int i; | 371 int i; |
340 assert(denoiser); | 372 assert(denoiser); |
341 denoiser->num_mb_cols = num_mb_cols; | 373 denoiser->num_mb_cols = num_mb_cols; |
342 | 374 |
343 for (i = 0; i < MAX_REF_FRAMES; i++) | 375 for (i = 0; i < MAX_REF_FRAMES; i++) |
344 { | 376 { |
345 denoiser->yv12_running_avg[i].flags = 0; | 377 denoiser->yv12_running_avg[i].flags = 0; |
346 | 378 |
347 if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_running_avg[i]), width, | 379 if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_running_avg[i]), width, |
(...skipping 12 matching lines...) Expand all Loading... |
360 if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_mc_running_avg), width, | 392 if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_mc_running_avg), width, |
361 height, VP8BORDERINPIXELS) < 0) | 393 height, VP8BORDERINPIXELS) < 0) |
362 { | 394 { |
363 vp8_denoiser_free(denoiser); | 395 vp8_denoiser_free(denoiser); |
364 return 1; | 396 return 1; |
365 } | 397 } |
366 | 398 |
367 vpx_memset(denoiser->yv12_mc_running_avg.buffer_alloc, 0, | 399 vpx_memset(denoiser->yv12_mc_running_avg.buffer_alloc, 0, |
368 denoiser->yv12_mc_running_avg.frame_size); | 400 denoiser->yv12_mc_running_avg.frame_size); |
369 | 401 |
| 402 if (vp8_yv12_alloc_frame_buffer(&denoiser->yv12_last_source, width, |
| 403 height, VP8BORDERINPIXELS) < 0) { |
| 404 vp8_denoiser_free(denoiser); |
| 405 return 1; |
| 406 } |
| 407 vpx_memset(denoiser->yv12_last_source.buffer_alloc, 0, |
| 408 denoiser->yv12_last_source.frame_size); |
| 409 |
370 denoiser->denoise_state = vpx_calloc((num_mb_rows * num_mb_cols), 1); | 410 denoiser->denoise_state = vpx_calloc((num_mb_rows * num_mb_cols), 1); |
371 vpx_memset(denoiser->denoise_state, 0, (num_mb_rows * num_mb_cols)); | 411 vpx_memset(denoiser->denoise_state, 0, (num_mb_rows * num_mb_cols)); |
372 | 412 vp8_denoiser_set_parameters(denoiser, mode); |
| 413 denoiser->nmse_source_diff = 0; |
| 414 denoiser->nmse_source_diff_count = 0; |
| 415 // TODO(marpan): Adjust thresholds, including effect on resolution. |
| 416 denoiser->threshold_aggressive_mode = 40; |
| 417 if (width * height > 640 * 480) |
| 418 denoiser->threshold_aggressive_mode = 180; |
373 return 0; | 419 return 0; |
374 } | 420 } |
375 | 421 |
| 422 |
376 void vp8_denoiser_free(VP8_DENOISER *denoiser) | 423 void vp8_denoiser_free(VP8_DENOISER *denoiser) |
377 { | 424 { |
378 int i; | 425 int i; |
379 assert(denoiser); | 426 assert(denoiser); |
380 | 427 |
381 for (i = 0; i < MAX_REF_FRAMES ; i++) | 428 for (i = 0; i < MAX_REF_FRAMES ; i++) |
382 { | 429 { |
383 vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_running_avg[i]); | 430 vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_running_avg[i]); |
384 } | 431 } |
385 vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_mc_running_avg); | 432 vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_mc_running_avg); |
386 vpx_free(denoiser->denoise_state); | 433 vpx_free(denoiser->denoise_state); |
387 } | 434 } |
388 | 435 |
389 | 436 |
390 void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser, | 437 void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser, |
391 MACROBLOCK *x, | 438 MACROBLOCK *x, |
392 unsigned int best_sse, | 439 unsigned int best_sse, |
393 unsigned int zero_mv_sse, | 440 unsigned int zero_mv_sse, |
394 int recon_yoffset, | 441 int recon_yoffset, |
395 int recon_uvoffset, | 442 int recon_uvoffset, |
396 loop_filter_info_n *lfi_n, | 443 loop_filter_info_n *lfi_n, |
397 int mb_row, | 444 int mb_row, |
398 int mb_col, | 445 int mb_col, |
399 int block_index, | 446 int block_index) |
400 int uv_denoise) | 447 |
401 { | 448 { |
402 int mv_row; | 449 int mv_row; |
403 int mv_col; | 450 int mv_col; |
| 451 unsigned int motion_threshold; |
404 unsigned int motion_magnitude2; | 452 unsigned int motion_magnitude2; |
405 unsigned int sse_thresh; | 453 unsigned int sse_thresh; |
406 int sse_diff_thresh = 0; | 454 int sse_diff_thresh = 0; |
407 // Spatial loop filter: only applied selectively based on | 455 // Spatial loop filter: only applied selectively based on |
408 // temporal filter state of block relative to top/left neighbors. | 456 // temporal filter state of block relative to top/left neighbors. |
409 int apply_spatial_loop_filter = 1; | 457 int apply_spatial_loop_filter = 1; |
410 MV_REFERENCE_FRAME frame = x->best_reference_frame; | 458 MV_REFERENCE_FRAME frame = x->best_reference_frame; |
411 MV_REFERENCE_FRAME zero_frame = x->best_zeromv_reference_frame; | 459 MV_REFERENCE_FRAME zero_frame = x->best_zeromv_reference_frame; |
412 | 460 |
413 enum vp8_denoiser_decision decision = FILTER_BLOCK; | 461 enum vp8_denoiser_decision decision = FILTER_BLOCK; |
414 enum vp8_denoiser_decision decision_u = COPY_BLOCK; | 462 enum vp8_denoiser_decision decision_u = COPY_BLOCK; |
415 enum vp8_denoiser_decision decision_v = COPY_BLOCK; | 463 enum vp8_denoiser_decision decision_v = COPY_BLOCK; |
416 | 464 |
417 if (zero_frame) | 465 if (zero_frame) |
418 { | 466 { |
419 YV12_BUFFER_CONFIG *src = &denoiser->yv12_running_avg[frame]; | 467 YV12_BUFFER_CONFIG *src = &denoiser->yv12_running_avg[frame]; |
420 YV12_BUFFER_CONFIG *dst = &denoiser->yv12_mc_running_avg; | 468 YV12_BUFFER_CONFIG *dst = &denoiser->yv12_mc_running_avg; |
421 YV12_BUFFER_CONFIG saved_pre,saved_dst; | 469 YV12_BUFFER_CONFIG saved_pre,saved_dst; |
422 MB_MODE_INFO saved_mbmi; | 470 MB_MODE_INFO saved_mbmi; |
423 MACROBLOCKD *filter_xd = &x->e_mbd; | 471 MACROBLOCKD *filter_xd = &x->e_mbd; |
424 MB_MODE_INFO *mbmi = &filter_xd->mode_info_context->mbmi; | 472 MB_MODE_INFO *mbmi = &filter_xd->mode_info_context->mbmi; |
425 int sse_diff = 0; | 473 int sse_diff = 0; |
426 // Bias on zero motion vector sse. | 474 // Bias on zero motion vector sse. |
427 int zero_bias = 95; | 475 const int zero_bias = denoiser->denoise_pars.denoise_mv_bias; |
428 zero_mv_sse = (unsigned int)((int64_t)zero_mv_sse * zero_bias / 100); | 476 zero_mv_sse = (unsigned int)((int64_t)zero_mv_sse * zero_bias / 100); |
429 sse_diff = zero_mv_sse - best_sse; | 477 sse_diff = zero_mv_sse - best_sse; |
430 | 478 |
431 saved_mbmi = *mbmi; | 479 saved_mbmi = *mbmi; |
432 | 480 |
433 /* Use the best MV for the compensation. */ | 481 /* Use the best MV for the compensation. */ |
434 mbmi->ref_frame = x->best_reference_frame; | 482 mbmi->ref_frame = x->best_reference_frame; |
435 mbmi->mode = x->best_sse_inter_mode; | 483 mbmi->mode = x->best_sse_inter_mode; |
436 mbmi->mv = x->best_sse_mv; | 484 mbmi->mv = x->best_sse_mv; |
437 mbmi->need_to_clamp_mvs = x->need_to_clamp_best_mvs; | 485 mbmi->need_to_clamp_mvs = x->need_to_clamp_best_mvs; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 } | 543 } |
496 filter_xd->pre = saved_pre; | 544 filter_xd->pre = saved_pre; |
497 filter_xd->dst = saved_dst; | 545 filter_xd->dst = saved_dst; |
498 *mbmi = saved_mbmi; | 546 *mbmi = saved_mbmi; |
499 | 547 |
500 } | 548 } |
501 | 549 |
502 mv_row = x->best_sse_mv.as_mv.row; | 550 mv_row = x->best_sse_mv.as_mv.row; |
503 mv_col = x->best_sse_mv.as_mv.col; | 551 mv_col = x->best_sse_mv.as_mv.col; |
504 motion_magnitude2 = mv_row * mv_row + mv_col * mv_col; | 552 motion_magnitude2 = mv_row * mv_row + mv_col * mv_col; |
505 sse_thresh = SSE_THRESHOLD; | 553 motion_threshold = denoiser->denoise_pars.scale_motion_thresh * |
506 if (x->increase_denoising) sse_thresh = SSE_THRESHOLD_HIGH; | 554 NOISE_MOTION_THRESHOLD; |
507 | 555 |
508 if (best_sse > sse_thresh || motion_magnitude2 | 556 if (motion_magnitude2 < |
509 > 8 * NOISE_MOTION_THRESHOLD) | 557 denoiser->denoise_pars.scale_increase_filter * NOISE_MOTION_THRESHOLD) |
510 { | 558 x->increase_denoising = 1; |
511 decision = COPY_BLOCK; | 559 |
512 } | 560 sse_thresh = denoiser->denoise_pars.scale_sse_thresh * SSE_THRESHOLD; |
| 561 if (x->increase_denoising) |
| 562 sse_thresh = denoiser->denoise_pars.scale_sse_thresh * SSE_THRESHOLD_HIGH; |
| 563 |
| 564 if (best_sse > sse_thresh || motion_magnitude2 > motion_threshold) |
| 565 decision = COPY_BLOCK; |
513 | 566 |
514 if (decision == FILTER_BLOCK) | 567 if (decision == FILTER_BLOCK) |
515 { | 568 { |
516 unsigned char *mc_running_avg_y = | 569 unsigned char *mc_running_avg_y = |
517 denoiser->yv12_mc_running_avg.y_buffer + recon_yoffset; | 570 denoiser->yv12_mc_running_avg.y_buffer + recon_yoffset; |
518 int mc_avg_y_stride = denoiser->yv12_mc_running_avg.y_stride; | 571 int mc_avg_y_stride = denoiser->yv12_mc_running_avg.y_stride; |
519 unsigned char *running_avg_y = | 572 unsigned char *running_avg_y = |
520 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset; | 573 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset; |
521 int avg_y_stride = denoiser->yv12_running_avg[INTRA_FRAME].y_stride; | 574 int avg_y_stride = denoiser->yv12_running_avg[INTRA_FRAME].y_stride; |
522 | 575 |
523 /* Filter. */ | 576 /* Filter. */ |
524 decision = vp8_denoiser_filter(mc_running_avg_y, mc_avg_y_stride, | 577 decision = vp8_denoiser_filter(mc_running_avg_y, mc_avg_y_stride, |
525 running_avg_y, avg_y_stride, | 578 running_avg_y, avg_y_stride, |
526 x->thismb, 16, motion_magnitude2, | 579 x->thismb, 16, motion_magnitude2, |
527 x->increase_denoising); | 580 x->increase_denoising); |
528 denoiser->denoise_state[block_index] = motion_magnitude2 > 0 ? | 581 denoiser->denoise_state[block_index] = motion_magnitude2 > 0 ? |
529 kFilterNonZeroMV : kFilterZeroMV; | 582 kFilterNonZeroMV : kFilterZeroMV; |
530 // Only denoise UV for zero motion, and if y channel was denoised. | 583 // Only denoise UV for zero motion, and if y channel was denoised. |
531 if (uv_denoise && | 584 if (denoiser->denoiser_mode != kDenoiserOnYOnly && |
532 motion_magnitude2 == 0 && | 585 motion_magnitude2 == 0 && |
533 decision == FILTER_BLOCK) { | 586 decision == FILTER_BLOCK) { |
534 unsigned char *mc_running_avg_u = | 587 unsigned char *mc_running_avg_u = |
535 denoiser->yv12_mc_running_avg.u_buffer + recon_uvoffset; | 588 denoiser->yv12_mc_running_avg.u_buffer + recon_uvoffset; |
536 unsigned char *running_avg_u = | 589 unsigned char *running_avg_u = |
537 denoiser->yv12_running_avg[INTRA_FRAME].u_buffer + recon_uvoffset; | 590 denoiser->yv12_running_avg[INTRA_FRAME].u_buffer + recon_uvoffset; |
538 unsigned char *mc_running_avg_v = | 591 unsigned char *mc_running_avg_v = |
539 denoiser->yv12_mc_running_avg.v_buffer + recon_uvoffset; | 592 denoiser->yv12_mc_running_avg.v_buffer + recon_uvoffset; |
540 unsigned char *running_avg_v = | 593 unsigned char *running_avg_v = |
541 denoiser->yv12_running_avg[INTRA_FRAME].v_buffer + recon_uvoffset; | 594 denoiser->yv12_running_avg[INTRA_FRAME].v_buffer + recon_uvoffset; |
(...skipping 16 matching lines...) Expand all Loading... |
558 { | 611 { |
559 /* No filtering of this block; it differs too much from the predictor, | 612 /* No filtering of this block; it differs too much from the predictor, |
560 * or the motion vector magnitude is considered too big. | 613 * or the motion vector magnitude is considered too big. |
561 */ | 614 */ |
562 vp8_copy_mem16x16( | 615 vp8_copy_mem16x16( |
563 x->thismb, 16, | 616 x->thismb, 16, |
564 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset
, | 617 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset
, |
565 denoiser->yv12_running_avg[INTRA_FRAME].y_stride); | 618 denoiser->yv12_running_avg[INTRA_FRAME].y_stride); |
566 denoiser->denoise_state[block_index] = kNoFilter; | 619 denoiser->denoise_state[block_index] = kNoFilter; |
567 } | 620 } |
568 if (uv_denoise) { | 621 if (denoiser->denoiser_mode != kDenoiserOnYOnly) { |
569 if (decision_u == COPY_BLOCK) { | 622 if (decision_u == COPY_BLOCK) { |
570 vp8_copy_mem8x8( | 623 vp8_copy_mem8x8( |
571 x->block[16].src + *x->block[16].base_src, x->block[16].src_stride, | 624 x->block[16].src + *x->block[16].base_src, x->block[16].src_stride, |
572 denoiser->yv12_running_avg[INTRA_FRAME].u_buffer + recon_uvoffset, | 625 denoiser->yv12_running_avg[INTRA_FRAME].u_buffer + recon_uvoffset, |
573 denoiser->yv12_running_avg[INTRA_FRAME].uv_stride); | 626 denoiser->yv12_running_avg[INTRA_FRAME].uv_stride); |
574 } | 627 } |
575 if (decision_v == COPY_BLOCK) { | 628 if (decision_v == COPY_BLOCK) { |
576 vp8_copy_mem8x8( | 629 vp8_copy_mem8x8( |
577 x->block[20].src + *x->block[20].base_src, x->block[16].src_stride, | 630 x->block[20].src + *x->block[20].base_src, x->block[16].src_stride, |
578 denoiser->yv12_running_avg[INTRA_FRAME].v_buffer + recon_uvoffset, | 631 denoiser->yv12_running_avg[INTRA_FRAME].v_buffer + recon_uvoffset, |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
626 } | 679 } |
627 if (apply_filter) { | 680 if (apply_filter) { |
628 // Update the signal block |x|. Pixel changes are only to top and/or | 681 // Update the signal block |x|. Pixel changes are only to top and/or |
629 // left boundary pixels: can we avoid full block copy here. | 682 // left boundary pixels: can we avoid full block copy here. |
630 vp8_copy_mem16x16( | 683 vp8_copy_mem16x16( |
631 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset, | 684 denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset, |
632 y_stride, x->thismb, 16); | 685 y_stride, x->thismb, 16); |
633 } | 686 } |
634 } | 687 } |
635 } | 688 } |
OLD | NEW |