1 /* 2 * Copyright (c) 2011 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/interface/video_processing.h" 12 #include "webrtc/modules/video_processing/main/source/brightness_detection.h" 13 14 #include <math.h> 15 16 namespace webrtc { 17 VPMBrightnessDetection()18VPMBrightnessDetection::VPMBrightnessDetection() : 19 id_(0) { 20 Reset(); 21 } 22 ~VPMBrightnessDetection()23VPMBrightnessDetection::~VPMBrightnessDetection() {} 24 ChangeUniqueId(const int32_t id)25int32_t VPMBrightnessDetection::ChangeUniqueId(const int32_t id) { 26 id_ = id; 27 return VPM_OK; 28 } 29 Reset()30void VPMBrightnessDetection::Reset() { 31 frame_cnt_bright_ = 0; 32 frame_cnt_dark_ = 0; 33 } 34 ProcessFrame(const I420VideoFrame & frame,const VideoProcessingModule::FrameStats & stats)35int32_t VPMBrightnessDetection::ProcessFrame( 36 const I420VideoFrame& frame, 37 const VideoProcessingModule::FrameStats& stats) { 38 if (frame.IsZeroSize()) { 39 return VPM_PARAMETER_ERROR; 40 } 41 int width = frame.width(); 42 int height = frame.height(); 43 44 if (!VideoProcessingModule::ValidFrameStats(stats)) { 45 return VPM_PARAMETER_ERROR; 46 } 47 48 const uint8_t frame_cnt_alarm = 2; 49 50 // Get proportion in lowest bins. 51 uint8_t low_th = 20; 52 float prop_low = 0; 53 for (uint32_t i = 0; i < low_th; i++) { 54 prop_low += stats.hist[i]; 55 } 56 prop_low /= stats.num_pixels; 57 58 // Get proportion in highest bins. 59 unsigned char high_th = 230; 60 float prop_high = 0; 61 for (uint32_t i = high_th; i < 256; i++) { 62 prop_high += stats.hist[i]; 63 } 64 prop_high /= stats.num_pixels; 65 66 if (prop_high < 0.4) { 67 if (stats.mean < 90 || stats.mean > 170) { 68 // Standard deviation of Y 69 const uint8_t* buffer = frame.buffer(kYPlane); 70 float std_y = 0; 71 for (int h = 0; h < height; h += (1 << stats.subSamplHeight)) { 72 int row = h*width; 73 for (int w = 0; w < width; w += (1 << stats.subSamplWidth)) { 74 std_y += (buffer[w + row] - stats.mean) * (buffer[w + row] - 75 stats.mean); 76 } 77 } 78 std_y = sqrt(std_y / stats.num_pixels); 79 80 // Get percentiles. 81 uint32_t sum = 0; 82 uint32_t median_y = 140; 83 uint32_t perc05 = 0; 84 uint32_t perc95 = 255; 85 float pos_perc05 = stats.num_pixels * 0.05f; 86 float pos_median = stats.num_pixels * 0.5f; 87 float posPerc95 = stats.num_pixels * 0.95f; 88 for (uint32_t i = 0; i < 256; i++) { 89 sum += stats.hist[i]; 90 if (sum < pos_perc05) perc05 = i; // 5th perc. 91 if (sum < pos_median) median_y = i; // 50th perc. 92 if (sum < posPerc95) 93 perc95 = i; // 95th perc. 94 else 95 break; 96 } 97 98 // Check if image is too dark 99 if ((std_y < 55) && (perc05 < 50)) { 100 if (median_y < 60 || stats.mean < 80 || perc95 < 130 || 101 prop_low > 0.20) { 102 frame_cnt_dark_++; 103 } else { 104 frame_cnt_dark_ = 0; 105 } 106 } else { 107 frame_cnt_dark_ = 0; 108 } 109 110 // Check if image is too bright 111 if ((std_y < 52) && (perc95 > 200) && (median_y > 160)) { 112 if (median_y > 185 || stats.mean > 185 || perc05 > 140 || 113 prop_high > 0.25) { 114 frame_cnt_bright_++; 115 } else { 116 frame_cnt_bright_ = 0; 117 } 118 } else { 119 frame_cnt_bright_ = 0; 120 } 121 } else { 122 frame_cnt_dark_ = 0; 123 frame_cnt_bright_ = 0; 124 } 125 } else { 126 frame_cnt_bright_++; 127 frame_cnt_dark_ = 0; 128 } 129 130 if (frame_cnt_dark_ > frame_cnt_alarm) { 131 return VideoProcessingModule::kDarkWarning; 132 } else if (frame_cnt_bright_ > frame_cnt_alarm) { 133 return VideoProcessingModule::kBrightWarning; 134 } else { 135 return VideoProcessingModule::kNoWarning; 136 } 137 } 138 139 } // namespace webrtc 140