| 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
|
|
|