Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(385)

Unified Diff: webrtc/modules/video_coding/bitrate_adjuster.cc

Issue 1660963002: Bitrate controller for VideoToolbox encoder. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Remove unneeded call Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/modules/video_coding/bitrate_adjuster.cc
diff --git a/webrtc/modules/video_coding/bitrate_adjuster.cc b/webrtc/modules/video_coding/bitrate_adjuster.cc
new file mode 100644
index 0000000000000000000000000000000000000000..9f3d939288fb1af13013e0274706733d8b6727a3
--- /dev/null
+++ b/webrtc/modules/video_coding/bitrate_adjuster.cc
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/modules/video_coding/include/bitrate_adjuster.h"
+
+#include "webrtc/base/checks.h"
+#include "webrtc/base/logging.h"
+#include "webrtc/base/timeutils.h"
+
+namespace webrtc {
+
+// 2 seconds.
+const uint32_t BitrateAdjuster::kBitrateUpdateIntervalMs = 2000;
+
+// 5 percent of original.
+const uint32_t BitrateAdjuster::kBitrateTolerancePct = 5;
+
+BitrateAdjuster::BitrateAdjuster(BitrateAdjusterObserver* observer)
+ : observer_(observer), bitrate_tracker_(30 * 20) {
+ RTC_DCHECK(observer_);
+ Reset();
+}
+
+void BitrateAdjuster::SetTargetBitrate(uint32_t bitrate_kbit) {
+ rtc::CritScope cs(&crit_);
+ target_bitrate_kbit_ = bitrate_kbit;
+}
+
+uint32_t BitrateAdjuster::GetTargetBitrate() const {
+ rtc::CritScope cs(&crit_);
+ return target_bitrate_kbit_;
+}
+
+uint32_t BitrateAdjuster::GetAdjustedBitrate() const {
+ rtc::CritScope cs(&crit_);
+ return adjusted_bitrate_kbit_;
+}
+
+void BitrateAdjuster::Update(size_t frame_size) {
+ rtc::CritScope cs(&crit_);
+ uint32_t current_time_ms = rtc::Time();
+ UpdateBitrate(current_time_ms);
+ UpdateBitrateTracker(frame_size, current_time_ms);
+}
+
+// Only safe to call this after Update calls have stopped
+void BitrateAdjuster::Reset() {
+ rtc::CritScope cs(&crit_);
+ target_bitrate_kbit_ = 0;
+ adjusted_bitrate_kbit_ = 0;
+ last_bitrate_update_time_ms_ = 0;
+ last_update_time_ms_ = 0;
+ bitrate_tracker_.Reset();
+}
+
+void BitrateAdjuster::UpdateBitrate(uint32_t current_time_ms) {
+ rtc::CritScope cs(&crit_);
+ if (current_time_ms - last_bitrate_update_time_ms_ <
+ kBitrateUpdateIntervalMs) {
+ return;
+ }
+ 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.
+ // Wait for some samples before doing anything. Roughly 2s of samples
+ // at 30fps.
+ return;
+ }
+ float target_bitrate = target_bitrate_kbit_;
+
+ // Compute exponentially weighted average of bitrate samples.
+ // 0.02 means last 60 samples represent about 70% of weight.
+ float bitrate = bitrate_tracker_.ComputeWeightedMean(0.02);
+ 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!
+
+ // Adjust if we've overshot by any amount or if we've undershot too much.
+ if (bitrate > target_bitrate ||
+ error * 100 > kBitrateTolerancePct * target_bitrate) {
+ // Adjust the bitrate by a fraction of the error.
+ float adjustment = .5 * error;
+ float adjusted_bitrate = target_bitrate + adjustment;
+
+ // Clamp the adjustment to [0.5 * target, 0.95 * target].
+ float min_bitrate = .5 * target_bitrate;
+ float max_bitrate =
+ static_cast<float>((100 - kBitrateTolerancePct) * target_bitrate) /
+ 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
+ adjusted_bitrate = std::max(adjusted_bitrate, min_bitrate);
+ adjusted_bitrate = std::min(adjusted_bitrate, max_bitrate);
+
+ // Set the adjustment if it's not already set.
+ float last_adjusted_bitrate = adjusted_bitrate_kbit_;
+ if (adjusted_bitrate != last_adjusted_bitrate) {
+ LOG(LS_INFO) << "Adjusting encoder bitrate:"
+ << "\n target_bitrate:" << target_bitrate
+ << "\n actual_bitrate:" << bitrate
+ << "\n previous_bitrate:" << (uint32_t)last_adjusted_bitrate
+ << "\n adjusted_bitrate:" << (uint32_t)adjusted_bitrate;
+ adjusted_bitrate_kbit_ = adjusted_bitrate;
+ 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.
+ }
+ }
+ last_bitrate_update_time_ms_ = current_time_ms;
+}
+
+void BitrateAdjuster::UpdateBitrateTracker(size_t frame_size,
+ uint32_t current_time_ms) {
+ rtc::CritScope cs(&crit_);
+ if (current_time_ms > last_update_time_ms_) {
+ // Convert to kbit/s.
+ float bitrate_sample =
+ static_cast<float>(frame_size * 8) /
+ static_cast<float>(current_time_ms - last_update_time_ms_);
+ bitrate_tracker_.AddSample(bitrate_sample);
+ }
+ last_update_time_ms_ = current_time_ms;
+}
+
+} // namespace webrtc

Powered by Google App Engine
This is Rietveld 408576698