Skip to content

Commit

Permalink
Apply suggestions from code review
Browse files Browse the repository at this point in the history
(completed)

Co-authored-by: stevomatthews <smatthews@haivision.com>
  • Loading branch information
ethouris and stevomatthews committed Feb 15, 2024
1 parent 25e2512 commit 31eeef6
Showing 1 changed file with 60 additions and 68 deletions.
128 changes: 60 additions & 68 deletions docs/features/latency.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,37 +41,35 @@ that packet's declared scheduling time interval.
SRT's approach to packet arrival time
=====================================

SRT provides two socket options `SRTO_PEERLATENCY` and `SRTO_RCVLATENCY`,
where the "latency" name was used for convenience (also for a common option
`SRTO_LATENCY`), but it doesn't mean that it will define the true time
distance between the `srt_sendmsg2` and `srt_recvmsg2` calls for the same
packet. This is only an extra delay added at the receiver side towards
SRT provides two socket options `SRTO_PEERLATENCY` and `SRTO_RCVLATENCY`.
While they have "latency" in their names, they do *not* define the true time
interval between the `srt_sendmsg2` and `srt_recvmsg2` calls for the same
packet. They are only used to add an extra delay (at the receiver side) to
the time when the packet "should" arrive (ETS). This extra delay is used to
compensate two things:
compensate for two things:

* The extra network delay, that is, if the packet arrived later than it
"should have arrived"
* an extra network delay (that is, if the packet arrived later than it
"should have arrived"), or

* The packet retransmission, regarding that there might be a need to be
requested at least twice
* a packet retransmission.

Note that the values included in these formulas are values that are
actually present, but many of them are not controllable and many are
not even measurable. In many cases there are measured values that are
sums of other values, but ingredients can't be extracted. Values that
we get at the receiver side are actually two:
Note that many of the values included in these formulas are not controllable and
some cannot be measured directly. In many cases there are measured values
that are sums of other values, but the component values can't be extracted.

* ATS: actual arrival time. It's simply the time when the UDP packet
There are two values that we can obtain at the receiver side:

* ATS: actual arrival time, which is the time when the UDP packet
has been extracted through the `recvmsg` system call.

* TS: time recorded in the packet header, set on the sender side and extracted
from the packet at the receiver side

