mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-04-15 08:21:11 -04:00
rtp: include stream delay to a read position
When a stream has some delay, a time t1 + delay has to be read in time t1 to play it when expected. Decrease target_buffer by delay to start playback sooner, so sound is played at correct time when delay is applied. Signed-off-by: Martin Geier <martin.geier@streamunlimited.com>
This commit is contained in:
parent
1ed8f771bd
commit
f8b0d0a43c
1 changed files with 24 additions and 2 deletions
|
|
@ -7,7 +7,9 @@ static void rtp_audio_process_playback(void *data)
|
||||||
struct impl *impl = data;
|
struct impl *impl = data;
|
||||||
struct pw_buffer *buf;
|
struct pw_buffer *buf;
|
||||||
struct spa_data *d;
|
struct spa_data *d;
|
||||||
|
struct pw_time pwt;
|
||||||
uint32_t wanted, timestamp, target_buffer, stride, maxsize;
|
uint32_t wanted, timestamp, target_buffer, stride, maxsize;
|
||||||
|
uint32_t device_delay;
|
||||||
int32_t avail, flags = 0;
|
int32_t avail, flags = 0;
|
||||||
|
|
||||||
if ((buf = pw_stream_dequeue_buffer(impl->stream)) == NULL) {
|
if ((buf = pw_stream_dequeue_buffer(impl->stream)) == NULL) {
|
||||||
|
|
@ -21,16 +23,36 @@ static void rtp_audio_process_playback(void *data)
|
||||||
maxsize = d[0].maxsize / stride;
|
maxsize = d[0].maxsize / stride;
|
||||||
wanted = buf->requested ? SPA_MIN(buf->requested, maxsize) : maxsize;
|
wanted = buf->requested ? SPA_MIN(buf->requested, maxsize) : maxsize;
|
||||||
|
|
||||||
|
pw_stream_get_time_n(impl->stream, &pwt, sizeof(pwt));
|
||||||
|
|
||||||
|
/* Negative delay is used rarely, mostly for the combine stream.
|
||||||
|
* There, the delay is used as an offset value between streams.
|
||||||
|
* Here, negative delay values make no sense. It is safe to clamp
|
||||||
|
* delay values to 0 (see docs), so do that here. */
|
||||||
|
device_delay = SPA_MAX(pwt.delay, 0LL);
|
||||||
|
|
||||||
if (impl->io_position && impl->direct_timestamp) {
|
if (impl->io_position && impl->direct_timestamp) {
|
||||||
/* in direct mode, read directly from the timestamp index,
|
/* in direct mode, read directly from the timestamp index,
|
||||||
* because sender and receiver are in sync, this would keep
|
* because sender and receiver are in sync, this would keep
|
||||||
* target_buffer of samples available. */
|
* target_buffer of samples available. */
|
||||||
|
|
||||||
|
/* Shift clock position by stream delay to compensate
|
||||||
|
* for processing and output delay. */
|
||||||
spa_ringbuffer_read_update(&impl->ring,
|
spa_ringbuffer_read_update(&impl->ring,
|
||||||
impl->io_position->clock.position);
|
impl->io_position->clock.position + device_delay);
|
||||||
}
|
}
|
||||||
avail = spa_ringbuffer_get_read_index(&impl->ring, ×tamp);
|
avail = spa_ringbuffer_get_read_index(&impl->ring, ×tamp);
|
||||||
|
|
||||||
target_buffer = impl->target_buffer;
|
/* Reduce target buffer by the delay amount to start playback sooner.
|
||||||
|
* This compensates for the delay to the device. */
|
||||||
|
if (SPA_UNLIKELY(impl->target_buffer < device_delay)) {
|
||||||
|
pw_log_error("Delay to device (%" PRIu32 ") is higher than "
|
||||||
|
"the target buffer size (%" PRIu32 ")", device_delay,
|
||||||
|
impl->target_buffer);
|
||||||
|
target_buffer = 0;
|
||||||
|
} else {
|
||||||
|
target_buffer = impl->target_buffer - device_delay;
|
||||||
|
}
|
||||||
|
|
||||||
if (avail < (int32_t)wanted) {
|
if (avail < (int32_t)wanted) {
|
||||||
enum spa_log_level level;
|
enum spa_log_level level;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue