summaryrefslogtreecommitdiff
path: root/src/buffer
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2025-11-22 14:22:11 -0500
committerAndrew Opalach <andrew@akon.city> 2025-11-22 14:22:11 -0500
commit0d6d13425015d78606232874498327cabcb0e4e2 (patch)
tree34682f9e9602117dac6db5f7de8c67d1207135c4 /src/buffer
parentd4ea79a8622b6bf03555f186aeb1f5fa9283721f (diff)
downloadcamu-0d6d13425015d78606232874498327cabcb0e4e2.tar.gz
camu-0d6d13425015d78606232874498327cabcb0e4e2.tar.bz2
camu-0d6d13425015d78606232874498327cabcb0e4e2.zip
Fixes and cleanup around synced gapless
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/buffer')
-rw-r--r--src/buffer/audio.c4
-rw-r--r--src/buffer/clock.c25
-rw-r--r--src/buffer/clock.h8
-rw-r--r--src/buffer/video.c4
4 files changed, 22 insertions, 19 deletions
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 <nnwt/thread.h>
+#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);