1 // Copyright 2019 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 "cast/streaming/packet_receive_stats_tracker.h"
6
7 #include <algorithm>
8
9 namespace openscreen {
10 namespace cast {
11
PacketReceiveStatsTracker(int rtp_timebase)12 PacketReceiveStatsTracker::PacketReceiveStatsTracker(int rtp_timebase)
13 : rtp_timebase_(rtp_timebase) {}
14
15 PacketReceiveStatsTracker::~PacketReceiveStatsTracker() = default;
16
OnReceivedValidRtpPacket(uint16_t sequence_number,RtpTimeTicks rtp_timestamp,Clock::time_point arrival_time)17 void PacketReceiveStatsTracker::OnReceivedValidRtpPacket(
18 uint16_t sequence_number,
19 RtpTimeTicks rtp_timestamp,
20 Clock::time_point arrival_time) {
21 if (num_rtp_packets_received_ == 0) {
22 // Since this is the very first packet received, initialize all other
23 // tracking stats.
24 num_rtp_packets_received_at_last_report_ = 0;
25 greatest_sequence_number_ = PacketSequenceNumber(sequence_number);
26 base_sequence_number_ = greatest_sequence_number_.previous();
27 greatest_sequence_number_at_last_report_ = base_sequence_number_;
28 jitter_ = Clock::duration::zero();
29 } else {
30 // Update the greatest sequence number ever seen.
31 const auto expanded_sequence_number =
32 greatest_sequence_number_.Expand(sequence_number);
33 if (expanded_sequence_number > greatest_sequence_number_) {
34 greatest_sequence_number_ = expanded_sequence_number;
35 }
36
37 // Update the interarrival jitter. This is similar to the calculation in
38 // Appendix A of the RFC 3550 spec (for RTP).
39 const Clock::duration time_between_arrivals =
40 arrival_time - last_rtp_packet_arrival_time_;
41 const auto media_time_difference =
42 (rtp_timestamp - last_rtp_packet_timestamp_)
43 .ToDuration<Clock::duration>(rtp_timebase_);
44 const auto delta = time_between_arrivals - media_time_difference;
45 const auto absolute_delta =
46 (delta < decltype(delta)::zero()) ? -delta : delta;
47 jitter_ += (absolute_delta - jitter_) / 16;
48 }
49
50 ++num_rtp_packets_received_;
51 last_rtp_packet_arrival_time_ = arrival_time;
52 last_rtp_packet_timestamp_ = rtp_timestamp;
53 }
54
PopulateNextReport(RtcpReportBlock * report)55 void PacketReceiveStatsTracker::PopulateNextReport(RtcpReportBlock* report) {
56 if (num_rtp_packets_received_ <= 0) {
57 // None of the packet loss, etc., tracking has valid values yet; so don't
58 // populate anything.
59 return;
60 }
61
62 report->SetPacketFractionLostNumerator(
63 greatest_sequence_number_ - greatest_sequence_number_at_last_report_,
64 num_rtp_packets_received_ - num_rtp_packets_received_at_last_report_);
65 greatest_sequence_number_at_last_report_ = greatest_sequence_number_;
66 num_rtp_packets_received_at_last_report_ = num_rtp_packets_received_;
67
68 report->SetCumulativePacketsLost(
69 greatest_sequence_number_ - base_sequence_number_,
70 num_rtp_packets_received_);
71
72 report->extended_high_sequence_number =
73 greatest_sequence_number_.lower_32_bits();
74
75 report->jitter = RtpTimeDelta::FromDuration(jitter_, rtp_timebase_);
76 }
77
78 } // namespace cast
79 } // namespace openscreen
80