503614ff8c3909b7479d4022be7d99c8a8f519f4
[platform/framework/web/crosswalk.git] / src / media / cast / rtcp / rtcp.cc
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/rand_util.h"
8 #include "media/cast/cast_config.h"
9 #include "media/cast/cast_defines.h"
10 #include "media/cast/cast_environment.h"
11 #include "media/cast/rtcp/rtcp_defines.h"
12 #include "media/cast/rtcp/rtcp_receiver.h"
13 #include "media/cast/rtcp/rtcp_sender.h"
14 #include "media/cast/rtcp/rtcp_utility.h"
15 #include "media/cast/transport/cast_transport_defines.h"
16 #include "net/base/big_endian.h"
17
18 namespace media {
19 namespace cast {
20
21 static const int kMaxRttMs = 10000;  // 10 seconds.
22
23 // Time limit for received RTCP messages when we stop using it for lip-sync.
24 static const int64 kMaxDiffSinceReceivedRtcpMs = 100000;  // 100 seconds.
25
26 class LocalRtcpRttFeedback : public RtcpRttFeedback {
27  public:
28   explicit LocalRtcpRttFeedback(Rtcp* rtcp)
29       : rtcp_(rtcp) {
30   }
31
32   virtual void OnReceivedDelaySinceLastReport(
33       uint32 receivers_ssrc,
34       uint32 last_report,
35       uint32 delay_since_last_report) OVERRIDE {
36     rtcp_->OnReceivedDelaySinceLastReport(receivers_ssrc,
37                                           last_report,
38                                           delay_since_last_report);
39   }
40
41  private:
42   Rtcp* rtcp_;
43 };
44
45 RtcpCastMessage::RtcpCastMessage(uint32 media_ssrc)
46     : media_ssrc_(media_ssrc) {}
47
48 RtcpCastMessage::~RtcpCastMessage() {}
49
50 RtcpNackMessage::RtcpNackMessage() {}
51 RtcpNackMessage::~RtcpNackMessage() {}
52
53 RtcpRembMessage::RtcpRembMessage() {}
54 RtcpRembMessage::~RtcpRembMessage() {}
55
56 RtcpReceiverFrameLogMessage::RtcpReceiverFrameLogMessage(uint32 timestamp)
57     : rtp_timestamp_(timestamp) {}
58
59 RtcpReceiverFrameLogMessage::~RtcpReceiverFrameLogMessage() {}
60
61 class LocalRtcpReceiverFeedback : public RtcpReceiverFeedback {
62  public:
63   LocalRtcpReceiverFeedback(Rtcp* rtcp,
64                             scoped_refptr<CastEnvironment> cast_environment)
65       : rtcp_(rtcp), cast_environment_(cast_environment) {
66   }
67
68   virtual void OnReceivedSenderReport(
69       const transport::RtcpSenderInfo& remote_sender_info) OVERRIDE {
70     rtcp_->OnReceivedNtp(remote_sender_info.ntp_seconds,
71                          remote_sender_info.ntp_fraction);
72     if (remote_sender_info.send_packet_count != 0) {
73       rtcp_->OnReceivedLipSyncInfo(remote_sender_info.rtp_timestamp,
74                                    remote_sender_info.ntp_seconds,
75                                    remote_sender_info.ntp_fraction);
76     }
77   }
78
79   virtual void OnReceiverReferenceTimeReport(
80       const RtcpReceiverReferenceTimeReport& remote_time_report) OVERRIDE {
81     rtcp_->OnReceivedNtp(remote_time_report.ntp_seconds,
82                          remote_time_report.ntp_fraction);
83   }
84
85   virtual void OnReceivedSendReportRequest() OVERRIDE {
86     rtcp_->OnReceivedSendReportRequest();
87   }
88
89   virtual void OnReceivedReceiverLog(
90       const RtcpReceiverLogMessage& receiver_log) OVERRIDE {
91     // Add received log messages into our log system.
92     RtcpReceiverLogMessage::const_iterator it = receiver_log.begin();
93
94     for (; it != receiver_log.end(); ++it) {
95       uint32 rtp_timestamp = it->rtp_timestamp_;
96
97       RtcpReceiverEventLogMessages::const_iterator event_it =
98           it->event_log_messages_.begin();
99       for (; event_it != it->event_log_messages_.end(); ++event_it) {
100         switch (event_it->type) {
101           case kAudioPacketReceived:
102           case kVideoPacketReceived:
103           case kDuplicatePacketReceived:
104             cast_environment_->Logging()->InsertPacketEvent(
105                 event_it->event_timestamp, event_it->type, rtp_timestamp,
106                 kFrameIdUnknown, event_it->packet_id, 0, 0);
107             break;
108           case kAudioAckSent:
109           case kVideoAckSent:
110           case kAudioFrameDecoded:
111           case kVideoFrameDecoded:
112             cast_environment_->Logging()->InsertFrameEvent(
113                 event_it->event_timestamp, event_it->type, rtp_timestamp,
114                 kFrameIdUnknown);
115             break;
116           case kAudioPlayoutDelay:
117           case kVideoRenderDelay:
118             cast_environment_->Logging()->InsertFrameEventWithDelay(
119                 event_it->event_timestamp, event_it->type, rtp_timestamp,
120                 kFrameIdUnknown, event_it->delay_delta);
121             break;
122           default:
123             VLOG(2) << "Received log message via RTCP that we did not expect: "
124                     << static_cast<int>(event_it->type);
125             break;
126         }
127       }
128     }
129   }
130
131   virtual void OnReceivedSenderLog(
132       const transport::RtcpSenderLogMessage& sender_log)  OVERRIDE {
133     transport::RtcpSenderLogMessage::const_iterator it = sender_log.begin();
134
135     for (; it != sender_log.end(); ++it) {
136       uint32 rtp_timestamp = it->rtp_timestamp;
137       CastLoggingEvent log_event = kUnknown;
138
139       // These events are provided to know the status of frames that never
140       // reached the receiver. The timing information for these events are not
141       // relevant and is not sent over the wire.
142       switch (it->frame_status) {
143         case transport::kRtcpSenderFrameStatusDroppedByFlowControl:
144           // A frame that have been dropped by the flow control would have
145           // kVideoFrameCaptured as its last event in the log.
146           log_event = kVideoFrameCaptured;
147           break;
148         case transport::kRtcpSenderFrameStatusDroppedByEncoder:
149           // A frame that have been dropped by the encoder would have
150           // kVideoFrameSentToEncoder as its last event in the log.
151           log_event = kVideoFrameSentToEncoder;
152           break;
153         case transport::kRtcpSenderFrameStatusSentToNetwork:
154           // A frame that have be encoded is always sent to the network. We
155           // do not add a new log entry for this.
156           log_event = kVideoFrameEncoded;
157           break;
158         default:
159           continue;
160       }
161       // TODO(pwestin): how do we handle the truncated rtp_timestamp?
162       // Add received log messages into our log system.
163       // TODO(pwestin): how do we handle the time? we don't care about it but
164       // we need to send in one.
165       base::TimeTicks now = cast_environment_->Clock()->NowTicks();
166       cast_environment_->Logging()->InsertFrameEvent(now, log_event,
167           rtp_timestamp, kFrameIdUnknown);
168     }
169   }
170
171  private:
172   Rtcp* rtcp_;
173   scoped_refptr<CastEnvironment> cast_environment_;
174 };
175
176 Rtcp::Rtcp(scoped_refptr<CastEnvironment> cast_environment,
177            RtcpSenderFeedback* sender_feedback,
178            transport::CastTransportSender* const transport_sender,
179            transport::PacedPacketSender* paced_packet_sender,
180            RtpSenderStatistics* rtp_sender_statistics,
181            RtpReceiverStatistics* rtp_receiver_statistics,
182            RtcpMode rtcp_mode,
183            const base::TimeDelta& rtcp_interval,
184            uint32 local_ssrc,
185            uint32 remote_ssrc,
186            const std::string& c_name)
187     : cast_environment_(cast_environment),
188       transport_sender_(transport_sender),
189       rtcp_interval_(rtcp_interval),
190       rtcp_mode_(rtcp_mode),
191       local_ssrc_(local_ssrc),
192       remote_ssrc_(remote_ssrc),
193       c_name_(c_name),
194       rtp_sender_statistics_(rtp_sender_statistics),
195       rtp_receiver_statistics_(rtp_receiver_statistics),
196       receiver_feedback_(new LocalRtcpReceiverFeedback(this, cast_environment)),
197       rtt_feedback_(new LocalRtcpRttFeedback(this)),
198       rtcp_sender_(new RtcpSender(cast_environment, paced_packet_sender,
199                                   local_ssrc, c_name)),
200       last_report_received_(0),
201       last_received_rtp_timestamp_(0),
202       last_received_ntp_seconds_(0),
203       last_received_ntp_fraction_(0),
204       min_rtt_(base::TimeDelta::FromMilliseconds(kMaxRttMs)),
205       number_of_rtt_in_avg_(0) {
206   rtcp_receiver_.reset(new RtcpReceiver(cast_environment,
207                                         sender_feedback,
208                                         receiver_feedback_.get(),
209                                         rtt_feedback_.get(),
210                                         local_ssrc));
211   rtcp_receiver_->SetRemoteSSRC(remote_ssrc);
212 }
213
214 Rtcp::~Rtcp() {}
215
216 // static
217 bool Rtcp::IsRtcpPacket(const uint8* packet, size_t length) {
218   DCHECK_GE(length, kMinLengthOfRtcp) << "Invalid RTCP packet";
219   if (length < kMinLengthOfRtcp) return false;
220
221   uint8 packet_type = packet[1];
222   if (packet_type >= transport::kPacketTypeLow &&
223       packet_type <= transport::kPacketTypeHigh) {
224     return true;
225   }
226   return false;
227 }
228
229 // static
230 uint32 Rtcp::GetSsrcOfSender(const uint8* rtcp_buffer, size_t length) {
231   DCHECK_GE(length, kMinLengthOfRtcp) << "Invalid RTCP packet";
232   uint32 ssrc_of_sender;
233   net::BigEndianReader big_endian_reader(rtcp_buffer, length);
234   big_endian_reader.Skip(4);  // Skip header
235   big_endian_reader.ReadU32(&ssrc_of_sender);
236   return ssrc_of_sender;
237 }
238
239 base::TimeTicks Rtcp::TimeToSendNextRtcpReport() {
240   if (next_time_to_send_rtcp_.is_null()) {
241     UpdateNextTimeToSendRtcp();
242   }
243   return next_time_to_send_rtcp_;
244 }
245
246 void Rtcp::IncomingRtcpPacket(const uint8* rtcp_buffer, size_t length) {
247   RtcpParser rtcp_parser(rtcp_buffer, length);
248   if (!rtcp_parser.IsValid()) {
249     // Silently ignore packet.
250     DLOG(ERROR) << "Received invalid RTCP packet";
251     return;
252   }
253   rtcp_receiver_->IncomingRtcpPacket(&rtcp_parser);
254 }
255
256 void Rtcp::SendRtcpFromRtpReceiver(const RtcpCastMessage* cast_message,
257                                    RtcpReceiverLogMessage* receiver_log) {
258   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
259   uint32 packet_type_flags = 0;
260
261   base::TimeTicks now = cast_environment_->Clock()->NowTicks();
262   transport::RtcpReportBlock report_block;
263   RtcpReceiverReferenceTimeReport rrtr;
264
265   if (cast_message) {
266     packet_type_flags |= RtcpSender::kRtcpCast;
267   }
268   if (receiver_log) {
269     packet_type_flags |= RtcpSender::kRtcpReceiverLog;
270   }
271   if (rtcp_mode_ == kRtcpCompound || now >= next_time_to_send_rtcp_) {
272     packet_type_flags |= RtcpSender::kRtcpRr;
273
274     report_block.remote_ssrc = 0;  // Not needed to set send side.
275     report_block.media_ssrc = remote_ssrc_;  // SSRC of the RTP packet sender.
276     if (rtp_receiver_statistics_) {
277       rtp_receiver_statistics_->GetStatistics(
278           &report_block.fraction_lost,
279           &report_block.cumulative_lost,
280           &report_block.extended_high_sequence_number,
281           &report_block.jitter);
282       cast_environment_->Logging()->InsertGenericEvent(now, kJitterMs,
283           report_block.jitter);
284       cast_environment_->Logging()->InsertGenericEvent(now, kPacketLoss,
285           report_block.fraction_lost);
286     }
287
288     report_block.last_sr = last_report_received_;
289     if (!time_last_report_received_.is_null()) {
290       uint32 delay_seconds = 0;
291       uint32 delay_fraction = 0;
292       base::TimeDelta delta = now - time_last_report_received_;
293       ConvertTimeToFractions(delta.InMicroseconds(),
294                              &delay_seconds,
295                              &delay_fraction);
296       report_block.delay_since_last_sr =
297           ConvertToNtpDiff(delay_seconds, delay_fraction);
298     } else {
299       report_block.delay_since_last_sr = 0;
300     }
301
302     packet_type_flags |= RtcpSender::kRtcpRrtr;
303     ConvertTimeTicksToNtp(now, &rrtr.ntp_seconds, &rrtr.ntp_fraction);
304     SaveLastSentNtpTime(now, rrtr.ntp_seconds, rrtr.ntp_fraction);
305     UpdateNextTimeToSendRtcp();
306   }
307   rtcp_sender_->SendRtcpFromRtpReceiver(packet_type_flags,
308                                         &report_block,
309                                         &rrtr,
310                                         cast_message,
311                                         receiver_log);
312 }
313
314 void Rtcp::SendRtcpFromRtpSender(
315     const transport::RtcpSenderLogMessage& sender_log_message) {
316   DCHECK(transport_sender_);
317   uint32 packet_type_flags = RtcpSender::kRtcpSr;
318   base::TimeTicks now = cast_environment_->Clock()->NowTicks();
319
320   if (sender_log_message.size()) {
321     packet_type_flags |= RtcpSender::kRtcpSenderLog;
322   }
323
324   transport::RtcpSenderInfo sender_info;
325   if (rtp_sender_statistics_) {
326     rtp_sender_statistics_->GetStatistics(now, &sender_info);
327   } else {
328     memset(&sender_info, 0, sizeof(sender_info));
329   }
330   SaveLastSentNtpTime(now, sender_info.ntp_seconds, sender_info.ntp_fraction);
331
332   transport::RtcpDlrrReportBlock dlrr;
333   if (!time_last_report_received_.is_null()) {
334     packet_type_flags |= RtcpSender::kRtcpDlrr;
335     dlrr.last_rr = last_report_received_;
336     uint32 delay_seconds = 0;
337     uint32 delay_fraction = 0;
338     base::TimeDelta delta = now - time_last_report_received_;
339     ConvertTimeToFractions(delta.InMicroseconds(),
340                            &delay_seconds,
341                            &delay_fraction);
342
343     dlrr.delay_since_last_rr = ConvertToNtpDiff(delay_seconds, delay_fraction);
344   }
345
346   cast_environment_->PostTask(CastEnvironment::TRANSPORT, FROM_HERE,
347       base::Bind(&Rtcp::SendRtcpFromRtpSenderOnTransportThread,
348                  base::Unretained(this), packet_type_flags, sender_info, dlrr,
349                  sender_log_message, local_ssrc_, c_name_));
350   UpdateNextTimeToSendRtcp();
351 }
352
353 void Rtcp::SendRtcpFromRtpSenderOnTransportThread(
354     uint32 packet_type_flags,
355     const transport::RtcpSenderInfo& sender_info,
356     const transport::RtcpDlrrReportBlock& dlrr,
357     const transport::RtcpSenderLogMessage& sender_log,
358     uint32 sending_ssrc,
359     std::string c_name) {
360   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::TRANSPORT));
361   transport_sender_->SendRtcpFromRtpSender(packet_type_flags,
362                                            sender_info,
363                                            dlrr,
364                                            sender_log,
365                                            sending_ssrc,
366                                            c_name);
367
368 }
369
370 void Rtcp::OnReceivedNtp(uint32 ntp_seconds, uint32 ntp_fraction) {
371   last_report_received_ = (ntp_seconds << 16) + (ntp_fraction >> 16);
372
373   base::TimeTicks now = cast_environment_->Clock()->NowTicks();
374   time_last_report_received_ = now;
375 }
376
377 void Rtcp::OnReceivedLipSyncInfo(uint32 rtp_timestamp,
378                                  uint32 ntp_seconds,
379                                  uint32 ntp_fraction) {
380   last_received_rtp_timestamp_ = rtp_timestamp;
381   last_received_ntp_seconds_ = ntp_seconds;
382   last_received_ntp_fraction_ = ntp_fraction;
383 }
384
385 void Rtcp::OnReceivedSendReportRequest() {
386   base::TimeTicks now = cast_environment_->Clock()->NowTicks();
387
388   // Trigger a new RTCP report at next timer.
389   next_time_to_send_rtcp_ = now;
390 }
391
392 bool Rtcp::RtpTimestampInSenderTime(int frequency, uint32 rtp_timestamp,
393       base::TimeTicks* rtp_timestamp_in_ticks) const {
394   if (last_received_ntp_seconds_ == 0)  return false;
395
396   int wrap = CheckForWrapAround(rtp_timestamp, last_received_rtp_timestamp_);
397   int64 rtp_timestamp_int64 = rtp_timestamp;
398   int64 last_received_rtp_timestamp_int64 = last_received_rtp_timestamp_;
399
400   if (wrap == 1) {
401     rtp_timestamp_int64 += (1LL << 32);
402   } else if (wrap == -1) {
403     last_received_rtp_timestamp_int64 += (1LL << 32);
404   }
405   // Time since the last RTCP message.
406   // Note that this can be negative since we can compare a rtp timestamp from
407   // a frame older than the last received RTCP message.
408   int64 rtp_timestamp_diff =
409       rtp_timestamp_int64 - last_received_rtp_timestamp_int64;
410
411   int frequency_khz = frequency / 1000;
412   int64 rtp_time_diff_ms = rtp_timestamp_diff / frequency_khz;
413
414   // Sanity check.
415   if (abs(rtp_time_diff_ms) > kMaxDiffSinceReceivedRtcpMs)  return false;
416
417   *rtp_timestamp_in_ticks = ConvertNtpToTimeTicks(last_received_ntp_seconds_,
418       last_received_ntp_fraction_) +
419       base::TimeDelta::FromMilliseconds(rtp_time_diff_ms);
420   return true;
421 }
422
423 void Rtcp::OnReceivedDelaySinceLastReport(uint32 receivers_ssrc,
424                                           uint32 last_report,
425                                           uint32 delay_since_last_report) {
426   RtcpSendTimeMap::iterator it = last_reports_sent_map_.find(last_report);
427   if (it == last_reports_sent_map_.end()) {
428     return;  // Feedback on another report.
429   }
430
431   base::TimeDelta sender_delay = cast_environment_->Clock()->NowTicks()
432       - it->second;
433   UpdateRtt(sender_delay, ConvertFromNtpDiff(delay_since_last_report));
434 }
435
436 void Rtcp::SaveLastSentNtpTime(const base::TimeTicks& now,
437                                uint32 last_ntp_seconds,
438                                uint32 last_ntp_fraction) {
439   // Make sure |now| is always greater than the last element in
440   // |last_reports_sent_queue_|.
441   if (!last_reports_sent_queue_.empty()) {
442     DCHECK(now >= last_reports_sent_queue_.back().second);
443   }
444
445   uint32 last_report = ConvertToNtpDiff(last_ntp_seconds, last_ntp_fraction);
446   last_reports_sent_map_[last_report] = now;
447   last_reports_sent_queue_.push(std::make_pair(last_report, now));
448
449   base::TimeTicks timeout = now - base::TimeDelta::FromMilliseconds(kMaxRttMs);
450
451   // Cleanup old statistics older than |timeout|.
452   while (!last_reports_sent_queue_.empty()) {
453     RtcpSendTimePair oldest_report = last_reports_sent_queue_.front();
454     if (oldest_report.second < timeout) {
455       last_reports_sent_map_.erase(oldest_report.first);
456       last_reports_sent_queue_.pop();
457     } else {
458       break;
459     }
460   }
461 }
462
463 void Rtcp::UpdateRtt(const base::TimeDelta& sender_delay,
464                      const base::TimeDelta& receiver_delay) {
465   base::TimeDelta rtt = sender_delay - receiver_delay;
466   rtt = std::max(rtt, base::TimeDelta::FromMilliseconds(1));
467   rtt_ = rtt;
468   min_rtt_ = std::min(min_rtt_, rtt);
469   max_rtt_ = std::max(max_rtt_, rtt);
470
471   if (number_of_rtt_in_avg_ != 0) {
472     float ac = static_cast<float>(number_of_rtt_in_avg_);
473     avg_rtt_ms_= ((ac / (ac + 1.0)) * avg_rtt_ms_) +
474         ((1.0 / (ac + 1.0)) * rtt.InMilliseconds());
475   } else {
476     avg_rtt_ms_ = rtt.InMilliseconds();
477   }
478   number_of_rtt_in_avg_++;
479 }
480
481 bool Rtcp::Rtt(base::TimeDelta* rtt,
482                base::TimeDelta* avg_rtt,
483                base::TimeDelta* min_rtt,
484                base::TimeDelta* max_rtt) const {
485   DCHECK(rtt) << "Invalid argument";
486   DCHECK(avg_rtt) << "Invalid argument";
487   DCHECK(min_rtt) << "Invalid argument";
488   DCHECK(max_rtt) << "Invalid argument";
489
490   if (number_of_rtt_in_avg_ == 0) return false;
491
492   base::TimeTicks now = cast_environment_->Clock()->NowTicks();
493   cast_environment_->Logging()->InsertGenericEvent(now, kRttMs,
494                                                    rtt->InMilliseconds());
495
496   *rtt = rtt_;
497   *avg_rtt = base::TimeDelta::FromMilliseconds(avg_rtt_ms_);
498   *min_rtt = min_rtt_;
499   *max_rtt = max_rtt_;
500   return true;
501 }
502
503 int Rtcp::CheckForWrapAround(uint32 new_timestamp,
504                              uint32 old_timestamp) const {
505   if (new_timestamp < old_timestamp) {
506     // This difference should be less than -2^31 if we have had a wrap around
507     // (e.g. |new_timestamp| = 1, |rtcp_rtp_timestamp| = 2^32 - 1). Since it is
508     // cast to a int32_t, it should be positive.
509     if (static_cast<int32>(new_timestamp - old_timestamp) > 0) {
510       return 1;  // Forward wrap around.
511     }
512   } else if (static_cast<int32>(old_timestamp - new_timestamp) > 0) {
513     // This difference should be less than -2^31 if we have had a backward wrap
514     // around. Since it is cast to a int32, it should be positive.
515     return -1;
516   }
517   return 0;
518 }
519
520 void Rtcp::UpdateNextTimeToSendRtcp() {
521   int random = base::RandInt(0, 999);
522   base::TimeDelta time_to_next = (rtcp_interval_ / 2) +
523       (rtcp_interval_ * random / 1000);
524
525   base::TimeTicks now = cast_environment_->Clock()->NowTicks();
526   next_time_to_send_rtcp_ = now + time_to_next;
527 }
528
529 }  // namespace cast
530 }  // namespace media