c – 如何使用VideoWriter从OpenCV打开GStreamer管道

我正在使用OpenCV VideoCapture捕获视频帧.捕获工作正常,因为我能够使用这样的帧:

cv::VideoCapture cap("v4l2src device=/dev/video1 ! videoscale ! videorate ! video/x-raw, width=640, height=360, framerate=30/1 ! videoconvert ! appsink");
cv::imshow("feed", frame);

我也想通过网络发送流,这里是我被卡住的地方.不知怎的,我在appsrc管道部分失败了.我想将流编码为jpeg并将其发送给vie udp.这就是我得到的:

cv::VideoWriter writer
writer.open("appsrc ! videoconvert ! jpegenc ! jpegparse ! rtpjpegpay pt=96 ! udpsink host=192.168.1.25 port=5000", 0, (double)30, cv::Size(640, 360), true);

看起来上面的行没有做任何事情.作者<< framedoes什么都不做.此gstreamer命令也不显示任何内容:

gst-launch-1.0 udpsrc port=5000 caps = "application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)JPEG, payload=(int)96" ! rtpjpegdepay ! jpegdec ! decodebin ! videoconvert ! autovideosink

我不知道我在作家的哪个方面失败了.开放的部分.如果我运行像这样的gstreamer命令,他们的工作:

gst-launch-1.0 v4l2src device=/dev/video1 ! videoscale ! videorate ! video/x-raw, width=640, height=360, framerate=30/1 ! jpegenc ! jpegparse ! rtpjpegpay pt=96 ! udpsink host=192.168.1.25 port=5000
gst-launch-1.0 udpsrc port=5000 caps = "application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)JPEG, payload=(int)96" ! rtpjpegdepay ! jpegdec ! decodebin ! videoconvert ! autovideosink

解决方法:

在使用OpenCV的Gstreamer API之前,我们需要一个使用Gstreamer命令行工具的工作管道.

发件人:OP正在使用JPEG编码,因此该管道将使用相同的编码.

gst-launch-1.0 -v v4l2src \
! video/x-raw,format=YUY2,width=640,height=480 \
! jpegenc \
! rtpjpegpay \
! udpsink host=127.0.0.1 port=5000

接收方:rtpjpegdepay的接收上限需要匹配发送方管道的rtpjpegpay的src大写.

gst-launch-1.0 -v udpsrc port=5000 \
! application/x-rtp, media=video, clock-rate=90000, encoding-name=JPEG, payload=26 \
! rtpjpegdepay \
! jpegdec \
! xvimagesink sync=0

既然我们有发送方和接收方的工作流水线,我们可以将它们移植到OpenCV.

发件人:

void sender()
{
    // VideoCapture: Getting frames using 'v4l2src' plugin, format is 'BGR' because
    // the VideoWriter class expects a 3 channel image since we are sending colored images.
    // Both 'YUY2' and 'I420' are single channel images. 
    VideoCapture cap("v4l2src ! video/x-raw,format=BGR,width=640,height=480,framerate=30/1 ! appsink",CAP_GSTREAMER);

    // VideoWriter: 'videoconvert' converts the 'BGR' images into 'YUY2' raw frames to be fed to
    // 'jpegenc' encoder since 'jpegenc' does not accept 'BGR' images. The 'videoconvert' is not
    // in the original pipeline, because in there we are reading frames in 'YUY2' format from 'v4l2src'
    VideoWriter out("appsrc ! videoconvert ! video/x-raw,format=YUY2,width=640,height=480,framerate=30/1 ! jpegenc ! rtpjpegpay ! udpsink host=127.0.0.1 port=5000",CAP_GSTREAMER,0,30,Size(640,480),true);

    if(!cap.isOpened() || !out.isOpened())
    {
        cout<<"VideoCapture or VideoWriter not opened"<<endl;
        exit(-1);
    }

    Mat frame;

    while(true) {

        cap.read(frame);

        if(frame.empty())
            break;

        out.write(frame);

        imshow("Sender", frame);
        if(waitKey(1) == 's')
            break;
    }
    destroyWindow("Sender");
}

接收器:

void receiver()
{    
    // The sink caps for the 'rtpjpegdepay' need to match the src caps of the 'rtpjpegpay' of the sender pipeline
    // Added 'videoconvert' at the end to convert the images into proper format for appsink, without
    // 'videoconvert' the receiver will not read the frames, even though 'videoconvert' is not present
    // in the original working pipeline
    VideoCapture cap("udpsrc port=5000 ! application/x-rtp,media=video,payload=26,clock-rate=90000,encoding-name=JPEG,framerate=30/1 ! rtpjpegdepay ! jpegdec ! videoconvert ! appsink",CAP_GSTREAMER);

    if(!cap.isOpened())
    {
        cout<<"VideoCapture not opened"<<endl;
        exit(-1);
    }

    Mat frame;

    while(true) {

        cap.read(frame);

        if(frame.empty())
            break;

        imshow("Receiver", frame);
        if(waitKey(1) == 'r')
            break;
    }
    destroyWindow("Receiver");
}
上一篇:【lucene系列学习四】使用IKAnalyzer分词器实现敏感词和停用词过滤


下一篇:c – 致命错误:gst / gst.h:没有这样的文件或目录(使用CMake)