webrtc rtt 计算

article/2025/8/27 1:01:38

Definitions

  • RTT(Round-Trip Time): 往返时延。在计算机网络中它是一个重要的性能指标,表示从发送端发送数据开始,到发送端收到来自接收端的确认(接收端收到数据后便立即发送确认),总共经历的时延。

  • 一般认为单向时延=传输时延t1+传播时延t2+排队时延t3 t1是数据从进入节点到传输媒体所需要的时间,通常等于数据块长度/信道带宽 t2是信号在信道中需要传播一定距离而花费的时间,等于信道长度/传播速率(光纤中电磁波的传播速率约为210^5 km/s,铜缆中2.310^5 km/s) t3可笼统归纳为随机噪声,由途径的每一跳设备及收发两端负荷情况及吞吐排队情况决定(包含互联网设备和传输设备时延) 综上:时延并无标准值只有经验值。某运营商规定网内路由器间时延1000公里之内<=40ms,2000公里之内<=60ms,3000公里之内<=80ms

RTT Calculation

大写S代表发送时间,R代表接收时间,D代表延时 S(a0) A------------------------------------------------------ > B R( b0)

S(a0) D(b0) A<--------------------------------------------------------B D(b0) = S(b0) - R(b0)

1,A先发一个数据包,在本地记录下发送时间 S(a0),并把 S(a0)放在数据包中发给B 2,B收到数据包,在本地记录下数据接收时间R( b0),并把数据包发回A,发送时把本地处理延时时间 D(b0)也记录到数据包中,D(b0) = S(b0) - R(b0) 3,A收到B的回应后,记录到数据接收时间R(a0) 4, rtt = R(a0) - S(a0) - D0

WebRtc RTT Calculation

 

1.名词解释

  • LSR: 最近一次SR包的NTP时间戳(remote_sender_ntp_time_);LSR由NTP秒(second)低16位和毫秒(fraction)高16位组合而成;

  • DLSR: 最近一次收到SR包到打包Report Block包的间隔.

    SR报文格式:

            0                   1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    header |V=2|P|    RC   |   PT=SR=200   |             length            |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                         SSRC of sender                        |+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    sender |              NTP timestamp, most significant word             |
    info   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|             NTP timestamp, least significant word             |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                         RTP timestamp                         |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                     sender's packet count                     |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                      sender's octet count                     |+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    report |                 SSRC_1 (SSRC of first source)                 |
    block  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+1    | fraction lost |       cumulative number of packets lost       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|           extended highest sequence number received           |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                      interarrival jitter                      |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                         last SR (LSR)                         |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                   delay since last SR (DLSR)                  |+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    ​
    ​

    RR报文格式:

            0                   1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    header |V=2|P|    RC   |   PT=RR=201   |             length            |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                     SSRC of packet sender                     |+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    report |                 SSRC_1 (SSRC of first source)                 |
    block  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+1    | fraction lost |       cumulative number of packets lost       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|           extended highest sequence number received           |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                      interarrival jitter                      |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                         last SR (LSR)                         |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                   delay since last SR (DLSR)                  |+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    report |                 SSRC_2 (SSRC of second source)                |
    block  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+2    :                               ...                             :+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+|                  profile-specific extensions                  |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

     

2. 探测流程

探测流程:

  • 发送端构造和发送SR包,携带发送时间戳LSR;

  • 接收端接收到最新的SR之后,使用last_received_sr_ntp_字段记录当前ntp时间戳;

  • 接收端构造RR包,设置DLSR字段为当前ntp时间戳 - last_received_sr_ntp_,之后发出RR包;

  • 发送端在接收到RR包之后,记录RR包到达时间now_ntp;

  • 计算rtt: now_ntp - LSR - DLSR

SR和RR包的数量并不需要完全相同,它们之间并不是一一对应的关系,而是相互独立发送的,各自按照自己的发送节奏发送数据. 即使SR或者RR丢失了一部分,只要发送端接收到过RR,它总能计算出rtt,因为发送端只需要一次RR包中的LSR和DLSR字段就能够算出一次rtt.

3. 更新流程

由上一步得到的rtt值会被传递到CallStats中进行定时更新操作(CallStats::Process), 时间间隔为1s(kUpdateIntervalMs). 一次处理流程CallStats::Process为:

  • RemoveOldReports移除1.5s之前的旧的rtt数据;

  • 计算最近1.5s之内的rtt平均值和最大值;

  • 如果最大值和平均值都是非负数,那么便认为rtt合法;

  • 以平均rtt值和之前的旧的值做一个加权(3:7)作为最终的rtt计算值,通知所有观察者.

     

