Home | History | Annotate | Download | only in rtp
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "media/cast/net/rtp/receiver_stats.h"
      6 
      7 #include "base/logging.h"
      8 #include "media/cast/net/rtp/rtp_receiver_defines.h"
      9 
     10 namespace media {
     11 namespace cast {
     12 
     13 static const uint32 kMaxSequenceNumber = 65536;
     14 
     15 ReceiverStats::ReceiverStats(base::TickClock* clock)
     16     : clock_(clock),
     17       min_sequence_number_(0),
     18       max_sequence_number_(0),
     19       total_number_packets_(0),
     20       sequence_number_cycles_(0),
     21       interval_min_sequence_number_(0),
     22       interval_number_packets_(0),
     23       interval_wrap_count_(0) {}
     24 
     25 ReceiverStats::~ReceiverStats() {}
     26 
     27 void ReceiverStats::GetStatistics(uint8* fraction_lost,
     28                                   uint32* cumulative_lost,
     29                                   uint32* extended_high_sequence_number,
     30                                   uint32* jitter) {
     31   // Compute losses.
     32   if (interval_number_packets_ == 0) {
     33     *fraction_lost = 0;
     34   } else {
     35     int diff = 0;
     36     if (interval_wrap_count_ == 0) {
     37       diff = max_sequence_number_ - interval_min_sequence_number_ + 1;
     38     } else {
     39       diff = kMaxSequenceNumber * (interval_wrap_count_ - 1) +
     40              (max_sequence_number_ - interval_min_sequence_number_ +
     41               kMaxSequenceNumber + 1);
     42     }
     43 
     44     if (diff < 1) {
     45       *fraction_lost = 0;
     46     } else {
     47       float tmp_ratio =
     48           (1 - static_cast<float>(interval_number_packets_) / abs(diff));
     49       *fraction_lost = static_cast<uint8>(256 * tmp_ratio);
     50     }
     51   }
     52 
     53   int expected_packets_num = max_sequence_number_ - min_sequence_number_ + 1;
     54   if (total_number_packets_ == 0) {
     55     *cumulative_lost = 0;
     56   } else if (sequence_number_cycles_ == 0) {
     57     *cumulative_lost = expected_packets_num - total_number_packets_;
     58   } else {
     59     *cumulative_lost =
     60         kMaxSequenceNumber * (sequence_number_cycles_ - 1) +
     61         (expected_packets_num - total_number_packets_ + kMaxSequenceNumber);
     62   }
     63 
     64   // Extended high sequence number consists of the highest seq number and the
     65   // number of cycles (wrap).
     66   *extended_high_sequence_number =
     67       (sequence_number_cycles_ << 16) + max_sequence_number_;
     68 
     69   *jitter = static_cast<uint32>(std::abs(jitter_.InMillisecondsRoundedUp()));
     70 
     71   // Reset interval values.
     72   interval_min_sequence_number_ = 0;
     73   interval_number_packets_ = 0;
     74   interval_wrap_count_ = 0;
     75 }
     76 
     77 void ReceiverStats::UpdateStatistics(const RtpCastHeader& header) {
     78   const uint16 new_seq_num = header.sequence_number;
     79 
     80   if (interval_number_packets_ == 0) {
     81     // First packet in the interval.
     82     interval_min_sequence_number_ = new_seq_num;
     83   }
     84   if (total_number_packets_ == 0) {
     85     // First incoming packet.
     86     min_sequence_number_ = new_seq_num;
     87     max_sequence_number_ = new_seq_num;
     88   }
     89 
     90   if (IsNewerSequenceNumber(new_seq_num, max_sequence_number_)) {
     91     // Check wrap.
     92     if (new_seq_num < max_sequence_number_) {
     93       ++sequence_number_cycles_;
     94       ++interval_wrap_count_;
     95     }
     96     max_sequence_number_ = new_seq_num;
     97   }
     98 
     99   // Compute Jitter.
    100   base::TimeTicks now = clock_->NowTicks();
    101   base::TimeDelta delta_new_timestamp =
    102       base::TimeDelta::FromMilliseconds(header.rtp_timestamp);
    103   if (total_number_packets_ > 0) {
    104     // Update jitter.
    105     base::TimeDelta delta =
    106         (now - last_received_packet_time_) -
    107         ((delta_new_timestamp - last_received_timestamp_) / 90);
    108     jitter_ += (delta - jitter_) / 16;
    109   }
    110   last_received_timestamp_ = delta_new_timestamp;
    111   last_received_packet_time_ = now;
    112 
    113   // Increment counters.
    114   ++total_number_packets_;
    115   ++interval_number_packets_;
    116 }
    117 
    118 }  // namespace cast
    119 }  // namespace media
    120