Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / video_coding / utility / quality_scaler.cc
1 /*
2  *  Copyright (c) 2014 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_coding/utility/quality_scaler.h"
12
13 namespace webrtc {
14
15 static const int kMinFps = 10;
16 static const int kMeasureSeconds = 5;
17 static const int kFramedropPercentThreshold = 60;
18 static const int kLowQpThresholdDenominator = 3;
19
20 QualityScaler::QualityScaler()
21     : num_samples_(0), low_qp_threshold_(-1), downscale_shift_(0) {
22 }
23
24 void QualityScaler::Init(int max_qp) {
25   ClearSamples();
26   downscale_shift_ = 0;
27   low_qp_threshold_ = max_qp / kLowQpThresholdDenominator ;
28 }
29
30 void QualityScaler::ReportFramerate(int framerate) {
31   num_samples_ = static_cast<size_t>(
32       kMeasureSeconds * (framerate < kMinFps ? kMinFps : framerate));
33 }
34
35 void QualityScaler::ReportEncodedFrame(int qp) {
36   average_qp_.AddSample(qp);
37   framedrop_percent_.AddSample(0);
38 }
39
40 void QualityScaler::ReportDroppedFrame() {
41   framedrop_percent_.AddSample(100);
42 }
43
44 QualityScaler::Resolution QualityScaler::GetScaledResolution(
45     const I420VideoFrame& frame) {
46   // Both of these should be set through InitEncode -> Should be set by now.
47   assert(low_qp_threshold_ >= 0);
48   assert(num_samples_ > 0);
49   // Update scale factor.
50   int avg;
51   if (framedrop_percent_.GetAverage(num_samples_, &avg) &&
52       avg >= kFramedropPercentThreshold) {
53     AdjustScale(false);
54   } else if (average_qp_.GetAverage(num_samples_, &avg) &&
55              avg <= low_qp_threshold_) {
56     AdjustScale(true);
57   }
58
59   Resolution res;
60   res.width = frame.width();
61   res.height = frame.height();
62
63   assert(downscale_shift_ >= 0);
64   for (int shift = downscale_shift_;
65        shift > 0 && res.width > 1 && res.height > 1;
66        --shift) {
67     res.width >>= 1;
68     res.height >>= 1;
69   }
70
71   return res;
72 }
73
74 const I420VideoFrame& QualityScaler::GetScaledFrame(
75     const I420VideoFrame& frame) {
76   Resolution res = GetScaledResolution(frame);
77   if (res.width == frame.width())
78     return frame;
79
80   scaler_.Set(frame.width(),
81               frame.height(),
82               res.width,
83               res.height,
84               kI420,
85               kI420,
86               kScaleBox);
87   if (scaler_.Scale(frame, &scaled_frame_) != 0)
88     return frame;
89
90   scaled_frame_.set_ntp_time_ms(frame.ntp_time_ms());
91   scaled_frame_.set_timestamp(frame.timestamp());
92   scaled_frame_.set_render_time_ms(frame.render_time_ms());
93
94   return scaled_frame_;
95 }
96
97 QualityScaler::MovingAverage::MovingAverage() : sum_(0) {
98 }
99
100 void QualityScaler::MovingAverage::AddSample(int sample) {
101   samples_.push_back(sample);
102   sum_ += sample;
103 }
104
105 bool QualityScaler::MovingAverage::GetAverage(size_t num_samples, int* avg) {
106   assert(num_samples > 0);
107   if (num_samples > samples_.size())
108     return false;
109
110   // Remove old samples.
111   while (num_samples < samples_.size()) {
112     sum_ -= samples_.front();
113     samples_.pop_front();
114   }
115
116   *avg = sum_ / static_cast<int>(num_samples);
117   return true;
118 }
119
120 void QualityScaler::MovingAverage::Reset() {
121   sum_ = 0;
122   samples_.clear();
123 }
124
125 void QualityScaler::ClearSamples() {
126   average_qp_.Reset();
127   framedrop_percent_.Reset();
128 }
129
130 void QualityScaler::AdjustScale(bool up) {
131   downscale_shift_ += up ? -1 : 1;
132   if (downscale_shift_ < 0)
133     downscale_shift_ = 0;
134   ClearSamples();
135 }
136
137 }  // namespace webrtc