Home | History | Annotate | Download | only in video
      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