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