4. 相关代码

`RTCPSender::BuildSR`
`RTCPSender::BuildRR`
`RTCPSender::SendCompoundRTCP`
`RTCPReceiver::HandleReceiverReport`
`RTCPReceiver::HandleReportBlock

获取LSR

bool ModuleRtpRtcpImpl::LastReceivedNTP(uint32_t* rtcp_arrival_time_secs,  // When we got the last report.uint32_t* rtcp_arrival_time_frac,uint32_t* remote_sr) const {// Remote SR: NTP inside the last received (mid 16 bits from sec and frac).uint32_t ntp_secs = 0;uint32_t ntp_frac = 0;
​if (!rtcp_receiver_.NTP(&ntp_secs,&ntp_frac,rtcp_arrival_time_secs,rtcp_arrival_time_frac,NULL)) {return false;}//remote_sr 就是 last SR (LSR)  LSR由NTP秒(second)低16位和毫秒(fraction)高16位组合而成;*remote_sr =((ntp_secs & 0x0000ffff) << 16) + ((ntp_frac & 0xffff0000) >> 16);return true;
}

计算DLSR

bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,uint32_t ssrc,StreamStatistician* statistician) {
​.........// Delay since last received report.if ((feedback_state.last_rr_ntp_secs != 0) ||(feedback_state.last_rr_ntp_frac != 0)) {// Get the 16 lowest bits of seconds and the 16 highest bits of fractions.uint32_t now = CompactNtp(ntp);
​//接收到sr的的时间 last_rr_ntp_secs  last_rr_ntp_fracuint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;receiveTime <<= 16;receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
​block->SetDelayLastSr(now - receiveTime);}return true;
}

计算RTT

void RTCPReceiver::HandleReportBlock(const ReportBlock& report_block,PacketInformation* packet_information,uint32_t remote_ssrc) {.........int64_t rtt_ms = 0;//LSRuint32_t send_time_ntp = report_block.last_sr();// RFC3550, section 6.4.1, LSR field discription states:// If no SR has been received yet, the field is set to zero.// Receiver rtp_rtcp module is not expected to calculate rtt using// Sender Reports even if it accidentally can.if (!receiver_only_ && send_time_ntp != 0) {//DLSRuint32_t delay_ntp = report_block.delay_since_last_sr();// Local NTP time.uint32_t receive_time_ntp = CompactNtp(clock_->CurrentNtpTime());
​//计算RTT// RTT in 1/(2^16) seconds.uint32_t rtt_ntp = receive_time_ntp - delay_ntp - send_time_ntp;// Convert to 1/1000 seconds (milliseconds).rtt_ms = CompactNtpRttToMs(rtt_ntp);if (rtt_ms > report_block_info->max_rtt_ms)report_block_info->max_rtt_ms = rtt_ms;
​if (report_block_info->num_rtts == 0 ||rtt_ms < report_block_info->min_rtt_ms)report_block_info->min_rtt_ms = rtt_ms;
​report_block_info->last_rtt_ms = rtt_ms;report_block_info->sum_rtt_ms += rtt_ms;++report_block_info->num_rtts;}.........
}

更新回调

void CallStats::Process() {RTC_DCHECK_RUN_ON(&process_thread_checker_);int64_t now = clock_->TimeInMilliseconds();last_process_time_ = now;
​// |avg_rtt_ms_| is allowed to be read on the process thread since that's the// only thread that modifies the value.int64_t avg_rtt_ms = avg_rtt_ms_;RemoveOldReports(now, &reports_);max_rtt_ms_ = GetMaxRttMs(reports_);avg_rtt_ms = GetNewAvgRttMs(reports_, avg_rtt_ms);{rtc::CritScope lock(&avg_rtt_ms_lock_);avg_rtt_ms_ = avg_rtt_ms;}
​// If there is a valid rtt, update all observers with the max rtt.if (max_rtt_ms_ >= 0) {RTC_DCHECK_GE(avg_rtt_ms, 0);for (CallStatsObserver* observer : observers_)observer->OnRttUpdate(avg_rtt_ms, max_rtt_ms_);// Sum for Histogram of average RTT reported over the entire call.sum_avg_rtt_ms_ += avg_rtt_ms;++num_avg_rtt_;}
}
int64_t GetNewAvgRttMs(const std::list<CallStats::RttTime>& reports,int64_t prev_avg_rtt) {if (reports.empty())return -1;  // Reset (invalid average).
​int64_t cur_rtt_ms = GetAvgRttMs(reports);if (prev_avg_rtt == -1)return cur_rtt_ms;  // New initial average value.
​// Weight factor to apply to the average rtt.// We weigh the old average at 70% against the new average (30%).constexpr const float kWeightFactor = 0.3f;return prev_avg_rtt * (1.0f - kWeightFactor) + cur_rtt_ms * kWeightFactor;
}

 

References

[http://www.voidcn.com/article/p-dkzjvoaj-bpd.html]  http://www.voidcn.com/article/p-dkzjvoaj-bpd.html 

[https://www.cnblogs.com/xl2432/p/13424448.html]  https://www.cnblogs.com/xl2432/p/13424448.html 

 


http://chatgpt.dhexx.cn/article/r8tpeyJ6.shtml

相关文章

《嵌入式 - 嵌入式大杂烩》详解J-Link RTT打印

开发环境: J-Link版本:V9.4 J-Link驱动版本:V760h_x86_64 Keil:V5.30 在嵌入式开发过程中,经常需要进行打印调试,通常使用串口进行打印输出,但通常串口资源有限,这时就可以通过J-Link工具里面自带的RTT实现打印,从而节约一个串口资源。 1 RTT简介 RTT全称是Real Ti…

RTT学习笔记8-RTT内核移植

RTT 内核移植接口 CortexM系列的内核移植 1.关闭中断 ;/* ; * rt_base_t rt_hw_interrupt_disable(void); ; */ rt_hw_interrupt_disable PROC ;PROC 伪指令定义函数EXPORT rt_hw_interrupt_disable ;EXPORT 输出定义的函数&#xff0c;类似于 C 语言 externMRS …

nordic 52832中添加RTT打印

JlinkRTT RTT是基于Jlink调试器的实时传输技术,可以代替串口打印一些调试信息,不需要额外接线。 nordic 52832官方例程中,会将RTT打印函数做进一步封装,下面就讲一下怎么开启52832中的RTT打印。 第一步 增加RTT代码 RTT源代码可以在segger官方网站下载,也可以在nordic 5…

计算机网络传输层——学习笔记

目录 传输层概述 多路复用和多路分解 协议 UDP协议 可靠数据传输协议&#xff08;reliable data transfer protocol RDT&#xff09; 经完全可靠信道的可靠数据传输&#xff1a;rdt 1.0 经具有比特差错信道的可靠数据传输&#xff1a;rdt 2.0 经具有比特差错的丢包信道的…

RTT简介及其简单应用

一、 裸机系统和多任务系统 裸机系统通常分为轮询系统和前后台系统。 轮询系统不难理解就是按照顺序从上往下反复来执行&#xff0c;伪代码如下&#xff1a; int main() {Init();while(1){/*事件1*/event1();/*事件2*/event2();/*事件3*/event3();} }前后台系统就是在轮询系统…

TCP中RTT时延的理解

最近服务器环境部署了tcprtt网络时延监控&#xff0c;发现不同服务器不同节点之间的RTT时延表象非常奇怪&#xff0c;无法准确的判断服务器的网络情况。因此需要弄清楚什么是RTT&#xff0c;以及能否作为服务器网络性能的检测指标。 1、RTT是什么&#xff1f; TCP中的RTT指的是…

FreeRTOS记录(四、FreeRTOS任务堆栈溢出问题和临界区)

本来计划是消息队列、信号量、任务通知、事件集、邮件的文章 但是因为自己调试的时候遇到了一个问题&#xff0c;还是把堆栈溢出问题放到前面来说 ..增加临界区的使用说明 2021/11/7 ..临界区的使用部分增加任务挂起与临界区说明 2021/11/26目录 任务…

1-FreeRTOS入门指南

本专栏是根据官方提供的文档进行FreeRTOS的各个功能函数的说明&#xff0c;以及函数的使用 本专栏不涉及动手操作&#xff0c;只是对原理进行说明&#xff0c;FreeRTOS基础知识篇更新完成会对如何在开发板上进行上手实战操作。 这里不会对比其他RTOS的优缺点&#xff0c;因为每…

freeRTOS调度

freeRTOS调度策略 背景 嵌入式的设备开发通常有两种模式&#xff1a;裸机开发和OS开发。像功能较为强大的SOC通常都会先一直linux或其他OS然后进行业务逻辑的开发&#xff1b;而单片机则有很多简单的应用场景直接使用裸机开发的模式&#xff0c;稍微复杂些的场景&#xff0c;会…

FreeRTOS 解析

目录 Task Task State Task Priority Idle Task Run Time Statistics Task Scheduling Single-core 单核处理器 AMP 非对称多核处理器 SMP 对称多核处理器 Context Switch Inter-task Communication and Synchronization Queue 队列 Binary Semaphore 二值信号量 …

FreeRTOS队列

在实际的应用中&#xff0c;常常会遇到一个任务或者中断服务需要和另外一个任务进行“沟通交流”&#xff0c;这个“沟通交流”的过程其实就是消息传递的过程。在没有操作系统的时候两个应用程序进行消息传递一般使用全局变量的方式&#xff0c;但是如果在使用操作系统的应用中…

FreeRTOS任务状态

1. 任务状态介绍 FreeRTOS中的任务状态&#xff0c;可以简单的分为运行态&#xff08;running&#xff09;和非运行态&#xff08;not running&#xff09;。 但是对于非运行态我们还可以继续细分&#xff1a; 阻塞状态&#xff08;Blocked&#xff09;暂停&#xff08;挂起…

FreeRTOS延时

1、相对延时函数 将当前任务添加到阻塞列表pxDelayedTaskList&#xff0c;任务进入阻塞态。 vTaskDelay → prvAddCurrentTaskToDelayedList → vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) )。任务的阻塞时间更新到状态列表项xStateListItem x…

FreeRTOS多任务管理

文章目录 1、任务1.1 任务简介1.2 任务调度1.3 任务的状态 (就绪态 / 运行态 / 阻塞态 / 挂起态)1.4 空闲任务 2、动态创建两个任务2.1 定义动态内存空间的堆2.2 定义任务函数2.3 定义 任务控制块 指针2.4 动态创建任务 xTaskCreate()2.5 启动任务 vTaskStartScheduler() 3、常…

FreeRTOS 移植

源码 FreeRTOS源码 选择 FreeRTOS 的最新版本 V9.0.0&#xff08;2016 年&#xff09;比较稳定 1&#xff09;解压后的文件 提取的文件&#xff0c; FreeRTOS—>Source->portable目录下的MemMang&#xff0c;RVDS MemMang 存放内存相关的源文件,heap_1.c,heap_2.c,he…

初识FreeRTos

初识FreeRTos Preface一、FreeRTos简介二、 为什么选择FreeRTos三、FreeRTos资料和源码的下载四、介绍我自己的开发环境4.1FreeRTos4.2AlienTek Summary Preface 距离我上一次写博客已经差不多有5个月了&#xff0c;最近想给自己挖个新坑&#xff0c;讲一讲关于FreeRTos 相关的…

FreeRTOS移植

1. 前言 本文是基于FreeRTOSv9.0.0版本的实时系统&#xff0c;移植到STM32F103芯片平台上。移植环境使用的是MDK5.32版本&#xff0c;我在移植之前就已经构建好了一个裸机工程源码了&#xff0c;而且已经确保了这份裸机代码是没有问题的。开始移植之前我强烈建议一定要确认自己…

FreeRTOS快速入门-初探FreeRTOS

首发&#xff0c;公众号【一起学嵌入式】 对于 RTOS 入门系列文章&#xff0c;已经更新完一款&#xff08;RT-Thread&#xff09;&#xff1a; 助你快速入门 RT-Thread 这个系列的文章结合 RT-Thread&#xff0c;介绍过 RTOS 相关的核心知识。 接下来&#xff0c;开始另外一…

FreeRTOS系列|FreeRTOS简介

1. RTOS简介 RTOS全称为 Real Time Operation System&#xff0c;即实时操作系统。RTOS强调的是实时性&#xff0c;又分为硬实时和软实时。硬实时要求在规定的时间内必须完成操作&#xff0c;不允许超时&#xff1b;而软实时里对处理过程超时的要求则没有很严格。RTOS的核心就…

freertos任务基础知识(freertos篇)

多任务 对于单任务系统就是常说裸机大while循环&#xff0c;有的时候也需要加一些中断服务函数完成一些处理&#xff0c;相比于多任务而言上面的单任务系统也叫做前后台系统&#xff0c;即&#xff08;中断服务函数叫前台程序&#xff0c;大while叫后台程序&#xff09; 前后台…