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::vector<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.push_back(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 |