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/base/timeutils.h" | |
16 | |
17 namespace webrtc { | |
18 | |
19 // 2 seconds. | |
20 const uint32_t BitrateAdjuster::kBitrateUpdateIntervalMs = 2000; | |
21 | |
22 // 5 percent of original. | |
23 const uint32_t BitrateAdjuster::kBitrateTolerancePct = 5; | |
24 | |
25 BitrateAdjuster::BitrateAdjuster(BitrateAdjusterObserver* observer) | |
26 : observer_(observer), bitrate_tracker_(30 * 20) { | |
27 RTC_DCHECK(observer_); | |
28 Reset(); | |
29 } | |
30 | |
31 void BitrateAdjuster::SetTargetBitrate(uint32_t bitrate_kbit) { | |
32 rtc::CritScope cs(&crit_); | |
33 target_bitrate_kbit_ = bitrate_kbit; | |
34 } | |
35 | |
36 uint32_t BitrateAdjuster::GetTargetBitrate() const { | |
37 rtc::CritScope cs(&crit_); | |
38 return target_bitrate_kbit_; | |
39 } | |
40 | |
41 uint32_t BitrateAdjuster::GetAdjustedBitrate() const { | |
42 rtc::CritScope cs(&crit_); | |
43 return adjusted_bitrate_kbit_; | |
44 } | |
45 | |
46 void BitrateAdjuster::Update(size_t frame_size) { | |
47 rtc::CritScope cs(&crit_); | |
48 uint32_t current_time_ms = rtc::Time(); | |
49 UpdateBitrate(current_time_ms); | |
50 UpdateBitrateTracker(frame_size, current_time_ms); | |
51 } | |
52 | |
53 // Only safe to call this after Update calls have stopped | |
54 void BitrateAdjuster::Reset() { | |
55 rtc::CritScope cs(&crit_); | |
56 target_bitrate_kbit_ = 0; | |
57 adjusted_bitrate_kbit_ = 0; | |
58 last_bitrate_update_time_ms_ = 0; | |
59 last_update_time_ms_ = 0; | |
60 bitrate_tracker_.Reset(); | |
61 } | |
62 | |
63 void BitrateAdjuster::UpdateBitrate(uint32_t current_time_ms) { | |
64 rtc::CritScope cs(&crit_); | |
65 if (current_time_ms - last_bitrate_update_time_ms_ < | |
66 kBitrateUpdateIntervalMs) { | |
67 return; | |
68 } | |
69 if (bitrate_tracker_.count() < 60) { | |
sprang
2016/02/09 10:46:26
Please used a named constant for this, or derive f
tkchin_webrtc
2016/02/11 00:03:20
Done.
| |
70 // Wait for some samples before doing anything. Roughly 2s of samples | |
71 // at 30fps. | |
72 return; | |
73 } | |
74 float target_bitrate = target_bitrate_kbit_; | |
75 | |
76 // Compute exponentially weighted average of bitrate samples. | |
77 // 0.02 means last 60 samples represent about 70% of weight. | |
78 float bitrate = bitrate_tracker_.ComputeWeightedMean(0.02); | |
79 float error = target_bitrate - bitrate; | |
sprang
2016/02/09 10:46:26
Can we perhaps use webrtc::RateStatistics instead
tkchin_webrtc
2016/02/11 00:03:20
Sure, that seems like a good idea.
Weird to introd
sprang_webrtc
2016/02/15 08:51:32
That sounds great, thanks!
| |
80 | |
81 // Adjust if we've overshot by any amount or if we've undershot too much. | |
82 if (bitrate > target_bitrate || | |
83 error * 100 > kBitrateTolerancePct * target_bitrate) { | |
84 // Adjust the bitrate by a fraction of the error. | |
85 float adjustment = .5 * error; | |
86 float adjusted_bitrate = target_bitrate + adjustment; | |
87 | |
88 // Clamp the adjustment to [0.5 * target, 0.95 * target]. | |
89 float min_bitrate = .5 * target_bitrate; | |
90 float max_bitrate = | |
91 static_cast<float>((100 - kBitrateTolerancePct) * target_bitrate) / | |
92 100.; | |
sprang
2016/02/09 10:46:26
Why do we need to clamp it to below target_bitrate
tkchin_webrtc
2016/02/11 00:03:20
It seemed to reduce oscillations. We know that the
sprang_webrtc
2016/02/15 08:51:32
Fair enough, perhaps a comment to that effect woul
| |
93 adjusted_bitrate = std::max(adjusted_bitrate, min_bitrate); | |
94 adjusted_bitrate = std::min(adjusted_bitrate, max_bitrate); | |
95 | |
96 // Set the adjustment if it's not already set. | |
97 float last_adjusted_bitrate = adjusted_bitrate_kbit_; | |
98 if (adjusted_bitrate != last_adjusted_bitrate) { | |
99 LOG(LS_INFO) << "Adjusting encoder bitrate:" | |
100 << "\n target_bitrate:" << target_bitrate | |
101 << "\n actual_bitrate:" << bitrate | |
102 << "\n previous_bitrate:" << (uint32_t)last_adjusted_bitrate | |
103 << "\n adjusted_bitrate:" << (uint32_t)adjusted_bitrate; | |
104 adjusted_bitrate_kbit_ = adjusted_bitrate; | |
105 observer_->OnBitrateAdjusted(adjusted_bitrate); | |
sprang
2016/02/09 10:46:26
Perhaps we should have a limit on how often this w
tkchin_webrtc
2016/02/11 00:03:20
The update only happens once every t seconds, so i
sprang_webrtc
2016/02/15 08:51:32
Ah, right. I'm fine with either then.
| |
106 } | |
107 } | |
108 last_bitrate_update_time_ms_ = current_time_ms; | |
109 } | |
110 | |
111 void BitrateAdjuster::UpdateBitrateTracker(size_t frame_size, | |
112 uint32_t current_time_ms) { | |
113 rtc::CritScope cs(&crit_); | |
114 if (current_time_ms > last_update_time_ms_) { | |
115 // Convert to kbit/s. | |
116 float bitrate_sample = | |
117 static_cast<float>(frame_size * 8) / | |
118 static_cast<float>(current_time_ms - last_update_time_ms_); | |
119 bitrate_tracker_.AddSample(bitrate_sample); | |
120 } | |
121 last_update_time_ms_ = current_time_ms; | |
122 } | |
123 | |
124 } // namespace webrtc | |
OLD | NEW |