From d1179084404e24af43e7c28e4deb4ead8498a6b3 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Tue, 28 Jul 2020 13:54:53 -0700 Subject: [PATCH] libobs: Add func to set async video frame immediately Allows the ability to directly override the current async frame immediately. --- libobs/obs-source.c | 76 +++++++++++++++++++++++++++++++++++++++++++++ libobs/obs.h | 12 +++++++ 2 files changed, 88 insertions(+) diff --git a/libobs/obs-source.c b/libobs/obs-source.c index ae6b59072..b6408f9a4 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -2976,6 +2976,82 @@ void obs_source_show_preloaded_video(obs_source_t *source) pthread_mutex_unlock(&source->audio_buf_mutex); } +static void +obs_source_set_video_frame_internal(obs_source_t *source, + const struct obs_source_frame *frame) +{ + if (!obs_source_valid(source, "obs_source_set_video_frame")) + return; + if (!frame) + return; + + obs_enter_graphics(); + + if (preload_frame_changed(source, frame)) { + obs_source_frame_destroy(source->async_preload_frame); + source->async_preload_frame = obs_source_frame_create( + frame->format, frame->width, frame->height); + } + + copy_frame_data(source->async_preload_frame, frame); + set_async_texture_size(source, source->async_preload_frame); + update_async_textures(source, source->async_preload_frame, + source->async_textures, source->async_texrender); + + source->last_frame_ts = frame->timestamp; + + obs_leave_graphics(); +} + +void obs_source_set_video_frame(obs_source_t *source, + const struct obs_source_frame *frame) +{ + if (!frame) { + obs_source_preload_video_internal(source, NULL); + return; + } + + struct obs_source_frame new_frame = *frame; + new_frame.full_range = + format_is_yuv(frame->format) ? new_frame.full_range : true; + + obs_source_set_video_frame_internal(source, &new_frame); +} + +void obs_source_set_video_frame2(obs_source_t *source, + const struct obs_source_frame2 *frame) +{ + if (!frame) { + obs_source_preload_video_internal(source, NULL); + return; + } + + struct obs_source_frame new_frame; + enum video_range_type range = + resolve_video_range(frame->format, frame->range); + + for (size_t i = 0; i < MAX_AV_PLANES; i++) { + new_frame.data[i] = frame->data[i]; + new_frame.linesize[i] = frame->linesize[i]; + } + + new_frame.width = frame->width; + new_frame.height = frame->height; + new_frame.timestamp = frame->timestamp; + new_frame.format = frame->format; + new_frame.full_range = range == VIDEO_RANGE_FULL; + new_frame.flip = frame->flip; + + memcpy(&new_frame.color_matrix, &frame->color_matrix, + sizeof(frame->color_matrix)); + memcpy(&new_frame.color_range_min, &frame->color_range_min, + sizeof(frame->color_range_min)); + memcpy(&new_frame.color_range_max, &frame->color_range_max, + sizeof(frame->color_range_max)); + + obs_source_set_video_frame_internal(source, &new_frame); +} + static inline struct obs_audio_data * filter_async_audio(obs_source_t *source, struct obs_audio_data *in) { diff --git a/libobs/obs.h b/libobs/obs.h index d091ebebf..5abe683dc 100644 --- a/libobs/obs.h +++ b/libobs/obs.h @@ -1210,6 +1210,18 @@ EXPORT void obs_source_preload_video2(obs_source_t *source, /** Shows any preloaded video data */ EXPORT void obs_source_show_preloaded_video(obs_source_t *source); +/** + * Sets current async video frame immediately + * + * NOTE: Non-YUV formats will always be treated as full range with this + * function! Use obs_source_preload_video2 instead if partial range support is + * desired for non-YUV video formats. + */ +EXPORT void obs_source_set_video_frame(obs_source_t *source, + const struct obs_source_frame *frame); +EXPORT void obs_source_set_video_frame2(obs_source_t *source, + const struct obs_source_frame2 *frame); + /** Outputs audio data (always asynchronous) */ EXPORT void obs_source_output_audio(obs_source_t *source, const struct obs_source_audio *audio);