c++ वीडियोक्राइटर के साथ OpenCV से एक GStreamer पाइपलाइन कैसे खोलें



video (1)

मैं 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);

ऐसा लगता है कि उपरोक्त रेखा कुछ भी नहीं करती है। writer << frame कुछ भी नहीं करता है। इसके अलावा इस 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

मुझे नहीं पता कि मैं writer.open में writer.open । अगर मैं gstreamer कमांड को इस bellow की तरह चलाता हूं तो वे काम करते हैं:

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 कमांड लाइन टूल का उपयोग करके एक कार्यशील पाइपलाइन की आवश्यकता होती है।

प्रेषक: ओपी जेपीईजी एन्कोडिंग का उपयोग कर रहा है, इसलिए यह पाइपलाइन उसी एन्कोडिंग का उपयोग करेगी।

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 लिए सिंक caps को प्रेषक पाइपलाइन के rtpjpegpay के src caps से मेल rtpjpegdepay चाहिए।

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");
}