This source file includes following definitions.
- bitrate_
- OnAck
- OnNack
#include "media/cast/congestion_control/congestion_control.h"
#include "base/logging.h"
#include "media/cast/cast_config.h"
#include "media/cast/cast_defines.h"
namespace media {
namespace cast {
static const int64 kCongestionControlMinChangeIntervalMs = 10;
static const int64 kCongestionControlMaxChangeIntervalMs = 100;
static const int kCongestionControlMaxBitrateIncreasePerMillisecond = 1200;
static const int64 kMaxElapsedTimeMs = kCongestionControlMaxChangeIntervalMs;
CongestionControl::CongestionControl(base::TickClock* clock,
float congestion_control_back_off,
uint32 max_bitrate_configured,
uint32 min_bitrate_configured,
uint32 start_bitrate)
: clock_(clock),
congestion_control_back_off_(congestion_control_back_off),
max_bitrate_configured_(max_bitrate_configured),
min_bitrate_configured_(min_bitrate_configured),
bitrate_(start_bitrate) {
DCHECK_GT(congestion_control_back_off, 0.0f) << "Invalid config";
DCHECK_LT(congestion_control_back_off, 1.0f) << "Invalid config";
DCHECK_GE(max_bitrate_configured, min_bitrate_configured) << "Invalid config";
DCHECK_GE(max_bitrate_configured, start_bitrate) << "Invalid config";
DCHECK_GE(start_bitrate, min_bitrate_configured) << "Invalid config";
}
CongestionControl::~CongestionControl() {}
bool CongestionControl::OnAck(base::TimeDelta rtt, uint32* new_bitrate) {
base::TimeTicks now = clock_->NowTicks();
if (time_last_increase_.is_null()) {
time_last_increase_ = now;
time_last_decrease_ = now;
return false;
}
if (max_bitrate_configured_ == bitrate_)
return false;
rtt = std::max(rtt, base::TimeDelta::FromMilliseconds(1));
base::TimeDelta elapsed_time =
std::min(now - time_last_increase_,
base::TimeDelta::FromMilliseconds(kMaxElapsedTimeMs));
base::TimeDelta change_interval = std::max(
rtt,
base::TimeDelta::FromMilliseconds(kCongestionControlMinChangeIntervalMs));
change_interval = std::min(
change_interval,
base::TimeDelta::FromMilliseconds(kCongestionControlMaxChangeIntervalMs));
if (elapsed_time < change_interval)
return false;
time_last_increase_ = now;
uint32 bitrate_increase =
(1500 * 8 * elapsed_time.InMilliseconds()) / rtt.InMilliseconds();
uint32 max_bitrate_increase =
kCongestionControlMaxBitrateIncreasePerMillisecond *
elapsed_time.InMilliseconds();
bitrate_increase = std::min(max_bitrate_increase, bitrate_increase);
*new_bitrate = std::min(bitrate_increase + bitrate_, max_bitrate_configured_);
bitrate_ = *new_bitrate;
return true;
}
bool CongestionControl::OnNack(base::TimeDelta rtt, uint32* new_bitrate) {
base::TimeTicks now = clock_->NowTicks();
if (time_last_decrease_.is_null()) {
time_last_increase_ = now;
time_last_decrease_ = now;
return false;
}
base::TimeDelta elapsed_time =
std::min(now - time_last_decrease_,
base::TimeDelta::FromMilliseconds(kMaxElapsedTimeMs));
base::TimeDelta change_interval = std::max(
rtt,
base::TimeDelta::FromMilliseconds(kCongestionControlMinChangeIntervalMs));
change_interval = std::min(
change_interval,
base::TimeDelta::FromMilliseconds(kCongestionControlMaxChangeIntervalMs));
if (elapsed_time < change_interval)
return false;
time_last_decrease_ = now;
time_last_increase_ = now;
*new_bitrate =
std::max(static_cast<uint32>(bitrate_ * congestion_control_back_off_),
min_bitrate_configured_);
bitrate_ = *new_bitrate;
return true;
}
}
}