1ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian/*
2ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
3ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *
4ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  Use of this source code is governed by a BSD-style license
5ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  that can be found in the LICENSE file in the root of the source
6ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  tree. An additional intellectual property rights grant can be found
7ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  in the file PATENTS.  All contributing project authors may
8ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian *  be found in the AUTHORS file in the root of the source tree.
9ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian */
10ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
11ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include <assert.h>
12ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include <limits.h>
13c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann#include <math.h>
14c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann
157ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian#include "./vpx_dsp_rtcd.h"
16c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann#include "vpx_dsp/vpx_dsp_common.h"
17ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "vpx_scale/yv12config.h"
18ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "vpx/vpx_integer.h"
19ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "vp9/common/vp9_reconinter.h"
20ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "vp9/encoder/vp9_context_tree.h"
21ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#include "vp9/encoder/vp9_denoiser.h"
22c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann#include "vp9/encoder/vp9_encoder.h"
23ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
248b92989c89bec8632aa47dc58dc162f199d62edcJames Zern// OUTPUT_YUV_DENOISED
258b92989c89bec8632aa47dc58dc162f199d62edcJames Zern
26ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#ifdef OUTPUT_YUV_DENOISED
27ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic void make_grayscale(YV12_BUFFER_CONFIG *yuv);
28ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
29ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
30ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic int absdiff_thresh(BLOCK_SIZE bs, int increase_denoising) {
31ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  (void)bs;
32ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 3 + (increase_denoising ? 1 : 0);
33ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
34ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
35ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic int delta_thresh(BLOCK_SIZE bs, int increase_denoising) {
36ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  (void)bs;
37ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  (void)increase_denoising;
38ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 4;
39ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
40ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
41ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic int noise_motion_thresh(BLOCK_SIZE bs, int increase_denoising) {
42ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  (void)bs;
43ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  (void)increase_denoising;
447ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  return 625;
45ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
46ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
47ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic unsigned int sse_thresh(BLOCK_SIZE bs, int increase_denoising) {
4868e1c830ade592be74773e249bf94e2bbfb50de7Johann  return (1 << num_pels_log2_lookup[bs]) * (increase_denoising ? 80 : 40);
49ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
50ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
51ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic int sse_diff_thresh(BLOCK_SIZE bs, int increase_denoising,
527ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian                           int motion_magnitude) {
537bc9febe8749e98a3812a0dc4380ceae75c29450Johann  if (motion_magnitude > noise_motion_thresh(bs, increase_denoising)) {
5468e1c830ade592be74773e249bf94e2bbfb50de7Johann    if (increase_denoising)
5568e1c830ade592be74773e249bf94e2bbfb50de7Johann      return (1 << num_pels_log2_lookup[bs]) << 2;
5668e1c830ade592be74773e249bf94e2bbfb50de7Johann    else
5768e1c830ade592be74773e249bf94e2bbfb50de7Johann      return 0;
58ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  } else {
5968e1c830ade592be74773e249bf94e2bbfb50de7Johann    return (1 << num_pels_log2_lookup[bs]) << 4;
60ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
61ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
62ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
63ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic int total_adj_weak_thresh(BLOCK_SIZE bs, int increase_denoising) {
647ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  return (1 << num_pels_log2_lookup[bs]) * (increase_denoising ? 3 : 2);
65ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
66ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
677ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian// TODO(jackychen): If increase_denoising is enabled in the future,
687ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian// we might need to update the code for calculating 'total_adj' in
697ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian// case the C code is not bit-exact with corresponding sse2 code.
707ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanianint vp9_denoiser_filter_c(const uint8_t *sig, int sig_stride,
717bc9febe8749e98a3812a0dc4380ceae75c29450Johann                          const uint8_t *mc_avg, int mc_avg_stride,
727bc9febe8749e98a3812a0dc4380ceae75c29450Johann                          uint8_t *avg, int avg_stride, int increase_denoising,
737bc9febe8749e98a3812a0dc4380ceae75c29450Johann                          BLOCK_SIZE bs, int motion_magnitude) {
74ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int r, c;
75ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const uint8_t *sig_start = sig;
76ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const uint8_t *mc_avg_start = mc_avg;
77ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8_t *avg_start = avg;
78ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int diff, adj, absdiff, delta;
797bc9febe8749e98a3812a0dc4380ceae75c29450Johann  int adj_val[] = { 3, 4, 6 };
80ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int total_adj = 0;
817ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  int shift_inc = 1;
827ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
837ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // If motion_magnitude is small, making the denoiser more aggressive by
847ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // increasing the adjustment for each level. Add another increment for
857ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // blocks that are labeled for increase denoising.
867ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  if (motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD) {
877ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    if (increase_denoising) {
887ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      shift_inc = 2;
897ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    }
907ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    adj_val[0] += shift_inc;
917ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    adj_val[1] += shift_inc;
927ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    adj_val[2] += shift_inc;
937ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  }
94ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
95ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // First attempt to apply a strong temporal denoising filter.
967ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  for (r = 0; r < (4 << b_height_log2_lookup[bs]); ++r) {
977ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    for (c = 0; c < (4 << b_width_log2_lookup[bs]); ++c) {
98ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      diff = mc_avg[c] - sig[c];
99ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      absdiff = abs(diff);
100ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
101ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (absdiff <= absdiff_thresh(bs, increase_denoising)) {
102ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        avg[c] = mc_avg[c];
103ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        total_adj += diff;
104ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      } else {
105ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        switch (absdiff) {
1067bc9febe8749e98a3812a0dc4380ceae75c29450Johann          case 4:
1077bc9febe8749e98a3812a0dc4380ceae75c29450Johann          case 5:
1087bc9febe8749e98a3812a0dc4380ceae75c29450Johann          case 6:
1097bc9febe8749e98a3812a0dc4380ceae75c29450Johann          case 7: adj = adj_val[0]; break;
1107bc9febe8749e98a3812a0dc4380ceae75c29450Johann          case 8:
1117bc9febe8749e98a3812a0dc4380ceae75c29450Johann          case 9:
1127bc9febe8749e98a3812a0dc4380ceae75c29450Johann          case 10:
1137bc9febe8749e98a3812a0dc4380ceae75c29450Johann          case 11:
1147bc9febe8749e98a3812a0dc4380ceae75c29450Johann          case 12:
1157bc9febe8749e98a3812a0dc4380ceae75c29450Johann          case 13:
1167bc9febe8749e98a3812a0dc4380ceae75c29450Johann          case 14:
1177bc9febe8749e98a3812a0dc4380ceae75c29450Johann          case 15: adj = adj_val[1]; break;
1187bc9febe8749e98a3812a0dc4380ceae75c29450Johann          default: adj = adj_val[2];
119ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        }
120ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        if (diff > 0) {
121c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann          avg[c] = VPXMIN(UINT8_MAX, sig[c] + adj);
122ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          total_adj += adj;
123ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        } else {
124c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann          avg[c] = VPXMAX(0, sig[c] - adj);
125ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian          total_adj -= adj;
126ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        }
127ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
128ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
129ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    sig += sig_stride;
130ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    avg += avg_stride;
131ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    mc_avg += mc_avg_stride;
132ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
133ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
134ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // If the strong filter did not modify the signal too much, we're all set.
135ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (abs(total_adj) <= total_adj_strong_thresh(bs, increase_denoising)) {
136ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return FILTER_BLOCK;
137ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
138ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
139ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Otherwise, we try to dampen the filter if the delta is not too high.
1407bc9febe8749e98a3812a0dc4380ceae75c29450Johann  delta = ((abs(total_adj) - total_adj_strong_thresh(bs, increase_denoising)) >>
1417bc9febe8749e98a3812a0dc4380ceae75c29450Johann           num_pels_log2_lookup[bs]) +
1427bc9febe8749e98a3812a0dc4380ceae75c29450Johann          1;
1437ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
1447ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  if (delta >= delta_thresh(bs, increase_denoising)) {
145ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return COPY_BLOCK;
146ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
147ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1487bc9febe8749e98a3812a0dc4380ceae75c29450Johann  mc_avg = mc_avg_start;
149ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  avg = avg_start;
150ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  sig = sig_start;
1517ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  for (r = 0; r < (4 << b_height_log2_lookup[bs]); ++r) {
1527ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    for (c = 0; c < (4 << b_width_log2_lookup[bs]); ++c) {
153ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      diff = mc_avg[c] - sig[c];
154ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      adj = abs(diff);
155ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (adj > delta) {
156ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian        adj = delta;
157ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
158ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      if (diff > 0) {
1597ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        // Diff positive means we made positive adjustment above
1607ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        // (in first try/attempt), so now make negative adjustment to bring
1617ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        // denoised signal down.
162c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann        avg[c] = VPXMAX(0, avg[c] - adj);
1637ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        total_adj -= adj;
164ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      } else {
1657ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        // Diff negative means we made negative adjustment above
1667ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        // (in first try/attempt), so now make positive adjustment to bring
1677ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        // denoised signal up.
168c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann        avg[c] = VPXMIN(UINT8_MAX, avg[c] + adj);
1697ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        total_adj += adj;
170ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      }
171ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
172ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    sig += sig_stride;
173ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    avg += avg_stride;
174ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    mc_avg += mc_avg_stride;
175ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
176ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
177ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // We can use the filter if it has been sufficiently dampened
178ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (abs(total_adj) <= total_adj_weak_thresh(bs, increase_denoising)) {
179ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return FILTER_BLOCK;
180ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
181ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return COPY_BLOCK;
182ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
183ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1847bc9febe8749e98a3812a0dc4380ceae75c29450Johannstatic uint8_t *block_start(uint8_t *framebuf, int stride, int mi_row,
1857bc9febe8749e98a3812a0dc4380ceae75c29450Johann                            int mi_col) {
1867bc9febe8749e98a3812a0dc4380ceae75c29450Johann  return framebuf + (stride * mi_row << 3) + (mi_col << 3);
187ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
188ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1897bc9febe8749e98a3812a0dc4380ceae75c29450Johannstatic VP9_DENOISER_DECISION perform_motion_compensation(
1908b92989c89bec8632aa47dc58dc162f199d62edcJames Zern    VP9_COMMON *const cm, VP9_DENOISER *denoiser, MACROBLOCK *mb, BLOCK_SIZE bs,
1917bc9febe8749e98a3812a0dc4380ceae75c29450Johann    int increase_denoising, int mi_row, int mi_col, PICK_MODE_CONTEXT *ctx,
1928b92989c89bec8632aa47dc58dc162f199d62edcJames Zern    int motion_magnitude, int is_skin, int *zeromv_filter, int consec_zeromv,
1938b92989c89bec8632aa47dc58dc162f199d62edcJames Zern    int num_spatial_layers, int width) {
1948b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  const int sse_diff = (ctx->newmv_sse == UINT_MAX)
1958b92989c89bec8632aa47dc58dc162f199d62edcJames Zern                           ? 0
1968b92989c89bec8632aa47dc58dc162f199d62edcJames Zern                           : ((int)ctx->zeromv_sse - (int)ctx->newmv_sse);
197ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  MV_REFERENCE_FRAME frame;
198ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  MACROBLOCKD *filter_mbd = &mb->e_mbd;
19968e1c830ade592be74773e249bf94e2bbfb50de7Johann  MODE_INFO *mi = filter_mbd->mi[0];
20068e1c830ade592be74773e249bf94e2bbfb50de7Johann  MODE_INFO saved_mi;
20168e1c830ade592be74773e249bf94e2bbfb50de7Johann  int i;
202ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  struct buf_2d saved_dst[MAX_MB_PLANE];
20368e1c830ade592be74773e249bf94e2bbfb50de7Johann  struct buf_2d saved_pre[MAX_MB_PLANE];
2048b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  RefBuffer *saved_block_refs[2];
205ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
206ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  frame = ctx->best_reference_frame;
20768e1c830ade592be74773e249bf94e2bbfb50de7Johann  saved_mi = *mi;
208ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2097bc9febe8749e98a3812a0dc4380ceae75c29450Johann  if (is_skin && (motion_magnitude > 0 || consec_zeromv < 4)) return COPY_BLOCK;
2107ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
2118b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  // Avoid denoising small blocks. When noise > kDenLow or frame width > 480,
2128b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  // denoise 16x16 blocks.
2138b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  if (bs == BLOCK_8X8 || bs == BLOCK_8X16 || bs == BLOCK_16X8 ||
2148b92989c89bec8632aa47dc58dc162f199d62edcJames Zern      (bs == BLOCK_16X16 && width > 480 &&
2158b92989c89bec8632aa47dc58dc162f199d62edcJames Zern       denoiser->denoising_level <= kDenLow))
216c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann    return COPY_BLOCK;
217c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann
218ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // If the best reference frame uses inter-prediction and there is enough of a
219ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // difference in sum-squared-error, use it.
2208b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  if (frame != INTRA_FRAME &&
2218b92989c89bec8632aa47dc58dc162f199d62edcJames Zern      (frame != GOLDEN_FRAME || num_spatial_layers == 1) &&
22268e1c830ade592be74773e249bf94e2bbfb50de7Johann      sse_diff > sse_diff_thresh(bs, increase_denoising, motion_magnitude)) {
22368e1c830ade592be74773e249bf94e2bbfb50de7Johann    mi->ref_frame[0] = ctx->best_reference_frame;
22468e1c830ade592be74773e249bf94e2bbfb50de7Johann    mi->mode = ctx->best_sse_inter_mode;
22568e1c830ade592be74773e249bf94e2bbfb50de7Johann    mi->mv[0] = ctx->best_sse_mv;
226ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  } else {
227ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // Otherwise, use the zero reference frame.
228ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    frame = ctx->best_zeromv_reference_frame;
22968e1c830ade592be74773e249bf94e2bbfb50de7Johann    ctx->newmv_sse = ctx->zeromv_sse;
23068e1c830ade592be74773e249bf94e2bbfb50de7Johann    // Bias to last reference.
2318b92989c89bec8632aa47dc58dc162f199d62edcJames Zern    if (num_spatial_layers > 1 ||
2328b92989c89bec8632aa47dc58dc162f199d62edcJames Zern        (frame != LAST_FRAME &&
2338b92989c89bec8632aa47dc58dc162f199d62edcJames Zern         ((ctx->zeromv_lastref_sse<(5 * ctx->zeromv_sse)>> 2) ||
2348b92989c89bec8632aa47dc58dc162f199d62edcJames Zern          denoiser->denoising_level >= kDenHigh))) {
23568e1c830ade592be74773e249bf94e2bbfb50de7Johann      frame = LAST_FRAME;
23668e1c830ade592be74773e249bf94e2bbfb50de7Johann      ctx->newmv_sse = ctx->zeromv_lastref_sse;
23768e1c830ade592be74773e249bf94e2bbfb50de7Johann    }
23868e1c830ade592be74773e249bf94e2bbfb50de7Johann    mi->ref_frame[0] = frame;
23968e1c830ade592be74773e249bf94e2bbfb50de7Johann    mi->mode = ZEROMV;
24068e1c830ade592be74773e249bf94e2bbfb50de7Johann    mi->mv[0].as_int = 0;
241ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ctx->best_sse_inter_mode = ZEROMV;
242ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ctx->best_sse_mv.as_int = 0;
24368e1c830ade592be74773e249bf94e2bbfb50de7Johann    *zeromv_filter = 1;
24468e1c830ade592be74773e249bf94e2bbfb50de7Johann    if (denoiser->denoising_level > kDenMedium) {
24568e1c830ade592be74773e249bf94e2bbfb50de7Johann      motion_magnitude = 0;
24668e1c830ade592be74773e249bf94e2bbfb50de7Johann    }
247ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
248ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2497ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  if (ctx->newmv_sse > sse_thresh(bs, increase_denoising)) {
2507ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    // Restore everything to its original state
25168e1c830ade592be74773e249bf94e2bbfb50de7Johann    *mi = saved_mi;
2527ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    return COPY_BLOCK;
2537ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  }
2547bc9febe8749e98a3812a0dc4380ceae75c29450Johann  if (motion_magnitude > (noise_motion_thresh(bs, increase_denoising) << 3)) {
2557ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    // Restore everything to its original state
25668e1c830ade592be74773e249bf94e2bbfb50de7Johann    *mi = saved_mi;
2577ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    return COPY_BLOCK;
2587ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  }
2597ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
2607ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // We will restore these after motion compensation.
2617ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  for (i = 0; i < MAX_MB_PLANE; ++i) {
26268e1c830ade592be74773e249bf94e2bbfb50de7Johann    saved_pre[i] = filter_mbd->plane[i].pre[0];
2637ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    saved_dst[i] = filter_mbd->plane[i].dst;
2647ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  }
2658b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  saved_block_refs[0] = filter_mbd->block_refs[0];
2667ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
267ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Set the pointers in the MACROBLOCKD to point to the buffers in the denoiser
268ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // struct.
26968e1c830ade592be74773e249bf94e2bbfb50de7Johann  filter_mbd->plane[0].pre[0].buf =
27068e1c830ade592be74773e249bf94e2bbfb50de7Johann      block_start(denoiser->running_avg_y[frame].y_buffer,
2717bc9febe8749e98a3812a0dc4380ceae75c29450Johann                  denoiser->running_avg_y[frame].y_stride, mi_row, mi_col);
2727bc9febe8749e98a3812a0dc4380ceae75c29450Johann  filter_mbd->plane[0].pre[0].stride = denoiser->running_avg_y[frame].y_stride;
27368e1c830ade592be74773e249bf94e2bbfb50de7Johann  filter_mbd->plane[1].pre[0].buf =
2747bc9febe8749e98a3812a0dc4380ceae75c29450Johann      block_start(denoiser->running_avg_y[frame].u_buffer,
2757bc9febe8749e98a3812a0dc4380ceae75c29450Johann                  denoiser->running_avg_y[frame].uv_stride, mi_row, mi_col);
2767bc9febe8749e98a3812a0dc4380ceae75c29450Johann  filter_mbd->plane[1].pre[0].stride = denoiser->running_avg_y[frame].uv_stride;
27768e1c830ade592be74773e249bf94e2bbfb50de7Johann  filter_mbd->plane[2].pre[0].buf =
27868e1c830ade592be74773e249bf94e2bbfb50de7Johann      block_start(denoiser->running_avg_y[frame].v_buffer,
2797bc9febe8749e98a3812a0dc4380ceae75c29450Johann                  denoiser->running_avg_y[frame].uv_stride, mi_row, mi_col);
2807bc9febe8749e98a3812a0dc4380ceae75c29450Johann  filter_mbd->plane[2].pre[0].stride = denoiser->running_avg_y[frame].uv_stride;
28168e1c830ade592be74773e249bf94e2bbfb50de7Johann
282ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  filter_mbd->plane[0].dst.buf =
283ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      block_start(denoiser->mc_running_avg_y.y_buffer,
2847bc9febe8749e98a3812a0dc4380ceae75c29450Johann                  denoiser->mc_running_avg_y.y_stride, mi_row, mi_col);
285ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  filter_mbd->plane[0].dst.stride = denoiser->mc_running_avg_y.y_stride;
286ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  filter_mbd->plane[1].dst.buf =
287ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      block_start(denoiser->mc_running_avg_y.u_buffer,
2887bc9febe8749e98a3812a0dc4380ceae75c29450Johann                  denoiser->mc_running_avg_y.uv_stride, mi_row, mi_col);
289ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  filter_mbd->plane[1].dst.stride = denoiser->mc_running_avg_y.uv_stride;
290ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  filter_mbd->plane[2].dst.buf =
291ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      block_start(denoiser->mc_running_avg_y.v_buffer,
2927bc9febe8749e98a3812a0dc4380ceae75c29450Johann                  denoiser->mc_running_avg_y.uv_stride, mi_row, mi_col);
293ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  filter_mbd->plane[2].dst.stride = denoiser->mc_running_avg_y.uv_stride;
294ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
2958b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  set_ref_ptrs(cm, filter_mbd, frame, NONE);
29668e1c830ade592be74773e249bf94e2bbfb50de7Johann  vp9_build_inter_predictors_sby(filter_mbd, mi_row, mi_col, bs);
297ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
298ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  // Restore everything to its original state
29968e1c830ade592be74773e249bf94e2bbfb50de7Johann  *mi = saved_mi;
3008b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  filter_mbd->block_refs[0] = saved_block_refs[0];
301ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (i = 0; i < MAX_MB_PLANE; ++i) {
30268e1c830ade592be74773e249bf94e2bbfb50de7Johann    filter_mbd->plane[i].pre[0] = saved_pre[i];
303ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    filter_mbd->plane[i].dst = saved_dst[i];
304ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
305ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
306ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return FILTER_BLOCK;
307ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
308ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
3097bc9febe8749e98a3812a0dc4380ceae75c29450Johannvoid vp9_denoiser_denoise(VP9_COMP *cpi, MACROBLOCK *mb, int mi_row, int mi_col,
3107bc9febe8749e98a3812a0dc4380ceae75c29450Johann                          BLOCK_SIZE bs, PICK_MODE_CONTEXT *ctx,
31168e1c830ade592be74773e249bf94e2bbfb50de7Johann                          VP9_DENOISER_DECISION *denoiser_decision) {
31268e1c830ade592be74773e249bf94e2bbfb50de7Johann  int mv_col, mv_row;
3137ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  int motion_magnitude = 0;
31468e1c830ade592be74773e249bf94e2bbfb50de7Johann  int zeromv_filter = 0;
31568e1c830ade592be74773e249bf94e2bbfb50de7Johann  VP9_DENOISER *denoiser = &cpi->denoiser;
316c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann  VP9_DENOISER_DECISION decision = COPY_BLOCK;
317ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  YV12_BUFFER_CONFIG avg = denoiser->running_avg_y[INTRA_FRAME];
318ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  YV12_BUFFER_CONFIG mc_avg = denoiser->mc_running_avg_y;
319ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8_t *avg_start = block_start(avg.y_buffer, avg.y_stride, mi_row, mi_col);
3207bc9febe8749e98a3812a0dc4380ceae75c29450Johann  uint8_t *mc_avg_start =
3217bc9febe8749e98a3812a0dc4380ceae75c29450Johann      block_start(mc_avg.y_buffer, mc_avg.y_stride, mi_row, mi_col);
322ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  struct buf_2d src = mb->plane[0].src;
323c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann  int is_skin = 0;
3248b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  int increase_denoising = 0;
32568e1c830ade592be74773e249bf94e2bbfb50de7Johann  int consec_zeromv = 0;
32668e1c830ade592be74773e249bf94e2bbfb50de7Johann  mv_col = ctx->best_sse_mv.as_mv.col;
32768e1c830ade592be74773e249bf94e2bbfb50de7Johann  mv_row = ctx->best_sse_mv.as_mv.row;
32868e1c830ade592be74773e249bf94e2bbfb50de7Johann  motion_magnitude = mv_row * mv_row + mv_col * mv_col;
32968e1c830ade592be74773e249bf94e2bbfb50de7Johann
3307bc9febe8749e98a3812a0dc4380ceae75c29450Johann  if (cpi->use_skin_detection && bs <= BLOCK_32X32 &&
33168e1c830ade592be74773e249bf94e2bbfb50de7Johann      denoiser->denoising_level < kDenHigh) {
33268e1c830ade592be74773e249bf94e2bbfb50de7Johann    int motion_level = (motion_magnitude < 16) ? 0 : 1;
33368e1c830ade592be74773e249bf94e2bbfb50de7Johann    // If motion for current block is small/zero, compute consec_zeromv for
33468e1c830ade592be74773e249bf94e2bbfb50de7Johann    // skin detection (early exit in skin detection is done for large
33568e1c830ade592be74773e249bf94e2bbfb50de7Johann    // consec_zeromv when current block has small/zero motion).
33668e1c830ade592be74773e249bf94e2bbfb50de7Johann    consec_zeromv = 0;
33768e1c830ade592be74773e249bf94e2bbfb50de7Johann    if (motion_level == 0) {
3387bc9febe8749e98a3812a0dc4380ceae75c29450Johann      VP9_COMMON *const cm = &cpi->common;
33968e1c830ade592be74773e249bf94e2bbfb50de7Johann      int j, i;
34068e1c830ade592be74773e249bf94e2bbfb50de7Johann      // Loop through the 8x8 sub-blocks.
34168e1c830ade592be74773e249bf94e2bbfb50de7Johann      const int bw = num_8x8_blocks_wide_lookup[BLOCK_64X64];
34268e1c830ade592be74773e249bf94e2bbfb50de7Johann      const int bh = num_8x8_blocks_high_lookup[BLOCK_64X64];
34368e1c830ade592be74773e249bf94e2bbfb50de7Johann      const int xmis = VPXMIN(cm->mi_cols - mi_col, bw);
34468e1c830ade592be74773e249bf94e2bbfb50de7Johann      const int ymis = VPXMIN(cm->mi_rows - mi_row, bh);
34568e1c830ade592be74773e249bf94e2bbfb50de7Johann      const int block_index = mi_row * cm->mi_cols + mi_col;
34668e1c830ade592be74773e249bf94e2bbfb50de7Johann      consec_zeromv = 100;
34768e1c830ade592be74773e249bf94e2bbfb50de7Johann      for (i = 0; i < ymis; i++) {
34868e1c830ade592be74773e249bf94e2bbfb50de7Johann        for (j = 0; j < xmis; j++) {
34968e1c830ade592be74773e249bf94e2bbfb50de7Johann          int bl_index = block_index + i * cm->mi_cols + j;
35068e1c830ade592be74773e249bf94e2bbfb50de7Johann          consec_zeromv = VPXMIN(cpi->consec_zero_mv[bl_index], consec_zeromv);
35168e1c830ade592be74773e249bf94e2bbfb50de7Johann          // No need to keep checking 8x8 blocks if any of the sub-blocks
35268e1c830ade592be74773e249bf94e2bbfb50de7Johann          // has small consec_zeromv (since threshold for no_skin based on
35368e1c830ade592be74773e249bf94e2bbfb50de7Johann          // zero/small motion in skin detection is high, i.e, > 4).
35468e1c830ade592be74773e249bf94e2bbfb50de7Johann          if (consec_zeromv < 4) {
35568e1c830ade592be74773e249bf94e2bbfb50de7Johann            i = ymis;
35668e1c830ade592be74773e249bf94e2bbfb50de7Johann            j = xmis;
35768e1c830ade592be74773e249bf94e2bbfb50de7Johann          }
35868e1c830ade592be74773e249bf94e2bbfb50de7Johann        }
35968e1c830ade592be74773e249bf94e2bbfb50de7Johann      }
36068e1c830ade592be74773e249bf94e2bbfb50de7Johann    }
36168e1c830ade592be74773e249bf94e2bbfb50de7Johann    // TODO(marpan): Compute skin detection over sub-blocks.
3627bc9febe8749e98a3812a0dc4380ceae75c29450Johann    is_skin = vp9_compute_skin_block(
3637bc9febe8749e98a3812a0dc4380ceae75c29450Johann        mb->plane[0].src.buf, mb->plane[1].src.buf, mb->plane[2].src.buf,
3647bc9febe8749e98a3812a0dc4380ceae75c29450Johann        mb->plane[0].src.stride, mb->plane[1].src.stride, bs, consec_zeromv,
3657bc9febe8749e98a3812a0dc4380ceae75c29450Johann        motion_level);
36668e1c830ade592be74773e249bf94e2bbfb50de7Johann  }
3678b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  if (!is_skin && denoiser->denoising_level == kDenHigh) increase_denoising = 1;
368ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
3698b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  // TODO(marpan): There is an issue with denoising for speed 5,
3708b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  // due to the partitioning scheme based on pickmode.
3718b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  // Remove this speed constraint when issue is resolved.
3728b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  if (denoiser->denoising_level >= kDenLow && cpi->oxcf.speed > 5)
3737bc9febe8749e98a3812a0dc4380ceae75c29450Johann    decision = perform_motion_compensation(
3748b92989c89bec8632aa47dc58dc162f199d62edcJames Zern        &cpi->common, denoiser, mb, bs, increase_denoising, mi_row, mi_col, ctx,
3758b92989c89bec8632aa47dc58dc162f199d62edcJames Zern        motion_magnitude, is_skin, &zeromv_filter, consec_zeromv,
3768b92989c89bec8632aa47dc58dc162f199d62edcJames Zern        cpi->svc.number_spatial_layers, cpi->Source->y_width);
377ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
378ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (decision == FILTER_BLOCK) {
3798b92989c89bec8632aa47dc58dc162f199d62edcJames Zern    decision = vp9_denoiser_filter(src.buf, src.stride, mc_avg_start,
3808b92989c89bec8632aa47dc58dc162f199d62edcJames Zern                                   mc_avg.y_stride, avg_start, avg.y_stride,
3818b92989c89bec8632aa47dc58dc162f199d62edcJames Zern                                   increase_denoising, bs, motion_magnitude);
382ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
383ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
384ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (decision == FILTER_BLOCK) {
3857bc9febe8749e98a3812a0dc4380ceae75c29450Johann    vpx_convolve_copy(avg_start, avg.y_stride, src.buf, src.stride, NULL, 0,
3867bc9febe8749e98a3812a0dc4380ceae75c29450Johann                      NULL, 0, num_4x4_blocks_wide_lookup[bs] << 2,
3877ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian                      num_4x4_blocks_high_lookup[bs] << 2);
388ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  } else {  // COPY_BLOCK
3897bc9febe8749e98a3812a0dc4380ceae75c29450Johann    vpx_convolve_copy(src.buf, src.stride, avg_start, avg.y_stride, NULL, 0,
3907bc9febe8749e98a3812a0dc4380ceae75c29450Johann                      NULL, 0, num_4x4_blocks_wide_lookup[bs] << 2,
3917ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian                      num_4x4_blocks_high_lookup[bs] << 2);
392ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
39368e1c830ade592be74773e249bf94e2bbfb50de7Johann  *denoiser_decision = decision;
39468e1c830ade592be74773e249bf94e2bbfb50de7Johann  if (decision == FILTER_BLOCK && zeromv_filter == 1)
39568e1c830ade592be74773e249bf94e2bbfb50de7Johann    *denoiser_decision = FILTER_ZEROMV_BLOCK;
396ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
397ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
3987bc9febe8749e98a3812a0dc4380ceae75c29450Johannstatic void copy_frame(YV12_BUFFER_CONFIG *const dest,
3997bc9febe8749e98a3812a0dc4380ceae75c29450Johann                       const YV12_BUFFER_CONFIG *const src) {
400ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int r;
401c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann  const uint8_t *srcbuf = src->y_buffer;
402c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann  uint8_t *destbuf = dest->y_buffer;
4037ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
404c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann  assert(dest->y_width == src->y_width);
405c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann  assert(dest->y_height == src->y_height);
406ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
407c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann  for (r = 0; r < dest->y_height; ++r) {
408c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann    memcpy(destbuf, srcbuf, dest->y_width);
409c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann    destbuf += dest->y_stride;
410c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann    srcbuf += src->y_stride;
411ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
412ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
413ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
4147bc9febe8749e98a3812a0dc4380ceae75c29450Johannstatic void swap_frame_buffer(YV12_BUFFER_CONFIG *const dest,
4157bc9febe8749e98a3812a0dc4380ceae75c29450Johann                              YV12_BUFFER_CONFIG *const src) {
4167ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  uint8_t *tmp_buf = dest->y_buffer;
4177ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  assert(dest->y_width == src->y_width);
4187ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  assert(dest->y_height == src->y_height);
4197ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  dest->y_buffer = src->y_buffer;
4207ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  src->y_buffer = tmp_buf;
4217ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian}
4227ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
4238b92989c89bec8632aa47dc58dc162f199d62edcJames Zernvoid vp9_denoiser_update_frame_info(
4248b92989c89bec8632aa47dc58dc162f199d62edcJames Zern    VP9_DENOISER *denoiser, YV12_BUFFER_CONFIG src, FRAME_TYPE frame_type,
4258b92989c89bec8632aa47dc58dc162f199d62edcJames Zern    int refresh_alt_ref_frame, int refresh_golden_frame, int refresh_last_frame,
4268b92989c89bec8632aa47dc58dc162f199d62edcJames Zern    int resized, int svc_base_is_key) {
427c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann  // Copy source into denoised reference buffers on KEY_FRAME or
4288b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  // if the just encoded frame was resized. For SVC, copy source if the base
4298b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  // spatial layer was key frame.
4308b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  if (frame_type == KEY_FRAME || resized != 0 || denoiser->reset ||
4318b92989c89bec8632aa47dc58dc162f199d62edcJames Zern      svc_base_is_key) {
432ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    int i;
433ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    // Start at 1 so as not to overwrite the INTRA_FRAME
4347ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    for (i = 1; i < MAX_REF_FRAMES; ++i)
435c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann      copy_frame(&denoiser->running_avg_y[i], &src);
43668e1c830ade592be74773e249bf94e2bbfb50de7Johann    denoiser->reset = 0;
4377ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    return;
4387ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  }
4397ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
440c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann  // If more than one refresh occurs, must copy frame buffer.
4417bc9febe8749e98a3812a0dc4380ceae75c29450Johann  if ((refresh_alt_ref_frame + refresh_golden_frame + refresh_last_frame) > 1) {
442c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann    if (refresh_alt_ref_frame) {
443c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann      copy_frame(&denoiser->running_avg_y[ALTREF_FRAME],
444c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann                 &denoiser->running_avg_y[INTRA_FRAME]);
445c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann    }
446c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann    if (refresh_golden_frame) {
447c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann      copy_frame(&denoiser->running_avg_y[GOLDEN_FRAME],
448c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann                 &denoiser->running_avg_y[INTRA_FRAME]);
449c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann    }
450c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann    if (refresh_last_frame) {
451c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann      copy_frame(&denoiser->running_avg_y[LAST_FRAME],
452c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann                 &denoiser->running_avg_y[INTRA_FRAME]);
453c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann    }
454c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann  } else {
455c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann    if (refresh_alt_ref_frame) {
456c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann      swap_frame_buffer(&denoiser->running_avg_y[ALTREF_FRAME],
457c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann                        &denoiser->running_avg_y[INTRA_FRAME]);
458c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann    }
459c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann    if (refresh_golden_frame) {
460c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann      swap_frame_buffer(&denoiser->running_avg_y[GOLDEN_FRAME],
461c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann                        &denoiser->running_avg_y[INTRA_FRAME]);
462c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann    }
463c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann    if (refresh_last_frame) {
464c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann      swap_frame_buffer(&denoiser->running_avg_y[LAST_FRAME],
465c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann                        &denoiser->running_avg_y[INTRA_FRAME]);
466c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann    }
467ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
468ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
469ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
470ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianvoid vp9_denoiser_reset_frame_stats(PICK_MODE_CONTEXT *ctx) {
471ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  ctx->zeromv_sse = UINT_MAX;
472ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  ctx->newmv_sse = UINT_MAX;
47368e1c830ade592be74773e249bf94e2bbfb50de7Johann  ctx->zeromv_lastref_sse = UINT_MAX;
47468e1c830ade592be74773e249bf94e2bbfb50de7Johann  ctx->best_sse_mv.as_int = 0;
475ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
476ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
47768e1c830ade592be74773e249bf94e2bbfb50de7Johannvoid vp9_denoiser_update_frame_stats(MODE_INFO *mi, unsigned int sse,
4787ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian                                     PREDICTION_MODE mode,
479ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                                     PICK_MODE_CONTEXT *ctx) {
48068e1c830ade592be74773e249bf94e2bbfb50de7Johann  if (mi->mv[0].as_int == 0 && sse < ctx->zeromv_sse) {
481ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ctx->zeromv_sse = sse;
48268e1c830ade592be74773e249bf94e2bbfb50de7Johann    ctx->best_zeromv_reference_frame = mi->ref_frame[0];
4837bc9febe8749e98a3812a0dc4380ceae75c29450Johann    if (mi->ref_frame[0] == LAST_FRAME) ctx->zeromv_lastref_sse = sse;
484ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
485ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
48668e1c830ade592be74773e249bf94e2bbfb50de7Johann  if (mi->mv[0].as_int != 0 && sse < ctx->newmv_sse) {
487ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ctx->newmv_sse = sse;
488ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    ctx->best_sse_inter_mode = mode;
48968e1c830ade592be74773e249bf94e2bbfb50de7Johann    ctx->best_sse_mv = mi->mv[0];
49068e1c830ade592be74773e249bf94e2bbfb50de7Johann    ctx->best_reference_frame = mi->ref_frame[0];
491ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
492ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
493ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
4947bc9febe8749e98a3812a0dc4380ceae75c29450Johannint vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height, int ssx,
4957bc9febe8749e98a3812a0dc4380ceae75c29450Johann                       int ssy,
4967ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian#if CONFIG_VP9_HIGHBITDEPTH
4977ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian                       int use_highbitdepth,
4987ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian#endif
4997ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian                       int border) {
500ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int i, fail;
5017ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  const int legacy_byte_alignment = 0;
502ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  assert(denoiser != NULL);
503ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
504ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (i = 0; i < MAX_REF_FRAMES; ++i) {
5057ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    fail = vpx_alloc_frame_buffer(&denoiser->running_avg_y[i], width, height,
5067ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian                                  ssx, ssy,
5077ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian#if CONFIG_VP9_HIGHBITDEPTH
5087ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian                                  use_highbitdepth,
5097ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian#endif
5107ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian                                  border, legacy_byte_alignment);
511ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    if (fail) {
512ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      vp9_denoiser_free(denoiser);
513ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      return 1;
514ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
515ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#ifdef OUTPUT_YUV_DENOISED
516ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    make_grayscale(&denoiser->running_avg_y[i]);
517ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
518ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
519ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
5207bc9febe8749e98a3812a0dc4380ceae75c29450Johann  fail = vpx_alloc_frame_buffer(&denoiser->mc_running_avg_y, width, height, ssx,
5217bc9febe8749e98a3812a0dc4380ceae75c29450Johann                                ssy,
5227ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian#if CONFIG_VP9_HIGHBITDEPTH
5237ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian                                use_highbitdepth,
5247ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian#endif
5257ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian                                border, legacy_byte_alignment);
526ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (fail) {
527ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    vp9_denoiser_free(denoiser);
528ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return 1;
529ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
530c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann
5317bc9febe8749e98a3812a0dc4380ceae75c29450Johann  fail = vpx_alloc_frame_buffer(&denoiser->last_source, width, height, ssx, ssy,
532c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann#if CONFIG_VP9_HIGHBITDEPTH
533c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann                                use_highbitdepth,
534c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann#endif
535c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann                                border, legacy_byte_alignment);
536c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann  if (fail) {
537c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann    vp9_denoiser_free(denoiser);
538c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann    return 1;
539c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann  }
540ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#ifdef OUTPUT_YUV_DENOISED
541ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  make_grayscale(&denoiser->running_avg_y[i]);
542ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
5437ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  denoiser->frame_buffer_initialized = 1;
54468e1c830ade592be74773e249bf94e2bbfb50de7Johann  denoiser->denoising_level = kDenLow;
54568e1c830ade592be74773e249bf94e2bbfb50de7Johann  denoiser->prev_denoising_level = kDenLow;
54668e1c830ade592be74773e249bf94e2bbfb50de7Johann  denoiser->reset = 0;
547ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return 0;
548ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
549ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
550ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianvoid vp9_denoiser_free(VP9_DENOISER *denoiser) {
551ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int i;
552ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  if (denoiser == NULL) {
553ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    return;
554ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
5557bc9febe8749e98a3812a0dc4380ceae75c29450Johann  denoiser->frame_buffer_initialized = 0;
556ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  for (i = 0; i < MAX_REF_FRAMES; ++i) {
5577ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    vpx_free_frame_buffer(&denoiser->running_avg_y[i]);
558ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
5597ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  vpx_free_frame_buffer(&denoiser->mc_running_avg_y);
560c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann  vpx_free_frame_buffer(&denoiser->last_source);
561c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann}
562c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann
5637bc9febe8749e98a3812a0dc4380ceae75c29450Johannvoid vp9_denoiser_set_noise_level(VP9_DENOISER *denoiser, int noise_level) {
56468e1c830ade592be74773e249bf94e2bbfb50de7Johann  denoiser->denoising_level = noise_level;
56568e1c830ade592be74773e249bf94e2bbfb50de7Johann  if (denoiser->denoising_level > kDenLowLow &&
56668e1c830ade592be74773e249bf94e2bbfb50de7Johann      denoiser->prev_denoising_level == kDenLowLow)
56768e1c830ade592be74773e249bf94e2bbfb50de7Johann    denoiser->reset = 1;
56868e1c830ade592be74773e249bf94e2bbfb50de7Johann  else
56968e1c830ade592be74773e249bf94e2bbfb50de7Johann    denoiser->reset = 0;
57068e1c830ade592be74773e249bf94e2bbfb50de7Johann  denoiser->prev_denoising_level = denoiser->denoising_level;
571ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
572ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
5738b92989c89bec8632aa47dc58dc162f199d62edcJames Zern// Scale/increase the partition threshold for denoiser speed-up.
5748b92989c89bec8632aa47dc58dc162f199d62edcJames Zernint64_t vp9_scale_part_thresh(int64_t threshold, VP9_DENOISER_LEVEL noise_level,
5758b92989c89bec8632aa47dc58dc162f199d62edcJames Zern                              int content_state, int temporal_layer_id) {
5768b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  if ((content_state == kLowSadLowSumdiff) ||
5778b92989c89bec8632aa47dc58dc162f199d62edcJames Zern      (content_state == kHighSadLowSumdiff) ||
5788b92989c89bec8632aa47dc58dc162f199d62edcJames Zern      (content_state == kLowVarHighSumdiff) || (noise_level == kDenHigh) ||
5798b92989c89bec8632aa47dc58dc162f199d62edcJames Zern      (temporal_layer_id != 0)) {
5808b92989c89bec8632aa47dc58dc162f199d62edcJames Zern    int64_t scaled_thr =
5818b92989c89bec8632aa47dc58dc162f199d62edcJames Zern        (temporal_layer_id < 2) ? (3 * threshold) >> 1 : (7 * threshold) >> 2;
5828b92989c89bec8632aa47dc58dc162f199d62edcJames Zern    return scaled_thr;
5838b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  } else {
5848b92989c89bec8632aa47dc58dc162f199d62edcJames Zern    return (5 * threshold) >> 2;
5858b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  }
5868b92989c89bec8632aa47dc58dc162f199d62edcJames Zern}
5878b92989c89bec8632aa47dc58dc162f199d62edcJames Zern
5888b92989c89bec8632aa47dc58dc162f199d62edcJames Zern//  Scale/increase the ac skip threshold for denoiser speed-up.
5898b92989c89bec8632aa47dc58dc162f199d62edcJames Zernint64_t vp9_scale_acskip_thresh(int64_t threshold,
5908b92989c89bec8632aa47dc58dc162f199d62edcJames Zern                                VP9_DENOISER_LEVEL noise_level, int abs_sumdiff,
5918b92989c89bec8632aa47dc58dc162f199d62edcJames Zern                                int temporal_layer_id) {
5928b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  if (noise_level >= kDenLow && abs_sumdiff < 5)
5938b92989c89bec8632aa47dc58dc162f199d62edcJames Zern    return threshold *=
5948b92989c89bec8632aa47dc58dc162f199d62edcJames Zern           (noise_level == kDenLow) ? 2 : (temporal_layer_id == 2) ? 10 : 6;
5958b92989c89bec8632aa47dc58dc162f199d62edcJames Zern  else
5968b92989c89bec8632aa47dc58dc162f199d62edcJames Zern    return threshold;
5978b92989c89bec8632aa47dc58dc162f199d62edcJames Zern}
5988b92989c89bec8632aa47dc58dc162f199d62edcJames Zern
599ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#ifdef OUTPUT_YUV_DENOISED
600ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic void make_grayscale(YV12_BUFFER_CONFIG *yuv) {
601ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  int r, c;
602ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8_t *u = yuv->u_buffer;
603ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  uint8_t *v = yuv->v_buffer;
604ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
6057ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  for (r = 0; r < yuv->uv_height; ++r) {
6067ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    for (c = 0; c < yuv->uv_width; ++c) {
607ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      u[c] = UINT8_MAX / 2;
608ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      v[c] = UINT8_MAX / 2;
609ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    }
6107ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    u += yuv->uv_stride;
6117ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    v += yuv->uv_stride;
612ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
613ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
614ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian#endif
615