mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-06-17 14:33:04 -04:00
module-rtp: Add calculate_seqnum_delta() utility function
This commit is contained in:
parent
fbe0d37649
commit
e7563b19b6
1 changed files with 46 additions and 0 deletions
|
|
@ -9,6 +9,9 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <spa/utils/defs.h>
|
||||||
|
|
||||||
struct rtp_header {
|
struct rtp_header {
|
||||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
unsigned cc:4;
|
unsigned cc:4;
|
||||||
|
|
@ -85,6 +88,49 @@ struct rtp_midi_journal {
|
||||||
uint16_t checkpoint_seqnum;
|
uint16_t checkpoint_seqnum;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
static inline int16_t calculate_seqnum_delta(uint16_t seqnum_a, uint16_t seqnum_b)
|
||||||
|
{
|
||||||
|
/* In RTP, sequence numbers are 16-bit unsigned integers. These
|
||||||
|
* can realistically reach the limit of that data type's range.
|
||||||
|
* In unsigned integer arithmetic, trying to increment past the
|
||||||
|
* range causes a wrap around. 65535 incremented by 1 becomes
|
||||||
|
* 0, for example.
|
||||||
|
*
|
||||||
|
* This matters when calculating deltas between sequence numbers.
|
||||||
|
* Straightforward cases like (500-450) are just like normal
|
||||||
|
* (the result would be 50 in this example). Same goes for
|
||||||
|
* reverse sequence numbers; 450-500 => -50. But when the first
|
||||||
|
* sequence number is something like 65535, and the second
|
||||||
|
* sequence number is something like 0, the straightforward
|
||||||
|
* method would result in something incorrect (a delta of
|
||||||
|
* -65535, when actually, the correct delta is 1).
|
||||||
|
*
|
||||||
|
* This code uses unsigned integer wrap-around arithmetic to
|
||||||
|
* handle such special sequence number wrap-around cases implicitly.
|
||||||
|
* A subtraction that normally would result in a negative value
|
||||||
|
* wraps around; subtracting 1 from 0, which normally would
|
||||||
|
* result in -1, becomes 65535 for example.
|
||||||
|
*
|
||||||
|
* By treating unsigned deltas below 32768 as positive deltas, and
|
||||||
|
* those >= 32768 as negative deltas, that arithmetic does the job
|
||||||
|
* for us. With two's complement, the cast directly reinterprets
|
||||||
|
* the bit pattern to produce the signed delta. (For example, uint16
|
||||||
|
* 65535 -> int16 -1). In the very rare case of a non-2-complement
|
||||||
|
* machine, an alternative code is used that handles the >=32768
|
||||||
|
* unsigned delta case separately.
|
||||||
|
*
|
||||||
|
* This allows for positive sequence number deltas of up to 32767 and
|
||||||
|
* negative ones of up to -32768 to be handled correctly. Such vast
|
||||||
|
* deltas between sequence numbers are highly anomalous in RTP, so
|
||||||
|
* this covers all real world use cases well. */
|
||||||
|
|
||||||
|
#ifdef SPA_MACHINE_USES_TWOS_COMPLEMENT
|
||||||
|
return (int16_t)(seqnum_b - seqnum_a);
|
||||||
|
#else
|
||||||
|
uint16_t udelta = seqnum_b - seqnum_a;
|
||||||
|
return (udelta < 32768) ? ((int32_t)udelta) : ((int32_t)udelta - 65536);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue