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

Unified Diff: webrtc/call/bitrate_allocator.cc

Issue 2117493002: Auto pause video streams based on encoder target bitrate. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 6 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/call/bitrate_allocator.cc
diff --git a/webrtc/call/bitrate_allocator.cc b/webrtc/call/bitrate_allocator.cc
index e82123a8b09c9069342aa4aaa62e0793d3da5190..cc29f7ed76817cdc16f842d9767731b84a92e299 100644
--- a/webrtc/call/bitrate_allocator.cc
+++ b/webrtc/call/bitrate_allocator.cc
@@ -15,7 +15,10 @@
#include <utility>
#include "webrtc/base/checks.h"
+#include "webrtc/base/logging.h"
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
+#include "webrtc/system_wrappers/include/clock.h"
+#include "webrtc/system_wrappers/include/metrics.h"
namespace webrtc {
@@ -28,13 +31,23 @@ const int kDefaultBitrateBps = 300000;
const double kToggleFactor = 0.1;
const uint32_t kMinToggleBitrateBps = 20000;
+const int64_t kBweLogIntervalMs = 5000;
+
BitrateAllocator::BitrateAllocator(LimitObserver* limit_observer)
: limit_observer_(limit_observer),
bitrate_observer_configs_(),
last_bitrate_bps_(kDefaultBitrateBps),
last_non_zero_bitrate_bps_(kDefaultBitrateBps),
last_fraction_loss_(0),
- last_rtt_(0) {}
+ last_rtt_(0),
+ num_pause_events_(0),
+ clock_(Clock::GetRealTimeClock()),
+ last_bwe_log_time_(0) {}
+
+BitrateAllocator::~BitrateAllocator() {
+ RTC_LOGGED_HISTOGRAM_COUNTS_100("WebRTC.Call.NumberOfPauseEvents",
+ num_pause_events_);
stefan-webrtc 2016/06/30 16:17:38 Good to have! Remember to add it to the uma config
mflodman 2016/07/01 09:40:15 Thanks for the reminder, I'll make sure this happe
+}
void BitrateAllocator::OnNetworkChanged(uint32_t target_bitrate_bps,
uint8_t fraction_loss,
@@ -46,11 +59,45 @@ void BitrateAllocator::OnNetworkChanged(uint32_t target_bitrate_bps,
last_fraction_loss_ = fraction_loss;
last_rtt_ = rtt;
+ // Periodically log the incoming BWE.
+ int64_t now = clock_->TimeInMilliseconds();
+ if (now > last_bwe_log_time_ + kBweLogIntervalMs) {
+ LOG(LS_INFO) << "Current BWE " << target_bitrate_bps;
+ last_bwe_log_time_ = now;
+ }
+
ObserverAllocation allocation = AllocateBitrates(target_bitrate_bps);
- for (const auto& kv : allocation) {
- kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_);
+
+ for (auto& config : bitrate_observer_configs_) {
+ uint32_t allocated_bitrate = allocation[config.observer];
+ uint32_t protection_bitrate = config.observer->OnBitrateUpdated(
+ allocated_bitrate, last_fraction_loss_, last_rtt_);
+
+ if (allocated_bitrate == 0 && config.allocated_bitrate_bps > 0) {
+ if (target_bitrate_bps > 0)
+ ++num_pause_events_;
+ uint32_t predicted_protection =
stefan-webrtc 2016/06/30 16:17:38 _bps Add a comment describing that this assumes t
mflodman 2016/07/01 09:40:15 Done.
+ (1.0 - config.media_ratio) * config.min_bitrate_bps;
+ LOG(LS_INFO) << "Pausing observer " << config.observer
+ << " with configured min bitrate " << config.min_bitrate_bps
+ << " and current estimate of " << target_bitrate_bps
stefan-webrtc 2016/06/30 16:17:38 Should you log the allocation here too?
mflodman 2016/07/01 09:40:15 Good point, added.
stefan-webrtc 2016/07/01 10:42:49 Can't see that it was added?
mflodman 2016/07/01 10:52:28 Sorry, bad reply from me. The allocation will be 0
+ << " and protection bitrate " << predicted_protection;
+ } else if (allocated_bitrate > 0 && config.allocated_bitrate_bps == 0) {
+ if (target_bitrate_bps > 0)
+ ++num_pause_events_;
+ LOG(LS_INFO) << "Resuming observer " << config.observer
+ << " with configured min bitrate " << config.min_bitrate_bps
+ << " and current allocation " << allocated_bitrate
+ << " and protection bitrate " << protection_bitrate;
+ }
+
+ // Only update the media ratio if the observer got an allocation.
+ if (allocated_bitrate > 0) {
+ config.media_ratio = (allocated_bitrate - protection_bitrate) /
stefan-webrtc 2016/06/30 16:17:38 Use a helper variable media_bitrate = allocated_bi
mflodman 2016/07/01 09:40:15 Done.
+ static_cast<double>(allocated_bitrate);
+ }
+ config.allocated_bitrate_bps = allocated_bitrate;
}
- last_allocation_ = allocation;
}
void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer,
@@ -77,8 +124,12 @@ void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer,
if (last_bitrate_bps_ > 0) {
// Calculate a new allocation and update all observers.
allocation = AllocateBitrates(last_bitrate_bps_);
- for (const auto& kv : allocation)
- kv.first->OnBitrateUpdated(kv.second, last_fraction_loss_, last_rtt_);
+ for (auto& config : bitrate_observer_configs_) {
+ uint32_t allocated_bitrate = allocation[config.observer];
+ config.observer->OnBitrateUpdated(
+ allocated_bitrate, last_fraction_loss_, last_rtt_);
+ config.allocated_bitrate_bps = allocated_bitrate;
stefan-webrtc 2016/06/30 16:17:38 Is there no need to update the media ratio here? I
mflodman 2016/07/01 09:40:15 That is a good question and I assumed it would be
stefan-webrtc 2016/07/01 10:42:49 Thanks. Better to do it and avoid others asking th
+ }
} else {
// Currently, an encoder is not allowed to produce frames.
// But we still have to return the initial config bitrate + let the
@@ -87,8 +138,6 @@ void BitrateAllocator::AddObserver(BitrateAllocatorObserver* observer,
observer->OnBitrateUpdated(0, last_fraction_loss_, last_rtt_);
}
UpdateAllocationLimits();
-
- last_allocation_ = allocation;
}
void BitrateAllocator::UpdateAllocationLimits() {
@@ -122,17 +171,22 @@ void BitrateAllocator::RemoveObserver(BitrateAllocatorObserver* observer) {
int BitrateAllocator::GetStartBitrate(BitrateAllocatorObserver* observer) {
rtc::CritScope lock(&crit_sect_);
- const auto& it = last_allocation_.find(observer);
- if (it != last_allocation_.end())
- return it->second;
-
- // This is a new observer that has not yet been started. Assume that if it is
- // added, all observers would split the available bitrate evenly.
- return last_non_zero_bitrate_bps_ /
- static_cast<int>((bitrate_observer_configs_.size() + 1));
+ const auto& it = FindObserverConfig(observer);
+ if (it == bitrate_observer_configs_.end()) {
+ // This observer hasn't been added yet, just give it its fair share.
stefan-webrtc 2016/06/30 16:17:38 Not clear to me why this can happen? Is it correct
mflodman 2016/07/01 09:40:15 AS of now it is, the encoder is configured before
stefan-webrtc 2016/07/01 10:42:49 Acknowledged.
+ return last_non_zero_bitrate_bps_ /
+ static_cast<int>((bitrate_observer_configs_.size() + 1));
+ } else if (it->allocated_bitrate_bps == -1) {
+ // This observer hasn't received an allocation yet, so do the same.
+ return last_non_zero_bitrate_bps_ /
+ static_cast<int>(bitrate_observer_configs_.size());
+ } else {
+ // This observer already has an allocation.
+ return it->allocated_bitrate_bps;
+ }
}
-BitrateAllocator::ObserverConfigList::iterator
+BitrateAllocator::ObserverConfigs::iterator
BitrateAllocator::FindObserverConfig(
const BitrateAllocatorObserver* observer) {
for (auto it = bitrate_observer_configs_.begin();
@@ -202,9 +256,10 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::LowRateAllocation(
LastAllocatedBitrate(observer_config) == 0)
continue;
- if (remaining_bitrate >= observer_config.min_bitrate_bps) {
- allocation[observer_config.observer] = observer_config.min_bitrate_bps;
- remaining_bitrate -= observer_config.min_bitrate_bps;
+ uint32_t required_bitrate = MinBitrateWithHysteresis(observer_config);
+ if (remaining_bitrate >= required_bitrate) {
+ allocation[observer_config.observer] = required_bitrate;
+ remaining_bitrate -= required_bitrate;
}
}
}
@@ -263,14 +318,11 @@ BitrateAllocator::ObserverAllocation BitrateAllocator::MaxRateAllocation(
uint32_t BitrateAllocator::LastAllocatedBitrate(
const ObserverConfig& observer_config) {
- const auto& it = last_allocation_.find(observer_config.observer);
- if (it != last_allocation_.end())
- return it->second;
-
// Return the configured minimum bitrate for newly added observers, to avoid
// requiring an extra high bitrate for the observer to get an allocated
// bitrate.
- return observer_config.min_bitrate_bps;
+ return observer_config.allocated_bitrate_bps == -1 ?
+ observer_config.min_bitrate_bps : observer_config.allocated_bitrate_bps;
}
uint32_t BitrateAllocator::MinBitrateWithHysteresis(
@@ -280,6 +332,15 @@ uint32_t BitrateAllocator::MinBitrateWithHysteresis(
min_bitrate += std::max(static_cast<uint32_t>(kToggleFactor * min_bitrate),
kMinToggleBitrateBps);
}
+ // Account for protection bitrate used by this observer in the previous
+ // allocation.
+ // Note: the ratio will only be updated when the stream is active, meaning a
+ // paused stream won't get any ratio updates. This might lead to waiting a bit
+ // longer than necessary if the network condition improves, but this is to
+ // avoid too much toggling.
stefan-webrtc 2016/06/30 16:17:38 I wonder if this should be moved up to where the r
mflodman 2016/07/01 09:40:15 As of now I prefer it this way to have it separate
stefan-webrtc 2016/07/01 10:42:49 Acknowledged.
+ if (observer_config.media_ratio > 0.0 && observer_config.media_ratio < 1.0)
+ min_bitrate += min_bitrate * (1.0 - observer_config.media_ratio);
+
return min_bitrate;
}

Powered by Google App Engine
This is Rietveld 408576698