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
3 // found in the LICENSE file.
5 #include "media/cast/net/rtcp/rtcp.h"
7 #include "media/cast/cast_config.h"
8 #include "media/cast/cast_defines.h"
9 #include "media/cast/cast_environment.h"
10 #include "media/cast/net/cast_transport_defines.h"
11 #include "media/cast/net/pacing/paced_sender.h"
12 #include "media/cast/net/rtcp/rtcp_builder.h"
13 #include "media/cast/net/rtcp/rtcp_defines.h"
14 #include "media/cast/net/rtcp/rtcp_utility.h"
16 using base::TimeDelta
;
21 static const int32 kStatsHistoryWindowMs
= 10000; // 10 seconds.
22 // Reject packets that are older than 0.5 seconds older than
23 // the newest packet we've seen so far. This protect internal
24 // states from crazy routers. (Based on RRTR)
25 static const int32 kOutOfOrderMaxAgeMs
= 500;
29 // A receiver frame event is identified by frame RTP timestamp, event timestamp
31 // A receiver packet event is identified by all of the above plus packet id.
32 // The key format is as follows:
34 // bits 0-11: zeroes (unused).
35 // bits 12-15: event type ID.
36 // bits 16-31: packet ID if packet event, 0 otherwise.
37 // bits 32-63: RTP timestamp.
39 // bits 0-63: event TimeTicks internal value.
40 std::pair
<uint64
, uint64
> GetReceiverEventKey(
41 uint32 frame_rtp_timestamp
,
42 const base::TimeTicks
& event_timestamp
,
44 uint16 packet_id_or_zero
) {
45 uint64 value1
= event_type
;
47 value1
|= packet_id_or_zero
;
49 value1
|= frame_rtp_timestamp
;
50 return std::make_pair(
51 value1
, static_cast<uint64
>(event_timestamp
.ToInternalValue()));
56 Rtcp::Rtcp(const RtcpCastMessageCallback
& cast_callback
,
57 const RtcpRttCallback
& rtt_callback
,
58 const RtcpLogMessageCallback
& log_callback
,
59 base::TickClock
* clock
,
60 PacedPacketSender
* packet_sender
,
63 : cast_callback_(cast_callback
),
64 rtt_callback_(rtt_callback
),
65 log_callback_(log_callback
),
67 rtcp_builder_(local_ssrc
),
68 packet_sender_(packet_sender
),
69 local_ssrc_(local_ssrc
),
70 remote_ssrc_(remote_ssrc
),
71 last_report_truncated_ntp_(0),
72 local_clock_ahead_by_(ClockDriftSmoother::GetDefaultTimeConstant()),
73 lip_sync_rtp_timestamp_(0),
74 lip_sync_ntp_timestamp_(0),
75 largest_seen_timestamp_(
76 base::TimeTicks::FromInternalValue(kint64min
)) {
81 bool Rtcp::IsRtcpPacket(const uint8
* packet
, size_t length
) {
82 if (length
< kMinLengthOfRtcp
) {
83 LOG(ERROR
) << "Invalid RTCP packet received.";
87 uint8 packet_type
= packet
[1];
88 return packet_type
>= kPacketTypeLow
&& packet_type
<= kPacketTypeHigh
;
91 uint32
Rtcp::GetSsrcOfSender(const uint8
* rtcp_buffer
, size_t length
) {
92 if (length
< kMinLengthOfRtcp
)
94 uint32 ssrc_of_sender
;
95 base::BigEndianReader
big_endian_reader(
96 reinterpret_cast<const char*>(rtcp_buffer
), length
);
97 big_endian_reader
.Skip(4); // Skip header.
98 big_endian_reader
.ReadU32(&ssrc_of_sender
);
99 return ssrc_of_sender
;
102 bool Rtcp::IncomingRtcpPacket(const uint8
* data
, size_t length
) {
103 // Check if this is a valid RTCP packet.
104 if (!IsRtcpPacket(data
, length
)) {
105 VLOG(1) << "Rtcp@" << this << "::IncomingRtcpPacket() -- "
106 << "Received an invalid (non-RTCP?) packet.";
110 // Check if this packet is to us.
111 uint32 ssrc_of_sender
= GetSsrcOfSender(data
, length
);
112 if (ssrc_of_sender
!= remote_ssrc_
) {
116 // Parse this packet.
117 RtcpParser
parser(local_ssrc_
, remote_ssrc_
);
118 base::BigEndianReader
reader(reinterpret_cast<const char*>(data
), length
);
119 if (parser
.Parse(&reader
)) {
120 if (parser
.has_receiver_reference_time_report()) {
121 base::TimeTicks t
= ConvertNtpToTimeTicks(
122 parser
.receiver_reference_time_report().ntp_seconds
,
123 parser
.receiver_reference_time_report().ntp_fraction
);
124 if (t
> largest_seen_timestamp_
) {
125 largest_seen_timestamp_
= t
;
126 } else if ((largest_seen_timestamp_
- t
).InMilliseconds() >
127 kOutOfOrderMaxAgeMs
) {
128 // Reject packet, it is too old.
129 VLOG(1) << "Rejecting RTCP packet as it is too old ("
130 << (largest_seen_timestamp_
- t
).InMilliseconds()
135 OnReceivedNtp(parser
.receiver_reference_time_report().ntp_seconds
,
136 parser
.receiver_reference_time_report().ntp_fraction
);
138 if (parser
.has_sender_report()) {
139 OnReceivedNtp(parser
.sender_report().ntp_seconds
,
140 parser
.sender_report().ntp_fraction
);
141 OnReceivedLipSyncInfo(parser
.sender_report().rtp_timestamp
,
142 parser
.sender_report().ntp_seconds
,
143 parser
.sender_report().ntp_fraction
);
145 if (parser
.has_receiver_log()) {
146 if (DedupeReceiverLog(parser
.mutable_receiver_log())) {
147 OnReceivedReceiverLog(parser
.receiver_log());
150 if (parser
.has_last_report()) {
151 OnReceivedDelaySinceLastReport(parser
.last_report(),
152 parser
.delay_since_last_report());
154 if (parser
.has_cast_message()) {
155 parser
.mutable_cast_message()->ack_frame_id
=
156 ack_frame_id_wrap_helper_
.MapTo32bitsFrameId(
157 parser
.mutable_cast_message()->ack_frame_id
);
158 OnReceivedCastFeedback(parser
.cast_message());
164 bool Rtcp::DedupeReceiverLog(RtcpReceiverLogMessage
* receiver_log
) {
165 RtcpReceiverLogMessage::iterator i
= receiver_log
->begin();
166 while (i
!= receiver_log
->end()) {
167 RtcpReceiverEventLogMessages
* messages
= &i
->event_log_messages_
;
168 RtcpReceiverEventLogMessages::iterator j
= messages
->begin();
169 while (j
!= messages
->end()) {
170 ReceiverEventKey key
= GetReceiverEventKey(i
->rtp_timestamp_
,
174 RtcpReceiverEventLogMessages::iterator tmp
= j
;
176 if (receiver_event_key_set_
.insert(key
).second
) {
177 receiver_event_key_queue_
.push(key
);
178 if (receiver_event_key_queue_
.size() > kReceiverRtcpEventHistorySize
) {
179 receiver_event_key_set_
.erase(receiver_event_key_queue_
.front());
180 receiver_event_key_queue_
.pop();
183 messages
->erase(tmp
);
187 RtcpReceiverLogMessage::iterator tmp
= i
;
189 if (messages
->empty()) {
190 receiver_log
->erase(tmp
);
193 return !receiver_log
->empty();
196 RtcpTimeData
Rtcp::ConvertToNTPAndSave(base::TimeTicks now
) {
200 // Attach our NTP to all RTCP packets; with this information a "smart" sender
201 // can make decisions based on how old the RTCP message is.
202 ConvertTimeTicksToNtp(now
, &ret
.ntp_seconds
, &ret
.ntp_fraction
);
203 SaveLastSentNtpTime(now
, ret
.ntp_seconds
, ret
.ntp_fraction
);
207 void Rtcp::SendRtcpFromRtpReceiver(
208 RtcpTimeData time_data
,
209 const RtcpCastMessage
* cast_message
,
210 base::TimeDelta target_delay
,
211 const ReceiverRtcpEventSubscriber::RtcpEvents
* rtcp_events
,
212 const RtpReceiverStatistics
* rtp_receiver_statistics
) const {
213 RtcpReportBlock report_block
;
214 RtcpReceiverReferenceTimeReport rrtr
;
215 rrtr
.ntp_seconds
= time_data
.ntp_seconds
;
216 rrtr
.ntp_fraction
= time_data
.ntp_fraction
;
218 if (rtp_receiver_statistics
) {
219 report_block
.remote_ssrc
= 0; // Not needed to set send side.
220 report_block
.media_ssrc
= remote_ssrc_
; // SSRC of the RTP packet sender.
221 report_block
.fraction_lost
= rtp_receiver_statistics
->fraction_lost
;
222 report_block
.cumulative_lost
= rtp_receiver_statistics
->cumulative_lost
;
223 report_block
.extended_high_sequence_number
=
224 rtp_receiver_statistics
->extended_high_sequence_number
;
225 report_block
.jitter
= rtp_receiver_statistics
->jitter
;
226 report_block
.last_sr
= last_report_truncated_ntp_
;
227 if (!time_last_report_received_
.is_null()) {
228 uint32 delay_seconds
= 0;
229 uint32 delay_fraction
= 0;
230 base::TimeDelta delta
= time_data
.timestamp
- time_last_report_received_
;
231 ConvertTimeToFractions(delta
.InMicroseconds(), &delay_seconds
,
233 report_block
.delay_since_last_sr
=
234 ConvertToNtpDiff(delay_seconds
, delay_fraction
);
236 report_block
.delay_since_last_sr
= 0;
239 RtcpBuilder
rtcp_builder(local_ssrc_
);
240 packet_sender_
->SendRtcpPacket(
242 rtcp_builder
.BuildRtcpFromReceiver(
243 rtp_receiver_statistics
? &report_block
: NULL
,
250 void Rtcp::SendRtcpFromRtpSender(base::TimeTicks current_time
,
251 uint32 current_time_as_rtp_timestamp
,
252 uint32 send_packet_count
,
253 size_t send_octet_count
) {
254 uint32 current_ntp_seconds
= 0;
255 uint32 current_ntp_fractions
= 0;
256 ConvertTimeTicksToNtp(current_time
, ¤t_ntp_seconds
,
257 ¤t_ntp_fractions
);
258 SaveLastSentNtpTime(current_time
, current_ntp_seconds
,
259 current_ntp_fractions
);
261 RtcpSenderInfo sender_info
;
262 sender_info
.ntp_seconds
= current_ntp_seconds
;
263 sender_info
.ntp_fraction
= current_ntp_fractions
;
264 sender_info
.rtp_timestamp
= current_time_as_rtp_timestamp
;
265 sender_info
.send_packet_count
= send_packet_count
;
266 sender_info
.send_octet_count
= send_octet_count
;
268 packet_sender_
->SendRtcpPacket(
270 rtcp_builder_
.BuildRtcpFromSender(sender_info
));
273 void Rtcp::OnReceivedNtp(uint32 ntp_seconds
, uint32 ntp_fraction
) {
274 last_report_truncated_ntp_
= ConvertToNtpDiff(ntp_seconds
, ntp_fraction
);
276 const base::TimeTicks now
= clock_
->NowTicks();
277 time_last_report_received_
= now
;
279 // TODO(miu): This clock offset calculation does not account for packet
280 // transit time over the network. End2EndTest.EvilNetwork confirms that this
281 // contributes a very significant source of error here. Determine whether
282 // RTT should be factored-in, and how that changes the rest of the
284 const base::TimeDelta measured_offset
=
285 now
- ConvertNtpToTimeTicks(ntp_seconds
, ntp_fraction
);
286 local_clock_ahead_by_
.Update(now
, measured_offset
);
287 if (measured_offset
< local_clock_ahead_by_
.Current()) {
288 // Logically, the minimum offset between the clocks has to be the correct
289 // one. For example, the time it took to transmit the current report may
290 // have been lower than usual, and so some of the error introduced by the
291 // transmission time can be eliminated.
292 local_clock_ahead_by_
.Reset(now
, measured_offset
);
294 VLOG(1) << "Local clock is ahead of the remote clock by: "
295 << "measured=" << measured_offset
.InMicroseconds() << " usec, "
296 << "filtered=" << local_clock_ahead_by_
.Current().InMicroseconds()
300 void Rtcp::OnReceivedLipSyncInfo(uint32 rtp_timestamp
, uint32 ntp_seconds
,
301 uint32 ntp_fraction
) {
302 if (ntp_seconds
== 0) {
306 lip_sync_rtp_timestamp_
= rtp_timestamp
;
307 lip_sync_ntp_timestamp_
=
308 (static_cast<uint64
>(ntp_seconds
) << 32) | ntp_fraction
;
311 bool Rtcp::GetLatestLipSyncTimes(uint32
* rtp_timestamp
,
312 base::TimeTicks
* reference_time
) const {
313 if (!lip_sync_ntp_timestamp_
)
316 const base::TimeTicks local_reference_time
=
317 ConvertNtpToTimeTicks(static_cast<uint32
>(lip_sync_ntp_timestamp_
>> 32),
318 static_cast<uint32
>(lip_sync_ntp_timestamp_
)) +
319 local_clock_ahead_by_
.Current();
321 // Sanity-check: Getting regular lip sync updates?
322 DCHECK((clock_
->NowTicks() - local_reference_time
) <
323 base::TimeDelta::FromMinutes(1));
325 *rtp_timestamp
= lip_sync_rtp_timestamp_
;
326 *reference_time
= local_reference_time
;
330 void Rtcp::OnReceivedDelaySinceLastReport(uint32 last_report
,
331 uint32 delay_since_last_report
) {
332 RtcpSendTimeMap::iterator it
= last_reports_sent_map_
.find(last_report
);
333 if (it
== last_reports_sent_map_
.end()) {
334 return; // Feedback on another report.
337 const base::TimeDelta sender_delay
= clock_
->NowTicks() - it
->second
;
338 const base::TimeDelta receiver_delay
=
339 ConvertFromNtpDiff(delay_since_last_report
);
340 current_round_trip_time_
= sender_delay
- receiver_delay
;
341 // If the round trip time was computed as less than 1 ms, assume clock
342 // imprecision by one or both peers caused a bad value to be calculated.
343 // While plenty of networks do easily achieve less than 1 ms round trip time,
344 // such a level of precision cannot be measured with our approach; and 1 ms is
345 // good enough to represent "under 1 ms" for our use cases.
346 current_round_trip_time_
=
347 std::max(current_round_trip_time_
, base::TimeDelta::FromMilliseconds(1));
349 if (!rtt_callback_
.is_null())
350 rtt_callback_
.Run(current_round_trip_time_
);
353 void Rtcp::OnReceivedCastFeedback(const RtcpCastMessage
& cast_message
) {
354 if (cast_callback_
.is_null())
356 cast_callback_
.Run(cast_message
);
359 void Rtcp::SaveLastSentNtpTime(const base::TimeTicks
& now
,
360 uint32 last_ntp_seconds
,
361 uint32 last_ntp_fraction
) {
362 // Make sure |now| is always greater than the last element in
363 // |last_reports_sent_queue_|.
364 if (!last_reports_sent_queue_
.empty()) {
365 DCHECK(now
>= last_reports_sent_queue_
.back().second
);
368 uint32 last_report
= ConvertToNtpDiff(last_ntp_seconds
, last_ntp_fraction
);
369 last_reports_sent_map_
[last_report
] = now
;
370 last_reports_sent_queue_
.push(std::make_pair(last_report
, now
));
372 const base::TimeTicks timeout
=
373 now
- TimeDelta::FromMilliseconds(kStatsHistoryWindowMs
);
375 // Cleanup old statistics older than |timeout|.
376 while (!last_reports_sent_queue_
.empty()) {
377 RtcpSendTimePair oldest_report
= last_reports_sent_queue_
.front();
378 if (oldest_report
.second
< timeout
) {
379 last_reports_sent_map_
.erase(oldest_report
.first
);
380 last_reports_sent_queue_
.pop();
387 void Rtcp::OnReceivedReceiverLog(const RtcpReceiverLogMessage
& receiver_log
) {
388 if (log_callback_
.is_null())
390 log_callback_
.Run(receiver_log
);