| 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 #include "base/debug/trace_event.h" | 7 #include "base/debug/trace_event.h" |
| 8 | 8 |
| 9 namespace media { | 9 namespace media { |
| 10 namespace cast { | 10 namespace cast { |
| 11 namespace { | 11 namespace { |
| 12 | 12 |
| 13 const int kMinSchedulingDelayMs = 1; | 13 const int kMinSchedulingDelayMs = 1; |
| 14 const int kNumAggressiveReportsSentAtStart = 100; | 14 const int kNumAggressiveReportsSentAtStart = 100; |
| 15 | 15 |
| 16 } // namespace | 16 } // namespace |
| 17 | 17 |
| 18 FrameSender::FrameSender(scoped_refptr<CastEnvironment> cast_environment, | 18 FrameSender::FrameSender(scoped_refptr<CastEnvironment> cast_environment, |
| 19 bool is_audio, | 19 bool is_audio, |
| 20 CastTransportSender* const transport_sender, | 20 CastTransportSender* const transport_sender, |
| 21 base::TimeDelta rtcp_interval, | 21 base::TimeDelta rtcp_interval, |
| 22 int rtp_timebase, | 22 int rtp_timebase, |
| 23 uint32 ssrc, | 23 uint32 ssrc, |
| 24 double max_frame_rate, | 24 double max_frame_rate, |
| 25 base::TimeDelta playout_delay, | 25 base::TimeDelta playout_delay, |
| 26 CongestionControl* congestion_control) | 26 CongestionControl* congestion_control) |
| 27 : cast_environment_(cast_environment), | 27 : cast_environment_(cast_environment), |
| 28 transport_sender_(transport_sender), | 28 transport_sender_(transport_sender), |
| 29 ssrc_(ssrc), | 29 ssrc_(ssrc), |
| 30 rtt_available_(false), | |
| 31 rtcp_interval_(rtcp_interval), | 30 rtcp_interval_(rtcp_interval), |
| 32 max_frame_rate_(max_frame_rate), | 31 max_frame_rate_(max_frame_rate), |
| 33 frames_in_encoder_(0), | 32 frames_in_encoder_(0), |
| 34 num_aggressive_rtcp_reports_sent_(0), | 33 num_aggressive_rtcp_reports_sent_(0), |
| 35 last_sent_frame_id_(0), | 34 last_sent_frame_id_(0), |
| 36 latest_acked_frame_id_(0), | 35 latest_acked_frame_id_(0), |
| 37 duplicate_ack_counter_(0), | 36 duplicate_ack_counter_(0), |
| 38 rtp_timebase_(rtp_timebase), | 37 rtp_timebase_(rtp_timebase), |
| 39 congestion_control_(congestion_control), | 38 congestion_control_(congestion_control), |
| 40 is_audio_(is_audio), | 39 is_audio_(is_audio), |
| 41 weak_factory_(this) { | 40 weak_factory_(this) { |
| 41 DCHECK(transport_sender_); |
| 42 DCHECK_GT(rtp_timebase_, 0); | 42 DCHECK_GT(rtp_timebase_, 0); |
| 43 DCHECK(congestion_control_); |
| 43 SetTargetPlayoutDelay(playout_delay); | 44 SetTargetPlayoutDelay(playout_delay); |
| 44 send_target_playout_delay_ = false; | 45 send_target_playout_delay_ = false; |
| 45 memset(frame_rtp_timestamps_, 0, sizeof(frame_rtp_timestamps_)); | 46 memset(frame_rtp_timestamps_, 0, sizeof(frame_rtp_timestamps_)); |
| 46 } | 47 } |
| 47 | 48 |
| 48 FrameSender::~FrameSender() { | 49 FrameSender::~FrameSender() { |
| 49 } | 50 } |
| 50 | 51 |
| 51 void FrameSender::ScheduleNextRtcpReport() { | 52 void FrameSender::ScheduleNextRtcpReport() { |
| 52 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 53 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 81 const int64 rtp_delta = TimeDeltaToRtpDelta(time_delta, rtp_timebase_); | 82 const int64 rtp_delta = TimeDeltaToRtpDelta(time_delta, rtp_timebase_); |
| 82 const uint32 now_as_rtp_timestamp = | 83 const uint32 now_as_rtp_timestamp = |
| 83 GetRecordedRtpTimestamp(last_sent_frame_id_) + | 84 GetRecordedRtpTimestamp(last_sent_frame_id_) + |
| 84 static_cast<uint32>(rtp_delta); | 85 static_cast<uint32>(rtp_delta); |
| 85 transport_sender_->SendSenderReport(ssrc_, now, now_as_rtp_timestamp); | 86 transport_sender_->SendSenderReport(ssrc_, now, now_as_rtp_timestamp); |
| 86 | 87 |
| 87 if (schedule_future_reports) | 88 if (schedule_future_reports) |
| 88 ScheduleNextRtcpReport(); | 89 ScheduleNextRtcpReport(); |
| 89 } | 90 } |
| 90 | 91 |
| 91 void FrameSender::OnReceivedRtt(base::TimeDelta rtt, | 92 void FrameSender::OnMeasuredRoundTripTime(base::TimeDelta rtt) { |
| 92 base::TimeDelta avg_rtt, | 93 DCHECK(rtt > base::TimeDelta()); |
| 93 base::TimeDelta min_rtt, | 94 current_round_trip_time_ = rtt; |
| 94 base::TimeDelta max_rtt) { | |
| 95 rtt_available_ = true; | |
| 96 rtt_ = rtt; | |
| 97 avg_rtt_ = avg_rtt; | |
| 98 min_rtt_ = min_rtt; | |
| 99 max_rtt_ = max_rtt; | |
| 100 } | 95 } |
| 101 | 96 |
| 102 void FrameSender::SetTargetPlayoutDelay( | 97 void FrameSender::SetTargetPlayoutDelay( |
| 103 base::TimeDelta new_target_playout_delay) { | 98 base::TimeDelta new_target_playout_delay) { |
| 104 target_playout_delay_ = new_target_playout_delay; | 99 target_playout_delay_ = new_target_playout_delay; |
| 105 max_unacked_frames_ = | 100 max_unacked_frames_ = |
| 106 std::min(kMaxUnackedFrames, | 101 std::min(kMaxUnackedFrames, |
| 107 1 + static_cast<int>(target_playout_delay_ * | 102 1 + static_cast<int>(target_playout_delay_ * |
| 108 max_frame_rate_ / | 103 max_frame_rate_ / |
| 109 base::TimeDelta::FromSeconds(1))); | 104 base::TimeDelta::FromSeconds(1))); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 if (send_target_playout_delay_) { | 229 if (send_target_playout_delay_) { |
| 235 encoded_frame->new_playout_delay_ms = | 230 encoded_frame->new_playout_delay_ms = |
| 236 target_playout_delay_.InMilliseconds(); | 231 target_playout_delay_.InMilliseconds(); |
| 237 } | 232 } |
| 238 transport_sender_->InsertFrame(ssrc_, *encoded_frame); | 233 transport_sender_->InsertFrame(ssrc_, *encoded_frame); |
| 239 } | 234 } |
| 240 | 235 |
| 241 void FrameSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { | 236 void FrameSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { |
| 242 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); | 237 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); |
| 243 | 238 |
| 244 base::TimeDelta rtt; | 239 const bool have_valid_rtt = current_round_trip_time_ > base::TimeDelta(); |
| 245 base::TimeDelta avg_rtt; | 240 if (have_valid_rtt) { |
| 246 base::TimeDelta min_rtt; | 241 congestion_control_->UpdateRtt(current_round_trip_time_); |
| 247 base::TimeDelta max_rtt; | |
| 248 if (is_rtt_available()) { | |
| 249 rtt = rtt_; | |
| 250 avg_rtt = avg_rtt_; | |
| 251 min_rtt = min_rtt_; | |
| 252 max_rtt = max_rtt_; | |
| 253 | 242 |
| 254 congestion_control_->UpdateRtt(rtt); | 243 // Having the RTT value implies the receiver sent back a receiver report |
| 255 | |
| 256 // Don't use a RTT lower than our average. | |
| 257 rtt = std::max(rtt, avg_rtt); | |
| 258 | |
| 259 // Having the RTT values implies the receiver sent back a receiver report | |
| 260 // based on it having received a report from here. Therefore, ensure this | 244 // based on it having received a report from here. Therefore, ensure this |
| 261 // sender stops aggressively sending reports. | 245 // sender stops aggressively sending reports. |
| 262 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { | 246 if (num_aggressive_rtcp_reports_sent_ < kNumAggressiveReportsSentAtStart) { |
| 263 VLOG(1) << "No longer a need to send reports aggressively (sent " | 247 VLOG(1) << "No longer a need to send reports aggressively (sent " |
| 264 << num_aggressive_rtcp_reports_sent_ << ")."; | 248 << num_aggressive_rtcp_reports_sent_ << ")."; |
| 265 num_aggressive_rtcp_reports_sent_ = kNumAggressiveReportsSentAtStart; | 249 num_aggressive_rtcp_reports_sent_ = kNumAggressiveReportsSentAtStart; |
| 266 ScheduleNextRtcpReport(); | 250 ScheduleNextRtcpReport(); |
| 267 } | 251 } |
| 268 } else { | |
| 269 // We have no measured value use default. | |
| 270 rtt = base::TimeDelta::FromMilliseconds(kStartRttMs); | |
| 271 } | 252 } |
| 272 | 253 |
| 273 if (last_send_time_.is_null()) | 254 if (last_send_time_.is_null()) |
| 274 return; // Cannot get an ACK without having first sent a frame. | 255 return; // Cannot get an ACK without having first sent a frame. |
| 275 | 256 |
| 276 if (cast_feedback.missing_frames_and_packets.empty()) { | 257 if (cast_feedback.missing_frames_and_packets.empty()) { |
| 277 OnAck(cast_feedback.ack_frame_id); | 258 OnAck(cast_feedback.ack_frame_id); |
| 278 | 259 |
| 279 // We only count duplicate ACKs when we have sent newer frames. | 260 // We only count duplicate ACKs when we have sent newer frames. |
| 280 if (latest_acked_frame_id_ == cast_feedback.ack_frame_id && | 261 if (latest_acked_frame_id_ == cast_feedback.ack_frame_id && |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 << duration_in_flight.InMicroseconds() << " usec (" | 324 << duration_in_flight.InMicroseconds() << " usec (" |
| 344 << (target_playout_delay_ > base::TimeDelta() ? | 325 << (target_playout_delay_ > base::TimeDelta() ? |
| 345 100 * duration_in_flight / target_playout_delay_ : | 326 100 * duration_in_flight / target_playout_delay_ : |
| 346 kint64max) << "%)"; | 327 kint64max) << "%)"; |
| 347 return frames_in_flight >= max_unacked_frames_ || | 328 return frames_in_flight >= max_unacked_frames_ || |
| 348 duration_in_flight >= target_playout_delay_; | 329 duration_in_flight >= target_playout_delay_; |
| 349 } | 330 } |
| 350 | 331 |
| 351 } // namespace cast | 332 } // namespace cast |
| 352 } // namespace media | 333 } // namespace media |
| OLD | NEW |