1 /*
2  *  Copyright (c) 2014 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/video_engine/report_block_stats.h"
12 
13 namespace webrtc {
14 
15 namespace {
FractionLost(uint32_t num_lost_sequence_numbers,uint32_t num_sequence_numbers)16 int FractionLost(uint32_t num_lost_sequence_numbers,
17                  uint32_t num_sequence_numbers) {
18   if (num_sequence_numbers == 0) {
19     return 0;
20   }
21   return ((num_lost_sequence_numbers * 255) + (num_sequence_numbers / 2)) /
22       num_sequence_numbers;
23 }
24 }  // namespace
25 
26 
27 // Helper class for rtcp statistics.
ReportBlockStats()28 ReportBlockStats::ReportBlockStats()
29     : num_sequence_numbers_(0),
30       num_lost_sequence_numbers_(0) {
31 }
32 
Store(const RtcpStatistics & rtcp_stats,uint32_t remote_ssrc,uint32_t source_ssrc)33 void ReportBlockStats::Store(const RtcpStatistics& rtcp_stats,
34                              uint32_t remote_ssrc,
35                              uint32_t source_ssrc) {
36   RTCPReportBlock block;
37   block.cumulativeLost = rtcp_stats.cumulative_lost;
38   block.fractionLost = rtcp_stats.fraction_lost;
39   block.extendedHighSeqNum = rtcp_stats.extended_max_sequence_number;
40   block.jitter = rtcp_stats.jitter;
41   block.remoteSSRC = remote_ssrc;
42   block.sourceSSRC = source_ssrc;
43   uint32_t num_sequence_numbers = 0;
44   uint32_t num_lost_sequence_numbers = 0;
45   StoreAndAddPacketIncrement(
46       block, &num_sequence_numbers, &num_lost_sequence_numbers);
47 }
48 
AggregateAndStore(const ReportBlockVector & report_blocks)49 RTCPReportBlock ReportBlockStats::AggregateAndStore(
50     const ReportBlockVector& report_blocks) {
51   RTCPReportBlock aggregate;
52   if (report_blocks.empty()) {
53     return aggregate;
54   }
55   uint32_t num_sequence_numbers = 0;
56   uint32_t num_lost_sequence_numbers = 0;
57   ReportBlockVector::const_iterator report_block = report_blocks.begin();
58   for (; report_block != report_blocks.end(); ++report_block) {
59     aggregate.cumulativeLost += report_block->cumulativeLost;
60     aggregate.jitter += report_block->jitter;
61     StoreAndAddPacketIncrement(*report_block,
62                                &num_sequence_numbers,
63                                &num_lost_sequence_numbers);
64   }
65 
66   if (report_blocks.size() == 1) {
67     // No aggregation needed.
68     return report_blocks[0];
69   }
70   // Fraction lost since previous report block.
71   aggregate.fractionLost =
72       FractionLost(num_lost_sequence_numbers, num_sequence_numbers);
73   aggregate.jitter =
74       (aggregate.jitter + report_blocks.size() / 2) / report_blocks.size();
75   return aggregate;
76 }
77 
StoreAndAddPacketIncrement(const RTCPReportBlock & report_block,uint32_t * num_sequence_numbers,uint32_t * num_lost_sequence_numbers)78 void ReportBlockStats::StoreAndAddPacketIncrement(
79     const RTCPReportBlock& report_block,
80     uint32_t* num_sequence_numbers,
81     uint32_t* num_lost_sequence_numbers) {
82   // Get diff with previous report block.
83   ReportBlockMap::iterator prev_report_block = prev_report_blocks_.find(
84         report_block.sourceSSRC);
85   if (prev_report_block != prev_report_blocks_.end()) {
86     int seq_num_diff = report_block.extendedHighSeqNum -
87                        prev_report_block->second.extendedHighSeqNum;
88     int cum_loss_diff = report_block.cumulativeLost -
89                         prev_report_block->second.cumulativeLost;
90     if (seq_num_diff >= 0 && cum_loss_diff >= 0) {
91       *num_sequence_numbers += seq_num_diff;
92       *num_lost_sequence_numbers += cum_loss_diff;
93       // Update total number of packets/lost packets.
94       num_sequence_numbers_ += seq_num_diff;
95       num_lost_sequence_numbers_ += cum_loss_diff;
96     }
97   }
98   // Store current report block.
99   prev_report_blocks_[report_block.sourceSSRC] = report_block;
100 }
101 
FractionLostInPercent() const102 int ReportBlockStats::FractionLostInPercent() const {
103   if (num_sequence_numbers_ == 0) {
104     return -1;
105   }
106   return FractionLost(
107       num_lost_sequence_numbers_, num_sequence_numbers_) * 100 / 255;
108 }
109 
110 }  // namespace webrtc
111 
112