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.
This commit is contained in:
jp9000 2021-08-10 13:56:50 -07:00
parent f0ab940282
commit f487954395

View File

@ -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 =