C++ 使用VideoWriter从OpenCV打开GStreamer管道

C++ 使用VideoWriter从OpenCV打开GStreamer管道,c++,opencv,video,gstreamer,C++,Opencv,Video,Gstreamer,我正在用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' !

我正在用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);
其结果是:

(测试:5533):GStreamer临界**:gst元素从uri生成: 断言“gst\u uri\u有效(uri)”失败OpenCV错误:未指定 中出现错误(GStreamer:无法在手动管道中找到appsrc) CvVideoWriter\u GStreamer::打开,文件 /home/ubuntu/opencv/modules/videoio/src/cap_gstreamer.cpp,第1363行 VIDEOIO(cvCreateVideoWriter_GStreamer)(文件名,fourcc,fps, frameSize,is_color)):引发的OpenCV异常:

/home/ubuntu/opencv/modules/videoio/src/cap_gstreamer.cpp:1363:错误: (-2)GStreamer:在函数中的手动管道中找不到appsrc CvVideoWriter\u GStreamer::打开

我也试过简单的方法:

video.open("appsrc ! autovideosink", 0, (double)25, cv::Size(1024, 1024), true);
这将产生:

GStreamer插件:嵌入式视频播放暂停;模块appsrc0 报告:内部数据流错误


我正在使用OpenCV 3.1和Gstreamer支持。硬件是带有L4T 24.2.1的Jetson TX1。

我以前遇到过类似的问题。由于管道/文件名以
.mkv
结尾,OpenCV将其解释为视频文件而不是管道

您可以尝试使用类似于after
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);

它有效!!!!哦,老兄,非常感谢你。我花了这么多时间在这上面,不知道出了什么问题……嗨,先生!如何将图像写入/推送到RTMP管道,而不是文件?这对我来说不起作用。它仍在写入一个名为整个Gstreamer管道的文件,不管末尾是否有空格或伪属性(Gstreamer 1.12.4,Mac OSX 10.13.3)。@SimonGarnier还有另一个重载到
VideoWriter::open()
函数和
apiPreference
参数。您可能希望使用
cv::CAP_GSTREAMER
作为
apipereference
参数来尝试。这里有一个指向函数文档的链接:@AlperKucukkomurler-Yep,就是它。谢谢