1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/cast/congestion_control/congestion_control.h"
7 #include "base/logging.h"
8 #include "media/cast/cast_config.h"
9 #include "media/cast/cast_defines.h"
14 static const int64 kCongestionControlMinChangeIntervalMs
= 10;
15 static const int64 kCongestionControlMaxChangeIntervalMs
= 100;
17 // At 10 ms RTT TCP Reno would ramp 1500 * 8 * 100 = 1200 Kbit/s.
18 // NACK is sent after a maximum of 10 ms.
19 static const int kCongestionControlMaxBitrateIncreasePerMillisecond
= 1200;
21 static const int64 kMaxElapsedTimeMs
= kCongestionControlMaxChangeIntervalMs
;
23 CongestionControl::CongestionControl(float congestion_control_back_off
,
24 uint32 max_bitrate_configured
,
25 uint32 min_bitrate_configured
,
27 : congestion_control_back_off_(congestion_control_back_off
),
28 max_bitrate_configured_(max_bitrate_configured
),
29 min_bitrate_configured_(min_bitrate_configured
),
30 bitrate_(start_bitrate
),
31 default_tick_clock_(new base::DefaultTickClock()),
32 clock_(default_tick_clock_
.get()) {
33 DCHECK_GT(congestion_control_back_off
, 0.0f
) << "Invalid config";
34 DCHECK_LT(congestion_control_back_off
, 1.0f
) << "Invalid config";
35 DCHECK_GE(max_bitrate_configured
, min_bitrate_configured
) << "Invalid config";
36 DCHECK_GE(max_bitrate_configured
, start_bitrate
) << "Invalid config";
37 DCHECK_GE(start_bitrate
, min_bitrate_configured
) << "Invalid config";
40 bool CongestionControl::OnAck(base::TimeDelta rtt
, uint32
* new_bitrate
) {
41 base::TimeTicks now
= clock_
->NowTicks();
44 if (time_last_increase_
.is_null()) {
45 time_last_increase_
= now
;
46 time_last_decrease_
= now
;
49 // Are we at the max bitrate?
50 if (max_bitrate_configured_
== bitrate_
) return false;
52 // Make sure RTT is never less than 1 ms.
53 rtt
= std::max(rtt
, base::TimeDelta::FromMilliseconds(1));
55 base::TimeDelta elapsed_time
= std::min(now
- time_last_increase_
,
56 base::TimeDelta::FromMilliseconds(kMaxElapsedTimeMs
));
57 base::TimeDelta change_interval
= std::max(rtt
,
58 base::TimeDelta::FromMilliseconds(kCongestionControlMinChangeIntervalMs
));
59 change_interval
= std::min(change_interval
,
60 base::TimeDelta::FromMilliseconds(kCongestionControlMaxChangeIntervalMs
));
62 // Have enough time have passed?
63 if (elapsed_time
< change_interval
) return false;
65 time_last_increase_
= now
;
67 // One packet per RTT multiplied by the elapsed time fraction.
68 // 1500 * 8 * (1000 / rtt_ms) * (elapsed_time_ms / 1000) =>
69 // 1500 * 8 * elapsed_time_ms / rtt_ms.
70 uint32 bitrate_increase
= (1500 * 8 * elapsed_time
.InMilliseconds()) /
72 uint32 max_bitrate_increase
=
73 kCongestionControlMaxBitrateIncreasePerMillisecond
*
74 elapsed_time
.InMilliseconds();
75 bitrate_increase
= std::min(max_bitrate_increase
, bitrate_increase
);
76 *new_bitrate
= std::min(bitrate_increase
+ bitrate_
, max_bitrate_configured_
);
77 bitrate_
= *new_bitrate
;
81 bool CongestionControl::OnNack(base::TimeDelta rtt
, uint32
* new_bitrate
) {
82 base::TimeTicks now
= clock_
->NowTicks();
85 if (time_last_decrease_
.is_null()) {
86 time_last_increase_
= now
;
87 time_last_decrease_
= now
;
90 base::TimeDelta elapsed_time
= std::min(now
- time_last_decrease_
,
91 base::TimeDelta::FromMilliseconds(kMaxElapsedTimeMs
));
92 base::TimeDelta change_interval
= std::max(rtt
,
93 base::TimeDelta::FromMilliseconds(kCongestionControlMinChangeIntervalMs
));
94 change_interval
= std::min(change_interval
,
95 base::TimeDelta::FromMilliseconds(kCongestionControlMaxChangeIntervalMs
));
97 // Have enough time have passed?
98 if (elapsed_time
< change_interval
) return false;
100 time_last_decrease_
= now
;
101 time_last_increase_
= now
;
103 *new_bitrate
= std::max(
104 static_cast<uint32
>(bitrate_
* congestion_control_back_off_
),
105 min_bitrate_configured_
);
107 bitrate_
= *new_bitrate
;