Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GStreamer element timestamping issues #43

Open
samhurst opened this issue Feb 15, 2022 · 16 comments
Open

GStreamer element timestamping issues #43

samhurst opened this issue Feb 15, 2022 · 16 comments

Comments

@samhurst
Copy link

Hello,

I’ve been trying to do some testing recently with SCReAM to understand how it performs with various levels of network quality and performance. I’m using Gstreamer to encode and decode some video streams, and then attempting to use your gstscream elements to do this all in-line, but I’m having some problems. I’m attempting to apply network conditions using the Linux tc and netem tools to apply caps to network throughput, adding jitter, random packet loss and increasing latency.

The primary issue that I’m having is that the scream elements cause timestamping problems on my platform. This manifests itself as lots of dropped frames at the receiver. This is happening even in my control tests, where I’m not applying any conditions to my test network. Using something like iperf3 in UDP mode, I can send and receive ~540Mbit/s of traffic between the sender and receiver but I’m configuring the screamtx maxrate as 10Mbit/s, so I don’t think I should be encountering any on-the-wire problems.

The pipelines I’m using are quite similar to what you’re using in the sender.sh and receiver.sh scripts available in gstscream/scripts/, except I’m adding caps to force the videotestsrc to output 720p video:

Sender:
gst-launch-1.0 -e videotestsrc is-live=true ! "video/x-raw,format=I420,width=1280,height=720,framerate=25/1" ! x264enc name=video threads=4 speed-preset=ultrafast tune=fastdecode+zerolatency bitrate=8000 ! tee name=t t. ! queue ! rtph264pay ssrc=1 config-interval=-1 ! queue max-size-buffers=2 max-size-bytes=0 max-size-time=0 ! screamtx name=screamtx params=" -forceidr -ect 1 -initrate 2500 -minrate 500 -maxrate 10000 " ! udpsink host=192.168.56.103 port=5000 sync=false t. ! queue ! fakesink silent=false sync=false rtpbin name=r udpsrc port=5001 address=192.168.56.102 ! queue ! screamtx.rtcp_sink screamtx.rtcp_src ! r.recv_rtcp_sink_0

Receiver:
gst-launch-1.0 -e rtpbin name=rtpbin udpsrc port=5000 ! screamrx name=screamrx screamrx.src ! application/x-rtp,media=video,encoding-name=H264,clock-rate=90000,payload=96 ! rtpbin.recv_rtp_sink_0 rtpbin. ! rtph264depay ! h264parse ! avdec_h264 name=videodecoder ! queue max-size-buffers=1 max-size-bytes=0 max-size-time=0 ! glupload ! glcolorconvert ! fpsdisplaysink video-sink=\"glimagesinkelement\" rtpbin.send_rtcp_src_0 ! funnel name=f ! udpsink host=192.168.56.102 port=5001 sync=false async=false screamrx.rtcp_src ! f.

I get lots of the following output on the receiver:
0:00:44.559898508 2231 0x7fdaec01d800 WARN videodecoder gstvideodecoder.c:3298:gst_video_decoder_clip_and_push_buf:<videodecoder> Dropping frame due to QoS. start:0:00:44.194611002 deadline:0:00:44.194611002 earliest_time:0:00:44.205054014 0:00:47.037605415 2231 0x7fdaec01d800 WARN videodecoder gstvideodecoder.c:3298:gst_video_decoder_clip_and_push_buf:<videodecoder> Dropping frame due to QoS. start:0:00:46.674504689 deadline:0:00:46.674504689 earliest_time:0:00:46.689336031 0:00:47.066500703 2231 0x7fdaec01d800 WARN videodecoder gstvideodecoder.c:3298:gst_video_decoder_clip_and_push_buf:<videodecoder> Dropping frame due to QoS. start:0:00:46.714503414 deadline:0:00:46.714503414 earliest_time:0:00:46.759894609

If I remove the screamtx and screamrx elements, I don't see any of this behaviour. Using the Gst-Shark interlatency tool, I can see that the amount of latency introduced on buffers in the screamrx element is definitely not consistent, occasionally spiking up to 800ms over an average of 33ms. My current working assumption is that this is what's causing my decode issues.

I have taken your code and compiled it against both GStreamer 1.18.3 and 1.20, but I seem to get similar results in both cases. I’ve also tried running it both in virtual machines and also on bare metal. Do you have any ideas of what I’m doing wrong?

