From d6735566cebf82a5d22a3ade22b9acd52fbe11a5 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Sun, 27 Oct 2024 19:58:31 -0400 Subject: Buffer tweaks Signed-off-by: Andrew Opalach --- src/buffer/audio.c | 6 +++--- src/buffer/video.c | 19 +++++++++++-------- src/codec/ffmpeg/decoder.c | 3 ++- src/codec/ffmpeg/demuxer.c | 4 ++-- src/liana/list.h | 2 +- src/liana/vcr.c | 11 ++++++----- src/libsink/sink.c | 29 ++++++++++++++++++++--------- src/mixer/audio_miniaudio.c | 12 +++--------- src/mixer/mixer.c | 2 +- 9 files changed, 49 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/buffer/audio.c b/src/buffer/audio.c index 141c589..f3e0b74 100644 --- a/src/buffer/audio.c +++ b/src/buffer/audio.c @@ -14,7 +14,7 @@ #define BUFFER_MARK_BUFFERED (1.5 * 1000000L) #ifdef CAMU_AUDIO_BUFFER_FADE -#define FADE_STEP(fmt) (1.f / (fmt)->sample_rate) +#define FADE_STEP(fmt) (1.1f / (fmt)->sample_rate) #endif enum { @@ -280,7 +280,7 @@ size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t re if (pts > 0.0) { // Skip. ret = camu_audio_format_sec_to_bytes(&buf->fmt.req, pts); ret = AL_MIN(ret, have); - al_log_debug("audio_buffer", "Skipping %fs of audio (%zu bytes).", pts, ret); + al_log_info("audio_buffer", "Skipping %fs of audio (%zu bytes).", pts, ret); ret = al_ring_buffer_discard(&buf->rb, ret); have -= ret; buf->pts += camu_audio_format_bytes_to_sec(&buf->fmt.req, ret); @@ -289,7 +289,7 @@ size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t re pts = -pts; ret = camu_audio_format_sec_to_bytes(&buf->fmt.req, pts); ret = AL_MIN(ret, req); - al_log_debug("audio_buffer", "Delaying audio by %fs (%zu bytes).", pts, ret); + al_log_info("audio_buffer", "Delaying audio by %fs (%zu bytes).", pts, ret); al_memset(data, 0, ret); data += ret; req -= ret; diff --git a/src/buffer/video.c b/src/buffer/video.c index 00902f3..04a9dbf 100644 --- a/src/buffer/video.c +++ b/src/buffer/video.c @@ -4,10 +4,10 @@ #include "common.h" #include "common_internal.h" -#define BUFFER_WATERMARK_LOW 8 // frames. -#define BUFFER_WATERMARK_BUFFERED 5 -#define BUFFER_WATERMARK_HIGH 12 -#define BUFFER_WATERMARK_RESET BUFFER_WATERMARK_HIGH + 10. +#define BUFFER_WATERMARK_LOW 6 // frames. +#define BUFFER_WATERMARK_BUFFERED 4 +#define BUFFER_WATERMARK_HIGH 10 +#define BUFFER_WATERMARK_RESET BUFFER_WATERMARK_HIGH + 10 bool camu_video_buffer_init(struct camu_video_buffer *buf, struct camu_clock *clock, struct camu_renderer *renderer) { @@ -99,7 +99,7 @@ static void after_push_internal(struct camu_video_buffer *buf) } #ifdef CAMU_HAVE_FFMPEG -static void push_av_frame_internal(struct camu_video_buffer *buf, AVFrame *frame) +static bool push_av_frame_internal(struct camu_video_buffer *buf, AVFrame *frame) { f64 pts = 0.0; if (!buf->single_frame) { @@ -107,7 +107,7 @@ static void push_av_frame_internal(struct camu_video_buffer *buf, AVFrame *frame pts = frame->best_effort_timestamp * av_q2d(stream->time_base); if (pts + buf->avg_frame_duration < camu_clock_get_base_pts(buf->clock)) { av_frame_free(&frame); - return; + return false; } } if (buf->pts == -1.0) buf->pts = pts; @@ -122,6 +122,7 @@ static void push_av_frame_internal(struct camu_video_buffer *buf, AVFrame *frame #endif if (frame) frame->opaque = buf; buf->queue->push_av_frame(buf->queue, frame, pts); + return true; } #endif @@ -137,10 +138,12 @@ void camu_video_buffer_push(struct camu_video_buffer *buf, struct camu_codec_fra buf->queue->push(buf->queue, frame, 0.0); break; #ifdef CAMU_HAVE_FFMPEG - case CAMU_FFMPEG_COMPAT: - push_av_frame_internal(buf, frame->av.frame); + case CAMU_FFMPEG_COMPAT: { + bool pushed = push_av_frame_internal(buf, frame->av.frame); al_free(frame); + if (!pushed) return; break; + } #endif } after_push_internal(buf); diff --git a/src/codec/ffmpeg/decoder.c b/src/codec/ffmpeg/decoder.c index 375bdfe..03940a0 100644 --- a/src/codec/ffmpeg/decoder.c +++ b/src/codec/ffmpeg/decoder.c @@ -43,7 +43,8 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend av->codec_context->thread_type = FF_THREAD_SLICE; al_log_debug("ff_decoder", "Using %i threads for decoder.", cpus); -#ifndef CAMU_SINK_NO_VIDEO +//#ifndef CAMU_SINK_NO_VIDEO +#if 0 if (codecpar->codec_type == AVMEDIA_TYPE_VIDEO && renderer && renderer->get_buffer2) { av->codec_context->get_buffer2 = renderer->get_buffer2; av->codec_context->opaque = renderer->opaque; diff --git a/src/codec/ffmpeg/demuxer.c b/src/codec/ffmpeg/demuxer.c index 7ff0dca..8ea645b 100644 --- a/src/codec/ffmpeg/demuxer.c +++ b/src/codec/ffmpeg/demuxer.c @@ -154,13 +154,13 @@ static u64 ff_demuxer_get_duration(struct camu_demuxer *demux) static bool ff_demuxer_seek(struct camu_demuxer *demux, u64 pos) { struct camu_ff_demuxer *av = (struct camu_ff_demuxer *)demux; - if (pos > av->duration) pos = av->duration; al_assert(pos <= INT64_MAX); - s64 ts = av_rescale_q((s64)pos, (AVRational){ 1, 1000000 }, AV_TIME_BASE_Q); + if (pos > av->duration) pos = av->duration; if (av->eof) { avformat_flush(av->format_context); av->eof = false; } + s64 ts = (s64)pos; if (avformat_seek_file(av->format_context, -1, INT64_MIN, ts, ts, 0) < 0) { return false; } diff --git a/src/liana/list.h b/src/liana/list.h index bbb2ce4..5e3eaec 100644 --- a/src/liana/list.h +++ b/src/liana/list.h @@ -8,7 +8,7 @@ #define LIANA_TIMESTAMP_INVALID UINT64_MAX #define LIANA_BASE_DELAY 475000Lu // 475ms -#define LIANA_BASE_PING 200000Lu // 200ms +#define LIANA_BASE_PING 150000Lu // 150ms #define LIANA_PAUSE_DELAY LIANA_BASE_PING #define LIANA_DELAY_IGNORE 0Lu diff --git a/src/liana/vcr.c b/src/liana/vcr.c index 192b4f1..40aa757 100644 --- a/src/liana/vcr.c +++ b/src/liana/vcr.c @@ -109,9 +109,9 @@ static void cork_if_buffered(struct lia_vcr *vcr) { u8 buffered = 1; struct lia_vcr_track *track; - al_array_foreach(vcr->tracks, i, track) { - buffered &= al_atomic_load(u8)(&track->buffered, AL_ATOMIC_RELAXED); - } + //al_array_foreach(vcr->tracks, i, track) { + // buffered &= al_atomic_load(u8)(&track->buffered, AL_ATOMIC_RELAXED); + //} if (buffered) { aki_packet_stream_cork(vcr->data, true); al_array_foreach(vcr->tracks, i, track) { @@ -136,9 +136,10 @@ bool lia_vcr_push_packet(struct lia_vcr *vcr, struct aki_packet *packet) aki_thread_create(&track->thread, vcr_track_thread, track); track->running = true; } + s32 count; if (!aki_packet_cache_send_packet(&track->cache, packet)) { aki_packet_free(packet); - } else if (al_atomic_add(s32)(&vcr->count, 1, AL_ATOMIC_RELAXED) > vcr->mark.buffered) { + } else if ((count = al_atomic_add(s32)(&vcr->count, 1, AL_ATOMIC_RELAXED)) > vcr->mark.buffered) { cork_if_buffered(vcr); } break; @@ -204,7 +205,7 @@ void lia_vcr_flush(struct lia_vcr *vcr) vcr_track_close_internal(track); track->client->flush(track->client); aki_packet_cache_enable(&track->cache); - track->running = false; + al_atomic_store(u8)(&track->buffered, 0, AL_ATOMIC_RELAXED); al_atomic_store(s32)(&track->state, LIANA_STREAM_RUNNING, AL_ATOMIC_RELAXED); } aki_signal_send(&vcr->signal); diff --git a/src/libsink/sink.c b/src/libsink/sink.c index a2262bc..ff9f4f2 100644 --- a/src/libsink/sink.c +++ b/src/libsink/sink.c @@ -468,18 +468,17 @@ static void video_buffer_callback(void *userdata, u8 op) static void evaluate_latency(struct camu_sink *sink, struct camu_sink_entry *entry) { - // Entry has both audio and video configured. +#if CAMU_SINK_LOCAL #ifndef CAMU_SINK_NO_VIDEO + // Entry has both audio and video configured. if (!BUFFER_EMPTY(&entry->audio) && !BUFFER_EMPTY(&entry->video)) { camu_video_buffer_set_latency(&entry->video.buf, -camu_mixer_get_latency(sink->audio.mixer)); - } else if (!BUFFER_EMPTY(&entry->audio)) { -#if !CAMU_SINK_LOCAL - camu_audio_buffer_set_latency(&entry->audio.buf, -camu_mixer_get_latency(sink->audio.mixer)); -#endif } +#endif #else - (void)sink; - (void)entry; + // To sync clients with differing audio latencies our only option is to factor the mixer + // latency into the audio buffer. + camu_audio_buffer_set_latency(&entry->audio.buf, camu_mixer_get_latency(sink->audio.mixer)); #endif } @@ -867,8 +866,16 @@ static bool set_command_callback(void *userdata, struct aki_rpc_connection *conn set_or_queue_entry(entry); sink->current = entry; break; - case LIANA_PAUSE_PAUSE: - if (sink->current) { + case LIANA_PAUSE_PAUSE: { + struct camu_sink_entry *prev_target = sink->target; + if (prev_target) { + if (prev_target == entry) { + sink->target = NULL; + } else { + sink->target = entry; + } + camu_clock_pause(&prev_target->clock, at); + } else if (sink->current) { if (camu_clock_is_ended(&sink->current->clock)) { // Server thought we weren't done, be we are. switch_to(sink, entry); @@ -878,6 +885,7 @@ static bool set_command_callback(void *userdata, struct aki_rpc_connection *conn } } break; + } case LIANA_PAUSE_BOTH: { camu_clock_resume(&entry->clock, at); struct camu_sink_entry *prev_target = sink->target; @@ -928,6 +936,9 @@ static bool pause_command_callback(void *userdata, struct aki_rpc_connection *co if (!current) goto out; #if CAMU_SINK_LOCAL + (void)sequence; + (void)at; + (void)pause; sink_local_pause(sink, current); #else if (current->sequence == sequence) { diff --git a/src/mixer/audio_miniaudio.c b/src/mixer/audio_miniaudio.c index fb4db23..4e29e0a 100644 --- a/src/mixer/audio_miniaudio.c +++ b/src/mixer/audio_miniaudio.c @@ -136,7 +136,7 @@ static void data_callback(ma_device *device, void *output, const void *input, u3 } #define DEFAULT_PERIODS 3 -#define DEFAULT_PERIOD_SIZE_IN_MILLISECONDS 75 +#define DEFAULT_PERIOD_SIZE_IN_MILLISECONDS 64 static bool audio_miniaudio_configure_stream(struct camu_audio *audio, void *opaque) { @@ -175,14 +175,8 @@ static bool audio_miniaudio_configure_stream(struct camu_audio *audio, void *opa static u64 audio_miniaudio_get_latency(struct camu_audio *audio) { struct camu_audio_miniaudio *ma = (struct camu_audio_miniaudio *)audio; - // Latency is one period on PulseAudio even if periods is >1. On WASAPI, latency is periods - // times period size. -#ifdef _WIN32 - return ((ma->device.playback.internalPeriodSizeInFrames * ma->device.playback.internalPeriods) / -#else - return ((ma->device.playback.internalPeriodSizeInFrames) / -#endif - (ma->device.playback.internalSampleRate / 1000000.0)); + return (ma->device.playback.internalPeriodSizeInFrames * ma->device.playback.internalPeriods) / + (ma->device.playback.internalSampleRate / 1000000.0); } static void audio_miniaudio_start(struct camu_audio *audio) diff --git a/src/mixer/mixer.c b/src/mixer/mixer.c index e6fd178..5af63b7 100644 --- a/src/mixer/mixer.c +++ b/src/mixer/mixer.c @@ -7,7 +7,7 @@ #define MIXER_WANT_INITIAL_SILENCE 1 // Number of silent frames to append before signaling MIXER_EMPTY. -#define MIXER_TRAILING_SILENCE 100 +#define MIXER_TRAILING_SILENCE 20 static s32 data_callback(void *userdata, u8 *data, s32 frame_count, bool *silence) { -- cgit v1.2.3-101-g0448