2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
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.
11 #include "webrtc/modules/video_coding/utility/quality_scaler.h"
15 static const int kMinFps = 10;
16 static const int kMeasureSeconds = 5;
17 static const int kFramedropPercentThreshold = 60;
18 static const int kLowQpThresholdDenominator = 3;
20 QualityScaler::QualityScaler()
21 : num_samples_(0), low_qp_threshold_(-1), downscale_shift_(0) {
24 void QualityScaler::Init(int max_qp) {
27 low_qp_threshold_ = max_qp / kLowQpThresholdDenominator ;
30 void QualityScaler::ReportFramerate(int framerate) {
31 num_samples_ = static_cast<size_t>(
32 kMeasureSeconds * (framerate < kMinFps ? kMinFps : framerate));
35 void QualityScaler::ReportEncodedFrame(int qp) {
36 average_qp_.AddSample(qp);
37 framedrop_percent_.AddSample(0);
40 void QualityScaler::ReportDroppedFrame() {
41 framedrop_percent_.AddSample(100);
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.
51 if (framedrop_percent_.GetAverage(num_samples_, &avg) &&
52 avg >= kFramedropPercentThreshold) {
54 } else if (average_qp_.GetAverage(num_samples_, &avg) &&
55 avg <= low_qp_threshold_) {
60 res.width = frame.width();
61 res.height = frame.height();
63 assert(downscale_shift_ >= 0);
64 for (int shift = downscale_shift_;
65 shift > 0 && res.width > 1 && res.height > 1;
74 const I420VideoFrame& QualityScaler::GetScaledFrame(
75 const I420VideoFrame& frame) {
76 Resolution res = GetScaledResolution(frame);
77 if (res.width == frame.width())
80 scaler_.Set(frame.width(),
87 if (scaler_.Scale(frame, &scaled_frame_) != 0)
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());
97 QualityScaler::MovingAverage::MovingAverage() : sum_(0) {
100 void QualityScaler::MovingAverage::AddSample(int sample) {
101 samples_.push_back(sample);
105 bool QualityScaler::MovingAverage::GetAverage(size_t num_samples, int* avg) {
106 assert(num_samples > 0);
107 if (num_samples > samples_.size())
110 // Remove old samples.
111 while (num_samples < samples_.size()) {
112 sum_ -= samples_.front();
113 samples_.pop_front();
116 *avg = sum_ / static_cast<int>(num_samples);
120 void QualityScaler::MovingAverage::Reset() {
125 void QualityScaler::ClearSamples() {
127 framedrop_percent_.Reset();
130 void QualityScaler::AdjustScale(bool up) {
131 downscale_shift_ += up ? -1 : 1;
132 if (downscale_shift_ < 0)
133 downscale_shift_ = 0;
137 } // namespace webrtc