问题-播放组播流卡顿

  • 操作系统:Linux
  • 硬件平台:Arm64
  • 播放工具:Gstreamer-1.0

步骤:

  1. 在一台PC上通过ffmpeg命令行推送ts组播流,通过rtp协议传输ts流。
ffmpeg -re -stream_loop -1 -i hd1080.mp4 -c:v copy -c:a copy -f rtp_mpegts rtp://239.239.22.22:3333
  1. 在arm开发板上通过Gstreamer命令行工具播放该组播流。
    目前gstreamer 无法通过playbin 插件播放通过rtp协议传输的ts流,因为自动创建的管道缺少了插件,所以只能手动组装管道。
gst-launch-1.0 -vv udpsrc uri=udp://239.239.22.22:3333 caps="application/x-rtp,media=video,clock-rate=90000,payload=33,encoding-name=MP2T" ! rtpbin latency=1000 ! rtpmp2tdepay ! tsdemux ! decodebin ! videoconvert ! videoscale ! xvimagesink
  • -vv可以输出状态和属性信息
    在这里插入图片描述
    图中可以看到有许多packet-lost 包,视频播放会不时的出现卡顿。
    而且在自己的主机播放时,视频比较流畅。说明发包的机器出现丢包的情况可能性比较小。

问题排查

首先通过ifconfig 命令查看对应网卡的丢包情况
在这里插入图片描述
发现RX errors 、dropped 、overrun 、frame都是0 ,所以不是网卡的原因、也不是系统繁忙处理不了的原因。
以下是这四个参数的具体含义

  1. RX errors
    表示总的收包的错误数量,这包括 too-long-frames 错误,Ring Buffer 溢出错误,crc 校验错误,帧同步错误,fifo overruns 以及 missed pkg 等等。
  2. RX dropped
    表示这个数据包已经进入到网卡的接收缓存fifo队列,并且开始被系统中断处理准备进行数据包拷贝(从网卡缓存fifo队列拷贝到系统内存),但由于此时的系统原因(比如内存不够等)导致这个数据包被丢掉,即这个数据包被Linux系统丢掉。
  3. RX overruns
    表示这个数据包还没有被进入到网卡的接收缓存fifo队列就被丢掉,因此此时网卡的fifo是满的。为什么fifo会是满的?因为系统繁忙,来不及响应网卡中断,导致网卡里的数据包没有及时的拷贝到系统内存,fifo是满的就导致后面的数据包进不来,即这个数据包被网卡硬件丢掉。
  4. RX frame
    表示 misaligned 的 frames。

既然网卡没有丢包,继续排查是不是协议层丢包。
输入命令:

netstat -su eth0

在这里插入图片描述
发现很多 packet receive errors 和 receive buffer errors
Udp: packet receive errors 增加有以下几点原因:

  • 没有足够的socket buffer 缓冲区
  • UDP 校验失败
  • UDP 包长度不匹配

这三点比较起来,比较大的可能原因是缓冲区不足。
通过命令查看当前设置的缓冲区大小:

sysctl net.core.rmem_default  #默认缓冲区大小
sysctl net.core.rmem_max   #最大缓冲区大小

在这里插入图片描述
缓冲区大小最大是 208Kb,而我们的视频的比特率是3500kbit/s,换算成字节大概是437Kb/s,如果程序读取速度稍慢很可能就会导致缓冲区溢出。

通过命令将缓冲区调大:
默认和最大都是2M

sudo sysctl net.core.rmem_default=2097152
sudo sysctl net.core.rmem_max=2097152

也可以写到配置文件中,每次系统重启后都会生效。

sudo vim /etc/sysctl.conf

添加到文档最后
在这里插入图片描述

让配置生效

sudo sysctl -p 

重新播放组播流

视频已经可以正常流畅播放,已没有丢包。

因为设备都是连接到同一个交换机所以一般不会出现传输过程中的丢包,除非数据流超出了交换机的处理能力。

Logo

更多推荐