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 #include "media/cast/sender/video_sender.h" | 5 #include "media/cast/sender/video_sender.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cstring> | 8 #include <cstring> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
275 } | 275 } |
276 // TODO(miu): The values "2" and "3" should be derived from configuration. | 276 // TODO(miu): The values "2" and "3" should be derived from configuration. |
277 if (duplicate_ack_counter_ >= 2 && duplicate_ack_counter_ % 3 == 2) { | 277 if (duplicate_ack_counter_ >= 2 && duplicate_ack_counter_ % 3 == 2) { |
278 VLOG(1) << "Received duplicate ACK for frame " << latest_acked_frame_id_; | 278 VLOG(1) << "Received duplicate ACK for frame " << latest_acked_frame_id_; |
279 ResendForKickstart(); | 279 ResendForKickstart(); |
280 } | 280 } |
281 } else { | 281 } else { |
282 // Only count duplicated ACKs if there is no NACK request in between. | 282 // Only count duplicated ACKs if there is no NACK request in between. |
283 // This is to avoid aggresive resend. | 283 // This is to avoid aggresive resend. |
284 duplicate_ack_counter_ = 0; | 284 duplicate_ack_counter_ = 0; |
285 | |
286 // A NACK is also used to cancel pending re-transmissions. | |
287 transport_sender_->ResendPackets( | |
288 false, cast_feedback.missing_frames_and_packets, true, rtt); | |
289 } | 285 } |
290 | 286 |
291 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); | 287 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); |
292 congestion_control_.AckFrame(cast_feedback.ack_frame_id, now); | 288 congestion_control_.AckFrame(cast_feedback.ack_frame_id, now); |
293 | 289 |
294 RtpTimestamp rtp_timestamp = | 290 RtpTimestamp rtp_timestamp = |
295 frame_id_to_rtp_timestamp_[cast_feedback.ack_frame_id & 0xff]; | 291 frame_id_to_rtp_timestamp_[cast_feedback.ack_frame_id & 0xff]; |
296 cast_environment_->Logging()->InsertFrameEvent(now, | 292 cast_environment_->Logging()->InsertFrameEvent(now, |
297 FRAME_ACK_RECEIVED, | 293 FRAME_ACK_RECEIVED, |
298 VIDEO_EVENT, | 294 VIDEO_EVENT, |
299 rtp_timestamp, | 295 rtp_timestamp, |
300 cast_feedback.ack_frame_id); | 296 cast_feedback.ack_frame_id); |
301 | 297 |
302 const bool is_acked_out_of_order = | 298 const bool is_acked_out_of_order = |
303 static_cast<int32>(cast_feedback.ack_frame_id - | 299 static_cast<int32>(cast_feedback.ack_frame_id - |
304 latest_acked_frame_id_) < 0; | 300 latest_acked_frame_id_) < 0; |
305 VLOG(2) << "Received ACK" << (is_acked_out_of_order ? " out-of-order" : "") | 301 VLOG(2) << "Received ACK" << (is_acked_out_of_order ? " out-of-order" : "") |
306 << " for frame " << cast_feedback.ack_frame_id; | 302 << " for frame " << cast_feedback.ack_frame_id; |
307 if (!is_acked_out_of_order) { | 303 if (!is_acked_out_of_order) { |
308 // Cancel resends of acked frames. | 304 // Cancel resends of acked frames. |
309 MissingFramesAndPacketsMap missing_frames_and_packets; | 305 std::set<uint32> cancel_sending_frames; |
hubbe
2014/08/11 19:11:50
Seems like a vector would be sufficient here.
| |
310 PacketIdSet missing; | |
311 while (latest_acked_frame_id_ != cast_feedback.ack_frame_id) { | 306 while (latest_acked_frame_id_ != cast_feedback.ack_frame_id) { |
312 latest_acked_frame_id_++; | 307 latest_acked_frame_id_++; |
313 missing_frames_and_packets[latest_acked_frame_id_] = missing; | 308 cancel_sending_frames.insert(latest_acked_frame_id_); |
314 } | 309 } |
315 transport_sender_->ResendPackets( | 310 transport_sender_->CancelSendingFrames(ssrc_, cancel_sending_frames); |
316 false, missing_frames_and_packets, true, rtt); | |
317 latest_acked_frame_id_ = cast_feedback.ack_frame_id; | 311 latest_acked_frame_id_ = cast_feedback.ack_frame_id; |
318 } | 312 } |
319 } | 313 } |
320 | 314 |
321 bool VideoSender::AreTooManyFramesInFlight() const { | 315 bool VideoSender::AreTooManyFramesInFlight() const { |
322 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 316 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
323 int frames_in_flight = frames_in_encoder_; | 317 int frames_in_flight = frames_in_encoder_; |
324 if (!last_send_time_.is_null()) { | 318 if (!last_send_time_.is_null()) { |
325 frames_in_flight += | 319 frames_in_flight += |
326 static_cast<int32>(last_sent_frame_id_ - latest_acked_frame_id_); | 320 static_cast<int32>(last_sent_frame_id_ - latest_acked_frame_id_); |
327 } | 321 } |
328 VLOG(2) << frames_in_flight | 322 VLOG(2) << frames_in_flight |
329 << " frames in flight; last sent: " << last_sent_frame_id_ | 323 << " frames in flight; last sent: " << last_sent_frame_id_ |
330 << " latest acked: " << latest_acked_frame_id_ | 324 << " latest acked: " << latest_acked_frame_id_ |
331 << " frames in encoder: " << frames_in_encoder_; | 325 << " frames in encoder: " << frames_in_encoder_; |
332 return frames_in_flight >= max_unacked_frames_; | 326 return frames_in_flight >= max_unacked_frames_; |
333 } | 327 } |
334 | 328 |
335 void VideoSender::ResendForKickstart() { | 329 void VideoSender::ResendForKickstart() { |
336 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 330 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
337 DCHECK(!last_send_time_.is_null()); | 331 DCHECK(!last_send_time_.is_null()); |
338 VLOG(1) << "Resending last packet of frame " << last_sent_frame_id_ | 332 VLOG(1) << "Resending last packet of frame " << last_sent_frame_id_ |
339 << " to kick-start."; | 333 << " to kick-start."; |
340 // Send the first packet of the last encoded frame to kick start | |
341 // retransmission. This gives enough information to the receiver what | |
342 // packets and frames are missing. | |
343 MissingFramesAndPacketsMap missing_frames_and_packets; | |
344 PacketIdSet missing; | |
345 missing.insert(kRtcpCastLastPacket); | |
346 missing_frames_and_packets.insert( | |
347 std::make_pair(last_sent_frame_id_, missing)); | |
348 last_send_time_ = cast_environment_->Clock()->NowTicks(); | 334 last_send_time_ = cast_environment_->Clock()->NowTicks(); |
349 | 335 transport_sender_->ResendFrameForKickstart(ssrc_, last_sent_frame_id_); |
350 // Sending this extra packet is to kick-start the session. There is | |
351 // no need to optimize re-transmission for this case. | |
352 transport_sender_->ResendPackets(false, missing_frames_and_packets, | |
353 false, rtt_); | |
354 } | 336 } |
355 | 337 |
356 } // namespace cast | 338 } // namespace cast |
357 } // namespace media | 339 } // namespace media |
OLD | NEW |