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