1 /* 2 * Copyright (c) 2012 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 12 #include "webrtc/modules/video_processing/main/source/video_processing_impl.h" 13 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 14 #include "webrtc/system_wrappers/interface/logging.h" 15 16 #include <assert.h> 17 18 namespace webrtc { 19 20 namespace { 21 void SetSubSampling(VideoProcessingModule::FrameStats* stats, 22 const int32_t width, 23 const int32_t height) { 24 if (width * height >= 640 * 480) { 25 stats->subSamplWidth = 3; 26 stats->subSamplHeight = 3; 27 } else if (width * height >= 352 * 288) { 28 stats->subSamplWidth = 2; 29 stats->subSamplHeight = 2; 30 } else if (width * height >= 176 * 144) { 31 stats->subSamplWidth = 1; 32 stats->subSamplHeight = 1; 33 } else { 34 stats->subSamplWidth = 0; 35 stats->subSamplHeight = 0; 36 } 37 } 38 } // namespace 39 40 VideoProcessingModule* VideoProcessingModule::Create(const int32_t id) { 41 return new VideoProcessingModuleImpl(id); 42 } 43 44 void VideoProcessingModule::Destroy(VideoProcessingModule* module) { 45 if (module) 46 delete static_cast<VideoProcessingModuleImpl*>(module); 47 } 48 49 int32_t VideoProcessingModuleImpl::ChangeUniqueId(const int32_t id) { 50 CriticalSectionScoped mutex(&mutex_); 51 id_ = id; 52 brightness_detection_.ChangeUniqueId(id); 53 deflickering_.ChangeUniqueId(id); 54 denoising_.ChangeUniqueId(id); 55 frame_pre_processor_.ChangeUniqueId(id); 56 return VPM_OK; 57 } 58 59 int32_t VideoProcessingModuleImpl::Id() const { 60 CriticalSectionScoped mutex(&mutex_); 61 return id_; 62 } 63 64 VideoProcessingModuleImpl::VideoProcessingModuleImpl(const int32_t id) 65 : id_(id), 66 mutex_(*CriticalSectionWrapper::CreateCriticalSection()) { 67 brightness_detection_.ChangeUniqueId(id); 68 deflickering_.ChangeUniqueId(id); 69 denoising_.ChangeUniqueId(id); 70 frame_pre_processor_.ChangeUniqueId(id); 71 } 72 73 VideoProcessingModuleImpl::~VideoProcessingModuleImpl() { 74 delete &mutex_; 75 } 76 77 void VideoProcessingModuleImpl::Reset() { 78 CriticalSectionScoped mutex(&mutex_); 79 deflickering_.Reset(); 80 denoising_.Reset(); 81 brightness_detection_.Reset(); 82 frame_pre_processor_.Reset(); 83 } 84 85 int32_t VideoProcessingModule::GetFrameStats(FrameStats* stats, 86 const I420VideoFrame& frame) { 87 if (frame.IsZeroSize()) { 88 LOG(LS_ERROR) << "Zero size frame."; 89 return VPM_PARAMETER_ERROR; 90 } 91 92 int width = frame.width(); 93 int height = frame.height(); 94 95 ClearFrameStats(stats); // The histogram needs to be zeroed out. 96 SetSubSampling(stats, width, height); 97 98 const uint8_t* buffer = frame.buffer(kYPlane); 99 // Compute histogram and sum of frame 100 for (int i = 0; i < height; i += (1 << stats->subSamplHeight)) { 101 int k = i * width; 102 for (int j = 0; j < width; j += (1 << stats->subSamplWidth)) { 103 stats->hist[buffer[k + j]]++; 104 stats->sum += buffer[k + j]; 105 } 106 } 107 108 stats->num_pixels = (width * height) / ((1 << stats->subSamplWidth) * 109 (1 << stats->subSamplHeight)); 110 assert(stats->num_pixels > 0); 111 112 // Compute mean value of frame 113 stats->mean = stats->sum / stats->num_pixels; 114 115 return VPM_OK; 116 } 117 118 bool VideoProcessingModule::ValidFrameStats(const FrameStats& stats) { 119 if (stats.num_pixels == 0) { 120 LOG(LS_WARNING) << "Invalid frame stats."; 121 return false; 122 } 123 return true; 124 } 125 126 void VideoProcessingModule::ClearFrameStats(FrameStats* stats) { 127 stats->mean = 0; 128 stats->sum = 0; 129 stats->num_pixels = 0; 130 stats->subSamplWidth = 0; 131 stats->subSamplHeight = 0; 132 memset(stats->hist, 0, sizeof(stats->hist)); 133 } 134 135 int32_t VideoProcessingModule::ColorEnhancement(I420VideoFrame* frame) { 136 return VideoProcessing::ColorEnhancement(frame); 137 } 138 139 int32_t VideoProcessingModule::Brighten(I420VideoFrame* frame, int delta) { 140 return VideoProcessing::Brighten(frame, delta); 141 } 142 143 int32_t VideoProcessingModuleImpl::Deflickering(I420VideoFrame* frame, 144 FrameStats* stats) { 145 CriticalSectionScoped mutex(&mutex_); 146 return deflickering_.ProcessFrame(frame, stats); 147 } 148 149 int32_t VideoProcessingModuleImpl::Denoising(I420VideoFrame* frame) { 150 CriticalSectionScoped mutex(&mutex_); 151 return denoising_.ProcessFrame(frame); 152 } 153 154 int32_t VideoProcessingModuleImpl::BrightnessDetection( 155 const I420VideoFrame& frame, 156 const FrameStats& stats) { 157 CriticalSectionScoped mutex(&mutex_); 158 return brightness_detection_.ProcessFrame(frame, stats); 159 } 160 161 162 void VideoProcessingModuleImpl::EnableTemporalDecimation(bool enable) { 163 CriticalSectionScoped mutex(&mutex_); 164 frame_pre_processor_.EnableTemporalDecimation(enable); 165 } 166 167 168 void VideoProcessingModuleImpl::SetInputFrameResampleMode(VideoFrameResampling 169 resampling_mode) { 170 CriticalSectionScoped cs(&mutex_); 171 frame_pre_processor_.SetInputFrameResampleMode(resampling_mode); 172 } 173 174 int32_t VideoProcessingModuleImpl::SetTargetResolution(uint32_t width, 175 uint32_t height, 176 uint32_t frame_rate) { 177 CriticalSectionScoped cs(&mutex_); 178 return frame_pre_processor_.SetTargetResolution(width, height, frame_rate); 179 } 180 181 uint32_t VideoProcessingModuleImpl::Decimatedframe_rate() { 182 CriticalSectionScoped cs(&mutex_); 183 return frame_pre_processor_.Decimatedframe_rate(); 184 } 185 186 uint32_t VideoProcessingModuleImpl::DecimatedWidth() const { 187 CriticalSectionScoped cs(&mutex_); 188 return frame_pre_processor_.DecimatedWidth(); 189 } 190 191 uint32_t VideoProcessingModuleImpl::DecimatedHeight() const { 192 CriticalSectionScoped cs(&mutex_); 193 return frame_pre_processor_.DecimatedHeight(); 194 } 195 196 int32_t VideoProcessingModuleImpl::PreprocessFrame( 197 const I420VideoFrame& frame, 198 I420VideoFrame **processed_frame) { 199 CriticalSectionScoped mutex(&mutex_); 200 return frame_pre_processor_.PreprocessFrame(frame, processed_frame); 201 } 202 203 VideoContentMetrics* VideoProcessingModuleImpl::ContentMetrics() const { 204 CriticalSectionScoped mutex(&mutex_); 205 return frame_pre_processor_.ContentMetrics(); 206 } 207 208 void VideoProcessingModuleImpl::EnableContentAnalysis(bool enable) { 209 CriticalSectionScoped mutex(&mutex_); 210 frame_pre_processor_.EnableContentAnalysis(enable); 211 } 212 213 } // namespace webrtc 214