OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2016 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/include/bitrate_adjuster.h" | |
12 | |
13 #include "webrtc/base/checks.h" | |
14 #include "webrtc/base/logging.h" | |
15 #include "webrtc/system_wrappers/include/clock.h" | |
16 | |
17 namespace webrtc { | |
18 | |
19 // Update bitrate at most once every second. | |
20 const uint32_t BitrateAdjuster::kBitrateUpdateIntervalMs = 1000; | |
21 | |
22 // Update bitrate at most once every 30 frames. | |
23 const uint32_t BitrateAdjuster::kBitrateUpdateFrameInterval = 30; | |
24 | |
25 // 5 percent of original. | |
26 const uint32_t BitrateAdjuster::kBitrateTolerancePct = 5; | |
27 | |
28 BitrateAdjuster::BitrateAdjuster(Clock* clock) | |
29 : clock_(clock), | |
30 bitrate_tracker_(1.5 * kBitrateUpdateIntervalMs, 8) { | |
31 Reset(); | |
32 } | |
33 | |
34 void BitrateAdjuster::SetTargetBitrate(uint32_t bitrate_kbit) { | |
35 rtc::CritScope cs(&crit_); | |
36 target_bitrate_kbit_ = bitrate_kbit; | |
37 // If we haven't had time to determine what adjustment is required yet then | |
38 // just use the target. | |
39 adjusted_bitrate_kbit_ = target_bitrate_kbit_; | |
40 } | |
41 | |
42 uint32_t BitrateAdjuster::GetTargetBitrate() const { | |
43 rtc::CritScope cs(&crit_); | |
44 return target_bitrate_kbit_; | |
45 } | |
46 | |
47 uint32_t BitrateAdjuster::GetAdjustedBitrate() const { | |
48 rtc::CritScope cs(&crit_); | |
49 return adjusted_bitrate_kbit_; | |
50 } | |
51 | |
52 uint32_t BitrateAdjuster::GetEstimatedBitrate() { | |
53 rtc::CritScope cs(&crit_); | |
54 return bitrate_tracker_.Rate(clock_->TimeInMilliseconds()); | |
55 } | |
56 | |
57 uint32_t BitrateAdjuster::GetMinAdjustedBitrate() const { | |
58 rtc::CritScope cs(&crit_); | |
59 // Half of target bitrate. | |
60 return target_bitrate_kbit_ / 2; | |
61 } | |
62 | |
63 uint32_t BitrateAdjuster::GetMaxAdjustedBitrate() const { | |
64 rtc::CritScope cs(&crit_); | |
65 // 95% of target bitrate. In practice we know that the VideoToolbox encoder | |
66 // on iOS overshoots regularly. Setting it to 95% seems to reduce | |
67 // oscillations. | |
68 return .95 * target_bitrate_kbit_; | |
69 } | |
70 | |
71 void BitrateAdjuster::Update(size_t frame_size) { | |
72 rtc::CritScope cs(&crit_); | |
73 uint32_t current_time_ms = clock_->TimeInMilliseconds(); | |
74 bitrate_tracker_.Update(frame_size, current_time_ms); | |
75 UpdateBitrate(current_time_ms); | |
76 } | |
77 | |
78 // Only safe to call this after Update calls have stopped | |
79 void BitrateAdjuster::Reset() { | |
80 rtc::CritScope cs(&crit_); | |
81 target_bitrate_kbit_ = 0; | |
pbos-webrtc
2016/02/19 11:26:39
Can this whole thing operate on bps_ instead?
tkchin_webrtc
2016/02/19 23:30:05
Done.
| |
82 adjusted_bitrate_kbit_ = 0; | |
83 last_bitrate_update_time_ms_ = 0; | |
84 frames_since_last_update_ = 0; | |
85 bitrate_tracker_.Reset(); | |
86 } | |
87 | |
88 void BitrateAdjuster::UpdateBitrate(uint32_t current_time_ms) { | |
89 rtc::CritScope cs(&crit_); | |
90 uint32_t time_since_last_update_ms = | |
91 current_time_ms - last_bitrate_update_time_ms_; | |
92 // Don't attempt to update bitrate unless enough time and frames have passed. | |
93 ++frames_since_last_update_; | |
94 if (time_since_last_update_ms < kBitrateUpdateIntervalMs || | |
95 frames_since_last_update_ < kBitrateUpdateFrameInterval) { | |
96 return; | |
97 } | |
98 float bitrate = bitrate_tracker_.Rate(current_time_ms); | |
99 float target_bitrate = target_bitrate_kbit_; | |
100 float error = target_bitrate - bitrate; | |
101 | |
102 // Adjust if we've overshot by any amount or if we've undershot too much. | |
103 if (bitrate > target_bitrate || | |
104 error * 100 > kBitrateTolerancePct * target_bitrate) { | |
105 // Adjust the bitrate by a fraction of the error. | |
106 float adjustment = .5 * error; | |
107 float adjusted_bitrate = target_bitrate + adjustment; | |
108 | |
109 // Clamp the adjustment to [0.5 * target, 0.95 * target]. | |
110 float min_bitrate = GetMinAdjustedBitrate(); | |
111 float max_bitrate = GetMaxAdjustedBitrate(); | |
112 adjusted_bitrate = std::max(adjusted_bitrate, min_bitrate); | |
pbos-webrtc
2016/02/19 11:26:39
units on all of these (_bps preferred)
tkchin_webrtc
2016/02/19 23:30:05
Done.
| |
113 adjusted_bitrate = std::min(adjusted_bitrate, max_bitrate); | |
114 | |
115 // Set the adjustment if it's not already set. | |
116 float last_adjusted_bitrate = adjusted_bitrate_kbit_; | |
117 if (adjusted_bitrate != last_adjusted_bitrate) { | |
118 LOG(LS_VERBOSE) << "Adjusting encoder bitrate:" | |
119 << "\n target_bitrate:" << target_bitrate | |
120 << "\n actual_bitrate:" << bitrate | |
121 << "\n last_adjusted_bitrate:" | |
122 << static_cast<uint32_t>(last_adjusted_bitrate) | |
123 << "\n adjusted_bitrate:" | |
124 << static_cast<uint32_t>(adjusted_bitrate); | |
125 adjusted_bitrate_kbit_ = adjusted_bitrate; | |
126 } | |
127 } | |
128 last_bitrate_update_time_ms_ = current_time_ms; | |
129 frames_since_last_update_ = 0; | |
130 } | |
131 | |
132 } // namespace webrtc | |
OLD | NEW |