webrtc jitterbuffer--buffer草稿

webrtc的jitterbuffer按照功能分类的话,可以分为jitter和buffer。buffer主要对丢包、乱序、延时到达等异常情况做处理,还会和NACK、FEC、FIR等QOS相互配合.jitter就是trendline算法的jitter.

为什么要有jitterbuffer:
假设40ms一帧,1s 25帧. 发送时间序列0,40,80,120,160,200ms。网络延时100ms;接收序列:100,140,200,240,280,300,400ms.
如果没有jitterbuffer则在180ms发生卡顿,因为帧没有到。
所以先缓存一段最大延时,然后播放,后面就再也不会有卡顿了。
那么最大等多久呢?不会造成任何帧卡顿。决定延时的两个因素:网速和路由器buffer。
用最大帧测试这两个值得到的就是max的jitterbuffer. 即每帧都不会超过这个时间到达。那么之后就在不会卡顿了。

第一部分 新版jitter buffer

整体结构:

  • PacketBuffer:负责帧的完整性,保证组成帧的每个包序列号连续,并且有一个包标识帧的开始,有一个包标识帧的结束;
  • RtpFrameReferenceFinder:帧参考关系寻找.负责给每个帧设置好参考帧,同时兼顾GOP内各帧的连续性;
  • FrameBuffer:帧缓存.负责帧的连续性和可解码性,这里帧的连续性是指某帧的所有参考帧都已经收到,帧的可解码性是指某帧的所有参考帧都已经被解码;

VCMJitterEstimator:计算抖动(googJitterbufferMS),用于计算目标延迟(googTargetDelayMs),用于音视频同步;
VCMTiming:计算当前延迟(googCurrentDelayMs),用于计算渲染时间。

JitterBuffer流程图

PacketBuffer:就是一帧的包乱序,在这个把一帧的包收集全了,帧完整在给下一环节
RtpFrameReferenceFinder:是保证帧的顺序,把来的完整的帧排序,不产生帧顺序错误。
同时设置参考帧,当前帧把前一帧设置成参考帧.
FrameBuffer 也设置参考帧不知道why? 它还会获取jitter值,编码器从这里获取帧和jitter值

在这里插入图片描述

1)RtpVideoStreamReceiver类收到RTP包后,交给PacketBuffer类缓存、排序
2)PacketBuffer收集满1个完整的帧后,交还给RtpVideoStreamReceiver类,RtpVideoStreamReceiver类将一个完整的帧交给RtpFrameReferenceFinder。
3)RtpFrameReferenceFinder类缓存最近的GOP,每个完整帧落在一个GOP中会填充好该帧的参考帧,交还给RtpVideoStreamReceiver。
notes:P帧的前一帧就是参考帧
4)RtpVideoStreamReceiver将填充好参考帧的完整帧交给FrameBuffer
5) FrameBuffer判断某帧的所有参考帧都收到认为该帧连续,在某帧的所有参考帧都解码后认为该帧可以解码,从而可以交给解码器。 
notes:保存一个GOP的所有frame。如果参考帧已经解码,说明这帧可以放入解码器了

JitterBuffer的这些模块分三个层次:分别做了RTP包的排序,GOP内帧的排序,GOP之间的排序??

  • 包的排序:PacketBuffer;
  • 帧的排序:RtpFrameReferenceFinder;
  • GOP的排序:FrameBuffer。
    notes:GOP排序?应该是一个GOP内部的事情

4.8 总结
PacketBuffer::InsertPacket向包缓存插入RTP数据,并触发帧完整性检查;
PacketBuffer::PaddingReceived处理空包,并触发帧完整性检查;
PacketBuffer::UpdateMissingPackets,更新丢包信息,用于检查P帧前面的空洞;
PacketBuffer::PotentialNewFrame,判断包的连续性,只有连续的包才检查帧完整性;
PacketBuffer::FindFrames,帧完整性检查,如果得到完整帧,则通过OnAssembledFrame回调上报
参考:WebRTC视频JitterBuffer详解_一朵喇叭花压海棠的博客-CSDN博客_jitterbuffer
WebRTC视频接收JitterBuffer_StoneLiu999的博客-CSDN博客

