Stream video from Raspberry Pi with OpenCV

Hello,
I am trying to stream my Raspberry Pi camera video modified using OpenCV to the ground station with the following code:

import cv2
import numpy as np

def send():
    cap_send = cv2.VideoCapture(0)
    out_send = cv2.VideoWriter('appsrc ! video/x-raw ! videoconvert ! x264enc ! rtph264pay ! udpsink host=192.168.2.1 port=5600',cv2.CAP_GSTREAMER,0, 30, (1920,1080), True)

    if not cap_send.isOpened():
        print('Error openning in')
        exit(0)
    if not out_send.isOpened():
        print("Error openning out")

    while True:
        ret,frame = cap_send.read()

        if not ret:
            print('empty frame')
            break


        out_send.write(frame)
        print(frame)
        pass

    cap_send.release()
    out_send.release()


send()

However, when QGroundControl automatically detects the stream it shows me a green page with no frames changing the view.
I have verified that the frames are correctly recorded by the OpenCV.

gst-launch-1.0 -v udpsrc port=5600 ! application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=(string)H264,payload=(int)96 ! rtph264depay ! decodebin ! videoconvert ! autovideosink

But still, the result is the when I use the following gstreamer pipeline in the receiving end, yielding the following output.

Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:src: caps = application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)96
/GstPipeline:pipeline0/GstRtpH264Depay:rtph264depay0.GstPad:sink: caps = application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)96
/GstPipeline:pipeline0/GstRtpH264Depay:rtph264depay0.GstPad:src: caps = video/x-h264, stream-format=(string)avc, alignment=(string)au, codec_data=(buffer)01f40028ffe1001f67f40028919b280f0044fc4e02d40404050000030001000003003c8f18319601000668ebec448440, level=(string)4, profile=(string)high-4:4:4
/GstPipeline:pipeline0/GstDecodeBin:decodebin0.GstGhostPad:sink.GstProxyPad:proxypad0: caps = video/x-h264, stream-format=(string)avc, alignment=(string)au, codec_data=(buffer)01f40028ffe1001f67f40028919b280f0044fc4e02d40404050000030001000003003c8f18319601000668ebec448440, level=(string)4, profile=(string)high-4:4:4
/GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstTypeFindElement:typefind.GstPad:src: caps = video/x-h264, stream-format=(string)avc, alignment=(string)au, codec_data=(buffer)01f40028ffe1001f67f40028919b280f0044fc4e02d40404050000030001000003003c8f18319601000668ebec448440, level=(string)4, profile=(string)high-4:4:4
Redistribute latency...
/GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstH264Parse:h264parse0.GstPad:src: caps = video/x-h264, stream-format=(string)avc, alignment=(string)au, codec_data=(buffer)01f40028ffe1001f67f40028919b280f0044fc4e02d40404050000030001000003003c8f18319601000668ebec448440, level=(string)4, profile=(string)high-4:4:4, pixel-aspect-ratio=(fraction)1/1, width=(int)1920, height=(int)1080, framerate=(fraction)30/1, coded-picture-structure=(string)frame, chroma-format=(string)4:4:4, bit-depth-luma=(uint)8, bit-depth-chroma=(uint)8, colorimetry=(string)bt709, parsed=(boolean)true
Redistribute latency...
/GstPipeline:pipeline0/GstDecodeBin:decodebin0/avdec_h264:avdec_h264-0.GstPad:sink: caps = video/x-h264, stream-format=(string)avc, alignment=(string)au, codec_data=(buffer)01f40028ffe1001f67f40028919b280f0044fc4e02d40404050000030001000003003c8f18319601000668ebec448440, level=(string)4, profile=(string)high-4:4:4, pixel-aspect-ratio=(fraction)1/1, width=(int)1920, height=(int)1080, framerate=(fraction)30/1, coded-picture-structure=(string)frame, chroma-format=(string)4:4:4, bit-depth-luma=(uint)8, bit-depth-chroma=(uint)8, colorimetry=(string)bt709, parsed=(boolean)true
/GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstCapsFilter:capsfilter1.GstPad:src: caps = video/x-h264, stream-format=(string)avc, alignment=(string)au, codec_data=(buffer)01f40028ffe1001f67f40028919b280f0044fc4e02d40404050000030001000003003c8f18319601000668ebec448440, level=(string)4, profile=(string)high-4:4:4, pixel-aspect-ratio=(fraction)1/1, width=(int)1920, height=(int)1080, framerate=(fraction)30/1, coded-picture-structure=(string)frame, chroma-format=(string)4:4:4, bit-depth-luma=(uint)8, bit-depth-chroma=(uint)8, colorimetry=(string)bt709, parsed=(boolean)true
/GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstCapsFilter:capsfilter1.GstPad:sink: caps = video/x-h264, stream-format=(string)avc, alignment=(string)au, codec_data=(buffer)01f40028ffe1001f67f40028919b280f0044fc4e02d40404050000030001000003003c8f18319601000668ebec448440, level=(string)4, profile=(string)high-4:4:4, pixel-aspect-ratio=(fraction)1/1, width=(int)1920, height=(int)1080, framerate=(fraction)30/1, coded-picture-structure=(string)frame, chroma-format=(string)4:4:4, bit-depth-luma=(uint)8, bit-depth-chroma=(uint)8, colorimetry=(string)bt709, parsed=(boolean)true
/GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstH264Parse:h264parse0.GstPad:sink: caps = video/x-h264, stream-format=(string)avc, alignment=(string)au, codec_data=(buffer)01f40028ffe1001f67f40028919b280f0044fc4e02d40404050000030001000003003c8f18319601000668ebec448440, level=(string)4, profile=(string)high-4:4:4
Redistribute latency...
/GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstTypeFindElement:typefind.GstPad:sink: caps = video/x-h264, stream-format=(string)avc, alignment=(string)au, codec_data=(buffer)01f40028ffe1001f67f40028919b280f0044fc4e02d40404050000030001000003003c8f18319601000668ebec448440, level=(string)4, profile=(string)high-4:4:4
/GstPipeline:pipeline0/GstDecodeBin:decodebin0.GstGhostPad:sink: caps = video/x-h264, stream-format=(string)avc, alignment=(string)au, codec_data=(buffer)01f40028ffe1001f67f40028919b280f0044fc4e02d40404050000030001000003003c8f18319601000668ebec448440, level=(string)4, profile=(string)high-4:4:4
/GstPipeline:pipeline0/GstDecodeBin:decodebin0/avdec_h264:avdec_h264-0.GstPad:src: caps = video/x-raw, format=(string)Y444, width=(int)1920, height=(int)1080, interlace-mode=(string)progressive, pixel-aspect-ratio=(fraction)1/1, chroma-site=(string)mpeg2, colorimetry=(string)bt709, framerate=(fraction)30/1
/GstPipeline:pipeline0/GstVideoConvert:videoconvert0.GstPad:src: caps = video/x-raw, width=(int)1920, height=(int)1080, interlace-mode=(string)progressive, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction)30/1, format=(string)YV12, colorimetry=(string)bt709
/GstPipeline:pipeline0/GstAutoVideoSink:autovideosink0.GstGhostPad:sink.GstProxyPad:proxypad1: caps = video/x-raw, width=(int)1920, height=(int)1080, interlace-mode=(string)progressive, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction)30/1, format=(string)YV12, colorimetry=(string)bt709
/GstPipeline:pipeline0/GstAutoVideoSink:autovideosink0/GstXvImageSink:autovideosink0-actual-sink-xvimage.GstPad:sink: caps = video/x-raw, width=(int)1920, height=(int)1080, interlace-mode=(string)progressive, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction)30/1, format=(string)YV12, colorimetry=(string)bt709
/GstPipeline:pipeline0/GstAutoVideoSink:autovideosink0.GstGhostPad:sink: caps = video/x-raw, width=(int)1920, height=(int)1080, interlace-mode=(string)progressive, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction)30/1, format=(string)YV12, colorimetry=(string)bt709
/GstPipeline:pipeline0/GstVideoConvert:videoconvert0.GstPad:sink: caps = video/x-raw, format=(string)Y444, width=(int)1920, height=(int)1080, interlace-mode=(string)progressive, pixel-aspect-ratio=(fraction)1/1, chroma-site=(string)mpeg2, colorimetry=(string)bt709, framerate=(fraction)30/1
/GstPipeline:pipeline0/GstDecodeBin:decodebin0.GstDecodePad:src_0.GstProxyPad:proxypad2: caps = video/x-raw, format=(string)Y444, width=(int)1920, height=(int)1080, interlace-mode=(string)progressive, pixel-aspect-ratio=(fraction)1/1, chroma-site=(string)mpeg2, colorimetry=(string)bt709, framerate=(fraction)30/1
Redistribute latency...
Redistribute latency...
WARNING: from element /GstPipeline:pipeline0/GstAutoVideoSink:autovideosink0/GstXvImageSink:autovideosink0-actual-sink-xvimage: Pipeline construction is invalid, please add queues.
Additional debug info:
../gstreamer/subprojects/gstreamer/libs/gst/base/gstbasesink.c(1249): gst_base_sink_query_latency (): /GstPipeline:pipeline0/GstAutoVideoSink:autovideosink0/GstXvImageSink:autovideosink0-actual-sink-xvimage:
Not enough buffering available for  the processing deadline of 0:00:00.015000000, add enough queues to buffer  0:00:00.015000000 additional data. Shortening processing latency to 0:00:00.000000000.
WARNING: from element /GstPipeline:pipeline0/GstAutoVideoSink:autovideosink0/GstXvImageSink:autovideosink0-actual-sink-xvimage: Pipeline construction is invalid, please add queues.
Additional debug info:
../gstreamer/subprojects/gstreamer/libs/gst/base/gstbasesink.c(1249): gst_base_sink_query_latency (): /GstPipeline:pipeline0/GstAutoVideoSink:autovideosink0/GstXvImageSink:autovideosink0-actual-sink-xvimage:
Not enough buffering available for  the processing deadline of 0:00:00.015000000, add enough queues to buffer  0:00:00.015000000 additional data. Shortening processing latency to 0:00:00.000000000.
ERROR: from element /GstPipeline:pipeline0/GstAutoVideoSink:autovideosink0/GstXvImageSink:autovideosink0-actual-sink-xvimage: Output window was closed
Additional debug info:
../gstreamer/subprojects/gst-plugins-base/sys/xvimage/xvimagesink.c(586): gst_xv_image_sink_handle_xevents (): /GstPipeline:pipeline0/GstAutoVideoSink:autovideosink0/GstXvImageSink:autovideosink0-actual-sink-xvimage
Execution ended after 0:00:13.277670659
Setting pipeline to NULL ...
Freeing pipeline ...

The key warning message is “Pipeline construction is invalid, please add queues”. It appears that the h264 decoder is a bit slower than expected and frames are getting dropped. Try adding a queue between rtph264depay and decodebin: “rtph264depay ! queue ! decodebin”. You can also try adding a queue between decodebin and videoconvert.

2 Likes

Were you able to solve this? We are tying to do something similar.