| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // The purpose of this file is determine what bitrate to use for mirroring. | 5 // The purpose of this file is determine what bitrate to use for mirroring. |
| 6 // Ideally this should be as much as possible, without causing any frames to | 6 // Ideally this should be as much as possible, without causing any frames to |
| 7 // arrive late. | 7 // arrive late. |
| 8 | 8 |
| 9 // The current algorithm is to measure how much bandwidth we've been using | 9 // The current algorithm is to measure how much bandwidth we've been using |
| 10 // recently. We also keep track of how much data has been queued up for sending | 10 // recently. We also keep track of how much data has been queued up for sending |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 AdaptiveCongestionControl(base::TickClock* clock, | 31 AdaptiveCongestionControl(base::TickClock* clock, |
| 32 int max_bitrate_configured, | 32 int max_bitrate_configured, |
| 33 int min_bitrate_configured, | 33 int min_bitrate_configured, |
| 34 double max_frame_rate); | 34 double max_frame_rate); |
| 35 | 35 |
| 36 ~AdaptiveCongestionControl() final; | 36 ~AdaptiveCongestionControl() final; |
| 37 | 37 |
| 38 // CongestionControl implementation. | 38 // CongestionControl implementation. |
| 39 void UpdateRtt(base::TimeDelta rtt) final; | 39 void UpdateRtt(base::TimeDelta rtt) final; |
| 40 void UpdateTargetPlayoutDelay(base::TimeDelta delay) final; | 40 void UpdateTargetPlayoutDelay(base::TimeDelta delay) final; |
| 41 void SendFrameToTransport(uint32 frame_id, | 41 void SendFrameToTransport(uint32_t frame_id, |
| 42 size_t frame_size_in_bits, | 42 size_t frame_size_in_bits, |
| 43 base::TimeTicks when) final; | 43 base::TimeTicks when) final; |
| 44 void AckFrame(uint32 frame_id, base::TimeTicks when) final; | 44 void AckFrame(uint32_t frame_id, base::TimeTicks when) final; |
| 45 int GetBitrate(base::TimeTicks playout_time, | 45 int GetBitrate(base::TimeTicks playout_time, |
| 46 base::TimeDelta playout_delay, | 46 base::TimeDelta playout_delay, |
| 47 int soft_max_bitrate) final; | 47 int soft_max_bitrate) final; |
| 48 | 48 |
| 49 private: | 49 private: |
| 50 struct FrameStats { | 50 struct FrameStats { |
| 51 FrameStats(); | 51 FrameStats(); |
| 52 // Time this frame was first enqueued for transport. | 52 // Time this frame was first enqueued for transport. |
| 53 base::TimeTicks enqueue_time; | 53 base::TimeTicks enqueue_time; |
| 54 // Time this frame was acked. | 54 // Time this frame was acked. |
| 55 base::TimeTicks ack_time; | 55 base::TimeTicks ack_time; |
| 56 // Size of encoded frame in bits. | 56 // Size of encoded frame in bits. |
| 57 size_t frame_size_in_bits; | 57 size_t frame_size_in_bits; |
| 58 }; | 58 }; |
| 59 | 59 |
| 60 // Calculate how much "dead air" (idle time) there is between two frames. | 60 // Calculate how much "dead air" (idle time) there is between two frames. |
| 61 static base::TimeDelta DeadTime(const FrameStats& a, const FrameStats& b); | 61 static base::TimeDelta DeadTime(const FrameStats& a, const FrameStats& b); |
| 62 // Get the FrameStats for a given |frame_id|. Never returns nullptr. | 62 // Get the FrameStats for a given |frame_id|. Never returns nullptr. |
| 63 // Note: Older FrameStats will be removed automatically. | 63 // Note: Older FrameStats will be removed automatically. |
| 64 FrameStats* GetFrameStats(uint32 frame_id); | 64 FrameStats* GetFrameStats(uint32_t frame_id); |
| 65 // Discard old FrameStats. | 65 // Discard old FrameStats. |
| 66 void PruneFrameStats(); | 66 void PruneFrameStats(); |
| 67 // Calculate a safe bitrate. This is based on how much we've been | 67 // Calculate a safe bitrate. This is based on how much we've been |
| 68 // sending in the past. | 68 // sending in the past. |
| 69 double CalculateSafeBitrate(); | 69 double CalculateSafeBitrate(); |
| 70 | 70 |
| 71 // Estimate when the transport will start sending the data for a given frame. | 71 // Estimate when the transport will start sending the data for a given frame. |
| 72 // |estimated_bitrate| is the current estimated transmit bitrate in bits per | 72 // |estimated_bitrate| is the current estimated transmit bitrate in bits per |
| 73 // second. | 73 // second. |
| 74 base::TimeTicks EstimatedSendingTime(uint32 frame_id, | 74 base::TimeTicks EstimatedSendingTime(uint32_t frame_id, |
| 75 double estimated_bitrate); | 75 double estimated_bitrate); |
| 76 | 76 |
| 77 base::TickClock* const clock_; // Not owned by this class. | 77 base::TickClock* const clock_; // Not owned by this class. |
| 78 const int max_bitrate_configured_; | 78 const int max_bitrate_configured_; |
| 79 const int min_bitrate_configured_; | 79 const int min_bitrate_configured_; |
| 80 const double max_frame_rate_; | 80 const double max_frame_rate_; |
| 81 std::deque<FrameStats> frame_stats_; | 81 std::deque<FrameStats> frame_stats_; |
| 82 uint32 last_frame_stats_; | 82 uint32_t last_frame_stats_; |
| 83 uint32 last_acked_frame_; | 83 uint32_t last_acked_frame_; |
| 84 uint32 last_enqueued_frame_; | 84 uint32_t last_enqueued_frame_; |
| 85 base::TimeDelta rtt_; | 85 base::TimeDelta rtt_; |
| 86 size_t history_size_; | 86 size_t history_size_; |
| 87 size_t acked_bits_in_history_; | 87 size_t acked_bits_in_history_; |
| 88 base::TimeDelta dead_time_in_history_; | 88 base::TimeDelta dead_time_in_history_; |
| 89 | 89 |
| 90 DISALLOW_COPY_AND_ASSIGN(AdaptiveCongestionControl); | 90 DISALLOW_COPY_AND_ASSIGN(AdaptiveCongestionControl); |
| 91 }; | 91 }; |
| 92 | 92 |
| 93 class FixedCongestionControl : public CongestionControl { | 93 class FixedCongestionControl : public CongestionControl { |
| 94 public: | 94 public: |
| 95 explicit FixedCongestionControl(int bitrate) : bitrate_(bitrate) {} | 95 explicit FixedCongestionControl(int bitrate) : bitrate_(bitrate) {} |
| 96 ~FixedCongestionControl() final {} | 96 ~FixedCongestionControl() final {} |
| 97 | 97 |
| 98 // CongestionControl implementation. | 98 // CongestionControl implementation. |
| 99 void UpdateRtt(base::TimeDelta rtt) final {} | 99 void UpdateRtt(base::TimeDelta rtt) final {} |
| 100 void UpdateTargetPlayoutDelay(base::TimeDelta delay) final {} | 100 void UpdateTargetPlayoutDelay(base::TimeDelta delay) final {} |
| 101 void SendFrameToTransport(uint32 frame_id, | 101 void SendFrameToTransport(uint32_t frame_id, |
| 102 size_t frame_size_in_bits, | 102 size_t frame_size_in_bits, |
| 103 base::TimeTicks when) final {} | 103 base::TimeTicks when) final {} |
| 104 void AckFrame(uint32 frame_id, base::TimeTicks when) final {} | 104 void AckFrame(uint32_t frame_id, base::TimeTicks when) final {} |
| 105 int GetBitrate(base::TimeTicks playout_time, | 105 int GetBitrate(base::TimeTicks playout_time, |
| 106 base::TimeDelta playout_delay, | 106 base::TimeDelta playout_delay, |
| 107 int soft_max_bitrate) final { | 107 int soft_max_bitrate) final { |
| 108 return bitrate_; | 108 return bitrate_; |
| 109 } | 109 } |
| 110 | 110 |
| 111 private: | 111 private: |
| 112 const int bitrate_; | 112 const int bitrate_; |
| 113 | 113 |
| 114 DISALLOW_COPY_AND_ASSIGN(FixedCongestionControl); | 114 DISALLOW_COPY_AND_ASSIGN(FixedCongestionControl); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 136 // congestion control more aggressive. | 136 // congestion control more aggressive. |
| 137 static const double kTargetEmptyBufferFraction = 0.9; | 137 static const double kTargetEmptyBufferFraction = 0.9; |
| 138 | 138 |
| 139 // This is the size of our history in frames. Larger values makes the | 139 // This is the size of our history in frames. Larger values makes the |
| 140 // congestion control adapt slower. | 140 // congestion control adapt slower. |
| 141 static const size_t kHistorySize = 100; | 141 static const size_t kHistorySize = 100; |
| 142 | 142 |
| 143 AdaptiveCongestionControl::FrameStats::FrameStats() : frame_size_in_bits(0) { | 143 AdaptiveCongestionControl::FrameStats::FrameStats() : frame_size_in_bits(0) { |
| 144 } | 144 } |
| 145 | 145 |
| 146 AdaptiveCongestionControl::AdaptiveCongestionControl( | 146 AdaptiveCongestionControl::AdaptiveCongestionControl(base::TickClock* clock, |
| 147 base::TickClock* clock, | 147 int max_bitrate_configured, |
| 148 int max_bitrate_configured, | 148 int min_bitrate_configured, |
| 149 int min_bitrate_configured, | 149 double max_frame_rate) |
| 150 double max_frame_rate) | |
| 151 : clock_(clock), | 150 : clock_(clock), |
| 152 max_bitrate_configured_(max_bitrate_configured), | 151 max_bitrate_configured_(max_bitrate_configured), |
| 153 min_bitrate_configured_(min_bitrate_configured), | 152 min_bitrate_configured_(min_bitrate_configured), |
| 154 max_frame_rate_(max_frame_rate), | 153 max_frame_rate_(max_frame_rate), |
| 155 last_frame_stats_(static_cast<uint32>(-1)), | 154 last_frame_stats_(static_cast<uint32_t>(-1)), |
| 156 last_acked_frame_(static_cast<uint32>(-1)), | 155 last_acked_frame_(static_cast<uint32_t>(-1)), |
| 157 last_enqueued_frame_(static_cast<uint32>(-1)), | 156 last_enqueued_frame_(static_cast<uint32_t>(-1)), |
| 158 history_size_(kHistorySize), | 157 history_size_(kHistorySize), |
| 159 acked_bits_in_history_(0) { | 158 acked_bits_in_history_(0) { |
| 160 DCHECK_GE(max_bitrate_configured, min_bitrate_configured) << "Invalid config"; | 159 DCHECK_GE(max_bitrate_configured, min_bitrate_configured) << "Invalid config"; |
| 161 DCHECK_GT(min_bitrate_configured, 0); | 160 DCHECK_GT(min_bitrate_configured, 0); |
| 162 frame_stats_.resize(2); | 161 frame_stats_.resize(2); |
| 163 base::TimeTicks now = clock->NowTicks(); | 162 base::TimeTicks now = clock->NowTicks(); |
| 164 frame_stats_[0].ack_time = now; | 163 frame_stats_[0].ack_time = now; |
| 165 frame_stats_[0].enqueue_time = now; | 164 frame_stats_[0].enqueue_time = now; |
| 166 frame_stats_[1].ack_time = now; | 165 frame_stats_[1].ack_time = now; |
| 167 DCHECK(!frame_stats_[0].ack_time.is_null()); | 166 DCHECK(!frame_stats_[0].ack_time.is_null()); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 198 double transmit_time = | 197 double transmit_time = |
| 199 (GetFrameStats(last_acked_frame_)->ack_time - | 198 (GetFrameStats(last_acked_frame_)->ack_time - |
| 200 frame_stats_.front().enqueue_time - dead_time_in_history_).InSecondsF(); | 199 frame_stats_.front().enqueue_time - dead_time_in_history_).InSecondsF(); |
| 201 | 200 |
| 202 if (acked_bits_in_history_ == 0 || transmit_time <= 0.0) { | 201 if (acked_bits_in_history_ == 0 || transmit_time <= 0.0) { |
| 203 return min_bitrate_configured_; | 202 return min_bitrate_configured_; |
| 204 } | 203 } |
| 205 return acked_bits_in_history_ / std::max(transmit_time, 1E-3); | 204 return acked_bits_in_history_ / std::max(transmit_time, 1E-3); |
| 206 } | 205 } |
| 207 | 206 |
| 208 AdaptiveCongestionControl::FrameStats* | 207 AdaptiveCongestionControl::FrameStats* AdaptiveCongestionControl::GetFrameStats( |
| 209 AdaptiveCongestionControl::GetFrameStats(uint32 frame_id) { | 208 uint32_t frame_id) { |
| 210 int32 offset = static_cast<int32>(frame_id - last_frame_stats_); | 209 int32_t offset = static_cast<int32_t>(frame_id - last_frame_stats_); |
| 211 DCHECK_LT(offset, static_cast<int32>(kHistorySize)); | 210 DCHECK_LT(offset, static_cast<int32_t>(kHistorySize)); |
| 212 if (offset > 0) { | 211 if (offset > 0) { |
| 213 frame_stats_.resize(frame_stats_.size() + offset); | 212 frame_stats_.resize(frame_stats_.size() + offset); |
| 214 last_frame_stats_ += offset; | 213 last_frame_stats_ += offset; |
| 215 offset = 0; | 214 offset = 0; |
| 216 } | 215 } |
| 217 PruneFrameStats(); | 216 PruneFrameStats(); |
| 218 offset += frame_stats_.size() - 1; | 217 offset += frame_stats_.size() - 1; |
| 219 // TODO(miu): Change the following to DCHECK once crash fix is confirmed. | 218 // TODO(miu): Change the following to DCHECK once crash fix is confirmed. |
| 220 // http://crbug.com/517145 | 219 // http://crbug.com/517145 |
| 221 CHECK(offset >= 0 && offset < static_cast<int32>(frame_stats_.size())); | 220 CHECK(offset >= 0 && offset < static_cast<int32_t>(frame_stats_.size())); |
| 222 return &frame_stats_[offset]; | 221 return &frame_stats_[offset]; |
| 223 } | 222 } |
| 224 | 223 |
| 225 void AdaptiveCongestionControl::PruneFrameStats() { | 224 void AdaptiveCongestionControl::PruneFrameStats() { |
| 226 while (frame_stats_.size() > history_size_) { | 225 while (frame_stats_.size() > history_size_) { |
| 227 DCHECK_GT(frame_stats_.size(), 1UL); | 226 DCHECK_GT(frame_stats_.size(), 1UL); |
| 228 DCHECK(!frame_stats_[0].ack_time.is_null()); | 227 DCHECK(!frame_stats_[0].ack_time.is_null()); |
| 229 acked_bits_in_history_ -= frame_stats_[0].frame_size_in_bits; | 228 acked_bits_in_history_ -= frame_stats_[0].frame_size_in_bits; |
| 230 dead_time_in_history_ -= DeadTime(frame_stats_[0], frame_stats_[1]); | 229 dead_time_in_history_ -= DeadTime(frame_stats_[0], frame_stats_[1]); |
| 231 DCHECK_GE(acked_bits_in_history_, 0UL); | 230 DCHECK_GE(acked_bits_in_history_, 0UL); |
| 232 VLOG(2) << "DT: " << dead_time_in_history_.InSecondsF(); | 231 VLOG(2) << "DT: " << dead_time_in_history_.InSecondsF(); |
| 233 DCHECK_GE(dead_time_in_history_.InSecondsF(), 0.0); | 232 DCHECK_GE(dead_time_in_history_.InSecondsF(), 0.0); |
| 234 frame_stats_.pop_front(); | 233 frame_stats_.pop_front(); |
| 235 } | 234 } |
| 236 } | 235 } |
| 237 | 236 |
| 238 void AdaptiveCongestionControl::AckFrame(uint32 frame_id, | 237 void AdaptiveCongestionControl::AckFrame(uint32_t frame_id, |
| 239 base::TimeTicks when) { | 238 base::TimeTicks when) { |
| 240 FrameStats* frame_stats = GetFrameStats(last_acked_frame_); | 239 FrameStats* frame_stats = GetFrameStats(last_acked_frame_); |
| 241 while (IsNewerFrameId(frame_id, last_acked_frame_)) { | 240 while (IsNewerFrameId(frame_id, last_acked_frame_)) { |
| 242 FrameStats* last_frame_stats = frame_stats; | 241 FrameStats* last_frame_stats = frame_stats; |
| 243 frame_stats = GetFrameStats(last_acked_frame_ + 1); | 242 frame_stats = GetFrameStats(last_acked_frame_ + 1); |
| 244 if (frame_stats->enqueue_time.is_null()) { | 243 if (frame_stats->enqueue_time.is_null()) { |
| 245 // Can't ack a frame that hasn't been sent yet. | 244 // Can't ack a frame that hasn't been sent yet. |
| 246 return; | 245 return; |
| 247 } | 246 } |
| 248 last_acked_frame_++; | 247 last_acked_frame_++; |
| 249 if (when < frame_stats->enqueue_time) | 248 if (when < frame_stats->enqueue_time) |
| 250 when = frame_stats->enqueue_time; | 249 when = frame_stats->enqueue_time; |
| 251 | 250 |
| 252 frame_stats->ack_time = when; | 251 frame_stats->ack_time = when; |
| 253 acked_bits_in_history_ += frame_stats->frame_size_in_bits; | 252 acked_bits_in_history_ += frame_stats->frame_size_in_bits; |
| 254 dead_time_in_history_ += DeadTime(*last_frame_stats, *frame_stats); | 253 dead_time_in_history_ += DeadTime(*last_frame_stats, *frame_stats); |
| 255 } | 254 } |
| 256 } | 255 } |
| 257 | 256 |
| 258 void AdaptiveCongestionControl::SendFrameToTransport(uint32 frame_id, | 257 void AdaptiveCongestionControl::SendFrameToTransport(uint32_t frame_id, |
| 259 size_t frame_size_in_bits, | 258 size_t frame_size_in_bits, |
| 260 base::TimeTicks when) { | 259 base::TimeTicks when) { |
| 261 last_enqueued_frame_ = frame_id; | 260 last_enqueued_frame_ = frame_id; |
| 262 FrameStats* frame_stats = GetFrameStats(frame_id); | 261 FrameStats* frame_stats = GetFrameStats(frame_id); |
| 263 frame_stats->enqueue_time = when; | 262 frame_stats->enqueue_time = when; |
| 264 frame_stats->frame_size_in_bits = frame_size_in_bits; | 263 frame_stats->frame_size_in_bits = frame_size_in_bits; |
| 265 } | 264 } |
| 266 | 265 |
| 267 base::TimeTicks AdaptiveCongestionControl::EstimatedSendingTime( | 266 base::TimeTicks AdaptiveCongestionControl::EstimatedSendingTime( |
| 268 uint32 frame_id, | 267 uint32_t frame_id, |
| 269 double estimated_bitrate) { | 268 double estimated_bitrate) { |
| 270 const base::TimeTicks now = clock_->NowTicks(); | 269 const base::TimeTicks now = clock_->NowTicks(); |
| 271 | 270 |
| 272 // Starting with the time of the latest acknowledgement, extrapolate forward | 271 // Starting with the time of the latest acknowledgement, extrapolate forward |
| 273 // to determine an estimated sending time for |frame_id|. | 272 // to determine an estimated sending time for |frame_id|. |
| 274 // | 273 // |
| 275 // |estimated_sending_time| will contain the estimated sending time for each | 274 // |estimated_sending_time| will contain the estimated sending time for each |
| 276 // frame after the last ACK'ed frame. It is possible for multiple frames to | 275 // frame after the last ACK'ed frame. It is possible for multiple frames to |
| 277 // be in-flight; and therefore it is common for the |estimated_sending_time| | 276 // be in-flight; and therefore it is common for the |estimated_sending_time| |
| 278 // for those frames to be before |now|. | 277 // for those frames to be before |now|. |
| 279 base::TimeTicks estimated_sending_time; | 278 base::TimeTicks estimated_sending_time; |
| 280 for (uint32 f = last_acked_frame_; IsNewerFrameId(frame_id, f); ++f) { | 279 for (uint32_t f = last_acked_frame_; IsNewerFrameId(frame_id, f); ++f) { |
| 281 FrameStats* const stats = GetFrameStats(f); | 280 FrameStats* const stats = GetFrameStats(f); |
| 282 | 281 |
| 283 // |estimated_ack_time| is the local time when the sender receives the ACK, | 282 // |estimated_ack_time| is the local time when the sender receives the ACK, |
| 284 // and not the time when the ACK left the receiver. | 283 // and not the time when the ACK left the receiver. |
| 285 base::TimeTicks estimated_ack_time = stats->ack_time; | 284 base::TimeTicks estimated_ack_time = stats->ack_time; |
| 286 | 285 |
| 287 // If |estimated_ack_time| is not null, then we already have the actual ACK | 286 // If |estimated_ack_time| is not null, then we already have the actual ACK |
| 288 // time, so we'll just use it. Otherwise, we need to estimate when the ACK | 287 // time, so we'll just use it. Otherwise, we need to estimate when the ACK |
| 289 // will arrive. | 288 // will arrive. |
| 290 if (estimated_ack_time.is_null()) { | 289 if (estimated_ack_time.is_null()) { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 empty_buffer_fraction); | 364 empty_buffer_fraction); |
| 366 bits_per_second = std::min(bits_per_second, soft_max_bitrate); | 365 bits_per_second = std::min(bits_per_second, soft_max_bitrate); |
| 367 bits_per_second = std::max(bits_per_second, min_bitrate_configured_); | 366 bits_per_second = std::max(bits_per_second, min_bitrate_configured_); |
| 368 bits_per_second = std::min(bits_per_second, max_bitrate_configured_); | 367 bits_per_second = std::min(bits_per_second, max_bitrate_configured_); |
| 369 | 368 |
| 370 return bits_per_second; | 369 return bits_per_second; |
| 371 } | 370 } |
| 372 | 371 |
| 373 } // namespace cast | 372 } // namespace cast |
| 374 } // namespace media | 373 } // namespace media |
| OLD | NEW |