I’m using Ubuntu 21.10 and Rust 1.56.1 on the host system(s).

@jacobt21
Copy link
Collaborator

Hi Sam,
At least for sender, please use scream_sender, for example:
export SENDPIPELINE="videotestsrc is-live=true ! video/xraw,format=I420,width=1280,height=720,framerate=25/1 ! x264enc name=video threads=4 speed-preset=ultrafast tune=fastdecode+zerolatency bitrate=8000 ! tee name=t t. ! queue ! rtph264pay ssrc=1 config-interval=-1 ! queue max-size-buffers=2 max-size-bytes=0 max-size-time=0 ! screamtx name=screamtx params=" -forceidr -ect 1 -initrate 2500 -minrate 500 -maxrate 10000 " ! udpsink host=192.168.1.10 port=5000 sync=false t. ! queue ! fakesink silent=false sync=false rtpbin name=r udpsrc port=5001 address=192.168.1.11 ! queue ! screamtx.rtcp_sink screamtx.rtcp_src ! r.recv_rtcp_sink_0 "
../target/debug/scream_sender
You need to use scream_sender to set correctly encoder bitrate.
Are you using WIFI between sender and receiver?
I'm using gst-launch-1.0 version 1.16.2
GStreamer 1.16.2
I can't reproduce the warning message you see. Only when I move renderer window, I see a few messages.
Can you re-run without noisy debugging(tracing=7) and collect outputs on receive and sender side + sender_scream_stats.csv ?
Regards,

  • Jacob

@jacobt21
Copy link
Collaborator

Hi,
I was able to reproduce the issue. I've fixed it by removing debugging prints. Please see attached patch. I'll pushed the changes in next day or two
drop_qos_diff.txt
.

@jacobt21
Copy link
Collaborator

Pushed the changes. Please let us know if you still see the issue.

@samhurst
Copy link
Author

Hi Jacob,

Thanks for looking into this. I've taken your changes and re-tested, and anecdotally it seems to be an improvement, but I'm still seeing a few timestamping issues on the receiver. To answer your other questions:

I have re-run my testing using the scream_sender application and the sender pipeline you gave above.

I am using gigabit ethernet between the sender and receiver. I have two separate testing setups that I've been using, one using VMs and the other with physical machines. In the case of my VM testing, these are using a host-only network to communicate between each other, and my physical machine testing is done with an ethernet cable.

I might try and get an older version of GStreamer built and test against that, as I'm using a more modern version of GStreamer at present.

You should find attached here the output of both the sender and receiver, as well as the sender stats file.

-Sam

@jacobt21
Copy link
Collaborator

jacobt21 commented Feb 21, 2022 via email

@samhurst
Copy link
Author

Hi Jacob,

Yes, when I tested without scream (just rtpbin) I don't see any timestamping issues on the receiver. As far as I know, the machines aren't running out of available resources as the load averages stay fairly sensible and well below the number of available CPU threads. Also, watching the processes in top doesn't show them ever using an exorbitant amount of CPU. I have tried dropping the bitrates (x264 bitrate=2000, and screamtx settings of -initrate 2000 -minrate 500 -maxrate 4000) as well as the video size (800x480) to make the job a bit easier but it doesn't seem to help, I still get timestamping errors.

However, adding -nosummary to the screamtx params definitely seems to have helped when I turn down the bitrates.

  • Sam

@samhurst
Copy link
Author

Hi Jacob,

I ended up trying an older version of GStreamer (1.16.3, built from source), and the timestamping problem seems to have gone away completely. I've run several test runs this afternoon and not a peep out of the receiver about any timestamping issues.

However, instead I'm getting occasional messages on the sender end about the queuing delay being too large, and that it's discarding a large number of packets:

summary 91.3 Transmit rate = 10170kbps, PLR = 0.00%( 0.00%), RTT = 0.003s, Queue delay = 0.006s encoder_rate 10329344bps rtpQueueDelay 0.233551 too large 2 92.0507 RTP queue 29 packets discarded for SSRC 1 hiSeqTx 49665 hiSeqAckendl 49661 seqNrOfNextRtp 49667 seqNrOfLastRtp 49695 diff 30 rate 0 ScreamSenderGetTargetRate 622 in_ssrc 1 imp.rs: force_idr rc true enabled 1

Is there some specific tuning that needs to be performed with these? Or is this just an expected thing with the SCReAM algorithm? I can drop this onto another bug if you like.

Best regards,
-Sam

