OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "base/big_endian.h" |
| 6 #include "base/time/tick_clock.h" |
| 7 #include "media/cast/net/pacing/paced_sender.h" |
| 8 #include "media/cast/net/rtcp/receiver_rtcp_session.h" |
| 9 #include "media/cast/net/rtcp/rtcp_builder.h" |
| 10 #include "media/cast/net/rtcp/rtcp_defines.h" |
| 11 #include "media/cast/net/rtcp/rtcp_utility.h" |
| 12 |
| 13 namespace media { |
| 14 namespace cast { |
| 15 |
| 16 namespace { |
| 17 |
| 18 // Create a NTP diff from seconds and fractions of seconds; delay_fraction is |
| 19 // fractions of a second where 0x80000000 is half a second. |
| 20 uint32_t ConvertToNtpDiff(uint32_t delay_seconds, uint32_t delay_fraction) { |
| 21 return ((delay_seconds & 0x0000FFFF) << 16) + |
| 22 ((delay_fraction & 0xFFFF0000) >> 16); |
| 23 } |
| 24 |
| 25 } // namespace |
| 26 |
| 27 ReceiverRtcpSession::ReceiverRtcpSession(base::TickClock* clock, |
| 28 PacedPacketSender* packet_sender, |
| 29 uint32_t local_ssrc, |
| 30 uint32_t remote_ssrc) |
| 31 : clock_(clock), |
| 32 packet_sender_(packet_sender), |
| 33 local_ssrc_(local_ssrc), |
| 34 remote_ssrc_(remote_ssrc), |
| 35 last_report_truncated_ntp_(0), |
| 36 local_clock_ahead_by_(ClockDriftSmoother::GetDefaultTimeConstant()), |
| 37 lip_sync_ntp_timestamp_(0), |
| 38 parser_(local_ssrc, remote_ssrc) {} |
| 39 |
| 40 ReceiverRtcpSession::~ReceiverRtcpSession() {} |
| 41 |
| 42 bool ReceiverRtcpSession::IncomingRtcpPacket(const uint8_t* data, |
| 43 size_t length) { |
| 44 // Check if this is a valid RTCP packet. |
| 45 if (!IsRtcpPacket(data, length)) { |
| 46 VLOG(1) << "Rtcp@" << this << "::IncomingRtcpPacket() -- " |
| 47 << "Received an invalid (non-RTCP?) packet."; |
| 48 return false; |
| 49 } |
| 50 |
| 51 // Check if this packet is to us. |
| 52 uint32_t ssrc_of_sender = GetSsrcOfSender(data, length); |
| 53 if (ssrc_of_sender != remote_ssrc_) { |
| 54 return false; |
| 55 } |
| 56 |
| 57 // Parse this packet. |
| 58 base::BigEndianReader reader(reinterpret_cast<const char*>(data), length); |
| 59 if (parser_.Parse(&reader)) { |
| 60 if (parser_.has_sender_report()) { |
| 61 OnReceivedNtp(parser_.sender_report().ntp_seconds, |
| 62 parser_.sender_report().ntp_fraction); |
| 63 OnReceivedLipSyncInfo(parser_.sender_report().rtp_timestamp, |
| 64 parser_.sender_report().ntp_seconds, |
| 65 parser_.sender_report().ntp_fraction); |
| 66 } |
| 67 } |
| 68 return true; |
| 69 } |
| 70 |
| 71 void ReceiverRtcpSession::OnReceivedNtp(uint32_t ntp_seconds, |
| 72 uint32_t ntp_fraction) { |
| 73 last_report_truncated_ntp_ = ConvertToNtpDiff(ntp_seconds, ntp_fraction); |
| 74 |
| 75 const base::TimeTicks now = clock_->NowTicks(); |
| 76 time_last_report_received_ = now; |
| 77 |
| 78 // TODO(miu): This clock offset calculation does not account for packet |
| 79 // transit time over the network. End2EndTest.EvilNetwork confirms that this |
| 80 // contributes a very significant source of error here. Determine whether |
| 81 // RTT should be factored-in, and how that changes the rest of the |
| 82 // calculation. |
| 83 const base::TimeDelta measured_offset = |
| 84 now - ConvertNtpToTimeTicks(ntp_seconds, ntp_fraction); |
| 85 local_clock_ahead_by_.Update(now, measured_offset); |
| 86 if (measured_offset < local_clock_ahead_by_.Current()) { |
| 87 // Logically, the minimum offset between the clocks has to be the correct |
| 88 // one. For example, the time it took to transmit the current report may |
| 89 // have been lower than usual, and so some of the error introduced by the |
| 90 // transmission time can be eliminated. |
| 91 local_clock_ahead_by_.Reset(now, measured_offset); |
| 92 } |
| 93 VLOG(1) << "Local clock is ahead of the remote clock by: " |
| 94 << "measured=" << measured_offset.InMicroseconds() << " usec, " |
| 95 << "filtered=" << local_clock_ahead_by_.Current().InMicroseconds() |
| 96 << " usec."; |
| 97 } |
| 98 |
| 99 void ReceiverRtcpSession::SendRtcpReport( |
| 100 RtcpTimeData time_data, |
| 101 const RtcpCastMessage* cast_message, |
| 102 base::TimeDelta target_delay, |
| 103 const ReceiverRtcpEventSubscriber::RtcpEvents* rtcp_events, |
| 104 const RtpReceiverStatistics* rtp_receiver_statistics) const { |
| 105 RtcpReportBlock report_block; |
| 106 RtcpReceiverReferenceTimeReport rrtr; |
| 107 rrtr.ntp_seconds = time_data.ntp_seconds; |
| 108 rrtr.ntp_fraction = time_data.ntp_fraction; |
| 109 |
| 110 if (rtp_receiver_statistics) { |
| 111 report_block.remote_ssrc = 0; // Not needed to set send side. |
| 112 report_block.media_ssrc = remote_ssrc_; // SSRC of the RTP packet sender. |
| 113 report_block.fraction_lost = rtp_receiver_statistics->fraction_lost; |
| 114 report_block.cumulative_lost = rtp_receiver_statistics->cumulative_lost; |
| 115 report_block.extended_high_sequence_number = |
| 116 rtp_receiver_statistics->extended_high_sequence_number; |
| 117 report_block.jitter = rtp_receiver_statistics->jitter; |
| 118 report_block.last_sr = last_report_truncated_ntp_; |
| 119 if (!time_last_report_received_.is_null()) { |
| 120 uint32_t delay_seconds = 0; |
| 121 uint32_t delay_fraction = 0; |
| 122 base::TimeDelta delta = time_data.timestamp - time_last_report_received_; |
| 123 ConvertTimeToFractions(delta.InMicroseconds(), &delay_seconds, |
| 124 &delay_fraction); |
| 125 report_block.delay_since_last_sr = |
| 126 ConvertToNtpDiff(delay_seconds, delay_fraction); |
| 127 } else { |
| 128 report_block.delay_since_last_sr = 0; |
| 129 } |
| 130 } |
| 131 RtcpBuilder rtcp_builder(local_ssrc_); |
| 132 packet_sender_->SendRtcpPacket( |
| 133 local_ssrc_, rtcp_builder.BuildRtcpFromReceiver( |
| 134 rtp_receiver_statistics ? &report_block : NULL, &rrtr, |
| 135 cast_message, rtcp_events, target_delay)); |
| 136 } |
| 137 |
| 138 void ReceiverRtcpSession::OnReceivedLipSyncInfo(RtpTimeTicks rtp_timestamp, |
| 139 uint32_t ntp_seconds, |
| 140 uint32_t ntp_fraction) { |
| 141 if (ntp_seconds == 0) { |
| 142 NOTREACHED(); |
| 143 return; |
| 144 } |
| 145 lip_sync_rtp_timestamp_ = rtp_timestamp; |
| 146 lip_sync_ntp_timestamp_ = |
| 147 (static_cast<uint64_t>(ntp_seconds) << 32) | ntp_fraction; |
| 148 } |
| 149 |
| 150 bool ReceiverRtcpSession::GetLatestLipSyncTimes( |
| 151 RtpTimeTicks* rtp_timestamp, |
| 152 base::TimeTicks* reference_time) const { |
| 153 if (!lip_sync_ntp_timestamp_) |
| 154 return false; |
| 155 |
| 156 const base::TimeTicks local_reference_time = |
| 157 ConvertNtpToTimeTicks( |
| 158 static_cast<uint32_t>(lip_sync_ntp_timestamp_ >> 32), |
| 159 static_cast<uint32_t>(lip_sync_ntp_timestamp_)) + |
| 160 local_clock_ahead_by_.Current(); |
| 161 |
| 162 // Sanity-check: Getting regular lip sync updates? |
| 163 DCHECK((clock_->NowTicks() - local_reference_time) < |
| 164 base::TimeDelta::FromMinutes(1)); |
| 165 |
| 166 *rtp_timestamp = lip_sync_rtp_timestamp_; |
| 167 *reference_time = local_reference_time; |
| 168 return true; |
| 169 } |
| 170 |
| 171 } // namespace cast |
| 172 } // namespace media |
OLD | NEW |