Hug*_*h W 7 video opencv ffmpeg h.264
我正在使用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)
Run Code Online (Sandbox Code Playgroud)
我还尝试使用ffmpeg 2.8.14-0ubuntu0.16.04.1和从源代码构建的最新ffmpeg(我使用了此提交),并看到了与以下相同的行为。
我正在运行的命令是:
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
Run Code Online (Sandbox Code Playgroud)
我以每秒至少一个的相当稳定的速度收到各种错误。这是一个示例:
[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
Run Code Online (Sandbox Code Playgroud)
最常见的是“解码MB xx字节流x时出错”。这对应于播放时视频文件中的严重损坏。
我在stackoverflow和其他地方看到了很多对该错误消息的引用,但是我还没有找到令人满意的解释或解决方法。它来自此行,似乎与流末尾的丢失数据相对应。“左块不可用”来自此处,并且看起来也像缺少数据。
还有人建议使用-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.
Run Code Online (Sandbox Code Playgroud)
我使用Wireshark确认,在UDP和TCP模式下,所有数据包都将其从摄像机传输到PC(连续的RTP序列号,没有任何丢失),这使我认为数据到达ffmpeg后就丢失了。
当我对Panasonic WV-SFV110摄像机运行相同的命令时,我也看到类似的行为,但是总的来说出错频率较低。在Panasonic摄像机上从UDP切换到TCP可以减少但不能完全消除错误/损坏。
我还在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流中的数据。
从质量上讲,似乎有几个因素使问题变得更糟:
-codec:copy消除所有错误,但在ffmpeg启动时会产生一些错误)错误是什么意思?那我该怎么办?
听起来丢包确实是个问题。更高的视频分辨率和更大的运动都会增加编码视频流的比特率,这将增加您的数据包丢失。根据丢失的数据包,您会在解码过程中看到不同的错误,如您在帖子中指出的那样。
更高的系统负载运行 ffmpeg 也表明您的网卡可能正在丢弃数据包,例如 ffmpeg 在忙于对视频进行转码时读取它们的时间太长。
第一个问题是你的网络拓扑是什么?通过公共 Internet 进行流式传输比通过 LAN 进行流式传输要困难得多。网络中有哪些类型的交换机/路由器?
下一个问题,您的相机流媒体的比特率是多少?尝试减少它并检查结果。在你的方法中要有系统性,即
我要做的下一件事是增加接收器缓冲区的大小。虽然我对 ffmpeg 不是很熟悉,但您似乎可以recv_buffer_size按照此处的说明进行设置。然后您需要根据您的相机配置计算出足够大的尺寸来存储例如几(5?)秒的视频数据。检查当您增加接收器缓冲区大小或更长的无伪影时间时伪影是否减少。
当然,如果您的处理器速度太慢而无法实时转码视频,那么您迟早会耗尽空间,在这种情况下,您可能必须转码为较低的分辨率/比特率或使用强度较低的编码器设置等或在更快的机器上运行转码。
另请注意,调整接收器缓冲区大小不会补偿公共 Internet 上发生的数据包丢失,因此假设您在支持相机比特率的本地网络上进行流式传输,上述内容将有所帮助。如果超出网络带宽,则可能会丢失数据包。在那种情况下,通过 TCP 流式传输可能会有所帮助(至少在接收器缓冲区最终溢出之前)。
如果上述方法不能帮助或完全解决问题,您可以尝试更多操作:
总之,您有一个管道架构,您需要确定丢失发生在管道中的哪个位置:
camera -> network -> receiver buffer (OS) -> application (ffmpeg)
查看初始错误消息:
[rtsp @ 0x7f268c5e9220] max delay reached. need to consume packet
[rtsp @ 0x7f268c5e9220] RTP: missed 40 packets
Run Code Online (Sandbox Code Playgroud)
我猜您正在丢失UDP数据包。其余的H.264错误消息是由接收不完整的比特流引起的。现在的关键是找出问题所在。您的网络丢包了吗?或者您的服务器接收UDP(RTP)太慢或过载。
首先,我要检查您操作系统的UDP缓冲区大小。https://access.redhat.com/documentation/zh-CN/JBoss_Enterprise_Web_Platform/5/html/Administration_And_Configuration_Guide/jgroups-perf-udpbuffer.html
如果增加UDP缓冲区大小无济于事,请使用ffmpeg和-codec:copy来降低CPU负载。您仍然收到错误吗?由于要重新编码,请考虑使用Intel Quicksync -vcodec h264_qsv或其他一些硬件编码器来降低CPU负载。
问题不在于PC是否具有足够的CPU。但是,更多有关在处理管道中识别瓶颈的信息。您的H.264编码器(x264)可能会超额使用CPU,这样您会得到瞬时峰值负载,从而导致数据包丢失。尝试限制x264的线程数和/或将质量降低为“快速”或“更快”。