From f48795439504acdfcd985e0d43f3f49ed08d3f85 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Tue, 10 Aug 2021 13:56:50 -0700 Subject: [PATCH] obs-transitions: Fix desync of stinger track matte Although obs_source_add_active_child indicates to a child source that a child source needs to activate, sources will not activate until the next tick. However, because the transition start call is made from within the UI thread, the time in which the media source renders is not guaranteed to be activated by the time the stinger renders due to a potential race. Thus he media source of a stinger is not guaranteed to be activated, causing a brief flash. This also applies when stopping a stinger. This problem normally doesn't really affect normal stingers; instead, it affects track matte stingers because it is critical for them to be on time in order to have the mask data. In order to solve this, check to see if the underlying media source is actually active and able to render when performing the masking. --- plugins/obs-transitions/transition-stinger.c | 23 ++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/plugins/obs-transitions/transition-stinger.c b/plugins/obs-transitions/transition-stinger.c index 1e8be94ea..30f7eb80a 100644 --- a/plugins/obs-transitions/transition-stinger.c +++ b/plugins/obs-transitions/transition-stinger.c @@ -37,6 +37,7 @@ struct stinger_info { float matte_height_factor; bool invert_matte; bool do_texrender; + bool matte_rendered; gs_effect_t *matte_effect; gs_eparam_t *ep_a_tex; @@ -306,8 +307,23 @@ static void stinger_video_render(void *data, gs_effect_t *effect) { struct stinger_info *s = data; + uint32_t media_cx = obs_source_get_width(s->media_source); + uint32_t media_cy = obs_source_get_height(s->media_source); + if (s->track_matte_enabled) { - obs_transition_video_render(s->source, stinger_matte_render); + bool ready = obs_source_active(s->media_source) && !!media_cx && + !!media_cy; + if (ready) { + if (!s->matte_rendered) + s->matte_rendered = true; + obs_transition_video_render(s->source, + stinger_matte_render); + } else { + obs_transition_video_render_direct( + s->source, s->matte_rendered + ? OBS_TRANSITION_SOURCE_B + : OBS_TRANSITION_SOURCE_A); + } if (s->matte_layout == MATTE_LAYOUT_MASK) return; } else { @@ -330,9 +346,6 @@ static void stinger_video_render(void *data, gs_effect_t *effect) float source_cxf = (float)source_cx; float source_cyf = (float)source_cy; - uint32_t media_cx = obs_source_get_width(s->media_source); - uint32_t media_cy = obs_source_get_height(s->media_source); - if (!media_cx || !media_cy) return; @@ -469,6 +482,8 @@ static void stinger_transition_start(void *data) return; } + s->matte_rendered = false; + proc_handler_call(ph, "get_duration", &cd); proc_handler_call(ph, "get_nb_frames", &cd); s->duration_ns =