blob: 50ff58b78665a3ed57766508c723c628026e2be8 [file] [log] [blame]
pbos@webrtc.orga0d78272014-09-12 11:51:47 +00001/*
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 */
jackychen61b4d512015-04-21 15:30:11 -070010#include "webrtc/modules/video_coding/utility/include/quality_scaler.h"
pbos@webrtc.orga0d78272014-09-12 11:51:47 +000011
12namespace webrtc {
13
14static const int kMinFps = 10;
15static const int kMeasureSeconds = 5;
16static const int kFramedropPercentThreshold = 60;
pbos@webrtc.orga0d78272014-09-12 11:51:47 +000017
18QualityScaler::QualityScaler()
jackychen61b4d512015-04-21 15:30:11 -070019 : num_samples_(0), low_qp_threshold_(-1), downscale_shift_(0),
20 min_width_(0), min_height_(0) {
pbos@webrtc.orga0d78272014-09-12 11:51:47 +000021}
22
jackychen98d8cf52015-05-21 11:12:02 -070023void QualityScaler::Init(int low_qp_threshold) {
pbos@webrtc.orga0d78272014-09-12 11:51:47 +000024 ClearSamples();
jackychen98d8cf52015-05-21 11:12:02 -070025 low_qp_threshold_ = low_qp_threshold;
pbos@webrtc.orga0d78272014-09-12 11:51:47 +000026}
27
jackychen61b4d512015-04-21 15:30:11 -070028void QualityScaler::SetMinResolution(int min_width, int min_height) {
29 min_width_ = min_width;
30 min_height_ = min_height;
31}
32
jackychen98d8cf52015-05-21 11:12:02 -070033// Report framerate(fps) to estimate # of samples.
pbos@webrtc.orga0d78272014-09-12 11:51:47 +000034void QualityScaler::ReportFramerate(int framerate) {
35 num_samples_ = static_cast<size_t>(
36 kMeasureSeconds * (framerate < kMinFps ? kMinFps : framerate));
37}
38
jackychen98d8cf52015-05-21 11:12:02 -070039void QualityScaler::ReportQP(int qp) {
pbos@webrtc.orga0d78272014-09-12 11:51:47 +000040 framedrop_percent_.AddSample(0);
jackychen98d8cf52015-05-21 11:12:02 -070041 average_qp_.AddSample(qp);
pbos@webrtc.orga0d78272014-09-12 11:51:47 +000042}
43
44void QualityScaler::ReportDroppedFrame() {
45 framedrop_percent_.AddSample(100);
46}
47
48QualityScaler::Resolution QualityScaler::GetScaledResolution(
49 const I420VideoFrame& frame) {
jackychen61b4d512015-04-21 15:30:11 -070050 // Should be set through InitEncode -> Should be set by now.
pbos@webrtc.orga0d78272014-09-12 11:51:47 +000051 assert(low_qp_threshold_ >= 0);
52 assert(num_samples_ > 0);
pbos@webrtc.orga0d78272014-09-12 11:51:47 +000053
54 Resolution res;
55 res.width = frame.width();
56 res.height = frame.height();
57
jackychen61b4d512015-04-21 15:30:11 -070058 // Update scale factor.
jackychen98d8cf52015-05-21 11:12:02 -070059 int avg_drop, avg_qp;
jackychen61b4d512015-04-21 15:30:11 -070060 if (framedrop_percent_.GetAverage(num_samples_, &avg_drop) &&
61 avg_drop >= kFramedropPercentThreshold) {
62 AdjustScale(false);
jackychen98d8cf52015-05-21 11:12:02 -070063 } else if (average_qp_.GetAverage(num_samples_, &avg_qp) &&
64 avg_qp <= low_qp_threshold_) {
jackychen61b4d512015-04-21 15:30:11 -070065 AdjustScale(true);
66 }
67
pbos@webrtc.orga0d78272014-09-12 11:51:47 +000068 assert(downscale_shift_ >= 0);
69 for (int shift = downscale_shift_;
70 shift > 0 && res.width > 1 && res.height > 1;
71 --shift) {
72 res.width >>= 1;
73 res.height >>= 1;
74 }
75
jackychen61b4d512015-04-21 15:30:11 -070076 // Set this limitation for VP8 HW encoder to avoid crash.
77 if (min_width_ > 0 && res.width * res.height < min_width_ * min_height_) {
78 res.width = min_width_;
79 res.height = min_height_;
80 }
81
pbos@webrtc.orga0d78272014-09-12 11:51:47 +000082 return res;
83}
84
85const I420VideoFrame& QualityScaler::GetScaledFrame(
86 const I420VideoFrame& frame) {
87 Resolution res = GetScaledResolution(frame);
88 if (res.width == frame.width())
89 return frame;
90
91 scaler_.Set(frame.width(),
92 frame.height(),
93 res.width,
94 res.height,
95 kI420,
96 kI420,
97 kScaleBox);
98 if (scaler_.Scale(frame, &scaled_frame_) != 0)
99 return frame;
100
101 scaled_frame_.set_ntp_time_ms(frame.ntp_time_ms());
102 scaled_frame_.set_timestamp(frame.timestamp());
103 scaled_frame_.set_render_time_ms(frame.render_time_ms());
104
105 return scaled_frame_;
106}
107
pbos@webrtc.orga0d78272014-09-12 11:51:47 +0000108void QualityScaler::ClearSamples() {
pbos@webrtc.orga0d78272014-09-12 11:51:47 +0000109 framedrop_percent_.Reset();
jackychen98d8cf52015-05-21 11:12:02 -0700110 average_qp_.Reset();
pbos@webrtc.orga0d78272014-09-12 11:51:47 +0000111}
112
113void QualityScaler::AdjustScale(bool up) {
114 downscale_shift_ += up ? -1 : 1;
115 if (downscale_shift_ < 0)
116 downscale_shift_ = 0;
117 ClearSamples();
118}
119
120} // namespace webrtc