Chromium Code Reviews| 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 |