From ce0a189228c236d2a0d3ee60b86677d92c1c73eb Mon Sep 17 00:00:00 2001 From: jp9000 Date: Sat, 16 Jan 2016 10:45:49 -0800 Subject: [PATCH] libobs: Fix audio issues with async video/audio looping This fixes an age-old issue where audio samples could be lost or audio could temporarily go out of sync in the case of looping videos. When audio/video data is looping, there's a window between when the audio data resets its timestamp value and when the video data resets its timestamp value. This method simply pushes back the audio data while in that window and does not modify sync, and when it detects that its out of the loop window it simply forces a resync of the audio data in the circular buffer. This ensures that minimal audio data is lost in the loop process, and minimizes the likelihood of any sort of sync issues associated with looping. --- libobs/obs-internal.h | 1 + libobs/obs-source.c | 31 +++++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/libobs/obs-internal.h b/libobs/obs-internal.h index 78f731bbf..f4fe36be3 100644 --- a/libobs/obs-internal.h +++ b/libobs/obs-internal.h @@ -540,6 +540,7 @@ struct obs_source { bool audio_pending; bool user_muted; bool muted; + bool resync_audio_with_video; struct obs_source *next_audio_source; struct obs_source **prev_next_audio_source; uint64_t audio_ts; diff --git a/libobs/obs-source.c b/libobs/obs-source.c index c5bf54148..78bed1e20 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -1143,11 +1143,34 @@ static void source_output_audio_data(obs_source_t *source, in.timestamp += source->timing_adjust; if (source->next_audio_sys_ts_min == in.timestamp) { - push_back = true; - } else { - diff = uint64_diff(source->next_audio_sys_ts_min, in.timestamp); - if (diff < TS_SMOOTHING_THRESHOLD) + if (source->resync_audio_with_video) + source->resync_audio_with_video = false; + else push_back = true; + + } else if (source->next_audio_sys_ts_min) { + diff = uint64_diff(source->next_audio_sys_ts_min, in.timestamp); + + if (diff < TS_SMOOTHING_THRESHOLD) { + if (source->resync_audio_with_video) + source->resync_audio_with_video = false; + else + push_back = true; + + /* This only happens if used with async video when audio/video + * start transitioning in to a timestamp jump. Audio will + * typically have a timestamp jump, and then video will have a + * timestamp jump. It's important to not just push back the + * next non-reset audio data after this happens, as that will + * be the video re-syncing. */ + } else if (in.timestamp < source->next_audio_sys_ts_min || + diff > MAX_TS_VAR) { + reset_audio_timing(source, data->timestamp, + source->next_audio_sys_ts_min); + push_back = true; + source->resync_audio_with_video = true; + in.timestamp = data->timestamp + source->timing_adjust; + } } sync_offset = source->sync_offset;