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#include "webrtc/modules/video_processing/video_processing_impl.h"
12
13#include <assert.h>
14
15#include "webrtc/base/checks.h"
16#include "webrtc/base/logging.h"
17#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
18
19namespace webrtc {
20
21namespace {
22
23int GetSubSamplingFactor(int width, int height) {
24  if (width * height >= 640 * 480) {
25    return 3;
26  } else if (width * height >= 352 * 288) {
27    return 2;
28  } else if (width * height >= 176 * 144) {
29    return 1;
30  } else {
31    return 0;
32  }
33}
34}  // namespace
35
36VideoProcessing* VideoProcessing::Create() {
37  return new VideoProcessingImpl();
38}
39
40VideoProcessingImpl::VideoProcessingImpl() {}
41VideoProcessingImpl::~VideoProcessingImpl() {}
42
43void VideoProcessing::GetFrameStats(const VideoFrame& frame,
44                                    FrameStats* stats) {
45  ClearFrameStats(stats);  // The histogram needs to be zeroed out.
46  if (frame.IsZeroSize()) {
47    return;
48  }
49
50  int width = frame.width();
51  int height = frame.height();
52  stats->sub_sampling_factor = GetSubSamplingFactor(width, height);
53
54  const uint8_t* buffer = frame.buffer(kYPlane);
55  // Compute histogram and sum of frame
56  for (int i = 0; i < height; i += (1 << stats->sub_sampling_factor)) {
57    int k = i * width;
58    for (int j = 0; j < width; j += (1 << stats->sub_sampling_factor)) {
59      stats->hist[buffer[k + j]]++;
60      stats->sum += buffer[k + j];
61    }
62  }
63
64  stats->num_pixels = (width * height) / ((1 << stats->sub_sampling_factor) *
65                                          (1 << stats->sub_sampling_factor));
66  assert(stats->num_pixels > 0);
67
68  // Compute mean value of frame
69  stats->mean = stats->sum / stats->num_pixels;
70}
71
72bool VideoProcessing::ValidFrameStats(const FrameStats& stats) {
73  if (stats.num_pixels == 0) {
74    LOG(LS_WARNING) << "Invalid frame stats.";
75    return false;
76  }
77  return true;
78}
79
80void VideoProcessing::ClearFrameStats(FrameStats* stats) {
81  stats->mean = 0;
82  stats->sum = 0;
83  stats->num_pixels = 0;
84  stats->sub_sampling_factor = 0;
85  memset(stats->hist, 0, sizeof(stats->hist));
86}
87
88void VideoProcessing::Brighten(int delta, VideoFrame* frame) {
89  RTC_DCHECK(!frame->IsZeroSize());
90  RTC_DCHECK(frame->width() > 0);
91  RTC_DCHECK(frame->height() > 0);
92
93  int num_pixels = frame->width() * frame->height();
94
95  int look_up[256];
96  for (int i = 0; i < 256; i++) {
97    int val = i + delta;
98    look_up[i] = ((((val < 0) ? 0 : val) > 255) ? 255 : val);
99  }
100
101  uint8_t* temp_ptr = frame->buffer(kYPlane);
102  for (int i = 0; i < num_pixels; i++) {
103    *temp_ptr = static_cast<uint8_t>(look_up[*temp_ptr]);
104    temp_ptr++;
105  }
106}
107
108int32_t VideoProcessingImpl::Deflickering(VideoFrame* frame,
109                                          FrameStats* stats) {
110  rtc::CritScope mutex(&mutex_);
111  return deflickering_.ProcessFrame(frame, stats);
112}
113
114int32_t VideoProcessingImpl::BrightnessDetection(const VideoFrame& frame,
115                                                 const FrameStats& stats) {
116  rtc::CritScope mutex(&mutex_);
117  return brightness_detection_.ProcessFrame(frame, stats);
118}
119
120void VideoProcessingImpl::EnableTemporalDecimation(bool enable) {
121  rtc::CritScope mutex(&mutex_);
122  frame_pre_processor_.EnableTemporalDecimation(enable);
123}
124
125void VideoProcessingImpl::SetInputFrameResampleMode(
126    VideoFrameResampling resampling_mode) {
127  rtc::CritScope cs(&mutex_);
128  frame_pre_processor_.SetInputFrameResampleMode(resampling_mode);
129}
130
131int32_t VideoProcessingImpl::SetTargetResolution(uint32_t width,
132                                                 uint32_t height,
133                                                 uint32_t frame_rate) {
134  rtc::CritScope cs(&mutex_);
135  return frame_pre_processor_.SetTargetResolution(width, height, frame_rate);
136}
137
138void VideoProcessingImpl::SetTargetFramerate(int frame_rate) {
139  rtc::CritScope cs(&mutex_);
140  frame_pre_processor_.SetTargetFramerate(frame_rate);
141}
142
143uint32_t VideoProcessingImpl::GetDecimatedFrameRate() {
144  rtc::CritScope cs(&mutex_);
145  return frame_pre_processor_.GetDecimatedFrameRate();
146}
147
148uint32_t VideoProcessingImpl::GetDecimatedWidth() const {
149  rtc::CritScope cs(&mutex_);
150  return frame_pre_processor_.GetDecimatedWidth();
151}
152
153uint32_t VideoProcessingImpl::GetDecimatedHeight() const {
154  rtc::CritScope cs(&mutex_);
155  return frame_pre_processor_.GetDecimatedHeight();
156}
157
158void VideoProcessingImpl::EnableDenosing(bool enable) {
159  rtc::CritScope cs(&mutex_);
160  frame_pre_processor_.EnableDenosing(enable);
161}
162
163const VideoFrame* VideoProcessingImpl::PreprocessFrame(
164    const VideoFrame& frame) {
165  rtc::CritScope mutex(&mutex_);
166  return frame_pre_processor_.PreprocessFrame(frame);
167}
168
169VideoContentMetrics* VideoProcessingImpl::GetContentMetrics() const {
170  rtc::CritScope mutex(&mutex_);
171  return frame_pre_processor_.GetContentMetrics();
172}
173
174void VideoProcessingImpl::EnableContentAnalysis(bool enable) {
175  rtc::CritScope mutex(&mutex_);
176  frame_pre_processor_.EnableContentAnalysis(enable);
177}
178
179}  // namespace webrtc
180