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 { 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. 28 ReportBlockStats::ReportBlockStats() 29 : num_sequence_numbers_(0), 30 num_lost_sequence_numbers_(0) { 31 } 32 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 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 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 102 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