diff options
Diffstat (limited to 'webrtc/video/report_block_stats.cc')
-rw-r--r-- | webrtc/video/report_block_stats.cc | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/webrtc/video/report_block_stats.cc b/webrtc/video/report_block_stats.cc new file mode 100644 index 0000000000..dee5662c3c --- /dev/null +++ b/webrtc/video/report_block_stats.cc @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/video/report_block_stats.h" + +namespace webrtc { + +namespace { +int FractionLost(uint32_t num_lost_sequence_numbers, + uint32_t num_sequence_numbers) { + if (num_sequence_numbers == 0) { + return 0; + } + return ((num_lost_sequence_numbers * 255) + (num_sequence_numbers / 2)) / + num_sequence_numbers; +} +} // namespace + + +// Helper class for rtcp statistics. +ReportBlockStats::ReportBlockStats() + : num_sequence_numbers_(0), + num_lost_sequence_numbers_(0) { +} + +void ReportBlockStats::Store(const RtcpStatistics& rtcp_stats, + uint32_t remote_ssrc, + uint32_t source_ssrc) { + RTCPReportBlock block; + block.cumulativeLost = rtcp_stats.cumulative_lost; + block.fractionLost = rtcp_stats.fraction_lost; + block.extendedHighSeqNum = rtcp_stats.extended_max_sequence_number; + block.jitter = rtcp_stats.jitter; + block.remoteSSRC = remote_ssrc; + block.sourceSSRC = source_ssrc; + uint32_t num_sequence_numbers = 0; + uint32_t num_lost_sequence_numbers = 0; + StoreAndAddPacketIncrement( + block, &num_sequence_numbers, &num_lost_sequence_numbers); +} + +RTCPReportBlock ReportBlockStats::AggregateAndStore( + const ReportBlockVector& report_blocks) { + RTCPReportBlock aggregate; + if (report_blocks.empty()) { + return aggregate; + } + uint32_t num_sequence_numbers = 0; + uint32_t num_lost_sequence_numbers = 0; + ReportBlockVector::const_iterator report_block = report_blocks.begin(); + for (; report_block != report_blocks.end(); ++report_block) { + aggregate.cumulativeLost += report_block->cumulativeLost; + aggregate.jitter += report_block->jitter; + StoreAndAddPacketIncrement(*report_block, + &num_sequence_numbers, + &num_lost_sequence_numbers); + } + + if (report_blocks.size() == 1) { + // No aggregation needed. + return report_blocks[0]; + } + // Fraction lost since previous report block. + aggregate.fractionLost = + FractionLost(num_lost_sequence_numbers, num_sequence_numbers); + aggregate.jitter = static_cast<uint32_t>( + (aggregate.jitter + report_blocks.size() / 2) / report_blocks.size()); + return aggregate; +} + +void ReportBlockStats::StoreAndAddPacketIncrement( + const RTCPReportBlock& report_block, + uint32_t* num_sequence_numbers, + uint32_t* num_lost_sequence_numbers) { + // Get diff with previous report block. + ReportBlockMap::iterator prev_report_block = prev_report_blocks_.find( + report_block.sourceSSRC); + if (prev_report_block != prev_report_blocks_.end()) { + int seq_num_diff = report_block.extendedHighSeqNum - + prev_report_block->second.extendedHighSeqNum; + int cum_loss_diff = report_block.cumulativeLost - + prev_report_block->second.cumulativeLost; + if (seq_num_diff >= 0 && cum_loss_diff >= 0) { + *num_sequence_numbers += seq_num_diff; + *num_lost_sequence_numbers += cum_loss_diff; + // Update total number of packets/lost packets. + num_sequence_numbers_ += seq_num_diff; + num_lost_sequence_numbers_ += cum_loss_diff; + } + } + // Store current report block. + prev_report_blocks_[report_block.sourceSSRC] = report_block; +} + +int ReportBlockStats::FractionLostInPercent() const { + if (num_sequence_numbers_ == 0) { + return -1; + } + return FractionLost( + num_lost_sequence_numbers_, num_sequence_numbers_) * 100 / 255; +} + +} // namespace webrtc + |