Inconsistency in guidelines for Receiver buffer size
Hi,
I am trying to wrap my head around the SRT parameters for streaming at high bitrates, maxbw, rcvbuf, fc and so forth. I read the most referenced issues, as #642, #703, #409 and others, as well as the Configuration Guidelines and the Socket options page.
I have some doubts but if necessary I will make other issues. For now I want to address two simple questions.
First, in Configuration Guidelines, under "Calculating Target Size in Packets", there are the following sentences: https://github.com/Haivision/srt/blob/952f9495246abc201bac55b8f9ad7409c0572423/docs/API/configuration-guidelines.md?plain=1#L55-L57 And this makes sense to me as we divide the stream bitrate by 8 to have bytes/s, then we multiply by the interval of time that we are interested in, that is RTT + latency, and finally divide by the payload size, to get the number of packets.
However, in the section "Summing Up" we find this function: https://github.com/Haivision/srt/blob/952f9495246abc201bac55b8f9ad7409c0572423/docs/API/configuration-guidelines.md?plain=1#L96-L103 Here the code is almost the same, except for the division by two applied to the RTT value. I think this is an error and should be corrected.
As for the calculation of FC in Socket Options I see this calculation for the suggested FC value:
FC = (bps / 8) × (RTTsec + latency_sec) / (MSS - 44)
which is identical to the first sample I reported above.
So, in conclusion is it correct to state that the formulas to calculate the recommended rcvbuf size and fc size are the following?
RCVBUF = (bps / 8) × (RTTsec / 2 + latency_sec) / (MSS - 44)
FC = (bps / 8) × (RTTsec + latency_sec) / (MSS - 44)
The second problem I have is that in the comment from @maxsharabayko in https://github.com/Haivision/srt/issues/703#issuecomment-495570496, I see that the bandwidth is marked ad being the link bandwidth. However every other reference I found is talking about the payload bandwidth. Is referencing the link bandwidth correct or it should be written payload bandwidth?
Thank you.
I made a python script to calculate the recommended dimensions for maxbw, rcvbuf and fc given a certain stream bandwidth, latency and rtt.
import math
UDP_HEADER_SIZE = 8
IPV4_HEADER_SIZE = 20
SRT_HEADER_SIZE = 16
MSS_SIZE = 1500
UDP_IPV4_HEADER_SIZE = UDP_HEADER_SIZE + IPV4_HEADER_SIZE # 28
SRT_UDP_IPV4_HEADER_SIZE = UDP_IPV4_HEADER_SIZE + SRT_HEADER_SIZE # 44
def compute_target_rcvbuf_size(rtt_ms, bandwidth_bps, latency_ms):
# Rcvbuf bytes value, based on rtt, bandwidth and latency
rcvbuf_bytes_value = (bandwidth_bps / 8) * ((latency_ms + rtt_ms / 2) / 1000)
# Divide bytes value for (1500 - 44) = 1456 to get number of packets
rcvbuf_packets_value = rcvbuf_bytes_value / (MSS_SIZE - SRT_UDP_IPV4_HEADER_SIZE)
# Multiply for 1500 - 28 = 1472
# (because internally the value set in SRTO_RCVBUF is divided by this number when setting the option to get packets)
target_rcvbuf_value = rcvbuf_packets_value * (MSS_SIZE - UDP_IPV4_HEADER_SIZE)
return target_rcvbuf_value
def compute_target_fc_size(rtt_ms, bandwidth_bps, latency_ms):
## FC
# fc bytes value, based on rtt, bandwidth and latency
fc_bytes_value = (bandwidth_bps / 8) * ((latency_ms + rtt_ms) / 1000)
# fc packets value
target_fc_value = fc_bytes_value / (MSS_SIZE - SRT_UDP_IPV4_HEADER_SIZE) # 1500 - 44 = 1456
return target_fc_value
rtt_ms = 200 # ms
bandwidth_bps = 419430400 # 400 Mbps
latency_ms = 120 # ms
target_fc_value = compute_target_fc_size(rtt_ms, bandwidth_bps, latency_ms)
target_rcvbuf_value = compute_target_rcvbuf_size(rtt_ms, bandwidth_bps, latency_ms)
target_maxbw_value = 2 * bandwidth_bps
target_fc_value, target_rcvbuf_value, target_maxbw_value = (
math.ceil(target_fc_value),
math.ceil(target_rcvbuf_value),
math.ceil(target_maxbw_value),
)
lines = [
("FC", f"{target_fc_value} packets / {target_fc_value * (MSS_SIZE - SRT_UDP_IPV4_HEADER_SIZE) / 1024 / 1024:.2f} MB", f"(default 25600 packets / {25600 * (MSS_SIZE - UDP_IPV4_HEADER_SIZE) / 1024 / 1024 * 8:.2f} MB)"),
("RCVBUF", f"{target_rcvbuf_value / 1024 / 1024:.2f} MB / {math.ceil(target_rcvbuf_value / (MSS_SIZE - UDP_IPV4_HEADER_SIZE))} packets", "(default 8192 packets / 11.5 MB)"),
("MAXBW", f"{target_maxbw_value} / {target_maxbw_value / 1024 / 1024:.2f} Mbps", "(default 1 Gbps)"),
]
for l in lines:
print("\t".join(l))
print()
print(f"fc={target_fc_value}&rcvbuf={target_rcvbuf_value}&maxbw={target_maxbw_value}")
When using the parameters hardcoded in the script, that is rtt = 200 ms, bandwidth = 400 Mbps, latency = 120 ms, the resulting numbers are the following:
| Param | Calculated value | Default value |
|---|---|---|
| FC | 11523 packets / 16.00 MB | (default 25600 packets / 287.50 MB) |
| RCVBUF | 11.12 MB / 7922 packets | (default 8192 packets / 11.5 MB) |
| MAXBW | 838860800 / 800.00 Mbps | (default 1 Gbps) |