diff options
| author | 2025-11-30 18:26:31 -0500 | |
|---|---|---|
| committer | 2025-11-30 18:26:31 -0500 | |
| commit | c6a78e2502fd3f7deabecbf48970f346424106f6 (patch) | |
| tree | 4564443ec04438d4c878203029f7abf53437c287 /src/buffer | |
| parent | c8412bbedae0fce38db96833732e8ce904721e4c (diff) | |
| download | camu-c6a78e2502fd3f7deabecbf48970f346424106f6.tar.gz camu-c6a78e2502fd3f7deabecbf48970f346424106f6.tar.bz2 camu-c6a78e2502fd3f7deabecbf48970f346424106f6.zip | |
Pass on atomic usage
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/buffer')
| -rw-r--r-- | src/buffer/audio.c | 56 | ||||
| -rw-r--r-- | src/buffer/audio.h | 4 | ||||
| -rw-r--r-- | src/buffer/common.h | 2 | ||||
| -rw-r--r-- | src/buffer/video.c | 52 | ||||
| -rw-r--r-- | src/buffer/video.h | 4 | ||||
| -rw-r--r-- | src/buffer/video_null.h | 4 |
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; } |