Home | History | Annotate | Download | only in source
      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   frame_pre_processor_.ChangeUniqueId(id);
     55   return VPM_OK;
     56 }
     57 
     58 int32_t VideoProcessingModuleImpl::Id() const {
     59   CriticalSectionScoped mutex(&mutex_);
     60   return id_;
     61 }
     62 
     63 VideoProcessingModuleImpl::VideoProcessingModuleImpl(const int32_t id)
     64     : id_(id),
     65     mutex_(*CriticalSectionWrapper::CreateCriticalSection()) {
     66   brightness_detection_.ChangeUniqueId(id);
     67   deflickering_.ChangeUniqueId(id);
     68   frame_pre_processor_.ChangeUniqueId(id);
     69 }
     70 
     71 VideoProcessingModuleImpl::~VideoProcessingModuleImpl() {
     72   delete &mutex_;
     73 }
     74 
     75 void VideoProcessingModuleImpl::Reset() {
     76   CriticalSectionScoped mutex(&mutex_);
     77   deflickering_.Reset();
     78   brightness_detection_.Reset();
     79   frame_pre_processor_.Reset();
     80 }
     81 
     82 int32_t VideoProcessingModule::GetFrameStats(FrameStats* stats,
     83                                              const I420VideoFrame& frame) {
     84   if (frame.IsZeroSize()) {
     85     LOG(LS_ERROR) << "Zero size frame.";
     86     return VPM_PARAMETER_ERROR;
     87   }
     88 
     89   int width = frame.width();
     90   int height = frame.height();
     91 
     92   ClearFrameStats(stats);  // The histogram needs to be zeroed out.
     93   SetSubSampling(stats, width, height);
     94 
     95   const uint8_t* buffer = frame.buffer(kYPlane);
     96   // Compute histogram and sum of frame
     97   for (int i = 0; i < height; i += (1 << stats->subSamplHeight)) {
     98     int k = i * width;
     99     for (int j = 0; j < width; j += (1 << stats->subSamplWidth)) {
    100       stats->hist[buffer[k + j]]++;
    101       stats->sum += buffer[k + j];
    102     }
    103   }
    104 
    105   stats->num_pixels = (width * height) / ((1 << stats->subSamplWidth) *
    106                      (1 << stats->subSamplHeight));
    107   assert(stats->num_pixels > 0);
    108 
    109   // Compute mean value of frame
    110   stats->mean = stats->sum / stats->num_pixels;
    111 
    112   return VPM_OK;
    113 }
    114 
    115 bool VideoProcessingModule::ValidFrameStats(const FrameStats& stats) {
    116   if (stats.num_pixels == 0) {
    117     LOG(LS_WARNING) << "Invalid frame stats.";
    118     return false;
    119   }
    120   return true;
    121 }
    122 
    123 void VideoProcessingModule::ClearFrameStats(FrameStats* stats) {
    124   stats->mean = 0;
    125   stats->sum = 0;
    126   stats->num_pixels = 0;
    127   stats->subSamplWidth = 0;
    128   stats->subSamplHeight = 0;
    129   memset(stats->hist, 0, sizeof(stats->hist));
    130 }
    131 
    132 int32_t VideoProcessingModule::ColorEnhancement(I420VideoFrame* frame) {
    133   return VideoProcessing::ColorEnhancement(frame);
    134 }
    135 
    136 int32_t VideoProcessingModule::Brighten(I420VideoFrame* frame, int delta) {
    137   return VideoProcessing::Brighten(frame, delta);
    138 }
    139 
    140 int32_t VideoProcessingModuleImpl::Deflickering(I420VideoFrame* frame,
    141                                                 FrameStats* stats) {
    142   CriticalSectionScoped mutex(&mutex_);
    143   return deflickering_.ProcessFrame(frame, stats);
    144 }
    145 
    146 int32_t VideoProcessingModuleImpl::BrightnessDetection(
    147   const I420VideoFrame& frame,
    148   const FrameStats& stats) {
    149   CriticalSectionScoped mutex(&mutex_);
    150   return brightness_detection_.ProcessFrame(frame, stats);
    151 }
    152 
    153 
    154 void VideoProcessingModuleImpl::EnableTemporalDecimation(bool enable) {
    155   CriticalSectionScoped mutex(&mutex_);
    156   frame_pre_processor_.EnableTemporalDecimation(enable);
    157 }
    158 
    159 
    160 void VideoProcessingModuleImpl::SetInputFrameResampleMode(VideoFrameResampling
    161                                                           resampling_mode) {
    162   CriticalSectionScoped cs(&mutex_);
    163   frame_pre_processor_.SetInputFrameResampleMode(resampling_mode);
    164 }
    165 
    166 int32_t VideoProcessingModuleImpl::SetTargetResolution(uint32_t width,
    167                                                        uint32_t height,
    168                                                        uint32_t frame_rate) {
    169   CriticalSectionScoped cs(&mutex_);
    170   return frame_pre_processor_.SetTargetResolution(width, height, frame_rate);
    171 }
    172 
    173 uint32_t VideoProcessingModuleImpl::Decimatedframe_rate() {
    174   CriticalSectionScoped cs(&mutex_);
    175   return  frame_pre_processor_.Decimatedframe_rate();
    176 }
    177 
    178 uint32_t VideoProcessingModuleImpl::DecimatedWidth() const {
    179   CriticalSectionScoped cs(&mutex_);
    180   return frame_pre_processor_.DecimatedWidth();
    181 }
    182 
    183 uint32_t VideoProcessingModuleImpl::DecimatedHeight() const {
    184   CriticalSectionScoped cs(&mutex_);
    185   return frame_pre_processor_.DecimatedHeight();
    186 }
    187 
    188 int32_t VideoProcessingModuleImpl::PreprocessFrame(
    189     const I420VideoFrame& frame,
    190     I420VideoFrame **processed_frame) {
    191   CriticalSectionScoped mutex(&mutex_);
    192   return frame_pre_processor_.PreprocessFrame(frame, processed_frame);
    193 }
    194 
    195 VideoContentMetrics* VideoProcessingModuleImpl::ContentMetrics() const {
    196   CriticalSectionScoped mutex(&mutex_);
    197   return frame_pre_processor_.ContentMetrics();
    198 }
    199 
    200 void VideoProcessingModuleImpl::EnableContentAnalysis(bool enable) {
    201   CriticalSectionScoped mutex(&mutex_);
    202   frame_pre_processor_.EnableContentAnalysis(enable);
    203 }
    204 
    205 }  // namespace webrtc
    206