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

Unified Diff: media/cast/sender/congestion_control.cc

Issue 542883004: Cast: Merge common functionality from audio/video sender into frame_sender. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: merge Created 6 years, 3 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
« no previous file with comments | « media/cast/sender/congestion_control.h ('k') | media/cast/sender/congestion_control_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 =
« no previous file with comments | « media/cast/sender/congestion_control.h ('k') | media/cast/sender/congestion_control_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698