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.
4
5 #include "media/cast/rtcp/rtcp.h"
6
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"
17
18 namespace media {
19 namespace cast {
20
21 static const int kMaxRttMs = 10000; // 10 seconds.
22 static const int kMaxDelay = 2000;
23
24 class LocalRtcpRttFeedback : public RtcpRttFeedback {
25 public:
LocalRtcpRttFeedback(Rtcp * rtcp)26 explicit LocalRtcpRttFeedback(Rtcp* rtcp) : rtcp_(rtcp) {}
27
OnReceivedDelaySinceLastReport(uint32 receivers_ssrc,uint32 last_report,uint32 delay_since_last_report)28 virtual void OnReceivedDelaySinceLastReport(
29 uint32 receivers_ssrc, uint32 last_report,
30 uint32 delay_since_last_report) OVERRIDE {
31 rtcp_->OnReceivedDelaySinceLastReport(receivers_ssrc, last_report,
32 delay_since_last_report);
33 }
34
35 private:
36 Rtcp* rtcp_;
37 };
38
39 class LocalRtcpReceiverFeedback : public RtcpReceiverFeedback {
40 public:
LocalRtcpReceiverFeedback(Rtcp * rtcp,scoped_refptr<CastEnvironment> cast_environment)41 LocalRtcpReceiverFeedback(Rtcp* rtcp,
42 scoped_refptr<CastEnvironment> cast_environment)
43 : rtcp_(rtcp), cast_environment_(cast_environment) {}
44
OnReceivedSenderReport(const transport::RtcpSenderInfo & remote_sender_info)45 virtual void OnReceivedSenderReport(
46 const transport::RtcpSenderInfo& remote_sender_info) OVERRIDE {
47 rtcp_->OnReceivedNtp(remote_sender_info.ntp_seconds,
48 remote_sender_info.ntp_fraction);
49 if (remote_sender_info.send_packet_count != 0) {
50 rtcp_->OnReceivedLipSyncInfo(remote_sender_info.rtp_timestamp,
51 remote_sender_info.ntp_seconds,
52 remote_sender_info.ntp_fraction);
53 }
54 }
55
OnReceiverReferenceTimeReport(const RtcpReceiverReferenceTimeReport & remote_time_report)56 virtual void OnReceiverReferenceTimeReport(
57 const RtcpReceiverReferenceTimeReport& remote_time_report) OVERRIDE {
58 rtcp_->OnReceivedNtp(remote_time_report.ntp_seconds,
59 remote_time_report.ntp_fraction);
60 }
61
OnReceivedSendReportRequest()62 virtual void OnReceivedSendReportRequest() OVERRIDE {
63 rtcp_->OnReceivedSendReportRequest();
64 }
65
OnReceivedReceiverLog(const RtcpReceiverLogMessage & receiver_log)66 virtual void OnReceivedReceiverLog(const RtcpReceiverLogMessage& receiver_log)
67 OVERRIDE {
68 rtcp_->OnReceivedReceiverLog(receiver_log);
69 }
70
71 private:
72 Rtcp* rtcp_;
73 scoped_refptr<CastEnvironment> cast_environment_;
74 };
75
Rtcp(scoped_refptr<CastEnvironment> cast_environment,RtcpSenderFeedback * sender_feedback,transport::CastTransportSender * const transport_sender,transport::PacedPacketSender * paced_packet_sender,RtpReceiverStatistics * rtp_receiver_statistics,RtcpMode rtcp_mode,const base::TimeDelta & rtcp_interval,uint32 local_ssrc,uint32 remote_ssrc,const std::string & c_name,EventMediaType event_media_type)76 Rtcp::Rtcp(scoped_refptr<CastEnvironment> cast_environment,
77 RtcpSenderFeedback* sender_feedback,
78 transport::CastTransportSender* const transport_sender,
79 transport::PacedPacketSender* paced_packet_sender,
80 RtpReceiverStatistics* rtp_receiver_statistics, RtcpMode rtcp_mode,
81 const base::TimeDelta& rtcp_interval, uint32 local_ssrc,
82 uint32 remote_ssrc, const std::string& c_name,
83 EventMediaType event_media_type)
84 : cast_environment_(cast_environment),
85 transport_sender_(transport_sender),
86 rtcp_interval_(rtcp_interval),
87 rtcp_mode_(rtcp_mode),
88 local_ssrc_(local_ssrc),
89 remote_ssrc_(remote_ssrc),
90 c_name_(c_name),
91 event_media_type_(event_media_type),
92 rtp_receiver_statistics_(rtp_receiver_statistics),
93 rtt_feedback_(new LocalRtcpRttFeedback(this)),
94 receiver_feedback_(new LocalRtcpReceiverFeedback(this, cast_environment)),
95 rtcp_sender_(new RtcpSender(cast_environment, paced_packet_sender,
96 local_ssrc, c_name)),
97 last_report_truncated_ntp_(0),
98 local_clock_ahead_by_(ClockDriftSmoother::GetDefaultTimeConstant()),
99 lip_sync_rtp_timestamp_(0),
100 lip_sync_ntp_timestamp_(0),
101 min_rtt_(base::TimeDelta::FromMilliseconds(kMaxRttMs)),
102 number_of_rtt_in_avg_(0) {
103 rtcp_receiver_.reset(new RtcpReceiver(cast_environment, sender_feedback,
104 receiver_feedback_.get(),
105 rtt_feedback_.get(), local_ssrc));
106 rtcp_receiver_->SetRemoteSSRC(remote_ssrc);
107 }
108
~Rtcp()109 Rtcp::~Rtcp() {}
110
111 // static
IsRtcpPacket(const uint8 * packet,size_t length)112 bool Rtcp::IsRtcpPacket(const uint8* packet, size_t length) {
113 DCHECK_GE(length, kMinLengthOfRtcp) << "Invalid RTCP packet";
114 if (length < kMinLengthOfRtcp) return false;
115
116 uint8 packet_type = packet[1];
117 if (packet_type >= transport::kPacketTypeLow &&
118 packet_type <= transport::kPacketTypeHigh) {
119 return true;
120 }
121 return false;
122 }
123
124 // static
GetSsrcOfSender(const uint8 * rtcp_buffer,size_t length)125 uint32 Rtcp::GetSsrcOfSender(const uint8* rtcp_buffer, size_t length) {
126 DCHECK_GE(length, kMinLengthOfRtcp) << "Invalid RTCP packet";
127 uint32 ssrc_of_sender;
128 base::BigEndianReader big_endian_reader(
129 reinterpret_cast<const char*>(rtcp_buffer), length);
130 big_endian_reader.Skip(4); // Skip header
131 big_endian_reader.ReadU32(&ssrc_of_sender);
132 return ssrc_of_sender;
133 }
134
TimeToSendNextRtcpReport()135 base::TimeTicks Rtcp::TimeToSendNextRtcpReport() {
136 if (next_time_to_send_rtcp_.is_null()) {
137 UpdateNextTimeToSendRtcp();
138 }
139 return next_time_to_send_rtcp_;
140 }
141
IncomingRtcpPacket(const uint8 * rtcp_buffer,size_t length)142 void Rtcp::IncomingRtcpPacket(const uint8* rtcp_buffer, size_t length) {
143 RtcpParser rtcp_parser(rtcp_buffer, length);
144 if (!rtcp_parser.IsValid()) {
145 // Silently ignore packet.
146 DLOG(ERROR) << "Received invalid RTCP packet";
147 return;
148 }
149 rtcp_receiver_->IncomingRtcpPacket(&rtcp_parser);
150 }
151
SendRtcpFromRtpReceiver(const RtcpCastMessage * cast_message,const ReceiverRtcpEventSubscriber::RtcpEventMultiMap * rtcp_events)152 void Rtcp::SendRtcpFromRtpReceiver(
153 const RtcpCastMessage* cast_message,
154 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events) {
155 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
156 uint32 packet_type_flags = 0;
157
158 base::TimeTicks now = cast_environment_->Clock()->NowTicks();
159 transport::RtcpReportBlock report_block;
160 RtcpReceiverReferenceTimeReport rrtr;
161
162 // Attach our NTP to all RTCP packets; with this information a "smart" sender
163 // can make decisions based on how old the RTCP message is.
164 packet_type_flags |= transport::kRtcpRrtr;
165 ConvertTimeTicksToNtp(now, &rrtr.ntp_seconds, &rrtr.ntp_fraction);
166 SaveLastSentNtpTime(now, rrtr.ntp_seconds, rrtr.ntp_fraction);
167
168 if (cast_message) {
169 packet_type_flags |= transport::kRtcpCast;
170 }
171 if (rtcp_events) {
172 packet_type_flags |= transport::kRtcpReceiverLog;
173 }
174 if (rtcp_mode_ == kRtcpCompound || now >= next_time_to_send_rtcp_) {
175 packet_type_flags |= transport::kRtcpRr;
176
177 report_block.remote_ssrc = 0; // Not needed to set send side.
178 report_block.media_ssrc = remote_ssrc_; // SSRC of the RTP packet sender.
179 if (rtp_receiver_statistics_) {
180 rtp_receiver_statistics_->GetStatistics(
181 &report_block.fraction_lost, &report_block.cumulative_lost,
182 &report_block.extended_high_sequence_number, &report_block.jitter);
183 }
184
185 report_block.last_sr = last_report_truncated_ntp_;
186 if (!time_last_report_received_.is_null()) {
187 uint32 delay_seconds = 0;
188 uint32 delay_fraction = 0;
189 base::TimeDelta delta = now - time_last_report_received_;
190 ConvertTimeToFractions(delta.InMicroseconds(), &delay_seconds,
191 &delay_fraction);
192 report_block.delay_since_last_sr =
193 ConvertToNtpDiff(delay_seconds, delay_fraction);
194 } else {
195 report_block.delay_since_last_sr = 0;
196 }
197 UpdateNextTimeToSendRtcp();
198 }
199 rtcp_sender_->SendRtcpFromRtpReceiver(packet_type_flags,
200 &report_block,
201 &rrtr,
202 cast_message,
203 rtcp_events,
204 target_delay_ms_);
205 }
206
SendRtcpFromRtpSender(base::TimeTicks current_time,uint32 current_time_as_rtp_timestamp)207 void Rtcp::SendRtcpFromRtpSender(base::TimeTicks current_time,
208 uint32 current_time_as_rtp_timestamp) {
209 DCHECK(transport_sender_);
210 uint32 packet_type_flags = transport::kRtcpSr;
211 uint32 current_ntp_seconds = 0;
212 uint32 current_ntp_fractions = 0;
213 ConvertTimeTicksToNtp(current_time, ¤t_ntp_seconds,
214 ¤t_ntp_fractions);
215 SaveLastSentNtpTime(current_time, current_ntp_seconds,
216 current_ntp_fractions);
217
218 transport::RtcpDlrrReportBlock dlrr;
219 if (!time_last_report_received_.is_null()) {
220 packet_type_flags |= transport::kRtcpDlrr;
221 dlrr.last_rr = last_report_truncated_ntp_;
222 uint32 delay_seconds = 0;
223 uint32 delay_fraction = 0;
224 base::TimeDelta delta = current_time - time_last_report_received_;
225 ConvertTimeToFractions(delta.InMicroseconds(), &delay_seconds,
226 &delay_fraction);
227
228 dlrr.delay_since_last_rr = ConvertToNtpDiff(delay_seconds, delay_fraction);
229 }
230
231 transport_sender_->SendRtcpFromRtpSender(
232 packet_type_flags, current_ntp_seconds, current_ntp_fractions,
233 current_time_as_rtp_timestamp, dlrr, local_ssrc_, c_name_);
234 UpdateNextTimeToSendRtcp();
235 }
236
OnReceivedNtp(uint32 ntp_seconds,uint32 ntp_fraction)237 void Rtcp::OnReceivedNtp(uint32 ntp_seconds, uint32 ntp_fraction) {
238 last_report_truncated_ntp_ = ConvertToNtpDiff(ntp_seconds, ntp_fraction);
239
240 const base::TimeTicks now = cast_environment_->Clock()->NowTicks();
241 time_last_report_received_ = now;
242
243 // TODO(miu): This clock offset calculation does not account for packet
244 // transit time over the network. End2EndTest.EvilNetwork confirms that this
245 // contributes a very significant source of error here. Fix this along with
246 // the RTT clean-up.
247 const base::TimeDelta measured_offset =
248 now - ConvertNtpToTimeTicks(ntp_seconds, ntp_fraction);
249 local_clock_ahead_by_.Update(now, measured_offset);
250 if (measured_offset < local_clock_ahead_by_.Current()) {
251 // Logically, the minimum offset between the clocks has to be the correct
252 // one. For example, the time it took to transmit the current report may
253 // have been lower than usual, and so some of the error introduced by the
254 // transmission time can be eliminated.
255 local_clock_ahead_by_.Reset(now, measured_offset);
256 }
257 VLOG(1) << "Local clock is ahead of the remote clock by: "
258 << "measured=" << measured_offset.InMicroseconds() << " usec, "
259 << "filtered=" << local_clock_ahead_by_.Current().InMicroseconds()
260 << " usec.";
261 }
262
OnReceivedLipSyncInfo(uint32 rtp_timestamp,uint32 ntp_seconds,uint32 ntp_fraction)263 void Rtcp::OnReceivedLipSyncInfo(uint32 rtp_timestamp, uint32 ntp_seconds,
264 uint32 ntp_fraction) {
265 if (ntp_seconds == 0) {
266 NOTREACHED();
267 return;
268 }
269 lip_sync_rtp_timestamp_ = rtp_timestamp;
270 lip_sync_ntp_timestamp_ =
271 (static_cast<uint64>(ntp_seconds) << 32) | ntp_fraction;
272 }
273
GetLatestLipSyncTimes(uint32 * rtp_timestamp,base::TimeTicks * reference_time) const274 bool Rtcp::GetLatestLipSyncTimes(uint32* rtp_timestamp,
275 base::TimeTicks* reference_time) const {
276 if (!lip_sync_ntp_timestamp_)
277 return false;
278
279 const base::TimeTicks local_reference_time =
280 ConvertNtpToTimeTicks(static_cast<uint32>(lip_sync_ntp_timestamp_ >> 32),
281 static_cast<uint32>(lip_sync_ntp_timestamp_)) +
282 local_clock_ahead_by_.Current();
283
284 // Sanity-check: Getting regular lip sync updates?
285 DCHECK((cast_environment_->Clock()->NowTicks() - local_reference_time) <
286 base::TimeDelta::FromMinutes(1));
287
288 *rtp_timestamp = lip_sync_rtp_timestamp_;
289 *reference_time = local_reference_time;
290 return true;
291 }
292
OnReceivedSendReportRequest()293 void Rtcp::OnReceivedSendReportRequest() {
294 base::TimeTicks now = cast_environment_->Clock()->NowTicks();
295
296 // Trigger a new RTCP report at next timer.
297 next_time_to_send_rtcp_ = now;
298 }
299
SetCastReceiverEventHistorySize(size_t size)300 void Rtcp::SetCastReceiverEventHistorySize(size_t size) {
301 rtcp_receiver_->SetCastReceiverEventHistorySize(size);
302 }
303
SetTargetDelay(base::TimeDelta target_delay)304 void Rtcp::SetTargetDelay(base::TimeDelta target_delay) {
305 DCHECK(target_delay.InMilliseconds() < kMaxDelay);
306 target_delay_ms_ = static_cast<uint16>(target_delay.InMilliseconds());
307 }
308
OnReceivedDelaySinceLastReport(uint32 receivers_ssrc,uint32 last_report,uint32 delay_since_last_report)309 void Rtcp::OnReceivedDelaySinceLastReport(uint32 receivers_ssrc,
310 uint32 last_report,
311 uint32 delay_since_last_report) {
312 RtcpSendTimeMap::iterator it = last_reports_sent_map_.find(last_report);
313 if (it == last_reports_sent_map_.end()) {
314 return; // Feedback on another report.
315 }
316
317 base::TimeDelta sender_delay =
318 cast_environment_->Clock()->NowTicks() - it->second;
319 UpdateRtt(sender_delay, ConvertFromNtpDiff(delay_since_last_report));
320 }
321
SaveLastSentNtpTime(const base::TimeTicks & now,uint32 last_ntp_seconds,uint32 last_ntp_fraction)322 void Rtcp::SaveLastSentNtpTime(const base::TimeTicks& now,
323 uint32 last_ntp_seconds,
324 uint32 last_ntp_fraction) {
325 // Make sure |now| is always greater than the last element in
326 // |last_reports_sent_queue_|.
327 if (!last_reports_sent_queue_.empty())
328 DCHECK(now >= last_reports_sent_queue_.back().second);
329
330 uint32 last_report = ConvertToNtpDiff(last_ntp_seconds, last_ntp_fraction);
331 last_reports_sent_map_[last_report] = now;
332 last_reports_sent_queue_.push(std::make_pair(last_report, now));
333
334 base::TimeTicks timeout = now - base::TimeDelta::FromMilliseconds(kMaxRttMs);
335
336 // Cleanup old statistics older than |timeout|.
337 while (!last_reports_sent_queue_.empty()) {
338 RtcpSendTimePair oldest_report = last_reports_sent_queue_.front();
339 if (oldest_report.second < timeout) {
340 last_reports_sent_map_.erase(oldest_report.first);
341 last_reports_sent_queue_.pop();
342 } else {
343 break;
344 }
345 }
346 }
347
UpdateRtt(const base::TimeDelta & sender_delay,const base::TimeDelta & receiver_delay)348 void Rtcp::UpdateRtt(const base::TimeDelta& sender_delay,
349 const base::TimeDelta& receiver_delay) {
350 base::TimeDelta rtt = sender_delay - receiver_delay;
351 // TODO(miu): Find out why this must be >= 1 ms, and remove the fudge if it's
352 // bogus.
353 rtt = std::max(rtt, base::TimeDelta::FromMilliseconds(1));
354 rtt_ = rtt;
355 min_rtt_ = std::min(min_rtt_, rtt);
356 max_rtt_ = std::max(max_rtt_, rtt);
357
358 // TODO(miu): Replace "average for all time" with an EWMA, or suitable
359 // "average over recent past" mechanism.
360 if (number_of_rtt_in_avg_ != 0) {
361 const double ac = static_cast<double>(number_of_rtt_in_avg_);
362 avg_rtt_ms_ = ((ac / (ac + 1.0)) * avg_rtt_ms_) +
363 ((1.0 / (ac + 1.0)) * rtt.InMillisecondsF());
364 } else {
365 avg_rtt_ms_ = rtt.InMillisecondsF();
366 }
367 number_of_rtt_in_avg_++;
368 }
369
Rtt(base::TimeDelta * rtt,base::TimeDelta * avg_rtt,base::TimeDelta * min_rtt,base::TimeDelta * max_rtt) const370 bool Rtcp::Rtt(base::TimeDelta* rtt, base::TimeDelta* avg_rtt,
371 base::TimeDelta* min_rtt, base::TimeDelta* max_rtt) const {
372 DCHECK(rtt) << "Invalid argument";
373 DCHECK(avg_rtt) << "Invalid argument";
374 DCHECK(min_rtt) << "Invalid argument";
375 DCHECK(max_rtt) << "Invalid argument";
376
377 if (number_of_rtt_in_avg_ == 0) return false;
378
379 *rtt = rtt_;
380 *avg_rtt = base::TimeDelta::FromMillisecondsD(avg_rtt_ms_);
381 *min_rtt = min_rtt_;
382 *max_rtt = max_rtt_;
383 return true;
384 }
385
UpdateNextTimeToSendRtcp()386 void Rtcp::UpdateNextTimeToSendRtcp() {
387 int random = base::RandInt(0, 999);
388 base::TimeDelta time_to_next =
389 (rtcp_interval_ / 2) + (rtcp_interval_ * random / 1000);
390
391 base::TimeTicks now = cast_environment_->Clock()->NowTicks();
392 next_time_to_send_rtcp_ = now + time_to_next;
393 }
394
OnReceivedReceiverLog(const RtcpReceiverLogMessage & receiver_log)395 void Rtcp::OnReceivedReceiverLog(const RtcpReceiverLogMessage& receiver_log) {
396 // Add received log messages into our log system.
397 RtcpReceiverLogMessage::const_iterator it = receiver_log.begin();
398 for (; it != receiver_log.end(); ++it) {
399 uint32 rtp_timestamp = it->rtp_timestamp_;
400
401 RtcpReceiverEventLogMessages::const_iterator event_it =
402 it->event_log_messages_.begin();
403 for (; event_it != it->event_log_messages_.end(); ++event_it) {
404 switch (event_it->type) {
405 case PACKET_RECEIVED:
406 cast_environment_->Logging()->InsertPacketEvent(
407 event_it->event_timestamp, event_it->type,
408 event_media_type_, rtp_timestamp,
409 kFrameIdUnknown, event_it->packet_id, 0, 0);
410 break;
411 case FRAME_ACK_SENT:
412 case FRAME_DECODED:
413 cast_environment_->Logging()->InsertFrameEvent(
414 event_it->event_timestamp, event_it->type, event_media_type_,
415 rtp_timestamp, kFrameIdUnknown);
416 break;
417 case FRAME_PLAYOUT:
418 cast_environment_->Logging()->InsertFrameEventWithDelay(
419 event_it->event_timestamp, event_it->type, event_media_type_,
420 rtp_timestamp, kFrameIdUnknown, event_it->delay_delta);
421 break;
422 default:
423 VLOG(2) << "Received log message via RTCP that we did not expect: "
424 << static_cast<int>(event_it->type);
425 break;
426 }
427 }
428 }
429 }
430
431 } // namespace cast
432 } // namespace media
433