WebRTC服务质量(11)- Pacer机制(03) IntervalBudget

WebRTC服务质量(01)- Qos概述
WebRTC服务质量(02)- RTP协议
WebRTC服务质量(03)- RTCP协议
WebRTC服务质量(04)- 重传机制(01) RTX NACK概述
WebRTC服务质量(05)- 重传机制(02) NACK判断丢包
WebRTC服务质量(06)- 重传机制(03) NACK找到真正的丢包
WebRTC服务质量(07)- 重传机制(04) 接收NACK消息
WebRTC服务质量(08)- 重传机制(05) RTX机制
WebRTC服务质量(09)- Pacer机制(01) 流程概述
WebRTC服务质量(10)- Pacer机制(02) RoundRobinPacketQueue
WebRTC服务质量(11)- Pacer机制(03) IntervalBudget
WebRTC服务质量(12)- Pacer机制(04) 向Pacer中插入数据

一、前言:

先想想,我们其实已经有了目标码率了,为什么还要控制码率?

因为,我们获取的目标码率是以秒为单位的,比如每秒钟发送300k,这是我们通过webrtc的网络拥塞控制可以获得的。 但是,具体到每个时间分片,我们前面看了pacer是5ms作为一个时间分片,IntervalBudget就是控制每个时间分片内应该发送的数据大小。

二、概念:

IntervalBudget 是 WebRTC 中的一个数据流速率控制工具,目的是在固定时间间隔内,根据目标码率动态管理和分配可以发送的字节数(预算字节)。它类似一个预算系统,平衡上一时间间隔的欠载(underuse)和过载(overuse)情况,确保整体码率维持在目标值,同时允许一定程度的积累和补偿。

