OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/video_coding/utility/quality_scaler.h" | 11 #include "webrtc/modules/video_coding/utility/quality_scaler.h" |
12 | 12 |
13 #include <math.h> | 13 #include <math.h> |
14 | 14 |
15 #include <algorithm> | 15 #include <algorithm> |
16 | 16 |
17 #include "webrtc/base/checks.h" | |
18 | |
17 // TODO(kthelgason): Some versions of Android have issues with log2. | 19 // TODO(kthelgason): Some versions of Android have issues with log2. |
18 // See https://code.google.com/p/android/issues/detail?id=212634 for details | 20 // See https://code.google.com/p/android/issues/detail?id=212634 for details |
19 #if defined(WEBRTC_ANDROID) | 21 #if defined(WEBRTC_ANDROID) |
20 #define log2(x) (log(x) / log(2)) | 22 #define log2(x) (log(x) / log(2)) |
21 #endif | 23 #endif |
22 | 24 |
23 namespace webrtc { | 25 namespace webrtc { |
24 | 26 |
25 namespace { | 27 namespace { |
26 // Threshold constant used until first downscale (to permit fast rampup). | 28 // Threshold constant used until first downscale (to permit fast rampup). |
27 static const int kMeasureSecondsFastUpscale = 2; | 29 static const int kMeasureSecondsFastUpscale = 2; |
28 static const int kMeasureSecondsUpscale = 5; | 30 static const int kMeasureSecondsUpscale = 5; |
29 static const int kMeasureSecondsDownscale = 5; | 31 static const int kMeasureSecondsDownscale = 5; |
30 static const int kFramedropPercentThreshold = 60; | 32 static const int kFramedropPercentThreshold = 60; |
31 // Min width/height to downscale to, set to not go below QVGA, but with some | 33 // Min width/height to downscale to, set to not go below QVGA, but with some |
32 // margin to permit "almost-QVGA" resolutions, such as QCIF. | 34 // margin to permit "almost-QVGA" resolutions, such as QCIF. |
33 static const int kMinDownscaleDimension = 140; | 35 static const int kMinDownscaleDimension = 140; |
34 // Initial resolutions corresponding to a bitrate. Aa bit above their actual | 36 // Initial resolutions corresponding to a bitrate. Aa bit above their actual |
35 // values to permit near-VGA and near-QVGA resolutions to use the same | 37 // values to permit near-VGA and near-QVGA resolutions to use the same |
36 // mechanism. | 38 // mechanism. |
37 static const int kVgaBitrateThresholdKbps = 500; | 39 static const int kVgaBitrateThresholdKbps = 500; |
38 static const int kVgaNumPixels = 700 * 500; // 640x480 | 40 static const int kVgaNumPixels = 700 * 500; // 640x480 |
39 static const int kQvgaBitrateThresholdKbps = 250; | 41 static const int kQvgaBitrateThresholdKbps = 250; |
40 static const int kQvgaNumPixels = 400 * 300; // 320x240 | 42 static const int kQvgaNumPixels = 400 * 300; // 320x240 |
43 | |
44 // QP scaling threshold defaults: | |
45 static const int kLowH264QpThreshold = 28; | |
46 static const int kHighH264QpThreshold = 39; | |
47 // QP is obtained from VP8-bitstream for HW, so the QP corresponds to the | |
48 // bitstream range of [0, 127] and not the user-level range of [0,63]. | |
49 static const int kLowVp8QpThreshold = 29; | |
50 static const int kHighVp8QpThreshold = 95; | |
41 } // namespace | 51 } // namespace |
42 | 52 |
43 // QP thresholds are chosen to be high enough to be hit in practice when quality | |
44 // is good, but also low enough to not cause a flip-flop behavior (e.g. going up | |
45 // in resolution shouldn't give so bad quality that we should go back down). | |
46 | |
47 const int QualityScaler::kLowVp8QpThreshold = 29; | |
48 const int QualityScaler::kBadVp8QpThreshold = 95; | |
49 | |
50 #if defined(WEBRTC_IOS) | |
51 const int QualityScaler::kLowH264QpThreshold = 32; | |
52 const int QualityScaler::kBadH264QpThreshold = 42; | |
53 #else | |
54 const int QualityScaler::kLowH264QpThreshold = 24; | |
55 const int QualityScaler::kBadH264QpThreshold = 37; | |
56 #endif | |
57 | |
58 // Default values. Should immediately get set to something more sensible. | 53 // Default values. Should immediately get set to something more sensible. |
59 QualityScaler::QualityScaler() | 54 QualityScaler::QualityScaler() |
60 : average_qp_(kMeasureSecondsUpscale * 30), | 55 : average_qp_(kMeasureSecondsUpscale * 30), |
61 framedrop_percent_(kMeasureSecondsUpscale * 30), | 56 framedrop_percent_(kMeasureSecondsUpscale * 30), |
62 low_qp_threshold_(-1) {} | 57 low_qp_threshold_(-1) {} |
63 | 58 |
64 void QualityScaler::Init(int low_qp_threshold, | 59 void QualityScaler::Init(VideoCodecType codec_type, |
65 int high_qp_threshold, | |
66 int initial_bitrate_kbps, | 60 int initial_bitrate_kbps, |
67 int width, | 61 int width, |
68 int height, | 62 int height, |
69 int fps) { | 63 int fps) { |
70 low_qp_threshold_ = low_qp_threshold; | 64 ClearSamples(); |
pbos-webrtc
2016/09/19 14:06:57
Have this function just get low/high thresholds an
| |
71 high_qp_threshold_ = high_qp_threshold; | 65 switch (codec_type) { |
66 case kVideoCodecH264: | |
67 low_qp_threshold_ = kLowH264QpThreshold; | |
68 high_qp_threshold_ = kHighH264QpThreshold; | |
69 break; | |
70 case kVideoCodecVP8: | |
71 low_qp_threshold_ = kLowVp8QpThreshold; | |
72 high_qp_threshold_ = kHighVp8QpThreshold; | |
73 break; | |
74 default: | |
75 RTC_NOTREACHED() << "Invalid codec type for QualityScaler."; | |
76 } | |
72 downscale_shift_ = 0; | 77 downscale_shift_ = 0; |
73 | 78 |
74 fast_rampup_ = true; | 79 fast_rampup_ = true; |
75 | 80 |
76 ClearSamples(); | 81 ClearSamples(); |
77 ReportFramerate(fps); | 82 ReportFramerate(fps); |
78 | 83 |
79 const int init_width = width; | 84 const int init_width = width; |
80 const int init_height = height; | 85 const int init_height = height; |
81 if (initial_bitrate_kbps > 0) { | 86 if (initial_bitrate_kbps > 0) { |
82 int init_num_pixels = width * height; | 87 int init_num_pixels = width * height; |
83 if (initial_bitrate_kbps < kVgaBitrateThresholdKbps) | 88 if (initial_bitrate_kbps < kVgaBitrateThresholdKbps) |
84 init_num_pixels = kVgaNumPixels; | 89 init_num_pixels = kVgaNumPixels; |
85 if (initial_bitrate_kbps < kQvgaBitrateThresholdKbps) | 90 if (initial_bitrate_kbps < kQvgaBitrateThresholdKbps) |
86 init_num_pixels = kQvgaNumPixels; | 91 init_num_pixels = kQvgaNumPixels; |
87 while (width * height > init_num_pixels) { | 92 while (width * height > init_num_pixels) { |
88 ++downscale_shift_; | 93 ++downscale_shift_; |
89 width /= 2; | 94 width /= 2; |
90 height /= 2; | 95 height /= 2; |
91 } | 96 } |
92 } | 97 } |
93 UpdateTargetResolution(init_width, init_height); | 98 UpdateTargetResolution(init_width, init_height); |
94 ReportFramerate(fps); | 99 ReportFramerate(fps); |
95 } | 100 } |
96 | 101 |
102 void QualityScaler::Init(VideoCodecType codec_type, | |
103 int initial_bitrate_kbps, | |
104 int width, | |
105 int height, | |
106 int fps, | |
107 int highQpThreshold, | |
pbos-webrtc
2016/09/19 14:06:57
high_qp_threshold, same for low
| |
108 int lowQpThreshold) { | |
109 Init(codec_type, initial_bitrate_kbps, width, height, fps); | |
110 low_qp_threshold_ = highQpThreshold; | |
111 high_qp_threshold_ = lowQpThreshold; | |
112 } | |
113 | |
97 // Report framerate(fps) to estimate # of samples. | 114 // Report framerate(fps) to estimate # of samples. |
98 void QualityScaler::ReportFramerate(int framerate) { | 115 void QualityScaler::ReportFramerate(int framerate) { |
99 // Use a faster window for upscaling initially. | 116 // Use a faster window for upscaling initially. |
100 // This enables faster initial rampups without risking strong up-down | 117 // This enables faster initial rampups without risking strong up-down |
101 // behavior later. | 118 // behavior later. |
102 num_samples_upscale_ = framerate * (fast_rampup_ ? kMeasureSecondsFastUpscale | 119 num_samples_upscale_ = framerate * (fast_rampup_ ? kMeasureSecondsFastUpscale |
103 : kMeasureSecondsUpscale); | 120 : kMeasureSecondsUpscale); |
104 num_samples_downscale_ = framerate * kMeasureSecondsDownscale; | 121 num_samples_downscale_ = framerate * kMeasureSecondsDownscale; |
105 | 122 |
106 average_qp_ = | 123 average_qp_ = |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
194 target_res_ = Resolution{width, height}; | 211 target_res_ = Resolution{width, height}; |
195 } | 212 } |
196 | 213 |
197 void QualityScaler::ClearSamples() { | 214 void QualityScaler::ClearSamples() { |
198 framedrop_percent_.Reset(); | 215 framedrop_percent_.Reset(); |
199 average_qp_.Reset(); | 216 average_qp_.Reset(); |
200 } | 217 } |
201 | 218 |
202 | 219 |
203 } // namespace webrtc | 220 } // namespace webrtc |
OLD | NEW |