diff --git a/libobs/obs-audio.c b/libobs/obs-audio.c index e6b107b2b..68a933a67 100644 --- a/libobs/obs-audio.c +++ b/libobs/obs-audio.c @@ -292,6 +292,65 @@ static inline void discard_audio(struct obs_core_audio *audio, source->audio_ts = ts->end; } +static inline bool audio_buffering_maxed(struct obs_core_audio *audio) +{ + return audio->total_buffering_ticks == MAX_BUFFERING_TICKS; +} + +static void set_fixed_audio_buffering(struct obs_core_audio *audio, + size_t sample_rate, struct ts_info *ts) +{ + struct ts_info new_ts; + size_t total_ms; + size_t ms; + int ticks; + + if (audio_buffering_maxed(audio)) + return; + + if (!audio->buffering_wait_ticks) + audio->buffered_ts = ts->start; + + ticks = MAX_BUFFERING_TICKS - audio->total_buffering_ticks; + audio->total_buffering_ticks += ticks; + + ms = ticks * AUDIO_OUTPUT_FRAMES * 1000 / sample_rate; + total_ms = audio->total_buffering_ticks * AUDIO_OUTPUT_FRAMES * 1000 / + sample_rate; + + blog(LOG_INFO, + "\n" + "enabling fixed audio buffering, total " + "audio buffering is now %d milliseconds" + "\n", + (int)total_ms); + + new_ts.start = + audio->buffered_ts - + audio_frames_to_ns(sample_rate, audio->buffering_wait_ticks * + AUDIO_OUTPUT_FRAMES); + + while (ticks--) { + const uint64_t cur_ticks = ++audio->buffering_wait_ticks; + + new_ts.end = new_ts.start; + new_ts.start = + audio->buffered_ts - + audio_frames_to_ns(sample_rate, + cur_ticks * AUDIO_OUTPUT_FRAMES); + +#if DEBUG_AUDIO == 1 + blog(LOG_DEBUG, "add buffered ts: %" PRIu64 "-%" PRIu64, + new_ts.start, new_ts.end); +#endif + + circlebuf_push_front(&audio->buffered_timestamps, &new_ts, + sizeof(new_ts)); + } + + *ts = new_ts; +} + static void add_audio_buffering(struct obs_core_audio *audio, size_t sample_rate, struct ts_info *ts, uint64_t min_ts, const char *buffering_name) @@ -303,7 +362,7 @@ static void add_audio_buffering(struct obs_core_audio *audio, size_t ms; int ticks; - if (audio->total_buffering_ticks == MAX_BUFFERING_TICKS) + if (audio_buffering_maxed(audio)) return; if (!audio->buffering_wait_ticks) @@ -518,7 +577,7 @@ bool audio_callback(void *param, uint64_t start_ts_in, uint64_t end_ts_in, /* if a source has gone backward in time and we can no * longer buffer, drop some or all of its audio */ - if (audio->total_buffering_ticks == MAX_BUFFERING_TICKS && + if (audio_buffering_maxed(audio) && source->audio_ts < ts.start) { if (source->info.audio_render) { blog(LOG_DEBUG, @@ -556,10 +615,15 @@ bool audio_callback(void *param, uint64_t start_ts_in, uint64_t end_ts_in, pthread_mutex_unlock(&data->audio_sources_mutex); /* ------------------------------------------------ */ - /* if a source has gone backward in time, buffer */ - if (min_ts < ts.start) + /* if a source has gone backward in time, buffer */ + if (audio->fixed_buffer) { + if (!audio_buffering_maxed(audio)) { + set_fixed_audio_buffering(audio, sample_rate, &ts); + } + } else if (min_ts < ts.start) { add_audio_buffering(audio, sample_rate, &ts, min_ts, buffering_name); + } /* ------------------------------------------------ */ /* mix audio */ diff --git a/libobs/obs-internal.h b/libobs/obs-internal.h index 1ced6fe1c..271bbe599 100644 --- a/libobs/obs-internal.h +++ b/libobs/obs-internal.h @@ -344,6 +344,7 @@ struct obs_core_audio { struct circlebuf buffered_timestamps; uint64_t buffering_wait_ticks; int total_buffering_ticks; + bool fixed_buffer; float user_volume;