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中插入数据
一、前言:
上一篇介绍了NACK/RTX这种机制,注意,NACK是一种RTCP消息而已,本文结合代码看下WebRtc如何实现NACK机制的。
二、NACK格式:
2.1、RTPFB 消息头统一格式:
0 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P| FMT | PT | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC of packet sender |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC of media source |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: Feedback Control Information (FCI) :
-
V: 版本号,占2位。
-
P: 填充位,占1位。
-
FMT(Feedback message type): 反馈消息类型,这里设为15表示 NACK。
-
PT: Payload Type,占8位,指示 RTPFB 包类型,205 表示 RTPFB。
-
Length: 长度字段,指示反馈消息长度,以 32 位字为单位。
-
Sender SSRC: 发送者同步信源,4字节。
-
Media SSRC: 媒体同步信源,4字节。
-
FCI(Feedback Control Information,反馈控制信息): 是RTCP报文的核心部分,包含各种反馈信息,可以帮助发送端及时调整或重传数据。
-
格式如下:
-
按照内容大致分为两大类:
-
RTPFB (RTP Feedback Messages): 针对RTP层的丢包检测和重传。
-
PSFB (Payload-Specific Feedback): 针对RTP净荷(Payload)层的增强反馈,主要用于处理更高层的问题,比如视频帧或切片的丢失。
-
-
2.2、RTPFB和PSFB:
- 典型的RTPFB控制消息 —— NACK(Negative Acknowledgement):
- 功能:接收端检测到有RTP数据包丢失后,通过NACK通知发送端重新发送丢失的RTP数据包。一般啥都不写就是这种传输机制。
- 应用场景:当网络质量较差但延迟要求比较高的场景,比如视频通话、实时流媒体等。
- 优点:粒度较小,可以精确地指出哪些RTP序列号丢失,有利于快速、精准地补偿丢包。
- 处理流程:
- 接收端发现一定范围的RTP序列号有丢失。
- 接收端发送RTCP报文中的NACK消息,带有丢失的RTP序列号信息。
- 发送端收到NACK后,针对性地重传丢失的RTP包。
- PSFB 是RTCP中的一个用于反馈净荷内容的框架,主要针对编码和媒体数据层面的重传控制。相比RTPFB,PSFB通常涉及更高层的媒体内容,比如整个视频帧或某种编码参考信息。PSFB进一步细化为以下三种主要类型:
- PLI (Picture Loss Indication) - 视频帧丢失重传
- 功能:
- 当接收端检测到关键帧(如I帧)丢失或破坏时,发送PLI消息给发送端,要求它重发一个完整的视频关键帧。
- 用途尤其体现在视频传输中,避免多帧由于关键帧丢失而无法解码。
- 处理流程:
- 接收端检测关键帧丢失或解码错误(比如画面突然坏块增多)。
- 接收端发送PLI信息给发送方。
- 发送端在收到PLI后,发送一个新的关键帧(通常是I帧)。
- 特点:
- 粒度较大,通常用于重要内容的恢复,比如视频关键帧丢失。
- 可能消耗更多带宽,因为完整的关键帧通常较大。
- 功能:
- SLI (Slice Loss Indication) - Slice丢失重传
- 功能:
- 反馈RTP流中某个视频切片(Slice)丢失的信息。
- 通常用于视频传输中某些特定的片段(非整个帧)的丢失导致部分画面无法解码。
- 处理流程:
- 接收端判断某个Slice数据丢失或破坏,发送SLI给对端。
- 发送端针对丢失Slice,通过数据包重传或替换的方式修复。
- 特点:
- 较之PLI,SLI的作用范围更小,仅针对部分切片,而不需要整帧重传。
- 带宽开销较低,但可能延迟较大,因为重传的粒度较细。
- 功能:
- RPSI (Reference Picture Selection Indication) - 参考帧丢失重传
- 功能:
- 当接收端检测到参考帧丢失(或者它依赖的解码参考无法使用时,如P帧无法解码),会反馈RPSI消息,建议发送端选择新的参考帧。
- 发送端可以根据RPSI调整编码或重发相关参考信息。
- 处理流程:
- 接收端通过解码检测或分析发现P帧等数据依赖的参考帧丢失或损毁。
- 接收端发送RPSI消息,建议使用新的参考帧。
- 发送端参考RPSI调整后续的编码策略,跳过丢失的参考帧并发送新的参考帧数据。
- 特点:
- 聚焦于“参考帧”的问题,对于影响范围有限的解码错误更加有效,避免过多的重传和带宽开销。
- 在视频编码中(如H.264、H.265),参考帧是P帧和B帧的编码基础,丢失的影响可能尤为严重。
- 功能:
- PLI (Picture Loss Indication) - 视频帧丢失重传
2.2.1、PLI和SLI和RPSI比较:
类型 | 粒度 | 应用场景 | 带宽开销 | 延迟影响 |
---|---|---|---|---|
PLI | 整帧 | 关键帧丢失,恢复整体画面 | 高 | 中等,需整帧重传 |
SLI | 切片 | 部分画面丢失,快速修复 | 低到中 | 较低,粒度更细 |
RPSI | 参考帧 | 参考帧错误,影响解码链 | 低 | 非重传型,调整编码策略 |
三、Call、Channel、Stream:
之前说过,Call、Channel、Stream这几个概念你是否还记得?
-
Session层:
- 一个
Stream
对应的是一个完整的媒体流,可以包含多个Track
。 - 一个
Track
表示流中的单一媒体轨道,例如音频轨道或视频轨道(类似于 WebRTC API 中的MediaStreamTrack
)。
- 一个
-
MediaEngine层:
- Channel 是进行音视频分类管理的基础单元。通常,音频和视频会分属于不同的 Channel(AudioChannel 和 VideoChannel)。
- Stream是音视频数据在 Channel 层中的更细化管理单元。
- 一个 Channel 通常会包含多个 Stream。
- 每个 Stream 不仅负责具体的音频或视频数据处理,还可以进一步分为发送(send)和接收(recv)的数据流。
MediaEngine
层中的 Stream 是底层实现,不再对应 Session 层中的逻辑 Stream,而是为传输和解码服务的独立实体。
关键点:
- 一个 Channel 的核心目的是管理一种媒介类型(音频或视频)。例如,一个音频 Channel 可以包含多个音频 Stream;一个视频 Channel 可以包含多个视频 Stream。
- 这些 Stream 分别表示 传输和接收方向的数据流。
-
Call层:
- 对于音频,引擎层的一个Stream就对应Call层的一个
SendStream
或者ReceiveStream
; - 对于音频,一个Stream中又有Channel,来连接编解码器;
- 对于视频,只有Stream对应引擎层的Stream,并没有channel的概念;
- 对于音频,引擎层的一个Stream就对应Call层的一个
三者的总结关系:
层次 | 作用 | 音频之间关系 | 视频之间关系 |
---|---|---|---|
Session | 管理逻辑 Stream 和其包含的 Track |
一个 Track (音轨)对应一个 Channel 。 |
一个 Track 映射为一个 Stream 。 |
MediaEngine | 处理底层音视频流管理,区分发送与接收 | 一个 Stream 对应 Call 层的 SendStream 或 ReceiveStream 。每个 Channel 中有若干 Stream 。 |
一个Stream 直接传到Call 层。 |
Call | 与用户操作逻辑一致,将 Stream 转化为最终发送/接收流 |
Stream 对应 SendStream 或ReceiveStream ,还有Channel 连接编解码器。 |
Stream 与用户的发送流或接收流一一对应。 |
视频 Channel 与 Stream图示:
Session 层:
+------------------+
| Stream |--- 同一个对等会话上的视频流逻辑。
| - Track (Video) |
+------------------+
|
MediaEngine 层:
+------------------------+
| Channel (VideoChannel) |--- 管理多路视频数据
+------------------------+
|
+----> Stream 1 (Send方向)
+----> Stream 2 (Recv)
.
Call 层:
+-------------------+
| SendStream |
| ReceiveStream |---- 视频输流的最外层封装接口
+-------------------+
四、NACK调用关系:
调用关系如下图:
- 看下调用顺序基本是:Channel -> Call -> Stream;
- 音频引擎那一节介绍过
RtpDemuxer
,就是数据分发器,总共两个地方用到:- 当收到RTP数据包的时候,通过
RtpDemuxer
分发给不同Channel
(音频是Channel或者视频是Stream); - 就是当前这个地方,分发给不同的Stream(每个Stream又连接着解码器);
- 分发给不同Stream时候,如果是正常包就分发给
RtpVideoStreamReceiver
,如果是RTX数据包,那么就分发给RtxReceiveStream
,当然,处理完之后还得继续发给RtpVideoStreamReceiver
;
- 当收到RTP数据包的时候,通过
- 当
OnReceivedPayloadDat