Index: media/cast/video_sender/video_sender.cc |
diff --git a/media/cast/video_sender/video_sender.cc b/media/cast/video_sender/video_sender.cc |
index 928360b6cc538bb4488ead534225a18b9c929c01..f228c1b3d1af1cedc5d376e41b690a5345132a79 100644 |
--- a/media/cast/video_sender/video_sender.cc |
+++ b/media/cast/video_sender/video_sender.cc |
@@ -256,9 +256,8 @@ void VideoSender::ResendCheck() { |
if (latest_acked_frame_id_ == last_sent_frame_id_) { |
// Last frame acked, no point in doing anything |
} else { |
- const uint32 kickstart_frame_id = latest_acked_frame_id_ + 1; |
- VLOG(1) << "ACK timeout, re-sending frame " << kickstart_frame_id; |
- ResendFrame(kickstart_frame_id); |
+ VLOG(1) << "ACK timeout; last acked frame: " << latest_acked_frame_id_; |
+ ResendForKickstart(); |
} |
} |
ScheduleNextResendCheck(); |
@@ -310,13 +309,13 @@ void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { |
} |
// TODO(miu): The values "2" and "3" should be derived from configuration. |
if (duplicate_ack_counter_ >= 2 && duplicate_ack_counter_ % 3 == 2) { |
- // Resend last ACK + 1 frame. |
- const uint32 frame_to_resend = latest_acked_frame_id_ + 1; |
- VLOG(1) << "Received duplicate ACK for frame " << latest_acked_frame_id_ |
- << ", will re-send frame " << frame_to_resend; |
- ResendFrame(frame_to_resend); |
+ VLOG(1) << "Received duplicate ACK for frame " << latest_acked_frame_id_; |
+ ResendForKickstart(); |
} |
} else { |
+ // Only count duplicated ACKs if there is no NACK request in between. |
+ // This is to avoid aggresive resend. |
+ duplicate_ack_counter_ = 0; |
transport_sender_->ResendPackets( |
false, cast_feedback.missing_frames_and_packets_); |
uint32 new_bitrate = 0; |
@@ -354,12 +353,19 @@ bool VideoSender::AreTooManyFramesInFlight() const { |
return frames_in_flight >= max_unacked_frames_; |
} |
-void VideoSender::ResendFrame(uint32 resend_frame_id) { |
+void VideoSender::ResendForKickstart() { |
DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
DCHECK(!last_send_time_.is_null()); |
+ VLOG(1) << "Resending first packet of frame " << last_sent_frame_id_ |
+ << " to kick-start."; |
+ // Send the first packet of the last encoded frame to kick start |
+ // retransmission. This gives enough information to the receiver what |
+ // packets and frames are missing. |
MissingFramesAndPacketsMap missing_frames_and_packets; |
PacketIdSet missing; |
- missing_frames_and_packets.insert(std::make_pair(resend_frame_id, missing)); |
+ missing.insert(0); |
+ missing_frames_and_packets.insert( |
+ std::make_pair(last_sent_frame_id_, missing)); |
last_send_time_ = cast_environment_->Clock()->NowTicks(); |
transport_sender_->ResendPackets(false, missing_frames_and_packets); |
} |