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/frame_preprocessor.h"
12 
13 #include "webrtc/modules/video_processing/video_denoiser.h"
14 
15 namespace webrtc {
16 
VPMFramePreprocessor()17 VPMFramePreprocessor::VPMFramePreprocessor()
18     : content_metrics_(nullptr),
19       resampled_frame_(),
20       enable_ca_(false),
21       frame_cnt_(0) {
22   spatial_resampler_ = new VPMSimpleSpatialResampler();
23   ca_ = new VPMContentAnalysis(true);
24   vd_ = new VPMVideoDecimator();
25 }
26 
~VPMFramePreprocessor()27 VPMFramePreprocessor::~VPMFramePreprocessor() {
28   Reset();
29   delete ca_;
30   delete vd_;
31   delete spatial_resampler_;
32 }
33 
Reset()34 void VPMFramePreprocessor::Reset() {
35   ca_->Release();
36   vd_->Reset();
37   content_metrics_ = nullptr;
38   spatial_resampler_->Reset();
39   enable_ca_ = false;
40   frame_cnt_ = 0;
41 }
42 
EnableTemporalDecimation(bool enable)43 void VPMFramePreprocessor::EnableTemporalDecimation(bool enable) {
44   vd_->EnableTemporalDecimation(enable);
45 }
46 
EnableContentAnalysis(bool enable)47 void VPMFramePreprocessor::EnableContentAnalysis(bool enable) {
48   enable_ca_ = enable;
49 }
50 
SetInputFrameResampleMode(VideoFrameResampling resampling_mode)51 void VPMFramePreprocessor::SetInputFrameResampleMode(
52     VideoFrameResampling resampling_mode) {
53   spatial_resampler_->SetInputFrameResampleMode(resampling_mode);
54 }
55 
SetTargetResolution(uint32_t width,uint32_t height,uint32_t frame_rate)56 int32_t VPMFramePreprocessor::SetTargetResolution(uint32_t width,
57                                                   uint32_t height,
58                                                   uint32_t frame_rate) {
59   if ((width == 0) || (height == 0) || (frame_rate == 0)) {
60     return VPM_PARAMETER_ERROR;
61   }
62   int32_t ret_val = 0;
63   ret_val = spatial_resampler_->SetTargetFrameSize(width, height);
64 
65   if (ret_val < 0)
66     return ret_val;
67 
68   vd_->SetTargetFramerate(frame_rate);
69   return VPM_OK;
70 }
71 
SetTargetFramerate(int frame_rate)72 void VPMFramePreprocessor::SetTargetFramerate(int frame_rate) {
73   if (frame_rate == -1) {
74     vd_->EnableTemporalDecimation(false);
75   } else {
76     vd_->EnableTemporalDecimation(true);
77     vd_->SetTargetFramerate(frame_rate);
78   }
79 }
80 
UpdateIncomingframe_rate()81 void VPMFramePreprocessor::UpdateIncomingframe_rate() {
82   vd_->UpdateIncomingframe_rate();
83 }
84 
GetDecimatedFrameRate()85 uint32_t VPMFramePreprocessor::GetDecimatedFrameRate() {
86   return vd_->GetDecimatedFrameRate();
87 }
88 
GetDecimatedWidth() const89 uint32_t VPMFramePreprocessor::GetDecimatedWidth() const {
90   return spatial_resampler_->TargetWidth();
91 }
92 
GetDecimatedHeight() const93 uint32_t VPMFramePreprocessor::GetDecimatedHeight() const {
94   return spatial_resampler_->TargetHeight();
95 }
96 
EnableDenosing(bool enable)97 void VPMFramePreprocessor::EnableDenosing(bool enable) {
98   denoiser_.reset(new VideoDenoiser(true));
99 }
100 
PreprocessFrame(const VideoFrame & frame)101 const VideoFrame* VPMFramePreprocessor::PreprocessFrame(
102     const VideoFrame& frame) {
103   if (frame.IsZeroSize()) {
104     return nullptr;
105   }
106 
107   vd_->UpdateIncomingframe_rate();
108   if (vd_->DropFrame()) {
109     return nullptr;
110   }
111 
112   const VideoFrame* current_frame = &frame;
113   if (denoiser_) {
114     denoiser_->DenoiseFrame(*current_frame, &denoised_frame_);
115     current_frame = &denoised_frame_;
116   }
117 
118   if (spatial_resampler_->ApplyResample(current_frame->width(),
119                                         current_frame->height())) {
120     if (spatial_resampler_->ResampleFrame(*current_frame, &resampled_frame_) !=
121         VPM_OK) {
122       return nullptr;
123     }
124     current_frame = &resampled_frame_;
125   }
126 
127   // Perform content analysis on the frame to be encoded.
128   if (enable_ca_ && frame_cnt_ % kSkipFrameCA == 0) {
129     // Compute new metrics every |kSkipFramesCA| frames, starting with
130     // the first frame.
131     content_metrics_ = ca_->ComputeContentMetrics(*current_frame);
132   }
133   ++frame_cnt_;
134   return current_frame;
135 }
136 
GetContentMetrics() const137 VideoContentMetrics* VPMFramePreprocessor::GetContentMetrics() const {
138   return content_metrics_;
139 }
140 
141 }  // namespace webrtc
142