mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-02-04 04:06:29 -05:00
module-rtp: Handle unsigned 32-bit integer overflow in constant delay mode
This commit is contained in:
parent
413f5762c4
commit
543000151f
1 changed files with 32 additions and 6 deletions
|
|
@ -380,17 +380,43 @@ static int rtp_audio_receive(struct impl *impl, uint8_t *buffer, ssize_t len,
|
|||
* and not _appended_. In this example, `expected_write` would
|
||||
* be 100 (since `expected_write` is the current write index),
|
||||
* `write` would be 90, `samples` would be 10. In this case,
|
||||
* the inequality below does not hold, so data is being
|
||||
* _inserted_. By contrast, during normal operation, `write`
|
||||
* and `expected_write` are equal, so the inequality below
|
||||
* _does_ hold, meaning that data is being appended.
|
||||
* the (expected_write < (write + samples)) inequality does
|
||||
* not hold, so data is being _inserted_. By contrast, during
|
||||
* normal operation, `write` and `expected_write` are equal,
|
||||
* so the aforementioned inequality _does_ hold, meaning that
|
||||
* data is being appended.
|
||||
*
|
||||
* The code below handles this, and also handles a 32-bit
|
||||
* integer overflow corner case where the comparison has
|
||||
* to be done differently to account for the wrap-around.
|
||||
*
|
||||
* (Note that this write index update is only important if
|
||||
* the constant delay mode is active, or if no spa_io_position
|
||||
* was not provided yet. See the rtp_audio_process_playback()
|
||||
* code for more about this.) */
|
||||
if (expected_write < (write + samples)) {
|
||||
write += samples;
|
||||
|
||||
/* Compute new_write, handling potential 32-bit overflow.
|
||||
* In unsigned arithmetic, if write + samples exceeds UINT32_MAX,
|
||||
* it wraps around to a smaller value. We detect this by checking
|
||||
* if new_write < write (which can only happen on overflow). */
|
||||
const uint32_t new_write = write + samples;
|
||||
const bool wrapped_around = new_write < write;
|
||||
|
||||
/* Determine if new_write is ahead of expected_write.
|
||||
* We're appending (ahead) if:
|
||||
*
|
||||
* 1. Normal case: new_write > expected_write (forward progress)
|
||||
* 2. Wrap-around case: new_write wrapped around (wrapped_around == true),
|
||||
* meaning we've cycled through the 32-bit index space and are
|
||||
* continuing from the beginning. In this case, we're always ahead.
|
||||
*
|
||||
* We're NOT appending (inserting/behind) if:
|
||||
* - new_write <= expected_write AND no wrap-around occurred
|
||||
* (we're filling a gap or writing behind the current position) */
|
||||
const bool is_appending = wrapped_around || (new_write > expected_write);
|
||||
|
||||
if (is_appending) {
|
||||
write = new_write;
|
||||
spa_ringbuffer_write_update(&impl->ring, write);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue