做过视频会议都清楚,当网络出现丢包异常后,经常会导致视频出现长时间花屏问题。严重降低用户体验。测试webrtc发现,视频无论在什么环境,都没有出现花屏现象。若出现丢包,通过掉帧方式解决该问题。最坏的情况就是视频出现卡顿,但是也不会出现花屏。我们都知道视频解码器只管数据解码,不会判断是否是花屏,这个丢包导致花屏问题,只能在调度侧解决,解码器是不处理该异常的。

webrtc在收包送到解码器这块流程,会处理三件事:

1、判断当前收到是视频帧是否完整,若不是完整帧,通过FEC+NACK请求丢失数据,若当解码器要数据的时候,还不是完整视频帧,直接丢弃该视频帧。

2、在将视频帧送到解码器的时候,会判断该视频帧的参考帧是否都存在,若不存在直接丢弃该帧。

3、视频解码器检测,当连续指定时间没有收到视频帧,会通过RTCP-FIR报文向发送端发送IDR帧请求命令。

一、视频帧完整性判断方法

以H264为例,在RTP净荷的FU Header,有个S字段,表示是否是一帧的起始;一帧的最后一包,RTP的mark字段为1。

通过这两个字段就可以获取到一帧的起始和结束报文。中间报文只要保证RTP头的序列号连续,就可以保证一帧的完整性。

1)视频帧起始S字段获取

RtpDepacketizerH264::ParseFuaNalu

2)视频帧结束mark字段

Packet::GetHeader

3)报文连续性判断

PacketBuffer::UpdateMissingPackets

二、参考帧完整性判读方法

在视频会议中,GOP的帧结构中只有IDR、I、P帧,没有B帧。并且GOP的类型为close gop。跨GOP的帧不会互相参考。

所以参考帧判断比较简单。以收到IDR帧为起点,后续收到的帧全部默认参考前一帧,若前一帧不存在,则丢弃当前帧。

1)设置帧间参考关系

RtpFrameReferenceFinder::ManageFrame

->RtpFrameReferenceFinder::ManageFrameInternal

->RtpFrameReferenceFinder::ManageFrameGeneric

这个是最简单的示例,这样实现的效果是在一个GOP中,从开始丢包处,就一致卡顿,直到下一个GOP到来。

H264、VP8、VP9有SVC。当配置Temporal Scalability,参考关系需要根据LayerSync字段判断。这样实现的效果是一个GOP中根据参考关系选择性丢包。缓解长时间卡顿问题。

2)判断参考帧是否缺失

FrameBuffer::UpdateFrameInfoWithIncomingFrame

3)丢弃无参考帧视频数据

FrameBuffer::ReturnReason FrameBuffer::NextFrame

若参考帧不全,就一直不解码,当最新帧被解码,老帧就会被删除。

FrameBuffer::AdvanceLastDecodedFrame

 

三、IDR帧请求流程

当解码器连续一段时间,没有收到视频帧,需要向视频发送端发送RTCP-FIR请求。目前webrtc配置的是3秒。

VideoReceiveStream::Decode

 

Logo

致力于链接即构和开发者,提供实时互动和元宇宙领域的前沿洞察、技术分享和丰富的开发者活动,共建实时互动世界。

更多推荐