TSBPD waits for 10 ms or next ACK if CRcvBuffer has no acknowledged packet #553
Labels
[core]
Area: Changes in SRT library core
Priority: Low
Type: Bug
Indicates an unexpected problem or unintended behavior
Milestone
The issue is related to TSBP for the receiving thread.
At some point under certain conditions the receiving may get delayed for up tp 10 ms (usually less) on top of the existing delay of reading a packet. When this happens on the receiving side, the sender drops some packets due to the increased delay of the receiver. This happens when the data from the receiver buffer is read out faster than it is being actually acknowledged (while the data itself may have already been received). Then there will be a timeout for reading until the next number of packets is acknowledged. By acknowledgement I mean sending actual ACK message, because now this is what triggers the receiver buffer to allow you to read those data from it.
Let's have a look at
receiveMessage(...)
function. If there are no packets in the receiver buffer to read, it will wait for 1s (default) on them_RecvDataCond
. In TSBPD mode theisRcvDataReady(...)
function returns false (no packet ready to be read) if there is no ACKnowledged packets in the receiver buffer or the TSBPD time of the next packet is less than current time. Seem_iLastAckPos
of theCRcvBuffer
.So, the
CRcvBuffer
will tell there is no packet ready to be read in case there are packets in it, but they are not ACKnowledged.Reading packets from the receive buffer (click to expand)
The acknowledgement of the packets in the
CRcvBuffer
happens when an actual ACK packet is sent (seeCUDT::sendCtrl(...)
callingm_pRcvBuffer->ackData(acksize);
).The acknowledment decision is made in
CUDT::checkTimers()
based on time (currtime_tk > m_ullNextACKTime_tk
) or packet count (m_iPktCount >= m_Smoother->ACKInterval()
- default 0).So by default there is only time interval, that is 10 ms by default.
The second way to acknowledge the packets is with quick ACK on every 64 packets if (refer to
static const int SELF_CLOCK_INTERVAL = 64;
). But it does not force to ACK data in the receiver buffer.The following code shows the ACK sending function. Note the place where
m_pRcvBuffer->ackData(acksize);
is called and the condition is signaledpthread_cond_signal(&m_RcvTsbPdCond);
.Sending ACK (click to expand)
Now let's check the TSBPD thread. It asks the
m_pRcvBuffer
for the next available packets. Intersting thing will happen, if there are packets in the buffer, but they are not acknowledged.In this case the TSBPD thread starts waiting for
m_RcvTsbPdCond
, although there might be a packet in the receiver buffer, and we may retrieve its time. Instead we will effectively wait for the next ACK to happen, that might happen in up to 10 ms.Sending ACK (click to expand)
This situation, when it happens, increases the latency without any reason. Furthermore, increasing the latency increases the number of packets stored in the receiver buffer. At some point this value may reach the 8000 limit.
The situation was reproduced when sending 34 Mbps and above from Windows and receiving on CentOS with the default maxbw value.
Reproduction steps (click to expand)
The tsp tool is TSDuck
File can be any.
So the command builds an internal pipeline with file reader (
-I file --infinite "Eden_HD.ts"
), bitrate regulator (-P regulate --bitrate 34000000
) and output component (-O ip localhost:4900
)Windows 10 sender:
CentOS 7 receiver:
After some time the sender starts to report SND_DROPPED. That was due to sender now acnowledging the packets and increasing the delay.
The text was updated successfully, but these errors were encountered: