1
0
Эх сурвалжийг харах

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.
jp9000 9 жил өмнө
parent
commit
ce0a189228

+ 1 - 0
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;

+ 26 - 3
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 {
+		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 (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;