From b54f70ef8d4747aaa4ac8fe45830a2a042ca62ec Mon Sep 17 00:00:00 2001 From: jp9000 Date: Fri, 29 Sep 2017 00:37:33 -0700 Subject: [PATCH] libobs: Add async video/audio decoupling functions Decoupling the audio from the video causes the audio to be played right when it's received rather than attempt to sync up to the video frames. This is useful with certain async sources/devices when the audio/video timestamps are not reliable. Naturally because it plays audio right when it's received, this should only be used when the async source is operating in unbuffered mode, otherwise the video frame timing will be out of sync by the amount of buffering the video currently has. --- libobs/audio-monitoring/win32/wasapi-output.c | 5 +++- libobs/obs-internal.h | 1 + libobs/obs-source.c | 30 +++++++++++++++++-- libobs/obs.h | 6 ++++ 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/libobs/audio-monitoring/win32/wasapi-output.c b/libobs/audio-monitoring/win32/wasapi-output.c index 750f9b58a..b6956b370 100644 --- a/libobs/audio-monitoring/win32/wasapi-output.c +++ b/libobs/audio-monitoring/win32/wasapi-output.c @@ -165,7 +165,10 @@ static void on_audio_playback(void *param, obs_source_t *source, UINT32 pad = 0; monitor->client->lpVtbl->GetCurrentPadding(monitor->client, &pad); - if (monitor->source_has_video) { + bool decouple_audio = + source->async_unbuffered && source->async_decoupled; + + if (monitor->source_has_video && !decouple_audio) { uint64_t ts = audio_data->timestamp - ts_offset; if (!process_audio_delay(monitor, (float**)(&resample_data[0]), diff --git a/libobs/obs-internal.h b/libobs/obs-internal.h index 0e9d3f484..aee6a3c38 100644 --- a/libobs/obs-internal.h +++ b/libobs/obs-internal.h @@ -610,6 +610,7 @@ struct obs_source { bool async_active; bool async_update_texture; bool async_unbuffered; + bool async_decoupled; struct obs_source_frame *async_preload_frame; DARRAY(struct async_frame) async_cache; DARRAY(struct obs_source_frame*)async_frames; diff --git a/libobs/obs-source.c b/libobs/obs-source.c index 2f33f0bbd..b374def5d 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -1675,9 +1675,13 @@ static void obs_source_update_async_video(obs_source_t *source) source->async_rendered = true; if (frame) { - source->timing_adjust = - obs->video.video_time - frame->timestamp; - source->timing_set = true; + if (!source->async_decoupled || + !source->async_unbuffered) { + source->timing_adjust = + obs->video.video_time - + frame->timestamp; + source->timing_set = true; + } if (source->async_update_texture) { update_async_texture(source, frame, @@ -4069,3 +4073,23 @@ obs_data_t *obs_source_get_private_settings(obs_source_t *source) obs_data_addref(source->private_settings); return source->private_settings; } + +void obs_source_set_async_decoupled(obs_source_t *source, bool decouple) +{ + if (!obs_ptr_valid(source, "obs_source_set_async_decoupled")) + return; + + source->async_decoupled = decouple; + if (decouple) { + pthread_mutex_lock(&source->audio_buf_mutex); + source->timing_set = false; + reset_audio_data(source, 0); + pthread_mutex_unlock(&source->audio_buf_mutex); + } +} + +bool obs_source_async_decoupled(const obs_source_t *source) +{ + return obs_source_valid(source, "obs_source_async_decoupled") ? + source->async_decoupled : false; +} diff --git a/libobs/obs.h b/libobs/obs.h index 152dc9102..9a62872b1 100644 --- a/libobs/obs.h +++ b/libobs/obs.h @@ -1118,6 +1118,12 @@ EXPORT void obs_source_set_async_unbuffered(obs_source_t *source, bool unbuffered); EXPORT bool obs_source_async_unbuffered(const obs_source_t *source); +/** Used to decouple audio from video so that audio doesn't attempt to sync up + * with video. I.E. Audio acts independently. Only works when in unbuffered + * mode. */ +EXPORT void obs_source_set_async_decoupled(obs_source_t *source, bool decouple); +EXPORT bool obs_source_async_decoupled(const obs_source_t *source); + /* ------------------------------------------------------------------------- */ /* Transition-specific functions */ enum obs_transition_target {