Index: webrtc/modules/video_processing/util/denoiser_filter_c.cc |
diff --git a/webrtc/modules/video_processing/util/denoiser_filter_c.cc b/webrtc/modules/video_processing/util/denoiser_filter_c.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e32bf838895e430037d51e64bbfb749b577cf80c |
--- /dev/null |
+++ b/webrtc/modules/video_processing/util/denoiser_filter_c.cc |
@@ -0,0 +1,194 @@ |
+/* |
+ * Copyright (c) 2015 The WebRTC 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. |
+ */ |
+ |
+#include <stdlib.h> |
+ |
+#include "webrtc/modules/video_processing/util/denoiser_filter_c.h" |
+ |
+namespace webrtc { |
+ |
+void DenoiserFilterC::CopyMem16x16(const uint8_t* src, |
+ int src_stride, |
+ uint8_t* dst, |
+ int dst_stride) { |
+ for (int i = 0; i < 16; i++) { |
+ memcpy(dst, src, 16); |
+ src += src_stride; |
+ dst += dst_stride; |
+ } |
+} |
+ |
+void DenoiserFilterC::CopyMem8x8(const uint8_t* src, |
+ int src_stride, |
+ uint8_t* dst, |
+ int dst_stride) { |
+ for (int i = 0; i < 8; i++) { |
+ memcpy(dst, src, 8); |
+ src += src_stride; |
+ dst += dst_stride; |
+ } |
+} |
+ |
+uint32_t DenoiserFilterC::Variance16x8(const uint8_t* a, |
+ int a_stride, |
+ const uint8_t* b, |
+ int b_stride, |
+ uint32_t* sse) { |
+ int sum = 0; |
+ *sse = 0; |
+ a_stride <<= 1; |
+ b_stride <<= 1; |
+ |
+ for (int i = 0; i < 8; i++) { |
+ for (int j = 0; j < 16; j++) { |
+ const int diff = a[j] - b[j]; |
+ sum += diff; |
+ *sse += diff * diff; |
+ } |
+ |
+ a += a_stride; |
+ b += b_stride; |
+ } |
+ return *sse - ((static_cast<int64_t>(sum) * sum) >> 8); |
+} |
+ |
+DenoiserDecision DenoiserFilterC::MbDenoise(uint8_t* mc_running_avg_y, |
+ int mc_avg_y_stride, |
+ uint8_t* running_avg_y, |
+ int avg_y_stride, |
+ const uint8_t* sig, |
+ int sig_stride, |
+ uint8_t motion_magnitude, |
+ int increase_denoising) { |
+ int sum_diff_thresh = 0; |
+ int sum_diff = 0; |
+ int adj_val[3] = {3, 4, 6}; |
+ int shift_inc1 = 0; |
+ int shift_inc2 = 1; |
+ int col_sum[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
+ if (motion_magnitude <= kMotionMagnitudeThreshold) { |
+ if (increase_denoising) { |
+ shift_inc1 = 1; |
+ shift_inc2 = 2; |
+ } |
+ adj_val[0] += shift_inc2; |
+ adj_val[1] += shift_inc2; |
+ adj_val[2] += shift_inc2; |
+ } |
+ |
+ for (int r = 0; r < 16; ++r) { |
+ for (int c = 0; c < 16; ++c) { |
+ int diff = 0; |
+ int adjustment = 0; |
+ int absdiff = 0; |
+ |
+ diff = mc_running_avg_y[c] - sig[c]; |
+ absdiff = abs(diff); |
+ |
+ // When |diff| <= |3 + shift_inc1|, use pixel value from |
+ // last denoised raw. |
+ if (absdiff <= 3 + shift_inc1) { |
+ running_avg_y[c] = mc_running_avg_y[c]; |
+ col_sum[c] += diff; |
+ } else { |
+ if (absdiff >= 4 + shift_inc1 && absdiff <= 7) |
+ adjustment = adj_val[0]; |
+ else if (absdiff >= 8 && absdiff <= 15) |
+ adjustment = adj_val[1]; |
+ else |
+ adjustment = adj_val[2]; |
+ |
+ if (diff > 0) { |
+ if ((sig[c] + adjustment) > 255) |
+ running_avg_y[c] = 255; |
+ else |
+ running_avg_y[c] = sig[c] + adjustment; |
+ |
+ col_sum[c] += adjustment; |
+ } else { |
+ if ((sig[c] - adjustment) < 0) |
+ running_avg_y[c] = 0; |
+ else |
+ running_avg_y[c] = sig[c] - adjustment; |
+ |
+ col_sum[c] -= adjustment; |
+ } |
+ } |
+ } |
+ |
+ // Update pointers for next iteration. |
+ sig += sig_stride; |
+ mc_running_avg_y += mc_avg_y_stride; |
+ running_avg_y += avg_y_stride; |
+ } |
+ |
+ for (int c = 0; c < 16; ++c) { |
+ if (col_sum[c] >= 128) { |
+ col_sum[c] = 127; |
+ } |
+ sum_diff += col_sum[c]; |
+ } |
+ |
+ sum_diff_thresh = kSumDiffThreshold; |
+ if (increase_denoising) |
+ sum_diff_thresh = kSumDiffThresholdHigh; |
+ if (abs(sum_diff) > sum_diff_thresh) { |
+ int delta = ((abs(sum_diff) - sum_diff_thresh) >> 8) + 1; |
+ // Only apply the adjustment for max delta up to 3. |
+ if (delta < 4) { |
+ sig -= sig_stride * 16; |
+ mc_running_avg_y -= mc_avg_y_stride * 16; |
+ running_avg_y -= avg_y_stride * 16; |
+ for (int r = 0; r < 16; ++r) { |
+ for (int c = 0; c < 16; ++c) { |
+ int diff = mc_running_avg_y[c] - sig[c]; |
+ int adjustment = abs(diff); |
+ if (adjustment > delta) |
+ adjustment = delta; |
+ if (diff > 0) { |
+ // Bring denoised signal down. |
+ if (running_avg_y[c] - adjustment < 0) |
+ running_avg_y[c] = 0; |
+ else |
+ running_avg_y[c] = running_avg_y[c] - adjustment; |
+ col_sum[c] -= adjustment; |
+ } else if (diff < 0) { |
+ // Bring denoised signal up. |
+ if (running_avg_y[c] + adjustment > 255) |
+ running_avg_y[c] = 255; |
+ else |
+ running_avg_y[c] = running_avg_y[c] + adjustment; |
+ col_sum[c] += adjustment; |
+ } |
+ } |
+ sig += sig_stride; |
+ mc_running_avg_y += mc_avg_y_stride; |
+ running_avg_y += avg_y_stride; |
+ } |
+ |
+ sum_diff = 0; |
+ for (int c = 0; c < 16; ++c) { |
+ if (col_sum[c] >= 128) { |
+ col_sum[c] = 127; |
+ } |
+ sum_diff += col_sum[c]; |
+ } |
+ |
+ if (abs(sum_diff) > sum_diff_thresh) |
+ return COPY_BLOCK; |
+ } else { |
+ return COPY_BLOCK; |
+ } |
+ } |
+ |
+ return FILTER_BLOCK; |
+} |
+ |
+} // namespace webrtc |