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/frame_sender.h" | 5 #include "media/cast/sender/frame_sender.h" |
6 | 6 |
7 namespace media { | 7 namespace media { |
8 namespace cast { | 8 namespace cast { |
9 namespace { | 9 namespace { |
10 const int kMinSchedulingDelayMs = 1; | 10 const int kMinSchedulingDelayMs = 1; |
11 } // namespace | 11 } // namespace |
12 | 12 |
13 FrameSender::FrameSender(scoped_refptr<CastEnvironment> cast_environment, | 13 FrameSender::FrameSender(scoped_refptr<CastEnvironment> cast_environment, |
14 CastTransportSender* const transport_sender, | 14 CastTransportSender* const transport_sender, |
15 base::TimeDelta rtcp_interval, | 15 base::TimeDelta rtcp_interval, |
16 int frequency, | 16 int frequency, |
17 uint32 ssrc, | 17 uint32 ssrc, |
18 double max_frame_rate, | 18 double max_frame_rate, |
19 base::TimeDelta playout_delay) | 19 base::TimeDelta playout_delay) |
20 : cast_environment_(cast_environment), | 20 : cast_environment_(cast_environment), |
21 transport_sender_(transport_sender), | 21 transport_sender_(transport_sender), |
22 ssrc_(ssrc), | 22 ssrc_(ssrc), |
23 rtp_timestamp_helper_(frequency), | 23 rtp_timestamp_helper_(frequency), |
24 rtt_available_(false), | 24 rtt_available_(false), |
25 rtcp_interval_(rtcp_interval), | 25 rtcp_interval_(rtcp_interval), |
26 max_frame_rate_(max_frame_rate), | 26 max_frame_rate_(max_frame_rate), |
| 27 num_aggressive_rtcp_reports_sent_(0), |
| 28 last_sent_frame_id_(0), |
| 29 latest_acked_frame_id_(0), |
| 30 duplicate_ack_counter_(0), |
27 weak_factory_(this) { | 31 weak_factory_(this) { |
28 SetTargetPlayoutDelay(playout_delay); | 32 SetTargetPlayoutDelay(playout_delay); |
29 send_target_playout_delay_ = false; | 33 send_target_playout_delay_ = false; |
| 34 memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_)); |
30 } | 35 } |
31 | 36 |
32 FrameSender::~FrameSender() { | 37 FrameSender::~FrameSender() { |
33 } | 38 } |
34 | 39 |
35 void FrameSender::ScheduleNextRtcpReport() { | 40 void FrameSender::ScheduleNextRtcpReport() { |
36 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 41 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
37 base::TimeDelta time_to_next = rtcp_interval_; | 42 base::TimeDelta time_to_next = rtcp_interval_; |
38 | 43 |
39 time_to_next = std::max( | 44 time_to_next = std::max( |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 base::TimeDelta new_target_playout_delay) { | 82 base::TimeDelta new_target_playout_delay) { |
78 target_playout_delay_ = new_target_playout_delay; | 83 target_playout_delay_ = new_target_playout_delay; |
79 max_unacked_frames_ = | 84 max_unacked_frames_ = |
80 std::min(kMaxUnackedFrames, | 85 std::min(kMaxUnackedFrames, |
81 1 + static_cast<int>(target_playout_delay_ * | 86 1 + static_cast<int>(target_playout_delay_ * |
82 max_frame_rate_ / | 87 max_frame_rate_ / |
83 base::TimeDelta::FromSeconds(1))); | 88 base::TimeDelta::FromSeconds(1))); |
84 send_target_playout_delay_ = true; | 89 send_target_playout_delay_ = true; |
85 } | 90 } |
86 | 91 |
| 92 void FrameSender::ResendCheck() { |
| 93 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 94 DCHECK(!last_send_time_.is_null()); |
| 95 const base::TimeDelta time_since_last_send = |
| 96 cast_environment_->Clock()->NowTicks() - last_send_time_; |
| 97 if (time_since_last_send > target_playout_delay_) { |
| 98 if (latest_acked_frame_id_ == last_sent_frame_id_) { |
| 99 // Last frame acked, no point in doing anything |
| 100 } else { |
| 101 VLOG(1) << "ACK timeout; last acked frame: " << latest_acked_frame_id_; |
| 102 ResendForKickstart(); |
| 103 } |
| 104 } |
| 105 ScheduleNextResendCheck(); |
| 106 } |
| 107 |
| 108 void FrameSender::ScheduleNextResendCheck() { |
| 109 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 110 DCHECK(!last_send_time_.is_null()); |
| 111 base::TimeDelta time_to_next = |
| 112 last_send_time_ - cast_environment_->Clock()->NowTicks() + |
| 113 target_playout_delay_; |
| 114 time_to_next = std::max( |
| 115 time_to_next, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); |
| 116 cast_environment_->PostDelayedTask( |
| 117 CastEnvironment::MAIN, |
| 118 FROM_HERE, |
| 119 base::Bind(&FrameSender::ResendCheck, weak_factory_.GetWeakPtr()), |
| 120 time_to_next); |
| 121 } |
| 122 |
| 123 void FrameSender::ResendForKickstart() { |
| 124 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 125 DCHECK(!last_send_time_.is_null()); |
| 126 VLOG(1) << "Resending last packet of frame " << last_sent_frame_id_ |
| 127 << " to kick-start."; |
| 128 last_send_time_ = cast_environment_->Clock()->NowTicks(); |
| 129 transport_sender_->ResendFrameForKickstart(ssrc_, last_sent_frame_id_); |
| 130 } |
| 131 |
87 } // namespace cast | 132 } // namespace cast |
88 } // namespace media | 133 } // namespace media |
OLD | NEW |