blob: 3b0d59ef717d8095a5ab1bac4650b296c7173de6 [file] [log] [blame]
jackychenfa0befe2016-04-01 07:46:58 -07001/*
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"
jackychen8556c482016-04-20 16:04:31 -070012#if DISPLAYNEON
jackychene42c0ae2016-04-16 10:44:16 -070013#include <android/log.h>
14#endif
jackychenfa0befe2016-04-01 07:46:58 -070015
16namespace webrtc {
17
18void 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
29void 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 &&
jackychenafaae0d2016-04-12 23:02:55 -070033 (luma >> 6) < kAverageLumaMax && (luma >> 6) > kAverageLumaMin) {
jackychenfa0befe2016-04-01 07:46:58 -070034 // Normalized var by the average luma value, this gives more weight to
35 // darker blocks.
jackychenafaae0d2016-04-12 23:02:55 -070036 int nor_var = var / (luma >> 10);
jackychenfa0befe2016-04-01 07:46:58 -070037 noise_var_ +=
38 nor_var > kBlockSelectionVarMax ? kBlockSelectionVarMax : nor_var;
39 num_noisy_block_++;
40 }
41}
42
43void NoiseEstimation::ResetConsecLowVar(int mb_index) {
44 consec_low_var_[mb_index] = 0;
45}
46
47void 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.
jackychenafaae0d2016-04-12 23:02:55 -070052 if (num_static_block_ <
53 (0.65 * mb_cols_ * mb_rows_ / NOISE_SUBSAMPLE_INTERVAL) ||
54 !num_noisy_block_) {
55#if DISPLAY
jackychen8556c482016-04-20 16:04:31 -070056 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_);
jackychenafaae0d2016-04-12 23:02:55 -070060#endif
jackychenfa0befe2016-04-01 07:46:58 -070061 noise_var_ = 0;
62 noise_var_accum_ = 0;
jackychenfa0befe2016-04-01 07:46:58 -070063 num_noisy_block_ = 0;
jackychenafaae0d2016-04-12 23:02:55 -070064 num_static_block_ = 0;
jackychenfa0befe2016-04-01 07:46:58 -070065 return;
66 } else {
jackychenafaae0d2016-04-12 23:02:55 -070067#if DISPLAY
jackychen8556c482016-04-20 16:04:31 -070068 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_);
jackychenafaae0d2016-04-12 23:02:55 -070076#endif
jackychenfa0befe2016-04-01 07:46:58 -070077 // Normalized by the number of noisy blocks.
78 noise_var_ /= num_noisy_block_;
79 // Get the percentage of static blocks.
jackychenafaae0d2016-04-12 23:02:55 -070080 percent_static_block_ = static_cast<double>(num_static_block_) /
81 (mb_cols_ * mb_rows_ / NOISE_SUBSAMPLE_INTERVAL);
jackychenfa0befe2016-04-01 07:46:58 -070082 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 }
jackychenfa0befe2016-04-01 07:46:58 -070092#if DISPLAY
jackychen8556c482016-04-20 16:04:31 -070093 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_);
jackychenfa0befe2016-04-01 07:46:58 -070099#endif
jackychenafaae0d2016-04-12 23:02:55 -0700100 // Reset noise_var_ for the next frame.
101 noise_var_ = 0;
jackychenfa0befe2016-04-01 07:46:58 -0700102}
103
104uint8_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