9 个版本 (5 个破坏性更新)
0.13.0 | 2024年7月16日 |
---|---|
0.12.0 | 2024年2月8日 |
0.11.1 | 2023年10月4日 |
0.10.0 | 2023年2月9日 |
0.9.0 | 2022年10月24日 |
#1 在 #数据包
每月110 次下载
79KB
1.5K SLoC
简介
这是 GStreamer 对 RTP 流的 RaptorQ FEC 的实现。
发送元素从 K
个 RTP 数据包中生成所需数量的修复数据包 X
。接收器只需要
K
个任何修复或 RTP 数据包即可以 99% 的概率恢复所有数据K + 1
个任何修复或 RTP 数据包即可以 99.99% 的概率恢复所有数据,K + 2
个任何修复或 RTP 数据包即可以 99.9999% 的概率恢复所有数据等。
相关文档
- RFC6363 - 前向纠错 (FEC) 框架
- RFC6681 - 用于 FECFRAME 的 Raptor 前向纠错 (FEC) 方案
- RFC6682 - Raptor 前向纠错 (FEC) 的 RTP 负载格式
发送/接收示例
gst-launch-1.0 \
rtpbin name=rtp fec-encoders='fec,0="raptorqenc\ mtu=1356\ symbol-size=192";' \
uridecodebin uri=file:///path/to/video/file ! x264enc key-int-max=60 tune=zerolatency ! \
queue ! mpegtsmux ! rtpmp2tpay ssrc=0 ! \
rtp.send_rtp_sink_0 rtp.send_rtp_src_0 ! udpsink host=127.0.0.1 port=5000 \
rtp.send_fec_src_0_0 ! udpsink host=127.0.0.1 port=5002 async=false
gst-launch-1.0 \
rtpbin latency=200 fec-decoders='fec,0="raptorqdec";' name=rtp \
udpsrc address=127.0.0.1 port=5002 \
caps="application/x-rtp, payload=96, raptor-scheme-id=(string)6, repair-window=(string)1000000, t=(string)192" ! \
queue ! rtp.recv_fec_sink_0_0 \
udpsrc address=127.0.0.1 port=5000 \
caps="application/x-rtp, media=video, clock-rate=90000, encoding-name=mp2t, payload=33" ! \
queue ! netsim drop-probability=0.05 ! rtp.recv_rtp_sink_0 \
rtp. ! decodebin ! videoconvert ! queue ! autovideosink
实现细节
编码器元素
编码器元素在内部存储原始 RTP 数据包的副本,直到它收到请求一起保护的数据包数量。此时,它创建一个源块,并将其传递给 RaptorQ 编码器。源块是通过连接 ADUI(应用程序数据单元信息)构建的,有时也称为 SPI(源数据包信息)。每个 ADUI 包含
- 带有流 ID 的头部 -
F(I)
和数据包长度的指示 -L(I)
, - UDP 负载,这是一个完整的 RTP 数据包,包括头部,
- 如果需要,填充字节,
T T T T
<----------------><--------------><---------------><---------------->
+----+--------+-----------------------+-----------------------------+
|F[0]| L[0] | ADU[0] | Pad[0] |
+----+--------+----------+------------+-----------------------------+
|F[1]| L[1] | ADU[1] | Pad[1] |
+----+--------+----------+------------------------------------------+
|F[2]| L[2] | ADU[2] |
+----+--------+------+----------------------------------------------+
|F[3]| L[3] |ADU[3]| Pad[3] |
+----+--------+------+----------------------------------------------+
\_________________________________ ________________________________/
\/
RaptorQ FEC encoding
+-------------------------------------------------------------------+
| Repair 4 |
+-------------------------------------------------------------------+
. .
. .
+-------------------------------------------------------------------+
| Repair 7 |
+-------------------------------------------------------------------+
T - Symbol Size
F - Flow ID
L - Length Indication
ADU - Application Data Unit (RTP packet)
编码器元素为给定的源块创建所需数量的数据包。修复数据包在 repair-window
期间发送,这是一个可配置的参数。例如,如果编码器元素生成 5 个修复数据包,并且将 repair-window
设置为 500ms,则第一个修复数据包在最后一个受保护的数据包后 100ms 发送,第二个在 200ms,最后一个在 repair-window
。
除了用于恢复丢失源数据包所需的符号外,每个修复数据包还包含源数据块的有关信息。
I
- 源数据块的初始序列号,Lp
- 符号中的ADUI长度,Lb
- 源数据块长度(以符号为单位),
解码器元素
解码器元素存储接收到的RTP数据包的副本,并立即将原始数据包推送到下游。如果所有RTP数据包都已接收,则丢弃缓冲的媒体数据包。如果任何数据包丢失,接收器会检查是否有足够的缓冲媒体和修复数据包来进行解码。如果是这种情况,它将尝试通过按照发送者相同的规则构建源数据块来恢复丢失的数据包,除了跳过丢失的数据包并在块中添加修复数据包。
因为接收器元素不会引入延迟,所以恢复的数据包会按顺序发送,这需要链式下游的rtpjitterbuffer
。需要将rtpjitterbuffer
配置为足够高的延迟。
接收器确定哪些媒体数据包属于源数据块时,使用可以从任何修复数据包中检索到的信息。然后,在构建源数据块时,考虑序列号为:I + Lb/Lp - 1
的媒体数据包(包括)。
接收器使用发送者发出的repair-window
以及自己的repair-window-tolerance
参数来决定在放弃之前应该等待对应修复数据包多长时间。等待时间为repair-window + repair-window-tolerance
。
依赖关系
~11MB
~230K SLoC