Line data Source code
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 "webrtc/modules/video_processing/util/noise_estimation.h"
12 : #if DISPLAYNEON
13 : #include <android/log.h>
14 : #endif
15 :
16 : namespace webrtc {
17 :
18 0 : void NoiseEstimation::Init(int width, int height, CpuType cpu_type) {
19 0 : int mb_cols = width >> 4;
20 0 : int mb_rows = height >> 4;
21 0 : consec_low_var_.reset(new uint32_t[mb_cols * mb_rows]());
22 0 : width_ = width;
23 0 : height_ = height;
24 0 : mb_cols_ = width_ >> 4;
25 0 : mb_rows_ = height_ >> 4;
26 0 : cpu_type_ = cpu_type;
27 0 : }
28 :
29 0 : void NoiseEstimation::GetNoise(int mb_index, uint32_t var, uint32_t luma) {
30 0 : consec_low_var_[mb_index]++;
31 0 : num_static_block_++;
32 0 : if (consec_low_var_[mb_index] >= kConsecLowVarFrame &&
33 0 : (luma >> 6) < kAverageLumaMax && (luma >> 6) > kAverageLumaMin) {
34 : // Normalized var by the average luma value, this gives more weight to
35 : // darker blocks.
36 0 : int nor_var = var / (luma >> 10);
37 0 : noise_var_ +=
38 0 : nor_var > kBlockSelectionVarMax ? kBlockSelectionVarMax : nor_var;
39 0 : num_noisy_block_++;
40 : }
41 0 : }
42 :
43 0 : void NoiseEstimation::ResetConsecLowVar(int mb_index) {
44 0 : consec_low_var_[mb_index] = 0;
45 0 : }
46 :
47 0 : 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 0 : if (num_static_block_ <
53 0 : (0.65 * mb_cols_ * mb_rows_ / NOISE_SUBSAMPLE_INTERVAL) ||
54 0 : !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 0 : noise_var_ = 0;
62 0 : noise_var_accum_ = 0;
63 0 : num_noisy_block_ = 0;
64 0 : num_static_block_ = 0;
65 0 : 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 0 : noise_var_ /= num_noisy_block_;
79 : // Get the percentage of static blocks.
80 0 : percent_static_block_ = static_cast<double>(num_static_block_) /
81 0 : (mb_cols_ * mb_rows_ / NOISE_SUBSAMPLE_INTERVAL);
82 0 : num_noisy_block_ = 0;
83 0 : 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 0 : if (noise_var_accum_ == 0) {
88 0 : noise_var_accum_ = noise_var_;
89 : } else {
90 0 : 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 0 : noise_var_ = 0;
102 : }
103 :
104 0 : uint8_t NoiseEstimation::GetNoiseLevel() {
105 0 : int noise_thr = cpu_type_ ? kNoiseThreshold : kNoiseThresholdNeon;
106 0 : UpdateNoiseLevel();
107 0 : if (noise_var_accum_ > noise_thr) {
108 0 : return 1;
109 : }
110 0 : return 0;
111 : }
112 :
113 : } // namespace webrtc
|