| 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 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 } | 301 } |
| 302 // TODO(miu): The values "2" and "3" should be derived from configuration. | 302 // TODO(miu): The values "2" and "3" should be derived from configuration. |
| 303 if (duplicate_ack_counter_ >= 2 && duplicate_ack_counter_ % 3 == 2) { | 303 if (duplicate_ack_counter_ >= 2 && duplicate_ack_counter_ % 3 == 2) { |
| 304 VLOG(1) << "Received duplicate ACK for frame " << latest_acked_frame_id_; | 304 VLOG(1) << "Received duplicate ACK for frame " << latest_acked_frame_id_; |
| 305 ResendForKickstart(); | 305 ResendForKickstart(); |
| 306 } | 306 } |
| 307 } else { | 307 } else { |
| 308 // Only count duplicated ACKs if there is no NACK request in between. | 308 // Only count duplicated ACKs if there is no NACK request in between. |
| 309 // This is to avoid aggresive resend. | 309 // This is to avoid aggresive resend. |
| 310 duplicate_ack_counter_ = 0; | 310 duplicate_ack_counter_ = 0; |
| 311 | |
| 312 // A NACK is also used to cancel pending re-transmissions. | |
| 313 transport_sender_->ResendPackets( | |
| 314 false, cast_feedback.missing_frames_and_packets, true, rtt); | |
| 315 } | 311 } |
| 316 | 312 |
| 317 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); | 313 base::TimeTicks now = cast_environment_->Clock()->NowTicks(); |
| 318 congestion_control_.AckFrame(cast_feedback.ack_frame_id, now); | 314 congestion_control_.AckFrame(cast_feedback.ack_frame_id, now); |
| 319 | 315 |
| 320 RtpTimestamp rtp_timestamp = | 316 RtpTimestamp rtp_timestamp = |
| 321 frame_id_to_rtp_timestamp_[cast_feedback.ack_frame_id & 0xff]; | 317 frame_id_to_rtp_timestamp_[cast_feedback.ack_frame_id & 0xff]; |
| 322 cast_environment_->Logging()->InsertFrameEvent(now, | 318 cast_environment_->Logging()->InsertFrameEvent(now, |
| 323 FRAME_ACK_RECEIVED, | 319 FRAME_ACK_RECEIVED, |
| 324 VIDEO_EVENT, | 320 VIDEO_EVENT, |
| 325 rtp_timestamp, | 321 rtp_timestamp, |
| 326 cast_feedback.ack_frame_id); | 322 cast_feedback.ack_frame_id); |
| 327 | 323 |
| 328 const bool is_acked_out_of_order = | 324 const bool is_acked_out_of_order = |
| 329 static_cast<int32>(cast_feedback.ack_frame_id - | 325 static_cast<int32>(cast_feedback.ack_frame_id - |
| 330 latest_acked_frame_id_) < 0; | 326 latest_acked_frame_id_) < 0; |
| 331 VLOG(2) << "Received ACK" << (is_acked_out_of_order ? " out-of-order" : "") | 327 VLOG(2) << "Received ACK" << (is_acked_out_of_order ? " out-of-order" : "") |
| 332 << " for frame " << cast_feedback.ack_frame_id; | 328 << " for frame " << cast_feedback.ack_frame_id; |
| 333 if (!is_acked_out_of_order) { | 329 if (!is_acked_out_of_order) { |
| 334 // Cancel resends of acked frames. | 330 // Cancel resends of acked frames. |
| 335 MissingFramesAndPacketsMap missing_frames_and_packets; | 331 std::set<uint32> cancel_sending_frames; |
| 336 PacketIdSet missing; | |
| 337 while (latest_acked_frame_id_ != cast_feedback.ack_frame_id) { | 332 while (latest_acked_frame_id_ != cast_feedback.ack_frame_id) { |
| 338 latest_acked_frame_id_++; | 333 latest_acked_frame_id_++; |
| 339 missing_frames_and_packets[latest_acked_frame_id_] = missing; | 334 cancel_sending_frames.insert(latest_acked_frame_id_); |
| 340 } | 335 } |
| 341 transport_sender_->ResendPackets( | 336 transport_sender_->CancelSendingFrames(ssrc_, cancel_sending_frames); |
| 342 false, missing_frames_and_packets, true, rtt); | |
| 343 latest_acked_frame_id_ = cast_feedback.ack_frame_id; | 337 latest_acked_frame_id_ = cast_feedback.ack_frame_id; |
| 344 } | 338 } |
| 345 } | 339 } |
| 346 | 340 |
| 347 bool VideoSender::AreTooManyFramesInFlight() const { | 341 bool VideoSender::AreTooManyFramesInFlight() const { |
| 348 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 342 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 349 int frames_in_flight = frames_in_encoder_; | 343 int frames_in_flight = frames_in_encoder_; |
| 350 if (!last_send_time_.is_null()) { | 344 if (!last_send_time_.is_null()) { |
| 351 frames_in_flight += | 345 frames_in_flight += |
| 352 static_cast<int32>(last_sent_frame_id_ - latest_acked_frame_id_); | 346 static_cast<int32>(last_sent_frame_id_ - latest_acked_frame_id_); |
| 353 } | 347 } |
| 354 VLOG(2) << frames_in_flight | 348 VLOG(2) << frames_in_flight |
| 355 << " frames in flight; last sent: " << last_sent_frame_id_ | 349 << " frames in flight; last sent: " << last_sent_frame_id_ |
| 356 << " latest acked: " << latest_acked_frame_id_ | 350 << " latest acked: " << latest_acked_frame_id_ |
| 357 << " frames in encoder: " << frames_in_encoder_; | 351 << " frames in encoder: " << frames_in_encoder_; |
| 358 return frames_in_flight >= max_unacked_frames_; | 352 return frames_in_flight >= max_unacked_frames_; |
| 359 } | 353 } |
| 360 | 354 |
| 361 void VideoSender::ResendForKickstart() { | 355 void VideoSender::ResendForKickstart() { |
| 362 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 356 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 363 DCHECK(!last_send_time_.is_null()); | 357 DCHECK(!last_send_time_.is_null()); |
| 364 VLOG(1) << "Resending last packet of frame " << last_sent_frame_id_ | 358 VLOG(1) << "Resending last packet of frame " << last_sent_frame_id_ |
| 365 << " to kick-start."; | 359 << " to kick-start."; |
| 366 // Send the first packet of the last encoded frame to kick start | |
| 367 // retransmission. This gives enough information to the receiver what | |
| 368 // packets and frames are missing. | |
| 369 MissingFramesAndPacketsMap missing_frames_and_packets; | |
| 370 PacketIdSet missing; | |
| 371 missing.insert(kRtcpCastLastPacket); | |
| 372 missing_frames_and_packets.insert( | |
| 373 std::make_pair(last_sent_frame_id_, missing)); | |
| 374 last_send_time_ = cast_environment_->Clock()->NowTicks(); | 360 last_send_time_ = cast_environment_->Clock()->NowTicks(); |
| 375 | 361 transport_sender_->ResendFrameForKickstart(ssrc_, last_sent_frame_id_); |
| 376 // Sending this extra packet is to kick-start the session. There is | |
| 377 // no need to optimize re-transmission for this case. | |
| 378 transport_sender_->ResendPackets(false, missing_frames_and_packets, | |
| 379 false, rtt_); | |
| 380 } | 362 } |
| 381 | 363 |
| 382 } // namespace cast | 364 } // namespace cast |
| 383 } // namespace media | 365 } // namespace media |
| OLD | NEW |