1 /*
2 * Copyright (c) 2016 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 "modules/video_processing/util/noise_estimation.h"
12 #if DISPLAYNEON
13 #include <android/log.h>
14 #endif
15
16 namespace webrtc {
17
Init(int width,int height,CpuType cpu_type)18 void NoiseEstimation::Init(int width, int height, CpuType cpu_type) {
19 int mb_cols = width >> 4;
20 int mb_rows = height >> 4;
21 consec_low_var_.reset(new uint32_t[mb_cols * mb_rows]());
22 width_ = width;
23 height_ = height;
24 mb_cols_ = width_ >> 4;
25 mb_rows_ = height_ >> 4;
26 cpu_type_ = cpu_type;
27 }
28
GetNoise(int mb_index,uint32_t var,uint32_t luma)29 void NoiseEstimation::GetNoise(int mb_index, uint32_t var, uint32_t luma) {
30 consec_low_var_[mb_index]++;
31 num_static_block_++;
32 if (consec_low_var_[mb_index] >= kConsecLowVarFrame &&
33 (luma >> 6) < kAverageLumaMax && (luma >> 6) > kAverageLumaMin) {
34 // Normalized var by the average luma value, this gives more weight to
35 // darker blocks.
36 int nor_var = var / (luma >> 10);
37 noise_var_ +=
38 nor_var > kBlockSelectionVarMax ? kBlockSelectionVarMax : nor_var;
39 num_noisy_block_++;
40 }
41 }
42
ResetConsecLowVar(int mb_index)43 void NoiseEstimation::ResetConsecLowVar(int mb_index) {
44 consec_low_var_[mb_index] = 0;
45 }
46
UpdateNoiseLevel()47 void NoiseEstimation::UpdateNoiseLevel() {
48 // TODO(jackychen): Tune a threshold for numb_noisy_block > T to make the
49 // condition more reasonable.
50 // No enough samples implies the motion of the camera or too many moving
51 // objects in the frame.
52 if (num_static_block_ <
53 (0.65 * mb_cols_ * mb_rows_ / NOISE_SUBSAMPLE_INTERVAL) ||
54 !num_noisy_block_) {
55 #if DISPLAY
56 printf("Not enough samples. %d \n", num_static_block_);
57 #elif DISPLAYNEON
58 __android_log_print(ANDROID_LOG_DEBUG, "DISPLAY",
59 "Not enough samples. %d \n", num_static_block_);
60 #endif
61 noise_var_ = 0;
62 noise_var_accum_ = 0;
63 num_noisy_block_ = 0;
64 num_static_block_ = 0;
65 return;
66 } else {
67 #if DISPLAY
68 printf("%d %d fraction = %.3f\n", num_static_block_,
69 mb_cols_ * mb_rows_ / NOISE_SUBSAMPLE_INTERVAL,
70 percent_static_block_);
71 #elif DISPLAYNEON
72 __android_log_print(ANDROID_LOG_DEBUG, "DISPLAY", "%d %d fraction = %.3f\n",
73 num_static_block_,
74 mb_cols_ * mb_rows_ / NOISE_SUBSAMPLE_INTERVAL,
75 percent_static_block_);
76 #endif
77 // Normalized by the number of noisy blocks.
78 noise_var_ /= num_noisy_block_;
79 // Get the percentage of static blocks.
80 percent_static_block_ = static_cast<double>(num_static_block_) /
81 (mb_cols_ * mb_rows_ / NOISE_SUBSAMPLE_INTERVAL);
82 num_noisy_block_ = 0;
83 num_static_block_ = 0;
84 }
85 // For the first frame just update the value with current noise_var_,
86 // otherwise, use the averaging window.
87 if (noise_var_accum_ == 0) {
88 noise_var_accum_ = noise_var_;
89 } else {
90 noise_var_accum_ = (noise_var_accum_ * 15 + noise_var_) / 16;
91 }
92 #if DISPLAY
93 printf("noise_var_accum_ = %.1f, noise_var_ = %d.\n", noise_var_accum_,
94 noise_var_);
95 #elif DISPLAYNEON
96 __android_log_print(ANDROID_LOG_DEBUG, "DISPLAY",
97 "noise_var_accum_ = %.1f, noise_var_ = %d.\n",
98 noise_var_accum_, noise_var_);
99 #endif
100 // Reset noise_var_ for the next frame.
101 noise_var_ = 0;
102 }
103
GetNoiseLevel()104 uint8_t NoiseEstimation::GetNoiseLevel() {
105 int noise_thr = cpu_type_ ? kNoiseThreshold : kNoiseThresholdNeon;
106 UpdateNoiseLevel();
107 if (noise_var_accum_ > noise_thr) {
108 return 1;
109 }
110 return 0;
111 }
112
113 } // namespace webrtc
114