Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / video_processing / main / source / denoising.cc
1 /*
2  *  Copyright (c) 2012 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 "webrtc/modules/video_processing/main/source/denoising.h"
12
13 #include <string.h>
14
15 namespace webrtc {
16 // Down-sampling in time (unit: number of frames)
17 enum { kSubsamplingTime = 0 };
18 // Sub-sampling in width (unit: power of 2.
19 enum { kSubsamplingWidth = 0 };
20 // Sub-sampling in height (unit: power of 2)
21 enum { kSubsamplingHeight = 0 };
22 // (Q8) De-noising filter parameter
23 enum { kDenoiseFiltParam = 179 };
24 // (Q8) 1 - filter parameter
25 enum { kDenoiseFiltParamRec = 77 };
26 // (Q8) De-noising threshold level
27 enum { kDenoiseThreshold = 19200 };
28
29 VPMDenoising::VPMDenoising()
30     : id_(0),
31       moment1_(NULL),
32       moment2_(NULL) {
33   Reset();
34 }
35
36 VPMDenoising::~VPMDenoising() {
37   if (moment1_) {
38     delete [] moment1_;
39     moment1_ = NULL;
40 }
41
42   if (moment2_) {
43     delete [] moment2_;
44     moment2_ = NULL;
45   }
46 }
47
48 int32_t VPMDenoising::ChangeUniqueId(const int32_t id) {
49   id_ = id;
50   return VPM_OK;
51 }
52
53 void VPMDenoising::Reset() {
54   frame_size_ = 0;
55   denoise_frame_cnt_ = 0;
56
57   if (moment1_) {
58     delete [] moment1_;
59     moment1_ = NULL;
60   }
61
62   if (moment2_) {
63     delete [] moment2_;
64     moment2_ = NULL;
65   }
66 }
67
68 int32_t VPMDenoising::ProcessFrame(I420VideoFrame* frame) {
69   assert(frame);
70   int32_t thevar;
71   int k;
72   int jsub, ksub;
73   int32_t diff0;
74   uint32_t tmp_moment1;
75   uint32_t tmp_moment2;
76   uint32_t tmp;
77   int32_t  num_pixels_changed = 0;
78
79   if (frame->IsZeroSize()) {
80     return VPM_GENERAL_ERROR;
81   }
82
83   int width = frame->width();
84   int height = frame->height();
85
86   /* Size of luminance component */
87   const uint32_t y_size  = height * width;
88
89   /* Initialization */
90   if (y_size != frame_size_) {
91     delete [] moment1_;
92     moment1_ = NULL;
93
94     delete [] moment2_;
95     moment2_ = NULL;
96   }
97   frame_size_ = y_size;
98
99   if (!moment1_) {
100     moment1_ = new uint32_t[y_size];
101     memset(moment1_, 0, sizeof(uint32_t)*y_size);
102   }
103
104   if (!moment2_) {
105     moment2_ = new uint32_t[y_size];
106     memset(moment2_, 0, sizeof(uint32_t)*y_size);
107   }
108
109   /* Apply de-noising on each pixel, but update variance sub-sampled */
110   uint8_t* buffer = frame->buffer(kYPlane);
111   for (int i = 0; i < height; i++) {  // Collect over height
112     k = i * width;
113     ksub = ((i >> kSubsamplingHeight) << kSubsamplingHeight) * width;
114     for (int j = 0; j < width; j++) {  // Collect over width
115       jsub = ((j >> kSubsamplingWidth) << kSubsamplingWidth);
116       /* Update mean value for every pixel and every frame */
117       tmp_moment1 = moment1_[k + j];
118       tmp_moment1 *= kDenoiseFiltParam;  // Q16
119       tmp_moment1 += ((kDenoiseFiltParamRec * ((uint32_t)buffer[k + j])) << 8);
120       tmp_moment1 >>= 8;  // Q8
121       moment1_[k + j] = tmp_moment1;
122
123       tmp_moment2 = moment2_[ksub + jsub];
124       if ((ksub == k) && (jsub == j) && (denoise_frame_cnt_ == 0)) {
125         tmp = ((uint32_t)buffer[k + j] *
126               (uint32_t)buffer[k + j]);
127         tmp_moment2 *= kDenoiseFiltParam;  // Q16
128         tmp_moment2 += ((kDenoiseFiltParamRec * tmp) << 8);
129         tmp_moment2 >>= 8;  // Q8
130       }
131        moment2_[k + j] = tmp_moment2;
132       /* Current event = deviation from mean value */
133       diff0 = ((int32_t)buffer[k + j] << 8) - moment1_[k + j];
134       /* Recent events = variance (variations over time) */
135       thevar = moment2_[k + j];
136       thevar -= ((moment1_[k + j] * moment1_[k + j]) >> 8);
137       // De-noising criteria, i.e., when should we replace a pixel by its mean.
138       // 1) recent events are minor.
139       // 2) current events are minor.
140       if ((thevar < kDenoiseThreshold)
141           && ((diff0 * diff0 >> 8) < kDenoiseThreshold)) {
142         // Replace with mean.
143         buffer[k + j] = (uint8_t)(moment1_[k + j] >> 8);
144         num_pixels_changed++;
145       }
146     }
147   }
148
149   denoise_frame_cnt_++;
150   if (denoise_frame_cnt_ > kSubsamplingTime)
151     denoise_frame_cnt_ = 0;
152
153   return num_pixels_changed;
154 }
155
156 }  // namespace