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

时间:2016-12-21 14:59:07

标签: opencv video ffmpeg h.264 rtsp

我在Ubuntu 14.04上使用来自ip camera的视频流。使用具有这些参数的相机(来自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后端列表。也许我应该切换到其他解码器和播放器? 从我的研究中我得出结论,我有这些选择:

  • 以某种方式让OpenCV使用libVlc而不是ffmpeg

切换到vlc的一个例子是here,但我不太清楚它是否足以说明这是否是我需要的。或者也许我应该parsing代码中的流?

  • 使用vlc按照建议here预处理流。

这可能很慢,这对实时结果来说又不好 任何建议和评论都将不胜感激。

3 个答案:

答案 0 :(得分:2)

错误是由丢包引起的,因为它默认使用RTP。您现在看到更多错误,因为您已切换到更高的比特率输入。

?tcp附加到您的输入中,例如。假设您的硬件和/或使用场景支持TCP,OpenCV的rtsp://*private*/media/video2?tcp函数中open强制使用TCP。

答案 1 :(得分:2)

我基本上解决了这个问题。

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

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

但它没有明显损坏框架。我没有解决流冻结问题,但它与我的代码有关,而不是软件。如果我可以帮助有类似问题的人,请随时询问其他信息。

答案 2 :(得分:0)

我在研究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;
    }