• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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