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
3 // found in the LICENSE file.
5 #include "media/cast/rtcp/rtcp.h"
7 #include "base/big_endian.h"
8 #include "base/rand_util.h"
9 #include "media/cast/cast_config.h"
10 #include "media/cast/cast_defines.h"
11 #include "media/cast/cast_environment.h"
12 #include "media/cast/rtcp/rtcp_defines.h"
13 #include "media/cast/rtcp/rtcp_receiver.h"
14 #include "media/cast/rtcp/rtcp_sender.h"
15 #include "media/cast/rtcp/rtcp_utility.h"
16 #include "media/cast/transport/cast_transport_defines.h"
21 static const int kMaxRttMs
= 10000; // 10 seconds.
23 // Time limit for received RTCP messages when we stop using it for lip-sync.
24 static const int64 kMaxDiffSinceReceivedRtcpMs
= 100000; // 100 seconds.
26 class LocalRtcpRttFeedback
: public RtcpRttFeedback
{
28 explicit LocalRtcpRttFeedback(Rtcp
* rtcp
) : rtcp_(rtcp
) {}
30 virtual void OnReceivedDelaySinceLastReport(
31 uint32 receivers_ssrc
, uint32 last_report
,
32 uint32 delay_since_last_report
) OVERRIDE
{
33 rtcp_
->OnReceivedDelaySinceLastReport(receivers_ssrc
, last_report
,
34 delay_since_last_report
);
41 class LocalRtcpReceiverFeedback
: public RtcpReceiverFeedback
{
43 LocalRtcpReceiverFeedback(Rtcp
* rtcp
,
44 scoped_refptr
<CastEnvironment
> cast_environment
)
45 : rtcp_(rtcp
), cast_environment_(cast_environment
) {}
47 virtual void OnReceivedSenderReport(
48 const transport::RtcpSenderInfo
& remote_sender_info
) OVERRIDE
{
49 rtcp_
->OnReceivedNtp(remote_sender_info
.ntp_seconds
,
50 remote_sender_info
.ntp_fraction
);
51 if (remote_sender_info
.send_packet_count
!= 0) {
52 rtcp_
->OnReceivedLipSyncInfo(remote_sender_info
.rtp_timestamp
,
53 remote_sender_info
.ntp_seconds
,
54 remote_sender_info
.ntp_fraction
);
58 virtual void OnReceiverReferenceTimeReport(
59 const RtcpReceiverReferenceTimeReport
& remote_time_report
) OVERRIDE
{
60 rtcp_
->OnReceivedNtp(remote_time_report
.ntp_seconds
,
61 remote_time_report
.ntp_fraction
);
64 virtual void OnReceivedSendReportRequest() OVERRIDE
{
65 rtcp_
->OnReceivedSendReportRequest();
68 virtual void OnReceivedReceiverLog(const RtcpReceiverLogMessage
& receiver_log
)
70 // Add received log messages into our log system.
71 RtcpReceiverLogMessage::const_iterator it
= receiver_log
.begin();
73 for (; it
!= receiver_log
.end(); ++it
) {
74 uint32 rtp_timestamp
= it
->rtp_timestamp_
;
76 RtcpReceiverEventLogMessages::const_iterator event_it
=
77 it
->event_log_messages_
.begin();
78 for (; event_it
!= it
->event_log_messages_
.end(); ++event_it
) {
79 switch (event_it
->type
) {
80 case kAudioPacketReceived
:
81 case kVideoPacketReceived
:
82 case kDuplicateAudioPacketReceived
:
83 case kDuplicateVideoPacketReceived
:
84 cast_environment_
->Logging()->InsertPacketEvent(
85 event_it
->event_timestamp
, event_it
->type
, rtp_timestamp
,
86 kFrameIdUnknown
, event_it
->packet_id
, 0, 0);
90 case kAudioFrameDecoded
:
91 case kVideoFrameDecoded
:
92 cast_environment_
->Logging()->InsertFrameEvent(
93 event_it
->event_timestamp
, event_it
->type
, rtp_timestamp
,
96 case kAudioPlayoutDelay
:
97 case kVideoRenderDelay
:
98 cast_environment_
->Logging()->InsertFrameEventWithDelay(
99 event_it
->event_timestamp
, event_it
->type
, rtp_timestamp
,
100 kFrameIdUnknown
, event_it
->delay_delta
);
103 VLOG(2) << "Received log message via RTCP that we did not expect: "
104 << static_cast<int>(event_it
->type
);
111 virtual void OnReceivedSenderLog(
112 const transport::RtcpSenderLogMessage
& sender_log
) OVERRIDE
{
113 transport::RtcpSenderLogMessage::const_iterator it
= sender_log
.begin();
115 for (; it
!= sender_log
.end(); ++it
) {
116 uint32 rtp_timestamp
= it
->rtp_timestamp
;
117 CastLoggingEvent log_event
= kUnknown
;
119 // These events are provided to know the status of frames that never
120 // reached the receiver. The timing information for these events are not
121 // relevant and is not sent over the wire.
122 switch (it
->frame_status
) {
123 case transport::kRtcpSenderFrameStatusDroppedByFlowControl
:
124 // A frame that have been dropped by the flow control would have
125 // kVideoFrameCaptured as its last event in the log.
126 log_event
= kVideoFrameCaptured
;
128 case transport::kRtcpSenderFrameStatusDroppedByEncoder
:
129 // A frame that have been dropped by the encoder would have
130 // kVideoFrameSentToEncoder as its last event in the log.
131 log_event
= kVideoFrameSentToEncoder
;
133 case transport::kRtcpSenderFrameStatusSentToNetwork
:
134 // A frame that have be encoded is always sent to the network. We
135 // do not add a new log entry for this.
136 log_event
= kVideoFrameEncoded
;
141 // TODO(pwestin): how do we handle the truncated rtp_timestamp?
142 // Add received log messages into our log system.
143 // TODO(pwestin): how do we handle the time? we don't care about it but
144 // we need to send in one.
145 base::TimeTicks now
= cast_environment_
->Clock()->NowTicks();
146 cast_environment_
->Logging()->InsertFrameEvent(
147 now
, log_event
, rtp_timestamp
, kFrameIdUnknown
);
153 scoped_refptr
<CastEnvironment
> cast_environment_
;
156 Rtcp::Rtcp(scoped_refptr
<CastEnvironment
> cast_environment
,
157 RtcpSenderFeedback
* sender_feedback
,
158 transport::CastTransportSender
* const transport_sender
,
159 transport::PacedPacketSender
* paced_packet_sender
,
160 RtpSenderStatistics
* rtp_sender_statistics
,
161 RtpReceiverStatistics
* rtp_receiver_statistics
, RtcpMode rtcp_mode
,
162 const base::TimeDelta
& rtcp_interval
, uint32 local_ssrc
,
163 uint32 remote_ssrc
, const std::string
& c_name
)
164 : cast_environment_(cast_environment
),
165 transport_sender_(transport_sender
),
166 rtcp_interval_(rtcp_interval
),
167 rtcp_mode_(rtcp_mode
),
168 local_ssrc_(local_ssrc
),
169 remote_ssrc_(remote_ssrc
),
171 rtp_sender_statistics_(rtp_sender_statistics
),
172 rtp_receiver_statistics_(rtp_receiver_statistics
),
173 receiver_feedback_(new LocalRtcpReceiverFeedback(this, cast_environment
)),
174 rtt_feedback_(new LocalRtcpRttFeedback(this)),
175 rtcp_sender_(new RtcpSender(cast_environment
, paced_packet_sender
,
176 local_ssrc
, c_name
)),
177 last_report_received_(0),
178 last_received_rtp_timestamp_(0),
179 last_received_ntp_seconds_(0),
180 last_received_ntp_fraction_(0),
181 min_rtt_(base::TimeDelta::FromMilliseconds(kMaxRttMs
)),
182 number_of_rtt_in_avg_(0) {
183 rtcp_receiver_
.reset(new RtcpReceiver(cast_environment
, sender_feedback
,
184 receiver_feedback_
.get(),
185 rtt_feedback_
.get(), local_ssrc
));
186 rtcp_receiver_
->SetRemoteSSRC(remote_ssrc
);
192 bool Rtcp::IsRtcpPacket(const uint8
* packet
, size_t length
) {
193 DCHECK_GE(length
, kMinLengthOfRtcp
) << "Invalid RTCP packet";
194 if (length
< kMinLengthOfRtcp
) return false;
196 uint8 packet_type
= packet
[1];
197 if (packet_type
>= transport::kPacketTypeLow
&&
198 packet_type
<= transport::kPacketTypeHigh
) {
205 uint32
Rtcp::GetSsrcOfSender(const uint8
* rtcp_buffer
, size_t length
) {
206 DCHECK_GE(length
, kMinLengthOfRtcp
) << "Invalid RTCP packet";
207 uint32 ssrc_of_sender
;
208 base::BigEndianReader
big_endian_reader(
209 reinterpret_cast<const char*>(rtcp_buffer
), length
);
210 big_endian_reader
.Skip(4); // Skip header
211 big_endian_reader
.ReadU32(&ssrc_of_sender
);
212 return ssrc_of_sender
;
215 base::TimeTicks
Rtcp::TimeToSendNextRtcpReport() {
216 if (next_time_to_send_rtcp_
.is_null()) {
217 UpdateNextTimeToSendRtcp();
219 return next_time_to_send_rtcp_
;
222 void Rtcp::IncomingRtcpPacket(const uint8
* rtcp_buffer
, size_t length
) {
223 RtcpParser
rtcp_parser(rtcp_buffer
, length
);
224 if (!rtcp_parser
.IsValid()) {
225 // Silently ignore packet.
226 DLOG(ERROR
) << "Received invalid RTCP packet";
229 rtcp_receiver_
->IncomingRtcpPacket(&rtcp_parser
);
232 void Rtcp::SendRtcpFromRtpReceiver(
233 const RtcpCastMessage
* cast_message
,
234 const ReceiverRtcpEventSubscriber
* event_subscriber
) {
235 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
236 uint32 packet_type_flags
= 0;
238 base::TimeTicks now
= cast_environment_
->Clock()->NowTicks();
239 transport::RtcpReportBlock report_block
;
240 RtcpReceiverReferenceTimeReport rrtr
;
243 packet_type_flags
|= RtcpSender::kRtcpCast
;
245 if (event_subscriber
) {
246 packet_type_flags
|= RtcpSender::kRtcpReceiverLog
;
248 if (rtcp_mode_
== kRtcpCompound
|| now
>= next_time_to_send_rtcp_
) {
249 packet_type_flags
|= RtcpSender::kRtcpRr
;
251 report_block
.remote_ssrc
= 0; // Not needed to set send side.
252 report_block
.media_ssrc
= remote_ssrc_
; // SSRC of the RTP packet sender.
253 if (rtp_receiver_statistics_
) {
254 rtp_receiver_statistics_
->GetStatistics(
255 &report_block
.fraction_lost
, &report_block
.cumulative_lost
,
256 &report_block
.extended_high_sequence_number
, &report_block
.jitter
);
257 cast_environment_
->Logging()->InsertGenericEvent(now
, kJitterMs
,
258 report_block
.jitter
);
259 cast_environment_
->Logging()->InsertGenericEvent(
260 now
, kPacketLoss
, report_block
.fraction_lost
);
263 report_block
.last_sr
= last_report_received_
;
264 if (!time_last_report_received_
.is_null()) {
265 uint32 delay_seconds
= 0;
266 uint32 delay_fraction
= 0;
267 base::TimeDelta delta
= now
- time_last_report_received_
;
268 ConvertTimeToFractions(delta
.InMicroseconds(), &delay_seconds
,
270 report_block
.delay_since_last_sr
=
271 ConvertToNtpDiff(delay_seconds
, delay_fraction
);
273 report_block
.delay_since_last_sr
= 0;
276 packet_type_flags
|= RtcpSender::kRtcpRrtr
;
277 ConvertTimeTicksToNtp(now
, &rrtr
.ntp_seconds
, &rrtr
.ntp_fraction
);
278 SaveLastSentNtpTime(now
, rrtr
.ntp_seconds
, rrtr
.ntp_fraction
);
279 UpdateNextTimeToSendRtcp();
281 rtcp_sender_
->SendRtcpFromRtpReceiver(
282 packet_type_flags
, &report_block
, &rrtr
, cast_message
, event_subscriber
);
285 void Rtcp::SendRtcpFromRtpSender(
286 const transport::RtcpSenderLogMessage
& sender_log_message
) {
287 DCHECK(transport_sender_
);
288 uint32 packet_type_flags
= RtcpSender::kRtcpSr
;
289 base::TimeTicks now
= cast_environment_
->Clock()->NowTicks();
291 if (sender_log_message
.size()) {
292 packet_type_flags
|= RtcpSender::kRtcpSenderLog
;
295 transport::RtcpSenderInfo sender_info
;
296 if (rtp_sender_statistics_
) {
297 rtp_sender_statistics_
->GetStatistics(now
, &sender_info
);
299 memset(&sender_info
, 0, sizeof(sender_info
));
301 SaveLastSentNtpTime(now
, sender_info
.ntp_seconds
, sender_info
.ntp_fraction
);
303 transport::RtcpDlrrReportBlock dlrr
;
304 if (!time_last_report_received_
.is_null()) {
305 packet_type_flags
|= RtcpSender::kRtcpDlrr
;
306 dlrr
.last_rr
= last_report_received_
;
307 uint32 delay_seconds
= 0;
308 uint32 delay_fraction
= 0;
309 base::TimeDelta delta
= now
- time_last_report_received_
;
310 ConvertTimeToFractions(delta
.InMicroseconds(), &delay_seconds
,
313 dlrr
.delay_since_last_rr
= ConvertToNtpDiff(delay_seconds
, delay_fraction
);
316 cast_environment_
->PostTask(
317 CastEnvironment::TRANSPORT
, FROM_HERE
,
318 base::Bind(&Rtcp::SendRtcpFromRtpSenderOnTransportThread
,
319 base::Unretained(this), packet_type_flags
, sender_info
, dlrr
,
320 sender_log_message
, local_ssrc_
, c_name_
));
321 UpdateNextTimeToSendRtcp();
324 void Rtcp::SendRtcpFromRtpSenderOnTransportThread(
325 uint32 packet_type_flags
, const transport::RtcpSenderInfo
& sender_info
,
326 const transport::RtcpDlrrReportBlock
& dlrr
,
327 const transport::RtcpSenderLogMessage
& sender_log
, uint32 sending_ssrc
,
328 std::string c_name
) {
329 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::TRANSPORT
));
330 transport_sender_
->SendRtcpFromRtpSender(packet_type_flags
, sender_info
, dlrr
,
331 sender_log
, sending_ssrc
, c_name
);
334 void Rtcp::OnReceivedNtp(uint32 ntp_seconds
, uint32 ntp_fraction
) {
335 last_report_received_
= (ntp_seconds
<< 16) + (ntp_fraction
>> 16);
337 base::TimeTicks now
= cast_environment_
->Clock()->NowTicks();
338 time_last_report_received_
= now
;
341 void Rtcp::OnReceivedLipSyncInfo(uint32 rtp_timestamp
, uint32 ntp_seconds
,
342 uint32 ntp_fraction
) {
343 last_received_rtp_timestamp_
= rtp_timestamp
;
344 last_received_ntp_seconds_
= ntp_seconds
;
345 last_received_ntp_fraction_
= ntp_fraction
;
348 void Rtcp::OnReceivedSendReportRequest() {
349 base::TimeTicks now
= cast_environment_
->Clock()->NowTicks();
351 // Trigger a new RTCP report at next timer.
352 next_time_to_send_rtcp_
= now
;
355 bool Rtcp::RtpTimestampInSenderTime(int frequency
, uint32 rtp_timestamp
,
356 base::TimeTicks
* rtp_timestamp_in_ticks
)
358 if (last_received_ntp_seconds_
== 0)
361 int wrap
= CheckForWrapAround(rtp_timestamp
, last_received_rtp_timestamp_
);
362 int64 rtp_timestamp_int64
= rtp_timestamp
;
363 int64 last_received_rtp_timestamp_int64
= last_received_rtp_timestamp_
;
366 rtp_timestamp_int64
+= (1LL << 32);
367 } else if (wrap
== -1) {
368 last_received_rtp_timestamp_int64
+= (1LL << 32);
370 // Time since the last RTCP message.
371 // Note that this can be negative since we can compare a rtp timestamp from
372 // a frame older than the last received RTCP message.
373 int64 rtp_timestamp_diff
=
374 rtp_timestamp_int64
- last_received_rtp_timestamp_int64
;
376 int frequency_khz
= frequency
/ 1000;
377 int64 rtp_time_diff_ms
= rtp_timestamp_diff
/ frequency_khz
;
380 if (abs(rtp_time_diff_ms
) > kMaxDiffSinceReceivedRtcpMs
)
383 *rtp_timestamp_in_ticks
= ConvertNtpToTimeTicks(last_received_ntp_seconds_
,
384 last_received_ntp_fraction_
) +
385 base::TimeDelta::FromMilliseconds(rtp_time_diff_ms
);
389 void Rtcp::SetCastReceiverEventHistorySize(size_t size
) {
390 rtcp_receiver_
->SetCastReceiverEventHistorySize(size
);
393 void Rtcp::OnReceivedDelaySinceLastReport(uint32 receivers_ssrc
,
395 uint32 delay_since_last_report
) {
396 RtcpSendTimeMap::iterator it
= last_reports_sent_map_
.find(last_report
);
397 if (it
== last_reports_sent_map_
.end()) {
398 return; // Feedback on another report.
401 base::TimeDelta sender_delay
=
402 cast_environment_
->Clock()->NowTicks() - it
->second
;
403 UpdateRtt(sender_delay
, ConvertFromNtpDiff(delay_since_last_report
));
406 void Rtcp::SaveLastSentNtpTime(const base::TimeTicks
& now
,
407 uint32 last_ntp_seconds
,
408 uint32 last_ntp_fraction
) {
409 // Make sure |now| is always greater than the last element in
410 // |last_reports_sent_queue_|.
411 if (!last_reports_sent_queue_
.empty())
412 DCHECK(now
>= last_reports_sent_queue_
.back().second
);
414 uint32 last_report
= ConvertToNtpDiff(last_ntp_seconds
, last_ntp_fraction
);
415 last_reports_sent_map_
[last_report
] = now
;
416 last_reports_sent_queue_
.push(std::make_pair(last_report
, now
));
418 base::TimeTicks timeout
= now
- base::TimeDelta::FromMilliseconds(kMaxRttMs
);
420 // Cleanup old statistics older than |timeout|.
421 while (!last_reports_sent_queue_
.empty()) {
422 RtcpSendTimePair oldest_report
= last_reports_sent_queue_
.front();
423 if (oldest_report
.second
< timeout
) {
424 last_reports_sent_map_
.erase(oldest_report
.first
);
425 last_reports_sent_queue_
.pop();
432 void Rtcp::UpdateRtt(const base::TimeDelta
& sender_delay
,
433 const base::TimeDelta
& receiver_delay
) {
434 base::TimeDelta rtt
= sender_delay
- receiver_delay
;
435 rtt
= std::max(rtt
, base::TimeDelta::FromMilliseconds(1));
437 min_rtt_
= std::min(min_rtt_
, rtt
);
438 max_rtt_
= std::max(max_rtt_
, rtt
);
440 if (number_of_rtt_in_avg_
!= 0) {
441 float ac
= static_cast<float>(number_of_rtt_in_avg_
);
442 avg_rtt_ms_
= ((ac
/ (ac
+ 1.0)) * avg_rtt_ms_
) +
443 ((1.0 / (ac
+ 1.0)) * rtt
.InMilliseconds());
445 avg_rtt_ms_
= rtt
.InMilliseconds();
447 number_of_rtt_in_avg_
++;
450 bool Rtcp::Rtt(base::TimeDelta
* rtt
, base::TimeDelta
* avg_rtt
,
451 base::TimeDelta
* min_rtt
, base::TimeDelta
* max_rtt
) const {
452 DCHECK(rtt
) << "Invalid argument";
453 DCHECK(avg_rtt
) << "Invalid argument";
454 DCHECK(min_rtt
) << "Invalid argument";
455 DCHECK(max_rtt
) << "Invalid argument";
457 if (number_of_rtt_in_avg_
== 0) return false;
459 base::TimeTicks now
= cast_environment_
->Clock()->NowTicks();
460 cast_environment_
->Logging()->InsertGenericEvent(now
, kRttMs
,
461 rtt
->InMilliseconds());
464 *avg_rtt
= base::TimeDelta::FromMilliseconds(avg_rtt_ms_
);
470 int Rtcp::CheckForWrapAround(uint32 new_timestamp
, uint32 old_timestamp
) const {
471 if (new_timestamp
< old_timestamp
) {
472 // This difference should be less than -2^31 if we have had a wrap around
473 // (e.g. |new_timestamp| = 1, |rtcp_rtp_timestamp| = 2^32 - 1). Since it is
474 // cast to a int32_t, it should be positive.
475 if (static_cast<int32
>(new_timestamp
- old_timestamp
) > 0) {
476 return 1; // Forward wrap around.
478 } else if (static_cast<int32
>(old_timestamp
- new_timestamp
) > 0) {
479 // This difference should be less than -2^31 if we have had a backward wrap
480 // around. Since it is cast to a int32, it should be positive.
486 void Rtcp::UpdateNextTimeToSendRtcp() {
487 int random
= base::RandInt(0, 999);
488 base::TimeDelta time_to_next
=
489 (rtcp_interval_
/ 2) + (rtcp_interval_
* random
/ 1000);
491 base::TimeTicks now
= cast_environment_
->Clock()->NowTicks();
492 next_time_to_send_rtcp_
= now
+ time_to_next
;