I’ve developed an MPEG-ts Streamer. It reads the packets from a file and sends them at the right pace to the receiver.
Now everything works fine excluding that I have some lags quite often. I have searched for every possible error in my code. I have optimized my program quite a bit performance wise.
Now I keep a log with the time it takes the sendto() function to send the packet and I also log the difference between when the packet should have been sent and when it is sent.
I noticed that every time the packets are a lot later than average, the time it took the sendto() to send the previous packet is much higher than normal too.
This indicates me that it is the sendto() that is causing those lags every time it somehow takes longer to send a packet. I am using UDP sockets.
Am I maybe doing something wrong with the sockets? Could it be possible that the socket buffer is full and that it actually takes longer to send the packet? Or am I missing something? Is there maybe a way to accelerate the socket or to make it not fill it’s buffer completely before sending?
As this is meant to stream video I am quite depending on the performance, mostly for HD where the lags happen more often as the amount of packets is much higher.
There are only two reasons for
sendto()to block:Check the size of your outgoing buffer:
Some linux systems default to absurdly small send buffers (only a few kilobytes), so you may need to set it to something larger.
If buffer is larger and
sendto()is briefly blocking anyway (how long exactly?) then that’s probably just the cost of doing business. Even on a LAN, and certainly on a WAN, latency is going to vary a lot.Update
To increase the system limit on UDP buffer sizes:
You can make this permanent by adding the following lines to
/etc/sysctl.conf:To take advantage of this within your application, you need to use
setsockopt():Repeat the same thing for
SO_RCVBUF. The loop is important because many systems silently enforce a maximum which is less than the max you set withsysctland whensetsockopt()fails, it leaves the previous value untouched. So you have to try many different values until you get one that sticks. Its also important to not test for(gotsize == trysize)because on some systems the result which is set is not actually the same as the one you requested.