前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WebRTC系列分享 第二期 | WebRTC QoS方法之Pacer实现

WebRTC系列分享 第二期 | WebRTC QoS方法之Pacer实现

作者头像
腾讯云音视频
发布2022-03-21 11:10:15
1.3K0
发布2022-03-21 11:10:15
举报
文章被收录于专栏:音视频咖音视频咖

导语 | 本文将解读WebRTC中Pacer算法的实现。WebRTC有两套Pacer算法:TaskQueuePacedSender、PacedSender。本文仅介绍PacedSender的实现。(文章中引用的WebRTC代码基于master,commit:3f412945f05ce1ac372a7dad77d85498d23deaae源码分析)

背景介绍

若仅仅发送音频数据,不需要Pacer模块。

  • 一帧音频数据本身不大,不会超过以太网的最大报文长度。一个RTP报文可以搞定,按照打包时长的节奏发送就可以。但视频数据不能按照音频数据的思路发送,一帧视频可能很大,远大于以太网的1500byte,需要分别封装在几个RTP报文中,若这些视频帧RTP报文一起发送到网络上,必然会导致网络瞬间拥塞。产生丢包抖动等异常。
  • 大多数编解码格式下,一帧音频数据长度固定,音频码率持续平稳。码率不会出现忽高忽低现象。但是一帧视频数据长度受内容影响严重。I、P、B帧间的长度相差非常大。直接发送网络波动幅度很大。尤其是WIFI环境下,受限WIFI的调度机制,媒体数据能否平稳发送,对弱网的WiFi环境对通话质量影响很大。

Pacer的目的就是让视频数据按照评估码率均匀的在各个时间片发送出去。如下图所示:

实现原理

设计PACER模块主要解决三个问题:怎么发送报文、什么时候发报文、每次发多少数据量。

1. 怎么发送报文

音频、视频、NACK、FEC、Padding报文都要统一从Pacer模块发送。若不区分报文优先级,势必会对系统延时产生很大影响。

所以音视频编码数据RTP切分打包后,首先将RTP报文存在pace queue队列,并将报文元数据(packet id, size, timestamp, 重传标示)送到pacer queue进行排队等待发送,插入队列的元数据会进行优先级排序。

pace queue是一个基于优先级排序的多维链表,它并不是一个先进先出的fifo,而是一个按优先级排序的list。报文优先级规则是:

  • 优先级高的报文排在fifo的前面,低的排在后面;
  • 首先判断报文的priority等级,等级越小的优先级越高(priority等级根据报文类型进行分类);
  • 然后判断重发标示,重发的报文比普通报文的优先级更高;
  • 最后是判断视频帧timestamp,越早的视频帧优先级更高。

Pacer每次触发发送事件时先从queue的最前面取出优先级最高的报文进行发送,这样做的目的是让视频在传输的过程中延迟尽量小,重传的报文尽快能到达防止等待卡顿。pace queue还可以设置最大延迟,如果超过最大延迟,会计算queue中数据发送所需要的码率,并且会把这个码率替代target bitrate作为budget参考码率来加速发送。(最大延时详细处理流程会在后文中介绍)

根据报文类型确定数据优先级处理函数如下:

