Index: media/cast/sender/congestion_control.cc |
diff --git a/media/cast/sender/congestion_control.cc b/media/cast/sender/congestion_control.cc |
index 9efe50adbf823f8d6c98d2a56599a8d8dbc78ffb..30e3be7d6e8245503a1c98d137aa33605dc4cf08 100644 |
--- a/media/cast/sender/congestion_control.cc |
+++ b/media/cast/sender/congestion_control.cc |
@@ -22,6 +22,117 @@ |
namespace media { |
namespace cast { |
+class AdaptiveCongestionControl : public CongestionControl { |
+ public: |
+ AdaptiveCongestionControl(base::TickClock* clock, |
+ uint32 max_bitrate_configured, |
+ uint32 min_bitrate_configured, |
+ size_t max_unacked_frames); |
+ |
+ virtual ~AdaptiveCongestionControl() OVERRIDE; |
+ |
+ virtual void UpdateRtt(base::TimeDelta rtt) OVERRIDE; |
+ |
+ // Called when an encoded frame is sent to the transport. |
+ virtual void SendFrameToTransport(uint32 frame_id, |
+ size_t frame_size, |
+ base::TimeTicks when) OVERRIDE; |
+ |
+ // Called when we receive an ACK for a frame. |
+ virtual void AckFrame(uint32 frame_id, base::TimeTicks when) OVERRIDE; |
+ |
+ // Returns the bitrate we should use for the next frame. |
+ virtual uint32 GetBitrate(base::TimeTicks playout_time, |
+ base::TimeDelta playout_delay) OVERRIDE; |
+ |
+ private: |
+ struct FrameStats { |
+ FrameStats(); |
+ // Time this frame was sent to the transport. |
+ base::TimeTicks sent_time; |
+ // Time this frame was acked. |
+ base::TimeTicks ack_time; |
+ // Size of encoded frame in bits. |
+ size_t frame_size; |
+ }; |
+ |
+ // Calculate how much "dead air" (idle time) there is between two frames. |
+ static base::TimeDelta DeadTime(const FrameStats& a, const FrameStats& b); |
+ // Get the FrameStats for a given |frame_id|. |
+ // Note: Older FrameStats will be removed automatically. |
+ FrameStats* GetFrameStats(uint32 frame_id); |
+ // Calculate a safe bitrate. This is based on how much we've been |
+ // sending in the past. |
+ double CalculateSafeBitrate(); |
+ |
+ // For a given frame, calculate when it might be acked. |
+ // (Or return the time it was acked, if it was.) |
+ base::TimeTicks EstimatedAckTime(uint32 frame_id, double bitrate); |
+ // Calculate when we start sending the data for a given frame. |
+ // This is done by calculating when we were done sending the previous |
+ // frame, but obviously can't be less than |sent_time| (if known). |
+ base::TimeTicks EstimatedSendingTime(uint32 frame_id, double bitrate); |
+ |
+ base::TickClock* const clock_; // Not owned by this class. |
+ const uint32 max_bitrate_configured_; |
+ const uint32 min_bitrate_configured_; |
+ std::deque<FrameStats> frame_stats_; |
+ uint32 last_frame_stats_; |
+ uint32 last_acked_frame_; |
+ uint32 last_encoded_frame_; |
+ base::TimeDelta rtt_; |
+ size_t history_size_; |
+ size_t acked_bits_in_history_; |
+ base::TimeDelta dead_time_in_history_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(AdaptiveCongestionControl); |
+}; |
+ |
+class FixedCongestionControl : public CongestionControl { |
+ public: |
+ FixedCongestionControl(uint32 bitrate) : bitrate_(bitrate) {} |
+ virtual ~FixedCongestionControl() OVERRIDE {} |
+ |
+ virtual void UpdateRtt(base::TimeDelta rtt) OVERRIDE { |
+ } |
+ |
+ // Called when an encoded frame is sent to the transport. |
+ virtual void SendFrameToTransport(uint32 frame_id, |
+ size_t frame_size, |
+ base::TimeTicks when) OVERRIDE { |
+ } |
+ |
+ // Called when we receive an ACK for a frame. |
+ virtual void AckFrame(uint32 frame_id, base::TimeTicks when) OVERRIDE { |
+ } |
+ |
+ // Returns the bitrate we should use for the next frame. |
+ virtual uint32 GetBitrate(base::TimeTicks playout_time, |
+ base::TimeDelta playout_delay) OVERRIDE { |
+ return bitrate_; |
+ } |
+ |
+ private: |
+ uint32 bitrate_; |
+ DISALLOW_COPY_AND_ASSIGN(FixedCongestionControl); |
+}; |
+ |
+ |
+CongestionControl* NewAdaptiveCongestionControl( |
+ base::TickClock* clock, |
+ uint32 max_bitrate_configured, |
+ uint32 min_bitrate_configured, |
+ size_t max_unacked_frames) { |
+ return new AdaptiveCongestionControl(clock, |
+ max_bitrate_configured, |
+ min_bitrate_configured, |
+ max_unacked_frames); |
+} |
+ |
+CongestionControl* NewFixedCongestionControl(uint32 bitrate) { |
+ return new FixedCongestionControl(bitrate); |
+} |
+ |
// This means that we *try* to keep our buffer 90% empty. |
// If it is less full, we increase the bandwidth, if it is more |
// we decrease the bandwidth. Making this smaller makes the |
@@ -32,13 +143,14 @@ static const double kTargetEmptyBufferFraction = 0.9; |
// congestion control adapt slower. |
static const size_t kHistorySize = 100; |
-CongestionControl::FrameStats::FrameStats() : frame_size(0) { |
+AdaptiveCongestionControl::FrameStats::FrameStats() : frame_size(0) { |
} |
-CongestionControl::CongestionControl(base::TickClock* clock, |
- uint32 max_bitrate_configured, |
- uint32 min_bitrate_configured, |
- size_t max_unacked_frames) |
+AdaptiveCongestionControl::AdaptiveCongestionControl( |
+ base::TickClock* clock, |
+ uint32 max_bitrate_configured, |
+ uint32 min_bitrate_configured, |
+ size_t max_unacked_frames) |
: clock_(clock), |
max_bitrate_configured_(max_bitrate_configured), |
min_bitrate_configured_(min_bitrate_configured), |
@@ -57,14 +169,15 @@ CongestionControl::CongestionControl(base::TickClock* clock, |
} |
CongestionControl::~CongestionControl() {} |
+AdaptiveCongestionControl::~AdaptiveCongestionControl() {} |
-void CongestionControl::UpdateRtt(base::TimeDelta rtt) { |
+void AdaptiveCongestionControl::UpdateRtt(base::TimeDelta rtt) { |
rtt_ = (7 * rtt_ + rtt) / 8; |
} |
// Calculate how much "dead air" there is between two frames. |
-base::TimeDelta CongestionControl::DeadTime(const FrameStats& a, |
- const FrameStats& b) { |
+base::TimeDelta AdaptiveCongestionControl::DeadTime(const FrameStats& a, |
+ const FrameStats& b) { |
if (b.sent_time > a.ack_time) { |
return b.sent_time - a.ack_time; |
} else { |
@@ -72,7 +185,7 @@ base::TimeDelta CongestionControl::DeadTime(const FrameStats& a, |
} |
} |
-double CongestionControl::CalculateSafeBitrate() { |
+double AdaptiveCongestionControl::CalculateSafeBitrate() { |
double transmit_time = |
(GetFrameStats(last_acked_frame_)->ack_time - |
frame_stats_.front().sent_time - dead_time_in_history_).InSecondsF(); |
@@ -83,8 +196,8 @@ double CongestionControl::CalculateSafeBitrate() { |
return acked_bits_in_history_ / std::max(transmit_time, 1E-3); |
} |
-CongestionControl::FrameStats* CongestionControl::GetFrameStats( |
- uint32 frame_id) { |
+AdaptiveCongestionControl::FrameStats* |
+AdaptiveCongestionControl::GetFrameStats(uint32 frame_id) { |
int32 offset = static_cast<int32>(frame_id - last_frame_stats_); |
DCHECK_LT(offset, static_cast<int32>(kHistorySize)); |
if (offset > 0) { |
@@ -109,7 +222,8 @@ CongestionControl::FrameStats* CongestionControl::GetFrameStats( |
return &frame_stats_[offset]; |
} |
-void CongestionControl::AckFrame(uint32 frame_id, base::TimeTicks when) { |
+void AdaptiveCongestionControl::AckFrame(uint32 frame_id, |
+ base::TimeTicks when) { |
FrameStats* frame_stats = GetFrameStats(last_acked_frame_); |
while (IsNewerFrameId(frame_id, last_acked_frame_)) { |
FrameStats* last_frame_stats = frame_stats; |
@@ -129,9 +243,9 @@ void CongestionControl::AckFrame(uint32 frame_id, base::TimeTicks when) { |
} |
} |
-void CongestionControl::SendFrameToTransport(uint32 frame_id, |
- size_t frame_size, |
- base::TimeTicks when) { |
+void AdaptiveCongestionControl::SendFrameToTransport(uint32 frame_id, |
+ size_t frame_size, |
+ base::TimeTicks when) { |
last_encoded_frame_ = frame_id; |
FrameStats* frame_stats = GetFrameStats(frame_id); |
DCHECK(frame_stats); |
@@ -139,8 +253,8 @@ void CongestionControl::SendFrameToTransport(uint32 frame_id, |
frame_stats->sent_time = when; |
} |
-base::TimeTicks CongestionControl::EstimatedAckTime(uint32 frame_id, |
- double bitrate) { |
+base::TimeTicks AdaptiveCongestionControl::EstimatedAckTime(uint32 frame_id, |
+ double bitrate) { |
FrameStats* frame_stats = GetFrameStats(frame_id); |
DCHECK(frame_stats); |
if (frame_stats->ack_time.is_null()) { |
@@ -164,8 +278,9 @@ base::TimeTicks CongestionControl::EstimatedAckTime(uint32 frame_id, |
} |
} |
-base::TimeTicks CongestionControl::EstimatedSendingTime(uint32 frame_id, |
- double bitrate) { |
+base::TimeTicks AdaptiveCongestionControl::EstimatedSendingTime( |
+ uint32 frame_id, |
+ double bitrate) { |
FrameStats* frame_stats = GetFrameStats(frame_id); |
DCHECK(frame_stats); |
base::TimeTicks ret = EstimatedAckTime(frame_id - 1, bitrate) - rtt_; |
@@ -177,8 +292,8 @@ base::TimeTicks CongestionControl::EstimatedSendingTime(uint32 frame_id, |
} |
} |
-uint32 CongestionControl::GetBitrate(base::TimeTicks playout_time, |
- base::TimeDelta playout_delay) { |
+uint32 AdaptiveCongestionControl::GetBitrate(base::TimeTicks playout_time, |
+ base::TimeDelta playout_delay) { |
double safe_bitrate = CalculateSafeBitrate(); |
// Estimate when we might start sending the next frame. |
base::TimeDelta time_to_catch_up = |