blob: 24dbff32a25fc7729c5a652be77fc9ec3f407b94 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/base/leaky_bucket.h"
namespace remoting {
LeakyBucket::LeakyBucket(int depth, int rate)
: depth_(depth),
rate_(rate),
current_level_(0),
level_updated_time_(base::TimeTicks::Now()) {}
LeakyBucket::~LeakyBucket() = default;
bool LeakyBucket::RefillOrSpill(int drops, base::TimeTicks now) {
UpdateLevel(now);
int new_level = current_level_ + drops;
if (depth_ >= 0 && new_level > depth_)
return false;
current_level_ = new_level;
return true;
}
base::TimeTicks LeakyBucket::GetEmptyTime() {
// To avoid unnecessary complexity in WebrtcFrameSchedulerSimple, we return
// a fairly large value (1 minute) here if the b/w estimate is 0 (which means
// that the video stream should be paused). This means that
// WebrtcFrameSchedulerSimple does not need to handle any overflow isssues
// caused by returning TimeDelta::Max().
base::TimeDelta time_to_empty =
(rate_ != 0) ? base::TimeDelta::FromMicroseconds(
base::TimeTicks::kMicrosecondsPerSecond *
current_level_ / rate_)
: base::TimeDelta::FromMinutes(1);
return level_updated_time_ + time_to_empty;
}
void LeakyBucket::UpdateRate(int new_rate, base::TimeTicks now) {
UpdateLevel(now);
rate_ = new_rate;
}
void LeakyBucket::UpdateLevel(base::TimeTicks now) {
int64_t drainage_amount = rate_ *
(now - level_updated_time_).InMicroseconds() /
base::TimeTicks::kMicrosecondsPerSecond;
if (current_level_ < drainage_amount) {
current_level_ = 0;
} else {
current_level_ -= drainage_amount;
}
level_updated_time_ = now;
}
} // namespace remoting