OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/video_sender/video_sender.h" | 5 #include "media/cast/video_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 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
249 | 249 |
250 void VideoSender::ResendCheck() { | 250 void VideoSender::ResendCheck() { |
251 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 251 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
252 DCHECK(!last_send_time_.is_null()); | 252 DCHECK(!last_send_time_.is_null()); |
253 const base::TimeDelta time_since_last_send = | 253 const base::TimeDelta time_since_last_send = |
254 cast_environment_->Clock()->NowTicks() - last_send_time_; | 254 cast_environment_->Clock()->NowTicks() - last_send_time_; |
255 if (time_since_last_send > target_playout_delay_) { | 255 if (time_since_last_send > target_playout_delay_) { |
256 if (latest_acked_frame_id_ == last_sent_frame_id_) { | 256 if (latest_acked_frame_id_ == last_sent_frame_id_) { |
257 // Last frame acked, no point in doing anything | 257 // Last frame acked, no point in doing anything |
258 } else { | 258 } else { |
259 const uint32 kickstart_frame_id = latest_acked_frame_id_ + 1; | 259 VLOG(1) << "ACK timeout; last acked frame: " << latest_acked_frame_id_; |
260 VLOG(1) << "ACK timeout, re-sending frame " << kickstart_frame_id; | 260 ResendForKickstart(); |
261 ResendFrame(kickstart_frame_id); | |
262 } | 261 } |
263 } | 262 } |
264 ScheduleNextResendCheck(); | 263 ScheduleNextResendCheck(); |
265 } | 264 } |
266 | 265 |
267 void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { | 266 void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { |
268 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 267 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
269 | 268 |
270 base::TimeDelta rtt; | 269 base::TimeDelta rtt; |
271 base::TimeDelta avg_rtt; | 270 base::TimeDelta avg_rtt; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
303 } | 302 } |
304 // We only count duplicate ACKs when we have sent newer frames. | 303 // We only count duplicate ACKs when we have sent newer frames. |
305 if (latest_acked_frame_id_ == cast_feedback.ack_frame_id_ && | 304 if (latest_acked_frame_id_ == cast_feedback.ack_frame_id_ && |
306 latest_acked_frame_id_ != last_sent_frame_id_) { | 305 latest_acked_frame_id_ != last_sent_frame_id_) { |
307 duplicate_ack_counter_++; | 306 duplicate_ack_counter_++; |
308 } else { | 307 } else { |
309 duplicate_ack_counter_ = 0; | 308 duplicate_ack_counter_ = 0; |
310 } | 309 } |
311 // TODO(miu): The values "2" and "3" should be derived from configuration. | 310 // TODO(miu): The values "2" and "3" should be derived from configuration. |
312 if (duplicate_ack_counter_ >= 2 && duplicate_ack_counter_ % 3 == 2) { | 311 if (duplicate_ack_counter_ >= 2 && duplicate_ack_counter_ % 3 == 2) { |
313 // Resend last ACK + 1 frame. | 312 VLOG(1) << "Received duplicate ACK for frame " << latest_acked_frame_id_; |
314 const uint32 frame_to_resend = latest_acked_frame_id_ + 1; | 313 ResendForKickstart(); |
315 VLOG(1) << "Received duplicate ACK for frame " << latest_acked_frame_id_ | |
316 << ", will re-send frame " << frame_to_resend; | |
317 ResendFrame(frame_to_resend); | |
318 } | 314 } |
319 } else { | 315 } else { |
316 // Only count duplicated ACKs if there is no NACK request in between. | |
317 // This is to avoid aggresive resend. | |
318 duplicate_ack_counter_ = 0; | |
miu
2014/06/07 00:59:42
Good catch! :)
Alpha Left Google
2014/06/07 01:15:10
Done.
| |
320 transport_sender_->ResendPackets( | 319 transport_sender_->ResendPackets( |
321 false, cast_feedback.missing_frames_and_packets_); | 320 false, cast_feedback.missing_frames_and_packets_); |
322 uint32 new_bitrate = 0; | 321 uint32 new_bitrate = 0; |
323 if (congestion_control_.OnNack(rtt, &new_bitrate)) { | 322 if (congestion_control_.OnNack(rtt, &new_bitrate)) { |
324 UpdateBitrate(new_bitrate); | 323 UpdateBitrate(new_bitrate); |
325 } | 324 } |
326 } | 325 } |
327 | 326 |
328 RtpTimestamp rtp_timestamp = | 327 RtpTimestamp rtp_timestamp = |
329 frame_id_to_rtp_timestamp_[cast_feedback.ack_frame_id_ & 0xff]; | 328 frame_id_to_rtp_timestamp_[cast_feedback.ack_frame_id_ & 0xff]; |
(...skipping 17 matching lines...) Expand all Loading... | |
347 frames_in_flight += | 346 frames_in_flight += |
348 static_cast<int32>(last_sent_frame_id_ - latest_acked_frame_id_); | 347 static_cast<int32>(last_sent_frame_id_ - latest_acked_frame_id_); |
349 } | 348 } |
350 VLOG(2) << frames_in_flight | 349 VLOG(2) << frames_in_flight |
351 << " frames in flight; last sent: " << last_sent_frame_id_ | 350 << " frames in flight; last sent: " << last_sent_frame_id_ |
352 << " latest acked: " << latest_acked_frame_id_ | 351 << " latest acked: " << latest_acked_frame_id_ |
353 << " frames in encoder: " << frames_in_encoder_; | 352 << " frames in encoder: " << frames_in_encoder_; |
354 return frames_in_flight >= max_unacked_frames_; | 353 return frames_in_flight >= max_unacked_frames_; |
355 } | 354 } |
356 | 355 |
357 void VideoSender::ResendFrame(uint32 resend_frame_id) { | 356 void VideoSender::ResendForKickstart() { |
358 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 357 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
359 DCHECK(!last_send_time_.is_null()); | 358 DCHECK(!last_send_time_.is_null()); |
359 // Send the first packet of the last encoded frame to kick start | |
miu
2014/06/07 00:59:42
Could you add:
VLOG(1) << "Resending first pack
Alpha Left Google
2014/06/07 01:15:10
Done.
| |
360 // retransmission. This gives enough information to the receiver what | |
361 // packets and frames are missing. | |
360 MissingFramesAndPacketsMap missing_frames_and_packets; | 362 MissingFramesAndPacketsMap missing_frames_and_packets; |
361 PacketIdSet missing; | 363 PacketIdSet missing; |
362 missing_frames_and_packets.insert(std::make_pair(resend_frame_id, missing)); | 364 missing.insert(0); |
365 missing_frames_and_packets.insert( | |
366 std::make_pair(last_sent_frame_id_, missing)); | |
363 last_send_time_ = cast_environment_->Clock()->NowTicks(); | 367 last_send_time_ = cast_environment_->Clock()->NowTicks(); |
364 transport_sender_->ResendPackets(false, missing_frames_and_packets); | 368 transport_sender_->ResendPackets(false, missing_frames_and_packets); |
365 } | 369 } |
366 | 370 |
367 void VideoSender::UpdateBitrate(int new_bitrate) { | 371 void VideoSender::UpdateBitrate(int new_bitrate) { |
368 // Make sure we don't set the bitrate too insanely low. | 372 // Make sure we don't set the bitrate too insanely low. |
369 DCHECK_GT(new_bitrate, 1000); | 373 DCHECK_GT(new_bitrate, 1000); |
370 video_encoder_->SetBitRate(new_bitrate); | 374 video_encoder_->SetBitRate(new_bitrate); |
371 current_requested_bitrate_ = new_bitrate; | 375 current_requested_bitrate_ = new_bitrate; |
372 } | 376 } |
373 | 377 |
374 } // namespace cast | 378 } // namespace cast |
375 } // namespace media | 379 } // namespace media |
OLD | NEW |