@jacobt21
Copy link
Collaborator

Hi Sam,
I've pushed a script to increase kernel buffers.
Please try it

@jacobt21
Copy link
Collaborator

BTW, "and the timestamping problem seems to have gone away completely. "
Did you have export GST_DEBUG=videodecoder:2

@samhurst
Copy link
Author

Hi Jacob,

I've tried increasing the kernel buffers but that hasn't helped. I have a little utility I wrote a long time ago which analyses socket buffer residency, and the transmit buffer never really seems to grow beyond about 16 kBytes. And yes, my testing was performed with GST_DEBUG=2, so that would include ERROR and WARN debug output from the decoder.

Best regards,
-Sam

@jacobt21
Copy link
Collaborator

jacobt21 commented Feb 23, 2022 via email

@jacobt21
Copy link
Collaborator

jacobt21 commented Feb 23, 2022 via email

@samhurst
Copy link
Author

Hi Jacob,

I don't get any complaints about clock-rate as my receiving pipeline includes a caps filter which explicitly defines the clockrate.

After some additional testing I've come to the conclusion that the "rtpQueueDelay too large" messages are only prevalent on my VM testing environment, but not if I run between two bare metal machines, so I think this is environmental on my end so I'll try and figure that out when I can.

-Sam

@jacobt21
Copy link
Collaborator

jacobt21 commented Feb 25, 2022 via email

@samhurst
Copy link
Author

Hi Jacob,

My sending pipeline, as used with the scream_sender application, is as follows:

export SENDPIPELINE="videotestsrc is-live=true ! video/x-raw,format=I420,width=1280,height=720,framerate=25/1 ! x264enc name=video threads=4 speed-preset=ultrafast tune=fastdecode+zerolatency bitrate=8000 ! tee name=t t. ! queue ! rtph264pay ssrc=1 config-interval=-1 ! queue max-size-buffers=2 max-size-bytes=0 max-size-time=0 ! screamtx name=screamtx params=\" -forceidr -ect 1 -initrate 2500 -minrate 500 -maxrate 10000 \" ! udpsink host=10.0.0.194 port=5000 sync=false t. ! queue ! fakesink silent=false sync=false rtpbin name=r udpsrc port=5001 address=10.0.0.168 ! queue ! screamtx.rtcp_sink screamtx.rtcp_src ! r.recv_rtcp_sink_0 "

My receiving pipeline, with a video sink:

gst-launch-1.0 -e rtpbin name=rtpbin udpsrc port=5000 ! screamrx name=screamrx screamrx.src ! application/x-rtp,media=video,encoding-name=H264,clock-rate=90000,payload=96 ! rtpbin.recv_rtp_sink_0 rtpbin. ! rtph264depay ! h264parse ! avdec_h264 name=videodecoder ! queue max-size-buffers=1 max-size-bytes=0 max-size-time=0 ! glupload ! glcolorconvert ! fpsdisplaysink video-sink=\"glimagesinkelement\" rtpbin.send_rtcp_src_0 ! funnel name=f ! udpsink host=10.0.0.168 port=5001 sync=false async=false screamrx.rtcp_src ! f.

And with avdec_h264 going directly into fakesink:

gst-launch-1.0 -e rtpbin name=rtpbin udpsrc port=5000 ! screamrx name=screamrx screamrx.src ! application/x-rtp,media=video,encoding-name=H264,clock-rate=90000,payload=96 ! rtpbin.recv_rtp_sink_0 rtpbin. ! rtph264depay ! h264parse ! avdec_h264 name=videodecoder ! queue max-size-buffers=1 max-size-bytes=0 max-size-time=0 ! fakesink rtpbin.send_rtcp_src_0 ! funnel name=f ! udpsink host=10.0.0.168 port=5001 sync=false async=false screamrx.rtcp_src ! f.

This works fine between two actual computers, using GStreamer 1.16.3 and commit dae29db9 of this library. Only when running between two VMs on the same hardware do I see any issues, and it is regardless of whether I have a video display sink in the receiver pipeline. The VMs are running the same OS as the host (Ubuntu 21.10), and the VMs are hosted by VirtualBox 6.1.32. The encoding VM is allocated 4 threads (and sees a load average of ~1.6) and the decoding VM is allocated 2 threads (and sees a load average of ~0.7) of the host Intel i7-1185G7 CPU.

-Sam

@jacobt21
Copy link
Collaborator

jacobt21 commented Feb 28, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants