1/* 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 * 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 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#include <stdlib.h> 12 13#include "webrtc/modules/video_processing/util/denoiser_filter_c.h" 14 15namespace webrtc { 16 17void DenoiserFilterC::CopyMem16x16(const uint8_t* src, 18 int src_stride, 19 uint8_t* dst, 20 int dst_stride) { 21 for (int i = 0; i < 16; i++) { 22 memcpy(dst, src, 16); 23 src += src_stride; 24 dst += dst_stride; 25 } 26} 27 28void DenoiserFilterC::CopyMem8x8(const uint8_t* src, 29 int src_stride, 30 uint8_t* dst, 31 int dst_stride) { 32 for (int i = 0; i < 8; i++) { 33 memcpy(dst, src, 8); 34 src += src_stride; 35 dst += dst_stride; 36 } 37} 38 39uint32_t DenoiserFilterC::Variance16x8(const uint8_t* a, 40 int a_stride, 41 const uint8_t* b, 42 int b_stride, 43 uint32_t* sse) { 44 int sum = 0; 45 *sse = 0; 46 a_stride <<= 1; 47 b_stride <<= 1; 48 49 for (int i = 0; i < 8; i++) { 50 for (int j = 0; j < 16; j++) { 51 const int diff = a[j] - b[j]; 52 sum += diff; 53 *sse += diff * diff; 54 } 55 56 a += a_stride; 57 b += b_stride; 58 } 59 return *sse - ((static_cast<int64_t>(sum) * sum) >> 7); 60} 61 62DenoiserDecision DenoiserFilterC::MbDenoise(uint8_t* mc_running_avg_y, 63 int mc_avg_y_stride, 64 uint8_t* running_avg_y, 65 int avg_y_stride, 66 const uint8_t* sig, 67 int sig_stride, 68 uint8_t motion_magnitude, 69 int increase_denoising) { 70 int sum_diff_thresh = 0; 71 int sum_diff = 0; 72 int adj_val[3] = {3, 4, 6}; 73 int shift_inc1 = 0; 74 int shift_inc2 = 1; 75 int col_sum[16] = {0}; 76 if (motion_magnitude <= kMotionMagnitudeThreshold) { 77 if (increase_denoising) { 78 shift_inc1 = 1; 79 shift_inc2 = 2; 80 } 81 adj_val[0] += shift_inc2; 82 adj_val[1] += shift_inc2; 83 adj_val[2] += shift_inc2; 84 } 85 86 for (int r = 0; r < 16; ++r) { 87 for (int c = 0; c < 16; ++c) { 88 int diff = 0; 89 int adjustment = 0; 90 int absdiff = 0; 91 92 diff = mc_running_avg_y[c] - sig[c]; 93 absdiff = abs(diff); 94 95 // When |diff| <= |3 + shift_inc1|, use pixel value from 96 // last denoised raw. 97 if (absdiff <= 3 + shift_inc1) { 98 running_avg_y[c] = mc_running_avg_y[c]; 99 col_sum[c] += diff; 100 } else { 101 if (absdiff >= 4 + shift_inc1 && absdiff <= 7) 102 adjustment = adj_val[0]; 103 else if (absdiff >= 8 && absdiff <= 15) 104 adjustment = adj_val[1]; 105 else 106 adjustment = adj_val[2]; 107 108 if (diff > 0) { 109 if ((sig[c] + adjustment) > 255) 110 running_avg_y[c] = 255; 111 else 112 running_avg_y[c] = sig[c] + adjustment; 113 114 col_sum[c] += adjustment; 115 } else { 116 if ((sig[c] - adjustment) < 0) 117 running_avg_y[c] = 0; 118 else 119 running_avg_y[c] = sig[c] - adjustment; 120 121 col_sum[c] -= adjustment; 122 } 123 } 124 } 125 126 // Update pointers for next iteration. 127 sig += sig_stride; 128 mc_running_avg_y += mc_avg_y_stride; 129 running_avg_y += avg_y_stride; 130 } 131 132 for (int c = 0; c < 16; ++c) { 133 if (col_sum[c] >= 128) { 134 col_sum[c] = 127; 135 } 136 sum_diff += col_sum[c]; 137 } 138 139 sum_diff_thresh = kSumDiffThreshold; 140 if (increase_denoising) 141 sum_diff_thresh = kSumDiffThresholdHigh; 142 if (abs(sum_diff) > sum_diff_thresh) { 143 int delta = ((abs(sum_diff) - sum_diff_thresh) >> 8) + 1; 144 // Only apply the adjustment for max delta up to 3. 145 if (delta < 4) { 146 sig -= sig_stride * 16; 147 mc_running_avg_y -= mc_avg_y_stride * 16; 148 running_avg_y -= avg_y_stride * 16; 149 for (int r = 0; r < 16; ++r) { 150 for (int c = 0; c < 16; ++c) { 151 int diff = mc_running_avg_y[c] - sig[c]; 152 int adjustment = abs(diff); 153 if (adjustment > delta) 154 adjustment = delta; 155 if (diff > 0) { 156 // Bring denoised signal down. 157 if (running_avg_y[c] - adjustment < 0) 158 running_avg_y[c] = 0; 159 else 160 running_avg_y[c] = running_avg_y[c] - adjustment; 161 col_sum[c] -= adjustment; 162 } else if (diff < 0) { 163 // Bring denoised signal up. 164 if (running_avg_y[c] + adjustment > 255) 165 running_avg_y[c] = 255; 166 else 167 running_avg_y[c] = running_avg_y[c] + adjustment; 168 col_sum[c] += adjustment; 169 } 170 } 171 sig += sig_stride; 172 mc_running_avg_y += mc_avg_y_stride; 173 running_avg_y += avg_y_stride; 174 } 175 176 sum_diff = 0; 177 for (int c = 0; c < 16; ++c) { 178 if (col_sum[c] >= 128) { 179 col_sum[c] = 127; 180 } 181 sum_diff += col_sum[c]; 182 } 183 184 if (abs(sum_diff) > sum_diff_thresh) 185 return COPY_BLOCK; 186 } else { 187 return COPY_BLOCK; 188 } 189 } 190 191 return FILTER_BLOCK; 192} 193 194} // namespace webrtc 195