RTP分片与UDP分片

6
我不明白为什么我们要在RTP层面进行分片,如果UDP(或IP)层已经进行了分片。
据我所知,假设我们在以太网链路上,MTU为1500字节。
如果我需要发送3880字节,那么在IP层面进行分片将导致3个数据包,分别为1500、1500和940字节(IP头为20字节,因此总开销为60字节)。
如果我在UDP层面进行分片,则开销为84字节(3x28字节)。
在RTP层面上,开销为120字节。
在H264 / NAL分组层,还需要额外的3个字节(因此最终为123个字节),适用于FU-A模式。
对于这样一个小数据包,它使初始数据包大小最终增加了3.1%,而在IP层,总体浪费只有1.5%。
知道它比较低层的分片更差,是否有任何有效的理由来麻烦制定这样复杂的RTP层面的分片规则?
4个回答

5
除了第一个分片,分段IP流量不包含源端和目标端口号。 相反,它使用序列ID将数据包粘合在一起。这使得无状态的中间网络设备(交换机和路由器)需要重新安装QoS(因为.1p或DSCP标志已被其他设备清除或从未存在)。除非该设备具有管理每个会话状态的资源,否则它要么冒着限制/优先处理来自不相关流的碎片的风险,要么不对任何碎片进行优先处理,其中一些可以是语音/视频。
据我所知,RTP数据包永远不会进行IP分段,除非网络中存在MTU不匹配。因此,每个UDP头都有源端和目标端口号,因此,如果您可以控制客户端使用已知的端口范围,则可以根据此信息重新建立QoS标记,并将IP分段作为普通流量传递,而不必担心删除语音/视频数据。

3
RTP是针对UDP设计的。
应用程序通常在UDP之上运行RTP,以利用其复用和校验服务;两个协议都提供了传输协议功能的部分。
然而,添加到原始UDP的RTP服务,例如检测数据包重排、丢失和定时等功能,需要UDP数据由RTP有效负载和服务信息组成。
像其他分组网络一样,互联网偶尔会丢失和重新排序数据包,并将它们延迟不同的时间。为了应对这些损伤,RTP头包含定时信息和序列号,使接收者能够重构源产生的定时,因此,在本例中,每20毫秒扬声器会连续播放音频块。这种定时重构是针对会议中每个RTP数据包源单独执行的。接收者还可以使用序列号来估计正在丢失多少个数据包。
然后,RTP旨在具有可扩展性,共同的头部和特定数据有效负载。
RTP是一个故意不完整的协议框架。本文规定了那些预计在所有适用于RTP应用程序中通用的功能。与传统协议不同,传统协议可能通过使协议更加普遍或添加需要解析的选项机制来容纳其他功能,而RTP旨在根据需要通过修改和/或添加标头进行定制。以上引用摘自RFC 1889 "RTP: A Transport Protocol for Real-Time Applications"
也就是说,对于H.264流,RTP开销不仅是带宽浪费。RTP标头和H.264有效载荷格式化以相对较低的成本实现了对视频数据流的更可靠处理,并同时利用了良好定义且适用于不同类型数据的规范。

虽然你说的很正确,但并没有回答我所问的问题。我不是在问为什么要使用 RTP 而不是 UDP(这对我来说很清楚),而是想知道为什么需要 H264 的 FU-A 分片,因为发送大数据包最终会消耗更多的数据,而使用 IP 层分片则不会导致重排序,因为完整的 RTP 数据包和头部将被保留。 - xryl669
你需要一些数据来确定你接收到了什么样的数据包。乱序的数据包?带有NAL单元的数据包?NAL单元的一部分?显然应该保留几个字节来提供这样的标识。然后,H.264传输是设计成这样的方式,不需要检测起始码来解析NAL单元(否则会再次消耗几个字节),因此应该清楚一个数据包是带填充的NAL单元,还是几个NAL单元足够小以适合单个UDP数据包。这就是FU-A的来源 - 一种将NAL单元排列成部分的方法。 - Roman R.
我的意思是,如果我有一个56kB的NAL,并发送一个56kB的RTP数据包,它将被IP层分成尽可能多的IP数据包,并由客户端接收为单个56kB的RTP数据包(并按顺序,否则根本不会存在)。 (最初的)NAL头仍然存在。该方案浪费的开销比使用FU-A标记的38个1.5kB RTP数据包要少得多。此外,FU-A头中的开始和结束位与RTP的头标记/序列号和时间戳重复,因为它们必须匹配。 - xryl669
想象一下,如果你丢失了一个数据包,那么按照RFC定义和你的方法来追回它需要做些什么。 - Roman R.
如果您丢失任何单个数据包(无论是FU-A / RTP还是IP的部分版本),都无法重建NAL单元。最终,使用两种方法将获得相同的结果。因此,我不理解您的最后一条评论。 - xryl669

1
我想补充一点,许多RTP服务器/发送器在发送分割数据报时效率低下。
它们在动态缓冲区上使用了大量的malloc/free。
它们还使用每个消息部分一个系统调用而不是消息向量。
更加糟糕的是,它们通常在发送数据报的每个部分之间进行大量的时间计算/其他处理。
这会导致更多的系统调用,有时甚至会因为没有上限来确定何时应该完成数据包,只有在发送下一批数据包之前完成它,而将数据包延长很长时间。
像这样的低效行为严重阻碍了如果您想扩展吞吐量或在低功耗嵌入式CPU上运行。出于带宽,网络和CPU效率原因,通常最好将整个数据报一次性发送到内核,并让它处理分段,而不是用户空间试图弄清楚它。

0

经过深思熟虑,使用基于IP的分片方式最多可达64kB是没有任何理由不这样做的(如果您需要通过STAP-A等方式聚合许多相同时间戳的NAL单元)。

RFC6184很清楚,您可以以这种方式使用高达64kB的NAL,因为每个NAL单元的大小都会在实际NAL单元之前附加2个字节(16位),尽管保持低于MTU更好。

如果“一次性”NAL单元的累计大小大于64kB会发生什么?RFC6184没有说明,但我猜您将不得不将所有NAL作为单独的FU-A数据包发送,而不增加它们之间的时间戳(这就是为什么FU-A头中的Start / End位有用的唯一原因,因为End位和RTP的标记位之间不再具有1:1匹配)。

RFC声明:

聚合数据包可以携带尽可能多的聚合单元; 但是,聚合数据包中的所有数据总量显然必须适合IP数据包,并且应选择大小,以便生成的IP数据包小于MTU大小

当“每帧单个NAL”大于MTU(例如,以太网为1460字节)时,必须使用分片单元数据包(例如,FU-A)进行拆分。

然而,RFC中没有规定限制应该是1460字节。在仅使用以太网流传输时,具有更大的字节大小是有意义的(如上述计算)

如果您有一个大于64kB的NAL单元,则必须使用FU-A发送它,因为您无法将其放入单个IP数据报中。

RFC规定:

这种有效载荷类型允许将NAL单元分成多个RTP数据包。在应用层而不是依赖于较低层次的分片(例如IP)进行此操作具有以下优点:
o 有效载荷格式能够传输大于64 kbytes的NAL单元,特别是在高清格式中可能存在的IPv4网络中(每张图片的切片数量有限,导致每张图片的NAL单元数量有限,可能会产生大的NAL单元)。
o 分片机制允许将单个NAL单元分片并应用通用前向纠错,如第12.5节所述。
我理解为:“如果您的NAL单元小于64kbytes,并且您不关心FEC,则不要使用FU-A,而是使用单个RTP数据包。”
另一个需要使用FU-A的情况是在使用RTP通过RTSP(交错模式)接收H264流时。 “数据包”的大小必须适合2个字节(16位),因此即使在可靠的流套接字上发送,您也必须分片较大的NAL单元。

1
在寻找不同的数据时,我偶然发现了这篇2015年的帖子。如果有用的话:我没有看到这个讨论中提到延迟。如果你正在使用RTP发送音频数据,你希望那20毫秒的音频包尽快离开你的盒子。你不希望你的听众在IP处理分段之前等待64k的opus编码数据。接收者可能会因为编码压缩而在几秒钟内听不到你的声音。 - fionbio
你说得对。然而问题是相反的,如何在现有的链接上尽可能高效地传输尽可能多的数据。在这种特定情况下,使用IP分段更有效。只有当延迟不是问题时(正如你所提到的),这才是有效的。如果延迟是一个问题,那么小包将工作得更好(但显然会有更多的带宽开销)。据我所知,音频不使用H264的NAL。 - xryl669
当通道存在错误时,UDP 需要重新传输所有分组的整个数据包。相比之下,RTP 只需要重新传输丢失的分组。如果带宽不是问题,这种差异将转化为不同的延迟。 - minghua
如果没有尝试重新传输,差异将转化为缺失数据的数量。如果在同一数据包中丢失了任何分片,UDP 将不会向您提供已接收的分片。RTP 只会传递其所接收到的内容。最终,视频或音频的呈现质量将有所不同。 - minghua

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接