inter_arrival.cc (6637B)
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 <cstddef> 14 #include <cstdint> 15 16 #include "modules/include/module_common_types_public.h" 17 #include "rtc_base/checks.h" 18 #include "rtc_base/logging.h" 19 20 namespace webrtc { 21 22 static const int kBurstDeltaThresholdMs = 5; 23 static const int kMaxBurstDurationMs = 100; 24 25 InterArrival::InterArrival(uint32_t timestamp_group_length_ticks, 26 double timestamp_to_ms_coeff) 27 : kTimestampGroupLengthTicks(timestamp_group_length_ticks), 28 current_timestamp_group_(), 29 prev_timestamp_group_(), 30 timestamp_to_ms_coeff_(timestamp_to_ms_coeff), 31 num_consecutive_reordered_packets_(0) {} 32 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 RTC_DCHECK(timestamp_delta); 41 RTC_DCHECK(arrival_time_delta_ms); 42 RTC_DCHECK(packet_size_delta); 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 RTC_DCHECK_GE(*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 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_`. 126 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 139 bool InterArrival::BelongsToBurst(int64_t arrival_time_ms, 140 uint32_t timestamp) const { 141 RTC_DCHECK_GE(current_timestamp_group_.complete_time_ms, 0); 142 int64_t arrival_time_delta_ms = 143 arrival_time_ms - current_timestamp_group_.complete_time_ms; 144 uint32_t timestamp_diff = timestamp - current_timestamp_group_.timestamp; 145 int64_t ts_delta_ms = timestamp_to_ms_coeff_ * timestamp_diff + 0.5; 146 if (ts_delta_ms == 0) 147 return true; 148 int propagation_delta_ms = arrival_time_delta_ms - ts_delta_ms; 149 if (propagation_delta_ms < 0 && 150 arrival_time_delta_ms <= kBurstDeltaThresholdMs && 151 arrival_time_ms - current_timestamp_group_.first_arrival_ms < 152 kMaxBurstDurationMs) 153 return true; 154 return false; 155 } 156 157 void InterArrival::Reset() { 158 num_consecutive_reordered_packets_ = 0; 159 current_timestamp_group_ = TimestampGroup(); 160 prev_timestamp_group_ = TimestampGroup(); 161 } 162 } // namespace webrtc