From 2bee71a7e032c0972418e324bb1d7e6b02330b18 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Wed, 19 Feb 2025 13:40:38 -0500 Subject: Server resource unload, many tweaks and fixes - Initial liana client preferences. - Hook up libplacebo dx11 backend. - Make usage of FFmpeg hardware decoding api make some sense. Signed-off-by: Andrew Opalach --- src/buffer/audio.c | 40 +++++++++++++++++++++++----------------- src/buffer/audio.h | 2 ++ src/buffer/frame_queue.h | 6 ++---- src/buffer/video.c | 23 +++++++++++------------ src/buffer/video.h | 8 ++------ 5 files changed, 40 insertions(+), 39 deletions(-) (limited to 'src/buffer') diff --git a/src/buffer/audio.c b/src/buffer/audio.c index eaac16f..8e0d428 100644 --- a/src/buffer/audio.c +++ b/src/buffer/audio.c @@ -11,11 +11,11 @@ #define BUFFER_SIZE 8.0 #define BUFFER_MARK_MIN 3.25 // Must be a most half of the buffer size. -#define BUFFER_MARK_BUFFERED 1.0 +#define BUFFER_MARK_BUFFERED 0.25 #ifdef CAMU_AUDIO_BUFFER_FADE #define FADE_STEP(fmt) (2.50f / (fmt)->sample_rate) -#define FADE_MIN(fmt) (8000.f / (fmt)->sample_rate) +#define FADE_MIN 0.175f #endif enum { @@ -32,6 +32,7 @@ static void reset_buffer_state(struct camu_audio_buffer *buf) al_atomic_store(f64)(&buf->pts, -1.0, AL_ATOMIC_RELAXED); buf->pause = PAUSE_PAUSED; al_atomic_store(u32)(&buf->unpause, 0, AL_ATOMIC_RELAXED); + buf->logged_delay = false; al_atomic_store(u32)(&buf->volume.set, 0, AL_ATOMIC_RELAXED); buf->buffered = false; al_atomic_store(u8)(&buf->flow, FLOWING, AL_ATOMIC_RELAXED); @@ -120,8 +121,7 @@ static bool push_internal(struct camu_audio_buffer *buf, f64 pts, u8 **data, s32 { f64 base_pts = al_atomic_load(f64)(&buf->pts, AL_ATOMIC_ACQUIRE); - if (sample_count > 0) { - al_assert(data); + if (data && sample_count > 0) { f64 duration = camu_audio_format_samples_to_sec(&buf->fmt.in, sample_count); if (frame_is_late(buf->clock, base_pts, pts, duration)) { return true; @@ -131,7 +131,6 @@ static bool push_internal(struct camu_audio_buffer *buf, f64 pts, u8 **data, s32 data = buf->resampler->get_data(buf->resampler); } } else { - al_assert(!data); if (buf->fmt.resampler_needed) { sample_count = buf->resampler->flush(buf->resampler); data = buf->resampler->get_data(buf->resampler); @@ -148,10 +147,10 @@ static bool push_internal(struct camu_audio_buffer *buf, f64 pts, u8 **data, s32 return true; } + // The maximum space is buf->size - 1. ptrdiff_t space = al_ring_buffer_space(&buf->rb); - if (!buf->buffered && buf->size - space > buf->mark.buffered) { - al_log_debug("audio_buffer", "Buffered (mark: %.2fs).", - camu_audio_format_bytes_to_sec(&buf->fmt.req, buf->size - space)); + if (!buf->buffered && (buf->size - 1) - space >= buf->mark.buffered) { + al_log_debug("audio_buffer", "Buffered (mark: %.1fkb).", buf->mark.buffered / 1024.0); buf->callback(buf->userdata, CAMU_BUFFER_BUFFERED); buf->buffered = true; } @@ -230,8 +229,7 @@ void camu_audio_buffer_flush(struct camu_audio_buffer *buf) } if (!buf->buffered) { - al_log_debug("audio_buffer", "Buffered (mark: %.2fs).", - camu_audio_format_bytes_to_sec(&buf->fmt.req, al_ring_buffer_occupied(&buf->rb))); + al_log_debug("audio_buffer", "Buffered (flush)."); buf->callback(buf->userdata, CAMU_BUFFER_BUFFERED); buf->buffered = true; } @@ -275,12 +273,16 @@ ptrdiff_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, ptrdif (buf->fade.volume == 0.f)) { al_memset(data, 0, req); if (buf->pause == PAUSE_FADING_COMPLETE) { - buf->callback(buf->userdata, CAMU_BUFFER_PAUSED); - buf->pause = PAUSE_PAUSED; + if (!--buf->fade.tail) { + buf->callback(buf->userdata, CAMU_BUFFER_PAUSED); + buf->pause = PAUSE_PAUSED; + } } else if (buf->pause != PAUSE_PAUSED) { // Don't signal PAUSED until the next read to ensure at least 1 silent // frame is included in the fade out. buf->pause = PAUSE_FADING_COMPLETE; + // How many frames of silence to append after fading. + buf->fade.tail = 1; } return req; } @@ -314,7 +316,7 @@ ptrdiff_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, ptrdif if (!buf->ignore_desync && al_atomic_load(u32)(&buf->unpause, AL_ATOMIC_ACQUIRE) > 0) { // Queuing multiple resyncs before resuming the stream will cause pops! - al_log_debug("audio_buffer", "Forcing resync."); + al_log_info("audio_buffer", "Forcing resync."); buf->pause = PAUSE_PAUSED; al_atomic_sub(u32)(&buf->unpause, 1, AL_ATOMIC_RELEASE); } @@ -342,13 +344,17 @@ ptrdiff_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, ptrdif } else if (pts < 0.0) { // Delay. pts = -pts; ret = MIN((ptrdiff_t)camu_audio_format_sec_to_bytes(fmt, pts), req); - al_log_info("audio_buffer", "Delaying audio by %fs.", pts); + if (!buf->logged_delay) { + al_log_info("audio_buffer", "Delaying audio by %fs.", pts); + buf->logged_delay = true; + } al_memset(data, 0, ret); data += ret; req -= ret; // We can continue to delay. if (req == 0) goto out; } + buf->logged_delay = false; } buf->pause = PAUSE_PLAYING; } @@ -420,7 +426,7 @@ ptrdiff_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, ptrdif // fades if the volume is low. step *= buf->volume.user; } - step *= MAX(buf->fade.volume, FADE_MIN(fmt)); + step *= MAX(buf->fade.volume, FADE_MIN); buf->fade.volume = apply_volume(data, req, fmt, buf->fade.volume, buf->volume.user, step); } #else @@ -443,8 +449,8 @@ ptrdiff_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, ptrdif } out: - // We are not safe to increment buf->pts from a different thread. - // We would need to accumulate the difference and do an atomic add here. + // 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); // To signal EOF, return less then req. diff --git a/src/buffer/audio.h b/src/buffer/audio.h index ef907bd..5fa2473 100644 --- a/src/buffer/audio.h +++ b/src/buffer/audio.h @@ -21,6 +21,7 @@ struct camu_audio_buffer { atomic(bool) no_video; u8 pause; + bool logged_delay; atomic(u32) unpause; struct camu_resampler_format fmt; @@ -47,6 +48,7 @@ struct camu_audio_buffer { struct { f32 volume; ptrdiff_t offset; + u32 tail; } fade; #endif diff --git a/src/buffer/frame_queue.h b/src/buffer/frame_queue.h index fdb49b5..ca47457 100644 --- a/src/buffer/frame_queue.h +++ b/src/buffer/frame_queue.h @@ -16,14 +16,12 @@ enum { struct camu_frame_queue { struct camu_video_buffer *buf; -#ifdef CAMU_HAVE_FFMPEG - bool (*configure_subtitles)(struct camu_frame_queue *, u32, u32, AVCodecParameters *); -#endif + bool (*configure_subtitles)(struct camu_frame_queue *, u32, u32, struct camu_codec_stream *); void (*push)(struct camu_frame_queue *, struct camu_codec_frame *, f64); #ifdef CAMU_HAVE_FFMPEG void (*push_av_frame)(struct camu_frame_queue *, AVFrame *, f64); - void (*push_subtitle)(struct camu_frame_queue *, AVPacket *); #endif + void (*push_subtitle)(struct camu_frame_queue *, struct camu_codec_packet *); void (*flush)(struct camu_frame_queue *); s32 (*count)(struct camu_frame_queue *); u8 (*read)(struct camu_frame_queue *, f64, void *); diff --git a/src/buffer/video.c b/src/buffer/video.c index 2fc5773..34672fb 100644 --- a/src/buffer/video.c +++ b/src/buffer/video.c @@ -12,8 +12,8 @@ #include "../codec/ffmpeg/scaler.h" #endif -#define BUFFER_MARK_LOW ((1.0 / 30.0) * 6) -#define BUFFER_MARK_BUFFERED ((1.0 / 30.0) * 5) // Must be >1. +#define BUFFER_MARK_LOW ((1.0 / 30.0) * 8) +#define BUFFER_MARK_BUFFERED ((1.0 / 30.0) * 4) // Must be >1. #define BUFFER_MARK_HIGH ((1.0 / 30.0) * 12) #define BUFFER_MARK_RESET (BUFFER_MARK_HIGH * 2.0) @@ -117,13 +117,12 @@ bool camu_video_buffer_configure(struct camu_video_buffer *buf, struct camu_code return true; } -#ifdef CAMU_HAVE_FFMPEG -bool camu_video_buffer_configure_subtitles(struct camu_video_buffer *buf, AVCodecParameters *codecpar) +bool camu_video_buffer_configure_subtitles(struct camu_video_buffer *buf, struct camu_codec_stream *stream) { + if (!buf->queue) return false; struct camu_video_format *fmt = &buf->stream->video.fmt; - return buf->queue->configure_subtitles(buf->queue, fmt->width, fmt->height, codecpar); + return buf->queue->configure_subtitles(buf->queue, fmt->width, fmt->height, stream); } -#endif void camu_video_buffer_set_latency(struct camu_video_buffer *buf, s32 frames) { @@ -168,6 +167,7 @@ static bool push_av_frame_internal(struct camu_video_buffer *buf, AVFrame *frame f64 duration = camu_ff_frame_duration(frame) * av_q2d(stream->time_base); f64 base_pts = al_atomic_load(f64)(&buf->pts, AL_ATOMIC_ACQUIRE); if (!buf->single_frame && frame_is_late(buf->clock, base_pts, pts, duration)) { + al_log_info("video_buffer", "Discarding late frame."); return false; } if (base_pts == -1.0) al_atomic_store(f64)(&buf->pts, pts, AL_ATOMIC_RELEASE); @@ -215,12 +215,10 @@ void camu_video_buffer_push(struct camu_video_buffer *buf, struct camu_codec_fra after_push_internal(buf); } -#ifdef CAMU_HAVE_FFMPEG -void camu_video_buffer_push_subtitle(struct camu_video_buffer *buf, AVPacket *pkt) +void camu_video_buffer_push_subtitle(struct camu_video_buffer *buf, struct camu_codec_packet *packet) { - buf->queue->push_subtitle(buf->queue, pkt); + if (buf->queue) buf->queue->push_subtitle(buf->queue, packet); } -#endif // flush() always comes from the same thread as push(). void camu_video_buffer_flush(struct camu_video_buffer *buf) @@ -230,10 +228,9 @@ void camu_video_buffer_flush(struct camu_video_buffer *buf) buf->queue->flush(buf->queue); if (!buf->buffered) { s32 count = buf->queue->count(buf->queue); - f64 have = count * buf->avg_frame_duration; buf->buffered = true; buf->buffered_with_one_frame = count == 1; - al_log_debug("video_buffer", "Buffered (mark: %.2fs).", have); + al_log_debug("video_buffer", "Buffered (flush)."); buf->callback(buf->userdata, CAMU_BUFFER_BUFFERED); } } @@ -286,6 +283,8 @@ bool camu_video_buffer_read(struct camu_video_buffer *buf, void *out, bool *weig if (ret == CAMU_QUEUE_OK) { *weighted = buf->weighted_read; buf->weighted_read = false; + } else if (ret == CAMU_QUEUE_MORE) { + al_log_warn("video_buffer", "Underrun."); } return ret == CAMU_QUEUE_OK || ret == CAMU_QUEUE_MORE; diff --git a/src/buffer/video.h b/src/buffer/video.h index 0814251..c587af1 100644 --- a/src/buffer/video.h +++ b/src/buffer/video.h @@ -49,15 +49,11 @@ struct camu_video_buffer { bool camu_video_buffer_init(struct camu_video_buffer *buf, struct camu_clock *clock); bool camu_video_buffer_configure(struct camu_video_buffer *buf, struct camu_codec_stream *stream, struct camu_renderer *renderer); -#ifdef CAMU_HAVE_FFMPEG -bool camu_video_buffer_configure_subtitles(struct camu_video_buffer *buf, AVCodecParameters *codecpar); -#endif +bool camu_video_buffer_configure_subtitles(struct camu_video_buffer *buf, struct camu_codec_stream *stream); void camu_video_buffer_set_latency(struct camu_video_buffer *buf, s32 frames); bool camu_video_buffer_is_single_frame(struct camu_video_buffer *buf); void camu_video_buffer_push(struct camu_video_buffer *buf, struct camu_codec_frame *frame); -#ifdef CAMU_HAVE_FFMPEG -void camu_video_buffer_push_subtitle(struct camu_video_buffer *buf, AVPacket *pkt); -#endif +void camu_video_buffer_push_subtitle(struct camu_video_buffer *buf, struct camu_codec_packet *packet); void camu_video_buffer_flush(struct camu_video_buffer *buf); void camu_video_buffer_reset(struct camu_video_buffer *buf); bool camu_video_buffer_read(struct camu_video_buffer *buf, void *out, bool *weighted); -- cgit v1.2.3-101-g0448