From 0d6d13425015d78606232874498327cabcb0e4e2 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Sat, 22 Nov 2025 14:22:11 -0500 Subject: Fixes and cleanup around synced gapless Signed-off-by: Andrew Opalach --- src/buffer/audio.c | 4 +++- src/buffer/clock.c | 25 ++++++++++--------------- src/buffer/clock.h | 8 ++++++-- src/buffer/video.c | 4 +++- 4 files changed, 22 insertions(+), 19 deletions(-) (limited to 'src/buffer') diff --git a/src/buffer/audio.c b/src/buffer/audio.c index 377877e..a740111 100644 --- a/src/buffer/audio.c +++ b/src/buffer/audio.c @@ -283,7 +283,9 @@ ptrdiff_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, ptrdif f64 base_pts = al_atomic_load(f64)(&buf->pts, AL_ATOMIC_ACQUIRE); bool set_clock = al_atomic_load(bool)(&buf->no_video, AL_ATOMIC_RELAXED); f64 pts = camu_clock_get_pts(buf->clock, buf->latency, set_clock); - if (pts == -1.0) { + if (pts == CAMU_PTS_SIGNAL_PAUSE) { + return 0; + } else if (pts == CAMU_PTS_PAUSED) { #ifdef CAMU_AUDIO_BUFFER_FADE if (buf->pause == PAUSE_PLAYING) { buf->pause = PAUSE_FADING; diff --git a/src/buffer/clock.c b/src/buffer/clock.c index 67a229b..732185e 100644 --- a/src/buffer/clock.c +++ b/src/buffer/clock.c @@ -1,5 +1,7 @@ #include +#include "../liana/common.h" + #include "clock.h" #define RUNNING 0.0 @@ -50,7 +52,7 @@ void camu_clock_seek(struct camu_clock *clock, f64 base, u64 target) // the clock would report the old position in get_pts() before triggering CLOCK_PAUSED. // Likely confusing an entry's buffers and causing excessive catchup or delay. // We mitigate this sink-side by immediately switching to a potential target in - // CLIENT_REMOVE_BUFFERS, if possible, which is always called before an entry is seeked. + // CLIENT_REMOVE_BUFFERS, which is always called before an entry is seeked. clock->paused_at = 0.0; } } @@ -58,18 +60,10 @@ void camu_clock_seek(struct camu_clock *clock, f64 base, u64 target) void camu_clock_loop(struct camu_clock *clock, f64 last_pts) { // Seek to 0 but include the time it took to perform the seek. - // Even without skipping a frame this method of looping is likely - // to mess up the frame pacing between the last frame of the previous - // loop and the first frame of this loop. clock->offset += last_pts - clock->base; clock->base = 0.0; } -void camu_clock_offset(struct camu_clock *clock, f64 amount) -{ - clock->offset += amount; -} - void camu_clock_pause(struct camu_clock *clock, u64 target) { al_assert(clock->paused_at == -1.0); @@ -120,10 +114,10 @@ f64 camu_clock_get_base_pts(struct camu_clock *clock) return clock->base; } -f64 camu_clock_get_pts(struct camu_clock *clock, f64 offset, bool allow_set) +f64 camu_clock_get_pts(struct camu_clock *clock, f64 latency, bool allow_set) { f64 pause = al_atomic_load(f64)(&clock->pause, AL_ATOMIC_ACQUIRE); - if (pause == PAUSED) return -1.0; + if (pause == PAUSED) return CAMU_PTS_PAUSED; f64 current = nn_get_tick(); @@ -133,16 +127,17 @@ f64 camu_clock_get_pts(struct camu_clock *clock, f64 offset, bool allow_set) tick = al_atomic_compare_and_swap(f64)(&clock->tick, -1.0, current); if (tick == -1.0) tick = current; } else { - return -1.0; + return CAMU_PTS_PAUSED; } } - // pause > 0.0 means running or pause armed. - if (pause > 0.0 && current > pause) { + bool signal_pause = false; + if (pause > 0.0 && current > pause) { // pause > 0.0 means running or pause armed. current = pause; pause = al_atomic_compare_and_swap(f64)(&clock->pause, pause, PAUSED); if (pause != PAUSED) { clock->callback(clock->userdata, CAMU_CLOCK_PAUSED); + signal_pause = true; } } @@ -152,7 +147,7 @@ f64 camu_clock_get_pts(struct camu_clock *clock, f64 offset, bool allow_set) al_atomic_store(f64)(&clock->last_pts, pts, AL_ATOMIC_RELAXED); } - return pts + offset; + return signal_pause ? CAMU_PTS_SIGNAL_PAUSE : pts + latency; } f64 camu_clock_get_last_pts(struct camu_clock *clock) diff --git a/src/buffer/clock.h b/src/buffer/clock.h index 57bdb7d..3209119 100644 --- a/src/buffer/clock.h +++ b/src/buffer/clock.h @@ -23,6 +23,10 @@ // Next/Prev: // - User input -> swap +#define CAMU_PTS_PAUSED 0xffffffffffffffff +#define CAMU_PTS_SIGNAL_PAUSE 0x7fffffffffffffff +#define CAMU_PTS_CONSIDER_PAUSED(pts) (pts == CAMU_PTS_PAUSED || pts == CAMU_PTS_SIGNAL_PAUSE) + enum { CAMU_CLOCK_PAUSED = 0 }; @@ -40,14 +44,14 @@ struct camu_clock { void camu_clock_init(struct camu_clock *clock, void (*callback)(void *, u8), void *userdata); void camu_clock_set(struct camu_clock *clock, f64 base); + void camu_clock_seek(struct camu_clock *clock, f64 base, u64 target); void camu_clock_loop(struct camu_clock *clock, f64 last_pts); -void camu_clock_offset(struct camu_clock *clock, f64 amount); void camu_clock_pause(struct camu_clock *clock, u64 target); void camu_clock_resume(struct camu_clock *clock, u64 target); bool camu_clock_is_paused(struct camu_clock *clock); f64 camu_clock_get_base_pts(struct camu_clock *clock); -f64 camu_clock_get_pts(struct camu_clock *clock, f64 offset, bool allow_set); +f64 camu_clock_get_pts(struct camu_clock *clock, f64 latency, bool allow_set); f64 camu_clock_get_last_pts(struct camu_clock *clock); diff --git a/src/buffer/video.c b/src/buffer/video.c index d16a106..e5c38a6 100644 --- a/src/buffer/video.c +++ b/src/buffer/video.c @@ -234,7 +234,9 @@ bool camu_video_buffer_read(struct camu_video_buffer *buf, void *out, bool *weig f64 base_pts = al_atomic_load(f64)(&buf->pts, AL_ATOMIC_ACQUIRE); if (!buf->single_frame) { f64 pts = camu_clock_get_pts(buf->clock, buf->latency, !buf->weighted_read); - if (pts > base_pts) base_pts = pts; + if (!CAMU_PTS_CONSIDER_PAUSED(pts) && pts > base_pts) { + base_pts = pts; + } } u8 flow = al_atomic_load(u8)(&buf->flow, AL_ATOMIC_ACQUIRE); -- cgit v1.2.3-101-g0448