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
15namespace webrtc {
16
17VPMFramePreprocessor::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
27VPMFramePreprocessor::~VPMFramePreprocessor() {
28  Reset();
29  delete ca_;
30  delete vd_;
31  delete spatial_resampler_;
32}
33
34void 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
43void VPMFramePreprocessor::EnableTemporalDecimation(bool enable) {
44  vd_->EnableTemporalDecimation(enable);
45}
46
47void VPMFramePreprocessor::EnableContentAnalysis(bool enable) {
48  enable_ca_ = enable;
49}
50
51void VPMFramePreprocessor::SetInputFrameResampleMode(
52    VideoFrameResampling resampling_mode) {
53  spatial_resampler_->SetInputFrameResampleMode(resampling_mode);
54}
55
56int32_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
72void 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
81void VPMFramePreprocessor::UpdateIncomingframe_rate() {
82  vd_->UpdateIncomingframe_rate();
83}
84
85uint32_t VPMFramePreprocessor::GetDecimatedFrameRate() {
86  return vd_->GetDecimatedFrameRate();
87}
88
89uint32_t VPMFramePreprocessor::GetDecimatedWidth() const {
90  return spatial_resampler_->TargetWidth();
91}
92
93uint32_t VPMFramePreprocessor::GetDecimatedHeight() const {
94  return spatial_resampler_->TargetHeight();
95}
96
97void VPMFramePreprocessor::EnableDenosing(bool enable) {
98  denoiser_.reset(new VideoDenoiser(true));
99}
100
101const 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
137VideoContentMetrics* VPMFramePreprocessor::GetContentMetrics() const {
138  return content_metrics_;
139}
140
141}  // namespace webrtc
142