1 // Copyright 2013 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/rtp_receiver/receiver_stats.h" 6 7 #include "base/logging.h" 8 #include "media/cast/rtp_receiver/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 *fraction_lost = static_cast<uint8>((256 * (1 - 48 static_cast<float>(interval_number_packets_) / abs(diff)))); 49 } 50 } 51 52 int expected_packets_num = max_sequence_number_ - min_sequence_number_ + 1; 53 if (total_number_packets_ == 0) { 54 *cumulative_lost = 0; 55 } else if (sequence_number_cycles_ == 0) { 56 *cumulative_lost = expected_packets_num - total_number_packets_; 57 } else { 58 *cumulative_lost = kMaxSequenceNumber * (sequence_number_cycles_ - 1) + 59 (expected_packets_num - total_number_packets_ + kMaxSequenceNumber); 60 } 61 62 // Extended high sequence number consists of the highest seq number and the 63 // number of cycles (wrap). 64 *extended_high_sequence_number = (sequence_number_cycles_ << 16) + 65 max_sequence_number_; 66 67 *jitter = static_cast<uint32>(abs(jitter_.InMillisecondsRoundedUp())); 68 69 // Reset interval values. 70 interval_min_sequence_number_ = 0; 71 interval_number_packets_ = 0; 72 interval_wrap_count_ = 0; 73 } 74 75 void ReceiverStats::UpdateStatistics(const RtpCastHeader& header) { 76 uint16 new_seq_num = header.webrtc.header.sequenceNumber; 77 78 if (interval_number_packets_ == 0) { 79 // First packet in the interval. 80 interval_min_sequence_number_ = new_seq_num; 81 } 82 if (total_number_packets_ == 0) { 83 // First incoming packet. 84 min_sequence_number_ = new_seq_num; 85 max_sequence_number_ = new_seq_num; 86 } 87 88 if (IsNewerSequenceNumber(new_seq_num, max_sequence_number_)) { 89 // Check wrap. 90 if (new_seq_num < max_sequence_number_) { 91 ++sequence_number_cycles_; 92 ++interval_wrap_count_; 93 } 94 max_sequence_number_ = new_seq_num; 95 } 96 97 // Compute Jitter. 98 base::TimeTicks now = clock_->NowTicks(); 99 base::TimeDelta delta_new_timestamp = 100 base::TimeDelta::FromMilliseconds(header.webrtc.header.timestamp); 101 if (total_number_packets_ > 0) { 102 // Update jitter. 103 base::TimeDelta delta = (now - last_received_packet_time_) - 104 ((delta_new_timestamp - last_received_timestamp_) / 90); 105 jitter_ += (delta - jitter_) / 16; 106 } 107 last_received_timestamp_ = delta_new_timestamp; 108 last_received_packet_time_ = now; 109 110 // Increment counters. 111 ++total_number_packets_; 112 ++interval_number_packets_; 113 } 114 115 } // namespace cast 116 } // namespace media 117