// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "cast/streaming/packet_receive_stats_tracker.h" #include namespace openscreen { namespace cast { PacketReceiveStatsTracker::PacketReceiveStatsTracker(int rtp_timebase) : rtp_timebase_(rtp_timebase) {} PacketReceiveStatsTracker::~PacketReceiveStatsTracker() = default; void PacketReceiveStatsTracker::OnReceivedValidRtpPacket( uint16_t sequence_number, RtpTimeTicks rtp_timestamp, Clock::time_point arrival_time) { if (num_rtp_packets_received_ == 0) { // Since this is the very first packet received, initialize all other // tracking stats. num_rtp_packets_received_at_last_report_ = 0; greatest_sequence_number_ = PacketSequenceNumber(sequence_number); base_sequence_number_ = greatest_sequence_number_.previous(); greatest_sequence_number_at_last_report_ = base_sequence_number_; jitter_ = Clock::duration::zero(); } else { // Update the greatest sequence number ever seen. const auto expanded_sequence_number = greatest_sequence_number_.Expand(sequence_number); if (expanded_sequence_number > greatest_sequence_number_) { greatest_sequence_number_ = expanded_sequence_number; } // Update the interarrival jitter. This is similar to the calculation in // Appendix A of the RFC 3550 spec (for RTP). const Clock::duration time_between_arrivals = arrival_time - last_rtp_packet_arrival_time_; const auto media_time_difference = (rtp_timestamp - last_rtp_packet_timestamp_) .ToDuration(rtp_timebase_); const auto delta = time_between_arrivals - media_time_difference; const auto absolute_delta = (delta < decltype(delta)::zero()) ? -delta : delta; jitter_ += (absolute_delta - jitter_) / 16; } ++num_rtp_packets_received_; last_rtp_packet_arrival_time_ = arrival_time; last_rtp_packet_timestamp_ = rtp_timestamp; } void PacketReceiveStatsTracker::PopulateNextReport(RtcpReportBlock* report) { if (num_rtp_packets_received_ <= 0) { // None of the packet loss, etc., tracking has valid values yet; so don't // populate anything. return; } report->SetPacketFractionLostNumerator( greatest_sequence_number_ - greatest_sequence_number_at_last_report_, num_rtp_packets_received_ - num_rtp_packets_received_at_last_report_); greatest_sequence_number_at_last_report_ = greatest_sequence_number_; num_rtp_packets_received_at_last_report_ = num_rtp_packets_received_; report->SetCumulativePacketsLost( greatest_sequence_number_ - base_sequence_number_, num_rtp_packets_received_); report->extended_high_sequence_number = greatest_sequence_number_.lower_32_bits(); report->jitter = RtpTimeDelta::FromDuration(jitter_, rtp_timebase_); } } // namespace cast } // namespace openscreen