• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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()18 VPMBrightnessDetection::VPMBrightnessDetection() :
19     id_(0) {
20   Reset();
21 }
22 
~VPMBrightnessDetection()23 VPMBrightnessDetection::~VPMBrightnessDetection() {}
24 
ChangeUniqueId(const int32_t id)25 int32_t VPMBrightnessDetection::ChangeUniqueId(const int32_t id) {
26   id_ = id;
27   return VPM_OK;
28 }
29 
Reset()30 void VPMBrightnessDetection::Reset() {
31   frame_cnt_bright_ = 0;
32   frame_cnt_dark_ = 0;
33 }
34 
ProcessFrame(const I420VideoFrame & frame,const VideoProcessingModule::FrameStats & stats)35 int32_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