vp9_denoiser.c 23.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
/*
 *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

Tim Kopp's avatar
Tim Kopp committed
11
#include <assert.h>
12
#include <limits.h>
13 14
#include <math.h>

Zoe Liu's avatar
Zoe Liu committed
15
#include "./vpx_dsp_rtcd.h"
16
#include "vpx_dsp/vpx_dsp_common.h"
17
#include "vpx_scale/yv12config.h"
Tim Kopp's avatar
Tim Kopp committed
18
#include "vpx/vpx_integer.h"
19
#include "vp9/common/vp9_reconinter.h"
20
#include "vp9/encoder/vp9_context_tree.h"
Tim Kopp's avatar
Tim Kopp committed
21
#include "vp9/encoder/vp9_denoiser.h"
22
#include "vp9/encoder/vp9_encoder.h"
23

24 25 26 27
#ifdef OUTPUT_YUV_DENOISED
static void make_grayscale(YV12_BUFFER_CONFIG *yuv);
#endif

28 29 30 31 32 33 34 35 36 37 38 39 40 41
static int absdiff_thresh(BLOCK_SIZE bs, int increase_denoising) {
  (void)bs;
  return 3 + (increase_denoising ? 1 : 0);
}

static int delta_thresh(BLOCK_SIZE bs, int increase_denoising) {
  (void)bs;
  (void)increase_denoising;
  return 4;
}

static int noise_motion_thresh(BLOCK_SIZE bs, int increase_denoising) {
  (void)bs;
  (void)increase_denoising;
42
  return 625;
43 44 45
}

static unsigned int sse_thresh(BLOCK_SIZE bs, int increase_denoising) {
46
  return (1 << num_pels_log2_lookup[bs]) * (increase_denoising ? 80 : 40);
47 48 49
}

static int sse_diff_thresh(BLOCK_SIZE bs, int increase_denoising,
50
                           int motion_magnitude) {
51
  if (motion_magnitude > noise_motion_thresh(bs, increase_denoising)) {
52 53 54 55
    if (increase_denoising)
      return (1 << num_pels_log2_lookup[bs]) << 2;
    else
      return 0;
56
  } else {
57
    return (1 << num_pels_log2_lookup[bs]) << 4;
58 59 60 61
  }
}

static int total_adj_weak_thresh(BLOCK_SIZE bs, int increase_denoising) {
62
  return (1 << num_pels_log2_lookup[bs]) * (increase_denoising ? 3 : 2);
63 64
}

65 66 67 68
// TODO(jackychen): If increase_denoising is enabled in the future,
// we might need to update the code for calculating 'total_adj' in
// case the C code is not bit-exact with corresponding sse2 code.
int vp9_denoiser_filter_c(const uint8_t *sig, int sig_stride,
69 70 71
                          const uint8_t *mc_avg, int mc_avg_stride,
                          uint8_t *avg, int avg_stride, int increase_denoising,
                          BLOCK_SIZE bs, int motion_magnitude) {
72
  int r, c;
73 74 75 76
  const uint8_t *sig_start = sig;
  const uint8_t *mc_avg_start = mc_avg;
  uint8_t *avg_start = avg;
  int diff, adj, absdiff, delta;
77
  int adj_val[] = { 3, 4, 6 };
78
  int total_adj = 0;
79 80
  int shift_inc = 1;

81 82 83
  // If motion_magnitude is small, making the denoiser more aggressive by
  // increasing the adjustment for each level. Add another increment for
  // blocks that are labeled for increase denoising.
84 85 86 87 88 89 90 91
  if (motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD) {
    if (increase_denoising) {
      shift_inc = 2;
    }
    adj_val[0] += shift_inc;
    adj_val[1] += shift_inc;
    adj_val[2] += shift_inc;
  }
92

93
  // First attempt to apply a strong temporal denoising filter.
94 95
  for (r = 0; r < (4 << b_height_log2_lookup[bs]); ++r) {
    for (c = 0; c < (4 << b_width_log2_lookup[bs]); ++c) {
96
      diff = mc_avg[c] - sig[c];
97
      absdiff = abs(diff);
98

99
      if (absdiff <= absdiff_thresh(bs, increase_denoising)) {
100 101
        avg[c] = mc_avg[c];
        total_adj += diff;
102
      } else {
103
        switch (absdiff) {
104 105 106 107 108 109 110 111 112 113 114 115 116
          case 4:
          case 5:
          case 6:
          case 7: adj = adj_val[0]; break;
          case 8:
          case 9:
          case 10:
          case 11:
          case 12:
          case 13:
          case 14:
          case 15: adj = adj_val[1]; break;
          default: adj = adj_val[2];
117 118
        }
        if (diff > 0) {
119
          avg[c] = VPXMIN(UINT8_MAX, sig[c] + adj);
120 121
          total_adj += adj;
        } else {
122
          avg[c] = VPXMAX(0, sig[c] - adj);
123 124
          total_adj -= adj;
        }
125 126 127 128 129 130
      }
    }
    sig += sig_stride;
    avg += avg_stride;
    mc_avg += mc_avg_stride;
  }
131 132 133 134 135 136 137

  // If the strong filter did not modify the signal too much, we're all set.
  if (abs(total_adj) <= total_adj_strong_thresh(bs, increase_denoising)) {
    return FILTER_BLOCK;
  }

  // Otherwise, we try to dampen the filter if the delta is not too high.
138 139 140
  delta = ((abs(total_adj) - total_adj_strong_thresh(bs, increase_denoising)) >>
           num_pels_log2_lookup[bs]) +
          1;
141 142

  if (delta >= delta_thresh(bs, increase_denoising)) {
143 144 145
    return COPY_BLOCK;
  }

146
  mc_avg = mc_avg_start;
147 148
  avg = avg_start;
  sig = sig_start;
149 150
  for (r = 0; r < (4 << b_height_log2_lookup[bs]); ++r) {
    for (c = 0; c < (4 << b_width_log2_lookup[bs]); ++c) {
151 152 153 154 155 156
      diff = mc_avg[c] - sig[c];
      adj = abs(diff);
      if (adj > delta) {
        adj = delta;
      }
      if (diff > 0) {
JackyChen's avatar
JackyChen committed
157 158 159
        // Diff positive means we made positive adjustment above
        // (in first try/attempt), so now make negative adjustment to bring
        // denoised signal down.
160
        avg[c] = VPXMAX(0, avg[c] - adj);
JackyChen's avatar
JackyChen committed
161
        total_adj -= adj;
162
      } else {
JackyChen's avatar
JackyChen committed
163 164 165
        // Diff negative means we made negative adjustment above
        // (in first try/attempt), so now make positive adjustment to bring
        // denoised signal up.
166
        avg[c] = VPXMIN(UINT8_MAX, avg[c] + adj);
JackyChen's avatar
JackyChen committed
167
        total_adj += adj;
168 169 170 171 172 173 174 175 176 177 178 179
      }
    }
    sig += sig_stride;
    avg += avg_stride;
    mc_avg += mc_avg_stride;
  }

  // We can use the filter if it has been sufficiently dampened
  if (abs(total_adj) <= total_adj_weak_thresh(bs, increase_denoising)) {
    return FILTER_BLOCK;
  }
  return COPY_BLOCK;
180 181
}

182 183 184
static uint8_t *block_start(uint8_t *framebuf, int stride, int mi_row,
                            int mi_col) {
  return framebuf + (stride * mi_row << 3) + (mi_col << 3);
185 186
}

187
static VP9_DENOISER_DECISION perform_motion_compensation(
188
    VP9_COMMON *const cm, VP9_DENOISER *denoiser, MACROBLOCK *mb, BLOCK_SIZE bs,
189
    int increase_denoising, int mi_row, int mi_col, PICK_MODE_CONTEXT *ctx,
190
    int motion_magnitude, int is_skin, int *zeromv_filter, int consec_zeromv,
191 192
    int num_spatial_layers, int width, int lst_fb_idx, int gld_fb_idx,
    int use_svc) {
193 194 195
  const int sse_diff = (ctx->newmv_sse == UINT_MAX)
                           ? 0
                           : ((int)ctx->zeromv_sse - (int)ctx->newmv_sse);
196
  int frame;
197
  MACROBLOCKD *filter_mbd = &mb->e_mbd;
198 199
  MODE_INFO *mi = filter_mbd->mi[0];
  MODE_INFO saved_mi;
200
  int i;
Tim Kopp's avatar
Tim Kopp committed
201
  struct buf_2d saved_dst[MAX_MB_PLANE];
202
  struct buf_2d saved_pre[MAX_MB_PLANE];
203
  RefBuffer *saved_block_refs[2];
204
  MV_REFERENCE_FRAME saved_frame;
Tim Kopp's avatar
Tim Kopp committed
205

206
  frame = ctx->best_reference_frame;
207

208
  saved_mi = *mi;
209

210
  if (is_skin && (motion_magnitude > 0 || consec_zeromv < 4)) return COPY_BLOCK;
211

212 213 214 215 216
  // Avoid denoising small blocks. When noise > kDenLow or frame width > 480,
  // denoise 16x16 blocks.
  if (bs == BLOCK_8X8 || bs == BLOCK_8X16 || bs == BLOCK_16X8 ||
      (bs == BLOCK_16X16 && width > 480 &&
       denoiser->denoising_level <= kDenLow))
217 218
    return COPY_BLOCK;

219 220
  // If the best reference frame uses inter-prediction and there is enough of a
  // difference in sum-squared-error, use it.
221
  if (frame != INTRA_FRAME && frame != ALTREF_FRAME &&
222
      (frame != GOLDEN_FRAME || num_spatial_layers == 1) &&
Marco's avatar
Marco committed
223
      sse_diff > sse_diff_thresh(bs, increase_denoising, motion_magnitude)) {
224 225 226
    mi->ref_frame[0] = ctx->best_reference_frame;
    mi->mode = ctx->best_sse_inter_mode;
    mi->mv[0] = ctx->best_sse_mv;
227 228
  } else {
    // Otherwise, use the zero reference frame.
229
    frame = ctx->best_zeromv_reference_frame;
230 231
    ctx->newmv_sse = ctx->zeromv_sse;
    // Bias to last reference.
232
    if (num_spatial_layers > 1 || frame == ALTREF_FRAME ||
233 234 235
        (frame != LAST_FRAME &&
         ((ctx->zeromv_lastref_sse<(5 * ctx->zeromv_sse)>> 2) ||
          denoiser->denoising_level >= kDenHigh))) {
236 237 238
      frame = LAST_FRAME;
      ctx->newmv_sse = ctx->zeromv_lastref_sse;
    }
239 240 241
    mi->ref_frame[0] = frame;
    mi->mode = ZEROMV;
    mi->mv[0].as_int = 0;
242 243
    ctx->best_sse_inter_mode = ZEROMV;
    ctx->best_sse_mv.as_int = 0;
244
    *zeromv_filter = 1;
245 246 247
    if (denoiser->denoising_level > kDenMedium) {
      motion_magnitude = 0;
    }
248 249
  }

250 251 252 253 254 255 256 257 258
  saved_frame = frame;
  // When using SVC, we need to map REF_FRAME to the frame buffer index.
  if (use_svc) {
    if (frame == LAST_FRAME)
      frame = lst_fb_idx + 1;
    else if (frame == GOLDEN_FRAME)
      frame = gld_fb_idx + 1;
  }

259 260
  if (ctx->newmv_sse > sse_thresh(bs, increase_denoising)) {
    // Restore everything to its original state
261
    *mi = saved_mi;
262 263
    return COPY_BLOCK;
  }
264
  if (motion_magnitude > (noise_motion_thresh(bs, increase_denoising) << 3)) {
265
    // Restore everything to its original state
266
    *mi = saved_mi;
267 268 269 270 271
    return COPY_BLOCK;
  }

  // We will restore these after motion compensation.
  for (i = 0; i < MAX_MB_PLANE; ++i) {
272
    saved_pre[i] = filter_mbd->plane[i].pre[0];
273 274
    saved_dst[i] = filter_mbd->plane[i].dst;
  }
275
  saved_block_refs[0] = filter_mbd->block_refs[0];
276

277 278
  // Set the pointers in the MACROBLOCKD to point to the buffers in the denoiser
  // struct.
279 280
  filter_mbd->plane[0].pre[0].buf =
      block_start(denoiser->running_avg_y[frame].y_buffer,
281 282
                  denoiser->running_avg_y[frame].y_stride, mi_row, mi_col);
  filter_mbd->plane[0].pre[0].stride = denoiser->running_avg_y[frame].y_stride;
283
  filter_mbd->plane[1].pre[0].buf =
284 285 286
      block_start(denoiser->running_avg_y[frame].u_buffer,
                  denoiser->running_avg_y[frame].uv_stride, mi_row, mi_col);
  filter_mbd->plane[1].pre[0].stride = denoiser->running_avg_y[frame].uv_stride;
287 288
  filter_mbd->plane[2].pre[0].buf =
      block_start(denoiser->running_avg_y[frame].v_buffer,
289 290
                  denoiser->running_avg_y[frame].uv_stride, mi_row, mi_col);
  filter_mbd->plane[2].pre[0].stride = denoiser->running_avg_y[frame].uv_stride;
291

292 293
  filter_mbd->plane[0].dst.buf =
      block_start(denoiser->mc_running_avg_y.y_buffer,
294
                  denoiser->mc_running_avg_y.y_stride, mi_row, mi_col);
295 296 297
  filter_mbd->plane[0].dst.stride = denoiser->mc_running_avg_y.y_stride;
  filter_mbd->plane[1].dst.buf =
      block_start(denoiser->mc_running_avg_y.u_buffer,
298
                  denoiser->mc_running_avg_y.uv_stride, mi_row, mi_col);
Tim Kopp's avatar
Tim Kopp committed
299
  filter_mbd->plane[1].dst.stride = denoiser->mc_running_avg_y.uv_stride;
300 301
  filter_mbd->plane[2].dst.buf =
      block_start(denoiser->mc_running_avg_y.v_buffer,
302
                  denoiser->mc_running_avg_y.uv_stride, mi_row, mi_col);
Tim Kopp's avatar
Tim Kopp committed
303
  filter_mbd->plane[2].dst.stride = denoiser->mc_running_avg_y.uv_stride;
304

305
  set_ref_ptrs(cm, filter_mbd, saved_frame, NONE);
306
  vp9_build_inter_predictors_sby(filter_mbd, mi_row, mi_col, bs);
307 308

  // Restore everything to its original state
309
  *mi = saved_mi;
310
  filter_mbd->block_refs[0] = saved_block_refs[0];
Tim Kopp's avatar
Tim Kopp committed
311
  for (i = 0; i < MAX_MB_PLANE; ++i) {
312
    filter_mbd->plane[i].pre[0] = saved_pre[i];
Tim Kopp's avatar
Tim Kopp committed
313 314
    filter_mbd->plane[i].dst = saved_dst[i];
  }
315 316 317 318

  return FILTER_BLOCK;
}

319 320
void vp9_denoiser_denoise(VP9_COMP *cpi, MACROBLOCK *mb, int mi_row, int mi_col,
                          BLOCK_SIZE bs, PICK_MODE_CONTEXT *ctx,
321
                          VP9_DENOISER_DECISION *denoiser_decision) {
Marco's avatar
Marco committed
322
  int mv_col, mv_row;
323
  int motion_magnitude = 0;
324
  int zeromv_filter = 0;
325
  VP9_DENOISER *denoiser = &cpi->denoiser;
326
  VP9_DENOISER_DECISION decision = COPY_BLOCK;
327
  YV12_BUFFER_CONFIG avg = denoiser->running_avg_y[INTRA_FRAME];
328 329
  YV12_BUFFER_CONFIG mc_avg = denoiser->mc_running_avg_y;
  uint8_t *avg_start = block_start(avg.y_buffer, avg.y_stride, mi_row, mi_col);
330 331
  uint8_t *mc_avg_start =
      block_start(mc_avg.y_buffer, mc_avg.y_stride, mi_row, mi_col);
332
  struct buf_2d src = mb->plane[0].src;
333
  int is_skin = 0;
334
  int increase_denoising = 0;
335
  int consec_zeromv = 0;
336 337 338
  mv_col = ctx->best_sse_mv.as_mv.col;
  mv_row = ctx->best_sse_mv.as_mv.row;
  motion_magnitude = mv_row * mv_row + mv_col * mv_col;
339

340
  if (cpi->use_skin_detection && bs <= BLOCK_32X32 &&
341
      denoiser->denoising_level < kDenHigh) {
342 343 344 345
    int motion_level = (motion_magnitude < 16) ? 0 : 1;
    // If motion for current block is small/zero, compute consec_zeromv for
    // skin detection (early exit in skin detection is done for large
    // consec_zeromv when current block has small/zero motion).
346
    consec_zeromv = 0;
347
    if (motion_level == 0) {
348
      VP9_COMMON *const cm = &cpi->common;
349 350
      int j, i;
      // Loop through the 8x8 sub-blocks.
351 352
      const int bw = num_8x8_blocks_wide_lookup[bs];
      const int bh = num_8x8_blocks_high_lookup[bs];
353 354 355 356 357 358 359
      const int xmis = VPXMIN(cm->mi_cols - mi_col, bw);
      const int ymis = VPXMIN(cm->mi_rows - mi_row, bh);
      const int block_index = mi_row * cm->mi_cols + mi_col;
      consec_zeromv = 100;
      for (i = 0; i < ymis; i++) {
        for (j = 0; j < xmis; j++) {
          int bl_index = block_index + i * cm->mi_cols + j;
360
          consec_zeromv = VPXMIN(cpi->consec_zero_mv[bl_index], consec_zeromv);
361 362
          // No need to keep checking 8x8 blocks if any of the sub-blocks
          // has small consec_zeromv (since threshold for no_skin based on
363 364
          // zero/small motion in skin detection is high, i.e, > 4).
          if (consec_zeromv < 4) {
365 366 367 368 369 370 371
            i = ymis;
            j = xmis;
          }
        }
      }
    }
    // TODO(marpan): Compute skin detection over sub-blocks.
372 373 374 375
    is_skin = vp9_compute_skin_block(
        mb->plane[0].src.buf, mb->plane[1].src.buf, mb->plane[2].src.buf,
        mb->plane[0].src.stride, mb->plane[1].src.stride, bs, consec_zeromv,
        motion_level);
376
  }
377
  if (!is_skin && denoiser->denoising_level == kDenHigh) increase_denoising = 1;
Marco's avatar
Marco committed
378

379
  if (denoiser->denoising_level >= kDenLow && !ctx->sb_skip_denoising)
380
    decision = perform_motion_compensation(
381
        &cpi->common, denoiser, mb, bs, increase_denoising, mi_row, mi_col, ctx,
382
        motion_magnitude, is_skin, &zeromv_filter, consec_zeromv,
383 384
        cpi->svc.number_spatial_layers, cpi->Source->y_width, cpi->lst_fb_idx,
        cpi->gld_fb_idx, cpi->use_svc);
385 386

  if (decision == FILTER_BLOCK) {
387 388 389
    decision = vp9_denoiser_filter(src.buf, src.stride, mc_avg_start,
                                   mc_avg.y_stride, avg_start, avg.y_stride,
                                   increase_denoising, bs, motion_magnitude);
390
  }
391 392

  if (decision == FILTER_BLOCK) {
393 394
    vpx_convolve_copy(avg_start, avg.y_stride, src.buf, src.stride, NULL, 0, 0,
                      0, 0, num_4x4_blocks_wide_lookup[bs] << 2,
395
                      num_4x4_blocks_high_lookup[bs] << 2);
396
  } else {  // COPY_BLOCK
397 398
    vpx_convolve_copy(src.buf, src.stride, avg_start, avg.y_stride, NULL, 0, 0,
                      0, 0, num_4x4_blocks_wide_lookup[bs] << 2,
399
                      num_4x4_blocks_high_lookup[bs] << 2);
400
  }
401
  *denoiser_decision = decision;
402 403
  if (decision == FILTER_BLOCK && zeromv_filter == 1)
    *denoiser_decision = FILTER_ZEROMV_BLOCK;
404 405
}

406 407
static void copy_frame(YV12_BUFFER_CONFIG *const dest,
                       const YV12_BUFFER_CONFIG *const src) {
408
  int r;
409 410
  const uint8_t *srcbuf = src->y_buffer;
  uint8_t *destbuf = dest->y_buffer;
411

412 413
  assert(dest->y_width == src->y_width);
  assert(dest->y_height == src->y_height);
414

415 416 417 418
  for (r = 0; r < dest->y_height; ++r) {
    memcpy(destbuf, srcbuf, dest->y_width);
    destbuf += dest->y_stride;
    srcbuf += src->y_stride;
419
  }
420 421
}

422 423
static void swap_frame_buffer(YV12_BUFFER_CONFIG *const dest,
                              YV12_BUFFER_CONFIG *const src) {
424 425 426 427 428
  uint8_t *tmp_buf = dest->y_buffer;
  assert(dest->y_width == src->y_width);
  assert(dest->y_height == src->y_height);
  dest->y_buffer = src->y_buffer;
  src->y_buffer = tmp_buf;
429 430
}

431 432 433
void vp9_denoiser_update_frame_info(
    VP9_DENOISER *denoiser, YV12_BUFFER_CONFIG src, FRAME_TYPE frame_type,
    int refresh_alt_ref_frame, int refresh_golden_frame, int refresh_last_frame,
434 435
    int alt_fb_idx, int gld_fb_idx, int lst_fb_idx, int resized,
    int svc_base_is_key) {
436
  // Copy source into denoised reference buffers on KEY_FRAME or
437 438 439 440
  // if the just encoded frame was resized. For SVC, copy source if the base
  // spatial layer was key frame.
  if (frame_type == KEY_FRAME || resized != 0 || denoiser->reset ||
      svc_base_is_key) {
Tim Kopp's avatar
Tim Kopp committed
441
    int i;
442
    // Start at 1 so as not to overwrite the INTRA_FRAME
443 444 445 446
    for (i = 1; i < denoiser->num_ref_frames; ++i) {
      if (denoiser->running_avg_y[i].buffer_alloc != NULL)
        copy_frame(&denoiser->running_avg_y[i], &src);
    }
447
    denoiser->reset = 0;
448 449 450
    return;
  }

451
  // If more than one refresh occurs, must copy frame buffer.
452 453 454 455 456
  if ((refresh_alt_ref_frame + refresh_golden_frame + refresh_last_frame) > 1) {
    if (refresh_alt_ref_frame) {
      copy_frame(&denoiser->running_avg_y[alt_fb_idx + 1],
                 &denoiser->running_avg_y[INTRA_FRAME]);
    }
457
    if (refresh_golden_frame) {
458
      copy_frame(&denoiser->running_avg_y[gld_fb_idx + 1],
459
                 &denoiser->running_avg_y[INTRA_FRAME]);
460
    }
461 462
    if (refresh_last_frame) {
      copy_frame(&denoiser->running_avg_y[lst_fb_idx + 1],
463
                 &denoiser->running_avg_y[INTRA_FRAME]);
464 465
    }
  } else {
466 467 468 469
    if (refresh_alt_ref_frame) {
      swap_frame_buffer(&denoiser->running_avg_y[alt_fb_idx + 1],
                        &denoiser->running_avg_y[INTRA_FRAME]);
    }
470
    if (refresh_golden_frame) {
471
      swap_frame_buffer(&denoiser->running_avg_y[gld_fb_idx + 1],
472 473
                        &denoiser->running_avg_y[INTRA_FRAME]);
    }
474 475
    if (refresh_last_frame) {
      swap_frame_buffer(&denoiser->running_avg_y[lst_fb_idx + 1],
476 477
                        &denoiser->running_avg_y[INTRA_FRAME]);
    }
478
  }
479 480
}

481 482
void vp9_denoiser_reset_frame_stats(PICK_MODE_CONTEXT *ctx) {
  ctx->zeromv_sse = UINT_MAX;
Marco's avatar
Marco committed
483
  ctx->newmv_sse = UINT_MAX;
484
  ctx->zeromv_lastref_sse = UINT_MAX;
485
  ctx->best_sse_mv.as_int = 0;
486 487
}

488
void vp9_denoiser_update_frame_stats(MODE_INFO *mi, unsigned int sse,
489
                                     PREDICTION_MODE mode,
490
                                     PICK_MODE_CONTEXT *ctx) {
491
  if (mi->mv[0].as_int == 0 && sse < ctx->zeromv_sse) {
492
    ctx->zeromv_sse = sse;
493
    ctx->best_zeromv_reference_frame = mi->ref_frame[0];
494
    if (mi->ref_frame[0] == LAST_FRAME) ctx->zeromv_lastref_sse = sse;
495 496
  }

497
  if (mi->mv[0].as_int != 0 && sse < ctx->newmv_sse) {
498 499
    ctx->newmv_sse = sse;
    ctx->best_sse_inter_mode = mode;
500 501
    ctx->best_sse_mv = mi->mv[0];
    ctx->best_reference_frame = mi->ref_frame[0];
502
  }
503 504
}

505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
static int vp9_denoiser_realloc_svc_helper(VP9_COMMON *cm,
                                           VP9_DENOISER *denoiser, int fb_idx) {
  int fail = 0;
  if (denoiser->running_avg_y[fb_idx].buffer_alloc == NULL) {
    fail =
        vpx_alloc_frame_buffer(&denoiser->running_avg_y[fb_idx], cm->width,
                               cm->height, cm->subsampling_x, cm->subsampling_y,
#if CONFIG_VP9_HIGHBITDEPTH
                               cm->use_highbitdepth,
#endif
                               VP9_ENC_BORDER_IN_PIXELS, 0);
    if (fail) {
      vp9_denoiser_free(denoiser);
      return 1;
    }
  }
  return 0;
}

int vp9_denoiser_realloc_svc(VP9_COMMON *cm, VP9_DENOISER *denoiser,
                             int refresh_alt, int refresh_gld, int refresh_lst,
                             int alt_fb_idx, int gld_fb_idx, int lst_fb_idx) {
  int fail = 0;
  if (refresh_alt) {
    // Increase the frame buffer index by 1 to map it to the buffer index in the
    // denoiser.
    fail = vp9_denoiser_realloc_svc_helper(cm, denoiser, alt_fb_idx + 1);
    if (fail) return 1;
  }
  if (refresh_gld) {
    fail = vp9_denoiser_realloc_svc_helper(cm, denoiser, gld_fb_idx + 1);
    if (fail) return 1;
  }
  if (refresh_lst) {
    fail = vp9_denoiser_realloc_svc_helper(cm, denoiser, lst_fb_idx + 1);
    if (fail) return 1;
  }
  return 0;
}

545 546
int vp9_denoiser_alloc(VP9_COMMON *cm, int use_svc, VP9_DENOISER *denoiser,
                       int width, int height, int ssx, int ssy,
547 548 549 550
#if CONFIG_VP9_HIGHBITDEPTH
                       int use_highbitdepth,
#endif
                       int border) {
551
  int i, fail, init_num_ref_frames;
552
  const int legacy_byte_alignment = 0;
Tim Kopp's avatar
Tim Kopp committed
553
  assert(denoiser != NULL);
554

555 556
  denoiser->num_ref_frames = use_svc ? SVC_REF_FRAMES : NONSVC_REF_FRAMES;
  init_num_ref_frames = use_svc ? MAX_REF_FRAMES : NONSVC_REF_FRAMES;
557 558 559
  CHECK_MEM_ERROR(
      cm, denoiser->running_avg_y,
      vpx_calloc(denoiser->num_ref_frames, sizeof(denoiser->running_avg_y[0])));
560
  for (i = 0; i < init_num_ref_frames; ++i) {
561
    fail = vpx_alloc_frame_buffer(&denoiser->running_avg_y[i], width, height,
562 563 564 565
                                  ssx, ssy,
#if CONFIG_VP9_HIGHBITDEPTH
                                  use_highbitdepth,
#endif
566
                                  border, legacy_byte_alignment);
567 568 569 570
    if (fail) {
      vp9_denoiser_free(denoiser);
      return 1;
    }
571 572 573
#ifdef OUTPUT_YUV_DENOISED
    make_grayscale(&denoiser->running_avg_y[i]);
#endif
574 575
  }

576 577
  fail = vpx_alloc_frame_buffer(&denoiser->mc_running_avg_y, width, height, ssx,
                                ssy,
578 579
#if CONFIG_VP9_HIGHBITDEPTH
                                use_highbitdepth,
580 581 582 583 584 585 586
#endif
                                border, legacy_byte_alignment);
  if (fail) {
    vp9_denoiser_free(denoiser);
    return 1;
  }

587
  fail = vpx_alloc_frame_buffer(&denoiser->last_source, width, height, ssx, ssy,
588 589
#if CONFIG_VP9_HIGHBITDEPTH
                                use_highbitdepth,
590
#endif
591
                                border, legacy_byte_alignment);
592
  if (fail) {
593 594 595
    vp9_denoiser_free(denoiser);
    return 1;
  }
596 597 598
#ifdef OUTPUT_YUV_DENOISED
  make_grayscale(&denoiser->running_avg_y[i]);
#endif
599
  denoiser->frame_buffer_initialized = 1;
600
  denoiser->denoising_level = kDenLow;
601 602
  denoiser->prev_denoising_level = kDenLow;
  denoiser->reset = 0;
603 604 605 606
  return 0;
}

void vp9_denoiser_free(VP9_DENOISER *denoiser) {
607
  int i;
Tim Kopp's avatar
Tim Kopp committed
608 609 610
  if (denoiser == NULL) {
    return;
  }
611
  denoiser->frame_buffer_initialized = 0;
612
  for (i = 0; i < denoiser->num_ref_frames; ++i) {
613
    vpx_free_frame_buffer(&denoiser->running_avg_y[i]);
614
  }
615 616
  vpx_free(denoiser->running_avg_y);
  denoiser->running_avg_y = NULL;
617
  vpx_free_frame_buffer(&denoiser->mc_running_avg_y);
618 619 620
  vpx_free_frame_buffer(&denoiser->last_source);
}

621
void vp9_denoiser_set_noise_level(VP9_DENOISER *denoiser, int noise_level) {
622
  denoiser->denoising_level = noise_level;
623 624 625 626 627 628
  if (denoiser->denoising_level > kDenLowLow &&
      denoiser->prev_denoising_level == kDenLowLow)
    denoiser->reset = 1;
  else
    denoiser->reset = 0;
  denoiser->prev_denoising_level = denoiser->denoising_level;
629
}
630

631 632
// Scale/increase the partition threshold
// for denoiser speed-up.
633
int64_t vp9_scale_part_thresh(int64_t threshold, VP9_DENOISER_LEVEL noise_level,
634
                              int content_state, int temporal_layer_id) {
635
  if ((content_state == kLowSadLowSumdiff) ||
636
      (content_state == kHighSadLowSumdiff) ||
637 638 639 640 641 642
      (content_state == kLowVarHighSumdiff) || (noise_level == kDenHigh) ||
      (temporal_layer_id != 0)) {
    int64_t scaled_thr =
        (temporal_layer_id < 2) ? (3 * threshold) >> 1 : (7 * threshold) >> 2;
    return scaled_thr;
  } else {
643
    return (5 * threshold) >> 2;
644
  }
645 646
}

647 648
//  Scale/increase the ac skip threshold for
//  denoiser speed-up.
649
int64_t vp9_scale_acskip_thresh(int64_t threshold,
650 651
                                VP9_DENOISER_LEVEL noise_level, int abs_sumdiff,
                                int temporal_layer_id) {
652
  if (noise_level >= kDenLow && abs_sumdiff < 5)
653 654
    return threshold *=
           (noise_level == kDenLow) ? 2 : (temporal_layer_id == 2) ? 10 : 6;
655 656 657 658
  else
    return threshold;
}

659 660 661 662 663 664
#ifdef OUTPUT_YUV_DENOISED
static void make_grayscale(YV12_BUFFER_CONFIG *yuv) {
  int r, c;
  uint8_t *u = yuv->u_buffer;
  uint8_t *v = yuv->v_buffer;

665 666
  for (r = 0; r < yuv->uv_height; ++r) {
    for (c = 0; c < yuv->uv_width; ++c) {
667 668 669
      u[c] = UINT8_MAX / 2;
      v[c] = UINT8_MAX / 2;
    }
670 671
    u += yuv->uv_stride;
    v += yuv->uv_stride;
672 673 674
  }
}
#endif