Chromium Code Reviews| 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 |