summaryrefslogtreecommitdiff
path: root/src/buffer
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2024-01-06 19:54:21 -0500
committerAndrew Opalach <andrew@akon.city> 2024-01-06 19:54:21 -0500
commite6c1c0afc69ee13465bb68a6bdeb35b6876146d4 (patch)
treeffea140be35691dfc24e9a6ca6c54e2d0247e8a8 /src/buffer
parent11bbaf5198d15da44731ffb63411558f1c72f97e (diff)
downloadcamu-e6c1c0afc69ee13465bb68a6bdeb35b6876146d4.tar.gz
camu-e6c1c0afc69ee13465bb68a6bdeb35b6876146d4.tar.bz2
camu-e6c1c0afc69ee13465bb68a6bdeb35b6876146d4.zip
Initial synced playback
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/buffer')
-rw-r--r--src/buffer/audio.c10
-rw-r--r--src/buffer/clock.c73
-rw-r--r--src/buffer/clock.h9
-rw-r--r--src/buffer/video.c1
4 files changed, 54 insertions, 39 deletions
diff --git a/src/buffer/audio.c b/src/buffer/audio.c
index 9799a95..ffb10dc 100644
--- a/src/buffer/audio.c
+++ b/src/buffer/audio.c
@@ -70,10 +70,9 @@ bool camu_audio_buffer_init(struct camu_audio_buffer *buf, struct camu_clock *cl
{
buf->mixer = mixer;
buf->clock = clock;
- buf->pts = camu_mixer_get_latency(buf->mixer);
buf->buffered = false;
buf->pause = PAUSE_PRE;
- buf->ignore_desync = true;
+ buf->ignore_desync = false;
#ifdef CAMU_AUDIO_BUFFER_FADE
buf->fade_period = 0;
buf->fade_offset = 0;
@@ -198,7 +197,7 @@ void camu_audio_buffer_reset(struct camu_audio_buffer *buf)
{
al_atomic_size_t_store(&buf->continue_mark, 0, AL_ATOMIC_RELAXED);
al_atomic_u8_store(&buf->flow, FLOWING, AL_ATOMIC_RELAXED);
- buf->pts = camu_clock_get_base_pts(buf->clock);
+ buf->pts = camu_clock_get_base_pts(buf->clock) + camu_mixer_get_latency(buf->mixer);
buf->buffered = false;
buf->pause = PAUSE_PRE;
al_ring_buffer_reset(&buf->rb);
@@ -259,7 +258,8 @@ static void handle_fade(struct camu_audio_buffer *buf, u8 *data, size_t size, bo
size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t req)
{
- if (camu_clock_is_paused(buf->clock)) {
+ f64 pts = camu_clock_get_pts(buf->clock);
+ if (pts < 0.0) {
#ifdef CAMU_AUDIO_BUFFER_FADE
if (buf->pause == PAUSE_PLAYING) {
// Fade out. Signified by >0 fade_period and PAUSE_FADING.
@@ -299,7 +299,7 @@ size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t re
#ifdef CAMU_AUDIO_BUFFER_FADE
if (buf->pause != PAUSE_FADING) {
#endif
- f64 pts = camu_clock_get_pts(buf->clock) - buf->pts;
+ pts -= buf->pts;
// We can assume a call to audio_buffer_read will happen before
// the user NEEDS the data, so, we can't accurately assess the sync here.
if (UNLIKELY(!buf->ignore_desync && (buf->pause == PAUSE_PRE || buf->pause == PAUSE_UNPAUSED))) {
diff --git a/src/buffer/clock.c b/src/buffer/clock.c
index c9b18ce..a1c3e83 100644
--- a/src/buffer/clock.c
+++ b/src/buffer/clock.c
@@ -1,55 +1,68 @@
+#include <al/lib.h>
+
#include "clock.h"
-void camu_clock_init(struct camu_clock *clock)
+void camu_clock_set(struct camu_clock *clock, u64 base, u64 start)
{
- f64 tick = aki_get_tick();
- al_atomic_f64_store(&clock->pause, tick, AL_ATOMIC_RELAXED);
- al_atomic_f64_store(&clock->start, tick, AL_ATOMIC_RELAXED);
- al_atomic_f64_store(&clock->base, 0.0, AL_ATOMIC_RELAXED);
+ al_atomic_f64_store(&clock->base, base / 1000000.f, AL_ATOMIC_RELAXED);
+ al_atomic_f64_store(&clock->tick, 0.0, AL_ATOMIC_RELAXED);
+ al_atomic_u64_store(&clock->start, start, AL_ATOMIC_RELAXED);
+ camu_clock_resume(clock);
}
-void camu_clock_pause(struct camu_clock *clock)
+void camu_clock_resume(struct camu_clock *clock)
{
- f64 pause = al_atomic_f64_load(&clock->pause, AL_ATOMIC_RELAXED);
- if (pause != -1.0) return;
- al_atomic_f64_store(&clock->pause, aki_get_tick(), AL_ATOMIC_RELAXED);
+ u64 start = al_atomic_u64_load(&clock->start, AL_ATOMIC_ACQUIRE);
+ if (start == 0L) return;
+ u64 ts = aki_get_timestamp();
+ al_assert(start < ts);
+ f64 diff = (ts - start) / 1000000.f;
+ f64 tick = al_atomic_f64_load(&clock->tick, AL_ATOMIC_RELAXED);
+ if (tick == 0.0) {
+ tick = aki_get_tick() - al_atomic_f64_load(&clock->base, AL_ATOMIC_RELAXED);
+ }
+ al_atomic_f64_store(&clock->tick, tick + diff, AL_ATOMIC_RELAXED);
+ al_atomic_u64_store(&clock->start, 0L, AL_ATOMIC_RELEASE);
}
-void camu_clock_resume(struct camu_clock *clock)
+static f64 get_pts_internal(struct camu_clock *clock)
{
- f64 pause = al_atomic_f64_load(&clock->pause, AL_ATOMIC_RELAXED);
- if (pause == -1.0) return;
- f64 start = al_atomic_f64_load(&clock->start, AL_ATOMIC_RELAXED);
- f64 base = al_atomic_f64_load(&clock->base, AL_ATOMIC_RELAXED);
- if (start == 0.0) start = (pause - base);
- al_atomic_f64_store(&clock->pause, -1.0, AL_ATOMIC_RELAXED);
- al_atomic_f64_store(&clock->start, aki_get_tick() - (pause - start), AL_ATOMIC_RELAXED);
+ f64 tick = al_atomic_f64_load(&clock->tick, AL_ATOMIC_RELAXED);
+ return aki_get_tick() - tick;
}
-void camu_clock_seek(struct camu_clock *clock, f64 pos)
+void camu_clock_pause(struct camu_clock *clock)
{
- al_atomic_f64_store(&clock->start, 0.0, AL_ATOMIC_RELAXED);
- al_atomic_f64_store(&clock->base, pos, AL_ATOMIC_RELAXED);
- f64 tick = aki_get_tick();
- al_atomic_f64_store(&clock->pause, tick, AL_ATOMIC_RELAXED);
+ u64 start = al_atomic_u64_load(&clock->start, AL_ATOMIC_ACQUIRE);
+ if (start != 0L) return;
+ al_atomic_f64_store(&clock->base, get_pts_internal(clock), AL_ATOMIC_RELAXED);
+ al_atomic_u64_store(&clock->start, aki_get_timestamp(), AL_ATOMIC_RELEASE);
+}
+
+void camu_clock_seek(struct camu_clock *clock, u64 base, u64 start)
+{
+ (void)clock;
+ (void)base;
+ (void)start;
}
bool camu_clock_is_paused(struct camu_clock *clock)
{
- f64 pause = al_atomic_f64_load(&clock->pause, AL_ATOMIC_RELAXED);
- return pause != -1.0;
+ u64 start = al_atomic_u64_load(&clock->start, AL_ATOMIC_RELAXED);
+ return start != 0L;
}
f64 camu_clock_get_base_pts(struct camu_clock *clock)
{
- f64 base = al_atomic_f64_load(&clock->base, AL_ATOMIC_RELAXED);
- return base;
+ return al_atomic_f64_load(&clock->base, AL_ATOMIC_RELAXED);
}
f64 camu_clock_get_pts(struct camu_clock *clock)
{
- f64 pause = al_atomic_f64_load(&clock->pause, AL_ATOMIC_RELAXED);
- f64 start = al_atomic_f64_load(&clock->start, AL_ATOMIC_RELAXED);
- if (pause != -1.f) return pause - start;
- return aki_get_tick() - start;
+ u64 start = al_atomic_u64_load(&clock->start, AL_ATOMIC_RELAXED);
+ if (start != 0L) return -1.0;
+ f64 base = al_atomic_f64_load(&clock->base, AL_ATOMIC_RELAXED);
+ f64 pts = get_pts_internal(clock);
+ if (pts < base) return -1.0;
+ return pts;
}
diff --git a/src/buffer/clock.h b/src/buffer/clock.h
index 9f34807..e39a963 100644
--- a/src/buffer/clock.h
+++ b/src/buffer/clock.h
@@ -4,13 +4,14 @@
#include <al/atomic.h>
struct camu_clock {
- atomic_f64 base, start, pause;
+ atomic_f64 base, tick;
+ atomic_u64 start;
};
-void camu_clock_init(struct camu_clock *clock);
-void camu_clock_pause(struct camu_clock *clock);
+void camu_clock_set(struct camu_clock *clock, u64 base, u64 start);
void camu_clock_resume(struct camu_clock *clock);
-void camu_clock_seek(struct camu_clock *clock, f64 pos);
+void camu_clock_pause(struct camu_clock *clock);
+void camu_clock_seek(struct camu_clock *clock, u64 base, u64 start);
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);
diff --git a/src/buffer/video.c b/src/buffer/video.c
index 6c8d6e3..3d3961b 100644
--- a/src/buffer/video.c
+++ b/src/buffer/video.c
@@ -137,6 +137,7 @@ void camu_video_buffer_flush(struct camu_video_buffer *buf)
bool camu_video_buffer_read(struct camu_video_buffer *buf, void *out)
{
f64 pts = buf->single_frame ? 0.0 : camu_clock_get_pts(buf->clock);
+ if (pts < 0.0) pts = camu_clock_get_base_pts(buf->clock);
u8 ret = buf->queue->read(buf->queue, pts, out);
if (ret == CAMU_QUEUE_EOF || (ret == CAMU_QUEUE_OK && buf->single_frame)) {
buf->callback(buf->userdata, CAMU_BUFFER_EOF);