c++ opencv video gstreamer

c++ - Cómo abrir una tubería GStreamer desde OpenCV con VideoWriter



(1)

Estoy capturando cuadros de video con OpenCV VideoCapture. La captura funciona bien, ya que puedo usar los marcos de esta manera:

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

También me gustaría enviar la transmisión a través de la red y aquí es donde estoy atascado. De alguna manera estoy fallando en la parte de la tubería de appsrc. Quiero codificar el flujo a jpeg y enviarlo vie udp. Esto es lo que conseguí:

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

Parece que la línea anterior no hace nada. El writer << frame no hace nada. Además, este comando gstreamer no muestra nada:

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

No sé dónde estoy fallando en el writer.open . Parte writer.open . Si ejecuto los comandos de gstreamer como este a continuación, funcionan:

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


Antes de usar la API de Gstreamer de OpenCV, necesitamos una tubería de trabajo que use la herramienta de línea de comando Gstreamer.

Remitente: El OP utiliza la codificación JPEG, por lo que esta canalización utilizará la misma codificación.

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

Receptor: las caps sumidero para rtpjpegdepay deben coincidir con las caps de src de la rtpjpegpay del remitente.

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

Ahora que tenemos canales de trabajo para el remitente y el receptor, podemos portarlos a OpenCV.

Remitente:

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

Receptor:

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