- add third_party src.
[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(Clock* clock)
28     : clock_(clock),
29       crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
30       incoming_bitrate_(clock),
31       ssrc_(0),
32       max_reordering_threshold_(kDefaultMaxReorderingThreshold),
33       jitter_q4_(0),
34       jitter_max_q4_(0),
35       cumulative_loss_(0),
36       jitter_q4_transmission_time_offset_(0),
37       last_receive_time_ms_(0),
38       last_receive_time_secs_(0),
39       last_receive_time_frac_(0),
40       last_received_timestamp_(0),
41       last_received_transmission_time_offset_(0),
42       received_seq_first_(0),
43       received_seq_max_(0),
44       received_seq_wraps_(0),
45       first_packet_(true),
46       received_packet_overhead_(12),
47       received_byte_count_(0),
48       received_retransmitted_packets_(0),
49       received_inorder_packet_count_(0),
50       last_report_inorder_packets_(0),
51       last_report_old_packets_(0),
52       last_report_seq_max_(0),
53       last_reported_statistics_() {}
54
55 void StreamStatisticianImpl::ResetStatistics() {
56   CriticalSectionScoped cs(crit_sect_.get());
57   last_report_inorder_packets_ = 0;
58   last_report_old_packets_ = 0;
59   last_report_seq_max_ = 0;
60   memset(&last_reported_statistics_, 0, sizeof(last_reported_statistics_));
61   jitter_q4_ = 0;
62   jitter_max_q4_ = 0;
63   cumulative_loss_ = 0;
64   jitter_q4_transmission_time_offset_ = 0;
65   received_seq_wraps_ = 0;
66   received_seq_max_ = 0;
67   received_seq_first_ = 0;
68   received_byte_count_ = 0;
69   received_retransmitted_packets_ = 0;
70   received_inorder_packet_count_ = 0;
71   first_packet_ = true;
72 }
73
74 void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header,
75                                             size_t bytes,
76                                             bool retransmitted) {
77   CriticalSectionScoped cs(crit_sect_.get());
78   bool in_order = InOrderPacketInternal(header.sequenceNumber);
79   ssrc_ = header.ssrc;
80   incoming_bitrate_.Update(bytes);
81   received_byte_count_ += bytes;
82
83   if (first_packet_) {
84     first_packet_ = false;
85     // This is the first received report.
86     received_seq_first_ = header.sequenceNumber;
87     received_seq_max_ = header.sequenceNumber;
88     received_inorder_packet_count_ = 1;
89     clock_->CurrentNtp(last_receive_time_secs_, last_receive_time_frac_);
90     last_receive_time_ms_ = clock_->TimeInMilliseconds();
91     return;
92   }
93
94   // Count only the new packets received. That is, if packets 1, 2, 3, 5, 4, 6
95   // are received, 4 will be ignored.
96   if (in_order) {
97     // Current time in samples.
98     uint32_t receive_time_secs;
99     uint32_t receive_time_frac;
100     clock_->CurrentNtp(receive_time_secs, receive_time_frac);
101     received_inorder_packet_count_++;
102
103     // Wrong if we use RetransmitOfOldPacket.
104     int32_t seq_diff = header.sequenceNumber - received_seq_max_;
105     if (seq_diff < 0) {
106       // Wrap around detected.
107       received_seq_wraps_++;
108     }
109     // New max.
110     received_seq_max_ = header.sequenceNumber;
111
112     if (header.timestamp != last_received_timestamp_ &&
113         received_inorder_packet_count_ > 1) {
114       uint32_t receive_time_rtp = ModuleRTPUtility::ConvertNTPTimeToRTP(
115           receive_time_secs, receive_time_frac, header.payload_type_frequency);
116       uint32_t last_receive_time_rtp = ModuleRTPUtility::ConvertNTPTimeToRTP(
117           last_receive_time_secs_, last_receive_time_frac_,
118           header.payload_type_frequency);
119       int32_t time_diff_samples = (receive_time_rtp - last_receive_time_rtp) -
120           (header.timestamp - last_received_timestamp_);
121
122       time_diff_samples = abs(time_diff_samples);
123
124       // lib_jingle sometimes deliver crazy jumps in TS for the same stream.
125       // If this happens, don't update jitter value. Use 5 secs video frequency
126       // as the threshold.
127       if (time_diff_samples < 450000) {
128         // Note we calculate in Q4 to avoid using float.
129         int32_t jitter_diff_q4 = (time_diff_samples << 4) - jitter_q4_;
130         jitter_q4_ += ((jitter_diff_q4 + 8) >> 4);
131       }
132
133       // Extended jitter report, RFC 5450.
134       // Actual network jitter, excluding the source-introduced jitter.
135       int32_t time_diff_samples_ext =
136         (receive_time_rtp - last_receive_time_rtp) -
137         ((header.timestamp +
138           header.extension.transmissionTimeOffset) -
139          (last_received_timestamp_ +
140           last_received_transmission_time_offset_));
141
142       time_diff_samples_ext = abs(time_diff_samples_ext);
143
144       if (time_diff_samples_ext < 450000) {
145         int32_t jitter_diffQ4TransmissionTimeOffset =
146           (time_diff_samples_ext << 4) - jitter_q4_transmission_time_offset_;
147         jitter_q4_transmission_time_offset_ +=
148           ((jitter_diffQ4TransmissionTimeOffset + 8) >> 4);
149       }
150     }
151     last_received_timestamp_ = header.timestamp;
152     last_receive_time_secs_ = receive_time_secs;
153     last_receive_time_frac_ = receive_time_frac;
154     last_receive_time_ms_ = clock_->TimeInMilliseconds();
155   } else {
156     if (retransmitted) {
157       received_retransmitted_packets_++;
158     } else {
159       received_inorder_packet_count_++;
160     }
161   }
162
163   uint16_t packet_oh = header.headerLength + header.paddingLength;
164
165   // Our measured overhead. Filter from RFC 5104 4.2.1.2:
166   // avg_OH (new) = 15/16*avg_OH (old) + 1/16*pckt_OH,
167   received_packet_overhead_ = (15 * received_packet_overhead_ + packet_oh) >> 4;
168 }
169
170 void StreamStatisticianImpl::SetMaxReorderingThreshold(
171     int max_reordering_threshold) {
172   CriticalSectionScoped cs(crit_sect_.get());
173   max_reordering_threshold_ = max_reordering_threshold;
174 }
175
176 bool StreamStatisticianImpl::GetStatistics(Statistics* statistics, bool reset) {
177   CriticalSectionScoped cs(crit_sect_.get());
178   if (received_seq_first_ == 0 && received_byte_count_ == 0) {
179     // We have not received anything.
180     return false;
181   }
182
183   if (!reset) {
184     if (last_report_inorder_packets_ == 0) {
185       // No report.
186       return false;
187     }
188     // Just get last report.
189     *statistics = last_reported_statistics_;
190     return true;
191   }
192
193   if (last_report_inorder_packets_ == 0) {
194     // First time we send a report.
195     last_report_seq_max_ = received_seq_first_ - 1;
196   }
197
198   // Calculate fraction lost.
199   uint16_t exp_since_last = (received_seq_max_ - last_report_seq_max_);
200
201   if (last_report_seq_max_ > received_seq_max_) {
202     // Can we assume that the seq_num can't go decrease over a full RTCP period?
203     exp_since_last = 0;
204   }
205
206   // Number of received RTP packets since last report, counts all packets but
207   // not re-transmissions.
208   uint32_t rec_since_last =
209       received_inorder_packet_count_ - last_report_inorder_packets_;
210
211   // With NACK we don't know the expected retransmissions during the last
212   // second. We know how many "old" packets we have received. We just count
213   // the number of old received to estimate the loss, but it still does not
214   // guarantee an exact number since we run this based on time triggered by
215   // sending of an RTP packet. This should have a minimum effect.
216
217   // With NACK we don't count old packets as received since they are
218   // re-transmitted. We use RTT to decide if a packet is re-ordered or
219   // re-transmitted.
220   uint32_t retransmitted_packets =
221       received_retransmitted_packets_ - last_report_old_packets_;
222   rec_since_last += retransmitted_packets;
223
224   int32_t missing = 0;
225   if (exp_since_last > rec_since_last) {
226     missing = (exp_since_last - rec_since_last);
227   }
228   uint8_t local_fraction_lost = 0;
229   if (exp_since_last) {
230     // Scale 0 to 255, where 255 is 100% loss.
231     local_fraction_lost =
232         static_cast<uint8_t>(255 * missing / exp_since_last);
233   }
234   statistics->fraction_lost = local_fraction_lost;
235
236   // We need a counter for cumulative loss too.
237   cumulative_loss_ += missing;
238
239   if (jitter_q4_ > jitter_max_q4_) {
240     jitter_max_q4_ = jitter_q4_;
241   }
242   statistics->cumulative_lost = cumulative_loss_;
243   statistics->extended_max_sequence_number = (received_seq_wraps_ << 16) +
244       received_seq_max_;
245   // Note: internal jitter value is in Q4 and needs to be scaled by 1/16.
246   statistics->jitter = jitter_q4_ >> 4;
247   statistics->max_jitter = jitter_max_q4_ >> 4;
248   if (reset) {
249     // Store this report.
250     last_reported_statistics_ = *statistics;
251
252     // Only for report blocks in RTCP SR and RR.
253     last_report_inorder_packets_ = received_inorder_packet_count_;
254     last_report_old_packets_ = received_retransmitted_packets_;
255     last_report_seq_max_ = received_seq_max_;
256   }
257   return true;
258 }
259
260 void StreamStatisticianImpl::GetDataCounters(
261     uint32_t* bytes_received, uint32_t* packets_received) const {
262   CriticalSectionScoped cs(crit_sect_.get());
263   if (bytes_received) {
264     *bytes_received = received_byte_count_;
265   }
266   if (packets_received) {
267     *packets_received =
268         received_retransmitted_packets_ + received_inorder_packet_count_;
269   }
270 }
271
272 uint32_t StreamStatisticianImpl::BitrateReceived() const {
273   CriticalSectionScoped cs(crit_sect_.get());
274   return incoming_bitrate_.BitrateNow();
275 }
276
277 void StreamStatisticianImpl::ProcessBitrate() {
278   CriticalSectionScoped cs(crit_sect_.get());
279   incoming_bitrate_.Process();
280 }
281
282 void StreamStatisticianImpl::LastReceiveTimeNtp(uint32_t* secs,
283                                                 uint32_t* frac) const {
284   CriticalSectionScoped cs(crit_sect_.get());
285   *secs = last_receive_time_secs_;
286   *frac = last_receive_time_frac_;
287 }
288
289 bool StreamStatisticianImpl::IsRetransmitOfOldPacket(
290     const RTPHeader& header, int min_rtt) const {
291   CriticalSectionScoped cs(crit_sect_.get());
292   if (InOrderPacketInternal(header.sequenceNumber)) {
293     return false;
294   }
295   uint32_t frequency_khz = header.payload_type_frequency / 1000;
296   assert(frequency_khz > 0);
297
298   int64_t time_diff_ms = clock_->TimeInMilliseconds() -
299       last_receive_time_ms_;
300
301   // Diff in time stamp since last received in order.
302   uint32_t timestamp_diff = header.timestamp - last_received_timestamp_;
303   int32_t rtp_time_stamp_diff_ms = static_cast<int32_t>(timestamp_diff) /
304       frequency_khz;
305
306   int32_t max_delay_ms = 0;
307   if (min_rtt == 0) {
308     // Jitter standard deviation in samples.
309     float jitter_std = sqrt(static_cast<float>(jitter_q4_ >> 4));
310
311     // 2 times the standard deviation => 95% confidence.
312     // And transform to milliseconds by dividing by the frequency in kHz.
313     max_delay_ms = static_cast<int32_t>((2 * jitter_std) / frequency_khz);
314
315     // Min max_delay_ms is 1.
316     if (max_delay_ms == 0) {
317       max_delay_ms = 1;
318     }
319   } else {
320     max_delay_ms = (min_rtt / 3) + 1;
321   }
322   return time_diff_ms > rtp_time_stamp_diff_ms + max_delay_ms;
323 }
324
325 bool StreamStatisticianImpl::IsPacketInOrder(uint16_t sequence_number) const {
326   CriticalSectionScoped cs(crit_sect_.get());
327   return InOrderPacketInternal(sequence_number);
328 }
329
330 bool StreamStatisticianImpl::InOrderPacketInternal(
331     uint16_t sequence_number) const {
332   // First packet is always in order.
333   if (last_receive_time_ms_ == 0)
334     return true;
335
336   if (IsNewerSequenceNumber(sequence_number, received_seq_max_)) {
337     return true;
338   } else {
339     // If we have a restart of the remote side this packet is still in order.
340     return !IsNewerSequenceNumber(sequence_number, received_seq_max_ -
341                                   max_reordering_threshold_);
342   }
343 }
344
345 ReceiveStatistics* ReceiveStatistics::Create(Clock* clock) {
346   return new ReceiveStatisticsImpl(clock);
347 }
348
349 ReceiveStatisticsImpl::ReceiveStatisticsImpl(Clock* clock)
350     : clock_(clock),
351       crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
352       last_rate_update_ms_(0) {}
353
354 ReceiveStatisticsImpl::~ReceiveStatisticsImpl() {
355   while (!statisticians_.empty()) {
356     delete statisticians_.begin()->second;
357     statisticians_.erase(statisticians_.begin());
358   }
359 }
360
361 void ReceiveStatisticsImpl::IncomingPacket(const RTPHeader& header,
362                                            size_t bytes, bool old_packet) {
363   CriticalSectionScoped cs(crit_sect_.get());
364   StatisticianImplMap::iterator it = statisticians_.find(header.ssrc);
365   if (it == statisticians_.end()) {
366     std::pair<StatisticianImplMap::iterator, uint32_t> insert_result =
367         statisticians_.insert(std::make_pair(
368             header.ssrc,  new StreamStatisticianImpl(clock_)));
369     it = insert_result.first;
370   }
371   statisticians_[header.ssrc]->IncomingPacket(header, bytes, old_packet);
372 }
373
374 void ReceiveStatisticsImpl::ChangeSsrc(uint32_t from_ssrc, uint32_t to_ssrc) {
375   CriticalSectionScoped cs(crit_sect_.get());
376   StatisticianImplMap::iterator from_it = statisticians_.find(from_ssrc);
377   if (from_it == statisticians_.end())
378     return;
379   if (statisticians_.find(to_ssrc) != statisticians_.end())
380     return;
381   statisticians_[to_ssrc] = from_it->second;
382   statisticians_.erase(from_it);
383 }
384
385 StatisticianMap ReceiveStatisticsImpl::GetActiveStatisticians() const {
386   CriticalSectionScoped cs(crit_sect_.get());
387   StatisticianMap active_statisticians;
388   for (StatisticianImplMap::const_iterator it = statisticians_.begin();
389        it != statisticians_.end(); ++it) {
390     uint32_t secs;
391     uint32_t frac;
392     it->second->LastReceiveTimeNtp(&secs, &frac);
393     if (clock_->CurrentNtpInMilliseconds() -
394         Clock::NtpToMs(secs, frac) < kStatisticsTimeoutMs) {
395       active_statisticians[it->first] = it->second;
396     }
397   }
398   return active_statisticians;
399 }
400
401 StreamStatistician* ReceiveStatisticsImpl::GetStatistician(
402     uint32_t ssrc) const {
403   CriticalSectionScoped cs(crit_sect_.get());
404   StatisticianImplMap::const_iterator it = statisticians_.find(ssrc);
405   if (it == statisticians_.end())
406     return NULL;
407   return it->second;
408 }
409
410 void ReceiveStatisticsImpl::SetMaxReorderingThreshold(
411     int max_reordering_threshold) {
412   CriticalSectionScoped cs(crit_sect_.get());
413   for (StatisticianImplMap::iterator it = statisticians_.begin();
414        it != statisticians_.end(); ++it) {
415     it->second->SetMaxReorderingThreshold(max_reordering_threshold);
416   }
417 }
418
419 int32_t ReceiveStatisticsImpl::Process() {
420   CriticalSectionScoped cs(crit_sect_.get());
421   for (StatisticianImplMap::iterator it = statisticians_.begin();
422        it != statisticians_.end(); ++it) {
423     it->second->ProcessBitrate();
424   }
425   last_rate_update_ms_ = clock_->TimeInMilliseconds();
426   return 0;
427 }
428
429 int32_t ReceiveStatisticsImpl::TimeUntilNextProcess() {
430   CriticalSectionScoped cs(crit_sect_.get());
431   int time_since_last_update = clock_->TimeInMilliseconds() -
432       last_rate_update_ms_;
433   return std::max(kStatisticsProcessIntervalMs - time_since_last_update, 0);
434 }
435
436
437 void NullReceiveStatistics::IncomingPacket(const RTPHeader& rtp_header,
438                                            size_t bytes,
439                                            bool retransmitted) {}
440
441 StatisticianMap NullReceiveStatistics::GetActiveStatisticians() const {
442   return StatisticianMap();
443 }
444
445 StreamStatistician* NullReceiveStatistics::GetStatistician(
446     uint32_t ssrc) const {
447   return NULL;
448 }
449
450 void NullReceiveStatistics::SetMaxReorderingThreshold(
451     int max_reordering_threshold) {}
452
453 int32_t NullReceiveStatistics::TimeUntilNextProcess() { return 0; }
454
455 int32_t NullReceiveStatistics::Process() { return 0; }
456
457 }  // namespace webrtc