Making UDP send latency more predictable (i.e. reducing jitter) (IDFGH-14588) #15345
Open
3 tasks done
Labels
Status: Opened
Issue is new
Answers checklist.
General issue report
Hi all,
my application is a low-latency UDP audio bridge using two ESP32-C5 sample Devkits, but I suppose the question can be answered with ESP32-C6 knowledge. I'm using the 5 GHz band with 11ax with the receiver taking the role as AP and the sender is the only station, with nothing in between and no other device in the same SSID. Wifi encryption is WPA3-SAE. The latency requirement is in the range of 10-12 ms. Basically, I got this to work but there are still occasional pops caused by buffer overruns. The reason turned out to be on the sending side. Datagrams are created and sent (using
sendto()
) every 1.36 ms triggered by the i2son_sent
callback (I do no usei2s_channel_read()
ori2s_channel_write()
- they are just too laggy). The UDP payload size is 1452 bytes so that no IP fragmenting takes place (and it is deactivated anyway). (For explanation, each datagram contains 60 samples with 8 slots with 3 byte samples each, summing up to 1440 bytes, plus a 4 byte XOR checksum, a 4 byte packet sequence number, plus a 4 byte data field for other stuff. The sample rate is 44.1 kHz. Each second, 735 datagrams are sent.)Most of the time, as I can see on the receiver and using wireshark, UDP packets are sent in regular intervals with an acceptable jitter (say, 1360 +/- 500 µs). However, at random intervals, datagrams appear to pile up for 10..20 ms or more before actually being sent, and then the piled up datagrams are sent in a fast burst, like after 12000 µs, 150, 220, 180, 150, ... about 10 or so packets.
On the receiver, I can see that in fact not a single packet is lost, and all packets arrive in sequence. My sequence-number based buffering can cope with arrival delays up to 6 datagrams. But at these occasions, packets are delayed by more than 10 or 15 ms, and this at first dries out the buffer and then overruns it. When the incident is over, everything is back to normal within two more packets.
So the question is, how do I prevent UDP packets from piling up on the sender, or how can I force packets to be sent immediately.
on_sent
andon_recv
callbacks but they are short and don't take longer than a few µs.esp_wifi_internal_tx()
but that's related to sending raw ieee80211 data.sendto()
torecvfrom()
is about 540 +/- 200 µs including the (rare) outliers.For now, I ran out of other options. Any help is appreciated!
The text was updated successfully, but these errors were encountered: