blob: 65193370dc482ad052cc2663c10da517f2df41cb [file] [log] [blame]
/*
* Copyright (c) 2011 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 "modules/audio_coding/neteq/rtcp.h"
#include <algorithm>
#include <cstdlib>
#include "api/rtp_headers.h"
#include "common_types.h"
#include "rtc_base/checks.h"
namespace webrtc {
void Rtcp::Init(uint16_t start_sequence_number) {
cycles_ = 0;
max_seq_no_ = start_sequence_number;
base_seq_no_ = start_sequence_number;
received_packets_ = 0;
received_packets_prior_ = 0;
expected_prior_ = 0;
jitter_ = 0;
transit_ = 0;
}
void Rtcp::Update(const RTPHeader& rtp_header, uint32_t receive_timestamp) {
// Update number of received packets, and largest packet number received.
received_packets_++;
int16_t sn_diff = rtp_header.sequenceNumber - max_seq_no_;
if (sn_diff >= 0) {
if (rtp_header.sequenceNumber < max_seq_no_) {
// Wrap-around detected.
cycles_++;
}
max_seq_no_ = rtp_header.sequenceNumber;
}
// Calculate jitter according to RFC 3550, and update previous timestamps.
// Note that the value in |jitter_| is in Q4.
if (received_packets_ > 1) {
int32_t ts_diff = receive_timestamp - (rtp_header.timestamp - transit_);
int64_t jitter_diff = (std::abs(int64_t{ts_diff}) << 4) - jitter_;
// Calculate 15 * jitter_ / 16 + jitter_diff / 16 (with proper rounding).
jitter_ = jitter_ + ((jitter_diff + 8) >> 4);
RTC_DCHECK_GE(jitter_, 0);
}
transit_ = rtp_header.timestamp - receive_timestamp;
}
void Rtcp::GetStatistics(bool no_reset, RtcpStatistics* stats) {
// Extended highest sequence number received.
stats->extended_highest_sequence_number =
(static_cast<int>(cycles_) << 16) + max_seq_no_;
// Calculate expected number of packets and compare it with the number of
// packets that were actually received. The cumulative number of lost packets
// can be extracted.
uint32_t expected_packets =
stats->extended_highest_sequence_number - base_seq_no_ + 1;
if (received_packets_ == 0) {
// No packets received, assume none lost.
stats->packets_lost = 0;
} else if (expected_packets > received_packets_) {
stats->packets_lost = expected_packets - received_packets_;
if (stats->packets_lost > 0xFFFFFF) {
stats->packets_lost = 0xFFFFFF;
}
} else {
stats->packets_lost = 0;
}
// Fraction lost since last report.
uint32_t expected_since_last = expected_packets - expected_prior_;
uint32_t received_since_last = received_packets_ - received_packets_prior_;
if (!no_reset) {
expected_prior_ = expected_packets;
received_packets_prior_ = received_packets_;
}
int32_t lost = expected_since_last - received_since_last;
if (expected_since_last == 0 || lost <= 0 || received_packets_ == 0) {
stats->fraction_lost = 0;
} else {
stats->fraction_lost = std::min(0xFFU, (lost << 8) / expected_since_last);
}
stats->jitter = jitter_ >> 4; // Scaling from Q4.
}
} // namespace webrtc