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

Side by Side Diff: media/cast/sender/frame_sender.cc

Issue 560223002: [Cast] Limit frames in flight by duration, and not by number of frames. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Removed auto-eviction from PacketStorage, since that should never happen. 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 unified diff | Download patch
OLDNEW
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 #include "media/cast/sender/frame_sender.h" 5 #include "media/cast/sender/frame_sender.h"
6 6
7 #include "base/debug/trace_event.h" 7 #include "base/debug/trace_event.h"
8 8
9 namespace media { 9 namespace media {
10 namespace cast { 10 namespace cast {
11 namespace { 11 namespace {
12 12
13 const int kMinSchedulingDelayMs = 1; 13 const int kMinSchedulingDelayMs = 1;
14 const int kNumAggressiveReportsSentAtStart = 100; 14 const int kNumAggressiveReportsSentAtStart = 100;
15 15
16 // The additional number of frames that can be in-flight when input exceeds the
17 // maximum frame rate.
18 const int kMaxFrameBurst = 5;
19
16 } // namespace 20 } // namespace
17 21
22 // Convenience macro used in logging statements throughout this file.
23 #define SENDER_SSRC (is_audio_ ? "AUDIO[" : "VIDEO[") << ssrc_ << "] "
24
18 FrameSender::FrameSender(scoped_refptr<CastEnvironment> cast_environment, 25 FrameSender::FrameSender(scoped_refptr<CastEnvironment> cast_environment,
19 bool is_audio, 26 bool is_audio,
20 CastTransportSender* const transport_sender, 27 CastTransportSender* const transport_sender,
21 base::TimeDelta rtcp_interval, 28 base::TimeDelta rtcp_interval,
22 int rtp_timebase, 29 int rtp_timebase,
23 uint32 ssrc, 30 uint32 ssrc,
24 double max_frame_rate, 31 double max_frame_rate,
25 base::TimeDelta min_playout_delay, 32 base::TimeDelta min_playout_delay,
26 base::TimeDelta max_playout_delay, 33 base::TimeDelta max_playout_delay,
27 CongestionControl* congestion_control) 34 CongestionControl* congestion_control)
28 : cast_environment_(cast_environment), 35 : cast_environment_(cast_environment),
29 transport_sender_(transport_sender), 36 transport_sender_(transport_sender),
30 ssrc_(ssrc), 37 ssrc_(ssrc),
31 rtcp_interval_(rtcp_interval), 38 rtcp_interval_(rtcp_interval),
32 min_playout_delay_(min_playout_delay == base::TimeDelta() ? 39 min_playout_delay_(min_playout_delay == base::TimeDelta() ?
33 max_playout_delay : min_playout_delay), 40 max_playout_delay : min_playout_delay),
34 max_playout_delay_(max_playout_delay), 41 max_playout_delay_(max_playout_delay),
35 max_frame_rate_(max_frame_rate), 42 max_frame_rate_(max_frame_rate),
36 num_aggressive_rtcp_reports_sent_(0), 43 num_aggressive_rtcp_reports_sent_(0),
37 last_sent_frame_id_(0), 44 last_sent_frame_id_(0),
38 latest_acked_frame_id_(0), 45 latest_acked_frame_id_(0),
39 duplicate_ack_counter_(0), 46 duplicate_ack_counter_(0),
47 congestion_control_(congestion_control),
40 rtp_timebase_(rtp_timebase), 48 rtp_timebase_(rtp_timebase),
41 congestion_control_(congestion_control),
42 is_audio_(is_audio), 49 is_audio_(is_audio),
43 weak_factory_(this) { 50 weak_factory_(this) {
44 DCHECK(transport_sender_); 51 DCHECK(transport_sender_);
45 DCHECK_GT(rtp_timebase_, 0); 52 DCHECK_GT(rtp_timebase_, 0);
46 DCHECK(congestion_control_); 53 DCHECK(congestion_control_);
47 SetTargetPlayoutDelay(min_playout_delay_); 54 SetTargetPlayoutDelay(min_playout_delay_);
48 send_target_playout_delay_ = false; 55 send_target_playout_delay_ = false;
49 memset(frame_rtp_timestamps_, 0, sizeof(frame_rtp_timestamps_)); 56 memset(frame_rtp_timestamps_, 0, sizeof(frame_rtp_timestamps_));
50 } 57 }
51 58
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 121
115 void FrameSender::ResendCheck() { 122 void FrameSender::ResendCheck() {
116 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 123 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
117 DCHECK(!last_send_time_.is_null()); 124 DCHECK(!last_send_time_.is_null());
118 const base::TimeDelta time_since_last_send = 125 const base::TimeDelta time_since_last_send =
119 cast_environment_->Clock()->NowTicks() - last_send_time_; 126 cast_environment_->Clock()->NowTicks() - last_send_time_;
120 if (time_since_last_send > target_playout_delay_) { 127 if (time_since_last_send > target_playout_delay_) {
121 if (latest_acked_frame_id_ == last_sent_frame_id_) { 128 if (latest_acked_frame_id_ == last_sent_frame_id_) {
122 // Last frame acked, no point in doing anything 129 // Last frame acked, no point in doing anything
123 } else { 130 } else {
124 VLOG(1) << "ACK timeout; last acked frame: " << latest_acked_frame_id_; 131 VLOG(1) << SENDER_SSRC << "ACK timeout; last acked frame: "
132 << latest_acked_frame_id_;
125 ResendForKickstart(); 133 ResendForKickstart();
126 } 134 }
127 } 135 }
128 ScheduleNextResendCheck(); 136 ScheduleNextResendCheck();
129 } 137 }
130 138
131 void FrameSender::ScheduleNextResendCheck() { 139 void FrameSender::ScheduleNextResendCheck() {
132 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 140 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
133 DCHECK(!last_send_time_.is_null()); 141 DCHECK(!last_send_time_.is_null());
134 base::TimeDelta time_to_next = 142 base::TimeDelta time_to_next =
135 last_send_time_ - cast_environment_->Clock()->NowTicks() + 143 last_send_time_ - cast_environment_->Clock()->NowTicks() +
136 target_playout_delay_; 144 target_playout_delay_;
137 time_to_next = std::max( 145 time_to_next = std::max(
138 time_to_next, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); 146 time_to_next, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs));
139 cast_environment_->PostDelayedTask( 147 cast_environment_->PostDelayedTask(
140 CastEnvironment::MAIN, 148 CastEnvironment::MAIN,
141 FROM_HERE, 149 FROM_HERE,
142 base::Bind(&FrameSender::ResendCheck, weak_factory_.GetWeakPtr()), 150 base::Bind(&FrameSender::ResendCheck, weak_factory_.GetWeakPtr()),
143 time_to_next); 151 time_to_next);
144 } 152 }
145 153
146 void FrameSender::ResendForKickstart() { 154 void FrameSender::ResendForKickstart() {
147 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 155 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
148 DCHECK(!last_send_time_.is_null()); 156 DCHECK(!last_send_time_.is_null());
149 VLOG(1) << "Resending last packet of frame " << last_sent_frame_id_ 157 VLOG(1) << SENDER_SSRC << "Resending last packet of frame "
150 << " to kick-start."; 158 << last_sent_frame_id_ << " to kick-start.";
151 last_send_time_ = cast_environment_->Clock()->NowTicks(); 159 last_send_time_ = cast_environment_->Clock()->NowTicks();
152 transport_sender_->ResendFrameForKickstart(ssrc_, last_sent_frame_id_); 160 transport_sender_->ResendFrameForKickstart(ssrc_, last_sent_frame_id_);
153 } 161 }
154 162
155 void FrameSender::RecordLatestFrameTimestamps(uint32 frame_id, 163 void FrameSender::RecordLatestFrameTimestamps(uint32 frame_id,
156 base::TimeTicks reference_time, 164 base::TimeTicks reference_time,
157 RtpTimestamp rtp_timestamp) { 165 RtpTimestamp rtp_timestamp) {
158 DCHECK(!reference_time.is_null()); 166 DCHECK(!reference_time.is_null());
159 frame_reference_times_[frame_id % arraysize(frame_reference_times_)] = 167 frame_reference_times_[frame_id % arraysize(frame_reference_times_)] =
160 reference_time; 168 reference_time;
161 frame_rtp_timestamps_[frame_id % arraysize(frame_rtp_timestamps_)] = 169 frame_rtp_timestamps_[frame_id % arraysize(frame_rtp_timestamps_)] =
162 rtp_timestamp; 170 rtp_timestamp;
163 } 171 }
164 172
165 base::TimeTicks FrameSender::GetRecordedReferenceTime(uint32 frame_id) const { 173 base::TimeTicks FrameSender::GetRecordedReferenceTime(uint32 frame_id) const {
166 return frame_reference_times_[frame_id % arraysize(frame_reference_times_)]; 174 return frame_reference_times_[frame_id % arraysize(frame_reference_times_)];
167 } 175 }
168 176
169 RtpTimestamp FrameSender::GetRecordedRtpTimestamp(uint32 frame_id) const { 177 RtpTimestamp FrameSender::GetRecordedRtpTimestamp(uint32 frame_id) const {
170 return frame_rtp_timestamps_[frame_id % arraysize(frame_rtp_timestamps_)]; 178 return frame_rtp_timestamps_[frame_id % arraysize(frame_rtp_timestamps_)];
171 } 179 }
172 180
181 int FrameSender::GetUnacknowledgedFrameCount() const {
182 const int count =
183 static_cast<int32>(last_sent_frame_id_ - latest_acked_frame_id_);
184 DCHECK_GE(count, 0);
185 return count;
186 }
187
188 base::TimeDelta FrameSender::GetAllowedInFlightMediaDuration() const {
189 // The total amount allowed in-flight media should equal the amount that fits
190 // within the entire playout delay window, plus the amount of time it takes to
191 // receive an ACK from the receiver.
192 // TODO(miu): Research is needed, but there is likely a better formula.
193 return target_playout_delay_ + (current_round_trip_time_ / 2);
194 }
195
173 void FrameSender::SendEncodedFrame( 196 void FrameSender::SendEncodedFrame(
174 int requested_bitrate_before_encode, 197 int requested_bitrate_before_encode,
175 scoped_ptr<EncodedFrame> encoded_frame) { 198 scoped_ptr<EncodedFrame> encoded_frame) {
176 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 199 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
177 200
201 VLOG(2) << SENDER_SSRC << "About to send another frame: last_sent="
202 << last_sent_frame_id_ << ", latest_acked=" << latest_acked_frame_id_;
203
178 const uint32 frame_id = encoded_frame->frame_id; 204 const uint32 frame_id = encoded_frame->frame_id;
179 205
180 const bool is_first_frame_to_be_sent = last_send_time_.is_null(); 206 const bool is_first_frame_to_be_sent = last_send_time_.is_null();
181 last_send_time_ = cast_environment_->Clock()->NowTicks(); 207 last_send_time_ = cast_environment_->Clock()->NowTicks();
182 last_sent_frame_id_ = frame_id; 208 last_sent_frame_id_ = frame_id;
183 // If this is the first frame about to be sent, fake the value of 209 // If this is the first frame about to be sent, fake the value of
184 // |latest_acked_frame_id_| to indicate the receiver starts out all caught up. 210 // |latest_acked_frame_id_| to indicate the receiver starts out all caught up.
185 // Also, schedule the periodic frame re-send checks. 211 // Also, schedule the periodic frame re-send checks.
186 if (is_first_frame_to_be_sent) { 212 if (is_first_frame_to_be_sent) {
187 latest_acked_frame_id_ = frame_id - 1; 213 latest_acked_frame_id_ = frame_id - 1;
188 ScheduleNextResendCheck(); 214 ScheduleNextResendCheck();
189 } 215 }
190 216
191 VLOG_IF(1, encoded_frame->dependency == EncodedFrame::KEY) 217 VLOG_IF(1, !is_audio_ && encoded_frame->dependency == EncodedFrame::KEY)
192 << "Send encoded key frame; frame_id: " << frame_id; 218 << SENDER_SSRC << "Sending encoded key frame, id=" << frame_id;
193 219
194 cast_environment_->Logging()->InsertEncodedFrameEvent( 220 cast_environment_->Logging()->InsertEncodedFrameEvent(
195 last_send_time_, FRAME_ENCODED, 221 last_send_time_, FRAME_ENCODED,
196 is_audio_ ? AUDIO_EVENT : VIDEO_EVENT, 222 is_audio_ ? AUDIO_EVENT : VIDEO_EVENT,
197 encoded_frame->rtp_timestamp, 223 encoded_frame->rtp_timestamp,
198 frame_id, static_cast<int>(encoded_frame->data.size()), 224 frame_id, static_cast<int>(encoded_frame->data.size()),
199 encoded_frame->dependency == EncodedFrame::KEY, 225 encoded_frame->dependency == EncodedFrame::KEY,
200 requested_bitrate_before_encode); 226 requested_bitrate_before_encode);
201 227
202 RecordLatestFrameTimestamps(frame_id, 228 RecordLatestFrameTimestamps(frame_id,
(...skipping 12 matching lines...) Expand all
215 // frame so that the receiver can properly compute playout times. The reason 241 // frame so that the receiver can properly compute playout times. The reason
216 // more than one report is sent is because transmission is not guaranteed, 242 // more than one report is sent is because transmission is not guaranteed,
217 // only best effort, so send enough that one should almost certainly get 243 // only best effort, so send enough that one should almost certainly get
218 // through. 244 // through.
219 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { 245 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) {
220 // SendRtcpReport() will schedule future reports to be made if this is the 246 // SendRtcpReport() will schedule future reports to be made if this is the
221 // last "aggressive report." 247 // last "aggressive report."
222 ++num_aggressive_rtcp_reports_sent_; 248 ++num_aggressive_rtcp_reports_sent_;
223 const bool is_last_aggressive_report = 249 const bool is_last_aggressive_report =
224 (num_aggressive_rtcp_reports_sent_ == kNumAggressiveReportsSentAtStart); 250 (num_aggressive_rtcp_reports_sent_ == kNumAggressiveReportsSentAtStart);
225 VLOG_IF(1, is_last_aggressive_report) << "Sending last aggressive report."; 251 VLOG_IF(1, is_last_aggressive_report)
252 << SENDER_SSRC << "Sending last aggressive report.";
226 SendRtcpReport(is_last_aggressive_report); 253 SendRtcpReport(is_last_aggressive_report);
227 } 254 }
228 255
229 congestion_control_->SendFrameToTransport( 256 congestion_control_->SendFrameToTransport(
230 frame_id, encoded_frame->data.size() * 8, last_send_time_); 257 frame_id, encoded_frame->data.size() * 8, last_send_time_);
231 258
232 if (send_target_playout_delay_) { 259 if (send_target_playout_delay_) {
233 encoded_frame->new_playout_delay_ms = 260 encoded_frame->new_playout_delay_ms =
234 target_playout_delay_.InMilliseconds(); 261 target_playout_delay_.InMilliseconds();
235 } 262 }
236 transport_sender_->InsertFrame(ssrc_, *encoded_frame); 263 transport_sender_->InsertFrame(ssrc_, *encoded_frame);
237 } 264 }
238 265
239 void FrameSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { 266 void FrameSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) {
240 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 267 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
241 268
242 const bool have_valid_rtt = current_round_trip_time_ > base::TimeDelta(); 269 const bool have_valid_rtt = current_round_trip_time_ > base::TimeDelta();
243 if (have_valid_rtt) { 270 if (have_valid_rtt) {
244 congestion_control_->UpdateRtt(current_round_trip_time_); 271 congestion_control_->UpdateRtt(current_round_trip_time_);
245 272
246 // Having the RTT value implies the receiver sent back a receiver report 273 // Having the RTT value implies the receiver sent back a receiver report
247 // based on it having received a report from here. Therefore, ensure this 274 // based on it having received a report from here. Therefore, ensure this
248 // sender stops aggressively sending reports. 275 // sender stops aggressively sending reports.
249 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { 276 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) {
250 VLOG(1) << "No longer a need to send reports aggressively (sent " 277 VLOG(1) << SENDER_SSRC
278 << "No longer a need to send reports aggressively (sent "
251 << num_aggressive_rtcp_reports_sent_ << ")."; 279 << num_aggressive_rtcp_reports_sent_ << ").";
252 num_aggressive_rtcp_reports_sent_ = kNumAggressiveReportsSentAtStart; 280 num_aggressive_rtcp_reports_sent_ = kNumAggressiveReportsSentAtStart;
253 ScheduleNextRtcpReport(); 281 ScheduleNextRtcpReport();
254 } 282 }
255 } 283 }
256 284
257 if (last_send_time_.is_null()) 285 if (last_send_time_.is_null())
258 return; // Cannot get an ACK without having first sent a frame. 286 return; // Cannot get an ACK without having first sent a frame.
259 287
260 if (cast_feedback.missing_frames_and_packets.empty()) { 288 if (cast_feedback.missing_frames_and_packets.empty()) {
261 OnAck(cast_feedback.ack_frame_id); 289 OnAck(cast_feedback.ack_frame_id);
262 290
263 // We only count duplicate ACKs when we have sent newer frames. 291 // We only count duplicate ACKs when we have sent newer frames.
264 if (latest_acked_frame_id_ == cast_feedback.ack_frame_id && 292 if (latest_acked_frame_id_ == cast_feedback.ack_frame_id &&
265 latest_acked_frame_id_ != last_sent_frame_id_) { 293 latest_acked_frame_id_ != last_sent_frame_id_) {
266 duplicate_ack_counter_++; 294 duplicate_ack_counter_++;
267 } else { 295 } else {
268 duplicate_ack_counter_ = 0; 296 duplicate_ack_counter_ = 0;
269 } 297 }
270 // TODO(miu): The values "2" and "3" should be derived from configuration. 298 // TODO(miu): The values "2" and "3" should be derived from configuration.
271 if (duplicate_ack_counter_ >= 2 && duplicate_ack_counter_ % 3 == 2) { 299 if (duplicate_ack_counter_ >= 2 && duplicate_ack_counter_ % 3 == 2) {
272 VLOG(1) << "Received duplicate ACK for frame " << latest_acked_frame_id_; 300 VLOG(1) << SENDER_SSRC << "Received duplicate ACK for frame "
301 << latest_acked_frame_id_;
273 ResendForKickstart(); 302 ResendForKickstart();
274 } 303 }
275 } else { 304 } else {
276 // Only count duplicated ACKs if there is no NACK request in between. 305 // Only count duplicated ACKs if there is no NACK request in between.
277 // This is to avoid aggresive resend. 306 // This is to avoid aggresive resend.
278 duplicate_ack_counter_ = 0; 307 duplicate_ack_counter_ = 0;
279 } 308 }
280 309
281 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); 310 base::TimeTicks now = cast_environment_->Clock()->NowTicks();
282 congestion_control_->AckFrame(cast_feedback.ack_frame_id, now); 311 congestion_control_->AckFrame(cast_feedback.ack_frame_id, now);
283 312
284 cast_environment_->Logging()->InsertFrameEvent( 313 cast_environment_->Logging()->InsertFrameEvent(
285 now, 314 now,
286 FRAME_ACK_RECEIVED, 315 FRAME_ACK_RECEIVED,
287 is_audio_ ? AUDIO_EVENT : VIDEO_EVENT, 316 is_audio_ ? AUDIO_EVENT : VIDEO_EVENT,
288 GetRecordedRtpTimestamp(cast_feedback.ack_frame_id), 317 GetRecordedRtpTimestamp(cast_feedback.ack_frame_id),
289 cast_feedback.ack_frame_id); 318 cast_feedback.ack_frame_id);
290 319
291 const bool is_acked_out_of_order = 320 const bool is_acked_out_of_order =
292 static_cast<int32>(cast_feedback.ack_frame_id - 321 static_cast<int32>(cast_feedback.ack_frame_id -
293 latest_acked_frame_id_) < 0; 322 latest_acked_frame_id_) < 0;
294 VLOG(2) << "Received ACK" << (is_acked_out_of_order ? " out-of-order" : "") 323 VLOG(2) << SENDER_SSRC
324 << "Received ACK" << (is_acked_out_of_order ? " out-of-order" : "")
295 << " for frame " << cast_feedback.ack_frame_id; 325 << " for frame " << cast_feedback.ack_frame_id;
296 if (!is_acked_out_of_order) { 326 if (!is_acked_out_of_order) {
297 // Cancel resends of acked frames. 327 // Cancel resends of acked frames.
298 std::vector<uint32> cancel_sending_frames; 328 std::vector<uint32> cancel_sending_frames;
299 while (latest_acked_frame_id_ != cast_feedback.ack_frame_id) { 329 while (latest_acked_frame_id_ != cast_feedback.ack_frame_id) {
300 latest_acked_frame_id_++; 330 latest_acked_frame_id_++;
301 cancel_sending_frames.push_back(latest_acked_frame_id_); 331 cancel_sending_frames.push_back(latest_acked_frame_id_);
302 } 332 }
303 transport_sender_->CancelSendingFrames(ssrc_, cancel_sending_frames); 333 transport_sender_->CancelSendingFrames(ssrc_, cancel_sending_frames);
304 latest_acked_frame_id_ = cast_feedback.ack_frame_id; 334 latest_acked_frame_id_ = cast_feedback.ack_frame_id;
305 } 335 }
306 } 336 }
307 337
308 bool FrameSender::ShouldDropNextFrame(base::TimeTicks capture_time) const { 338 bool FrameSender::ShouldDropNextFrame(base::TimeDelta frame_duration) const {
309 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); 339 // Check that accepting the next frame won't cause more frames to become
310 int frames_in_flight = 0; 340 // in-flight than the system's design limit.
311 base::TimeDelta duration_in_flight; 341 const int count_frames_in_flight =
312 if (!last_send_time_.is_null()) { 342 GetUnacknowledgedFrameCount() + GetNumberOfFramesInEncoder();
313 frames_in_flight = 343 if (count_frames_in_flight >= kMaxUnackedFrames) {
314 static_cast<int32>(last_sent_frame_id_ - latest_acked_frame_id_); 344 VLOG(1) << SENDER_SSRC << "Dropping: Too many frames would be in-flight.";
315 if (frames_in_flight > 0) { 345 return true;
316 const uint32 oldest_unacked_frame_id = latest_acked_frame_id_ + 1;
317 duration_in_flight =
318 capture_time - GetRecordedReferenceTime(oldest_unacked_frame_id);
319 }
320 } 346 }
321 frames_in_flight += GetNumberOfFramesInEncoder(); 347
322 VLOG(2) << frames_in_flight 348 // Check that accepting the next frame won't exceed the configured maximum
hubbe 2014/09/18 17:56:05 Do we really need this part? We'll still be limite
miu 2014/09/18 21:38:43 IMO, it's an important safety measure to have. It
323 << " frames in flight; last sent: " << last_sent_frame_id_ 349 // frame rate, allowing for short-term bursts.
324 << "; latest acked: " << latest_acked_frame_id_ 350 base::TimeDelta duration_in_flight = GetInFlightMediaDuration();
325 << "; frames in encoder: " << GetNumberOfFramesInEncoder() 351 const double max_frames_in_flight =
326 << "; duration in flight: " 352 max_frame_rate_ * duration_in_flight.InSecondsF();
327 << duration_in_flight.InMicroseconds() << " usec (" 353 if (count_frames_in_flight >= max_frames_in_flight + kMaxFrameBurst) {
328 << (target_playout_delay_ > base::TimeDelta() ? 354 VLOG(1) << SENDER_SSRC << "Dropping: Burst threshold would be exceeded.";
329 100 * duration_in_flight / target_playout_delay_ : 355 return true;
330 kint64max) << "%)"; 356 }
331 return frames_in_flight >= max_unacked_frames_ || 357
332 duration_in_flight >= target_playout_delay_; 358 // Check that accepting the next frame won't exceed the allowed in-flight
359 // media duration.
360 const base::TimeDelta duration_would_be_in_flight =
361 duration_in_flight + frame_duration;
362 const base::TimeDelta allowed_in_flight = GetAllowedInFlightMediaDuration();
363 if (VLOG_IS_ON(1)) {
364 const int64 percent = allowed_in_flight > base::TimeDelta() ?
365 100 * duration_would_be_in_flight / allowed_in_flight : kint64max;
366 VLOG_IF(1, percent > 50)
367 << SENDER_SSRC
368 << duration_in_flight.InMicroseconds() << " usec in-flight + "
369 << frame_duration.InMicroseconds() << " usec for next frame --> "
370 << percent << "% of allowed in-flight.";
371 }
372 if (duration_would_be_in_flight > allowed_in_flight) {
373 VLOG(1) << SENDER_SSRC << "Dropping: In-flight duration would be too high.";
374 return true;
375 }
376
377 // Next frame is accepted.
378 return false;
333 } 379 }
334 380
335 } // namespace cast 381 } // namespace cast
336 } // namespace media 382 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698