详细分主要作用是:

  1. 维持目标码率(target_rate_kbps 根据目标速率(如 300 kbps),动态调整每段时间的字节发送目标。
  2. 处理过载和欠载 若某次时间片中没有充分利用发送预算,是否允许将未用的预算累积到后续时间片(由 can_build_up_underuse 决定)。
  3. 预算限制 限制过载和欠载的值,最高不能超过特定的预算范围(max_bytes_in_budget_)。
  4. 字节消耗管理 随着数据发送,会减少预算,维持运行中实时的发送和控制。

三、类定义:

class IntervalBudget {public:explicit IntervalBudget(int initial_target_rate_kbps);IntervalBudget(int initial_target_rate_kbps, bool can_build_up_underuse);// 用于设置目标码率void set_target_rate_kbps(int target_rate_kbps);// TODO(tschumim): Unify IncreaseBudget and UseBudget to one function.// 用于计算我们这个时间分片,有多少数据可以发送void IncreaseBudget(int64_t delta_time_ms);void UseBudget(size_t bytes);size_t bytes_remaining() const;double budget_ratio() const;int target_rate_kbps() const;private:// 通过带宽评估算法评估出的目标码率(也就是1s内发送多少数据)int target_rate_kbps_;// 在budget中最大可以存放多少字节int64_t max_bytes_in_budget_;// 在一个时间分片内,还有多少数据可以发送int64_t bytes_remaining_;bool can_build_up_underuse_;
};

四、Pacer中两个重要的IntervalBudget:

  IntervalBudget media_budget_; // 用于计算可以发送媒体的数据量IntervalBudget padding_budget_; // 用于计算可以发送padding的数据量

五、设置目标码率:

要使用IntervalBudget,就需要先设置目标码率。两种设置目标码率的途径:

  • 周期执行RtpTransportControllerSend::UpdateControllerWithTimeInterval ;
  • 通过收到对方发送来的transport-cc,然后使用OnTransportPacketsFeedback函数来分析,并更新目标码率;

5.1、调用UpdateControllerWithTimeInterval过程:

在这里插入图片描述

红框中的都属于RepeatingTask,进行任务的反复执行。

// 周期执行当前任务
bool RepeatingTaskBase::Run() {// 执行当前任务TimeDelta delay = RunClosure();// ...// 然后再把this打包成任务,放入线程的任务队列当中,之后这个线程又会执行Run,反复如此// delay.ms()是每隔多长时间执行这个任务task_queue_->PostDelayedTask(absl::WrapUnique(this), delay.ms());return false;
}// 在其父类 RepeatingTaskBase 当中会通过Run来执行任务
template <class Closure>
class RepeatingTaskImpl final : public RepeatingTaskBase {public:RepeatingTaskImpl(TaskQueueBase* task_queue,TimeDelta first_delay,Closure&& closure,Clock* clock): RepeatingTaskBase(task_queue, first_delay, clock),closure_(std::forward<Closure>(closure)) {static_assert(std::is_same<TimeDelta, typename std::result_of<decltype (&Closure::operator())(Closure)>::type>::value, "");}private:// 执行当前任务TimeDelta RunClosure() override { return closure_(); }typename std::remove_const<typename std::remove_reference<Closure>::type>::type closure_;
};

5.2、根据Transport-cc执行:

当我们收到transport-cc反馈后,会执行下面函数:

// 每当我们收到transport-cc之后,就会调用下面的方法
void RtpTransportControllerSend::OnTransportFeedback(const rtcp::TransportFeedback& feedback) {feedback_demuxer_.OnTransportFeedback(feedback);auto feedback_time = Timestamp::Millis(clock_->TimeInMilliseconds());// 生成一个匿名函数任务,这个任务当中通过 OnTransportPacketsFeedback 来解析transport-cc中的内容// 解析完这个内容之后,就会计算我们当前的带宽是多少,拿到带宽就可以为budget设置目标码率了// 将返回值(也就是目标码率)传给PostUpdates,这里面会设置给budget目标码率task_queue_.PostTask([this, feedback, feedback_time]() {RTC_DCHECK_RUN_ON(&task_queue_);absl::optional<TransportPacketsFeedback> feedback_msg =transport_feedback_adapter_.ProcessTransportFeedback(feedback, feedback_time);if (feedback_msg && controller_) {PostUpdates(controller_->OnTransportPacketsFeedback(*feedback_msg));}pacer()->UpdateOutstandingData(transport_feedback_adapter_.GetOutstandingData());});
}

就是解析出人家反馈给我们的内容,根据这个计算我们自己的目标码率,并设置给budget;

六、使用media_budget:

看下ProcessPackets如何使用media_budget的:

// 周期处理包的发送
void PacingController::ProcessPackets() {if (mode_ == ProcessMode::kPeriodic) {// 将前面设置给pacer的目标码率设置给media_budgetmedia_budget_.set_target_rate_kbps(target_rate.kbps());UpdateBudgetWithElapsedTime(elapsed_time);} else {media_rate_ = target_rate;}
}

其中,elapsed_time就是逝去的时间,在UpdateBudgetWithElapsedTime当中会使用:

/*** 使用逝去的时间更新media_budget_*/
void PacingController::UpdateBudgetWithElapsedTime(TimeDelta delta) {if (mode_ == ProcessMode::kPeriodic) {// 获取较小者(kMaxProcessingInterval是30ms)delta = std::min(kMaxProcessingInterval, delta);// 将delta时间传给media_budgetmedia_budget_.IncreaseBudget(delta.ms());padding_budget_.IncreaseBudget(delta.ms());} else {media_debt_ -= std::min(media_debt_, media_rate_ * delta);padding_debt_ -= std::min(padding_debt_, padding_rate_ * delta);}
}

再看看传进去IncreaseBudget怎么使用的:

void IntervalBudget::IncreaseBudget(int64_t delta_time_ms) {// target_rate_kbps_是我们之前传入的目标码率// 加入我们现在目标码率target_rate_kbps_是300,delta是10ms,那么bytes约等于300字节,// 也就是说我们接下来这段时间可以发送的数据是300字节int64_t bytes = target_rate_kbps_ * delta_time_ms / 8;if (bytes_remaining_ < 0 || can_build_up_underuse_) {// We overused last interval, compensate this interval.// 这种情况说明过载了(比如上次要求发100,最终发了150,多发了50)// 那么我们就用本次应该发送的数据量减去(因为bytes_remaining_为负数,下面看着是加)上次多出来的50,就是本次要发送的// 当然如果大于我们budget可以发送的最大值max_bytes_in_budget_,那么,只能允许发送max_bytes_in_budget_bytes_remaining_ = std::min(bytes_remaining_ + bytes, max_bytes_in_budget_);} else {// If we underused last interval we can't use it this interval.// 如果没有过载,使用当前计算的结果bytes_remaining_ = std::min(bytes, max_bytes_in_budget_);}
}

我尝试再好好解释下:

IncreaseBudget 增加新的字节预算,用于下一时间片发送。

核心逻辑:
  1. 计算新增预算字节:

    bytes = target_rate_kbps_ * delta_time_ms / 8
    

    此预算决定时间间隔 delta_time_ms 内允许发送的字节数。

  2. 判断是否存在欠载积累(bytes_remaining_ 为负值),以及是否允许保留欠载(can_build_up_underuse_)。两种情况:

    • 允许欠载/欠载存在:补偿上一次过载,同时加入当前新增预算,更新剩余字节。
    • 不允许欠载/无欠载:仅允许当前时间段的预算。
  3. 使用 std::min() 限制最终预算,确保预算总值不超过 max_bytes_in_budget_

示例:
  • 目标码率:300 kbps,时间段:10 ms

    bytes = 300 * 10 / 8 = 375 字节
    
  • 欠载情况:假设 bytes_remaining_ = -100can_build_up_underuse = true

    bytes_remaining_ = min(-100 + 375, max_bytes_in_budget_)= min(275, 375)= 275 字节
    
  • 正常情况:没有欠载,直接按当前时间段计算:

    bytes_remaining_ = min(375, 375) = 375 字节
    

七、总结:

本文主要介绍了Pacer模块中怎么根据目标码率,然后通过IntervalBudget来完成动态调整每段时间的字节预算,使整体码率稳定在设计的目标值附近,同时平衡欠载和过载的情况。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/496294.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java爬虫技术:按关键字搜索VIP商品详情

在数字化时代&#xff0c;电子商务平台的竞争日益激烈&#xff0c;而精准的数据采集和分析成为了企业获取竞争优势的关键。对于电商平台而言&#xff0c;能够根据用户输入的关键字快速搜索并展示VIP商品的详细信息&#xff0c;不仅能够提升用户体验&#xff0c;还能够增加销售机…

若依框架中的上传图片后如何实现回显到页面的

在日常开发中&#xff0c;总会遇到上传文件、图片等功能&#xff0c;然后本地开发的话&#xff0c;又没有像OSS、七牛等网络存储&#xff0c;这个时候通常将文件上传到本地&#xff0c;那么上传之后拿到的是本地的路径&#xff0c;存储到数据库中&#xff0c;查询的时候如何将本…

一键图片转3D模型,AI建模,一键把图片转三维模型,二维图片转3维模型,AI建模

一键图片转3D模型&#xff0c;AI建模&#xff0c;一键把图片转三维模型&#xff0c;二维图片转3维模型,AI建模&#xff0c;公测版&#xff0c;每天不定时免费开放&#xff0c;非常强大 1咱们先打开ai.glbxz.com http://ai.glbxz.com 22 2导入图片。支持单张和多张图片生成 3…

梳理你的思路(从OOP到架构设计)_设计模式Android + Composite模式

目录 1、Android Composite模式 2、范例之一 3、范例之二 1、Android Composite模式 在Android平台里&#xff0c;像Button或ImageButton等屏幕控件皆通称为View。多个View能组合在一起&#xff0c;就会各种排列方式&#xff0c;即称为「布局」 (Layout)。这Layout类别就是…

LabVIEW软件项目设计方案如何制定

制定LabVIEW软件项目设计方案需要综合考虑需求分析、架构设计、功能模块划分和时间预算等多个方面&#xff0c;确保项目开发过程高效、可控且最终满足目标要求。以下是一个详细的制定流程&#xff1a; ​ 1. 需求分析 目标定义&#xff1a;明确项目的目标&#xff0c;例如数据采…

机器学习(二)-简单线性回归

文章目录 1. 简单线性回归理论2. python通过简单线性回归预测房价2.1 预测数据2.2导入标准库2.3 导入数据2.4 划分数据集2.5 导入线性回归模块2.6 对测试集进行预测2.7 计算均方误差 J2.8 计算参数 w0、w12.9 可视化训练集拟合结果2.10 可视化测试集拟合结果2.11 保存模型2.12 …

Linux运维常见命令

vi/vim快捷键使用 1)拷贝当前行 yy ,拷贝当前行向下的5行 5yy&#xff0c;并粘贴&#xff08;输入p&#xff09;。 2)删除当前行 dd ,删除当前行向下的5行5dd 3)在文件中查找某个单词 [命令行下 /关键字&#xff0c;回车查找 ,输入n就是查找下一个 ] 4)设置文件的行号&…

MacOS下TestHubo安装配置指南

TestHubo是一款开源免费的测试管理工具&#xff0c; 下面介绍MacOS私有部署的安装与配置。TestHubo 私有部署版本更适合有严格数据安全要求的企业&#xff0c;支持在本地或专属服务器上运行&#xff0c;以实现对数据和系统的完全控制。 1、Mac 服务端安装 Mac安装包下载地址&a…

jumpserver docker安装

#安装jumpserver最新版本&#xff08;当前最新版本v4.5.0-ce&#xff09; curl -sSL https://resource.fit2cloud.com/jumpserver/jumpserver/releases/latest/download/quick_start.sh | bash#登录 http://192.168.31.168/ 默认账号密码 admin/ChangeMe 修改后&#xff1a; ad…

VBA技术资料MF243:利用第三方软件复制PDF数据到EXCEL

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

LabVIEW生物医学信号虚拟实验平台

介绍了一款基于LabVIEW的多功能生物医学信号处理实验平台的设计和实现。平台通过实践活动加强学生对理论的理解和应用能力&#xff0c;特别是在心电图(ECG)和脑电图(EEG)的信号处理方面。实验平台包括信号的滤波、特征提取和频谱分析等功能&#xff0c;能直观体验和掌握生物医学…

json字符串或者json文件转换成相应的bean,报错“Unrecognized field xxx , not marked as ignorable”

1. 异常描述 将一个json字符串或者json文件转换成相应的bean的时候&#xff0c;报如下错误&#xff1a; 2. 异常分析 bean中某个字段的get和set方法可能不是工具自动生成的&#xff0c;而是自己写的&#xff0c;譬如字段是“sInfo”&#xff0c;本来get方法是应该写成getsI…

Postman接口测试01|接口测试基础概念、http协议、RESTful风格、接口文档

目录 一、接口测试基础概念 1、什么是接口 2、接口的类型 3、什么是接口测试 4、为什么要做接口测试 5、接口测试的实现方式 6、什么是自动化接口测试&#xff1f; 二、接口返回的数据格式 1、三种格式 2、Json 三、接口协议 1、webservice协议 2、dubbo协议 3、…

游戏引擎学习第62天

回顾 我们目前正在开发一把虚拟剑&#xff0c;目的是让角色可以用这把剑进行攻击。最初的工作中&#xff0c;我们使用了一个摇滚位图作为虚拟剑的模型&#xff0c;并且实现了一个基本的功能&#xff1a;角色可以丢下剑。但这个功能并没有达到预期的效果&#xff0c;因为我们想…

AAAI-2024 | 大语言模型赋能导航决策!NavGPT:基于大模型显式推理的视觉语言导航

作者&#xff1a;Gengze Zhou, Yicong Hong, Qi Wu 单位&#xff1a;阿德莱德大学&#xff0c;澳大利亚国立大学 论文链接&#xff1a; NavGPT: Explicit Reasoning in Vision-and-Language Navigation with Large Language Models &#xff08;https://ojs.aaai.org/index.p…

商品线上个性定制,并实时预览3D定制效果,是如何实现的?

商品线上3D个性化定制的实现涉及多个环节和技术&#xff0c;以下是详细的解释&#xff1a; 一、实现流程 产品3D建模&#xff1a; 是实现3D可视化定制的前提&#xff0c;需要对产品进行三维建模。可通过三维扫描仪或建模师进行建模&#xff0c;将产品的外观、结构、材质等细…

JS 异步 ( 一、异步概念、Web worker 基本使用 )

文章目录 异步代码异步执行概念ES6 之前的异步 Web worker 异步 代码异步执行概念 通常代码是自上而下同步执行的&#xff0c;既后面的代码必须等待前面的代码执行完才会执行&#xff0c;而异步执行则是将主线程中的某段代码交由子线程去执行&#xff0c;当交给子线程后&…

Elasticsearch-脚本查询

脚本查询 概念 Scripting是Elasticsearch支持的一种专门用于复杂场景下支持自定义编程的强大的脚本功能&#xff0c;ES支持多种脚本语言&#xff0c;如painless&#xff0c;其语法类似于Java,也有注释、关键字、类型、变量、函数等&#xff0c;其就要相对于其他脚本高出几倍的性…

蓝牙BLE开发——解决iOS设备获取MAC方式

解决iOS设备获取MAC方式 uniapp 解决 iOS 获取 MAC地址&#xff0c;在Android、iOS不同端中互通&#xff0c;根据MAC 地址处理相关的业务场景&#xff1b; 文章目录 解决iOS设备获取MAC方式监听寻找到新设备的事件BLE工具效果图APP监听设备返回数据解决方式ArrayBuffer转16进制…

高仿CSDN编辑器,前端博客模板

高仿CSDN编辑器纯前端模板&#xff0c;使用的js、html、vue、axios等技术&#xff0c;网络请求库已进行封装&#xff0c;可以按需调整界面,需要源码联系(4k左右)。 1.支持代码高亮 2.支持目录点击定位 3.支持文件上传、图片上传&#xff08;需要自己写后端接口&#xff09; 4.M…