19a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org/* 29a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 39a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * 49a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * Use of this source code is governed by a BSD-style license 59a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * that can be found in the LICENSE file in the root of the source 69a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * tree. An additional intellectual property rights grant can be found 79a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * in the file PATENTS. All contributing project authors may 89a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org * be found in the AUTHORS file in the root of the source tree. 99a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org */ 109a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 11e5abc854f3dc47de16067c2a41476c39b7626722henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/rtcp.h" 129a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 139a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org#include <string.h> 149a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 15201049cd791b718821495a7951e1d3d9ea3bf1c1henrik.lundin@webrtc.org#include <algorithm> 16201049cd791b718821495a7951e1d3d9ea3bf1c1henrik.lundin@webrtc.org 179a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" 189a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org#include "webrtc/modules/interface/module_common_types.h" 199a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 209a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgnamespace webrtc { 219a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 229a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid Rtcp::Init(uint16_t start_sequence_number) { 239a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org cycles_ = 0; 249a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org max_seq_no_ = start_sequence_number; 259a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org base_seq_no_ = start_sequence_number; 269a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org received_packets_ = 0; 279a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org received_packets_prior_ = 0; 289a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org expected_prior_ = 0; 299a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org jitter_ = 0; 309a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org transit_ = 0; 319a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 329a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 339a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid Rtcp::Update(const RTPHeader& rtp_header, uint32_t receive_timestamp) { 349a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Update number of received packets, and largest packet number received. 359a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org received_packets_++; 369a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int16_t sn_diff = rtp_header.sequenceNumber - max_seq_no_; 379a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (sn_diff >= 0) { 389a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (rtp_header.sequenceNumber < max_seq_no_) { 399a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Wrap-around detected. 409a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org cycles_++; 419a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 429a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org max_seq_no_ = rtp_header.sequenceNumber; 439a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 449a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 459a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Calculate jitter according to RFC 3550, and update previous timestamps. 469a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Note that the value in |jitter_| is in Q4. 479a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (received_packets_ > 1) { 489a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int32_t ts_diff = receive_timestamp - (rtp_header.timestamp - transit_); 499a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org ts_diff = WEBRTC_SPL_ABS_W32(ts_diff); 509a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int32_t jitter_diff = (ts_diff << 4) - jitter_; 519a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Calculate 15 * jitter_ / 16 + jitter_diff / 16 (with proper rounding). 529a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org jitter_ = jitter_ + ((jitter_diff + 8) >> 4); 539a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 549a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org transit_ = rtp_header.timestamp - receive_timestamp; 559a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 569a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 579a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.orgvoid Rtcp::GetStatistics(bool no_reset, RtcpStatistics* stats) { 589a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Extended highest sequence number received. 592714c796f7d474b58ae4eab18b6863d7988a3487sprang@webrtc.org stats->extended_max_sequence_number = 602714c796f7d474b58ae4eab18b6863d7988a3487sprang@webrtc.org (static_cast<int>(cycles_) << 16) + max_seq_no_; 619a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 629a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Calculate expected number of packets and compare it with the number of 639a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // packets that were actually received. The cumulative number of lost packets 649a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // can be extracted. 652714c796f7d474b58ae4eab18b6863d7988a3487sprang@webrtc.org uint32_t expected_packets = 662714c796f7d474b58ae4eab18b6863d7988a3487sprang@webrtc.org stats->extended_max_sequence_number - base_seq_no_ + 1; 679a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (received_packets_ == 0) { 689a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // No packets received, assume none lost. 699a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org stats->cumulative_lost = 0; 709a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else if (expected_packets > received_packets_) { 719a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org stats->cumulative_lost = expected_packets - received_packets_; 729a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (stats->cumulative_lost > 0xFFFFFF) { 739a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org stats->cumulative_lost = 0xFFFFFF; 749a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 759a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else { 769a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org stats->cumulative_lost = 0; 779a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 789a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 799a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org // Fraction lost since last report. 809a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org uint32_t expected_since_last = expected_packets - expected_prior_; 819a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org uint32_t received_since_last = received_packets_ - received_packets_prior_; 829a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (!no_reset) { 839a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org expected_prior_ = expected_packets; 849a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org received_packets_prior_ = received_packets_; 859a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 869a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org int32_t lost = expected_since_last - received_since_last; 879a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org if (expected_since_last == 0 || lost <= 0 || received_packets_ == 0) { 889a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org stats->fraction_lost = 0; 899a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } else { 902714c796f7d474b58ae4eab18b6863d7988a3487sprang@webrtc.org stats->fraction_lost = std::min(0xFFU, (lost << 8) / expected_since_last); 919a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org } 929a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 939a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org stats->jitter = jitter_ >> 4; // Scaling from Q4. 949a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} 959a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org 969a400812ca0006d12e538d465ab6728a8ecd07aahenrik.lundin@webrtc.org} // namespace webrtc 97