为了计算2帧/组数据之间的传输时间延迟(发送端时间戳差,接收端接收时间差),传输字节大小差
可能网络设备会把多个包聚合到一起进行发送的问题
-
构造
// timestamp_group_length_ticks:时间戳间隔少于这个值,表示是一组数据 // timestamp_to_ms_coeff: 时间戳到ms的转化系数 // enable_burst_grouping: 是否根据接收时间进行分组,一些网络设备会聚合一坨数据,到达时间片后一起发送出去 InterArrival(uint32_t timestamp_group_length_ticks, double timestamp_to_ms_coeff, bool enable_burst_grouping);
-
计算出发送时间差(timestamp_delta),接收时间差(arrival_time_delta_ms),传输字节大小差(packet_size_delta)
主要使用下面2个成员变量进行计算
- 当前的聚合包信息
TimestampGroup current_timestamp_group_; - 上一次的聚合包信息
TimestampGroup prev_timestamp_group_;
- 当前的聚合包信息
–
//timestamp:当前包时间戳
//arrival_time_ms:接收时间
//system_time_ms:当前时间
//packet_size:数据包大小
//如果成功计算出结果则返回true
bool 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){
bool calculated_deltas = false;
if (current_timestamp_group_.IsFirstPacket()) {
//第一个包,更新当前组的开始时间错,和最近的时间错
current_timestamp_group_.timestamp = timestamp;
current_timestamp_group_.first_timestamp = timestamp;
} else if (!PacketInOrder(timestamp)) {
//是否顺序的包,timestamp递增的
return false;
} else if (NewTimestampGroup(arrival_time_ms, timestamp)){
//一组新的数据
if (prev_timestamp_group_.complete_time_ms >= 0) {
//发送时间差
*timestamp_delta=current_timestamp_group_.timestamp-prev_timestamp_group_.timestamp;
//接收时间差
*arrival_time_delta_ms=current_timestamp_group_.complete_time_ms-prev_timestamp_group_.complete_time_ms;
//
int64_t system_time_delta_ms =current_timestamp_group_.last_system_time_ms-prev_timestamp_group_.last_system_time_ms;
if (*arrival_time_delta_ms - system_time_delta_ms >=kArrivalTimeOffsetThresholdMs) {
//数据异常了,重置一下 ,正常情况下system_time_delta_ms和*arrival_time_delta_ms基本一致的
Reset();
return false;
}
if (*arrival_time_delta_ms < 0) {
//异常,
// 当前包的到达时间还比上一个包的到达时间早,连续出现多次以后重置
num_consecutive_reordered_packets_++;
return false;
} else {
num_consecutive_reordered_packets_ = 0;
}
*packet_size_delta = static_cast<int>(current_timestamp_group_.size) -
static_cast<int>(prev_timestamp_group_.size);
calculated_deltas = true;
}
//使用新的group
prev_timestamp_group_ = current_timestamp_group_;
current_timestamp_group_.first_timestamp = timestamp;
current_timestamp_group_.timestamp = timestamp;
current_timestamp_group_.size = 0;
} else {
//更新时间戳到这组数据中的最近时间戳上
current_timestamp_group_.timestamp = LatestTimestamp(
current_timestamp_group_.timestamp, timestamp);
}
// 累加当前组数据的大小,最后的到达时间,当前的系统时间
current_timestamp_group_.size += packet_size;
current_timestamp_group_.complete_time_ms = arrival_time_ms;
current_timestamp_group_.last_system_time_ms = system_time_ms;
return calculated_deltas;
}
3.判断是否一个新的group
bool NewTimestampGroup(int64_t arrival_time_ms, uint32_t timestamp) const {
if (current_timestamp_group_.IsFirstPacket()){
//第一包数据,肯定不是新的group
return false;
} else if (BelongsToBurst(arrival_time_ms, timestamp)) {
//如果更上一帧数据可能被网络设备聚合过
return false;
} else {
//时间戳相差比较大的情况下判断为另一组
uint32_t timestamp_diff = timestamp -current_timestamp_group_.first_timestamp;
return timestamp_diff > kTimestampGroupLengthTicks;
}
}
-
是否被网络设备聚合过了
bool InterArrival::BelongsToBurst(int64_t arrival_time_ms, uint32_t timestamp) const { if (!burst_grouping_) { return false; } // // 计算跟上一次的到达时间差值(接收时间差) d1 assert(current_timestamp_group_.complete_time_ms >= 0); int64_t arrival_time_delta_ms = arrival_time_ms - current_timestamp_group_.complete_time_ms; // //计算跟上一次的时间戳差值(发送时间差) d2 uint32_t timestamp_diff = timestamp - current_timestamp_group_.timestamp; int64_t ts_delta_ms = timestamp_to_ms_coeff_ * timestamp_diff + 0.5; if (ts_delta_ms == 0) return true; // // 计算一下传输影响的相对差值 d1-d2 理论上如果没有网络影响 d1-d2>=0 int propagation_delta_ms = arrival_time_delta_ms - ts_delta_ms; // // 如果差值< 0 并且接收间隔<kBurstDeltaThresholdMs则可以认定为同一个聚合 // 可能无线设备,路由器进行了聚合 return propagation_delta_ms < 0 && arrival_time_delta_ms <= kBurstDeltaThresholdMs; }