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/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 |