使用VideoWriter从OpenCV打开GStreamer管道

Eri*_*uth 0 c++ video opencv 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' ! omxh265enc ! matroskamux ! filesink location=test.mkv
Run Code Online (Sandbox Code Playgroud)

现在我想从我的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);

   ...
}
Run Code Online (Sandbox Code Playgroud)

乍一看,这似乎有效,但它的作用是创建文件命名 "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);
Run Code Online (Sandbox Code Playgroud)

结果如下:

(测试:5533):GStreamer-CRITICAL**:gst_element_make_from_uri:断言'gst_uri_is_valid(uri)'失败OpenCV错误:未指定错误(GStreamer:在手动管道中找不到appsrc)CvVideoWriter_GStreamer :: open,file/home/ubuntu/opencv /modules/videoio/src/cap_gstreamer.cpp,第1363行VIDEOIO(cvCreateVideoWriter_GStreamer(filename,fourcc,fps,frameSize,is_color)):引发OpenCV异常:

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

我也试过这么简单:

video.open("appsrc ! autovideosink", 0, (double)25, cv::Size(1024, 1024), true);
Run Code Online (Sandbox Code Playgroud)

产量:

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

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

Alp*_*ler 7

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

您可以尝试使用像之后的虚拟间距来结束它 mkv

video.open("appsrc ! autovideoconvert ! omxh265enc ! matroskamux ! filesink location=test.mkv ", 0, (double)25, cv::Size(1024, 1024), true);
Run Code Online (Sandbox Code Playgroud)

或者像虚拟财产一样

video.open("appsrc ! autovideoconvert ! omxh265enc ! matroskamux ! filesink location=test.mkv sync=false", 0, (double)25, cv::Size(1024, 1024), true);
Run Code Online (Sandbox Code Playgroud)

  • @SimonGarnier带有`apiPreference`参数的`VideoWriter :: open()`函数有另一个重载.您可能希望使用`cv :: CAP_GSTREAMER`作为`apiPreference`参数进行尝试.以下是该函数文档的链接:https://docs.opencv.org/3.3.0/dd/d9e/classcv_1_1VideoWriter.html#a808ee7d60c58af071035a19e396bfa91 (2认同)