代码语言:javascript
复制
int GetPriorityForType(RtpPacketMediaType type) {  // Lower number takes priority over higher.  switch (type) {    case RtpPacketMediaType::kAudio:      // Audio is always prioritized over other packet types.      return kFirstPriority + 1;    case RtpPacketMediaType::kRetransmission:      // Send retransmissions before new media.      return kFirstPriority + 2;    case RtpPacketMediaType::kVideo:    case RtpPacketMediaType::kForwardErrorCorrection:      // Video has "normal" priority, in the old speak.      // Send redundancy concurrently to video. If it is delayed it might have a      // lower chance of being useful.      return kFirstPriority + 3;    case RtpPacketMediaType::kPadding:      // Packets that are in themselves likely useless, only sent to keep the      // BWE high.      return kFirstPriority + 4;  }  RTC_CHECK_NOTREACHED();}

按照优先级POP数据处理函数如下:

代码语言:javascript
复制
bool RoundRobinPacketQueue::QueuedPacket::operator<(    const RoundRobinPacketQueue::QueuedPacket& other) const {  if (priority_ != other.priority_)    return priority_ > other.priority_;  if (is_retransmission_ != other.is_retransmission_)    return other.is_retransmission_;
  return enqueue_order_ > other.enqueue_order_;}

2. 什么时候发报文

PacingController::ProcessPackets按照PacingController::NextSendTime控制的节奏周期调用。完成PACER平滑发送功能。

PacingController::NextSendTime在控制发送节奏上,有两种模式kPeriodic、kDynamic。这里先介绍kPeriodic实现方式。kPeriodic模式下,固定每隔5ms调用一次发送报文任务。

代码语言:javascript
复制
constexpr TimeDelta kDefaultMinPacketLimit = TimeDelta::Millis(5);

3. 每次发多少数据量

PacingController::ProcessPackets被定时触发后,会计算当前时间和上次被调用时间的时间差,然后将时间差参数传入media_budget_,media_budget_算出当前时间片网络可以发送多少数据,然后从pacer queue当中取出报文元数据进行网络发送。

media_budget_根据评估出来的参考码率计算这次定时事件能发送多少字节的公式如下:

delta time:上次检查时间点和这次检查时间点的时间差。

target bitrate:pacer的参考码率,是由probe模块根据网络探测带宽评估出来的。

remain_bytes:每次触发发包时会减去发送报文的长度size,如果remain_bytes > 0,继续从pace queue中取下一个报文进行发送,直到remain_bytes <=0 或者 pace queue没有更多的报文。

如果pacer queue没有更多待发送的报文,但media_budget_计算出还可以发送更多的数据,这个时候pacer会进行padding报文补充

4. Pacer模块引入延时规避方法

max_pacing_delay:

Pacer模块定量计算发送网络报文数据量,相当于cache等待发送,必然会引起延迟。为了保证实时性,Pacer模块有个max_pacing_delay全局变量,配置最大缓冲发送延时时间上限,若最大缓冲延时大于该值,就要重新调整Pacer模块的目标码率,保证当前数据都能及时发送出去。

max_pacing_delay生效流程如下:

VideoSendStreamImpl::VideoSendStreamImpl配置到transport->SetQueueTimeLimit

代码语言:javascript
复制
void PacingController::SetQueueTimeLimit(TimeDelta limit) {  queue_time_limit = limit;}

PacingController::ProcessPackets会实时计算当前处理方式会引入的系统延时,当延时大于设定目标上限值,需要及时调整Pacer目标码率,保证Pacer模块引入延时时间可控。

很明显这仅仅是一个迫不得己的规避方法,实际应用中,这种方法会出现码率梯度上升现象。

编码算法码控模块配合:

Pacer模块实现不复杂,但是要想真正做好Pacer功能,仅仅靠一个Pacer模块是玩不转的,需要与视频编码器的码控模块配合:

  • 首先探测模块配置码率给编码器,编码器一定要保证在可控周期内码率收敛到配置的码率参数值以内,否则会给Pacer模块造成的累计延时越来越大压力;
  • 另外IP帧rate也要在合理范围内。若I帧超大,势必导致关键帧传输延时变大,影响端到端系统延时。

这些参数都要根据自己的实际应用场景进行调优。

参考:

WebRTC的拥塞控制和带宽策略

关于云架构平台部

云架构平台部是腾讯规模最大的技术部门之一,长期深耕音视频、存储、接入和计算服务等技术领域,通过海量的存储和数据库平台,世界级的CDN&音视频服务,先进的操作系统和视频编解码技术,助力腾讯云以技术的力量持续赋能客户,帮他们提升效率,降低成本。

腾讯云音视频在音视频领域已有超过21年的技术积累,持续支持国内90%的音视频客户实现云上创新,独家具备 RT-ONE™ 全球网络,在此基础上,构建了业界最完整的 PaaS 产品家族,并通过腾讯云视立方 RT-Cube™ 提供All in One 的终端SDK,助力客户一键获取众多腾讯云音视频能力。腾讯云音视频为全真互联时代,提供坚实的数字化助力。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-03-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯云音视频 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 设计PACER模块主要解决三个问题:怎么发送报文、什么时候发报文、每次发多少数据量。
  • 1. 怎么发送报文
  • 2. 什么时候发报文
  • 3. 每次发多少数据量
  • 4. Pacer模块引入延时规避方法
相关产品与服务
图像处理
图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档