Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / rtp_rtcp / source / receive_statistics_impl.cc
1 /*
2  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10
11 #include "webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h"
12
13 #include <math.h>
14
15 #include "webrtc/modules/rtp_rtcp/source/bitrate.h"
16 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
17 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
18 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
19
20 namespace webrtc {
21
22 const int64_t kStatisticsTimeoutMs = 8000;
23 const int kStatisticsProcessIntervalMs = 1000;
24
25 StreamStatistician::~StreamStatistician() {}
26
27 StreamStatisticianImpl::StreamStatisticianImpl(
28     Clock* clock,
29     RtcpStatisticsCallback* rtcp_callback,
30     StreamDataCountersCallback* rtp_callback)
31     : clock_(clock),
32       stream_lock_(CriticalSectionWrapper::CreateCriticalSection()),
33       incoming_bitrate_(clock, NULL),
34       ssrc_(0),
35       max_reordering_threshold_(kDefaultMaxReorderingThreshold),
36       jitter_q4_(0),
37       cumulative_loss_(0),
38       jitter_q4_transmission_time_offset_(0),
39       last_receive_time_ms_(0),
40       last_receive_time_secs_(0),
41       last_receive_time_frac_(0),
42       last_received_timestamp_(0),
43       last_received_transmission_time_offset_(0),
44       received_seq_first_(0),
45       received_seq_max_(0),
46       received_seq_wraps_(0),
47       received_packet_overhead_(12),
48       last_report_inorder_packets_(0),
49       last_report_old_packets_(0),
50       last_report_seq_max_(0),
51       rtcp_callback_(rtcp_callback),
52       rtp_callback_(rtp_callback) {}
53
54 void StreamStatisticianImpl::ResetStatistics() {
55   CriticalSectionScoped cs(stream_lock_.get());
56   last_report_inorder_packets_ = 0;
57   last_report_old_packets_ = 0;
58   last_report_seq_max_ = 0;
59   last_reported_statistics_ = RtcpStatistics();
60   jitter_q4_ = 0;
61   cumulative_loss_ = 0;
62   jitter_q4_transmission_time_offset_ = 0;
63   received_seq_wraps_ = 0;
64   received_seq_max_ = 0;
65   received_seq_first_ = 0;
66   receive_counters_ = StreamDataCounters();
67 }
68
69 void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header,
70                                             size_t bytes,
71                                             bool retransmitted) {
72   UpdateCounters(header, bytes, retransmitted);
73   NotifyRtpCallback();
74 }
75
76 void StreamStatisticianImpl::UpdateCounters(const RTPHeader& header,
77                                             size_t bytes,
78                                             bool retransmitted) {
79   CriticalSectionScoped cs(stream_lock_.get());
80   bool in_order = InOrderPacketInternal(header.sequenceNumber);
81   ssrc_ = header.ssrc;
82   incoming_bitrate_.Update(bytes);
83   receive_counters_.bytes +=
84       bytes - (header.paddingLength + header.headerLength);
85   receive_counters_.header_bytes += header.headerLength;
86   receive_counters_.padding_bytes += header.paddingLength;
87   ++receive_counters_.packets;
88   if (!in_order && retransmitted) {
89     ++receive_counters_.retransmitted_packets;
90   }
91
92   if (receive_counters_.packets == 1) {
93     received_seq_first_ = header.sequenceNumber;
94   }
95
96   // Count only the new packets received. That is, if packets 1, 2, 3, 5, 4, 6
97   // are received, 4 will be ignored.
98   if (in_order) {
99     // Current time in samples.
100     uint32_t receive_time_secs;
101     uint32_t receive_time_frac;
102     clock_->CurrentNtp(receive_time_secs, receive_time_frac);
103
104     // Wrong if we use RetransmitOfOldPacket.
105     if (receive_counters_.packets > 1 &&
106         received_seq_max_ > header.sequenceNumber) {
107       // Wrap around detected.
108       received_seq_wraps_++;
109     }
110     // New max.
111     received_seq_max_ = header.sequenceNumber;
112
113     // If new time stamp and more than one in-order packet received, calculate
114     // new jitter statistics.
115     if (header.timestamp != last_received_timestamp_ &&
116         (receive_counters_.packets - receive_counters_.retransmitted_packets) >
117             1) {
118       UpdateJitter(header, receive_time_secs, receive_time_frac);
119     }
120     last_received_timestamp_ = header.timestamp;
121     last_receive_time_secs_ = receive_time_secs;
122     last_receive_time_frac_ = receive_time_frac;
123     last_receive_time_ms_ = clock_->TimeInMilliseconds();
124   }
125
126   uint16_t packet_oh = header.headerLength + header.paddingLength;
127
128   // Our measured overhead. Filter from RFC 5104 4.2.1.2:
129   // avg_OH (new) = 15/16*avg_OH (old) + 1/16*pckt_OH,
130   received_packet_overhead_ = (15 * received_packet_overhead_ + packet_oh) >> 4;
131 }
132
133 void StreamStatisticianImpl::UpdateJitter(const RTPHeader& header,
134                                           uint32_t receive_time_secs,
135                                           uint32_t receive_time_frac) {
136   uint32_t receive_time_rtp = ModuleRTPUtility::ConvertNTPTimeToRTP(
137           receive_time_secs, receive_time_frac, header.payload_type_frequency);
138   uint32_t last_receive_time_rtp = ModuleRTPUtility::ConvertNTPTimeToRTP(
139       last_receive_time_secs_, last_receive_time_frac_,
140       header.payload_type_frequency);
141   int32_t time_diff_samples = (receive_time_rtp - last_receive_time_rtp) -
142       (header.timestamp - last_received_timestamp_);
143
144   time_diff_samples = abs(time_diff_samples);
145
146   // lib_jingle sometimes deliver crazy jumps in TS for the same stream.
147   // If this happens, don't update jitter value. Use 5 secs video frequency
148   // as the threshold.
149   if (time_diff_samples < 450000) {
150     // Note we calculate in Q4 to avoid using float.
151     int32_t jitter_diff_q4 = (time_diff_samples << 4) - jitter_q4_;
152     jitter_q4_ += ((jitter_diff_q4 + 8) >> 4);
153   }
154
155   // Extended jitter report, RFC 5450.
156   // Actual network jitter, excluding the source-introduced jitter.
157   int32_t time_diff_samples_ext =
158     (receive_time_rtp - last_receive_time_rtp) -
159     ((header.timestamp +
160       header.extension.transmissionTimeOffset) -
161      (last_received_timestamp_ +
162       last_received_transmission_time_offset_));
163
164   time_diff_samples_ext = abs(time_diff_samples_ext);
165
166   if (time_diff_samples_ext < 450000) {
167     int32_t jitter_diffQ4TransmissionTimeOffset =
168       (time_diff_samples_ext << 4) - jitter_q4_transmission_time_offset_;
169     jitter_q4_transmission_time_offset_ +=
170       ((jitter_diffQ4TransmissionTimeOffset + 8) >> 4);
171   }
172 }
173
174 void StreamStatisticianImpl::NotifyRtpCallback() {
175   StreamDataCounters data;
176   uint32_t ssrc;
177   {
178     CriticalSectionScoped cs(stream_lock_.get());
179     data = receive_counters_;
180     ssrc = ssrc_;
181   }
182   rtp_callback_->DataCountersUpdated(data, ssrc);
183 }
184
185 void StreamStatisticianImpl::NotifyRtcpCallback() {
186   RtcpStatistics data;
187   uint32_t ssrc;
188   {
189     CriticalSectionScoped cs(stream_lock_.get());
190     data = last_reported_statistics_;
191     ssrc = ssrc_;
192   }
193   rtcp_callback_->StatisticsUpdated(data, ssrc);
194 }
195
196 void StreamStatisticianImpl::FecPacketReceived() {
197   {
198     CriticalSectionScoped cs(stream_lock_.get());
199     ++receive_counters_.fec_packets;
200   }
201   NotifyRtpCallback();
202 }
203
204 void StreamStatisticianImpl::SetMaxReorderingThreshold(
205     int max_reordering_threshold) {
206   CriticalSectionScoped cs(stream_lock_.get());
207   max_reordering_threshold_ = max_reordering_threshold;
208 }
209
210 bool StreamStatisticianImpl::GetStatistics(RtcpStatistics* statistics,
211                                            bool reset) {
212   {
213     CriticalSectionScoped cs(stream_lock_.get());
214     if (received_seq_first_ == 0 && receive_counters_.bytes == 0) {
215       // We have not received anything.
216       return false;
217     }
218
219     if (!reset) {
220       if (last_report_inorder_packets_ == 0) {
221         // No report.
222         return false;
223       }
224       // Just get last report.
225       *statistics = last_reported_statistics_;
226       return true;
227     }
228
229     *statistics = CalculateRtcpStatistics();
230   }
231
232   NotifyRtcpCallback();
233
234   return true;
235 }
236
237 RtcpStatistics StreamStatisticianImpl::CalculateRtcpStatistics() {
238   RtcpStatistics stats;
239
240   if (last_report_inorder_packets_ == 0) {
241     // First time we send a report.
242     last_report_seq_max_ = received_seq_first_ - 1;
243   }
244
245   // Calculate fraction lost.
246   uint16_t exp_since_last = (received_seq_max_ - last_report_seq_max_);
247
248   if (last_report_seq_max_ > received_seq_max_) {
249     // Can we assume that the seq_num can't go decrease over a full RTCP period?
250     exp_since_last = 0;
251   }
252
253   // Number of received RTP packets since last report, counts all packets but
254   // not re-transmissions.
255   uint32_t rec_since_last =
256       (receive_counters_.packets - receive_counters_.retransmitted_packets) -
257       last_report_inorder_packets_;
258
259   // With NACK we don't know the expected retransmissions during the last
260   // second. We know how many "old" packets we have received. We just count
261   // the number of old received to estimate the loss, but it still does not
262   // guarantee an exact number since we run this based on time triggered by
263   // sending of an RTP packet. This should have a minimum effect.
264
265   // With NACK we don't count old packets as received since they are
266   // re-transmitted. We use RTT to decide if a packet is re-ordered or
267   // re-transmitted.
268   uint32_t retransmitted_packets =
269       receive_counters_.retransmitted_packets - last_report_old_packets_;
270   rec_since_last += retransmitted_packets;
271
272   int32_t missing = 0;
273   if (exp_since_last > rec_since_last) {
274     missing = (exp_since_last - rec_since_last);
275   }
276   uint8_t local_fraction_lost = 0;
277   if (exp_since_last) {
278     // Scale 0 to 255, where 255 is 100% loss.
279     local_fraction_lost =
280         static_cast<uint8_t>(255 * missing / exp_since_last);
281   }
282   stats.fraction_lost = local_fraction_lost;
283
284   // We need a counter for cumulative loss too.
285   cumulative_loss_ += missing;
286   stats.cumulative_lost = cumulative_loss_;
287   stats.extended_max_sequence_number =
288       (received_seq_wraps_ << 16) + received_seq_max_;
289   // Note: internal jitter value is in Q4 and needs to be scaled by 1/16.
290   stats.jitter = jitter_q4_ >> 4;
291
292   // Store this report.
293   last_reported_statistics_ = stats;
294
295   // Only for report blocks in RTCP SR and RR.
296   last_report_inorder_packets_ =
297       receive_counters_.packets - receive_counters_.retransmitted_packets;
298   last_report_old_packets_ = receive_counters_.retransmitted_packets;
299   last_report_seq_max_ = received_seq_max_;
300
301   return stats;
302 }
303
304 void StreamStatisticianImpl::GetDataCounters(
305     uint32_t* bytes_received, uint32_t* packets_received) const {
306   CriticalSectionScoped cs(stream_lock_.get());
307   if (bytes_received) {
308     *bytes_received = receive_counters_.bytes + receive_counters_.header_bytes +
309                       receive_counters_.padding_bytes;
310   }
311   if (packets_received) {
312     *packets_received = receive_counters_.packets;
313   }
314 }
315
316 uint32_t StreamStatisticianImpl::BitrateReceived() const {
317   CriticalSectionScoped cs(stream_lock_.get());
318   return incoming_bitrate_.BitrateNow();
319 }
320
321 void StreamStatisticianImpl::ProcessBitrate() {
322   CriticalSectionScoped cs(stream_lock_.get());
323   incoming_bitrate_.Process();
324 }
325
326 void StreamStatisticianImpl::LastReceiveTimeNtp(uint32_t* secs,
327                                                 uint32_t* frac) const {
328   CriticalSectionScoped cs(stream_lock_.get());
329   *secs = last_receive_time_secs_;
330   *frac = last_receive_time_frac_;
331 }
332
333 bool StreamStatisticianImpl::IsRetransmitOfOldPacket(
334     const RTPHeader& header, int min_rtt) const {
335   CriticalSectionScoped cs(stream_lock_.get());
336   if (InOrderPacketInternal(header.sequenceNumber)) {
337     return false;
338   }
339   uint32_t frequency_khz = header.payload_type_frequency / 1000;
340   assert(frequency_khz > 0);
341
342   int64_t time_diff_ms = clock_->TimeInMilliseconds() -
343       last_receive_time_ms_;
344
345   // Diff in time stamp since last received in order.
346   uint32_t timestamp_diff = header.timestamp - last_received_timestamp_;
347   int32_t rtp_time_stamp_diff_ms = static_cast<int32_t>(timestamp_diff) /
348       frequency_khz;
349
350   int32_t max_delay_ms = 0;
351   if (min_rtt == 0) {
352     // Jitter standard deviation in samples.
353     float jitter_std = sqrt(static_cast<float>(jitter_q4_ >> 4));
354
355     // 2 times the standard deviation => 95% confidence.
356     // And transform to milliseconds by dividing by the frequency in kHz.
357     max_delay_ms = static_cast<int32_t>((2 * jitter_std) / frequency_khz);
358
359     // Min max_delay_ms is 1.
360     if (max_delay_ms == 0) {
361       max_delay_ms = 1;
362     }
363   } else {
364     max_delay_ms = (min_rtt / 3) + 1;
365   }
366   return time_diff_ms > rtp_time_stamp_diff_ms + max_delay_ms;
367 }
368
369 bool StreamStatisticianImpl::IsPacketInOrder(uint16_t sequence_number) const {
370   CriticalSectionScoped cs(stream_lock_.get());
371   return InOrderPacketInternal(sequence_number);
372 }
373
374 bool StreamStatisticianImpl::InOrderPacketInternal(
375     uint16_t sequence_number) const {
376   // First packet is always in order.
377   if (last_receive_time_ms_ == 0)
378     return true;
379
380   if (IsNewerSequenceNumber(sequence_number, received_seq_max_)) {
381     return true;
382   } else {
383     // If we have a restart of the remote side this packet is still in order.
384     return !IsNewerSequenceNumber(sequence_number, received_seq_max_ -
385                                   max_reordering_threshold_);
386   }
387 }
388
389 ReceiveStatistics* ReceiveStatistics::Create(Clock* clock) {
390   return new ReceiveStatisticsImpl(clock);
391 }
392
393 ReceiveStatisticsImpl::ReceiveStatisticsImpl(Clock* clock)
394     : clock_(clock),
395       receive_statistics_lock_(CriticalSectionWrapper::CreateCriticalSection()),
396       last_rate_update_ms_(0),
397       rtcp_stats_callback_(NULL),
398       rtp_stats_callback_(NULL) {}
399
400 ReceiveStatisticsImpl::~ReceiveStatisticsImpl() {
401   while (!statisticians_.empty()) {
402     delete statisticians_.begin()->second;
403     statisticians_.erase(statisticians_.begin());
404   }
405 }
406
407 void ReceiveStatisticsImpl::IncomingPacket(const RTPHeader& header,
408                                            size_t bytes,
409                                            bool retransmitted) {
410   StatisticianImplMap::iterator it;
411   {
412     CriticalSectionScoped cs(receive_statistics_lock_.get());
413     it = statisticians_.find(header.ssrc);
414     if (it == statisticians_.end()) {
415       std::pair<StatisticianImplMap::iterator, uint32_t> insert_result =
416           statisticians_.insert(std::make_pair(
417               header.ssrc, new StreamStatisticianImpl(clock_, this, this)));
418       it = insert_result.first;
419     }
420   }
421   it->second->IncomingPacket(header, bytes, retransmitted);
422 }
423
424 void ReceiveStatisticsImpl::FecPacketReceived(uint32_t ssrc) {
425   CriticalSectionScoped cs(receive_statistics_lock_.get());
426   StatisticianImplMap::iterator it = statisticians_.find(ssrc);
427   assert(it != statisticians_.end());
428   it->second->FecPacketReceived();
429 }
430
431 void ReceiveStatisticsImpl::ChangeSsrc(uint32_t from_ssrc, uint32_t to_ssrc) {
432   CriticalSectionScoped cs(receive_statistics_lock_.get());
433   StatisticianImplMap::iterator from_it = statisticians_.find(from_ssrc);
434   if (from_it == statisticians_.end())
435     return;
436   if (statisticians_.find(to_ssrc) != statisticians_.end())
437     return;
438   statisticians_[to_ssrc] = from_it->second;
439   statisticians_.erase(from_it);
440 }
441
442 StatisticianMap ReceiveStatisticsImpl::GetActiveStatisticians() const {
443   CriticalSectionScoped cs(receive_statistics_lock_.get());
444   StatisticianMap active_statisticians;
445   for (StatisticianImplMap::const_iterator it = statisticians_.begin();
446        it != statisticians_.end(); ++it) {
447     uint32_t secs;
448     uint32_t frac;
449     it->second->LastReceiveTimeNtp(&secs, &frac);
450     if (clock_->CurrentNtpInMilliseconds() -
451         Clock::NtpToMs(secs, frac) < kStatisticsTimeoutMs) {
452       active_statisticians[it->first] = it->second;
453     }
454   }
455   return active_statisticians;
456 }
457
458 StreamStatistician* ReceiveStatisticsImpl::GetStatistician(
459     uint32_t ssrc) const {
460   CriticalSectionScoped cs(receive_statistics_lock_.get());
461   StatisticianImplMap::const_iterator it = statisticians_.find(ssrc);
462   if (it == statisticians_.end())
463     return NULL;
464   return it->second;
465 }
466
467 void ReceiveStatisticsImpl::SetMaxReorderingThreshold(
468     int max_reordering_threshold) {
469   CriticalSectionScoped cs(receive_statistics_lock_.get());
470   for (StatisticianImplMap::iterator it = statisticians_.begin();
471        it != statisticians_.end(); ++it) {
472     it->second->SetMaxReorderingThreshold(max_reordering_threshold);
473   }
474 }
475
476 int32_t ReceiveStatisticsImpl::Process() {
477   CriticalSectionScoped cs(receive_statistics_lock_.get());
478   for (StatisticianImplMap::iterator it = statisticians_.begin();
479        it != statisticians_.end(); ++it) {
480     it->second->ProcessBitrate();
481   }
482   last_rate_update_ms_ = clock_->TimeInMilliseconds();
483   return 0;
484 }
485
486 int32_t ReceiveStatisticsImpl::TimeUntilNextProcess() {
487   CriticalSectionScoped cs(receive_statistics_lock_.get());
488   int time_since_last_update = clock_->TimeInMilliseconds() -
489       last_rate_update_ms_;
490   return std::max(kStatisticsProcessIntervalMs - time_since_last_update, 0);
491 }
492
493 void ReceiveStatisticsImpl::RegisterRtcpStatisticsCallback(
494     RtcpStatisticsCallback* callback) {
495   CriticalSectionScoped cs(receive_statistics_lock_.get());
496   if (callback != NULL)
497     assert(rtcp_stats_callback_ == NULL);
498   rtcp_stats_callback_ = callback;
499 }
500
501 void ReceiveStatisticsImpl::StatisticsUpdated(const RtcpStatistics& statistics,
502                                               uint32_t ssrc) {
503   CriticalSectionScoped cs(receive_statistics_lock_.get());
504   if (rtcp_stats_callback_) {
505     rtcp_stats_callback_->StatisticsUpdated(statistics, ssrc);
506   }
507 }
508
509 void ReceiveStatisticsImpl::RegisterRtpStatisticsCallback(
510     StreamDataCountersCallback* callback) {
511   CriticalSectionScoped cs(receive_statistics_lock_.get());
512   if (callback != NULL)
513     assert(rtp_stats_callback_ == NULL);
514   rtp_stats_callback_ = callback;
515 }
516
517 void ReceiveStatisticsImpl::DataCountersUpdated(const StreamDataCounters& stats,
518                                                 uint32_t ssrc) {
519   CriticalSectionScoped cs(receive_statistics_lock_.get());
520   if (rtp_stats_callback_) {
521     rtp_stats_callback_->DataCountersUpdated(stats, ssrc);
522   }
523 }
524
525 void NullReceiveStatistics::IncomingPacket(const RTPHeader& rtp_header,
526                                            size_t bytes,
527                                            bool retransmitted) {}
528
529 void NullReceiveStatistics::FecPacketReceived(uint32_t ssrc) {}
530
531 StatisticianMap NullReceiveStatistics::GetActiveStatisticians() const {
532   return StatisticianMap();
533 }
534
535 StreamStatistician* NullReceiveStatistics::GetStatistician(
536     uint32_t ssrc) const {
537   return NULL;
538 }
539
540 void NullReceiveStatistics::SetMaxReorderingThreshold(
541     int max_reordering_threshold) {}
542
543 int32_t NullReceiveStatistics::TimeUntilNextProcess() { return 0; }
544
545 int32_t NullReceiveStatistics::Process() { return 0; }
546
547 void NullReceiveStatistics::RegisterRtcpStatisticsCallback(
548     RtcpStatisticsCallback* callback) {}
549
550 void NullReceiveStatistics::RegisterRtpStatisticsCallback(
551     StreamDataCountersCallback* callback) {}
552
553 }  // namespace webrtc