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 = 24; |
| 46 static const int kHighH264QpThreshold = 37; |
| 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 |
| 59 void QualityScaler::Init(VideoCodecType codec_type, |
| 60 int initial_bitrate_kbps, |
| 61 int width, |
| 62 int height, |
| 63 int fps) { |
| 64 int low = -1, high = -1; |
| 65 switch (codec_type) { |
| 66 case kVideoCodecH264: |
| 67 low = kLowH264QpThreshold; |
| 68 high = kHighH264QpThreshold; |
| 69 break; |
| 70 case kVideoCodecVP8: |
| 71 low = kLowVp8QpThreshold; |
| 72 high = kHighVp8QpThreshold; |
| 73 break; |
| 74 default: |
| 75 RTC_NOTREACHED() << "Invalid codec type for QualityScaler."; |
| 76 } |
| 77 Init(low, high, initial_bitrate_kbps, width, height, fps); |
| 78 } |
| 79 |
64 void QualityScaler::Init(int low_qp_threshold, | 80 void QualityScaler::Init(int low_qp_threshold, |
65 int high_qp_threshold, | 81 int high_qp_threshold, |
66 int initial_bitrate_kbps, | 82 int initial_bitrate_kbps, |
67 int width, | 83 int width, |
68 int height, | 84 int height, |
69 int fps) { | 85 int fps) { |
| 86 ClearSamples(); |
70 low_qp_threshold_ = low_qp_threshold; | 87 low_qp_threshold_ = low_qp_threshold; |
71 high_qp_threshold_ = high_qp_threshold; | 88 high_qp_threshold_ = high_qp_threshold; |
72 downscale_shift_ = 0; | 89 downscale_shift_ = 0; |
73 | |
74 fast_rampup_ = true; | 90 fast_rampup_ = true; |
75 | |
76 ClearSamples(); | |
77 ReportFramerate(fps); | 91 ReportFramerate(fps); |
78 | 92 |
79 const int init_width = width; | 93 const int init_width = width; |
80 const int init_height = height; | 94 const int init_height = height; |
81 if (initial_bitrate_kbps > 0) { | 95 if (initial_bitrate_kbps > 0) { |
82 int init_num_pixels = width * height; | 96 int init_num_pixels = width * height; |
83 if (initial_bitrate_kbps < kVgaBitrateThresholdKbps) | 97 if (initial_bitrate_kbps < kVgaBitrateThresholdKbps) |
84 init_num_pixels = kVgaNumPixels; | 98 init_num_pixels = kVgaNumPixels; |
85 if (initial_bitrate_kbps < kQvgaBitrateThresholdKbps) | 99 if (initial_bitrate_kbps < kQvgaBitrateThresholdKbps) |
86 init_num_pixels = kQvgaNumPixels; | 100 init_num_pixels = kQvgaNumPixels; |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 target_res_ = Resolution{width, height}; | 208 target_res_ = Resolution{width, height}; |
195 } | 209 } |
196 | 210 |
197 void QualityScaler::ClearSamples() { | 211 void QualityScaler::ClearSamples() { |
198 framedrop_percent_.Reset(); | 212 framedrop_percent_.Reset(); |
199 average_qp_.Reset(); | 213 average_qp_.Reset(); |
200 } | 214 } |
201 | 215 |
202 | 216 |
203 } // namespace webrtc | 217 } // namespace webrtc |
OLD | NEW |