xref: /aosp_15_r20/external/webrtc/modules/remote_bitrate_estimator/inter_arrival.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "modules/remote_bitrate_estimator/inter_arrival.h"
12 
13 #include "modules/include/module_common_types_public.h"
14 #include "rtc_base/logging.h"
15 
16 namespace webrtc {
17 
18 static const int kBurstDeltaThresholdMs = 5;
19 static const int kMaxBurstDurationMs = 100;
20 
InterArrival(uint32_t timestamp_group_length_ticks,double timestamp_to_ms_coeff,bool enable_burst_grouping)21 InterArrival::InterArrival(uint32_t timestamp_group_length_ticks,
22                            double timestamp_to_ms_coeff,
23                            bool enable_burst_grouping)
24     : kTimestampGroupLengthTicks(timestamp_group_length_ticks),
25       current_timestamp_group_(),
26       prev_timestamp_group_(),
27       timestamp_to_ms_coeff_(timestamp_to_ms_coeff),
28       burst_grouping_(enable_burst_grouping),
29       num_consecutive_reordered_packets_(0) {}
30 
ComputeDeltas(uint32_t timestamp,int64_t arrival_time_ms,int64_t system_time_ms,size_t packet_size,uint32_t * timestamp_delta,int64_t * arrival_time_delta_ms,int * packet_size_delta)31 bool InterArrival::ComputeDeltas(uint32_t timestamp,
32                                  int64_t arrival_time_ms,
33                                  int64_t system_time_ms,
34                                  size_t packet_size,
35                                  uint32_t* timestamp_delta,
36                                  int64_t* arrival_time_delta_ms,
37                                  int* packet_size_delta) {
38   RTC_DCHECK(timestamp_delta);
39   RTC_DCHECK(arrival_time_delta_ms);
40   RTC_DCHECK(packet_size_delta);
41   bool calculated_deltas = false;
42   if (current_timestamp_group_.IsFirstPacket()) {
43     // We don't have enough data to update the filter, so we store it until we
44     // have two frames of data to process.
45     current_timestamp_group_.timestamp = timestamp;
46     current_timestamp_group_.first_timestamp = timestamp;
47     current_timestamp_group_.first_arrival_ms = arrival_time_ms;
48   } else if (!PacketInOrder(timestamp)) {
49     return false;
50   } else if (NewTimestampGroup(arrival_time_ms, timestamp)) {
51     // First packet of a later frame, the previous frame sample is ready.
52     if (prev_timestamp_group_.complete_time_ms >= 0) {
53       *timestamp_delta =
54           current_timestamp_group_.timestamp - prev_timestamp_group_.timestamp;
55       *arrival_time_delta_ms = current_timestamp_group_.complete_time_ms -
56                                prev_timestamp_group_.complete_time_ms;
57       // Check system time differences to see if we have an unproportional jump
58       // in arrival time. In that case reset the inter-arrival computations.
59       int64_t system_time_delta_ms =
60           current_timestamp_group_.last_system_time_ms -
61           prev_timestamp_group_.last_system_time_ms;
62       if (*arrival_time_delta_ms - system_time_delta_ms >=
63           kArrivalTimeOffsetThresholdMs) {
64         RTC_LOG(LS_WARNING)
65             << "The arrival time clock offset has changed (diff = "
66             << *arrival_time_delta_ms - system_time_delta_ms
67             << " ms), resetting.";
68         Reset();
69         return false;
70       }
71       if (*arrival_time_delta_ms < 0) {
72         // The group of packets has been reordered since receiving its local
73         // arrival timestamp.
74         ++num_consecutive_reordered_packets_;
75         if (num_consecutive_reordered_packets_ >= kReorderedResetThreshold) {
76           RTC_LOG(LS_WARNING)
77               << "Packets are being reordered on the path from the "
78                  "socket to the bandwidth estimator. Ignoring this "
79                  "packet for bandwidth estimation, resetting.";
80           Reset();
81         }
82         return false;
83       } else {
84         num_consecutive_reordered_packets_ = 0;
85       }
86       RTC_DCHECK_GE(*arrival_time_delta_ms, 0);
87       *packet_size_delta = static_cast<int>(current_timestamp_group_.size) -
88                            static_cast<int>(prev_timestamp_group_.size);
89       calculated_deltas = true;
90     }
91     prev_timestamp_group_ = current_timestamp_group_;
92     // The new timestamp is now the current frame.
93     current_timestamp_group_.first_timestamp = timestamp;
94     current_timestamp_group_.timestamp = timestamp;
95     current_timestamp_group_.first_arrival_ms = arrival_time_ms;
96     current_timestamp_group_.size = 0;
97   } else {
98     current_timestamp_group_.timestamp =
99         LatestTimestamp(current_timestamp_group_.timestamp, timestamp);
100   }
101   // Accumulate the frame size.
102   current_timestamp_group_.size += packet_size;
103   current_timestamp_group_.complete_time_ms = arrival_time_ms;
104   current_timestamp_group_.last_system_time_ms = system_time_ms;
105 
106   return calculated_deltas;
107 }
108 
PacketInOrder(uint32_t timestamp)109 bool InterArrival::PacketInOrder(uint32_t timestamp) {
110   if (current_timestamp_group_.IsFirstPacket()) {
111     return true;
112   } else {
113     // Assume that a diff which is bigger than half the timestamp interval
114     // (32 bits) must be due to reordering. This code is almost identical to
115     // that in IsNewerTimestamp() in module_common_types.h.
116     uint32_t timestamp_diff =
117         timestamp - current_timestamp_group_.first_timestamp;
118     return timestamp_diff < 0x80000000;
119   }
120 }
121 
122 // Assumes that `timestamp` is not reordered compared to
123 // `current_timestamp_group_`.
NewTimestampGroup(int64_t arrival_time_ms,uint32_t timestamp) const124 bool InterArrival::NewTimestampGroup(int64_t arrival_time_ms,
125                                      uint32_t timestamp) const {
126   if (current_timestamp_group_.IsFirstPacket()) {
127     return false;
128   } else if (BelongsToBurst(arrival_time_ms, timestamp)) {
129     return false;
130   } else {
131     uint32_t timestamp_diff =
132         timestamp - current_timestamp_group_.first_timestamp;
133     return timestamp_diff > kTimestampGroupLengthTicks;
134   }
135 }
136 
BelongsToBurst(int64_t arrival_time_ms,uint32_t timestamp) const137 bool InterArrival::BelongsToBurst(int64_t arrival_time_ms,
138                                   uint32_t timestamp) const {
139   if (!burst_grouping_) {
140     return false;
141   }
142   RTC_DCHECK_GE(current_timestamp_group_.complete_time_ms, 0);
143   int64_t arrival_time_delta_ms =
144       arrival_time_ms - current_timestamp_group_.complete_time_ms;
145   uint32_t timestamp_diff = timestamp - current_timestamp_group_.timestamp;
146   int64_t ts_delta_ms = timestamp_to_ms_coeff_ * timestamp_diff + 0.5;
147   if (ts_delta_ms == 0)
148     return true;
149   int propagation_delta_ms = arrival_time_delta_ms - ts_delta_ms;
150   if (propagation_delta_ms < 0 &&
151       arrival_time_delta_ms <= kBurstDeltaThresholdMs &&
152       arrival_time_ms - current_timestamp_group_.first_arrival_ms <
153           kMaxBurstDurationMs)
154     return true;
155   return false;
156 }
157 
Reset()158 void InterArrival::Reset() {
159   num_consecutive_reordered_packets_ = 0;
160   current_timestamp_group_ = TimestampGroup();
161   prev_timestamp_group_ = TimestampGroup();
162 }
163 }  // namespace webrtc
164