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/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 = static_cast<uint32_t>(
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