Force key-frame with h264 and udpsrc in Gstreamer? - gstreamer

I'm trying to transmit via UDP a h264 encoded video using Gstreamer.
It works fine but only when I start the client before the server. I think it may be something related to key-frame, Its possible that the client is waiting for this mark, and when started at first the server it only sends one.
Here I attach server Gstreamer command, is there any parameter that indicate the number of frames between two keyframes?
gst-launch-1.0 v4l2src device=/dev/video0 ! "video/x-raw,width=1920,height=1080,format=(string)YV12,framerate=30/1" ! imxipuvideotransform ! "video/x-raw,width=1280,height=720,format=(string)I420,framerate=30/1" ! imxvpuenc_h264 idr-interval=0 ! rtph264pay pt=96 ! udpsink host=MULTICAST multicast-iface=eth0 force-ipv4=true port=5010 sync=false
Thanks a lot for the answers!

Related

Creating a low latency RTP MPEGTS H.264 pipeline with GStreamer

I'm writing a Qt 5.15 application that should play an RTP / MPETGS / H.264 video on Linux UbuntuĀ 20.04 (Focal Fossa).
I'm running GStreamer 1.16.3.
Since I'm new to GStreamer, I made everything step by step starting from official tutorials... at this moment I'm able to play an RTP / H.264 stream almost realtime.
Now the last step (adding MPEGTS support) seems to be the hardest.
My source to make a test is an MP4 H.264 QuickTime file, and I stream it over the network through gst-launch.
The working RTP / H.264 output pipeline is the following shell command:
gst-launch-1.0 filesrc location=file.mp4 ! qtdemux ! h264parse ! avdec_h264 ! x264enc tune=zerolatency ! rtph264pay ! udpsink host=127.0.0.1 port=5000;
To test the input pipeline without messing up the Qt/C++ code, I use another shell command like this:
gst-launch-1.0 -v udpsrc port=5000 ! "application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)96" ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! autovideosink;
AFAIK, if the shell input pipeline works, it will work in my C++ code (of course elements after avdec_h264 depends on my programming/running environment, but if someone needs it I can share without problem).
To add mpegts support, I tried with these lines (the last of a long sequence of trials):
OUTPUT:
gst-launch-1.0 filesrc location=file.mp4 ! qtdemux ! h264parse ! avdec_h264 ! x264enc tune=zerolatency ! mpegtsmux ! rtpmp2tpay ! udpsink host=127.0.0.1 port=5000;
INPUT:
gst-launch-1.0 -v udpsrc port=5000 caps="application/x-rtp" ! rtpmp2tdepay ! tsparse ! tsdemux ! h264parse ! avdec_h264 ! videoconvert ! autovideosink;
It works, but the video seems to stumble/bounce while playing.
What I'm missing?
As a side question, I would like to avoid to re-encode the video of the source prior sending it trough RTP. I would like to remove such elements from the output pipeline:
avdec_h264 ! x264enc tune=zerolatency
I tried, but the result goes from nothing to this,
if I add the config-interval=-1 parameter to h264parse.
Please note that I would like to keep the latency as low as possible.
--- UPDATE ---
I tried putting a queue element between rtpmp2tdepay and tsparse and this makes video playing fluid, but latency grows to seconds while playing RTP / H.264, only it's nearly real-time.
Since MPEGTS is only a transport protocol, why should it add more delay than actual encoding?
Is there a way to shorten this delay? No matter if it changes the whole pipeline as long as protocols and encoding are kept the same.
BTW, I tried tuning max-size-buffers size, but using values under 150 will cause play to stumble.
--- UPDATE ---
If I use VLC to create the output stream using the same file, things get even worse:
*:sout=#rtp{dst=127.0.0.1,port=5000,mux=ts} :no-sout-all :sout-keep*
It is the same stumbling and scrambled video without a chance to fix it:
I found a partial fix to the latency problem and compatibility with VLC:
! autovideosink sync=false
Disabling the clock synchronisation allows to shorten delays, and also VLC output streaming is now collected correctly by GStreamer.
This also makes the queue element unnecessary (not in the general use case probably), and AFAIK also tsparse is redundant.
Anyway, I still need to understand why I need to re-encode H.264 video (in the output pipeline).

how to enable transport wide congestion control in gstreamer

I am developing an application that streams h264 video with gstreamer using RTP and RTCP in c++. The video stream is successfully received and both the sender and receiver is generating SR/RR RTCP packets. My next goal was to utilize twcc (transport wide congestion control) for bandwidth management, which should be supported in gstreamer since version 1.18. I can not however figure out to enable this feature. My pipeline looks similar to this:
appsrc ! videoconvert ! h264enc ! rtph264pay ! rtpbin ! udpsink -> udpsrc ! rtpbin ! rtph264depay ! avdec_h264 ! videoconvert ! autovideosink
The rtpbin also has the appropriate RTCP pad links with its own udpsrc and udpsink on both sender and receiver side (not shown here).
As i understand twcc i need to set the appropriate rtp header extension, but i cannot figure out how to do that using gstreamer. I am also unsure how to make the recevier side send back the correct rtcp packets so that i can read the twcc-stats on the sender side.
Does anyone have an example on how i would make my gstreamer pipeline start using twcc?

Cannot capture stream when written from another thread [OpenCV GStreamer C++]

I have a program that captures video from USB camera, process and stream to rtsp udp. I am using OpenCV with Gstreamer.
When I use the main thread to write out the frames, I can capture it with no problem using gst-launch.
However, when I create another thread to do the writing out the frame, nothing happens with gst-launch. I know the other thread is running because I am able to "imshow" the frames in that thread. Also, I am sure that the writer is open since I checked it before writing.
Writer pipeline : appsrc ! videoconvert ! x264enc ! rtph264pay ! udpsink host=127.0.0.1 port=5015
Receiver: gst-launch-1.0 udpsrc port=5015 ! queue ! "application/x-rtp, media=(string)video, encoding-name=(string)H264, framerate=30/1" ! rtph264depay ! decodebin ! videoconvert ! autovideosink
This is already solved and is not related to multi-threading at all. It was in the composition of the pipeline. "port" keyword was not added in the ostream.

Network streaming GStreamer C++

I'm using GStreamer to take a webcam feed, edit it through OpenCV, and stream it to a network. The pipeline I'm using isn't throwing any exceptions or errors, but it also isn't streaming. I haven't the faintest idea what could be wrong.
Here's the sample of code.
res = sprintf(pipeline2_str, "appsrc name=\"%s\" ! ffmpegcolorspace ! x264enc ! rtph264pay ! queue ! udpsink port=9001", app_src_name);
appsrc name is coming back from OpenCV.

transfer video without compressiing

I am using gstreamer for streaming a video. The server side is
gst-launch v4l2src ! jpegenc ! udpsink host=<ip> port=5000
and for the client side
gst-launch udpsrc port=5000 ! jpegdec ! xvimagesink.
This one is working pretty good.
My requirement is : I would like to transfer the video without using a compression technique like jpegenc. would like to connect v4l2src directly to udpsink. when I tried such a connection, errors were not generated. but video is not getting transfered.
udp is not a lossless protocol. Chances are your video buffers are going to be too big to handle properly.
Why not try with tcpserversink and tcpclientsrc instead ?