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