解码 MB 时出现 ffmpeg RTSP 错误

ffmpeg RTSP error while decoding MB

我正在使用 ffmpeg 从 Cisco 3050 IP 摄像头读取 h264 RTSP 流并将其重新编码为 h264 到磁盘(我不只是使用 -codec:copy 的原因)。

ffmpeg版本如下:

ffmpeg version 3.2.6 Copyright (c) 2000-2017 the FFmpeg developers
  built with gcc 6.3.0 (Alpine 6.3.0)

我也尝试过使用 ffmpeg 2.8.14-0ubuntu0.16.04.1 和从源代码构建的最新 ffmpeg(我使用 this commit)并看到与下面相同的行为。

我运行的命令是:

ffmpeg -rtsp_transport udp -i 'rtsp://<user>:<pw>@<ip>:554/StreamingSetting?version=1.0&action=getRTSPStream&ChannelID=1&ChannelName=Channel1' -r 10 -c:v h264 -crf 23 -x264-params keyint=60:min-keyint=60 -an -f ssegment -segment_time 60 -strftime 1 /output/%Y%m%d_%H%M%S.ts -abort_on empty_output

我以每秒至少一个的相当稳定的速度收到各种错误。这是一个示例:

[rtsp @ 0x7f268c5e9220] max delay reached. need to consume packet
[rtsp @ 0x7f268c5e9220] RTP: missed 40 packets
[h264 @ 0x55b1e115d400] left block unavailable for requested intra mode
[h264 @ 0x55b1e115d400] error while decoding MB 0 12, bytestream 114567
[h264 @ 0x55b1e115d400] concealing 3889 DC, 3889 AC, 3889 MV errors in I frame

最常见的是'error while decoding MB x x, bytestream x'。这对应于播放时视频文件中的严重损坏。

我在 Whosebug 和其他地方看到很多关于该错误消息的引用,但我还没有找到令人满意的解释或解决方法。它来自 this line which appears to correspond to missing data at the end of the stream. 'left block unavailable' comes from here 并且看起来也缺少数据。

其他人建议改用 -rtsp_transport tcp (1, 2, 3),这在我的例子中只是给出了稍微不同的错误组合,并且仍然是视频损坏:

[h264 @ 0x557923191b00] left block unavailable for requested intra4x4 mode -1
[h264 @ 0x557923191b00] error while decoding MB 0 28, bytestream 31068
[h264 @ 0x557923191b00] concealing 2609 DC, 2609 AC, 2609 MV errors in I frame
[rtsp @ 0x7f88e817b220] CSeq 5 expected, 0 received.

我使用 Wireshark 确认在 UDP 和 TCP 模式下,所有数据包都从相机发送到 PC(连续的 RTP 序列号,没有任何丢失)这让我觉得数据在它之后丢失了到达 ffmpeg。

当 运行 对 Panasonic WV-SFV110 相机执行相同的命令时,我也看到了类似的行为,但总体上错误频率较低。在 Panasonic 相机上从 UDP 切换到 TCP 会减少但不会完全消除 errors/corruption.

我也用 VLC 尝试了类似的命令并得到了类似的错误 (cvlc rtsp://<user>:<pw>@<ip>/MediaInput/h264 :sout='#transcode{vcodec=h264}:std{access=file, mux=ts, dst="output.ts"}) -- 大概自从 libav 从 ffmpeg 分叉以来代码没有太大差异。

摄像头直接插入 PC 上的 PoE 端口,因此网络拥塞不会成为问题。鉴于 PC 有足够的 CPU 来保持对实时流的编码,在我看来,ffmpeg 的一个问题是它仍然从 TCP 流中删除数据。

定性地,有几个因素似乎使问题变得更糟:

错误是什么意思?我该怎么办?

查看初始错误消息:

[rtsp @ 0x7f268c5e9220] max delay reached. need to consume packet
[rtsp @ 0x7f268c5e9220] RTP: missed 40 packets

我猜你正在丢失 UDP 数据包。其余的 H.264 错误消息是由接收到不完整的比特流引起的。 现在关键是隔离问题。您的网络是否丢包?或者您的服务器接收 UDP (RTP) 时速度太慢或过载。

首先,我会检查您 OS 的 UDP 缓冲区大小。 https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Web_Platform/5/html/Administration_And_Configuration_Guide/jgroups-perf-udpbuffer.html

如果增加 UDP 缓冲区大小没有帮助 - 使用带有 -codec:copy 的 ffmpeg 来降低 CPU 负载。你仍然有错误吗? 由于您想重新编码,请考虑使用 Intel Quicksync -vcodec h264_qsv 或其他一些降低 CPU 负载的硬件编码器。

问题不在于 PC 是否 足够 CPU。但更多关于识别处理管道中的 瓶颈 。您的 H.264 编码器 (x264) 可能会过度订阅您的 CPU,从而导致您获得瞬时峰值负载,从而导致数据包丢失。尝试限制 x264 的线程数 and/or 将质量降低到 'fast' 或 'faster'。

听起来丢包确实是个问题。更高的视频分辨率和更大的运动都会增加编码视频流的比特率,这将增加您的数据包丢失。根据丢失的数据包,您会在 post 中指出的解码过程中看到不同的错误。

更高的系统负载 运行ning ffmpeg 也表明您的网卡可能正在丢弃数据包,例如ffmpeg 忙于转码视频时读取它们的时间太长。

第一个问题是您的网络拓扑结构是什么?通过 public Internet 进行流式传输比通过 LAN 进行流式传输要困难得多。网络中有哪些switches/routers?

下一个问题,您的相机流式传输的比特率是多少?尝试减少它并检查结果。系统化您的方法,即

  • 先不要转码。
  • 刚刚收到视频。
  • 写入文件。
  • 检查数据包 loss/video 工件。
  • 从较低的比特率开始,例如100kbps 并在没有明显损失的情况下增加此值

接下来我要做的是增加接收缓冲区的大小。虽然我不太熟悉 ffmpeg,但看起来您可以通过 recv_buffer_size 设置它,如 here 所示。然后,您需要根据您的相机配置计算出一个足够大的尺寸来存储,例如几(5?)秒的视频数据。检查是否随着您增加接收器缓冲区大小或更长的时间没有伪影而减少伪影。

当然,如果您的处理器太慢而无法实时转码视频,您迟早会 运行 超出 space,在这种情况下,您可能需要转码为较低的 resolution/bitrate 或使用强度较低的编码器设置等,或 运行 在更快的机器上进行转码。

另请注意,调整接收器缓冲区大小不会补偿 public 互联网上发生的数据包丢失,因此以上内容将有助于假设您在支持相机比特率的本地网络上进行流式传输。如果超出网络带宽,则可能会丢失数据包。在那种情况下,通过 TCP 进行流式传输可能会有所帮助(至少直到接收器缓冲区最终超过 运行s)。

如果以上方法没有帮助或无法完全解决问题,您可以尝试更多的方法:

  • 使用 wireshark 或 tcpdump 嗅探传入流量。 看看痕迹。使用 "RTSP" 过滤跟踪。 您应该能够看到 RTP 流量,其中连续的 RTP 数据包具有递增的序列号,例如20、21、22、23 等。如果您看到缺少序列号,那么您遇到了数据包丢失并尝试通过 TCP 进行流式传输。通过 TCP 流式传输时重复跟踪。此外,请记住在通过 TCP 进行流式传输时也要增加接收缓冲区大小。

总而言之,您有一个管道架构,您需要确定管道中发生损失的位置:

camera -> network -> receiver buffer (OS) -> application (ffmpeg)