Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(110)

Side by Side Diff: source/libvpx/vp8/encoder/denoising.c

Issue 478033002: libvpx: Pull from upstream (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/libvpx/
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « source/libvpx/vp8/encoder/denoising.h ('k') | source/libvpx/vp8/encoder/encodeframe.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « source/libvpx/vp8/encoder/denoising.h ('k') | source/libvpx/vp8/encoder/encodeframe.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698