summaryrefslogtreecommitdiff
path: root/src/buffer
diff options
context:
space:
mode:
Diffstat (limited to 'src/buffer')
-rw-r--r--src/buffer/audio.c56
-rw-r--r--src/buffer/audio.h4
-rw-r--r--src/buffer/common.h2
-rw-r--r--src/buffer/video.c52
-rw-r--r--src/buffer/video.h4
-rw-r--r--src/buffer/video_null.h4
6 files changed, 61 insertions, 61 deletions
diff --git a/src/buffer/audio.c b/src/buffer/audio.c
index 998662b..f066f18 100644
--- a/src/buffer/audio.c
+++ b/src/buffer/audio.c
@@ -30,14 +30,14 @@ enum {
static void reset_buffer_state(struct camu_audio_buffer *buf)
{
- al_atomic_store(f64)(&buf->pts, -1.0, AL_ATOMIC_RELAXED);
+ atomic_store(f64)(&buf->pts, -1.0, AL_ATOMIC_RELAXED);
buf->pause = PAUSE_PAUSED;
- al_atomic_store(u32)(&buf->unpause, 0, AL_ATOMIC_RELAXED);
+ atomic_store(u32)(&buf->unpause, 0, AL_ATOMIC_RELAXED);
buf->logged_delay = false;
- al_atomic_store(u32)(&buf->volume.set, 0, AL_ATOMIC_RELAXED);
+ atomic_store(u32)(&buf->volume.set, 0, AL_ATOMIC_RELAXED);
buf->buffered = false;
- al_atomic_store(u8)(&buf->flow, FLOWING, AL_ATOMIC_RELAXED);
- al_atomic_store(ptrdiff_t)(&buf->uncork_at, 0, AL_ATOMIC_RELAXED);
+ atomic_store(u32)(&buf->flow, FLOWING, AL_ATOMIC_RELAXED);
+ atomic_store(ptrdiff_t)(&buf->uncork_at, 0, AL_ATOMIC_RELAXED);
}
bool camu_audio_buffer_init(struct camu_audio_buffer *buf, struct camu_clock *clock)
@@ -45,14 +45,14 @@ bool camu_audio_buffer_init(struct camu_audio_buffer *buf, struct camu_clock *cl
buf->clock = clock;
buf->latency = 0.0;
buf->ignore_desync = false;
- al_atomic_store(bool)(&buf->no_video, false, AL_ATOMIC_RELAXED);
+ atomic_store(bool)(&buf->no_video, false, AL_ATOMIC_RELAXED);
reset_buffer_state(buf);
#ifdef CAMU_AUDIO_BUFFER_FADE
// Persist fade volume across resets.
buf->fade.volume = -1.f;
#endif
#ifdef CAMU_MIXER_THREADED
- al_atomic_store(u8)(&buf->ref, 0, AL_ATOMIC_RELAXED);
+ atomic_store(bool)(&buf->ref, false, AL_ATOMIC_RELAXED);
#endif
return true;
}
@@ -98,8 +98,8 @@ bool camu_audio_buffer_configure(struct camu_audio_buffer *buf, struct camu_code
void camu_audio_buffer_set_volume(struct camu_audio_buffer *buf, f32 volume)
{
- al_atomic_store(f32)(&buf->volume.queued, volume, AL_ATOMIC_RELAXED);
- al_atomic_add(u32)(&buf->volume.set, 1, AL_ATOMIC_RELAXED);
+ atomic_store(f32)(&buf->volume.queued, volume, AL_ATOMIC_RELAXED);
+ atomic_add(u32)(&buf->volume.set, 1, AL_ATOMIC_RELAXED);
}
void camu_audio_buffer_set_latency(struct camu_audio_buffer *buf, f64 latency)
@@ -114,13 +114,13 @@ void camu_audio_buffer_set_ignore_desync(struct camu_audio_buffer *buf, bool ign
void camu_audio_buffer_set_no_video(struct camu_audio_buffer *buf, bool no_video)
{
- al_atomic_store(bool)(&buf->no_video, no_video, AL_ATOMIC_RELAXED);
+ atomic_store(bool)(&buf->no_video, no_video, AL_ATOMIC_RELAXED);
}
// A return value of false signals that we pushed to the peak buffer.
static bool push_internal(struct camu_audio_buffer *buf, f64 pts, u8 **data, s32 sample_count)
{
- f64 base_pts = al_atomic_load(f64)(&buf->pts, AL_ATOMIC_ACQUIRE);
+ f64 base_pts = atomic_load(f64)(&buf->pts, AL_ATOMIC_ACQUIRE);
if (data && sample_count > 0) {
f64 duration = camu_audio_format_samples_to_sec(&buf->fmt.in, sample_count);
@@ -140,7 +140,7 @@ static bool push_internal(struct camu_audio_buffer *buf, f64 pts, u8 **data, s32
if (base_pts == -1.0) {
// We want this push() to set the pts even if sample_count = 0.
- al_atomic_store(f64)(&buf->pts, pts, AL_ATOMIC_RELEASE);
+ atomic_store(f64)(&buf->pts, pts, AL_ATOMIC_RELEASE);
}
if (sample_count == 0) {
@@ -170,7 +170,7 @@ static bool push_internal(struct camu_audio_buffer *buf, f64 pts, u8 **data, s32
}
al_assert(peak <= buf->mark.min);
// We adjust the min mark by the peak buffer size just for consistency.
- al_atomic_store(ptrdiff_t)(&buf->uncork_at, buf->mark.min - peak, AL_ATOMIC_RELAXED);
+ atomic_store(ptrdiff_t)(&buf->uncork_at, buf->mark.min - peak, AL_ATOMIC_RELAXED);
buf->callback(buf->userdata, CAMU_BUFFER_CORK);
return false;
}
@@ -198,7 +198,7 @@ static void push_av_frame_internal(struct camu_audio_buffer *buf, AVFrame *frame
// A reset() must finish before any data is pushed.
void camu_audio_buffer_push(struct camu_audio_buffer *buf, struct camu_codec_frame *frame)
{
- u8 flow = al_atomic_load(u8)(&buf->flow, AL_ATOMIC_RELAXED);
+ u8 flow = atomic_load(u32)(&buf->flow, AL_ATOMIC_RELAXED);
// flow could be ERRORED here.
if (flow != FLOWING) {
// Assert that push() is never called after flush().
@@ -235,7 +235,7 @@ void camu_audio_buffer_flush(struct camu_audio_buffer *buf, bool error)
{
log_debug("Flush requested.");
u8 flow = error ? FLUSHED_ERROR : FLUSHED;
- al_atomic_store(u8)(&buf->flow, flow, AL_ATOMIC_RELAXED);
+ atomic_store(u32)(&buf->flow, flow, AL_ATOMIC_RELAXED);
if (!push_internal(buf, 0.0, NULL, 0)) {
log_debug("Buffer filled by flush.");
}
@@ -259,7 +259,7 @@ void camu_audio_buffer_reset(struct camu_audio_buffer *buf)
void camu_audio_buffer_resync(struct camu_audio_buffer *buf)
{
- al_atomic_add(u32)(&buf->unpause, 1, AL_ATOMIC_RELAXED);
+ atomic_add(u32)(&buf->unpause, 1, AL_ATOMIC_RELAXED);
}
ptrdiff_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, ptrdiff_t req)
@@ -267,11 +267,11 @@ ptrdiff_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, ptrdif
// Assert this buffer isn't being read before we signaled BUFFER_BUFFERED.
al_assert(buf->buffered);
- u8 flow = al_atomic_load(u8)(&buf->flow, AL_ATOMIC_ACQUIRE);
+ u8 flow = atomic_load(u32)(&buf->flow, AL_ATOMIC_ACQUIRE);
if (UNLIKELY(flow == ERRORED || flow == FLUSHED_ERROR)) {
if (flow == FLUSHED_ERROR) {
buf->callback(buf->userdata, CAMU_BUFFER_ERRORED);
- al_atomic_store(u8)(&buf->flow, ERRORED, AL_ATOMIC_RELEASE);
+ atomic_store(u32)(&buf->flow, ERRORED, AL_ATOMIC_RELEASE);
}
al_memset(data, 0, req);
return req;
@@ -280,8 +280,8 @@ ptrdiff_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, ptrdif
struct camu_audio_format *fmt = &buf->fmt.req;
ptrdiff_t ret, signal = req;
- 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 base_pts = atomic_load(f64)(&buf->pts, AL_ATOMIC_ACQUIRE);
+ bool set_clock = atomic_load(bool)(&buf->no_video, AL_ATOMIC_RELAXED);
f64 pts = camu_clock_get_pts(buf->clock, buf->latency, set_clock);
if (pts == CAMU_PTS_SIGNAL_PAUSE) {
return 0;
@@ -326,19 +326,19 @@ ptrdiff_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, ptrdif
#endif
}
- if (al_atomic_load(u32)(&buf->volume.set, AL_ATOMIC_ACQUIRE) > 0) {
- buf->volume.user = al_atomic_load(f32)(&buf->volume.queued, AL_ATOMIC_RELAXED);
+ if (atomic_load(u32)(&buf->volume.set, AL_ATOMIC_ACQUIRE) > 0) {
+ buf->volume.user = atomic_load(f32)(&buf->volume.queued, AL_ATOMIC_RELAXED);
#ifdef CAMU_AUDIO_BUFFER_FADE
if (buf->fade.volume == -1.f) buf->fade.volume = buf->volume.user;
#endif
- al_atomic_sub(u32)(&buf->volume.set, 1, AL_ATOMIC_RELEASE);
+ atomic_sub(u32)(&buf->volume.set, 1, AL_ATOMIC_RELEASE);
}
- if (!buf->ignore_desync && al_atomic_load(u32)(&buf->unpause, AL_ATOMIC_ACQUIRE) > 0) {
+ if (!buf->ignore_desync && atomic_load(u32)(&buf->unpause, AL_ATOMIC_ACQUIRE) > 0) {
// Queuing multiple resyncs before resuming the stream will cause pops!
log_debug("Forcing resync.");
buf->pause = PAUSE_PAUSED;
- al_atomic_sub(u32)(&buf->unpause, 1, AL_ATOMIC_RELEASE);
+ atomic_sub(u32)(&buf->unpause, 1, AL_ATOMIC_RELEASE);
}
ptrdiff_t have = al_ring_buffer_occupied(&buf->rb);
@@ -397,7 +397,7 @@ ptrdiff_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, ptrdif
signal = have;
log_debug("Flushed (signal: %zd).", signal);
buf->callback(buf->userdata, CAMU_BUFFER_EOF);
- al_atomic_store(u8)(&buf->flow, SIGNALED, AL_ATOMIC_RELEASE);
+ atomic_store(u32)(&buf->flow, SIGNALED, AL_ATOMIC_RELEASE);
}
} else {
// Silence the remainder of the request.
@@ -454,7 +454,7 @@ ptrdiff_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, ptrdif
#else
if (flow == FLOWING) {
#endif
- ret = al_atomic_load(ptrdiff_t)(&buf->uncork_at, AL_ATOMIC_RELAXED);
+ ret = atomic_load(ptrdiff_t)(&buf->uncork_at, AL_ATOMIC_RELAXED);
if (ret && have - req <= ret) {
buf->callback(buf->userdata, CAMU_BUFFER_UNCORK);
}
@@ -463,7 +463,7 @@ ptrdiff_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, ptrdif
out:
// We aren't safe to increment buf->pts from a different thread.
// For that we could accumulate the difference and atomic_add here instead.
- al_atomic_store(f64)(&buf->pts, base_pts, AL_ATOMIC_RELEASE);
+ atomic_store(f64)(&buf->pts, base_pts, AL_ATOMIC_RELEASE);
// To signal EOF, return less then req.
return signal;
diff --git a/src/buffer/audio.h b/src/buffer/audio.h
index a740c6c..db3c42f 100644
--- a/src/buffer/audio.h
+++ b/src/buffer/audio.h
@@ -33,7 +33,7 @@ struct camu_audio_buffer {
struct { ptrdiff_t min, buffered; } mark;
bool buffered;
- atomic(u8) flow;
+ atomic(u32) flow;
struct camu_peak_buffer peak;
atomic(ptrdiff_t) uncork_at;
@@ -53,7 +53,7 @@ struct camu_audio_buffer {
#endif
#ifdef CAMU_MIXER_THREADED
- atomic(u8) ref;
+ atomic(bool) ref;
#endif
void (*callback)(void *, u8);
diff --git a/src/buffer/common.h b/src/buffer/common.h
index bd9ca45..701969f 100644
--- a/src/buffer/common.h
+++ b/src/buffer/common.h
@@ -5,7 +5,7 @@
#include <al/random.h>
#define ROLL_FOR_BUFFER_ERROR(buf) do { \
if (al_random_int(0, 254) == 72) { \
- al_atomic_store(u8)(&(buf)->flow, FLUSHED_ERROR, AL_ATOMIC_RELAXED); \
+ al_atomic_store(u32)(&(buf)->flow, FLUSHED_ERROR, AL_ATOMIC_RELAXED); \
} \
} while (0)
#endif
diff --git a/src/buffer/video.c b/src/buffer/video.c
index 5011e9d..8bcb1e1 100644
--- a/src/buffer/video.c
+++ b/src/buffer/video.c
@@ -25,15 +25,15 @@ bool camu_video_buffer_init(struct camu_video_buffer *buf, struct camu_clock *cl
{
buf->clock = clock;
buf->latency = 0.0;
- al_atomic_store(f64)(&buf->pts, -1.0, AL_ATOMIC_RELAXED);
+ atomic_store(f64)(&buf->pts, -1.0, AL_ATOMIC_RELAXED);
buf->seek_pts = -1.0;
buf->single_frame = true;
buf->queue = NULL;
buf->buffered = false;
buf->weighted_first_read = false;
- al_atomic_store(u8)(&buf->flow, FLOWING, AL_ATOMIC_RELAXED);
+ atomic_store(u32)(&buf->flow, FLOWING, AL_ATOMIC_RELAXED);
#ifdef CAMU_SCREEN_THREADED
- al_atomic_store(u8)(&buf->ref, 0, AL_ATOMIC_RELAXED);
+ atomic_store(bool)(&buf->ref, false, AL_ATOMIC_RELAXED);
#endif
buf->view.mode = CAMU_VIEW_NONE;
return true;
@@ -123,12 +123,12 @@ static bool push_av_frame_internal(struct camu_video_buffer *buf, AVFrame *frame
{
AVStream *stream = buf->stream->av.stream;
f64 pts = frame->best_effort_timestamp * av_q2d(stream->time_base);
- f64 base_pts = al_atomic_load(f64)(&buf->pts, AL_ATOMIC_ACQUIRE);
+ f64 base_pts = atomic_load(f64)(&buf->pts, AL_ATOMIC_ACQUIRE);
f64 duration = camu_ff_frame_duration(frame) * av_q2d(stream->time_base);
if (!buf->single_frame && frame_is_late(buf->clock, base_pts, pts, duration)) {
return false;
}
- if (base_pts == -1.0) al_atomic_store(f64)(&buf->pts, pts, AL_ATOMIC_RELEASE);
+ if (base_pts == -1.0) atomic_store(f64)(&buf->pts, pts, AL_ATOMIC_RELEASE);
if (buf->fmt.scaler_needed) {
if (!buf->scaler->scale(buf->scaler, (const u8 **)frame->data, frame->linesize)) {
return false;
@@ -143,7 +143,7 @@ static bool push_av_frame_internal(struct camu_video_buffer *buf, AVFrame *frame
void camu_video_buffer_push(struct camu_video_buffer *buf, struct camu_codec_frame *frame)
{
- u8 flow = al_atomic_load(u8)(&buf->flow, AL_ATOMIC_ACQUIRE);
+ u8 flow = atomic_load(u32)(&buf->flow, AL_ATOMIC_ACQUIRE);
if (flow != FLOWING) {
// A single frame will be FLUSHED after any push().
if (buf->single_frame) {
@@ -155,9 +155,9 @@ void camu_video_buffer_push(struct camu_video_buffer *buf, struct camu_codec_fra
switch (frame->mode) {
case CAMU_NORMAL: {
- f64 base_pts = al_atomic_load(f64)(&buf->pts, AL_ATOMIC_ACQUIRE);
+ f64 base_pts = atomic_load(f64)(&buf->pts, AL_ATOMIC_ACQUIRE);
if (base_pts == -1.0) {
- al_atomic_store(f64)(&buf->pts, 0.0, AL_ATOMIC_RELEASE);
+ atomic_store(f64)(&buf->pts, 0.0, AL_ATOMIC_RELEASE);
}
buf->queue->push(buf->queue, frame, 0.0);
break;
@@ -178,7 +178,7 @@ void camu_video_buffer_push(struct camu_video_buffer *buf, struct camu_codec_fra
if (!buf->buffered && (buf->single_frame || count >= BUFFER_MARK_BUFFERED)) {
// Preserve order of: set flow -> flush -> callback, for single frames.
if (buf->single_frame) {
- al_atomic_store(u8)(&buf->flow, FLUSHED, AL_ATOMIC_RELEASE);
+ atomic_store(u32)(&buf->flow, FLUSHED, AL_ATOMIC_RELEASE);
buf->queue->flush(buf->queue);
}
buf->buffered = true;
@@ -204,7 +204,7 @@ void camu_video_buffer_flush(struct camu_video_buffer *buf, bool error)
{
log_debug("Flush requested.");
u8 flow = error ? FLUSHED_ERROR : FLUSHED;
- al_atomic_store(u8)(&buf->flow, flow, AL_ATOMIC_RELAXED);
+ atomic_store(u32)(&buf->flow, flow, AL_ATOMIC_RELAXED);
buf->queue->flush(buf->queue);
if (!buf->buffered) {
s32 count = buf->queue->count(buf->queue);
@@ -221,10 +221,10 @@ void camu_video_buffer_flush(struct camu_video_buffer *buf, bool error)
void camu_video_buffer_reset(struct camu_video_buffer *buf, f64 pts)
{
buf->seek_pts = pts;
- al_atomic_store(f64)(&buf->pts, -1.0, AL_ATOMIC_RELAXED);
+ atomic_store(f64)(&buf->pts, -1.0, AL_ATOMIC_RELAXED);
if (buf->queue) buf->queue->reset(buf->queue);
buf->buffered = false;
- al_atomic_store(u8)(&buf->flow, FLOWING, AL_ATOMIC_RELAXED);
+ atomic_store(u32)(&buf->flow, FLOWING, AL_ATOMIC_RELAXED);
}
bool camu_video_buffer_read(struct camu_video_buffer *buf, void *out, bool *weighted)
@@ -232,7 +232,7 @@ bool camu_video_buffer_read(struct camu_video_buffer *buf, void *out, bool *weig
// Assert this buffer isn't being read before we signaled BUFFER_BUFFERED.
al_assert(buf->buffered);
- f64 base_pts = al_atomic_load(f64)(&buf->pts, AL_ATOMIC_ACQUIRE);
+ f64 base_pts = atomic_load(f64)(&buf->pts, AL_ATOMIC_ACQUIRE);
if (!buf->single_frame) {
bool set_clock = !buf->weighted_first_read;
f64 pts = camu_clock_get_pts(buf->clock, buf->latency, set_clock);
@@ -241,22 +241,29 @@ bool camu_video_buffer_read(struct camu_video_buffer *buf, void *out, bool *weig
}
}
- u8 flow = al_atomic_load(u8)(&buf->flow, AL_ATOMIC_ACQUIRE);
+ u8 flow = atomic_load(u32)(&buf->flow, AL_ATOMIC_ACQUIRE);
if (flow == ERRORED) return false;
u8 ret = buf->queue->read(buf->queue, base_pts, out);
if (ret == CAMU_QUEUE_ERR || flow == FLUSHED_ERROR) {
buf->callback(buf->userdata, CAMU_BUFFER_ERRORED);
- al_atomic_store(u8)(&buf->flow, ERRORED, AL_ATOMIC_RELEASE);
+ atomic_store(u32)(&buf->flow, ERRORED, AL_ATOMIC_RELEASE);
return false;
}
+ // We must update buf->pts on every read(), even on QUEUE_MORE.
+ // Consdier a case where the PTS we call queue->read() with does nothing but
+ // drop frames and returns QUEUE_MORE. If we didn't update buf->pts during
+ // that call and on the next call to read() the clock is paused, base_pts
+ // will erroneously be less than PTS we just used on the previous read().
+ atomic_store(f64)(&buf->pts, base_pts, AL_ATOMIC_RELEASE);
+
// If a buffer only ever has 1 frame, libplacebo will never return EOF.
// In our code that 1 frame buffer might be a video, in which case that behavior is erroneous.
bool eof = ret == CAMU_QUEUE_EOF || (buf->buffered_with_one_frame && ret == CAMU_QUEUE_OK);
if (flow == FLUSHED && eof) {
log_debug("Flushed.");
buf->callback(buf->userdata, CAMU_BUFFER_EOF);
- al_atomic_store(u8)(&buf->flow, SIGNALED, AL_ATOMIC_RELEASE);
+ atomic_store(u32)(&buf->flow, SIGNALED, AL_ATOMIC_RELEASE);
} else if (flow == FLOWING) {
// Never attempt to uncork if flow = FLUSHED.
s32 count = buf->queue->count(buf->queue);
@@ -269,16 +276,9 @@ bool camu_video_buffer_read(struct camu_video_buffer *buf, void *out, bool *weig
}
}
- if (ret == CAMU_QUEUE_OK) {
- // Only updating buf->pts on QUEUE_OK affects the behavior when we fall completely behind.
- // Setting it here will result in laggily displaying out of date frames as they come in.
- // Setting it on every read() will cause the video to freeze.
- // This option ignores sync but is easier for the user to understand what's happening.
- al_atomic_store(f64)(&buf->pts, base_pts, AL_ATOMIC_RELEASE);
- if (UNLIKELY(buf->weighted_first_read)) {
- *weighted = true;
- buf->weighted_first_read = false;
- }
+ if (UNLIKELY(ret == CAMU_QUEUE_OK && buf->weighted_first_read)) {
+ *weighted = true;
+ buf->weighted_first_read = false;
} else if (ret == CAMU_QUEUE_MORE) {
log_trace("Underrun.");
}
diff --git a/src/buffer/video.h b/src/buffer/video.h
index 20644bc..112688a 100644
--- a/src/buffer/video.h
+++ b/src/buffer/video.h
@@ -32,10 +32,10 @@ struct camu_video_buffer {
// Flush the renderer on this read and don't allow it to set the clock.
bool weighted_first_read;
- atomic(u8) flow;
+ atomic(u32) flow;
#ifdef CAMU_SCREEN_THREADED
- atomic(u8) ref;
+ atomic(bool) ref;
#endif
// Previous view, set from screen::add_buffer_internal().
diff --git a/src/buffer/video_null.h b/src/buffer/video_null.h
index f82a4d3..da9d969 100644
--- a/src/buffer/video_null.h
+++ b/src/buffer/video_null.h
@@ -12,7 +12,7 @@ struct camu_video_buffer {
bool single_frame;
f64 avg_frame_duration;
#ifdef CAMU_SCREEN_THREADED
- atomic(u8) ref;
+ atomic(bool) ref;
#endif
void (*callback)(void *, u8);
void *userdata;
@@ -31,7 +31,7 @@ static bool camu_video_buffer_init(struct camu_video_buffer *buf, struct camu_cl
buf->single_frame = true;
buf->avg_frame_duration = 0.0;
#ifdef CAMU_SCREEN_THREADED
- al_atomic_store(u8)(&buf->ref, 0, AL_ATOMIC_RELAXED);
+ al_atomic_store(bool)(&buf->ref, false, AL_ATOMIC_RELAXED);
#endif
return true;
}