Note that the timestamp in the packet's header is 32-bit, which gives
it more-less 2.5 minutes to roll over. Therefore there is the timestamp
rollover tracked and a segment increase is done in order to keep an
it more or less 2.5 minutes to roll over. Therefore timestamp
rollover is tracked and a segment increase is performed in order to keep an
eye on the overall actual time. For the needs of the formula definitions
it will be stated that TS is the true difference between the connection
it must be stated that TS is the true difference between the connection
start time and the time when the sending time has been declared when
the sender application is calling any of the `srt_send*` functions
(see [`srt_sendmsg2`](../API/API-functions.md#srt_sendmsg2) for details).
Expand All @@ -82,28 +80,28 @@ SRT latency components

To understand the latency components we need also other definitions:

* ETS: expected arrival time. This is the time of the packet when it
"should" arrive according to its TS
* **ETS** (Expected Time Stamp): The packet's expected arrival time, when it
"should" arrive according to its timestamp

* PTS: packet's play time. It's the time when SRT gives up the packet
* **PTS** (Presentation Time Stamp): The packet's play time, when SRT gives the packet
to the `srt_recvmsg2` call (that is, it sets up the IN flag in epoll
and resumes the blocked function call, if it was in blocking mode).

* STS: the time declared as the sending time when the packet was
* **STS** (Sender Time Stamp): The time when the packet was
scheduled for sending at the sender side (if you don't use the
declared time, by default it's the monotonic time taken when this
function was called), which is represented by TS.
declared time, by default it's the monotonic time used when this
function is called).

* RTS: the same as STS, but calculated at the receiver side. The
* **RTS** (Receiver Time Stamp): The same as STS, but calculated at the receiver side. The
only way to extract it is by using some initial statements.

The "true latency" for a particular packet in SRT can be simply defined as:

* `TD = PTS - STS`

Note that this is a stable definition (independent on the packet),
Note that this is a stable definition (independent of the packet),
but this value is not really controllable. So let's define the PTS
for the packet `x`:
for a packet `x`:

* `PTS[x] = ETS[x] + LATENCY + DRIFT`

Expand All @@ -116,12 +114,12 @@ These components undergo the following formula:

* `ETS[x] = start_time + TS[x]`

Note that it's not possible to simply define it basing on STS
because sender and receiver are two different machines that can only
see one another through the network, but their clocks are separate,
and can even run on different or changing speeds, while the only
visible phenomena happen only at a packet arrival machine. This
above formula, however, allows us to define the start time because
Note that it's not possible to simply define a "true" latency based on STS
because the sender and receiver are two different machines that can only
see one another through the network. Their clocks are separate,
and can even run at different or changing speeds, and the only
visible phenomena happen when packets arrive at the receiver machine.
However, the formula above does allow us to define the start time because
we state the following for the very first data packet:

* `ETS[0] = ATS[0]`
Expand All @@ -140,10 +138,9 @@ is that there doesn't exist the common clock base for two
network-communicating machines, so these components should be
treated as something that does exist, but isn't exactly measurable).

But even if there is still this formula for ATS, it doesn't
apply to the real latency - this one is based strictly on ETS.
But you can apply this formula for the very first arriving
packet, because for this one they are equal: `ATS[0] = ETS[0]`.
This formula for ATS doesn't apply to the real latency, which is based strictly
on ETS. But you can apply this formula for the very first arriving packet,
because in this case they are equal: `ATS[0] = ETS[0]`.

Therefore this formula is true for the very first packet:

Expand All @@ -161,30 +158,30 @@ we have then:

* `start_time = prg_delay[0] + net_delay[0] + snd_connect_time`

Note important thing: `start_time` is not the time of arrival of the first packet,
**IMPORTANT**: `start_time` is not the time of arrival of the first packet,
but that time taken backwards by using the delay already recorded in TS. As TS should
represent the delay towards `snd_connect_time`, `start_time` should be simply the same
as `snd_connect_time`, just on the receiver side, and so obviously shifted by the
as `snd_connect_time`, just on the receiver side, and so shifted by the
first packet's delays of `prg_delay` and `net_delay`.

So, as we have the start time defined, the above formulas:

* `ETS[x] = start_time + TS[x]`
* `PTS[x] = ETS[x] + LATENCY + DRIFT`

define now the packet delivery time as:
now define the packet delivery time as:

* `PTS[x] = start_time + TS[x] + LATENCY + DRIFT`

and after replacing the start time we have:

* `PTS[x] = prg_delay[0] + net_delay[0] + snd_connect_time + TS[x] + LATENCY + DRIFT`

and for the formula of TS we get STS, so we replace it:
and from the TS formula we get STS, so we replace it:

* `PTS[x] = prg_delay[0] + net_delay[0] + STS[x] + LATENCY + DRIFT`

so the true network latency in SRT we can get by moving STS to the other side:
We can now get the true network latency in SRT by moving STS to the other side:

* `PTS[x] - STS[x] = prg_delay[0] + net_delay[0] + LATENCY + DRIFT`

Expand All @@ -198,35 +195,30 @@ value of the Arrival Time Deviation:

* `ATD[x] = ATS[x] - ETS[x]`

The drift is then formed as:
The drift is then calculated as:

* `DRIFT[x] = average(ATD[x-N] ... ATD[x])`

The value of the drift is tracked by appropriate number of samples and if
The value of the drift is tracked over an appropriate number of samples. If
it exceeds a threshold value, the drift value is applied to modify the
base time. However, as you can see from the formula for ATD, the drift is
simply taken from the real time when the packet was arrived, and the time
when it would arrive, if the `prg_delay` and `net_delay` values were
simply taken from the actual time when the packet arrived, and the time
when it would have arrived if the `prg_delay` and `net_delay` values were
exactly the same as for the very first packet. ATD then represents the
changes in these values. There can be two main factors that could result
in having this value as nonzero:

1. There has been observed a phenomenon in several types of networks that
the very first packet arrives very quickly, but then as the data packets
come in regularly, the network delay slightly increases and then stays
for a long time with this increased value. This phenomenon could be
mitigated by having a reliable value of RTT, so once it's observed as
increased, a special factor could be used to decrease the positive value
of the drift, but this currently isn't implemented. This phenomenon also
isn't observed in every network, especially in a longer distance.

2. The clock speed on both machines isn't exactly the same, which means
that if you decipher the ETS basing on the TS, after time it may result
in values that even precede the STS (and this way suggesting as if the
network delay was negative) or having an enormous delay (with ATS exceeding
PTS). This is actually the main reason of tracking the drift.





in having this value as non-zero:

1. A phenomenon has been observed in several types of networks where
the very first packet arrives quickly, but as subsequent data packets
come in regularly, the network delay slightly increases and then remains fixed
for a long time at this increased value. This phenomenon can be
mitigated by having a reliable value for RTT. Once the increase is observed
a special factor could be applied to decrease the positive value
of the drift. This isn't currently implemented. This phenomenon also
isn't observed in every network, especially those covering longer distances.

2. The clock speed on both machines (sender and receiver) isn't exactly the same,
which means that if you decipher the ETS basing on the TS, over time it may result
in values that even precede the STS (suggesting a negative network delay) or that
have an enormous delay (with ATS exceeding PTS). This is actually the main reason
for tracking the drift.

0 comments on commit 31eeef6

Please sign in to comment.