音频流传输:使用Gstreamer接收RTP流 - 延迟

6

目前我正在研究一个音频IP项目,并想知道你是否能帮助我。 我有一个局域网,其中包含一个音频源(Dante / AES67-RTP-流),我想将其分发到多个接收器(SBC(例如RaspberryPi)配备音频输出(例如耳机插孔):

PC-->Audio-USB-Dongle-->AES67/RTP-Multicast-Stream-->LAN-Network-Switch-->RPI (Gstreamer --> AudioJack)

我目前使用Gstreamer处理数据流:

gst-launch-1.0 -v udpsrc uri=udp://239.69.xxx.xx:5004 caps="application/x-rtp,channels=(int)2,format=(string)S16LE,media=(string)audio,payload=(int)96,clock-rate=(int)48000,encoding-name=(string)L24" ! rtpL24depay ! audioconvert ! alsasink device=hw:0,0

一切都运作得很好,但是如果我在电脑上观看视频并从RPI听音频,会有一些延迟(约200-300毫秒),因此我的问题如下:

  1. 我在我的Gstreamer Pipeline中是否漏掉了某些内容以便降低延迟?
  2. 使用RTP流能够实现的最小延迟是多少,是否可以达到<50ms?
  3. 延迟是由于网络还是由于Raspberry Pi的速度引起的?
  4. 由于我的音频输入不是Gstreamer输入,我假设rtpjitterbuffer或类似的东西不能帮助减少延迟?
1个回答

0

简而言之:如果您坚持使用gstreamer,请检查updsrc缓冲区的大小。我建议使用Ravenna实现。

这个问题非常关注gstreamer,但是可能并不需要它来实现您的目标。 这个答案更多地涉及到在ARM Linux上进行音频IP(AoIP)的一般性问题,就像问题2和3一样。

首先,您提到了视频和音频。如果以专业方式完成,这将需要一个AV over IP解决方案,以保持音频和视频同步。例如DanteAV或符合SMPTE 2110标准的解决方案。对于业余项目,您的方法似乎很好。请记住,Dante在AES67模式下有一些限制

2. 低延迟AoIP:

是的,如果您的设备具有与NXP i.MX8相当的规格,那么肯定可以将Dante/AES67/RTP延迟降至50毫秒以下。

作为参考:使用Dante和专业硬件很容易实现4-5毫秒的往返延迟。

如果您的目标是:“将低延迟AES67流传输到RPi”,我建议查看Linux的Ravenna实现。 Ravenna类似于Dante,但更符合AES67标准。 Ravenna和AES67完全以相同的方式使用RTP。

有两个主要的开源Linux实现:

提供商业支持的"原版"。控制工具是专有的,仅限x86。
  • 有一个分支包含有用的补丁和开源控制软件。
    • 在这两种情况下,您仍然需要为ARM/RPi交叉编译代码。
    • 个人建议使用分支。

    Dante为制造商提供Linux实现,但您可能无法获得该实现:https://www.audinate.com/products/manufacturer-products/dante-embedded-platform

    3.延迟来源

    对于AoIP,有不同的延迟来源:

    • 数据包时间:计算数据包中样本的时间,约为1毫秒。
    • 网络:取决于您的硬件和设置,大约为< 1毫秒到几秒钟。
    • 接收缓冲区:可配置,大约为< 1毫秒到多毫秒。
    • 接收器上的处理和DAC。

    数据包时间应为1毫秒,因为Dante使用AES67强制配置文件(48 kHz,每个数据包48个样本)。我假设您的发送器正确处理此问题,但我无法确定。

    在网络上,您应该至少使用千兆交换机和Cat 5e电缆。 确保遵循建议的交换机和配置(特别是禁用EEE)。 如果发送方和接收方的时钟同步,则在两者上运行tcpdump或Wireshark以获得网络延迟的良好估计。 按端口过滤有效载荷最容易,例如RTP:port 5004或port 9875 Dante:portrange 14336-14591。在捕获中轻松发现静音/取消静音(延迟= T_send-T_recv)。

    如果以上都没有问题,可以查看接收缓冲区或者接收端的处理。 树莓派低延迟音频 似乎 可行。 此外,您可以测量RPi上的ADC / DAC速度并优化您的Linux系统(从无头到实时补丁内核再到使用Yocto构建优化的发行版等)。

    1. 4. Gstreamer

    如前所述,如果您能够这样做,请使用Ravenna Linux实现。 它的整个目的是有效地接收AES67流。 尽管如此,请考虑一些有关您的管道的想法:

    文档中提到udpsrc会添加一个约50KB至100KB可配置的缓冲区。 以1ms数据包时间和48kHz采样率的AES67 RTP数据包大小为342字节。 因此,该缓冲区相当于 50kB / 342字节 * 1ms = 146ms

    -> 这可能是罪魁祸首。

    我认为您不需要使用rtpjitterbuffer。它的文档中提到了“重传”功能。AES67不会重新传输有效负载(据我所知)。 此外,管道还会添加另一个200个数据包的缓冲区,对于1ms数据包时间而言为200ms。 排序等应该仍然可以正常工作,因为AES67使用标准RTP时间戳。但这将增加延迟,在局域网上可能是不必要的。 看起来,rtpjitterbuffer更适用于广域网RTP,而不是本地网络AES67。

    还发现了这篇文章, 它使用的和你一样的pipeline。

    如果这不能解决你的问题,找出延迟是在哪里引入的。并告诉我们延迟是如何测量的。


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