Upstream version 5.34.104.0
[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) : rtcp_(rtcp) {}
29
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);
35   }
36
37  private:
38   Rtcp* rtcp_;
39 };
40
41 class LocalRtcpReceiverFeedback : public RtcpReceiverFeedback {
42  public:
43   LocalRtcpReceiverFeedback(Rtcp* rtcp,
44                             scoped_refptr<CastEnvironment> cast_environment)
45       : rtcp_(rtcp), cast_environment_(cast_environment) {}
46
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);
55     }
56   }
57
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);
62   }
63
64   virtual void OnReceivedSendReportRequest() OVERRIDE {
65     rtcp_->OnReceivedSendReportRequest();
66   }
67
68   virtual void OnReceivedReceiverLog(const RtcpReceiverLogMessage& receiver_log)
69       OVERRIDE {
70     // Add received log messages into our log system.
71     RtcpReceiverLogMessage::const_iterator it = receiver_log.begin();
72
73     for (; it != receiver_log.end(); ++it) {
74       uint32 rtp_timestamp = it->rtp_timestamp_;
75
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);
87             break;
88           case kAudioAckSent:
89           case kVideoAckSent:
90           case kAudioFrameDecoded:
91           case kVideoFrameDecoded:
92             cast_environment_->Logging()->InsertFrameEvent(
93                 event_it->event_timestamp, event_it->type, rtp_timestamp,
94                 kFrameIdUnknown);
95             break;
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);
101             break;
102           default:
103             VLOG(2) << "Received log message via RTCP that we did not expect: "
104                     << static_cast<int>(event_it->type);
105             break;
106         }
107       }
108     }
109   }
110
111   virtual void OnReceivedSenderLog(
112       const transport::RtcpSenderLogMessage& sender_log) OVERRIDE {
113     transport::RtcpSenderLogMessage::const_iterator it = sender_log.begin();
114
115     for (; it != sender_log.end(); ++it) {
116       uint32 rtp_timestamp = it->rtp_timestamp;
117       CastLoggingEvent log_event = kUnknown;
118
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;
127           break;
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;
132           break;
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;
137           break;
138         default:
139           continue;
140       }
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);
148     }
149   }
150
151  private:
152   Rtcp* rtcp_;
153   scoped_refptr<CastEnvironment> cast_environment_;
154 };
155
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),
170       c_name_(c_name),
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);
187 }
188
189 Rtcp::~Rtcp() {}
190
191 // static
192 bool Rtcp::IsRtcpPacket(const uint8* packet, size_t length) {
193   DCHECK_GE(length, kMinLengthOfRtcp) << "Invalid RTCP packet";
194   if (length < kMinLengthOfRtcp) return false;
195
196   uint8 packet_type = packet[1];
197   if (packet_type >= transport::kPacketTypeLow &&
198       packet_type <= transport::kPacketTypeHigh) {
199     return true;
200   }
201   return false;
202 }
203
204 // static
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   net::BigEndianReader big_endian_reader(rtcp_buffer, length);
209   big_endian_reader.Skip(4);  // Skip header
210   big_endian_reader.ReadU32(&ssrc_of_sender);
211   return ssrc_of_sender;
212 }
213
214 base::TimeTicks Rtcp::TimeToSendNextRtcpReport() {
215   if (next_time_to_send_rtcp_.is_null()) {
216     UpdateNextTimeToSendRtcp();
217   }
218   return next_time_to_send_rtcp_;
219 }
220
221 void Rtcp::IncomingRtcpPacket(const uint8* rtcp_buffer, size_t length) {
222   RtcpParser rtcp_parser(rtcp_buffer, length);
223   if (!rtcp_parser.IsValid()) {
224     // Silently ignore packet.
225     DLOG(ERROR) << "Received invalid RTCP packet";
226     return;
227   }
228   rtcp_receiver_->IncomingRtcpPacket(&rtcp_parser);
229 }
230
231 void Rtcp::SendRtcpFromRtpReceiver(
232     const RtcpCastMessage* cast_message,
233     ReceiverRtcpEventSubscriber* event_subscriber) {
234   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
235   uint32 packet_type_flags = 0;
236
237   base::TimeTicks now = cast_environment_->Clock()->NowTicks();
238   transport::RtcpReportBlock report_block;
239   RtcpReceiverReferenceTimeReport rrtr;
240
241   if (cast_message) {
242     packet_type_flags |= RtcpSender::kRtcpCast;
243   }
244   if (event_subscriber) {
245     packet_type_flags |= RtcpSender::kRtcpReceiverLog;
246   }
247   if (rtcp_mode_ == kRtcpCompound || now >= next_time_to_send_rtcp_) {
248     packet_type_flags |= RtcpSender::kRtcpRr;
249
250     report_block.remote_ssrc = 0;            // Not needed to set send side.
251     report_block.media_ssrc = remote_ssrc_;  // SSRC of the RTP packet sender.
252     if (rtp_receiver_statistics_) {
253       rtp_receiver_statistics_->GetStatistics(
254           &report_block.fraction_lost, &report_block.cumulative_lost,
255           &report_block.extended_high_sequence_number, &report_block.jitter);
256       cast_environment_->Logging()->InsertGenericEvent(now, kJitterMs,
257                                                        report_block.jitter);
258       cast_environment_->Logging()->InsertGenericEvent(
259           now, kPacketLoss, report_block.fraction_lost);
260     }
261
262     report_block.last_sr = last_report_received_;
263     if (!time_last_report_received_.is_null()) {
264       uint32 delay_seconds = 0;
265       uint32 delay_fraction = 0;
266       base::TimeDelta delta = now - time_last_report_received_;
267       ConvertTimeToFractions(delta.InMicroseconds(), &delay_seconds,
268                              &delay_fraction);
269       report_block.delay_since_last_sr =
270           ConvertToNtpDiff(delay_seconds, delay_fraction);
271     } else {
272       report_block.delay_since_last_sr = 0;
273     }
274
275     packet_type_flags |= RtcpSender::kRtcpRrtr;
276     ConvertTimeTicksToNtp(now, &rrtr.ntp_seconds, &rrtr.ntp_fraction);
277     SaveLastSentNtpTime(now, rrtr.ntp_seconds, rrtr.ntp_fraction);
278     UpdateNextTimeToSendRtcp();
279   }
280   rtcp_sender_->SendRtcpFromRtpReceiver(
281       packet_type_flags, &report_block, &rrtr, cast_message, event_subscriber);
282 }
283
284 void Rtcp::SendRtcpFromRtpSender(
285     const transport::RtcpSenderLogMessage& sender_log_message) {
286   DCHECK(transport_sender_);
287   uint32 packet_type_flags = RtcpSender::kRtcpSr;
288   base::TimeTicks now = cast_environment_->Clock()->NowTicks();
289
290   if (sender_log_message.size()) {
291     packet_type_flags |= RtcpSender::kRtcpSenderLog;
292   }
293
294   transport::RtcpSenderInfo sender_info;
295   if (rtp_sender_statistics_) {
296     rtp_sender_statistics_->GetStatistics(now, &sender_info);
297   } else {
298     memset(&sender_info, 0, sizeof(sender_info));
299   }
300   SaveLastSentNtpTime(now, sender_info.ntp_seconds, sender_info.ntp_fraction);
301
302   transport::RtcpDlrrReportBlock dlrr;
303   if (!time_last_report_received_.is_null()) {
304     packet_type_flags |= RtcpSender::kRtcpDlrr;
305     dlrr.last_rr = last_report_received_;
306     uint32 delay_seconds = 0;
307     uint32 delay_fraction = 0;
308     base::TimeDelta delta = now - time_last_report_received_;
309     ConvertTimeToFractions(delta.InMicroseconds(), &delay_seconds,
310                            &delay_fraction);
311
312     dlrr.delay_since_last_rr = ConvertToNtpDiff(delay_seconds, delay_fraction);
313   }
314
315   cast_environment_->PostTask(
316       CastEnvironment::TRANSPORT, FROM_HERE,
317       base::Bind(&Rtcp::SendRtcpFromRtpSenderOnTransportThread,
318                  base::Unretained(this), packet_type_flags, sender_info, dlrr,
319                  sender_log_message, local_ssrc_, c_name_));
320   UpdateNextTimeToSendRtcp();
321 }
322
323 void Rtcp::SendRtcpFromRtpSenderOnTransportThread(
324     uint32 packet_type_flags, const transport::RtcpSenderInfo& sender_info,
325     const transport::RtcpDlrrReportBlock& dlrr,
326     const transport::RtcpSenderLogMessage& sender_log, uint32 sending_ssrc,
327     std::string c_name) {
328   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::TRANSPORT));
329   transport_sender_->SendRtcpFromRtpSender(packet_type_flags, sender_info, dlrr,
330                                            sender_log, sending_ssrc, c_name);
331 }
332
333 void Rtcp::OnReceivedNtp(uint32 ntp_seconds, uint32 ntp_fraction) {
334   last_report_received_ = (ntp_seconds << 16) + (ntp_fraction >> 16);
335
336   base::TimeTicks now = cast_environment_->Clock()->NowTicks();
337   time_last_report_received_ = now;
338 }
339
340 void Rtcp::OnReceivedLipSyncInfo(uint32 rtp_timestamp, uint32 ntp_seconds,
341                                  uint32 ntp_fraction) {
342   last_received_rtp_timestamp_ = rtp_timestamp;
343   last_received_ntp_seconds_ = ntp_seconds;
344   last_received_ntp_fraction_ = ntp_fraction;
345 }
346
347 void Rtcp::OnReceivedSendReportRequest() {
348   base::TimeTicks now = cast_environment_->Clock()->NowTicks();
349
350   // Trigger a new RTCP report at next timer.
351   next_time_to_send_rtcp_ = now;
352 }
353
354 bool Rtcp::RtpTimestampInSenderTime(int frequency, uint32 rtp_timestamp,
355                                     base::TimeTicks* rtp_timestamp_in_ticks)
356     const {
357   if (last_received_ntp_seconds_ == 0)
358     return false;
359
360   int wrap = CheckForWrapAround(rtp_timestamp, last_received_rtp_timestamp_);
361   int64 rtp_timestamp_int64 = rtp_timestamp;
362   int64 last_received_rtp_timestamp_int64 = last_received_rtp_timestamp_;
363
364   if (wrap == 1) {
365     rtp_timestamp_int64 += (1LL << 32);
366   } else if (wrap == -1) {
367     last_received_rtp_timestamp_int64 += (1LL << 32);
368   }
369   // Time since the last RTCP message.
370   // Note that this can be negative since we can compare a rtp timestamp from
371   // a frame older than the last received RTCP message.
372   int64 rtp_timestamp_diff =
373       rtp_timestamp_int64 - last_received_rtp_timestamp_int64;
374
375   int frequency_khz = frequency / 1000;
376   int64 rtp_time_diff_ms = rtp_timestamp_diff / frequency_khz;
377
378   // Sanity check.
379   if (abs(rtp_time_diff_ms) > kMaxDiffSinceReceivedRtcpMs)
380     return false;
381
382   *rtp_timestamp_in_ticks = ConvertNtpToTimeTicks(last_received_ntp_seconds_,
383                                                   last_received_ntp_fraction_) +
384                             base::TimeDelta::FromMilliseconds(rtp_time_diff_ms);
385   return true;
386 }
387
388 void Rtcp::OnReceivedDelaySinceLastReport(uint32 receivers_ssrc,
389                                           uint32 last_report,
390                                           uint32 delay_since_last_report) {
391   RtcpSendTimeMap::iterator it = last_reports_sent_map_.find(last_report);
392   if (it == last_reports_sent_map_.end()) {
393     return;  // Feedback on another report.
394   }
395
396   base::TimeDelta sender_delay =
397       cast_environment_->Clock()->NowTicks() - it->second;
398   UpdateRtt(sender_delay, ConvertFromNtpDiff(delay_since_last_report));
399 }
400
401 void Rtcp::SaveLastSentNtpTime(const base::TimeTicks& now,
402                                uint32 last_ntp_seconds,
403                                uint32 last_ntp_fraction) {
404   // Make sure |now| is always greater than the last element in
405   // |last_reports_sent_queue_|.
406   if (!last_reports_sent_queue_.empty())
407     DCHECK(now >= last_reports_sent_queue_.back().second);
408
409   uint32 last_report = ConvertToNtpDiff(last_ntp_seconds, last_ntp_fraction);
410   last_reports_sent_map_[last_report] = now;
411   last_reports_sent_queue_.push(std::make_pair(last_report, now));
412
413   base::TimeTicks timeout = now - base::TimeDelta::FromMilliseconds(kMaxRttMs);
414
415   // Cleanup old statistics older than |timeout|.
416   while (!last_reports_sent_queue_.empty()) {
417     RtcpSendTimePair oldest_report = last_reports_sent_queue_.front();
418     if (oldest_report.second < timeout) {
419       last_reports_sent_map_.erase(oldest_report.first);
420       last_reports_sent_queue_.pop();
421     } else {
422       break;
423     }
424   }
425 }
426
427 void Rtcp::UpdateRtt(const base::TimeDelta& sender_delay,
428                      const base::TimeDelta& receiver_delay) {
429   base::TimeDelta rtt = sender_delay - receiver_delay;
430   rtt = std::max(rtt, base::TimeDelta::FromMilliseconds(1));
431   rtt_ = rtt;
432   min_rtt_ = std::min(min_rtt_, rtt);
433   max_rtt_ = std::max(max_rtt_, rtt);
434
435   if (number_of_rtt_in_avg_ != 0) {
436     float ac = static_cast<float>(number_of_rtt_in_avg_);
437     avg_rtt_ms_ = ((ac / (ac + 1.0)) * avg_rtt_ms_) +
438                   ((1.0 / (ac + 1.0)) * rtt.InMilliseconds());
439   } else {
440     avg_rtt_ms_ = rtt.InMilliseconds();
441   }
442   number_of_rtt_in_avg_++;
443 }
444
445 bool Rtcp::Rtt(base::TimeDelta* rtt, base::TimeDelta* avg_rtt,
446                base::TimeDelta* min_rtt, base::TimeDelta* max_rtt) const {
447   DCHECK(rtt) << "Invalid argument";
448   DCHECK(avg_rtt) << "Invalid argument";
449   DCHECK(min_rtt) << "Invalid argument";
450   DCHECK(max_rtt) << "Invalid argument";
451
452   if (number_of_rtt_in_avg_ == 0) return false;
453
454   base::TimeTicks now = cast_environment_->Clock()->NowTicks();
455   cast_environment_->Logging()->InsertGenericEvent(now, kRttMs,
456                                                    rtt->InMilliseconds());
457
458   *rtt = rtt_;
459   *avg_rtt = base::TimeDelta::FromMilliseconds(avg_rtt_ms_);
460   *min_rtt = min_rtt_;
461   *max_rtt = max_rtt_;
462   return true;
463 }
464
465 int Rtcp::CheckForWrapAround(uint32 new_timestamp, uint32 old_timestamp) const {
466   if (new_timestamp < old_timestamp) {
467     // This difference should be less than -2^31 if we have had a wrap around
468     // (e.g. |new_timestamp| = 1, |rtcp_rtp_timestamp| = 2^32 - 1). Since it is
469     // cast to a int32_t, it should be positive.
470     if (static_cast<int32>(new_timestamp - old_timestamp) > 0) {
471       return 1;  // Forward wrap around.
472     }
473   } else if (static_cast<int32>(old_timestamp - new_timestamp) > 0) {
474     // This difference should be less than -2^31 if we have had a backward wrap
475     // around. Since it is cast to a int32, it should be positive.
476     return -1;
477   }
478   return 0;
479 }
480
481 void Rtcp::UpdateNextTimeToSendRtcp() {
482   int random = base::RandInt(0, 999);
483   base::TimeDelta time_to_next =
484       (rtcp_interval_ / 2) + (rtcp_interval_ * random / 1000);
485
486   base::TimeTicks now = cast_environment_->Clock()->NowTicks();
487   next_time_to_send_rtcp_ = now + time_to_next;
488 }
489
490 }  // namespace cast
491 }  // namespace media