• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &current_ntp_seconds,
214                         &current_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