gstreamermpeg2-ts

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,

Enter image description here

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:

Enter image description here


Solution

  • 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).