,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

第二部分:旧版webrtc:VCMJitterBuffer 实现原理

Buffer decodable_frames_和incomplete_frames_

这里介绍的是播放器的jitterbuffer

decodable_frames_存储可以解码的帧(比如关键帧或者前序完整的P帧);
incomplete_frames_存储暂时不能解码的帧:(1)本身rtp包不完整的帧.(2)依赖的参考帧不完整的帧

为了更便于理解jitter的存储机制,用以下的逻辑存储格式来描述

在这里插入图片描述
每个方格为一帧数据vcmframe。

  • 绿色表示可解码帧(图中1、2),存储在decodable_frames_
  • 红渐变色表示rtp包不完整的帧(图中3、4),存储在incomplete_frames_
  • 红色表示rtp包完整,但是依赖的参考帧不完整(图中5、6),存储在incomplete_frames_
  • 白色表示还未接收到的包(图中7),存储在missing_sequence_numbers_
  1. 每个gop都是以关键帧起始,如果关键帧不完整,那整个gop都不可解吗,必然都是存储在incomplete_frames_中.
  2. 在一个gop中,可解码帧都是以关键帧起始,然后连续存储在一起的。中间只要有间隔的不完整包或者丢失包,后面都是存储在incomplete_frames_中。如图中的5本身rtp包是完整的,但因为依赖参照帧3、4不完整,本身也不能解码,连锁导致6也不能解码。同样图中12由于依赖参考帧未接收到,暂时也不能解码.
  3. decode_state记录当前解码到哪一帧,如图中已解码到9,那之前未解码的帧(3~7)都丢弃,未接收到的rtp也不再发送nack请求。 

从图中可以看出,未接收到包的重要程度是不同的,11的重要程度大于14,11的不完整影响了12和13的解码。因此在网络拥塞时,可以根据未接收到包的重要程度来优先发送nack请求,尽可能使靠近关键帧的包接收完整。必要情况下可以丢弃重要程度低的nack请求

Buffer 流程图

 buffer对接收到的rtp包的处理流程如下:

  • 第一次接收到一个视频包,从freeframes队列中弹出一个空frame块,用来放置这个包。
    notes:新包分配一个新frame buffer
  • 之后每次接收到一个RTP包,根据时间戳在incompleteframes和decodableframes中寻找,看是否已经接收到过相同时间戳的包。
    如果找到,则弹出该frame块,否则,从freeframes弹出一个空frame。
    notes:同一帧的包使用相同的frame buffer
  • 根据包的序列号,找到应该插入frame的位置,并更新state。
    其中state有empty、incomplete、decodable和complete,empty为没有数据的状态,incomplete为至少有一个包的状态,decodable为可解码状态,complete为这一帧所有数据都已经到齐。
  • 根据不同的state将frame帧 push回到队列中去。
    其中state为incomplete时,push到incompleteframes队列,
    decodable和complete状态的frame,push回到decodableframes队列中
    notes:收到包之后检查,如果一个帧的所有包都收到了,就放入decodableframes队列。否则,仍在incompleteframes队列
  • freeframes队列有初始size,freeframes队列为空时,会增加队列size,但有最大值。
    也会定期从incompleteframes,decodable队列中,清除一些过时的frame,push到freeframes队列
    notes:释放过时的frame给回到freeframes 队列.
  • 解码线程取出frame,解码完成之后,push回freeframes队列。
    notes:解码完成的frame放回到freeframes队列

jitterbuffer与QOS策略联系紧密,比如,incompleteframes和decodable队列清除一些frame之后,需要FIR(关键帧请求),根据包序号检测到丢包之后要NACK(丢包重传)等。

webrtc源码分析(6)- jitter delay计算详解 - woder - 博客园

源码解析:webrtc QOS方法八(JitterBuffer)_CrystalShaw的博客-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值