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