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

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: Fix GN build. 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..fad183ca16ab44682d56d28f75504e900b0e5fdc
--- /dev/null
+++ b/webrtc/modules/video_coding/bitrate_adjuster.cc
@@ -0,0 +1,132 @@
+/*
+ * 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/system_wrappers/include/clock.h"
+
+namespace webrtc {
+
+// Update bitrate at most once every second.
+const uint32_t BitrateAdjuster::kBitrateUpdateIntervalMs = 1000;
+
+// Update bitrate at most once every 30 frames.
+const uint32_t BitrateAdjuster::kBitrateUpdateFrameInterval = 30;
+
+// 5 percent of original.
+const uint32_t BitrateAdjuster::kBitrateTolerancePct = 5;
+
+BitrateAdjuster::BitrateAdjuster(Clock* clock,
+ BitrateAdjusterObserver* observer)
+ : clock_(clock),
+ observer_(observer),
+ bitrate_tracker_(1.5 * kBitrateUpdateIntervalMs, 8) {
+ 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_;
+}
+
+uint32_t BitrateAdjuster::GetEstimatedBitrate() {
+ rtc::CritScope cs(&crit_);
+ return bitrate_tracker_.Rate(clock_->TimeInMilliseconds());
+}
+
+uint32_t BitrateAdjuster::GetMinAdjustedBitrate() const {
+ rtc::CritScope cs(&crit_);
+ // Half of target bitrate.
+ return target_bitrate_kbit_ / 2;
+}
+
+uint32_t BitrateAdjuster::GetMaxAdjustedBitrate() const {
+ rtc::CritScope cs(&crit_);
+ // 95% of target bitrate. In practice we know that the VideoToolbox encoder
+ // on iOS overshoots regularly. Setting it to 95% seems to reduce
+ // oscillations.
+ return .95 * target_bitrate_kbit_;
+}
+
+void BitrateAdjuster::Update(size_t frame_size) {
+ rtc::CritScope cs(&crit_);
+ uint32_t current_time_ms = clock_->TimeInMilliseconds();
+ bitrate_tracker_.Update(frame_size, current_time_ms);
+ UpdateBitrate(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;
+ frames_since_last_update_ = 0;
+ bitrate_tracker_.Reset();
+}
+
+void BitrateAdjuster::UpdateBitrate(uint32_t current_time_ms) {
+ rtc::CritScope cs(&crit_);
+ uint32_t time_since_last_update_ms =
+ current_time_ms - last_bitrate_update_time_ms_;
+ // Don't attempt to update bitrate unless enough time and frames have passed.
+ ++frames_since_last_update_;
+ if (time_since_last_update_ms < kBitrateUpdateIntervalMs ||
+ frames_since_last_update_ < kBitrateUpdateFrameInterval) {
+ return;
+ }
+ float bitrate = bitrate_tracker_.Rate(current_time_ms);
+ float target_bitrate = target_bitrate_kbit_;
+ float error = target_bitrate - bitrate;
+
+ // 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 = GetMinAdjustedBitrate();
+ float max_bitrate = GetMaxAdjustedBitrate();
+ 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_VERBOSE) << "Adjusting encoder bitrate:"
+ << "\n target_bitrate:" << target_bitrate
+ << "\n actual_bitrate:" << bitrate
+ << "\n previous_bitrate:"
+ << (uint32_t)last_adjusted_bitrate
stefan-webrtc 2016/02/18 20:56:58 static_cast
tkchin_webrtc 2016/02/18 23:50:39 Done.
+ << "\n adjusted_bitrate:" << (uint32_t)adjusted_bitrate;
stefan-webrtc 2016/02/18 20:56:58 static_cast
tkchin_webrtc 2016/02/18 23:50:39 Done.
+ adjusted_bitrate_kbit_ = adjusted_bitrate;
+ observer_->OnBitrateAdjusted(adjusted_bitrate);
+ }
+ }
+ last_bitrate_update_time_ms_ = current_time_ms;
+ frames_since_last_update_ = 0;
+}
+
+} // namespace webrtc

Powered by Google App Engine
This is Rietveld 408576698