我正在使用OpenCV捕获和处理视频帧,我想将它们写成h265视频文件.我正在努力从OpenCV获得适当的Gstreamer管道.
Gstreamer本身很好用.特别是,我能够运行这个命令,它可以非常快速地编码视频(感谢GPU加速)并将其保存到mkv文件中:
gst-launch-1.0 videotestsrc num-buffers=90 ! 'video/x-raw, format=(string)I420, width=(int)640, height=(int)480' ! omxh265enc ! matroskamux ! filesink location=test.mkv
现在我想从我的OpenCV应用程序中做同样的事情.我的代码是这样的:
Mat img_vid = Mat(1024, 1024, CV_8UC3);
VideoWriter video;
video.open("appsrc ! autovideoconvert ! omxh265enc ! matroskamux ! filesink location=test.mkv", 0, (double)25, cv::Size(1024, 1024), true);
if (!video.isOpened()) {
printf("can't create writer\n");
return -1;
}
while ( ... ) {
// Capture frame into img_vid => That works fine
video.write(img_vid);
...
}
乍一看,这似乎工作,但它的作用是创建名为“appsrc!autovideoconvert!omxh265enc!matroskamux!filesink location = test.mkv”的文件并用未压缩的视频帧填充它,完全忽略了这是一个事实Gstreamer管道.
我尝试过其他管道,但它们会导致各种错误:
video.open("appsrc ! autovideoconvert ! omxh264enc ! 'video/x-h264, streamformat=(string)byte-stream' ! h264parse ! qtmux ! filesink location=test.mp4 -e", 0, (double)25, cv::Size(1024, 1024), true);
结果如下:
(Test:5533): GStreamer-CRITICAL **: gst_element_make_from_uri:
assertion ‘gst_uri_is_valid (uri)’ failed OpenCV Error: Unspecified
error (GStreamer: cannot find appsrc in manual pipeline ) in
CvVideoWriter_GStreamer::open, file
/home/ubuntu/opencv/modules/videoio/src/cap_gstreamer.cpp, line 1363
VIDEOIO(cvCreateVideoWriter_GStreamer(filename, fourcc, fps,
frameSize, is_color)): raised OpenCV exception:/home/ubuntu/opencv/modules/videoio/src/cap_gstreamer.cpp:1363: error:
(-2) GStreamer: cannot find appsrc in manual pipeline in function
CvVideoWriter_GStreamer::open
我也试过这么简单:
video.open("appsrc ! autovideosink", 0, (double)25, cv::Size(1024, 1024), true);
产量:
GStreamer Plugin: Embedded video playback halted; module appsrc0
reported: Internal data flow error.
我正在使用OpenCV 3.1和Gstreamer支持.硬件是带有L4T 24.2.1的Jetson TX1.
解决方法:
我以前遇到过类似的问题.由于管道/文件名以.mkv结尾,OpenCV会将其解释为视频文件而不是管道.
您可以尝试以mkv之后的虚拟间距结束它
video.open("appsrc ! autovideoconvert ! omxh265enc ! matroskamux ! filesink location=test.mkv ", 0, (double)25, cv::Size(1024, 1024), true);
或者像虚拟财产一样
video.open("appsrc ! autovideoconvert ! omxh265enc ! matroskamux ! filesink location=test.mkv sync=false", 0, (double)25, cv::Size(1024, 1024), true);