在 Ubuntu 上使用 OpenCV 的 ffmpeg 解码 h264(高)流

Decoding a h264 (High) stream with OpenCV's ffmpeg on Ubuntu

我正在 Ubuntu 14.04 上使用来自网络摄像机的视频流。使用具有这些参数(来自 FFMPEG)的相机,一切都很顺利:

    Stream #0:0: Video: h264 (Main), yuv420p(progressive), 352x192, 29.97 tbr, 90k tbn, 180k tbc

但后来我换了一个较新的相机,它有这些参数:

    Stream #0:0: Video: h264 (High), yuvj420p(pc, bt709, progressive), 1280x720, 25 fps, 25 tbr, 90k tbn, 50 tbc

我的 C++ 程序使用 OpenCV3 来处理流。默认情况下,OpenCV 使用 ffmpeg 解码和显示带有函数 VideoCapture 的流。

VideoCapture vc;
vc.open(input_stream);
while ((vc >> frame), !frame.empty()) {
   *do work*
}

使用新的摄像头流时,我得到了这样的错误(来自 ffmpeg):

[h264 @ 0x7c6980] cabac decode of qscale diff failed at 41 38
[h264 @ 0x7c6980] error while decoding MB 41 38, bytestream (3572)
[h264 @ 0x7c6980] left block unavailable for requested intra mode at 0 44
[h264 @ 0x7bc2c0] SEI type 25 truncated at 208

图像有时会出现故障,有时会完全冻结。但是 在 vlc 上播放完美。我用

安装了最新版本的 ffmpeg 播放器 (3.2.2)
./configure --enable-gpl --enable-libx264

现在直接用ffplay播放(而不是用OpenCV函数VideoCapture从源代码启动),流播放效果更好,但有时仍然会显示警告:

[NULL @ 0x7f834c008c00] SEI type 25 size 896 truncated at 320=1/1   
[h264 @ 0x7f834c0d5d20] SEI type 25 size 896 truncated at 319=1/1   
[rtsp @ 0x7f834c0008c0] max delay reached. need to consume packet   
[rtsp @ 0x7f834c0008c0] RTP: missed 1 packets
[h264 @ 0x7f834c094740] concealing 675 DC, 675 AC, 675 MV errors in P frame

更改相机硬件不是一个选项。可以将相机设置为编码为 h265 或 mjpeg。当编码为 mjpeg 时,它可以输出 5 fps,这是不够的。解码为静态视频也不是一个选项,因为我需要显示有关流的实时结果。 Here 是可在函数 VideoCapture 中使用的 API 后端列表。也许我应该换用其他解码器和播放器? 根据我的研究,我得出结论,我有这些选择:

切换到 vlc 的一个例子是 here, but i don't understand it well enough to say if that is what i need. Or maybe i should be 代码中的流?

这可能很慢,这又对实时结果不利。
任何建议和意见将不胜感激。

由于默认使用RTP,所以报错是丢包导致的。您现在看到更多错误,因为您已切换到更高的比特率输入。

?tcp 添加到您的输入中,例如。 rtsp://*private*/media/video2?tcp 在 OpenCV 的 open 函数中强制使用 TCP,前提是您的硬件 and/or 使用场景支持它。

我已经基本解决了这个问题。

  • 首先,我使用必要的设置手动安装了最新版本的 ffmpeg 重新编译了 OpenCV。
  • 我使用 VLC 工具 > 编解码器信息 检查了流,以检查流是否有损坏的帧,但事实并非如此。
  • 我降低了流分辨率。这给了最大的改进。
  • 最后一个错误是

    [NULL @ 0x7f834c008c00] SEI 类型 25 大小 896 在 320=1/1
    处截断 [h264 @ 0x7f834c0d5d20] SEI 类型 25 大小 896 在 319=1/1 处截断

但它不会明显损坏框架。然而,我还没有解决流冻结问题,但这与我的代码有关,与软件无关。如果我可以帮助遇到类似问题的任何人,请随时询问更多信息。

经过 4 天的研究,我遇到了同样的问题,最后我通过这段代码轻松解决了这个问题:

for(;;) {
        if(!vcap.read(image)) {
            std::cout << "No frame" << std::endl;
            cv::waitKey();
        }
        cv::imshow("Output Window", image);
        if(cv::waitKey(1) >= 0) break;
    }